bf_dev_env.c 11 KB

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