You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

446 lines
18 KiB

  1. // Copyright 2020 @ridingqwerty
  2. // Copyright 2020 @tzarc
  3. // Copyright 2021 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
  4. // SPDX-License-Identifier: GPL-2.0-or-later
  5. #include "drashna.h"
  6. #include "unicode.h"
  7. #include "process_unicode_common.h"
  8. uint8_t unicode_typing_mode = UCTM_NO_MODE;
  9. const char unicode_mode_str[UNCODES_MODE_END][13] PROGMEM = {
  10. " Normal\0",
  11. " Wide\0",
  12. " Script\0",
  13. " Blocks\0",
  14. " Regional\0",
  15. " Aussie\0",
  16. " Zalgo\0",
  17. "Super Script\0",
  18. " Comic\0",
  19. };
  20. /**
  21. * @brief Registers the unicode keystrokes based on desired unicode
  22. *
  23. * @param glyph Unicode character, supports up to 0x1FFFF (or higher)
  24. */
  25. void tap_unicode_glyph_nomods(uint32_t glyph) {
  26. uint8_t temp_mod = get_mods();
  27. clear_mods();
  28. clear_oneshot_mods();
  29. register_unicode(glyph);
  30. set_mods(temp_mod);
  31. }
  32. typedef uint32_t (*translator_function_t)(bool is_shifted, uint32_t keycode);
  33. #define DEFINE_UNICODE_RANGE_TRANSLATOR(translator_name, lower_alpha, upper_alpha, zero_glyph, number_one, space_glyph) \
  34. static inline uint32_t translator_name(bool is_shifted, uint32_t keycode) { \
  35. switch (keycode) { \
  36. case KC_A ... KC_Z: \
  37. return (is_shifted ? upper_alpha : lower_alpha) + keycode - KC_A; \
  38. case KC_0: \
  39. return zero_glyph; \
  40. case KC_1 ... KC_9: \
  41. return (number_one + keycode - KC_1); \
  42. case KC_SPACE: \
  43. return space_glyph; \
  44. } \
  45. return keycode; \
  46. }
  47. #define DEFINE_UNICODE_LUT_TRANSLATOR(translator_name, ...) \
  48. static inline uint32_t translator_name(bool is_shifted, uint32_t keycode) { \
  49. static const uint32_t translation[] = {__VA_ARGS__}; \
  50. uint32_t ret = keycode; \
  51. if ((keycode - KC_A) < ARRAY_SIZE(translation)) { \
  52. ret = translation[keycode - KC_A]; \
  53. } \
  54. return ret; \
  55. }
  56. /**
  57. * @brief Handler function for outputting unicode.
  58. *
  59. * @param keycode Keycode from matrix.
  60. * @param record keyrecord_t data structure
  61. * @param translator translator lut for different unicode modes
  62. * @return true Continue processing matrix press, and send to host
  63. * @return false Replace keycode, and do not send to host
  64. */
  65. bool process_record_glyph_replacement(uint16_t keycode, keyrecord_t *record, translator_function_t translator) {
  66. uint8_t temp_mod = get_mods();
  67. uint8_t temp_osm = get_oneshot_mods();
  68. bool is_shifted = (temp_mod | temp_osm) & MOD_MASK_SHIFT;
  69. if (((temp_mod | temp_osm) & (MOD_MASK_CTRL | MOD_MASK_ALT | MOD_MASK_GUI)) == 0) {
  70. if (KC_A <= keycode && keycode <= KC_Z) {
  71. if (record->event.pressed) {
  72. tap_unicode_glyph_nomods(translator(is_shifted, keycode));
  73. }
  74. return false;
  75. } else if (KC_1 <= keycode && keycode <= KC_0) {
  76. if (is_shifted) { // skip shifted numbers, so that we can still use symbols etc.
  77. return process_record_keymap(keycode, record);
  78. }
  79. if (record->event.pressed) {
  80. register_unicode(translator(is_shifted, keycode));
  81. }
  82. return false;
  83. } else if (keycode == KC_SPACE) {
  84. if (record->event.pressed) {
  85. register_unicode(translator(is_shifted, keycode));
  86. }
  87. return false;
  88. }
  89. }
  90. return true;
  91. }
  92. DEFINE_UNICODE_RANGE_TRANSLATOR(unicode_range_translator_wide, 0xFF41, 0xFF21, 0xFF10, 0xFF11, 0x2003);
  93. DEFINE_UNICODE_RANGE_TRANSLATOR(unicode_range_translator_script, 0x1D4EA, 0x1D4D0, 0x1D7CE, 0x1D7C1, 0x2002);
  94. DEFINE_UNICODE_RANGE_TRANSLATOR(unicode_range_translator_boxes, 0x1F170, 0x1F170, '0', '1', 0x2002);
  95. DEFINE_UNICODE_RANGE_TRANSLATOR(unicode_range_translator_regional, 0x1F1E6, 0x1F1E6, '0', '1', 0x2003);
  96. // DEFINE_UNICODE_LUT_TRANSLATOR(unicode_lut_translator_normal,
  97. // 'a', // a
  98. // 'b', // b
  99. // 'c', // c
  100. // 'd', // d
  101. // 'e', // e
  102. // 'f', // f
  103. // 'g', // g
  104. // 'h', // h
  105. // 'i', // i
  106. // 'j', // j
  107. // 'k', // k
  108. // 'l', // l
  109. // 'm', // m
  110. // 'n', // n
  111. // 'o', // o
  112. // 'p', // p
  113. // 'q', // q
  114. // 'r', // r
  115. // 's', // s
  116. // 't', // t
  117. // 'u', // u
  118. // 'v', // v
  119. // 'w', // w
  120. // 'x', // x
  121. // 'y', // y
  122. // 'z', // z
  123. // '1', // 1
  124. // '2', // 2
  125. // '3', // 3
  126. // '4', // 4
  127. // '5', // 5
  128. // '6', // 6
  129. // '7', // 7
  130. // '8', // 8
  131. // '9', // 9
  132. // '0' // 0
  133. // );
  134. DEFINE_UNICODE_LUT_TRANSLATOR(unicode_lut_translator_aussie,
  135. 0x0250, // a
  136. 'q', // b
  137. 0x0254, // c
  138. 'p', // d
  139. 0x01DD, // e
  140. 0x025F, // f
  141. 0x0183, // g
  142. 0x0265, // h
  143. 0x1D09, // i
  144. 0x027E, // j
  145. 0x029E, // k
  146. 'l', // l
  147. 0x026F, // m
  148. 'u', // n
  149. 'o', // o
  150. 'd', // p
  151. 'b', // q
  152. 0x0279, // r
  153. 's', // s
  154. 0x0287, // t
  155. 'n', // u
  156. 0x028C, // v
  157. 0x028D, // w
  158. 0x2717, // x
  159. 0x028E, // y
  160. 'z', // z
  161. 0x0269, // 1
  162. 0x3139, // 2
  163. 0x0190, // 3
  164. 0x3123, // 4
  165. 0x03DB, // 5
  166. '9', // 6
  167. 0x3125, // 7
  168. '8', // 8
  169. '6', // 9
  170. '0' // 0
  171. );
  172. DEFINE_UNICODE_LUT_TRANSLATOR(unicode_lut_translator_super,
  173. 0x1D43, // a
  174. 0x1D47, // b
  175. 0x1D9C, // c
  176. 0x1D48, // d
  177. 0x1D49, // e
  178. 0x1DA0, // f
  179. 0x1D4D, // g
  180. 0x02B0, // h
  181. 0x2071, // i
  182. 0x02B2, // j
  183. 0x1D4F, // k
  184. 0x02E1, // l
  185. 0x1D50, // m
  186. 0x207F, // n
  187. 0x1D52, // o
  188. 0x1D56, // p
  189. 0x06F9, // q
  190. 0x02B3, // r
  191. 0x02E2, // s
  192. 0x1D57, // t
  193. 0x1D58, // u
  194. 0x1D5B, // v
  195. 0x02B7, // w
  196. 0x02E3, // x
  197. 0x02B8, // y
  198. 0x1DBB, // z
  199. 0x00B9, // 1
  200. 0x00B2, // 2
  201. 0x00B3, // 3
  202. 0x2074, // 4
  203. 0x2075, // 5
  204. 0x2076, // 6
  205. 0x2077, // 7
  206. 0x2078, // 8
  207. 0x2079, // 9
  208. 0x2070 // 0
  209. );
  210. DEFINE_UNICODE_LUT_TRANSLATOR(unicode_lut_translator_comic,
  211. 0x212B, // a
  212. 0x212C, // b
  213. 0x2102, // c
  214. 0x2145, // d
  215. 0x2107, // e
  216. 0x2132, // f
  217. 0x2141, // g
  218. 0x210D, // h
  219. 0x2148, // i
  220. 0x2111, // j
  221. 'k', // k
  222. 0x2143, // l
  223. 'm', // m
  224. 0x2115, // n
  225. 0x2134, // o
  226. 0x2119, // p
  227. 0x211A, // q
  228. 0x211B, // r
  229. 0x20B7, // s
  230. 0x20B8, // t
  231. 0x2127, // u
  232. 'v', // v
  233. 0x20A9, // w
  234. 'x', // x
  235. 0x213D, // y
  236. 'z', // z
  237. '1', // 1
  238. '2', // 2
  239. '3', // 3
  240. '4', // 4
  241. '5', // 5
  242. '6', // 6
  243. '7', // 7
  244. '8', // 8
  245. '9', // 9
  246. '0' // 0
  247. );
  248. bool process_record_aussie(uint16_t keycode, keyrecord_t *record) {
  249. bool is_shifted = (get_mods() | get_oneshot_mods()) & MOD_MASK_SHIFT;
  250. if ((KC_A <= keycode) && (keycode <= KC_0)) {
  251. if (record->event.pressed) {
  252. if (!process_record_glyph_replacement(keycode, record, unicode_lut_translator_aussie)) {
  253. tap_code16_nomods(KC_LEFT);
  254. return false;
  255. }
  256. }
  257. } else if (record->event.pressed && keycode == KC_SPACE) {
  258. tap_code16_nomods(KC_SPACE);
  259. tap_code16_nomods(KC_LEFT);
  260. return false;
  261. } else if (record->event.pressed && keycode == KC_ENTER) {
  262. tap_code16_nomods(KC_END);
  263. tap_code16_nomods(KC_ENTER);
  264. return false;
  265. } else if (record->event.pressed && keycode == KC_HOME) {
  266. tap_code16_nomods(KC_END);
  267. return false;
  268. } else if (record->event.pressed && keycode == KC_END) {
  269. tap_code16_nomods(KC_HOME);
  270. return false;
  271. } else if (record->event.pressed && keycode == KC_BSPC) {
  272. tap_code16_nomods(KC_DEL);
  273. return false;
  274. } else if (record->event.pressed && keycode == KC_DEL) {
  275. tap_code16_nomods(KC_BSPC);
  276. return false;
  277. } else if (record->event.pressed && keycode == KC_QUOT) {
  278. tap_unicode_glyph_nomods(is_shifted ? 0x201E : 0x201A);
  279. tap_code16_nomods(KC_LEFT);
  280. return false;
  281. } else if (record->event.pressed && keycode == KC_COMMA) {
  282. tap_unicode_glyph_nomods(is_shifted ? '<' : 0x2018);
  283. tap_code16_nomods(KC_LEFT);
  284. return false;
  285. } else if (record->event.pressed && keycode == KC_DOT) {
  286. tap_unicode_glyph_nomods(is_shifted ? '>' : 0x02D9);
  287. tap_code16_nomods(KC_LEFT);
  288. return false;
  289. } else if (record->event.pressed && keycode == KC_SLASH) {
  290. tap_unicode_glyph_nomods(is_shifted ? 0x00BF : '/');
  291. tap_code16_nomods(KC_LEFT);
  292. return false;
  293. }
  294. return true;
  295. }
  296. bool process_record_zalgo(uint16_t keycode, keyrecord_t *record) {
  297. if ((KC_A <= keycode) && (keycode <= KC_0)) {
  298. if (record->event.pressed) {
  299. tap_code16_nomods(keycode);
  300. int number = (rand() % (8 + 1 - 2)) + 2;
  301. for (int index = 0; index < number; index++) {
  302. uint16_t hex = (rand() % (0x036F + 1 - 0x0300)) + 0x0300;
  303. register_unicode(hex);
  304. }
  305. return false;
  306. }
  307. }
  308. return true;
  309. }
  310. /**
  311. * @brief Main handler for unicode input
  312. *
  313. * @param keycode Keycode from switch matrix
  314. * @param record keyrecord_t data struture
  315. * @return true Send keycode from matrix to host
  316. * @return false Stop processing and do not send to host
  317. */
  318. bool process_record_unicode(uint16_t keycode, keyrecord_t *record) {
  319. switch (keycode) {
  320. case UC_FLIP: // (ノಠ痊ಠ)ノ彡┻━┻
  321. if (record->event.pressed) {
  322. send_unicode_string("(ノಠ痊ಠ)ノ彡┻━┻");
  323. }
  324. break;
  325. case UC_TABL: // ┬─┬ノ( º _ ºノ)
  326. if (record->event.pressed) {
  327. send_unicode_string("┬─┬ノ( º _ ºノ)");
  328. }
  329. break;
  330. case UC_SHRG: // ¯\_(ツ)_/¯
  331. if (record->event.pressed) {
  332. send_unicode_string("¯\\_(ツ)_/¯");
  333. }
  334. break;
  335. case UC_DISA: // ಠ_ಠ
  336. if (record->event.pressed) {
  337. send_unicode_string("ಠ_ಠ");
  338. }
  339. break;
  340. case UC_IRNY: // ⸮
  341. if (record->event.pressed) {
  342. register_unicode(0x2E2E);
  343. }
  344. break;
  345. case UC_CLUE: // ‽
  346. if (record->event.pressed) {
  347. register_unicode(0x203D);
  348. }
  349. break;
  350. case KC_NOMODE ... KC_COMIC:
  351. if (record->event.pressed) {
  352. if (unicode_typing_mode != keycode - KC_NOMODE) {
  353. unicode_typing_mode = keycode - KC_NOMODE;
  354. } else {
  355. unicode_typing_mode = UCTM_NO_MODE;
  356. }
  357. }
  358. break;
  359. }
  360. if (((get_mods() | get_oneshot_mods()) & ~MOD_MASK_SHIFT) != 0) {
  361. return true;
  362. }
  363. if (IS_QK_MOD_TAP(keycode) && record->tap.count) {
  364. keycode = QK_MOD_TAP_GET_TAP_KEYCODE(keycode);
  365. }
  366. if (IS_QK_LAYER_TAP(keycode) && record->tap.count) {
  367. keycode = QK_LAYER_TAP_GET_TAP_KEYCODE(keycode);
  368. }
  369. if (unicode_typing_mode == UCTM_WIDE) {
  370. if (((KC_A <= keycode) && (keycode <= KC_0)) || keycode == KC_SPACE) {
  371. return process_record_glyph_replacement(keycode, record, unicode_range_translator_wide);
  372. }
  373. } else if (unicode_typing_mode == UCTM_SCRIPT) {
  374. if (((KC_A <= keycode) && (keycode <= KC_0)) || keycode == KC_SPACE) {
  375. return process_record_glyph_replacement(keycode, record, unicode_range_translator_script);
  376. }
  377. } else if (unicode_typing_mode == UCTM_BLOCKS) {
  378. if (((KC_A <= keycode) && (keycode <= KC_0)) || keycode == KC_SPACE) {
  379. return process_record_glyph_replacement(keycode, record, unicode_range_translator_boxes);
  380. }
  381. } else if (unicode_typing_mode == UCTM_REGIONAL) {
  382. if (((KC_A <= keycode) && (keycode <= KC_0)) || keycode == KC_SPACE) {
  383. if (!process_record_glyph_replacement(keycode, record, unicode_range_translator_regional)) {
  384. wait_us(500);
  385. tap_unicode_glyph_nomods(0x200C);
  386. return false;
  387. }
  388. }
  389. } else if (unicode_typing_mode == UCTM_SUPER) {
  390. if (((KC_A <= keycode) && (keycode <= KC_0))) {
  391. return process_record_glyph_replacement(keycode, record, unicode_lut_translator_super);
  392. }
  393. } else if (unicode_typing_mode == UCTM_COMIC) {
  394. if (((KC_A <= keycode) && (keycode <= KC_0))) {
  395. return process_record_glyph_replacement(keycode, record, unicode_lut_translator_comic);
  396. }
  397. } else if (unicode_typing_mode == UCTM_AUSSIE) {
  398. return process_record_aussie(keycode, record);
  399. } else if (unicode_typing_mode == UCTM_ZALGO) {
  400. return process_record_zalgo(keycode, record);
  401. }
  402. return true;
  403. }
  404. /**
  405. * @brief Initialize the default unicode mode on firmware startup
  406. *
  407. */
  408. void keyboard_post_init_unicode(void) {
  409. unicode_input_mode_init();
  410. }
  411. /**
  412. * @brief Set the unicode input mode without extra functionality
  413. *
  414. * @param input_mode
  415. */
  416. void set_unicode_input_mode_soft(uint8_t input_mode) {
  417. unicode_config.input_mode = input_mode;
  418. unicode_input_mode_set_kb(input_mode);
  419. }