Unicode, Unicodemap and UCIS refactor (#21659)
This commit is contained in:
parent
95681b8ff4
commit
70e34e491c
34 changed files with 1196 additions and 386 deletions
96
quantum/unicode/ucis.c
Normal file
96
quantum/unicode/ucis.c
Normal file
|
@ -0,0 +1,96 @@
|
|||
// Copyright 2023 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "ucis.h"
|
||||
#include "unicode.h"
|
||||
#include "action.h"
|
||||
|
||||
uint8_t count = 0;
|
||||
bool active = false;
|
||||
char input[UCIS_MAX_INPUT_LENGTH] = {0};
|
||||
|
||||
void ucis_start(void) {
|
||||
count = 0;
|
||||
active = true;
|
||||
|
||||
register_unicode(0x2328); // ⌨
|
||||
}
|
||||
|
||||
bool ucis_active(void) {
|
||||
return active;
|
||||
}
|
||||
|
||||
uint8_t ucis_count(void) {
|
||||
return count;
|
||||
}
|
||||
|
||||
static char keycode_to_char(uint16_t keycode) {
|
||||
if (keycode >= KC_A && keycode <= KC_Z) {
|
||||
return 'a' + (keycode - KC_A);
|
||||
} else if (keycode >= KC_1 && keycode <= KC_9) {
|
||||
return '1' + (keycode - KC_1);
|
||||
} else if (keycode == KC_0) {
|
||||
return '0';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ucis_add(uint16_t keycode) {
|
||||
char c = keycode_to_char(keycode);
|
||||
if (c) {
|
||||
input[count++] = c;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ucis_remove_last(void) {
|
||||
if (count) {
|
||||
count--;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool match_mnemonic(char *mnemonic) {
|
||||
for (uint8_t i = 0; input[i]; i++) {
|
||||
if (i > count || input[i] != mnemonic[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ucis_finish(void) {
|
||||
uint8_t i = 0;
|
||||
bool found = false;
|
||||
for (; ucis_symbol_table[i].mnemonic; i++) {
|
||||
if (match_mnemonic(ucis_symbol_table[i].mnemonic)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
for (uint8_t j = 0; j <= count; j++) {
|
||||
tap_code(KC_BACKSPACE);
|
||||
}
|
||||
register_ucis(i);
|
||||
}
|
||||
|
||||
active = false;
|
||||
}
|
||||
|
||||
void ucis_cancel(void) {
|
||||
count = 0;
|
||||
active = false;
|
||||
}
|
||||
|
||||
void register_ucis(uint8_t index) {
|
||||
const uint32_t *code_points = ucis_symbol_table[index].code_points;
|
||||
|
||||
for (int i = 0; i < UCIS_MAX_CODE_POINTS && code_points[i]; i++) {
|
||||
register_unicode(code_points[i]);
|
||||
}
|
||||
}
|
97
quantum/unicode/ucis.h
Normal file
97
quantum/unicode/ucis.h
Normal file
|
@ -0,0 +1,97 @@
|
|||
// Copyright 2023 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \defgroup ucis UCIS
|
||||
* \{
|
||||
*/
|
||||
|
||||
#ifndef UCIS_MAX_INPUT_LENGTH
|
||||
# define UCIS_MAX_INPUT_LENGTH 32
|
||||
#endif
|
||||
|
||||
#ifndef UCIS_MAX_CODE_POINTS
|
||||
# define UCIS_MAX_CODE_POINTS 3
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
char* mnemonic;
|
||||
uint32_t code_points[UCIS_MAX_CODE_POINTS];
|
||||
} ucis_symbol_t;
|
||||
|
||||
// clang-format off
|
||||
|
||||
#define UCIS_TABLE(...) { \
|
||||
__VA_ARGS__, \
|
||||
{ NULL, {} } \
|
||||
}
|
||||
|
||||
#define UCIS_SYM(name, ...) { \
|
||||
.mnemonic = name, \
|
||||
.code_points = {__VA_ARGS__} \
|
||||
}
|
||||
|
||||
// clang-format on
|
||||
|
||||
extern const ucis_symbol_t ucis_symbol_table[];
|
||||
|
||||
/**
|
||||
* \brief Begin the input sequence.
|
||||
*/
|
||||
void ucis_start(void);
|
||||
|
||||
/**
|
||||
* \brief Whether UCIS is currently active.
|
||||
*
|
||||
* \return `true` if UCIS is active.
|
||||
*/
|
||||
bool ucis_active(void);
|
||||
|
||||
/**
|
||||
* \brief Get the number of characters in the input sequence buffer.
|
||||
*
|
||||
* \return The current input sequence buffer length.
|
||||
*/
|
||||
uint8_t ucis_count(void);
|
||||
|
||||
/**
|
||||
* \brief Add the given keycode to the input sequence buffer.
|
||||
*
|
||||
* \param keycode The keycode to add. Must be between `KC_A` and `KC_Z`, or `KC_1` and `KC_0`.
|
||||
*
|
||||
* \return `true` if the keycode was added.
|
||||
*/
|
||||
bool ucis_add(uint16_t keycode);
|
||||
|
||||
/**
|
||||
* \brief Remove the last character from the input sequence.
|
||||
*
|
||||
* \return `true` if the sequence was not empty.
|
||||
*/
|
||||
bool ucis_remove_last(void);
|
||||
|
||||
/**
|
||||
* Mark the input sequence as complete, and attempt to match.
|
||||
*/
|
||||
void ucis_finish(void);
|
||||
|
||||
/**
|
||||
* \brief Cancel the input sequence.
|
||||
*/
|
||||
void ucis_cancel(void);
|
||||
|
||||
/**
|
||||
* Send the code point(s) for the given UCIS index.
|
||||
*
|
||||
* \param index The index into the UCIS symbol table.
|
||||
*/
|
||||
void register_ucis(uint8_t index);
|
||||
|
||||
/** \} */
|
|
@ -73,16 +73,8 @@ static int8_t selected_count = ARRAY_SIZE(selected);
|
|||
static int8_t selected_index;
|
||||
#endif
|
||||
|
||||
/** \brief unicode input mode set at user level
|
||||
*
|
||||
* Run user code on unicode input mode change
|
||||
*/
|
||||
__attribute__((weak)) void unicode_input_mode_set_user(uint8_t input_mode) {}
|
||||
|
||||
/** \brief unicode input mode set at keyboard level
|
||||
*
|
||||
* Run keyboard code on unicode input mode change
|
||||
*/
|
||||
__attribute__((weak)) void unicode_input_mode_set_kb(uint8_t input_mode) {
|
||||
unicode_input_mode_set_user(input_mode);
|
||||
}
|
||||
|
@ -172,6 +164,10 @@ uint8_t get_unicode_input_mode(void) {
|
|||
return unicode_config.input_mode;
|
||||
}
|
||||
|
||||
static void persist_unicode_input_mode(void) {
|
||||
eeprom_update_byte(EECONFIG_UNICODEMODE, unicode_config.input_mode);
|
||||
}
|
||||
|
||||
void set_unicode_input_mode(uint8_t mode) {
|
||||
unicode_config.input_mode = mode;
|
||||
persist_unicode_input_mode();
|
||||
|
@ -182,26 +178,34 @@ void set_unicode_input_mode(uint8_t mode) {
|
|||
dprintf("Unicode input mode set to: %u\n", unicode_config.input_mode);
|
||||
}
|
||||
|
||||
void cycle_unicode_input_mode(int8_t offset) {
|
||||
static void cycle_unicode_input_mode(int8_t offset) {
|
||||
#if UNICODE_SELECTED_MODES != -1
|
||||
selected_index = (selected_index + offset) % selected_count;
|
||||
if (selected_index < 0) {
|
||||
selected_index += selected_count;
|
||||
}
|
||||
|
||||
unicode_config.input_mode = selected[selected_index];
|
||||
|
||||
# if UNICODE_CYCLE_PERSIST
|
||||
persist_unicode_input_mode();
|
||||
# endif
|
||||
|
||||
# ifdef AUDIO_ENABLE
|
||||
unicode_play_song(unicode_config.input_mode);
|
||||
# endif
|
||||
|
||||
unicode_input_mode_set_kb(unicode_config.input_mode);
|
||||
dprintf("Unicode input mode cycle to: %u\n", unicode_config.input_mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
void persist_unicode_input_mode(void) {
|
||||
eeprom_update_byte(EECONFIG_UNICODEMODE, unicode_config.input_mode);
|
||||
void unicode_input_mode_step(void) {
|
||||
cycle_unicode_input_mode(1);
|
||||
}
|
||||
|
||||
void unicode_input_mode_step_reverse(void) {
|
||||
cycle_unicode_input_mode(-1);
|
||||
}
|
||||
|
||||
__attribute__((weak)) void unicode_input_start(void) {
|
||||
|
|
|
@ -19,6 +19,13 @@
|
|||
#include <stdint.h>
|
||||
#include "unicode_keycodes.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \defgroup unicode Unicode
|
||||
* \{
|
||||
*/
|
||||
|
||||
typedef union {
|
||||
uint8_t raw;
|
||||
struct {
|
||||
|
@ -41,21 +48,87 @@ enum unicode_input_modes {
|
|||
UNICODE_MODE_COUNT // Number of available input modes (always leave at the end)
|
||||
};
|
||||
|
||||
void unicode_input_mode_init(void);
|
||||
uint8_t get_unicode_input_mode(void);
|
||||
void set_unicode_input_mode(uint8_t mode);
|
||||
void cycle_unicode_input_mode(int8_t offset);
|
||||
void persist_unicode_input_mode(void);
|
||||
void unicode_input_mode_init(void);
|
||||
|
||||
/**
|
||||
* \brief Get the current Unicode input mode.
|
||||
*
|
||||
* \return The currently active Unicode input mode.
|
||||
*/
|
||||
uint8_t get_unicode_input_mode(void);
|
||||
|
||||
/**
|
||||
* \brief Set the Unicode input mode.
|
||||
*
|
||||
* \param mode The input mode to set.
|
||||
*/
|
||||
void set_unicode_input_mode(uint8_t mode);
|
||||
|
||||
/**
|
||||
* \brief Change to the next Unicode input mode.
|
||||
*/
|
||||
void unicode_input_mode_step(void);
|
||||
|
||||
/**
|
||||
* \brief Change to the previous Unicode input mode.
|
||||
*/
|
||||
void unicode_input_mode_step_reverse(void);
|
||||
|
||||
/**
|
||||
* \brief User-level callback, invoked when the input mode is changed.
|
||||
*
|
||||
* \param input_mode The new input mode.
|
||||
*/
|
||||
void unicode_input_mode_set_user(uint8_t input_mode);
|
||||
|
||||
/**
|
||||
* \brief Keyboard-level callback, invoked when the input mode is changed.
|
||||
*
|
||||
* \param input_mode The new input mode.
|
||||
*/
|
||||
void unicode_input_mode_set_kb(uint8_t input_mode);
|
||||
|
||||
/**
|
||||
* \brief Begin the Unicode input sequence. The exact behavior depends on the currently selected input mode.
|
||||
*/
|
||||
void unicode_input_start(void);
|
||||
|
||||
/**
|
||||
* \brief Complete the Unicode input sequence. The exact behavior depends on the currently selected input mode.
|
||||
*/
|
||||
void unicode_input_finish(void);
|
||||
|
||||
/**
|
||||
* \brief Cancel the Unicode input sequence. The exact behavior depends on the currently selected input mode.
|
||||
*/
|
||||
void unicode_input_cancel(void);
|
||||
|
||||
/**
|
||||
* \brief Send a 16-bit hex number.
|
||||
*
|
||||
* \param hex The number to send.
|
||||
*/
|
||||
void register_hex(uint16_t hex);
|
||||
|
||||
/**
|
||||
* \brief Send a 32-bit hex number.
|
||||
*
|
||||
* \param hex The number to send.
|
||||
*/
|
||||
void register_hex32(uint32_t hex);
|
||||
|
||||
/**
|
||||
* \brief Input a single Unicode character. A surrogate pair will be sent if required by the input mode.
|
||||
*
|
||||
* \param code_point The code point of the character to send.
|
||||
*/
|
||||
void register_unicode(uint32_t code_point);
|
||||
|
||||
/**
|
||||
* \brief Send a string containing Unicode characters.
|
||||
*
|
||||
* \param str The string to send.
|
||||
*/
|
||||
void send_unicode_string(const char *str);
|
||||
|
||||
/** \} */
|
||||
|
|
43
quantum/unicode/unicodemap.c
Normal file
43
quantum/unicode/unicodemap.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
// Copyright 2023 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "unicodemap.h"
|
||||
#include "unicode.h"
|
||||
#include "keycodes.h"
|
||||
#include "quantum_keycodes.h"
|
||||
#include "modifiers.h"
|
||||
#include "host.h"
|
||||
#include "action_util.h"
|
||||
|
||||
uint8_t unicodemap_index(uint16_t keycode) {
|
||||
if (keycode >= QK_UNICODEMAP_PAIR) {
|
||||
// Keycode is a pair: extract index based on Shift / Caps Lock state
|
||||
uint16_t index;
|
||||
|
||||
uint8_t mods = get_mods() | get_weak_mods();
|
||||
#ifndef NO_ACTION_ONESHOT
|
||||
mods |= get_oneshot_mods();
|
||||
#endif
|
||||
|
||||
bool shift = mods & MOD_MASK_SHIFT;
|
||||
bool caps = host_keyboard_led_state().caps_lock;
|
||||
if (shift ^ caps) {
|
||||
index = QK_UNICODEMAP_PAIR_GET_SHIFTED_INDEX(keycode);
|
||||
} else {
|
||||
index = QK_UNICODEMAP_PAIR_GET_UNSHIFTED_INDEX(keycode);
|
||||
}
|
||||
|
||||
return index;
|
||||
} else {
|
||||
// Keycode is a regular index
|
||||
return QK_UNICODEMAP_GET_INDEX(keycode);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t unicodemap_get_code_point(uint8_t index) {
|
||||
return pgm_read_dword(unicode_map + index);
|
||||
}
|
||||
|
||||
void register_unicodemap(uint8_t index) {
|
||||
register_unicode(unicodemap_get_code_point(index));
|
||||
}
|
43
quantum/unicode/unicodemap.h
Normal file
43
quantum/unicode/unicodemap.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
// Copyright 2023 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "progmem.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \defgroup unicodemap Unicode Map
|
||||
* \{
|
||||
*/
|
||||
|
||||
extern const uint32_t unicode_map[] PROGMEM;
|
||||
|
||||
/**
|
||||
* \brief Get the index into the `unicode_map` array for the given keycode, respecting shift state for pair keycodes.
|
||||
*
|
||||
* \param keycode The Unicode Map keycode to get the index of.
|
||||
*
|
||||
* \return An index into the `unicode_map` array.
|
||||
*/
|
||||
uint8_t unicodemap_index(uint16_t keycode);
|
||||
|
||||
/**
|
||||
* \brief Get the code point for the given index in the `unicode_map` array.
|
||||
*
|
||||
* \param index The index into the `unicode_map` array.
|
||||
*
|
||||
* \return A Unicode code point value.
|
||||
*/
|
||||
uint32_t unicodemap_get_code_point(uint8_t index);
|
||||
|
||||
/**
|
||||
* \brief Send the code point for the given index in the `unicode_map` array.
|
||||
*
|
||||
* \param index The index into the `unicode_map` array.
|
||||
*/
|
||||
void register_unicodemap(uint8_t index);
|
||||
|
||||
/** \} */
|
Loading…
Add table
Add a link
Reference in a new issue