Guest User

keyremap

a guest
Mar 6th, 2022
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.27 KB | None | 0 0
  1. diff --git a/apps/plugins/keyremap.c b/apps/plugins/keyremap.c
  2. index 0a6b705e9d..ebddeda642 100644
  3. --- a/apps/plugins/keyremap.c
  4. +++ b/apps/plugins/keyremap.c
  5. @@ -102,6 +102,8 @@ enum {
  6. M_SETKEYS,
  7. M_TESTKEYS,
  8. M_RESETKEYS,
  9. + M_EXPORTKEYS,
  10. + M_IMPORTKEYS,
  11. M_SAVEKEYS,
  12. M_LOADKEYS,
  13. M_DELKEYS,
  14. @@ -125,8 +127,10 @@ MENU_ITEM(M_ROOT, "Key Remap Plugin", M_LAST_MAINITEM - 1),
  15. MENU_ITEM(M_SETKEYS, "Edit Keymap", 1),
  16. MENU_ITEM(M_TESTKEYS, "Test Keymap", 4),
  17. MENU_ITEM(M_RESETKEYS, "Reset Keymap", 1),
  18. -MENU_ITEM(M_SAVEKEYS, "Save Keymap", 1),
  19. -MENU_ITEM(M_LOADKEYS, "Load Keymaps", 1),
  20. +MENU_ITEM(M_EXPORTKEYS, "Export Text Keymap", 1),
  21. +MENU_ITEM(M_IMPORTKEYS, "Import Text Keymap", 1),
  22. +MENU_ITEM(M_SAVEKEYS, "Save Native Keymap", 1),
  23. +MENU_ITEM(M_LOADKEYS, "Load Native Keymaps", 1),
  24. MENU_ITEM(M_DELKEYS, "Delete Keymaps", 1),
  25. MENU_ITEM(M_TMPCORE, "Temp Core Remap", 1),
  26. MENU_ITEM(M_SETCORE, "Set Core Remap", 1),
  27. @@ -172,8 +176,11 @@ static struct mainmenu *mainitem(int selected_item)
  28. else
  29. return ∅
  30. }
  31. -
  32. +/* Forward Declarations */
  33. +static const char *edit_keymap_name_cb(int selected_item, void* data,char* buf, size_t buf_len);
  34. +static int keyremap_import_file(char *filenamebuf, size_t bufsz);
  35. static void synclist_set(int id, int selected_item, int items, int sel_size);
  36. +
  37. static void synclist_set_update(int id, int selected_item, int items, int sel_size)
  38. {
  39. SET_MENU_ITEM(lists.selected_item + 1); /* update selected for previous menu*/
  40. @@ -471,11 +478,11 @@ static int keyremap_save_current(const char *filename)
  41. static void keyremap_save_user_keys(bool notify)
  42. {
  43. char buf[MAX_PATH];
  44. - int i = 1;
  45. + int i = 0;
  46. do
  47. {
  48. - rb->snprintf(buf, sizeof(buf), "%s/%s%d%s", KMFDIR, KMFUSER, i, KMFEXT1);
  49. i++;
  50. + rb->snprintf(buf, sizeof(buf), "%s/%s%d%s", KMFDIR, KMFUSER, i, KMFEXT1);
  51. } while (i < 100 && rb->file_exists(buf));
  52.  
  53. if (keyremap_save_current(buf) == 0)
  54. @@ -487,6 +494,120 @@ static void keyremap_save_user_keys(bool notify)
  55. rb->splashf(HZ *2, "Saved %s", buf);
  56. }
  57.  
  58. +static int keyremap_export_current(char *filenamebuf, size_t bufsz)
  59. +{
  60. + filenamebuf[bufsz - 1] = '\0';
  61. + int i, j;
  62. + int ctx_count = 0;
  63. + size_t entrylen;
  64. +
  65. + int entry_count = ctx_data.ctx_count + ctx_data.act_count + 1;;/* (ctx_count + ctx_count + act_count + 1) */
  66. +
  67. + if (entry_count <= 3)
  68. + return 0;
  69. +
  70. + int fd = rb->open(filenamebuf, O_WRONLY | O_CREAT | O_TRUNC, 0666);
  71. +
  72. + if (fd < 0)
  73. + return -1;
  74. + rb->fdprintf(fd, "Key Remap Entries: %d\n", entry_count - 1);
  75. + for (i = 0; i <= entry_count; i++)
  76. + {
  77. + entrylen = 0;
  78. + rb->memset(filenamebuf, 0, bufsz);
  79. + edit_keymap_name_cb(i, MENU_ID(M_EXPORTKEYS), filenamebuf, bufsz);
  80. + if (i == 0)
  81. + {
  82. + ctx_menu_data.act_fmt = " {%s%s, %s, %s},\n\n";
  83. + continue;
  84. + }
  85. + else if (i == entry_count)
  86. + {
  87. + rb->strlcpy(filenamebuf, "}\n\n", bufsz);
  88. + }
  89. + char last = '\0';
  90. + for (j = 0; j < (int)bufsz ;j++)
  91. + {
  92. + char ch = filenamebuf[j];
  93. + if (ch == '$' && last == '\0') /*CONTEXT*/
  94. + {
  95. + const char eoc[] = "}\n";
  96. + if (ctx_count > 0)
  97. + rb->write(fd, &eoc, sizeof(eoc) - 1);
  98. + ctx_count++;
  99. + filenamebuf[j] = '\n';
  100. + }
  101. + if (ch == '\n' && last == '\n')
  102. + {
  103. + entrylen = j;
  104. + break;
  105. + }
  106. + else if (ch == '\0')
  107. + filenamebuf[j] = ',';
  108. + last = ch;
  109. + }
  110. +
  111. + size_t bytes = rb->write(fd, filenamebuf, entrylen);
  112. + if (bytes != entrylen)
  113. + {
  114. + entry_count = -2;
  115. + goto fail;
  116. + }
  117. + }
  118. +
  119. +fail:
  120. + rb->close(fd);
  121. +
  122. + return entry_count;
  123. +}
  124. +
  125. +static void keyremap_export_user_keys(void)
  126. +{
  127. + const bool notify = true;
  128. + char buf[MAX_PATH];
  129. + int i = 0;
  130. + do
  131. + {
  132. + i++;
  133. + rb->snprintf(buf, sizeof(buf), "%s/%s%d%s", "", KMFUSER, i, ".txt");
  134. + } while (i < 100 && rb->file_exists(buf));
  135. +
  136. + if (keyremap_export_current(buf, sizeof(buf)) <= 0)
  137. + {
  138. + if(notify)
  139. + rb->splash(HZ *2, "Error Saving");
  140. + }
  141. + else if (notify)
  142. + {
  143. + rb->snprintf(buf, sizeof(buf), "%s/%s%d%s", "", KMFUSER, i, ".txt");
  144. + rb->splashf(HZ *2, "Saved %s", buf);
  145. + }
  146. +}
  147. +
  148. +static void keyremap_import_user_keys(void)
  149. +{
  150. + char buf[MAX_PATH];
  151. + struct browse_context browse;
  152. +
  153. + rb->browse_context_init(&browse, SHOW_ALL, BROWSE_SELECTONLY, "Select Keymap",
  154. + Icon_Plugin, "/", NULL);
  155. +
  156. + browse.buf = buf;
  157. + browse.bufsize = sizeof(buf);
  158. +
  159. + if (rb->rockbox_browse(&browse) == GO_TO_PREVIOUS)
  160. + {
  161. + int ret = keyremap_import_file(buf, sizeof(buf));
  162. + if (ret <= 0)
  163. + {
  164. + keyremap_reset_buffer();
  165. + rb->splash(HZ *2, "Error Opening");
  166. + }
  167. + else
  168. + rb->splashf(HZ * 2, "Loaded Text Keymap ");
  169. + }
  170. +}
  171. +
  172. static int keymap_add_context_entry(int context)
  173. {
  174. int remap_context = CORE_CONTEXT_REMAP(context);
  175. @@ -538,6 +659,317 @@ fail:
  176. return 0;
  177. }
  178.  
  179. +static int get_action_from_str(char *pfield, size_t bufsz)
  180. +{
  181. + int act = -1;
  182. + for (int i=0;i < LAST_ACTION_PLACEHOLDER; i++)
  183. + {
  184. + if (rb->strncasecmp(pfield, action_name(i), bufsz) == 0)
  185. + {
  186. + logf("Action Found: %s (%d)", pfield, i);
  187. + act = i;
  188. + break;
  189. + }
  190. + }
  191. + return act;
  192. +}
  193. +
  194. +static int get_button_from_str(char *pfield, size_t bufsz)
  195. +{
  196. + int btn = -1;
  197. + for (int i=0;i < available_button_count; i++)
  198. + {
  199. + const struct available_button* abtn = &available_buttons[i];
  200. + if (rb->strncasecmp(pfield, abtn->name, bufsz) == 0)
  201. + {
  202. + logf("Button Found: %s (%lx)", abtn->name, abtn->value);
  203. + btn = abtn->value;
  204. + break;
  205. + }
  206. + }
  207. + return btn;
  208. +}
  209. +
  210. +static int parse_action_import_entry(int context, char * pbuf, size_t bufsz)
  211. +{
  212. + size_t bufleft;
  213. + int count = 0;
  214. + char ch;
  215. + char *pfirst = NULL;
  216. + char *pfield;
  217. + int field = -1;
  218. + int act = -1;
  219. + int button = BUTTON_NONE;
  220. + int prebtn = BUTTON_NONE;
  221. + while ((ch = *(pbuf)) != '\0')
  222. + {
  223. + pfield = NULL; /* Valid names */
  224. + if ((ch >= 'A' && ch <= 'Z') || ch == '_')
  225. + {
  226. + if (pfirst == NULL)
  227. + pfirst = pbuf;
  228. + }
  229. + else if (ch == ',')
  230. + {
  231. + if (pfirst != NULL)
  232. + {
  233. + field++;
  234. + pfield = pfirst;
  235. + pfirst = NULL;
  236. + *pbuf = '\0';
  237. + }
  238. + }
  239. + else if (ch == ' ' || ch == '|'){;}
  240. + else
  241. + pfirst = NULL;
  242. +
  243. + if (field == 1 && pfirst != NULL && pbuf[1] == '\0')
  244. + {
  245. + field++;
  246. + pfield = pfirst;
  247. + pfirst = NULL;
  248. + }
  249. +
  250. + if (pfield != NULL)
  251. + {
  252. + char *pf;
  253. +
  254. + if (field == 0) /* action */
  255. + {
  256. + char *pact = pfield;
  257. + pf = pfield;
  258. + while ((ch = *(pf)) != '\0')
  259. + {
  260. + if(ch == ' ')
  261. + *pf = '\0';
  262. + else
  263. + pf++;
  264. + }
  265. + bufleft = bufsz - (pact - pbuf);
  266. + act = get_action_from_str(pact, bufleft);
  267. +
  268. + if (act < 0)
  269. + {
  270. + logf("Error Action Expected: %s", pact);
  271. + return -1;
  272. + }
  273. + }
  274. + else if (field == 1 || field == 2) /* button / pre_btn */
  275. + {
  276. + char *pbtn = pfield;
  277. + pf = pfield;
  278. + while ((ch = *(pf)) != '\0')
  279. + {
  280. + if (pf[1] == '\0') /* last item? */
  281. + {
  282. + pf++;
  283. + ch = '|';
  284. + pfield = NULL;
  285. + }
  286. + else if (ch == ' ' || ch == '|')
  287. + {
  288. + *pf = '\0';
  289. + }
  290. +
  291. + if(ch == '|')
  292. + {
  293. + bufleft = bufsz - (pbtn - pbuf);
  294. + int btn = get_button_from_str(pbtn, bufleft);
  295. +
  296. + if (btn > BUTTON_NONE)
  297. + {
  298. + if (field == 1)
  299. + button |= btn;
  300. + else if (field == 2)
  301. + prebtn |= btn;
  302. + }
  303. +
  304. + if (pfield != NULL)
  305. + {
  306. + pf++;
  307. + while ((ch = *(pf)) != '\0')
  308. + {
  309. + if (*pf == ' ')
  310. + pf++;
  311. + else
  312. + break;
  313. + }
  314. + pbtn = pf;
  315. + }
  316. + }
  317. + else
  318. + pf++;
  319. + }
  320. +
  321. + if (act < 0)
  322. + {
  323. + logf("Error Action Expected: %s", pfield);
  324. + return -1;
  325. + }
  326. + }
  327. +
  328. + pfield = NULL;
  329. + }
  330. +
  331. + pbuf++;
  332. + }
  333. + if (field == 2)
  334. + {
  335. + count = keymap_add_button_entry(context, act, button, prebtn);
  336. + if (count > 0)
  337. + {
  338. + logf("Added: Ctx: %d, Act: %d, Btn: %d PBtn: %d",
  339. + context, act, button, prebtn);
  340. + }
  341. + }
  342. + return count;
  343. +}
  344. +
  345. +static int keyremap_import_file(char *filenamebuf, size_t bufsz)
  346. +{
  347. + size_t bufleft;
  348. + int count = 0;
  349. + int line = 0;
  350. + filenamebuf[bufsz - 1] = '\0';
  351. + logf("keyremap: import %s", filenamebuf);
  352. + int fd = rb->open(filenamebuf, O_RDONLY);
  353. + if (fd < 0)
  354. + return -1;
  355. +
  356. + char ch;
  357. + char *pbuf;
  358. + char *pfirst;
  359. +
  360. + char *pctx = NULL;
  361. + char *pact;
  362. + int ctx = -1;
  363. +
  364. + keyremap_reset_buffer();
  365. +next_line:
  366. + while (rb->read_line(fd, filenamebuf, (int) bufsz) > 0)
  367. + {
  368. + line++;
  369. +
  370. +
  371. + pbuf = filenamebuf;
  372. + pfirst = NULL;
  373. + pact = NULL;
  374. +
  375. + while ((ch = *(pbuf)) != '\0')
  376. + {
  377. + /* PARSE CONTEXT = { */
  378. + if ((ch >= 'A' && ch <= 'Z') || ch == '_')
  379. + {
  380. + if (pfirst == NULL)
  381. + pfirst = pbuf;
  382. + }
  383. + else if (ch == ' ')
  384. + {
  385. + if (ctx < 0 && pfirst != NULL)
  386. + {
  387. + *pbuf = '\0';
  388. + pctx = pfirst;
  389. + pfirst = NULL;
  390. + }
  391. + }
  392. + else if (ch == '=')
  393. + {
  394. + if (ctx < 0 && pfirst != NULL)
  395. + {
  396. + *pbuf = '\0';
  397. + pbuf++;
  398. + pctx = pfirst;
  399. + pfirst = NULL;
  400. + }
  401. + while ((ch = *(pbuf)) != '\0')
  402. + {
  403. + if (ch == '{')
  404. + break;
  405. + pbuf++;
  406. + }
  407. + if (ch == '{' && pctx != NULL)
  408. + {
  409. + bufleft = bufsz - (pctx - filenamebuf);
  410. + ctx = -1;
  411. + for (int i=0;i < LAST_CONTEXT_PLACEHOLDER;i++)
  412. + {
  413. + if (rb->strncasecmp(pctx, context_name(i), bufleft) == 0)
  414. + {
  415. + logf("ln: %d: Context Found: %s (%d)", line, pctx, i);
  416. + if (keymap_add_context_entry(i) <= 0)
  417. + logf("ln: %d: Context Exists: %s (%d)", line, pctx, i);
  418. + ctx = i;
  419. + goto next_line;
  420. +
  421. + }
  422. + }
  423. + logf("ln: %d: ERROR { Context Expected got: %s", line, pctx);
  424. + goto fail;
  425. + }
  426. + }
  427. + else if (ch == '}')
  428. + {
  429. + if (ctx >= 0)
  430. + ctx = -1;
  431. + else
  432. + {
  433. + logf("ln: %d: ERROR no context, unexpected close {", line);
  434. + goto fail;
  435. + }
  436. + }
  437. + else if (ch == '{') /* PARSE FIELDS { ACTION, BUTTON, PREBTN } */
  438. + {
  439. + int res = 0;
  440. + if (ctx >= 0)
  441. + {
  442. + pfirst = pbuf;
  443. +
  444. + while ((ch = *(pbuf)) != '\0')
  445. + {
  446. + if (ch == '}')
  447. + {
  448. + pact = pfirst + 1;
  449. + pfirst = NULL;
  450. + *pbuf = '\0';
  451. + pbuf = "";
  452. + continue;
  453. + }
  454. + pbuf++;
  455. + }
  456. + if (pact != NULL)
  457. + {
  458. + bufleft = bufsz - (pact - filenamebuf);
  459. + logf("ln: %d: Entry Found: {%s} (%d)", line, pact, 0);
  460. + res = parse_action_import_entry(ctx, pact, bufleft);
  461. + }
  462. + }
  463. + if (res <= 0)
  464. + {
  465. + logf("ln: %d: ERROR action entry expected", line);
  466. + goto fail;
  467. + }
  468. + else
  469. + {
  470. + pbuf = "";
  471. + continue;
  472. + }
  473. + }
  474. + else
  475. + pfirst = NULL;
  476. + pbuf++;
  477. + }
  478. +
  479. + }
  480. + rb->close(fd);
  481. + count = ctx_data.ctx_count + ctx_data.act_count;
  482. + return count;
  483. +
  484. +fail:
  485. + rb->close(fd);
  486. + rb->splashf(HZ * 2, "Error @ line %d", line);
  487. + return 0;
  488. +}
  489. +
  490. static int keyremap_load_file(const char *filename)
  491. {
  492. logf("keyremap: load %s", filename);
  493. @@ -709,7 +1141,18 @@ static const char *menu_useract_items_cb(int selected_item, void* data,
  494. static char buf_button[MAX_BUTTON_NAME * MAX_BUTTON_COMBO];
  495. static char buf_prebtn[MAX_BUTTON_NAME * MAX_BUTTON_COMBO];
  496. int i;
  497. - (void)data;
  498. + int szbtn = sizeof("BUTTON");
  499. + int szctx = sizeof("CONTEXT");
  500. + int szact = sizeof("ACTION");
  501. + const char* ctxfmt = "%s";
  502. +
  503. + if (data == MENU_ID(M_EXPORTKEYS))
  504. + {
  505. + szbtn = 0;
  506. + szctx = 0;
  507. + szact = 0;
  508. + ctxfmt = "$%s = {\n\n";
  509. + }
  510. buf[0] = '\0';
  511. for(i = 0; i < ctx_data.ctx_count; i ++)
  512. {
  513. @@ -720,7 +1163,7 @@ static const char *menu_useract_items_cb(int selected_item, void* data,
  514. context_name(ctx_data.ctx_map[i].context),
  515. "Select$to add$actions");
  516. else
  517. - rb->snprintf(buf, buf_len, "%s", context_name(ctx_data.ctx_map[i].context));
  518. + rb->snprintf(buf, buf_len, ctxfmt, context_name(ctx_data.ctx_map[i].context));
  519. return buf;
  520. }
  521. }
  522. @@ -730,19 +1173,23 @@ static const char *menu_useract_items_cb(int selected_item, void* data,
  523. {
  524. int context = ctx_data.act_map[i].context;
  525. char ctxbuf[action_helper_maxbuffer];
  526. - char *pctxbuf = ctxbuf;
  527. + char *pctxbuf = "\0";
  528. char *pactname;
  529. - rb->snprintf(ctxbuf, sizeof(ctxbuf), "%s", context_name(context));
  530. - pctxbuf += sizeof("CONTEXT");
  531. + if (data != MENU_ID(M_EXPORTKEYS))
  532. + {
  533. + pctxbuf = ctxbuf;
  534. + rb->snprintf(ctxbuf, sizeof(ctxbuf), ctxfmt, context_name(context));
  535. + pctxbuf += szctx;//sizeof("CONTEXT")
  536. + }
  537. struct button_mapping * bm = &ctx_data.act_map[i].map;
  538. pactname = action_name(bm->action_code);
  539. - pactname += sizeof("ACTION");
  540. + pactname += szact;//sizeof("ACTION")
  541. /* BUTTON & PRE_BUTTON */
  542. btnval_to_name(buf_button, sizeof(buf_button), bm->button_code);
  543. btnval_to_name(buf_prebtn, sizeof(buf_prebtn), bm->pre_button_code);
  544.  
  545. rb->snprintf(buf, buf_len, ctx_menu_data.act_fmt, pctxbuf,
  546. - pactname, buf_button + sizeof("BUTTON"), buf_prebtn + sizeof("BUTTON"));
  547. + pactname, buf_button + szbtn, buf_prebtn + szbtn);
  548. return buf;
  549. }
  550. }
  551. @@ -752,7 +1199,6 @@ static const char *menu_useract_items_cb(int selected_item, void* data,
  552. static const char *edit_keymap_name_cb(int selected_item, void* data,
  553. char* buf, size_t buf_len)
  554. {
  555. - (void)data;
  556. buf[0] = '\0';
  557. if (selected_item == 0)
  558. {
  559. @@ -930,6 +1376,16 @@ int menu_action_root(int *action, int selected_item, bool* exit, struct gui_sync
  560. keyremap_save_user_keys(true);
  561. goto default_handler;
  562. }
  563. + else if (cur->menuid == MENU_ID(M_EXPORTKEYS))
  564. + {
  565. + keyremap_export_user_keys();
  566. + goto default_handler;
  567. + }
  568. + else if (cur->menuid == MENU_ID(M_IMPORTKEYS))
  569. + {
  570. + keyremap_import_user_keys();
  571. + goto default_handler;
  572. + }
  573. else if (cur->menuid == MENU_ID(M_DELKEYS) ||
  574. cur->menuid == MENU_ID(M_LOADKEYS))
  575. {
  576. @@ -1118,7 +1574,6 @@ int menu_action_testkeys(int *action, int selected_item, bool* exit, struct gui_
  577. goto default_handler;
  578. }
  579.  
  580. -
  581. if (*action == ACTION_STD_CANCEL && selected_item == 0 && keytest.keymap != NULL)
  582. {
  583. keytest.index -= 2;
  584.  
Advertisement
Add Comment
Please, Sign In to add comment