hex_viewer_startscreen.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. #include "../hex_viewer.h"
  2. #include <furi.h>
  3. #include <furi_hal.h>
  4. #include <input/input.h>
  5. #include <gui/elements.h>
  6. struct HexViewerStartscreen {
  7. View* view;
  8. HexViewerStartscreenCallback callback;
  9. void* context;
  10. };
  11. typedef struct {
  12. int some_value;
  13. } HexViewerStartscreenModel;
  14. void hex_viewer_startscreen_set_callback(
  15. HexViewerStartscreen* instance,
  16. HexViewerStartscreenCallback callback,
  17. void* context) {
  18. furi_assert(instance);
  19. furi_assert(callback);
  20. instance->callback = callback;
  21. instance->context = context;
  22. }
  23. void hex_viewer_startscreen_draw(Canvas* canvas, HexViewerStartscreenModel* model) {
  24. UNUSED(model);
  25. canvas_clear(canvas);
  26. if (!app->model->file_size) {
  27. canvas_set_color(canvas, ColorBlack);
  28. canvas_set_font(canvas, FontPrimary);
  29. canvas_draw_str_aligned(canvas, 64, 10, AlignCenter, AlignTop, "HexViewer v2.0");
  30. canvas_set_font(canvas, FontSecondary);
  31. canvas_draw_str_aligned(canvas, 64, 22, AlignCenter, AlignTop, "Basic hex viewer");
  32. canvas_draw_str_aligned(canvas, 64, 32, AlignCenter, AlignTop, "for your Flipper");
  33. elements_button_center(canvas, "Open");
  34. } else {
  35. canvas_set_color(canvas, ColorBlack);
  36. elements_button_left(canvas, app->model->mode ? "Addr" : "Text");
  37. elements_button_right(canvas, "Info");
  38. elements_button_center(canvas, "Menu");
  39. int ROW_HEIGHT = 12;
  40. int TOP_OFFSET = 10;
  41. int LEFT_OFFSET = 3;
  42. uint32_t line_count = app->model->file_size / HEX_VIEWER_BYTES_PER_LINE;
  43. if(app->model->file_size % HEX_VIEWER_BYTES_PER_LINE != 0) line_count += 1;
  44. uint32_t first_line_on_screen = app->model->file_offset / HEX_VIEWER_BYTES_PER_LINE;
  45. if(line_count > HEX_VIEWER_LINES_ON_SCREEN) {
  46. uint8_t width = canvas_width(canvas);
  47. elements_scrollbar_pos(
  48. canvas,
  49. width,
  50. 0,
  51. ROW_HEIGHT * HEX_VIEWER_LINES_ON_SCREEN,
  52. first_line_on_screen, // TODO
  53. line_count - (HEX_VIEWER_LINES_ON_SCREEN - 1));
  54. }
  55. char temp_buf[32];
  56. uint32_t row_iters = app->model->file_read_bytes / HEX_VIEWER_BYTES_PER_LINE;
  57. if(app->model->file_read_bytes % HEX_VIEWER_BYTES_PER_LINE != 0) row_iters += 1;
  58. for(uint32_t i = 0; i < row_iters; ++i) {
  59. uint32_t bytes_left_per_row =
  60. app->model->file_read_bytes - i * HEX_VIEWER_BYTES_PER_LINE;
  61. bytes_left_per_row = MIN(bytes_left_per_row, HEX_VIEWER_BYTES_PER_LINE);
  62. if(app->model->mode) {
  63. memcpy(temp_buf, app->model->file_bytes[i], bytes_left_per_row);
  64. temp_buf[bytes_left_per_row] = '\0';
  65. for(uint32_t j = 0; j < bytes_left_per_row; ++j)
  66. if(!isprint((int)temp_buf[j])) temp_buf[j] = '.';
  67. canvas_set_font(canvas, FontKeyboard);
  68. canvas_draw_str(canvas, LEFT_OFFSET, TOP_OFFSET + i * ROW_HEIGHT, temp_buf);
  69. } else {
  70. uint32_t addr = app->model->file_offset + i * HEX_VIEWER_BYTES_PER_LINE;
  71. snprintf(temp_buf, 32, "%04lX", addr);
  72. canvas_set_font(canvas, FontKeyboard);
  73. canvas_draw_str(canvas, LEFT_OFFSET, TOP_OFFSET + i * ROW_HEIGHT, temp_buf);
  74. }
  75. char* p = temp_buf;
  76. for(uint32_t j = 0; j < bytes_left_per_row; ++j)
  77. p += snprintf(p, 32, "%02X ", app->model->file_bytes[i][j]);
  78. canvas_set_font(canvas, FontKeyboard);
  79. canvas_draw_str(canvas, LEFT_OFFSET + 41, TOP_OFFSET + i * ROW_HEIGHT, temp_buf);
  80. }
  81. }
  82. }
  83. static void hex_viewer_startscreen_model_init(HexViewerStartscreenModel* const model) {
  84. model->some_value = 1;
  85. }
  86. bool hex_viewer_startscreen_input(InputEvent* event, void* context) {
  87. furi_assert(context);
  88. HexViewerStartscreen* instance = context;
  89. if (event->type == InputTypeRelease) {
  90. switch(event->key) {
  91. case InputKeyBack:
  92. with_view_model(
  93. instance->view,
  94. HexViewerStartscreenModel * model,
  95. {
  96. UNUSED(model);
  97. instance->callback(HexViewerCustomEventStartscreenBack, instance->context);
  98. },
  99. true);
  100. break;
  101. case InputKeyLeft:
  102. with_view_model(
  103. instance->view,
  104. HexViewerStartscreenModel * model,
  105. {
  106. UNUSED(model);
  107. instance->callback(HexViewerCustomEventStartscreenLeft, instance->context);
  108. },
  109. true);
  110. break;
  111. case InputKeyRight:
  112. with_view_model(
  113. instance->view,
  114. HexViewerStartscreenModel * model,
  115. {
  116. UNUSED(model);
  117. instance->callback(HexViewerCustomEventStartscreenRight, instance->context);
  118. },
  119. true);
  120. break;
  121. case InputKeyUp:
  122. with_view_model(
  123. instance->view,
  124. HexViewerStartscreenModel * model,
  125. {
  126. UNUSED(model);
  127. instance->callback(HexViewerCustomEventStartscreenUp, instance->context);
  128. },
  129. true);
  130. break;
  131. case InputKeyDown:
  132. with_view_model(
  133. instance->view,
  134. HexViewerStartscreenModel * model,
  135. {
  136. UNUSED(model);
  137. instance->callback(HexViewerCustomEventStartscreenDown, instance->context);
  138. },
  139. true);
  140. break;
  141. case InputKeyOk:
  142. with_view_model(
  143. instance->view,
  144. HexViewerStartscreenModel* model,
  145. {
  146. UNUSED(model);
  147. instance->callback(HexViewerCustomEventStartscreenOk, instance->context);
  148. },
  149. true);
  150. break;
  151. case InputKeyMAX:
  152. break;
  153. }
  154. }
  155. return true;
  156. }
  157. void hex_viewer_startscreen_exit(void* context) {
  158. furi_assert(context);
  159. }
  160. void hex_viewer_startscreen_enter(void* context) {
  161. furi_assert(context);
  162. HexViewerStartscreen* instance = (HexViewerStartscreen*)context;
  163. with_view_model(
  164. instance->view,
  165. HexViewerStartscreenModel * model,
  166. {
  167. hex_viewer_startscreen_model_init(model);
  168. },
  169. true
  170. );
  171. }
  172. HexViewerStartscreen* hex_viewer_startscreen_alloc() {
  173. HexViewerStartscreen* instance = malloc(sizeof(HexViewerStartscreen));
  174. instance->view = view_alloc();
  175. view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(HexViewerStartscreenModel));
  176. view_set_context(instance->view, instance); // furi_assert crashes in events without this
  177. view_set_draw_callback(instance->view, (ViewDrawCallback)hex_viewer_startscreen_draw);
  178. view_set_input_callback(instance->view, hex_viewer_startscreen_input);
  179. //view_set_enter_callback(instance->view, hex_viewer_startscreen_enter);
  180. //view_set_exit_callback(instance->view, hex_viewer_startscreen_exit);
  181. with_view_model(
  182. instance->view,
  183. HexViewerStartscreenModel * model,
  184. {
  185. hex_viewer_startscreen_model_init(model);
  186. },
  187. true
  188. );
  189. return instance;
  190. }
  191. void hex_viewer_startscreen_free(HexViewerStartscreen* instance) {
  192. furi_assert(instance);
  193. with_view_model(
  194. instance->view,
  195. HexViewerStartscreenModel * model,
  196. {
  197. UNUSED(model);
  198. },
  199. true);
  200. view_free(instance->view);
  201. free(instance);
  202. }
  203. View* hex_viewer_startscreen_get_view(HexViewerStartscreen* instance) {
  204. furi_assert(instance);
  205. return instance->view;
  206. }