fix compose bug
This commit is contained in:
parent
c22f25a597
commit
d7aeb6cc5d
11 changed files with 36291 additions and 36244 deletions
|
@ -11,7 +11,7 @@
|
||||||
#define MATRIX_COLS 6
|
#define MATRIX_COLS 6
|
||||||
#define DEBUG_MATRIX_SCAN_RATE
|
#define DEBUG_MATRIX_SCAN_RATE
|
||||||
|
|
||||||
#define UNICODE_SELECTED_MODES UC_LNX, UC_MAC, UC_WINC
|
#define UNICODE_SELECTED_MODES UNICODE_MODE_LINUX, UNICODE_MODE_MACOS, UNICODE_MODE_WINCOMPOSE, UNICODE_MODE_EMACS
|
||||||
|
|
||||||
#define OLED_DISPLAY_128X64
|
#define OLED_DISPLAY_128X64
|
||||||
|
|
||||||
|
|
|
@ -10,118 +10,115 @@
|
||||||
static int charsWritten, currentState;
|
static int charsWritten, currentState;
|
||||||
|
|
||||||
static void resetState(void) {
|
static void resetState(void) {
|
||||||
print("resetState()\n");
|
print("resetState()\n");
|
||||||
charsWritten = 0;
|
charsWritten = 0;
|
||||||
currentState = 0;
|
currentState = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void finishCompose(const char* result) {
|
static void finishCompose(const char *result) {
|
||||||
uprintf("Finishing compose with result: %s (%d chars written)\n", result, charsWritten);
|
uprintf("Finishing compose with result: %s (%d chars written)\n", result, charsWritten);
|
||||||
while(charsWritten) {
|
while (charsWritten) {
|
||||||
tap_code(KC_BACKSPACE);
|
tap_code(KC_BACKSPACE);
|
||||||
charsWritten--;
|
charsWritten--;
|
||||||
}
|
}
|
||||||
send_unicode_string(result);
|
send_unicode_string(result);
|
||||||
resetState();
|
resetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t first_edge_idx;
|
uint16_t first_edge_idx;
|
||||||
uint16_t edge_count;
|
uint16_t edge_count;
|
||||||
} compose_node_t;
|
} compose_node_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char * value;
|
const char *value;
|
||||||
uint16_t c;
|
uint16_t c;
|
||||||
uint16_t next_node;
|
uint16_t next_node;
|
||||||
} compose_edge_t;
|
} compose_edge_t;
|
||||||
|
|
||||||
#include "composeTable.h"
|
#include "composeTable.h"
|
||||||
|
|
||||||
static void checkComposeState(void) {
|
static void checkComposeState(void) {
|
||||||
print("checkComposeState()\n");
|
print("checkComposeState()\n");
|
||||||
if(currentState * sizeof(compose_node_t) > sizeof(nodes)) {
|
if (currentState * sizeof(compose_node_t) > sizeof(nodes)) {
|
||||||
finishCompose("[error in compose]");
|
finishCompose("[error in compose]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const compose_edge_t *findEdge(uint16_t keycode) {
|
static const compose_edge_t *findEdge(uint16_t keycode) {
|
||||||
checkComposeState();
|
checkComposeState();
|
||||||
uint32_t uc = keystroke_to_unicode(keycode);
|
uint32_t uc = keystroke_to_unicode(keycode);
|
||||||
uprintf("Resolved keycode %d: %ld\n", keycode, uc);
|
uprintf("Resolved keycode %d: %ld\n", keycode, uc);
|
||||||
|
|
||||||
uint16_t match1 = (uint16_t)uc; // yes only bmp support, keyboard doesn’t have any astral keycodes anyways
|
uint16_t match1 = (uint16_t)uc; // yes only bmp support, keyboard doesn’t have any astral keycodes anyways
|
||||||
uint16_t match2 = 0;
|
uint16_t match2 = 0;
|
||||||
if(keycode < 256) {
|
if (keycode < 256) {
|
||||||
match2 = 0xD800 + keycode;
|
match2 = 0xD800 + keycode;
|
||||||
print("(low keycode)\n");
|
print("(low keycode)\n");
|
||||||
} else if(keycode == KC_LEAD) {
|
} else if (keycode == QK_LEAD) {
|
||||||
match2 = 0xD800;
|
match2 = 0xD800;
|
||||||
print("(leader key)\n");
|
print("(leader key)\n");
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = nodes[currentState].first_edge_idx; i < nodes[currentState].first_edge_idx + nodes[currentState].edge_count; i++) {
|
|
||||||
if(compose_edges[i].c == match1 || compose_edges[i].c == match2) {
|
|
||||||
uprintf("found matching node: %d -> %d\n", currentState, i);
|
|
||||||
return &compose_edges[i];
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
print("no matching edge found.\n");
|
for (int i = nodes[currentState].first_edge_idx; i < nodes[currentState].first_edge_idx + nodes[currentState].edge_count; i++) {
|
||||||
return NULL;
|
if (compose_edges[i].c == match1 || compose_edges[i].c == match2) {
|
||||||
|
uprintf("found matching node: %d -> %d\n", currentState, i);
|
||||||
|
return &compose_edges[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print("no matching edge found.\n");
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// yes this breaks with emoji
|
// yes this breaks with emoji
|
||||||
static size_t charcount_utf8(const char * s) {
|
static size_t charcount_utf8(const char *s) {
|
||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
while(*s)
|
while (*s)
|
||||||
if((*(s++) & 0xC0) != 0x80)
|
if ((*(s++) & 0xC0) != 0x80) n++; // only count non-continuation characters
|
||||||
n++; // only count non-continuation characters
|
return n;
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void transEdge(const compose_edge_t *edge) {
|
static void transEdge(const compose_edge_t *edge) {
|
||||||
uprintf("Transitioning to node %d\n", edge->next_node);
|
uprintf("Transitioning to node %d\n", edge->next_node);
|
||||||
if(edge->value) {
|
if (edge->value) {
|
||||||
uprintf("new node has value %s\n", edge->value);
|
uprintf("new node has value %s\n", edge->value);
|
||||||
finishCompose(edge->value);
|
finishCompose(edge->value);
|
||||||
if(edge->next_node != 0) // not necessarily the final product
|
if (edge->next_node != 0) // not necessarily the final product
|
||||||
charsWritten = charcount_utf8(edge->value);
|
charsWritten = charcount_utf8(edge->value);
|
||||||
}
|
}
|
||||||
currentState = edge->next_node;
|
currentState = edge->next_node;
|
||||||
checkComposeState();
|
checkComposeState();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isCombining(uint32_t uc) {
|
static bool isCombining(uint32_t uc) {
|
||||||
// yes it is not all of them, but all of them that matter for us
|
// yes it is not all of them, but all of them that matter for us
|
||||||
if(uc >= 0x300 && uc < 0x370)
|
if (uc >= 0x300 && uc < 0x370) return true;
|
||||||
return true;
|
if (uc == 0x20d7) return true;
|
||||||
if(uc == 0x20d7)
|
return false;
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void process_compose(uint16_t keycode, keyrecord_t *record) {
|
void process_compose(uint16_t keycode, keyrecord_t *record) {
|
||||||
if(!record->event.pressed)
|
if (!record->event.pressed) return;
|
||||||
return;
|
uint32_t uc = keystroke_to_unicode(keycode);
|
||||||
uint32_t uc = keystroke_to_unicode(keycode);
|
const compose_edge_t *edge = findEdge(keycode);
|
||||||
const compose_edge_t * edge = findEdge(keycode);
|
if (edge == NULL && uc != 0) { // no matching edge found, reset and try again
|
||||||
if(edge == NULL && uc != 0) { // no matching edge found, reset and try again
|
uprintf("uc: %ld", uc);
|
||||||
print("No matching edge found, reset.\n");
|
print("No matching edge found, reset.\n");
|
||||||
resetState();
|
resetState();
|
||||||
edge = findEdge(keycode);
|
edge = findEdge(keycode);
|
||||||
}
|
}
|
||||||
if(edge == NULL) {
|
if (edge == NULL) {
|
||||||
print("No compose edge found.\n");
|
print("No compose edge found.\n");
|
||||||
return; // nothing found
|
return; // nothing found
|
||||||
}
|
}
|
||||||
// before we can advance the compose state, we need to prepare certain keys (dead keys, the leader key) because otherwise our deletion will delete too much (which of course is something we do not want)
|
// before we can advance the compose state, we need to prepare certain keys (dead keys, the leader key) because otherwise our deletion will delete too much (which of course is something we do not want)
|
||||||
if(isCombining(uc)) {
|
if (isCombining(uc)) {
|
||||||
print("keycode refers to deadkey, writing space\n");
|
print("keycode refers to deadkey, writing space\n");
|
||||||
tap_code(KC_SPACE);
|
tap_code(KC_SPACE);
|
||||||
} else if(keycode == KC_LEAD) {
|
} else if (keycode == QK_LEAD) {
|
||||||
print("keycode refers to leader key, writing compose symbol\n");
|
print("keycode refers to leader key, writing compose symbol\n");
|
||||||
send_unicode_string("♫");
|
send_unicode_string("♫");
|
||||||
}
|
}
|
||||||
charsWritten++;
|
charsWritten++;
|
||||||
transEdge(edge);
|
transEdge(edge);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,4 +2,4 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "action.h"
|
#include "action.h"
|
||||||
void process_compose(uint16_t keycode, keyrecord_t *record);
|
void process_compose(uint16_t keycode, keyrecord_t *record);
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -5,17 +5,7 @@
|
||||||
#include "raw_hid.h"
|
#include "raw_hid.h"
|
||||||
#include "neo2.h"
|
#include "neo2.h"
|
||||||
#include "compose.h"
|
#include "compose.h"
|
||||||
enum {
|
enum { _MAIN, _NUMPAD, _PLOVER, _MOUSE, _GAMING, _SYS, _NAV, _FN, _EMPTY };
|
||||||
_MAIN,
|
|
||||||
_NUMPAD,
|
|
||||||
_PLOVER,
|
|
||||||
_MOUSE,
|
|
||||||
_GAMING,
|
|
||||||
_SYS,
|
|
||||||
_NAV,
|
|
||||||
_FN,
|
|
||||||
_EMPTY
|
|
||||||
};
|
|
||||||
|
|
||||||
#define LAYOUT(k0A, k0B, k0C, k0D, k0E, k0F, k5A, k5B, k5C, k5D, k5E, k5F, k1A, k1B, k1C, k1D, k1E, k1F, k6A, k6B, k6C, k6D, k6E, k6F, k2A, k2B, k2C, k2D, k2E, k2F, k7A, k7B, k7C, k7D, k7E, k7F, k3A, k3B, k3C, k3D, k3E, k3F, k8A, k8B, k8C, k8D, k8E, k8F, k4C, k4D, k4E, k4F, k9C, k9D, k9E, k9F) LAYOUT_ortho_4x6_2x2uc(k0A, k0B, k0C, k0D, k0E, k0F, k1A, k1B, k1C, k1D, k1E, k1F, k2A, k2B, k2C, k2D, k2E, k2F, k3A, k3B, k3C, k3D, k3E, k3F, k4C, k4D, k4E, k4F, k5A, k5B, k5C, k5D, k5E, k5F, k6A, k6B, k6C, k6D, k6E, k6F, k7A, k7B, k7C, k7D, k7E, k7F, k8A, k8B, k8C, k8D, k8E, k8F, k9C, k9D, k9E, k9F)
|
#define LAYOUT(k0A, k0B, k0C, k0D, k0E, k0F, k5A, k5B, k5C, k5D, k5E, k5F, k1A, k1B, k1C, k1D, k1E, k1F, k6A, k6B, k6C, k6D, k6E, k6F, k2A, k2B, k2C, k2D, k2E, k2F, k7A, k7B, k7C, k7D, k7E, k7F, k3A, k3B, k3C, k3D, k3E, k3F, k8A, k8B, k8C, k8D, k8E, k8F, k4C, k4D, k4E, k4F, k9C, k9D, k9E, k9F) LAYOUT_ortho_4x6_2x2uc(k0A, k0B, k0C, k0D, k0E, k0F, k1A, k1B, k1C, k1D, k1E, k1F, k2A, k2B, k2C, k2D, k2E, k2F, k3A, k3B, k3C, k3D, k3E, k3F, k4C, k4D, k4E, k4F, k5A, k5B, k5C, k5D, k5E, k5F, k6A, k6B, k6C, k6D, k6E, k6F, k7A, k7B, k7C, k7D, k7E, k7F, k8A, k8B, k8C, k8D, k8E, k8F, k9C, k9D, k9E, k9F)
|
||||||
#define STN_PLS STN_NB
|
#define STN_PLS STN_NB
|
||||||
|
@ -27,8 +17,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||||
[_MAIN] = LAYOUT(
|
[_MAIN] = LAYOUT(
|
||||||
KC_ESC , KC_Q , KC_W , KC_E , KC_R , KC_T , KC_Y , KC_U , KC_I , KC_O , KC_P , KC_LBRC,
|
KC_ESC , KC_Q , KC_W , KC_E , KC_R , KC_T , KC_Y , KC_U , KC_I , KC_O , KC_P , KC_LBRC,
|
||||||
KC_TAB , KC_A , KC_S , KC_D , KC_F , KC_G , KC_H , KC_J , KC_K , KC_L , KC_SCLN , KC_QUOT,
|
KC_TAB , KC_A , KC_S , KC_D , KC_F , KC_G , KC_H , KC_J , KC_K , KC_L , KC_SCLN , KC_QUOT,
|
||||||
KC_LSFT, KC_Z , KC_X , KC_C , KC_V , KC_B , KC_N , KC_M , KC_COMM , KC_DOT , KC_SLSH , KC_LEAD,
|
KC_LSFT, KC_Z , KC_X , KC_C , KC_V , KC_B , KC_N , KC_M , KC_COMM , KC_DOT , KC_SLSH , QK_LEAD,
|
||||||
KC_LCTL, KC_LGUI, KC_LALT, KC_NUBS , TT(_FN), _______, KC_LOCK, TG(_PLOVER), KC_RALT , KC_RGUI, KC_APP , KC_RCTL,
|
KC_LCTL, KC_LGUI, KC_LALT, KC_NUBS , TT(_FN), _______, QK_LOCK, TG(_PLOVER), KC_RALT , KC_RGUI, KC_APP , KC_RCTL,
|
||||||
KC_CAPS, TT(_GAMING), KC_SPC , KC_LSFT, TT(_MOUSE), TT(_NUMPAD), TT(_NAV), TT(_SYS)
|
KC_CAPS, TT(_GAMING), KC_SPC , KC_LSFT, TT(_MOUSE), TT(_NUMPAD), TT(_NAV), TT(_SYS)
|
||||||
),
|
),
|
||||||
[_NUMPAD] = LAYOUT(
|
[_NUMPAD] = LAYOUT(
|
||||||
|
@ -166,7 +156,7 @@ void register_unicode(uint32_t codepoint) {
|
||||||
buffer[1] = 0x80 | (uint8_t)(codepoint & 0x3F);
|
buffer[1] = 0x80 | (uint8_t)(codepoint & 0x3F);
|
||||||
codepoint >>= 6;
|
codepoint >>= 6;
|
||||||
buffer[0] = 0xC0 | (uint8_t)(codepoint);
|
buffer[0] = 0xC0 | (uint8_t)(codepoint);
|
||||||
size = 2;
|
size = 2;
|
||||||
} else if(codepoint < 0x10000) {
|
} else if(codepoint < 0x10000) {
|
||||||
buffer[2] = 0x80 | (uint8_t)(codepoint & 0x3F);
|
buffer[2] = 0x80 | (uint8_t)(codepoint & 0x3F);
|
||||||
codepoint >>= 6;
|
codepoint >>= 6;
|
||||||
|
|
|
@ -247,4 +247,4 @@ for edge in edges:
|
||||||
if "next_node" in edge:
|
if "next_node" in edge:
|
||||||
print(f" .next_node = {edge['next_node']},")
|
print(f" .next_node = {edge['next_node']},")
|
||||||
print(" },")
|
print(" },")
|
||||||
print("};")
|
print("};")
|
||||||
|
|
|
@ -57,7 +57,7 @@ bool caps_word_press_user(uint16_t keycode) {
|
||||||
// Keycodes that continue Caps Word, with shift applied.
|
// Keycodes that continue Caps Word, with shift applied.
|
||||||
case KC_A ... KC_Z:
|
case KC_A ... KC_Z:
|
||||||
case KC_MINS:
|
case KC_MINS:
|
||||||
add_weak_mods(MOD_BIT(KC_LSFT)); // Apply shift to next key.
|
add_weak_mods(MOD_BIT(KC_LSFT)); // Apply shift to next key.
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Keycodes that continue Caps Word, without shifting.
|
// Keycodes that continue Caps Word, without shifting.
|
||||||
|
@ -74,6 +74,6 @@ bool caps_word_press_user(uint16_t keycode) {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return getLayer() != 3; // Deactivate Caps Word.
|
return getLayer() != 3; // Deactivate Caps Word.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,5 +3,5 @@
|
||||||
#include "quantum/action.h"
|
#include "quantum/action.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
void track_neo2_modifier_state(uint16_t keycode, keyrecord_t *record);
|
void track_neo2_modifier_state(uint16_t keycode, keyrecord_t *record);
|
||||||
uint32_t keystroke_to_unicode(uint16_t keycode);
|
uint32_t keystroke_to_unicode(uint16_t keycode);
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
SRC += neo2.c compose.c
|
SRC += neo2.c compose.c
|
||||||
|
|
|
@ -79,4 +79,4 @@ struct SparseTable<T, 0, entryBits> {
|
||||||
const T *operator[](size_t index) const {
|
const T *operator[](size_t index) const {
|
||||||
return &value;
|
return &value;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue