bf_dev_env.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. #include "bf_dev_env.h"
  2. #include <gui/elements.h>
  3. typedef struct BFDevEnv {
  4. View* view;
  5. DevEnvOkCallback callback;
  6. void* context;
  7. BFApp* appDev;
  8. } BFDevEnv;
  9. typedef struct {
  10. uint32_t row;
  11. uint32_t col;
  12. } BFDevEnvModel;
  13. typedef struct{
  14. int up;
  15. int down;
  16. int left;
  17. int right;
  18. }bMapping;
  19. static bool bf_dev_process_up(BFDevEnv* devEnv);
  20. static bool bf_dev_process_down(BFDevEnv* devEnv);
  21. static bool bf_dev_process_left(BFDevEnv* devEnv);
  22. static bool bf_dev_process_right(BFDevEnv* devEnv);
  23. static bool bf_dev_process_ok(BFDevEnv* devEnv, InputEvent* event);
  24. BFApp* appDev;
  25. int selectedButton = 0;
  26. int saveNotifyCountdown = 0;
  27. static bMapping buttonMappings[11] = {
  28. {4, 4, 8, 1},
  29. {5, 5, 0, 2},
  30. {6, 6, 1, 3},
  31. {7, 7, 2, 8},
  32. {0, 0, 10, 5},
  33. {1, 1, 4, 6},
  34. {2, 2, 5, 7},
  35. {3, 3, 6, 10},
  36. {10, 9, 3, 0},
  37. {8, 10, 3, 0},
  38. {9, 8, 7, 4}
  39. };
  40. static void bf_dev_draw_button(Canvas* canvas, int x, int y, bool selected, const char* lbl){
  41. UNUSED(lbl);
  42. if(selected){
  43. canvas_draw_rbox(canvas, x, y, 18, 18, 3);
  44. canvas_invert_color(canvas);
  45. canvas_set_font(canvas, FontKeyboard);
  46. canvas_draw_str_aligned(canvas, x + (18/2), y + (18/2) - 1, AlignCenter, AlignCenter, lbl);
  47. canvas_invert_color(canvas);
  48. }
  49. else{
  50. canvas_draw_rbox(canvas, x, y, 18, 18, 3);
  51. canvas_invert_color(canvas);
  52. canvas_draw_rbox(canvas, x+2, y-1, 16, 17, 3);
  53. canvas_invert_color(canvas);
  54. canvas_draw_rframe(canvas, x, y, 18, 18, 3);
  55. canvas_set_font(canvas, FontKeyboard);
  56. canvas_draw_str_aligned(canvas, x + (18/2), y + (18/2) - 1, AlignCenter, AlignCenter, lbl);
  57. }
  58. }
  59. static void bf_dev_draw_callback(Canvas* canvas, void* _model) {
  60. UNUSED(_model);
  61. //buttons
  62. bf_dev_draw_button(canvas, 2, 24, (selectedButton == 0), "+"); //T 0
  63. bf_dev_draw_button(canvas, 22, 24, (selectedButton == 1), "-"); //T 1
  64. bf_dev_draw_button(canvas, 42, 24, (selectedButton == 2), "<"); //T 2
  65. bf_dev_draw_button(canvas, 62, 24, (selectedButton == 3), ">"); //T 3
  66. bf_dev_draw_button(canvas, 2, 44, (selectedButton == 4), "["); //B 0
  67. bf_dev_draw_button(canvas, 22, 44, (selectedButton == 5), "]"); //B 1
  68. bf_dev_draw_button(canvas, 42, 44, (selectedButton == 6), "."); //B 2
  69. bf_dev_draw_button(canvas, 62, 44, (selectedButton == 7), ","); //B 3
  70. //save, run, backspace
  71. canvas_draw_icon(canvas, 110, 24, (selectedButton == 8) ? &I_KeyBackspaceSelected_16x9 : &I_KeyBackspace_16x9);
  72. canvas_draw_icon(canvas, 102, 38, (selectedButton == 9) ? &I_KeyRunSel_24x11 : &I_KeyRun_24x11);
  73. canvas_draw_icon(canvas, 102, 51, (selectedButton == 10) ? &I_KeySaveSelected_24x11 : &I_KeySave_24x11);
  74. if(saveNotifyCountdown > 0){
  75. canvas_draw_icon(canvas, 98, 54, &I_ButtonRightSmall_3x5);
  76. saveNotifyCountdown--;
  77. }
  78. //textbox
  79. canvas_draw_rframe(canvas, 2, 2, 124, 20, 2);
  80. canvas_set_font(canvas, FontKeyboard);
  81. int dbOffset = 0;
  82. if(appDev->dataSize > 20){
  83. dbOffset = (appDev->dataSize - 20);
  84. }
  85. //canvas_draw_str(canvas, 5, 15, (char*)(appDev->dataBuffer + dbOffset));
  86. canvas_draw_str_aligned(canvas, 4, 12, AlignLeft, AlignCenter, (char*)(appDev->dataBuffer + dbOffset));
  87. }
  88. static bool bf_dev_input_callback(InputEvent* event, void* context) {
  89. furi_assert(context);
  90. BFDevEnv* devEnv = context;
  91. bool consumed = false;
  92. if(event->type == InputTypeShort) {
  93. if(event->key == InputKeyRight) {
  94. consumed = bf_dev_process_right(devEnv);
  95. } else if(event->key == InputKeyLeft) {
  96. consumed = bf_dev_process_left(devEnv);
  97. } else if(event->key == InputKeyUp) {
  98. consumed = bf_dev_process_up(devEnv);
  99. } else if(event->key == InputKeyDown) {
  100. consumed = bf_dev_process_down(devEnv);
  101. }
  102. } else if(event->key == InputKeyOk) {
  103. consumed = bf_dev_process_ok(devEnv, event);
  104. }
  105. return consumed;
  106. }
  107. static bool bf_dev_process_up(BFDevEnv* devEnv) {
  108. UNUSED(devEnv);
  109. selectedButton = buttonMappings[selectedButton].up;
  110. return true;
  111. }
  112. static bool bf_dev_process_down(BFDevEnv* devEnv) {
  113. UNUSED(devEnv);
  114. selectedButton = buttonMappings[selectedButton].down;
  115. return true;
  116. }
  117. static bool bf_dev_process_left(BFDevEnv* devEnv) {
  118. UNUSED(devEnv);
  119. selectedButton = buttonMappings[selectedButton].left;
  120. return true;
  121. }
  122. static bool bf_dev_process_right(BFDevEnv* devEnv) {
  123. UNUSED(devEnv);
  124. selectedButton = buttonMappings[selectedButton].right;
  125. return true;
  126. }
  127. static bool bf_dev_process_ok(BFDevEnv* devEnv, InputEvent* event) {
  128. UNUSED(devEnv);
  129. UNUSED(event);
  130. if(event->type != InputTypePress){ return false; }
  131. switch(selectedButton){
  132. case 0:
  133. {
  134. if(appDev->dataSize < BF_INST_BUFFER_SIZE){
  135. appDev->dataBuffer[appDev->dataSize] = (uint32_t)'+';
  136. appDev->dataSize++; }
  137. break;
  138. }
  139. case 1:
  140. {
  141. if(appDev->dataSize < BF_INST_BUFFER_SIZE){
  142. appDev->dataBuffer[appDev->dataSize] = (uint32_t)'-';
  143. appDev->dataSize++; }
  144. break;
  145. }
  146. case 2:
  147. {
  148. if(appDev->dataSize < BF_INST_BUFFER_SIZE){
  149. appDev->dataBuffer[appDev->dataSize] = (uint32_t)'<';
  150. appDev->dataSize++; }
  151. break;
  152. }
  153. case 3:
  154. {
  155. if(appDev->dataSize < BF_INST_BUFFER_SIZE){
  156. appDev->dataBuffer[appDev->dataSize] = (uint32_t)'>';
  157. appDev->dataSize++; }
  158. break;
  159. }
  160. case 4:
  161. {
  162. if(appDev->dataSize < BF_INST_BUFFER_SIZE){
  163. appDev->dataBuffer[appDev->dataSize] = (uint32_t)'[';
  164. appDev->dataSize++; }
  165. break;
  166. }
  167. case 5:
  168. {
  169. if(appDev->dataSize < BF_INST_BUFFER_SIZE){
  170. appDev->dataBuffer[appDev->dataSize] = (uint32_t)']';
  171. appDev->dataSize++; }
  172. break;
  173. }
  174. case 6:
  175. {
  176. if(appDev->dataSize < BF_INST_BUFFER_SIZE){
  177. appDev->dataBuffer[appDev->dataSize] = (uint32_t)'.';
  178. appDev->dataSize++; }
  179. break;
  180. }
  181. case 7:
  182. {
  183. if(appDev->dataSize < BF_INST_BUFFER_SIZE){
  184. appDev->dataBuffer[appDev->dataSize] = (uint32_t)',';
  185. appDev->dataSize++; }
  186. break;
  187. }
  188. case 8:
  189. {
  190. if(appDev->dataSize > 0){
  191. appDev->dataSize--;
  192. appDev->dataBuffer[appDev->dataSize] = (uint32_t)0x00;}
  193. break;
  194. }
  195. case 9:
  196. {
  197. initWorker(appDev->dataBuffer, appDev->dataSize);
  198. beginWorker();
  199. text_box_set_text(appDev->text_box, workerGetOutput());
  200. scene_manager_next_scene(appDev->scene_manager, brainfuckSceneExecEnv);
  201. break;
  202. }
  203. case 10:
  204. {
  205. //remove old file
  206. Storage* storage = furi_record_open(RECORD_STORAGE);
  207. storage_simply_remove(storage, furi_string_get_cstr(appDev->BF_file_path));
  208. //save new file
  209. Stream* stream = buffered_file_stream_alloc(storage);
  210. buffered_file_stream_open(stream, furi_string_get_cstr(appDev->BF_file_path), FSAM_WRITE, FSOM_CREATE_ALWAYS);
  211. stream_write(stream, (const uint8_t*)appDev->dataBuffer, appDev->dataSize);
  212. buffered_file_stream_close(stream);
  213. //notify
  214. saveNotifyCountdown = 5;
  215. break;
  216. }
  217. }
  218. bool consumed = false;
  219. return consumed;
  220. }
  221. static void bf_dev_enter_callback(void* context) {
  222. furi_assert(context);
  223. BFDevEnv* devEnv = context;
  224. with_view_model(
  225. devEnv->view,
  226. BFDevEnvModel* model,
  227. {
  228. model->col = 0;
  229. model->row = 0;
  230. },
  231. true);
  232. appDev = devEnv->appDev;
  233. //clear the bf instruction buffer
  234. memset(appDev->dataBuffer, 0x00, BF_INST_BUFFER_SIZE * sizeof(char));
  235. //open the file
  236. Storage* storage = furi_record_open(RECORD_STORAGE);
  237. Stream* stream = buffered_file_stream_alloc(storage);
  238. buffered_file_stream_open(stream, furi_string_get_cstr(appDev->BF_file_path), FSAM_READ, FSOM_OPEN_EXISTING);
  239. //read into the buffer
  240. appDev->dataSize = stream_size(stream);
  241. stream_read(stream, (uint8_t*)appDev->dataBuffer, appDev->dataSize);
  242. buffered_file_stream_close(stream);
  243. //find the end of the file to begin editing
  244. int tptr = 0;
  245. while(appDev->dataBuffer[tptr] != 0x00){ tptr++; }
  246. appDev->dataSize = tptr;
  247. }
  248. BFDevEnv* bf_dev_env_alloc(BFApp* appDev) {
  249. BFDevEnv* devEnv = malloc(sizeof(BFDevEnv));
  250. devEnv->view = view_alloc();
  251. devEnv->appDev = appDev;
  252. view_allocate_model(devEnv->view, ViewModelTypeLocking, sizeof(BFDevEnvModel));
  253. with_view_model(
  254. devEnv->view,
  255. BFDevEnvModel* model,
  256. {
  257. model->col = 0;
  258. model->row = 0;
  259. },
  260. true);
  261. view_set_context(devEnv->view, devEnv);
  262. view_set_draw_callback(devEnv->view, bf_dev_draw_callback);
  263. view_set_input_callback(devEnv->view, bf_dev_input_callback);
  264. view_set_enter_callback(devEnv->view, bf_dev_enter_callback);
  265. return devEnv;
  266. }
  267. void bf_dev_env_free(BFDevEnv* devEnv) {
  268. furi_assert(devEnv);
  269. view_free(devEnv->view);
  270. free(devEnv);
  271. }
  272. View* bf_dev_env_get_view(BFDevEnv* devEnv) {
  273. furi_assert(devEnv);
  274. return devEnv->view;
  275. }