diff --git a/src/keys.c b/src/keys.c index 1c2d54a1..472db903 100644 --- a/src/keys.c +++ b/src/keys.c @@ -499,5 +499,6 @@ void (*keydriver_setLowercaseEnabled)(bool enabled) = NULL; void (*keydriver_keyboardReadCallback)(void) = NULL; void (*keydriver_beginCalibration)(void) = NULL; void (*keydriver_endCalibration)(void) = NULL; +void (*keydriver_loadAltKbd)(const char *kbdPath) = NULL; #endif diff --git a/src/keys.h b/src/keys.h index 2bf0c5e2..e5907fb1 100644 --- a/src/keys.h +++ b/src/keys.h @@ -175,6 +175,9 @@ extern void (*keydriver_beginCalibration)(void); // end calibration mode extern void (*keydriver_endCalibration)(void); + +// load an alternate keyboard variant +extern void (*keydriver_loadAltKbd)(const char *kbdPath); #endif #endif diff --git a/src/video/gltouchkbd.c b/src/video/gltouchkbd.c index 32eb7313..17788b70 100644 --- a/src/video/gltouchkbd.c +++ b/src/video/gltouchkbd.c @@ -13,6 +13,7 @@ #include "video/glvideo.h" #include "video/glhudmodel.h" #include "video/glnode.h" +#include "json_parse.h" #if !INTERFACE_TOUCH #error this is a touch interface module, possibly you mean to not compile this at all? @@ -760,6 +761,150 @@ static void gltouchkbd_endCalibration(void) { isCalibrating = false; } +static void gltouchkbd_loadAltKbd(const char *kbdPath) { + JSON_s parsedData = { 0 }; + int tokCount = json_createFromFile(kbdPath, &parsedData); + + do { + if (tokCount < 0) { + break; + } + + // we are expecting a very specific layout ... abort if anything is not correct + int idx=0; + + // begin with array + if (parsedData.jsonTokens[idx].type != JSMN_ARRAY) { + ERRLOG("Keyboard JSON must start with array"); + break; + } + ++idx; + + // next is a global comment string + if (parsedData.jsonTokens[idx].type != JSMN_STRING) { + ERRLOG("Expecting a comment string at JSON token position 1"); + break; + } + ++idx; + + // next is the dictionary of special strings + if (parsedData.jsonTokens[idx].type != JSMN_OBJECT) { + ERRLOG("Expecting a dictionary at JSON token position 2"); + break; + } + const int dictCount = parsedData.jsonTokens[idx].size; + ++idx; + const int dictBegin = idx; + + // verify all dictionary keys/vals are strings + bool allStrings = true; + const int dictEnd = dictBegin + (dictCount*2); + for (; idx= start && "bug"); + const int size = end - start; + + if (size == 1) { + kbdTemplateArrow[row][col] = parsedData.jsonString[start]; + continue; + } else if (size == 0) { + kbdTemplateArrow[row][col] = ICONTEXT_NONACTIONABLE; + continue; + } else if (size < 0) { + assert(false && "negative size coming from jsmn!"); + continue; + } + + // assign special interface/mousetext visuals + char *key = &parsedData.jsonString[start]; + + bool foundMatch = false; + for (int i=dictBegin; i= start && "bug"); + + if (end - start != size) { + continue; + } + + foundMatch = (strncmp(key, &parsedData.jsonString[start], size) == 0); + + if (foundMatch) { + start = parsedData.jsonTokens[i+1].start; + uint8_t ch = (uint8_t)strtol(&parsedData.jsonString[start], NULL, /*base:*/16); + kbdTemplateArrow[row][col] = ch; + break; + } + } + if (!foundMatch) { + ERRLOG("no match for found multichar value in keyboard row %d", row+1); + } + } + + ++row; + } + + if (row != KBD_TEMPLATE_ROWS) { + ERRLOG("Did not find expected number of keyboard rows"); + } else { + LOG("Parsed keyboard at %s", kbdPath); + } + + } while (0); + + json_destroy(&parsedData); +} + static void _animation_showTouchKeyboard(void) { if (!isAvailable) { return; @@ -792,6 +937,7 @@ static void _init_gltouchkbd(void) { keydriver_setLowercaseEnabled = &gltouchkbd_setLowercaseEnabled; keydriver_beginCalibration = &gltouchkbd_beginCalibration; keydriver_endCalibration = &gltouchkbd_endCalibration; + keydriver_loadAltKbd = &gltouchkbd_loadAltKbd; kbd.selectedCol = -1; kbd.selectedRow = -1;