logo

qmk_firmware

custom branch of QMK firmware git clone https://anongit.hacktivis.me/git/qmk_firmware.git

keycode_string.c (23052B)


  1. // Copyright 2024-2025 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // https://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "keycode_string.h"
  15. #include <string.h>
  16. #include "bitwise.h"
  17. #include "keycode.h"
  18. #include "progmem.h"
  19. #include "quantum_keycodes.h"
  20. #include "util.h"
  21. typedef int_fast8_t index_t;
  22. // clang-format off
  23. /** Packs a 7-char keycode name, ignoring the third char, as 3 words. */
  24. #define KEYCODE_NAME7(c0, c1, unused_c2, c3, c4, c5, c6) \
  25. ((uint16_t)c0) | (((uint16_t)c1) << 8), \
  26. ((uint16_t)c3) | (((uint16_t)c4) << 8), \
  27. ((uint16_t)c5) | (((uint16_t)c6) << 8)
  28. /**
  29. * @brief Names of some common keycodes.
  30. *
  31. * Each (keycode, name) entry is stored flat in 8 bytes in PROGMEM. Names in
  32. * this table must be at most 7 chars long and have an underscore '_' for the
  33. * third char. This underscore is assumed and not actually stored.
  34. *
  35. * To save memory, feature-specific key entries are ifdef'd to include them only
  36. * when their feature is enabled.
  37. */
  38. static const uint16_t common_names[] PROGMEM = {
  39. KC_TRNS, KEYCODE_NAME7('K', 'C', '_', 'T', 'R', 'N', 'S'),
  40. KC_ENT , KEYCODE_NAME7('K', 'C', '_', 'E', 'N', 'T', 0 ),
  41. KC_ESC , KEYCODE_NAME7('K', 'C', '_', 'E', 'S', 'C', 0 ),
  42. KC_BSPC, KEYCODE_NAME7('K', 'C', '_', 'B', 'S', 'P', 'C'),
  43. KC_TAB , KEYCODE_NAME7('K', 'C', '_', 'T', 'A', 'B', 0 ),
  44. KC_SPC , KEYCODE_NAME7('K', 'C', '_', 'S', 'P', 'C', 0 ),
  45. KC_MINS, KEYCODE_NAME7('K', 'C', '_', 'M', 'I', 'N', 'S'),
  46. KC_EQL , KEYCODE_NAME7('K', 'C', '_', 'E', 'Q', 'L', 0 ),
  47. KC_LBRC, KEYCODE_NAME7('K', 'C', '_', 'L', 'B', 'R', 'C'),
  48. KC_RBRC, KEYCODE_NAME7('K', 'C', '_', 'R', 'B', 'R', 'C'),
  49. KC_BSLS, KEYCODE_NAME7('K', 'C', '_', 'B', 'S', 'L', 'S'),
  50. KC_NUHS, KEYCODE_NAME7('K', 'C', '_', 'N', 'U', 'H', 'S'),
  51. KC_SCLN, KEYCODE_NAME7('K', 'C', '_', 'S', 'C', 'L', 'N'),
  52. KC_QUOT, KEYCODE_NAME7('K', 'C', '_', 'Q', 'U', 'O', 'T'),
  53. KC_GRV , KEYCODE_NAME7('K', 'C', '_', 'G', 'R', 'V', 0 ),
  54. KC_COMM, KEYCODE_NAME7('K', 'C', '_', 'C', 'O', 'M', 'M'),
  55. KC_DOT , KEYCODE_NAME7('K', 'C', '_', 'D', 'O', 'T', 0 ),
  56. KC_SLSH, KEYCODE_NAME7('K', 'C', '_', 'S', 'L', 'S', 'H'),
  57. KC_CAPS, KEYCODE_NAME7('K', 'C', '_', 'C', 'A', 'P', 'S'),
  58. KC_PSCR, KEYCODE_NAME7('K', 'C', '_', 'P', 'S', 'C', 'R'),
  59. KC_PAUS, KEYCODE_NAME7('K', 'C', '_', 'P', 'A', 'U', 'S'),
  60. KC_INS , KEYCODE_NAME7('K', 'C', '_', 'I', 'N', 'S', 0 ),
  61. KC_HOME, KEYCODE_NAME7('K', 'C', '_', 'H', 'O', 'M', 'E'),
  62. KC_PGUP, KEYCODE_NAME7('K', 'C', '_', 'P', 'G', 'U', 'P'),
  63. KC_DEL , KEYCODE_NAME7('K', 'C', '_', 'D', 'E', 'L', 0 ),
  64. KC_END , KEYCODE_NAME7('K', 'C', '_', 'E', 'N', 'D', 0 ),
  65. KC_PGDN, KEYCODE_NAME7('K', 'C', '_', 'P', 'G', 'D', 'N'),
  66. KC_RGHT, KEYCODE_NAME7('K', 'C', '_', 'R', 'G', 'H', 'T'),
  67. KC_LEFT, KEYCODE_NAME7('K', 'C', '_', 'L', 'E', 'F', 'T'),
  68. KC_DOWN, KEYCODE_NAME7('K', 'C', '_', 'D', 'O', 'W', 'N'),
  69. KC_UP , KEYCODE_NAME7('K', 'C', '_', 'U', 'P', 0 , 0 ),
  70. KC_NUBS, KEYCODE_NAME7('K', 'C', '_', 'N', 'U', 'B', 'S'),
  71. KC_HYPR, KEYCODE_NAME7('K', 'C', '_', 'H', 'Y', 'P', 'R'),
  72. KC_MEH , KEYCODE_NAME7('K', 'C', '_', 'M', 'E', 'H', 0 ),
  73. #ifdef EXTRAKEY_ENABLE
  74. KC_WHOM, KEYCODE_NAME7('K', 'C', '_', 'W', 'H', 'O', 'M'),
  75. KC_WBAK, KEYCODE_NAME7('K', 'C', '_', 'W', 'B', 'A', 'K'),
  76. KC_WFWD, KEYCODE_NAME7('K', 'C', '_', 'W', 'F', 'W', 'D'),
  77. KC_WSTP, KEYCODE_NAME7('K', 'C', '_', 'W', 'S', 'T', 'P'),
  78. KC_WREF, KEYCODE_NAME7('K', 'C', '_', 'W', 'R', 'E', 'F'),
  79. KC_MNXT, KEYCODE_NAME7('K', 'C', '_', 'M', 'N', 'X', 'T'),
  80. KC_MPRV, KEYCODE_NAME7('K', 'C', '_', 'M', 'P', 'R', 'V'),
  81. KC_MPLY, KEYCODE_NAME7('K', 'C', '_', 'M', 'P', 'L', 'Y'),
  82. KC_MUTE, KEYCODE_NAME7('K', 'C', '_', 'M', 'U', 'T', 'E'),
  83. KC_VOLU, KEYCODE_NAME7('K', 'C', '_', 'V', 'O', 'L', 'U'),
  84. KC_VOLD, KEYCODE_NAME7('K', 'C', '_', 'V', 'O', 'L', 'D'),
  85. #endif // EXTRAKEY_ENABLE
  86. #ifdef MOUSEKEY_ENABLE
  87. MS_LEFT, KEYCODE_NAME7('M', 'S', '_', 'L', 'E', 'F', 'T'),
  88. MS_RGHT, KEYCODE_NAME7('M', 'S', '_', 'R', 'G', 'H', 'T'),
  89. MS_UP , KEYCODE_NAME7('M', 'S', '_', 'U', 'P', 0 , 0 ),
  90. MS_DOWN, KEYCODE_NAME7('M', 'S', '_', 'D', 'O', 'W', 'N'),
  91. MS_WHLL, KEYCODE_NAME7('M', 'S', '_', 'W', 'H', 'L', 'L'),
  92. MS_WHLR, KEYCODE_NAME7('M', 'S', '_', 'W', 'H', 'L', 'R'),
  93. MS_WHLU, KEYCODE_NAME7('M', 'S', '_', 'W', 'H', 'L', 'U'),
  94. MS_WHLD, KEYCODE_NAME7('M', 'S', '_', 'W', 'H', 'L', 'D'),
  95. #endif // MOUSEKEY_ENABLE
  96. #ifdef SWAP_HANDS_ENABLE
  97. SH_ON , KEYCODE_NAME7('S', 'H', '_', 'O', 'N', 0 , 0 ),
  98. SH_OFF , KEYCODE_NAME7('S', 'H', '_', 'O', 'F', 'F', 0 ),
  99. SH_MON , KEYCODE_NAME7('S', 'H', '_', 'M', 'O', 'N', 0 ),
  100. SH_MOFF, KEYCODE_NAME7('S', 'H', '_', 'M', 'O', 'F', 'F'),
  101. SH_TOGG, KEYCODE_NAME7('S', 'H', '_', 'T', 'O', 'G', 'G'),
  102. SH_TT , KEYCODE_NAME7('S', 'H', '_', 'T', 'T', 0 , 0 ),
  103. # if !defined(NO_ACTION_ONESHOT)
  104. SH_OS , KEYCODE_NAME7('S', 'H', '_', 'O', 'S', 0 , 0 ),
  105. # endif // !defined(NO_ACTION_ONESHOT)
  106. #endif // SWAP_HANDS_ENABLE
  107. #ifdef LEADER_ENABLE
  108. QK_LEAD, KEYCODE_NAME7('Q', 'K', '_', 'L', 'E', 'A', 'D'),
  109. #endif // LEADER_ENABLE
  110. #ifdef KEY_LOCK_ENABLE
  111. QK_LOCK, KEYCODE_NAME7('Q', 'K', '_', 'L', 'O', 'C', 'K'),
  112. #endif // KEY_LOCK_ENABLE
  113. #ifdef TRI_LAYER_ENABLE
  114. TL_LOWR, KEYCODE_NAME7('T', 'L', '_', 'L', 'O', 'W', 'R'),
  115. TL_UPPR, KEYCODE_NAME7('T', 'L', '_', 'U', 'P', 'P', 'R'),
  116. #endif // TRI_LAYER_ENABLE
  117. #ifdef GRAVE_ESC_ENABLE
  118. QK_GESC, KEYCODE_NAME7('Q', 'K', '_', 'G', 'E', 'S', 'C'),
  119. #endif // GRAVE_ESC_ENABLE
  120. #ifdef CAPS_WORD_ENABLE
  121. CW_TOGG, KEYCODE_NAME7('C', 'W', '_', 'T', 'O', 'G', 'G'),
  122. #endif // CAPS_WORD_ENABLE
  123. #ifdef SECURE_ENABLE
  124. SE_LOCK, KEYCODE_NAME7('S', 'E', '_', 'L', 'O', 'C', 'K'),
  125. SE_UNLK, KEYCODE_NAME7('S', 'E', '_', 'U', 'N', 'L', 'K'),
  126. SE_TOGG, KEYCODE_NAME7('S', 'E', '_', 'T', 'O', 'G', 'G'),
  127. SE_REQ , KEYCODE_NAME7('S', 'E', '_', 'R', 'E', 'Q', 0 ),
  128. #endif // SECURE_ENABLE
  129. #ifdef LAYER_LOCK_ENABLE
  130. QK_LLCK, KEYCODE_NAME7('Q', 'K', '_', 'L', 'L', 'C', 'K'),
  131. #endif // LAYER_LOCK_ENABLE
  132. EE_CLR , KEYCODE_NAME7('E', 'E', '_', 'C', 'L', 'R', 0 ),
  133. QK_BOOT, KEYCODE_NAME7('Q', 'K', '_', 'B', 'O', 'O', 'T'),
  134. DB_TOGG, KEYCODE_NAME7('D', 'B', '_', 'T', 'O', 'G', 'G'),
  135. };
  136. // clang-format on
  137. /** Users can override this to define names of additional keycodes. */
  138. __attribute__((weak)) const keycode_string_name_t* keycode_string_names_data_user = NULL;
  139. __attribute__((weak)) uint16_t keycode_string_names_size_user = 0;
  140. /** Keyboard vendors can override this to define names of additional keycodes. */
  141. __attribute__((weak)) const keycode_string_name_t* keycode_string_names_data_kb = NULL;
  142. __attribute__((weak)) uint16_t keycode_string_names_size_kb = 0;
  143. /** Names of the 4 mods on each hand. */
  144. static const char mod_names[] PROGMEM = "CTL\0SFT\0ALT\0GUI";
  145. /** Internal buffer for holding a stringified keycode. */
  146. static char buffer[32];
  147. #define BUFFER_MAX_LEN (sizeof(buffer) - 1)
  148. static index_t buffer_len;
  149. /** Finds the name of a keycode in `common_names` or returns NULL. */
  150. static const char* search_common_names(uint16_t keycode) {
  151. static uint8_t buffer[8];
  152. for (int_fast16_t offset = 0; offset < ARRAY_SIZE(common_names); offset += 4) {
  153. if (keycode == pgm_read_word(common_names + offset)) {
  154. const uint16_t w0 = pgm_read_word(common_names + offset + 1);
  155. const uint16_t w1 = pgm_read_word(common_names + offset + 2);
  156. const uint16_t w2 = pgm_read_word(common_names + offset + 3);
  157. buffer[0] = (uint8_t)w0;
  158. buffer[1] = (uint8_t)(w0 >> 8);
  159. buffer[2] = '_';
  160. buffer[3] = (uint8_t)w1;
  161. buffer[4] = (uint8_t)(w1 >> 8);
  162. buffer[5] = (uint8_t)w2;
  163. buffer[6] = (uint8_t)(w2 >> 8);
  164. buffer[7] = 0;
  165. return (const char*)buffer;
  166. }
  167. }
  168. return NULL;
  169. }
  170. /**
  171. * @brief Finds the name of a keycode in table or returns NULL.
  172. *
  173. * @param data Pointer to table to be searched.
  174. * @param size Numer of entries in the table.
  175. * @return Name string for the keycode, or NULL if not found.
  176. */
  177. static const char* search_table(const keycode_string_name_t* data, uint16_t size, uint16_t keycode) {
  178. if (data != NULL) {
  179. for (uint16_t i = 0; i < size; ++i) {
  180. if (data[i].keycode == keycode) {
  181. return data[i].name;
  182. }
  183. }
  184. }
  185. return NULL;
  186. }
  187. /** Formats `number` in `base`, either 10 or 16. */
  188. static char* number_string(uint16_t number, int8_t base) {
  189. static char result[7];
  190. result[sizeof(result) - 1] = '\0';
  191. index_t i = sizeof(result) - 1;
  192. do {
  193. const uint8_t digit = number % base;
  194. number /= base;
  195. result[--i] = (digit < 10) ? (char)(digit + UINT8_C('0')) : (char)(digit + (UINT8_C('A') - 10));
  196. } while (number > 0 && i > 0);
  197. if (base == 16 && i >= 2) {
  198. result[--i] = 'x';
  199. result[--i] = '0';
  200. }
  201. return result + i;
  202. }
  203. /** Appends `str` to `buffer`, truncating if the result would overflow. */
  204. static void append(const char* str) {
  205. char* dest = buffer + buffer_len;
  206. index_t i;
  207. for (i = 0; buffer_len + i < BUFFER_MAX_LEN && str[i]; ++i) {
  208. dest[i] = str[i];
  209. }
  210. buffer_len += i;
  211. buffer[buffer_len] = '\0';
  212. }
  213. /** Same as append(), but where `str` is a PROGMEM string. */
  214. static void append_P(const char* str) {
  215. char* dest = buffer + buffer_len;
  216. index_t i;
  217. for (i = 0; buffer_len + i < BUFFER_MAX_LEN; ++i) {
  218. const char c = pgm_read_byte(&str[i]);
  219. if (c == '\0') {
  220. break;
  221. }
  222. dest[i] = c;
  223. }
  224. buffer_len += i;
  225. buffer[buffer_len] = '\0';
  226. }
  227. /** Appends a single char to `buffer` if there is space. */
  228. static void append_char(char c) {
  229. if (buffer_len < BUFFER_MAX_LEN) {
  230. buffer[buffer_len] = c;
  231. buffer[++buffer_len] = '\0';
  232. }
  233. }
  234. /** Formats `number` in `base`, either 10 or 16, and appends it to `buffer`. */
  235. static void append_number(uint16_t number, int8_t base) {
  236. append(number_string(number, base));
  237. }
  238. /** Stringifies 5-bit mods and appends it to `buffer`. */
  239. static void append_5_bit_mods(uint8_t mods) {
  240. const bool is_rhs = mods > 15;
  241. const uint8_t csag = mods & 15;
  242. if (csag != 0 && (csag & (csag - 1)) == 0) { // One mod is set.
  243. append_P(PSTR("MOD_"));
  244. append_char(is_rhs ? 'R' : 'L');
  245. append_P(&mod_names[4 * biton(csag)]);
  246. } else { // Fallback: write the mod as a hex value.
  247. append_number(mods, 16);
  248. }
  249. }
  250. /**
  251. * @brief Writes a keycode of the format `name` + "(" + `param` + ")".
  252. * @note `name` is a PROGMEM string, `param` is not.
  253. */
  254. static void append_unary_keycode(const char* name, const char* param) {
  255. append_P(name);
  256. append_char('(');
  257. append(param);
  258. append_char(')');
  259. }
  260. /**
  261. * @brief Writes a keycode of the format `name` + `number`.
  262. * @note `name` is a PROGMEM string.
  263. */
  264. static void append_numbered_keycode(const char* name, uint16_t number) {
  265. append_P(name);
  266. append_number(number, 10);
  267. }
  268. /** Stringifies `keycode` and appends it to `buffer`. */
  269. static void append_keycode(uint16_t keycode) {
  270. // In case there is overlap among tables, search `keycode_string_names_user`
  271. // first so that it takes precedence.
  272. const char* keycode_name = search_table(keycode_string_names_data_user, keycode_string_names_size_user, keycode);
  273. if (keycode_name) {
  274. append(keycode_name);
  275. return;
  276. }
  277. keycode_name = search_table(keycode_string_names_data_kb, keycode_string_names_size_kb, keycode);
  278. if (keycode_name) {
  279. append(keycode_name);
  280. return;
  281. }
  282. keycode_name = search_common_names(keycode);
  283. if (keycode_name) {
  284. append(keycode_name);
  285. return;
  286. }
  287. if (keycode <= 255) { // Basic keycodes.
  288. switch (keycode) {
  289. // Modifiers KC_LSFT, KC_RCTL, etc.
  290. case MODIFIER_KEYCODE_RANGE: {
  291. const uint8_t i = keycode - KC_LCTL;
  292. const bool is_rhs = i > 3;
  293. append_P(PSTR("KC_"));
  294. append_char(is_rhs ? 'R' : 'L');
  295. append_P(&mod_names[4 * (i & 3)]);
  296. }
  297. return;
  298. // Letters A-Z.
  299. case KC_A ... KC_Z:
  300. append_P(PSTR("KC_"));
  301. append_char((char)(keycode + (UINT8_C('A') - KC_A)));
  302. return;
  303. // Digits 0-9 (NOTE: Unlike the ASCII order, KC_0 comes *after* KC_9.)
  304. case KC_1 ... KC_0:
  305. append_numbered_keycode(PSTR("KC_"), (keycode - (KC_1 - 1)) % 10);
  306. return;
  307. // Keypad digits.
  308. case KC_KP_1 ... KC_KP_0:
  309. append_numbered_keycode(PSTR("KC_KP_"), (keycode - (KC_KP_1 - 1)) % 10);
  310. return;
  311. // Function keys. F1-F12 and F13-F24 are coded in separate ranges.
  312. case KC_F1 ... KC_F12:
  313. append_numbered_keycode(PSTR("KC_F"), keycode - (KC_F1 - 1));
  314. return;
  315. case KC_F13 ... KC_F24:
  316. append_numbered_keycode(PSTR("KC_F"), keycode - (KC_F13 - 13));
  317. return;
  318. }
  319. }
  320. // clang-format off
  321. switch (keycode) {
  322. // A modified keycode, like S(KC_1) for Shift + 1 = !. This implementation
  323. // only covers modified keycodes where one modifier is applied, e.g. a
  324. // Ctrl + Shift + kc or Hyper + kc keycode is not formatted.
  325. case QK_MODS ... QK_MODS_MAX: {
  326. uint8_t mods = QK_MODS_GET_MODS(keycode);
  327. const bool is_rhs = mods > 15;
  328. mods &= 15;
  329. if (mods != 0 && (mods & (mods - 1)) == 0) { // One mod is set.
  330. const char* name = &mod_names[4 * biton(mods)];
  331. if (is_rhs) {
  332. append_char('R');
  333. append_P(name);
  334. } else {
  335. append_char(pgm_read_byte(&name[0]));
  336. }
  337. append_char('(');
  338. append_keycode(QK_MODS_GET_BASIC_KEYCODE(keycode));
  339. append_char(')');
  340. return;
  341. }
  342. } break;
  343. #if !defined(NO_ACTION_ONESHOT)
  344. case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX: // One-shot mod OSM(mod) key.
  345. append_P(PSTR("OSM("));
  346. append_5_bit_mods(QK_ONE_SHOT_MOD_GET_MODS(keycode));
  347. append_char(')');
  348. return;
  349. #endif // !defined(NO_ACTION_ONESHOT)
  350. // Various layer switch keys.
  351. case QK_LAYER_TAP ... QK_LAYER_TAP_MAX: // Layer-tap LT(layer,kc) key.
  352. append_P(PSTR("LT("));
  353. append_number(QK_LAYER_TAP_GET_LAYER(keycode), 10);
  354. append_char(',');
  355. append_keycode(QK_LAYER_TAP_GET_TAP_KEYCODE(keycode));
  356. append_char(')');
  357. return;
  358. case QK_LAYER_MOD ... QK_LAYER_MOD_MAX: // LM(layer,mod) key.
  359. append_P(PSTR("LM("));
  360. append_number(QK_LAYER_MOD_GET_LAYER(keycode), 10);
  361. append_char(',');
  362. append_5_bit_mods(QK_LAYER_MOD_GET_MODS(keycode));
  363. append_char(')');
  364. return;
  365. case QK_TO ... QK_TO_MAX: // TO(layer) key.
  366. append_unary_keycode(PSTR("TO"), number_string(QK_TO_GET_LAYER(keycode), 10));
  367. return;
  368. case QK_MOMENTARY ... QK_MOMENTARY_MAX: // MO(layer) key.
  369. append_unary_keycode(PSTR("MO"), number_string(QK_MOMENTARY_GET_LAYER(keycode), 10));
  370. return;
  371. case QK_DEF_LAYER ... QK_DEF_LAYER_MAX: // DF(layer) key.
  372. append_unary_keycode(PSTR("DF"), number_string(QK_DEF_LAYER_GET_LAYER(keycode), 10));
  373. return;
  374. case QK_TOGGLE_LAYER ... QK_TOGGLE_LAYER_MAX: // TG(layer) key.
  375. append_unary_keycode(PSTR("TG"), number_string(QK_TOGGLE_LAYER_GET_LAYER(keycode), 10));
  376. return;
  377. #if !defined(NO_ACTION_ONESHOT)
  378. case QK_ONE_SHOT_LAYER ... QK_ONE_SHOT_LAYER_MAX: // OSL(layer) key.
  379. append_unary_keycode(PSTR("OSL"), number_string(QK_ONE_SHOT_LAYER_GET_LAYER(keycode), 10));
  380. return;
  381. #endif // !defined(NO_ACTION_ONESHOT)
  382. case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX: // TT(layer) key.
  383. append_unary_keycode(PSTR("TT"), number_string(QK_LAYER_TAP_TOGGLE_GET_LAYER(keycode), 10));
  384. return;
  385. case QK_PERSISTENT_DEF_LAYER ... QK_PERSISTENT_DEF_LAYER_MAX: // PDF(layer) key.
  386. append_unary_keycode(PSTR("PDF"), number_string(QK_PERSISTENT_DEF_LAYER_GET_LAYER(keycode), 10));
  387. return;
  388. // Mod-tap MT(mod,kc) key. This implementation formats the MT keys where
  389. // one modifier is applied. For MT keys with multiple modifiers, the mod
  390. // arg is written numerically as a hex code.
  391. case QK_MOD_TAP ... QK_MOD_TAP_MAX: {
  392. uint8_t mods = QK_MOD_TAP_GET_MODS(keycode);
  393. const bool is_rhs = mods > 15;
  394. const uint8_t csag = mods & 15;
  395. if (csag != 0 && (csag & (csag - 1)) == 0) { // One mod is set.
  396. append_char(is_rhs ? 'R' : 'L');
  397. append_P(&mod_names[4 * biton(csag)]);
  398. append_P(PSTR("_T("));
  399. } else if (mods == MOD_HYPR) {
  400. append_P(PSTR("HYPR_T("));
  401. } else if (mods == MOD_MEH) {
  402. append_P(PSTR("MEH_T("));
  403. } else {
  404. append_P(PSTR("MT("));
  405. append_number(mods, 16);
  406. append_char(',');
  407. }
  408. append_keycode(QK_MOD_TAP_GET_TAP_KEYCODE(keycode));
  409. append_char(')');
  410. } return;
  411. case QK_TAP_DANCE ... QK_TAP_DANCE_MAX: // Tap dance TD(i) key.
  412. append_unary_keycode(PSTR("TD"), number_string(QK_TAP_DANCE_GET_INDEX(keycode), 10));
  413. return;
  414. #ifdef UNICODE_ENABLE
  415. case QK_UNICODE ... QK_UNICODE_MAX: // Unicode UC(codepoint) key.
  416. append_unary_keycode(PSTR("UC"), number_string(QK_UNICODE_GET_CODE_POINT(keycode), 16));
  417. return;
  418. #elif defined(UNICODEMAP_ENABLE)
  419. case QK_UNICODEMAP ... QK_UNICODEMAP_MAX: // Unicode Map UM(i) key.
  420. append_unary_keycode(PSTR("UM"), number_string(QK_UNICODEMAP_GET_INDEX(keycode), 10));
  421. return;
  422. case QK_UNICODEMAP_PAIR ... QK_UNICODEMAP_PAIR_MAX: { // UP(i,j) key.
  423. const uint8_t i = QK_UNICODEMAP_PAIR_GET_UNSHIFTED_INDEX(keycode);
  424. const uint8_t j = QK_UNICODEMAP_PAIR_GET_SHIFTED_INDEX(keycode);
  425. append_P(PSTR("UP("));
  426. append_number(i, 10);
  427. append_char(',');
  428. append_number(j, 10);
  429. append_char(')');
  430. } return;
  431. #endif
  432. #ifdef MOUSEKEY_ENABLE
  433. case MS_BTN1 ... MS_BTN8: // Mouse button keycode.
  434. append_numbered_keycode(PSTR("MS_BTN"), keycode - (MS_BTN1 - 1));
  435. return;
  436. #endif // MOUSEKEY_ENABLE
  437. #ifdef SWAP_HANDS_ENABLE
  438. case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX: // Swap Hands SH_T(kc) key.
  439. if (!IS_SWAP_HANDS_KEYCODE(keycode)) {
  440. append_P(PSTR("SH_T("));
  441. append_keycode(QK_SWAP_HANDS_GET_TAP_KEYCODE(keycode));
  442. append_char(')');
  443. return;
  444. }
  445. break;
  446. #endif // SWAP_HANDS_ENABLE
  447. #ifdef JOYSTICK_ENABLE
  448. case JOYSTICK_KEYCODE_RANGE: // Joystick JS_ key.
  449. append_numbered_keycode(PSTR("JS_"), keycode - JS_0);
  450. return;
  451. #endif // JOYSTICK_ENABLE
  452. #ifdef PROGRAMMABLE_BUTTON_ENABLE
  453. case PROGRAMMABLE_BUTTON_KEYCODE_RANGE: // Programmable button PB_ key.
  454. append_numbered_keycode(PSTR("PB_"), keycode - (PB_1 - 1));
  455. return;
  456. #endif // PROGRAMMABLE_BUTTON_ENABLE
  457. case MACRO_KEYCODE_RANGE: // Macro range MC_ keycode.
  458. append_numbered_keycode(PSTR("MC_"), keycode - MC_0);
  459. return;
  460. case KB_KEYCODE_RANGE: // Keyboard range keycode.
  461. append_numbered_keycode(PSTR("QK_KB_"), keycode - QK_KB_0);
  462. return;
  463. case USER_KEYCODE_RANGE: // User range keycode.
  464. append_numbered_keycode(PSTR("QK_USER_"), keycode - QK_USER_0);
  465. return;
  466. // It would take a nontrivial amount of string data to cover some
  467. // feature-specific keycodes, such as those for MIDI and lighting. As a
  468. // fallback while still providing some information, we stringify
  469. // remaining keys in known code ranges as "QK_<feature>+<number>".
  470. #ifdef MAGIC_ENABLE
  471. case MAGIC_KEYCODE_RANGE:
  472. append_numbered_keycode(PSTR("QK_MAGIC+"), keycode - QK_MAGIC);
  473. return;
  474. #endif // MAGIC_ENABLE
  475. #ifdef MIDI_ENABLE
  476. case MIDI_KEYCODE_RANGE:
  477. append_numbered_keycode(PSTR("QK_MIDI+"), keycode - QK_MIDI);
  478. return;
  479. #endif // MIDI_ENABLE
  480. #ifdef SEQUENCER_ENABLE
  481. case SEQUENCER_KEYCODE_RANGE:
  482. append_numbered_keycode(PSTR("QK_SEQUENCER+"), keycode - QK_SEQUENCER);
  483. return;
  484. #endif // SEQUENCER_ENABLE
  485. #ifdef AUDIO_ENABLE
  486. case AUDIO_KEYCODE_RANGE:
  487. append_numbered_keycode(PSTR("QK_AUDIO+"), keycode - QK_AUDIO);
  488. return;
  489. #endif // AUDIO_ENABLE
  490. #if defined(BACKLIGHT_ENABLE) || defined(LED_MATRIX_ENABLE) || defined(RGBLIGHT_ENABLED) || defined(RGB_MATRIX_ENABLE) // Lighting-related features.
  491. case QK_LIGHTING ... QK_LIGHTING_MAX:
  492. append_numbered_keycode(PSTR("QK_LIGHTING+"), keycode - QK_LIGHTING);
  493. return;
  494. #endif // defined(BACKLIGHT_ENABLE) || defined(LED_MATRIX_ENABLE) || defined(RGBLIGHT_ENABLED) || defined(RGB_MATRIX_ENABLE)
  495. #ifdef STENO_ENABLE
  496. case STENO_KEYCODE_RANGE:
  497. append_numbered_keycode(PSTR("QK_STENO+"), keycode - QK_STENO);
  498. return;
  499. #endif // AUDIO_ENABLE
  500. #ifdef BLUETOOTH_ENABLE
  501. case CONNECTION_KEYCODE_RANGE:
  502. append_numbered_keycode(PSTR("QK_CONNECTION+"), keycode - QK_CONNECTION);
  503. return;
  504. #endif // BLUETOOTH_ENABLE
  505. case QUANTUM_KEYCODE_RANGE:
  506. append_numbered_keycode(PSTR("QK_QUANTUM+"), keycode - QK_QUANTUM);
  507. return;
  508. }
  509. // clang-format on
  510. append_number(keycode, 16); // Fallback: write keycode as hex value.
  511. }
  512. const char* get_keycode_string(uint16_t keycode) {
  513. buffer_len = 0;
  514. buffer[0] = '\0';
  515. append_keycode(keycode);
  516. return buffer;
  517. }