From 0250b6729e79404780b79613d41c97e303972211 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 23 May 2023 14:52:28 +0200 Subject: [PATCH 01/16] feature(linux): mcompile setup framework for mcompile: read US keyboard, get keysms and push to vector --- linux/mcompile/keymap/README.md | 4 + linux/mcompile/keymap/keymap.h | 12 +++ linux/mcompile/keymap/main.cpp | 148 ++++++++++++++++++++++++++++++ linux/mcompile/keymap/meson.build | 11 +++ 4 files changed, 175 insertions(+) create mode 100644 linux/mcompile/keymap/README.md create mode 100644 linux/mcompile/keymap/keymap.h create mode 100644 linux/mcompile/keymap/main.cpp create mode 100644 linux/mcompile/keymap/meson.build diff --git a/linux/mcompile/keymap/README.md b/linux/mcompile/keymap/README.md new file mode 100644 index 00000000000..4891de51529 --- /dev/null +++ b/linux/mcompile/keymap/README.md @@ -0,0 +1,4 @@ +# Keymap + +Sample program that loops over the key codes 10-61 and outputs the key +values for groups 0 and 1. diff --git a/linux/mcompile/keymap/keymap.h b/linux/mcompile/keymap/keymap.h new file mode 100644 index 00000000000..7beb5186ae0 --- /dev/null +++ b/linux/mcompile/keymap/keymap.h @@ -0,0 +1,12 @@ + +#include + +#include +#include +#include +#include + +static void PrintKeymapForCode(GdkKeymap *keymap, guint keycode); +std::vector > > write_US_ToVector(std::string language, const char* text) ; +std::vector CreateCompleteRow_US(FILE* fpp, const char* text, std::string language) ; +void extract_difference(std::vector > > US_vector, std::string lang_Other ) ; diff --git a/linux/mcompile/keymap/main.cpp b/linux/mcompile/keymap/main.cpp new file mode 100644 index 00000000000..b48cd273397 --- /dev/null +++ b/linux/mcompile/keymap/main.cpp @@ -0,0 +1,148 @@ +#include "keymap.h" + +static void PrintKeymapForCode(GdkKeymap *keymap, guint keycode) +{ + GdkKeymapKey *maps; + guint *keyvals; + gint count; + + if (!gdk_keymap_get_entries_for_keycode(keymap, keycode, &maps, &keyvals, &count)) + return; + + for (int i = 0; i < count; i++) { + if (maps[i].level > 0 || maps[i].group > 1) + continue; + printf(" i=%d, keycode=%d, keyval=%d (%c), level=%d, group=%d\n", i, maps[i].keycode, keyvals[i], keyvals[i], maps[i].level, maps[i].group); + } + + g_free(keyvals); + g_free(maps); +} + +std::vector > > write_US_ToVector(std::string language, const char* text) { + printf("+++++++ start to open_file \n"); + std::vector > > Vector_split; + std::string FullPathName = "/usr/share/X11/xkb/symbols/" + language; + const char* cc = FullPathName.c_str(); + FILE* fp = fopen((cc), "r"); + if ( !fp) + printf("could not open file!"); + else + printf("+++++++ file open OK \n"); + std::vector Vector_complete = CreateCompleteRow_US(fp, text, language); // creates vector of all . TTODO lookup other language files + + fclose(fp); + return Vector_split; +} + +std::vector CreateCompleteRow_US(FILE* fpp, const char* text, std::string language) { + printf("+++++++ start CreateCompleteRow_US\n"); + std::vector complete_List; + int buffer_size = 512; + char buffer[buffer_size]; + bool print_OK = false; + const char* key = "key <"; + std::string str_txt(text); + std::string xbk_mark = "xkb_symbol"; + std::ofstream KeyboardFile("File_" + language + ".txt"); + + printf("Keyboard %s\n", text); + KeyboardFile << "Keyboard" << text << "\n"; + + if (fpp) { + while (fgets(buffer, buffer_size, fpp) != NULL) { + std::string str_buf(buffer); + + // TODO: recursive search for other included Configuration files + // if find "include" -> recursive... + + // stop when finding the mark xkb_symbol + if (std::string(str_buf).find(xbk_mark) != std::string::npos) + print_OK = false; + + // start when finding the mark xkb_symbol + correct layout + if ((std::string(str_buf).find(str_txt) != std::string::npos)) + print_OK = true; + + if ((print_OK) && (std::string(str_buf).find(key) != std::string::npos)) { + printf("... %s", buffer); + complete_List.push_back(buffer); + KeyboardFile << buffer; + } + } + } + printf("end Keyboard %s..........................................\n\n", text); + return complete_List; +} + +void extract_difference(std::vector > > US_vector, std::string lang_Other ) +{ + printf("+++++++ start extract_difference\n"); + /* + std::ofstream Map_File("Map_" + lang_US + "_To_" + lang_Other + ".txt"); + std::string diff; + std::cout <<"key"<< std::setw(26)<< "Char US"<< std::setw(20)<<"Char other" << std::setw(10)<< "diff? \n"; + Map_File <<"key"<< std::setw(26)<< "Char US"<< std::setw(20)<<"Char other" << std::setw(10)<< "diff? \n"; + std::cout <<"---------------------------------------------------------------\n"; + Map_File <<"---------------------------------------------------------------\n"; + + //ToDo for all columns; watchout for empty fields!! + for ( int i =0; i< US_vector.size();i++) + { + for ( int j =0; j< other_vector.size();j++) + { + diff =" \t"; + if( US_vector[i][0] == other_vector[j][0] ) + { + if( US_vector[i][1] != other_vector[j][1] ) diff = " *** "; + std::cout << US_vector[i][0] << std::setw(20)<< US_vector[i][1] << std::setw(20)<< other_vector[j][1] < > > All_Vector = write_US_ToVector(US_language, text_us); + extract_difference(All_Vector,other_language); + +//------------------------------------------ + + + + + gdk_display_close(display); + + return 0; +} diff --git a/linux/mcompile/keymap/meson.build b/linux/mcompile/keymap/meson.build new file mode 100644 index 00000000000..7f41bc2f709 --- /dev/null +++ b/linux/mcompile/keymap/meson.build @@ -0,0 +1,11 @@ +project('keymap', 'c', 'cpp', + license: 'MIT', + meson_version: '>=1.0') + +gtk = dependency('gtk+-3.0', version: '>= 2.4') + +keymap = executable( + 'keymap', + sources: ['main.cpp'], + dependencies: [gtk] +) From 9e609dead0aa95e659b02fbae5e8010d471162c1 Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 23 May 2023 18:28:45 +0200 Subject: [PATCH 02/16] feature(linux): mcompile replace main.cpp with keymap.cpp --- linux/mcompile/keymap/{main.cpp => Xmain.cpp} | 0 linux/mcompile/keymap/keymap.cpp | 236 ++++++++++++++++++ linux/mcompile/keymap/keymap.h | 14 +- linux/mcompile/keymap/meson.build | 2 +- 4 files changed, 248 insertions(+), 4 deletions(-) rename linux/mcompile/keymap/{main.cpp => Xmain.cpp} (100%) create mode 100644 linux/mcompile/keymap/keymap.cpp diff --git a/linux/mcompile/keymap/main.cpp b/linux/mcompile/keymap/Xmain.cpp similarity index 100% rename from linux/mcompile/keymap/main.cpp rename to linux/mcompile/keymap/Xmain.cpp diff --git a/linux/mcompile/keymap/keymap.cpp b/linux/mcompile/keymap/keymap.cpp new file mode 100644 index 00000000000..069fad7fffd --- /dev/null +++ b/linux/mcompile/keymap/keymap.cpp @@ -0,0 +1,236 @@ +#include "keymap.h" + +static void PrintKeymapForCode(GdkKeymap *keymap, guint keycode) +{ + GdkKeymapKey *maps; + guint *keyvals; + gint count; + + if (!gdk_keymap_get_entries_for_keycode(keymap, keycode, &maps, &keyvals, &count)) + return; + + for (int i = 0; i < count; i++) { + if (maps[i].level > 1 || maps[i].group > 4) + continue; + printf(" i=%d, keycode=%d, keyval=%d (%c), level=%d, group=%d\n", i, maps[i].keycode, keyvals[i], keyvals[i], maps[i].level, maps[i].group); + } + + + g_free(keyvals); + g_free(maps); +} + +v_str_3D write_US_ToVector(std::string language, const char* text) { + + printf("+++++++ start to open_file \n"); + v_str_3D Vector_split; + std::string FullPathName = "/usr/share/X11/xkb/symbols/" + language; + + const char* cc = FullPathName.c_str(); + FILE* fp = fopen((cc), "r"); + if ( !fp) + printf("could not open file!"); + else + printf("+++++++ file open OK \n"); + + v_str_1D Vector_completeUS = CreateCompleteRow_US(fp, text, language); // creates vector of all . TTODO lookup other language files + + //here split Vector to 3D vector + Vector_split = SplitTo_3D_Vector( Vector_completeUS); + + printf("+++++++ sizes write_US_ToVector %li..%li..%li\n", Vector_split.size(), Vector_split[0].size(),Vector_split[0][0].size()); + fclose(fp); + return Vector_split; +} + +bool test(v_str_3D V){ + printf("+++++++ stest"); +std::cout << V[0][0][0]<< "..\n" + << V[0][0][1]<< "..\n" + << V[0][0][2]<< "..\n" + << V[0][0][3]<< "..\n" + << V[0][0][4]<< "..\n\n" + + << V[0][1][0]<< "..\n" + << V[0][1][1]<< "..\n" + << V[0][1][2]<< "..\n" + << V[0][1][3]<< "..\n" + << V[0][1][4]<< "..\n\n" + + << V[0][22][0]<< "..\n" + << V[0][22][1]<< "..\n" + << V[0][22][2]<< "..\n" + << V[0][22][3]<< "..\n" + << V[0][22][4]<< "..\n\n" + + << V[0][45][0]<< "..\n" + << V[0][45][1]<< "..\n" + << V[0][45][2]<< "..\n" + << V[0][45][3]<< "..\n" + << V[0][45][4]<< "..\n\n" + + << V[0][46][0]<< "..\n" + << V[0][46][1]<< "..\n" + << V[0][46][2]<< "..\n" + << V[0][46][3]<< "..\n" + << V[0][46][4]<< "..\n\n" + + << V[0][0][0]<< "..\n"; + return true; +} + +v_str_1D CreateCompleteRow_US(FILE* fpp, const char* text, std::string language) { + printf("+++++++ start CreateCompleteRow_US\n"); + v_str_1D complete_List; + int buffer_size = 512; + char buffer[buffer_size]; + bool print_OK = false; + const char* key = "key <"; + std::string str_txt(text); + std::string xbk_mark = "xkb_symbol"; + std::ofstream KeyboardFile("File_" + language + ".txt"); + + printf("Keyboard %s\n", text); + KeyboardFile << "Keyboard" << text << "\n"; + + if (fpp) { + while (fgets(buffer, buffer_size, fpp) != NULL) { + std::string str_buf(buffer); + + // Maybe TODO: recursive search for other included Configuration files + // if find "include" -> recursive... + + // stop when finding the mark xkb_symbol + if (std::string(str_buf).find(xbk_mark) != std::string::npos) + print_OK = false; + + // start when finding the mark xkb_symbol + correct layout + if ((std::string(str_buf).find(str_txt) != std::string::npos)) + print_OK = true; + + if ((print_OK) && (std::string(str_buf).find(key) != std::string::npos)) { + printf("... %s", buffer); + complete_List.push_back(buffer); + KeyboardFile << buffer; + } + } + } + printf("end Keyboard %s..........................................\n\n", text); + return complete_List; +} + +void extract_difference(v_str_3D, std::string lang_Other ) +{ + printf("+++++++ start extract_difference\n"); + /* + std::ofstream Map_File("Map_" + lang_US + "_To_" + lang_Other + ".txt"); + std::string diff; + std::cout <<"key"<< std::setw(26)<< "Char US"<< std::setw(20)<<"Char other" << std::setw(10)<< "diff? \n"; + Map_File <<"key"<< std::setw(26)<< "Char US"<< std::setw(20)<<"Char other" << std::setw(10)<< "diff? \n"; + std::cout <<"---------------------------------------------------------------\n"; + Map_File <<"---------------------------------------------------------------\n"; + + //ToDo for all columns; watchout for empty fields!! + for ( int i =0; i< US_vector.size();i++) + { + for ( int j =0; j< other_vector.size();j++) + { + diff =" \t"; + if( US_vector[i][0] == other_vector[j][0] ) + { + if( US_vector[i][1] != other_vector[j][1] ) diff = " *** "; + std::cout << US_vector[i][0] << std::setw(20)<< US_vector[i][1] << std::setw(20)<< other_vector[j][1] < delim{' ', '[', ']', '}', ';', '\t', '\n'}; + printf("+++++++ start SplitTo_3D_Vector\n"); + char split_bracel = '{'; + char split_char_komma = ','; + std::vector tokens; + std::vector > everything; + v_str_3D all; + + // while starts with key... + for (int k = 0; k < (int)p_completeList.size() - 1; k++) { + + // remove alll unwanted char + for (int i = 0; i < (int) delim.size(); i++) + p_completeList[k].erase(remove(p_completeList[k].begin(), p_completeList[k].end(), delim[i]), p_completeList[k].end()); + + // inly lines with ("key<.. are of interest + if (p_completeList[k].find("key<") != std::string::npos) { + // seperate key<... + std::istringstream split1(p_completeList[k]); + for (std::string each; std::getline(split1, each, split_bracel); tokens.push_back(each)); + + // seperate rest with comma and push to everything + std::istringstream split(tokens[1]); + tokens.pop_back(); + for (std::string each; std::getline(split, each, split_char_komma); tokens.push_back(each)); + everything.push_back(tokens); + tokens.clear(); + } + } + //return everything; + all.push_back(everything); + //printf("+++++++ ssizes %i..%i..%i\n", all.size(), all[0].size ,all[0][0].size); + printf("+++++++ sizes SplitTo_3D_Vector %li..%li..%li\n", all.size(), all[0].size(),all[0][0].size()); + return all; +} + +//-------------------------------------- +int main(gint argc, gchar **argv) +{ + gdk_init(&argc, &argv); + GdkDisplay *display = gdk_display_get_default(); + if (!display) { + printf("ERROR: can't get display\n"); + return 1; + } + GdkKeymap *keymap = gdk_keymap_get_for_display(display); + if (!keymap) { + printf("ERROR: Can't get keymap\n"); + gdk_display_close(display); + return 2; + } + + for (int keycode = 10; keycode <= 61; keycode++) { + printf("-------------------\n"); + printf("Keycode %d:\n", keycode); + PrintKeymapForCode(keymap, keycode); + } +//------------------------------------------ +//GdkKeymap* kmp; +//kmp = gdk_get_default(); + + + std::string US_language = "us"; + const char* text_us = "xkb_symbols \"intl\""; + + std::string other_language = "--"; + // ToDo get other/current language from XKB + // e.g. other_language = 2; +printf("-°°°°°°°° write_US_ToVector\n"); + v_str_3D All_Vector = write_US_ToVector(US_language, text_us); + +printf("-°°°°°°°° test\n"); + //bool ok = test(All_Vector); + +printf("-°°°°°°°° extract_difference\n"); + extract_difference(All_Vector,other_language); + +//------------------------------------------ + + + + + gdk_display_close(display); + + return 0; +} diff --git a/linux/mcompile/keymap/keymap.h b/linux/mcompile/keymap/keymap.h index 7beb5186ae0..67469ef26a2 100644 --- a/linux/mcompile/keymap/keymap.h +++ b/linux/mcompile/keymap/keymap.h @@ -5,8 +5,16 @@ #include #include #include +#include +#include + +typedef std::vector v_str_1D; +typedef std::vector > v_str_2D; +typedef std::vector > > v_str_3D; static void PrintKeymapForCode(GdkKeymap *keymap, guint keycode); -std::vector > > write_US_ToVector(std::string language, const char* text) ; -std::vector CreateCompleteRow_US(FILE* fpp, const char* text, std::string language) ; -void extract_difference(std::vector > > US_vector, std::string lang_Other ) ; + +v_str_3D write_US_ToVector(std::string language, const char* text) ; +v_str_1D CreateCompleteRow_US(FILE* fpp, const char* text, std::string language) ; +void extract_difference(v_str_3D US_vector, std::string lang_Other ) ; +v_str_3D SplitTo_3D_Vector(v_str_1D completeListUS); diff --git a/linux/mcompile/keymap/meson.build b/linux/mcompile/keymap/meson.build index 7f41bc2f709..eb1e03783b7 100644 --- a/linux/mcompile/keymap/meson.build +++ b/linux/mcompile/keymap/meson.build @@ -6,6 +6,6 @@ gtk = dependency('gtk+-3.0', version: '>= 2.4') keymap = executable( 'keymap', - sources: ['main.cpp'], + sources: ['keymap.cpp'], dependencies: [gtk] ) From fedbfbf7be35d7beb6ec9acad5944a188964737c Mon Sep 17 00:00:00 2001 From: Sabine Date: Tue, 23 May 2023 14:52:28 +0200 Subject: [PATCH 03/16] feature(linux): mcompile copy keymap-test --- linux/mcompile/keymap/main.cpp | 47 ++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 linux/mcompile/keymap/main.cpp diff --git a/linux/mcompile/keymap/main.cpp b/linux/mcompile/keymap/main.cpp new file mode 100644 index 00000000000..2fa3409d871 --- /dev/null +++ b/linux/mcompile/keymap/main.cpp @@ -0,0 +1,47 @@ +#include + + +static void PrintKeymapForCode(GdkKeymap *keymap, guint keycode) +{ + GdkKeymapKey *maps; + guint *keyvals; + gint count; + + if (!gdk_keymap_get_entries_for_keycode(keymap, keycode, &maps, &keyvals, &count)) + return; + + for (int i = 0; i < count; i++) { + if (maps[i].level > 0 || maps[i].group > 1) + continue; + printf(" i=%d, keycode=%d, keyval=%d (%c), level=%d, group=%d\n", i, maps[i].keycode, keyvals[i], keyvals[i], maps[i].level, maps[i].group); + } + + g_free(keyvals); + g_free(maps); +} + +int main(gint argc, gchar **argv) +{ + gdk_init(&argc, &argv); + GdkDisplay *display = gdk_display_get_default(); + if (!display) { + printf("ERROR: can't get display\n"); + return 1; + } + GdkKeymap *keymap = gdk_keymap_get_for_display(display); + if (!keymap) { + printf("ERROR: Can't get keymap\n"); + gdk_display_close(display); + return 2; + } + + for (int keycode = 10; keycode <= 61; keycode++) { + printf("-------------------\n"); + printf("Keycode %d:\n", keycode); + PrintKeymapForCode(keymap, keycode); + } + + gdk_display_close(display); + + return 0; +} From 441ab3890395e40433f2c15f4a5b08970f2e6f75 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 31 May 2023 09:49:20 +0200 Subject: [PATCH 04/16] feature(Linux): mcompile changes in keymap -> read/write --- linux/mcompile/keymap/keymap.cpp | 450 ++++++++++++++++++++----------- linux/mcompile/keymap/keymap.h | 55 +++- 2 files changed, 342 insertions(+), 163 deletions(-) diff --git a/linux/mcompile/keymap/keymap.cpp b/linux/mcompile/keymap/keymap.cpp index 069fad7fffd..0295e41e0e6 100644 --- a/linux/mcompile/keymap/keymap.cpp +++ b/linux/mcompile/keymap/keymap.cpp @@ -1,5 +1,6 @@ #include "keymap.h" + static void PrintKeymapForCode(GdkKeymap *keymap, guint keycode) { GdkKeymapKey *maps; @@ -10,182 +11,326 @@ static void PrintKeymapForCode(GdkKeymap *keymap, guint keycode) return; for (int i = 0; i < count; i++) { - if (maps[i].level > 1 || maps[i].group > 4) + if (maps[i].level > 0 || maps[i].group > 1) continue; printf(" i=%d, keycode=%d, keyval=%d (%c), level=%d, group=%d\n", i, maps[i].keycode, keyvals[i], keyvals[i], maps[i].level, maps[i].group); } - g_free(keyvals); g_free(maps); } -v_str_3D write_US_ToVector(std::string language, const char* text) { - - printf("+++++++ start to open_file \n"); - v_str_3D Vector_split; +void write_US_ToVector( v_str_3D &vec,std::string language, const char* text) { std::string FullPathName = "/usr/share/X11/xkb/symbols/" + language; const char* cc = FullPathName.c_str(); FILE* fp = fopen((cc), "r"); if ( !fp) printf("could not open file!"); - else - printf("+++++++ file open OK \n"); - v_str_1D Vector_completeUS = CreateCompleteRow_US(fp, text, language); // creates vector of all . TTODO lookup other language files + // create 1D-vector of the complete line + v_str_1D Vector_completeUS; + CreateCompleteRow_US(Vector_completeUS,fp, text, language); - //here split Vector to 3D vector - Vector_split = SplitTo_3D_Vector( Vector_completeUS); + // split contents of 1D Vector to 3D vector + Split_US_To_3D_Vector( vec,Vector_completeUS); - printf("+++++++ sizes write_US_ToVector %li..%li..%li\n", Vector_split.size(), Vector_split[0].size(),Vector_split[0][0].size()); + printf("+++++++ dimensions of Vector after write_US_ToVector\t\t %li..%li..%li\n", vec.size(), vec[0].size(),vec[0][0].size()); fclose(fp); - return Vector_split; -} - -bool test(v_str_3D V){ - printf("+++++++ stest"); -std::cout << V[0][0][0]<< "..\n" - << V[0][0][1]<< "..\n" - << V[0][0][2]<< "..\n" - << V[0][0][3]<< "..\n" - << V[0][0][4]<< "..\n\n" - - << V[0][1][0]<< "..\n" - << V[0][1][1]<< "..\n" - << V[0][1][2]<< "..\n" - << V[0][1][3]<< "..\n" - << V[0][1][4]<< "..\n\n" - - << V[0][22][0]<< "..\n" - << V[0][22][1]<< "..\n" - << V[0][22][2]<< "..\n" - << V[0][22][3]<< "..\n" - << V[0][22][4]<< "..\n\n" - - << V[0][45][0]<< "..\n" - << V[0][45][1]<< "..\n" - << V[0][45][2]<< "..\n" - << V[0][45][3]<< "..\n" - << V[0][45][4]<< "..\n\n" - - << V[0][46][0]<< "..\n" - << V[0][46][1]<< "..\n" - << V[0][46][2]<< "..\n" - << V[0][46][3]<< "..\n" - << V[0][46][4]<< "..\n\n" - - << V[0][0][0]<< "..\n"; - return true; } -v_str_1D CreateCompleteRow_US(FILE* fpp, const char* text, std::string language) { - printf("+++++++ start CreateCompleteRow_US\n"); - v_str_1D complete_List; - int buffer_size = 512; - char buffer[buffer_size]; - bool print_OK = false; - const char* key = "key <"; - std::string str_txt(text); - std::string xbk_mark = "xkb_symbol"; - std::ofstream KeyboardFile("File_" + language + ".txt"); - - printf("Keyboard %s\n", text); - KeyboardFile << "Keyboard" << text << "\n"; - - if (fpp) { - while (fgets(buffer, buffer_size, fpp) != NULL) { - std::string str_buf(buffer); - - // Maybe TODO: recursive search for other included Configuration files - // if find "include" -> recursive... - - // stop when finding the mark xkb_symbol - if (std::string(str_buf).find(xbk_mark) != std::string::npos) - print_OK = false; - - // start when finding the mark xkb_symbol + correct layout - if ((std::string(str_buf).find(str_txt) != std::string::npos)) - print_OK = true; - - if ((print_OK) && (std::string(str_buf).find(key) != std::string::npos)) { - printf("... %s", buffer); - complete_List.push_back(buffer); - KeyboardFile << buffer; - } +void CreateCompleteRow_US(v_str_1D &complete_List, FILE* fpp, const char* text, std::string language) { + // in the Configuration file we find the appopriate paragraph between "xkb_symbol " and the next xkb_symbol + // and then copy all rows starting with "key <" to a v1D-Vector + + int buffer_size = 512; + char buffer[buffer_size]; + bool print_OK = false; + const char* key = "key <"; + std::string str_txt(text); + std::string xbk_mark = "xkb_symbol"; + std::ofstream KeyboardFile("File_" + language + ".txt"); + + printf("Keyboard %s\n", text); + KeyboardFile << "Keyboard" << text << "\n"; + + if (fpp) { + while (fgets(buffer, buffer_size, fpp) != NULL) { + std::string str_buf(buffer); + + // stop when finding the mark xkb_symbol + if (std::string(str_buf).find(xbk_mark) != std::string::npos) + print_OK = false; + + // start when finding the mark xkb_symbol + correct layout + if ((std::string(str_buf).find(str_txt) != std::string::npos)) + print_OK = true; + + // as long as we are in the same xkb_symbol layout and find "key <" we push the whole line into a 1D-vector + if ((print_OK) && (std::string(str_buf).find(key) != std::string::npos)) { + printf("%s", buffer); + complete_List.push_back(buffer); + KeyboardFile << buffer; } } - printf("end Keyboard %s..........................................\n\n", text); - return complete_List; + } + printf("-°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° \n"); } -void extract_difference(v_str_3D, std::string lang_Other ) -{ - printf("+++++++ start extract_difference\n"); - /* - std::ofstream Map_File("Map_" + lang_US + "_To_" + lang_Other + ".txt"); - std::string diff; - std::cout <<"key"<< std::setw(26)<< "Char US"<< std::setw(20)<<"Char other" << std::setw(10)<< "diff? \n"; - Map_File <<"key"<< std::setw(26)<< "Char US"<< std::setw(20)<<"Char other" << std::setw(10)<< "diff? \n"; - std::cout <<"---------------------------------------------------------------\n"; - Map_File <<"---------------------------------------------------------------\n"; - - //ToDo for all columns; watchout for empty fields!! - for ( int i =0; i< US_vector.size();i++) - { - for ( int j =0; j< other_vector.size();j++) - { - diff =" \t"; - if( US_vector[i][0] == other_vector[j][0] ) - { - if( US_vector[i][1] != other_vector[j][1] ) diff = " *** "; - std::cout << US_vector[i][0] << std::setw(20)<< US_vector[i][1] << std::setw(20)<< other_vector[j][1] < and the shiftstates + // third: push Names/Shiftstates to shift_states and then shiftstates to All_US, our 3D-Vector holding all Elements -v_str_3D SplitTo_3D_Vector(v_str_1D p_completeList) {std::vector delim{' ', '[', ']', '}', ';', '\t', '\n'}; - printf("+++++++ start SplitTo_3D_Vector\n"); + std::vector delim{' ', '[', ']', '}', ';', '\t', '\n'}; char split_bracel = '{'; char split_char_komma = ','; - std::vector tokens; - std::vector > everything; - v_str_3D all; + std::string empty = "--"; + v_str_1D tokens; + v_str_2D shift_states; + + // go through the whole vector + for (int k = 0; k < (int)completeList.size() - 1; k++) { - // while starts with key... - for (int k = 0; k < (int)p_completeList.size() - 1; k++) { + // remove all unwanted char + for (int i = 0; i < (int) delim.size(); i++) { + completeList[k].erase(remove(completeList[k].begin(), completeList[k].end(), delim[i]), completeList[k].end()); + } - // remove alll unwanted char - for (int i = 0; i < (int) delim.size(); i++) - p_completeList[k].erase(remove(p_completeList[k].begin(), p_completeList[k].end(), delim[i]), p_completeList[k].end()); + // only lines with ("key<.. are of interest + if (completeList[k].find("key<") != std::string::npos) { - // inly lines with ("key<.. are of interest - if (p_completeList[k].find("key<") != std::string::npos) { - // seperate key<... - std::istringstream split1(p_completeList[k]); + //split off the keys names + std::istringstream split1(completeList[k]); for (std::string each; std::getline(split1, each, split_bracel); tokens.push_back(each)); - // seperate rest with comma and push to everything + // replace keys names with number ( with 29,...) + int Keycode_ = replace_PosKey_with_Keycode(tokens[0]); + tokens[0] = std::to_string(Keycode_); + + // seperate rest of the vector to its elements and push to 'states' std::istringstream split(tokens[1]); tokens.pop_back(); for (std::string each; std::getline(split, each, split_char_komma); tokens.push_back(each)); - everything.push_back(tokens); + //printf("### 5 Split_US_To_3D_Vector: tokens: size:%li...tokens[0]-[4]:-name:%s\tShiftstates:%s--%s--%s--%s---.\n", tokens.size(),tokens[0].c_str(),tokens[1].c_str(),tokens[2].c_str(),tokens[3].c_str(),tokens[4].c_str()); + + shift_states.push_back(tokens); tokens.clear(); } } - //return everything; - all.push_back(everything); - //printf("+++++++ ssizes %i..%i..%i\n", all.size(), all[0].size ,all[0][0].size); - printf("+++++++ sizes SplitTo_3D_Vector %li..%li..%li\n", all.size(), all[0].size(),all[0][0].size()); + all_US.push_back(shift_states); + + //printf("### 6 Split_US_To_3D_clearVector %li..%li..%li\n", all_US.size(), all_US[0].size(),all_US[0][0].size()); +} + +int replace_PosKey_with_Keycode(std::string in) { + int out=0; + if ( in == "key") out = 49; //correct ??? + else if ( in == "key") out = 10; + else if ( in == "key") out = 11; + else if ( in == "key") out = 12; + else if ( in == "key") out = 13; + else if ( in == "key") out = 14; + else if ( in == "key") out = 15; + else if ( in == "key") out = 16; + else if ( in == "key") out = 17; + else if ( in == "key") out = 18; + else if ( in == "key") out = 19; + else if ( in == "key") out = 20; + else if ( in == "key") out = 21; + + else if ( in == "key") out = 24; + else if ( in == "key") out = 25; + else if ( in == "key") out = 26; + else if ( in == "key") out = 27; + else if ( in == "key") out = 28; + else if ( in == "key") out = 29; + else if ( in == "key") out = 30; + else if ( in == "key") out = 31; + else if ( in == "key") out = 32; + else if ( in == "key") out = 33; + else if ( in == "key") out = 34; + else if ( in == "key") out = 35; + + else if ( in == "key") out = 38; + else if ( in == "key") out = 39; + else if ( in == "key") out = 40; + else if ( in == "key") out = 41; + else if ( in == "key") out = 42; + else if ( in == "key") out = 43; + else if ( in == "key") out = 44; + else if ( in == "key") out = 45; + else if ( in == "key") out = 46; + else if ( in == "key") out = 47; + else if ( in == "key") out = 48; + else if ( in == "key") out = 49; + + else if ( in == "key") out = 52; + else if ( in == "key") out = 53; + else if ( in == "key") out = 54; + else if ( in == "key") out = 55; + else if ( in == "key") out = 56; + else if ( in == "key") out = 57; + else if ( in == "key") out = 58; + else if ( in == "key") out = 59; + else if ( in == "key") out = 60; + else if ( in == "key") out = 61; + else if ( in == "key") out = 62; //correct ??? + else if ( in == "key") out = 51; //correct ??? + return out; +} + +void append_other_ToVector(v_str_3D &All_Vector,GdkKeymap * keymap) { + + // create a 2D vector all fill0ed with "--" and push to 3D-Vector + v_str_2D Other_Vector2D = create_empty_2D(All_Vector[0].size(),All_Vector[0][0].size()); + All_Vector.push_back(Other_Vector2D); + + printf("+++++++ dimensions of Vector after append_other_ToVector\t %li..%li..%li\n", All_Vector.size(), All_Vector[0].size(),All_Vector[0][0].size()); + + for(int i =1; i< (int) All_Vector[1].size()-1;i++) + { + // get key name US stored in [0][i][0] and copy to name in other-block[1][i][0] + All_Vector[1][i][0] = All_Vector[0][i][0]; + + // write this value to 3D- Vector + All_Vector[1][i][0+1] = GetKeyvalsFromKeymap(keymap,stoi(All_Vector[1][i][0]),0); //shift state: unshifted:0 + All_Vector[1][i][1+1] = GetKeyvalsFromKeymap(keymap,stoi(All_Vector[1][i][0]),1); //shift state: shifted:1 + All_Vector[1][i][2+1] = GetKeyvalsFromKeymap(keymap,stoi(All_Vector[1][i][0]),2); //shift state: ? + All_Vector[1][i][3+1] = GetKeyvalsFromKeymap(keymap,stoi(All_Vector[1][i][0]),3); //shift state: ? + + //printf("Keycodes US->Other: %d(US): %s %s ---- (other):%s, %s, %s \n",stoi(All_Vector[1][i][0]),All_Vector[0][i][1].c_str(),All_Vector[0][i][2].c_str(),All_Vector[1][i][1].c_str(),All_Vector[1][i][2].c_str(),All_Vector[1][i][3].c_str()); + } +} + +v_str_2D create_empty_2D( int dim_rows,int dim_shifts) +{ + std::string empty = "--"; + v_str_1D shifts; + v_str_2D all; + + for ( int i=0; i< dim_rows;i++) { + for ( int i=0; i< dim_shifts;i++) { + shifts.push_back(empty); + } + all.push_back(shifts); + } return all; } +int GetKeyvalsFromKeymap(GdkKeymap *keymap, guint keycode, int keyval_value) { + GdkKeymapKey *maps; + guint *keyvals; + gint count; + int out; + + if (!gdk_keymap_get_entries_for_keycode(keymap, keycode, &maps, &keyvals, &count)) + return 0; + + out = keyvals[keyval_value]; + + g_free(keyvals); + g_free(maps); + return out; +} + +void extract_difference( v_str_3D &All_Vector) +{ + std::ofstream Map_File("Map_US.txt"); + std::string diff =" "; + + printf("-----------------------------------------------------------------------------------------------------------------------------------------------\n"); + std::cout << "Nr of \n" ; + std::cout << "Key: " << "\t Character US (no shift) " << " Character US (shift) "<< "\t\tCharacter other (no shift)" << "\tCharacter other (shift) difference \n" ; + printf("-----------------------------------------------------------------------------------------------------------------------------------------------\n"); + + Map_File <<"--------------------------------------------------------------------------------------------------------------------------------------------\n"; + Map_File << "Nr of \n" ; + Map_File << "Key: " << "\t Character US (no shift) " << " Character US (shift) "<< "\t\tCharacter other (no shift)" << "\tCharacter other (shift) difference \n" ; + Map_File <<"--------------------------------------------------------------------------------------------------------------------------------------------\n"; + + for ( int k=0; k<(int)All_Vector[0].size()-1; k++) { + if (All_Vector[0][k][1] == All_Vector[1][k][1]) + diff =" "; + else + diff =" *** "; + + std::cout << All_Vector[0][k][0] << "\t " <<+(*(All_Vector[0][k][1].c_str()))<< "\t("<< All_Vector[0][k][1] <<")"<1) + std::cout << " row 1 (Other).."< @@ -11,10 +13,53 @@ typedef std::vector v_str_1D; typedef std::vector > v_str_2D; typedef std::vector > > v_str_3D; + +int keyval_value =0; // get first group (0: small letters) +std::vector used_shift_state ={0,1}; // use shiftstate : no shift, shift + +// read configuration file, split and write to 3D-Vector (Data for US on [0][ ][ ] ) +void write_US_ToVector( v_str_3D &vec,std::string language, const char* text) ; + +//1. step: read complete Row of Configuration file US +void CreateCompleteRow_US(v_str_1D &complete_List ,FILE* fpp, const char* text, std::string language); + +//2nd step: write contents to 3D vector +void Split_US_To_3D_Vector(v_str_3D &all_US,v_str_1D completeList); + +// replace Name of Key (e.g. ) wih Keycode ( e.g. 15 ) +int replace_PosKey_with_Keycode(std::string in); + + + +// append characters using GDK to 3D-Vector (Data for Other Language on [1][ ][ ] ) +void append_other_ToVector(v_str_3D &All_Vector,GdkKeymap * keymap); + +// create an empty 2D vector containing "--" in all fields +v_str_2D create_empty_2D( int dim_rows,int dim_shifts); + +// find Keyvals to fill into 2D-Vector of Other Language +int GetKeyvalsFromKeymap(GdkKeymap *keymap, guint keycode, int keyval_value); + + +// print both sets of characters (US and OtherLanguage) to console and file for comparison +void extract_difference(v_str_3D &All_Vector ) ; + + +// get mapped key from Other (Other->US) +std::string get_Other_Char_FromUS( std::string in , v_str_3D &All_Vector); +// get mapped key from US->Other (US->Other) +std::string get_US_Char_FromOther(std::string in , v_str_3D &All_Vector); +// get KeyNr from US +std::string getKeyNrOf_USChar(std::string in , v_str_3D &All_Vector); +// get KeyNr from Other +std::string getKeyNrOf_OtherChar(std::string in , v_str_3D &All_Vector); + +// test of above functions (character mapping US <-> Other; KeyNr <-> CHaracter) +void test_in_out(v_str_3D &All_Vector); + +// testing of Vector contents ( first row of US and Other) +bool test(v_str_3D &V); + -static void PrintKeymapForCode(GdkKeymap *keymap, guint keycode); -v_str_3D write_US_ToVector(std::string language, const char* text) ; -v_str_1D CreateCompleteRow_US(FILE* fpp, const char* text, std::string language) ; -void extract_difference(v_str_3D US_vector, std::string lang_Other ) ; -v_str_3D SplitTo_3D_Vector(v_str_1D completeListUS); +//---------------------------------- From 2a2455c78e8a79275bed289b11141f8b63938c64 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 31 May 2023 10:28:40 +0200 Subject: [PATCH 05/16] feature(Linux): mcompile use US basic instead of US intl --- linux/mcompile/keymap/keymap.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linux/mcompile/keymap/keymap.cpp b/linux/mcompile/keymap/keymap.cpp index 0295e41e0e6..f0882cdc829 100644 --- a/linux/mcompile/keymap/keymap.cpp +++ b/linux/mcompile/keymap/keymap.cpp @@ -346,11 +346,11 @@ int main(gint argc, gchar *argv[]) } // write content of xkb_symbols to 3D Vector - // I assume we use Keyboard US intl as base + // I assume we use Keyboard US basic as base printf("-°°°°°°°° write_US_ToVector\n"); std::string US_language = "us"; - const char* text_us = "xkb_symbols \"intl\""; - //const char* text_us = "xkb_symbols \"basic\""; + //const char* text_us = "xkb_symbols \"intl\""; + const char* text_us = "xkb_symbols \"basic\""; v_str_3D All_Vector; write_US_ToVector(All_Vector,US_language, text_us); From 802617b50a8031a7ed97f256c8284911c5953705 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 31 May 2023 15:19:08 +0200 Subject: [PATCH 06/16] feature(Linux): mcompile change readme --- linux/mcompile/keymap/README.md | 3 +-- linux/mcompile/keymap/keymap.cpp | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/linux/mcompile/keymap/README.md b/linux/mcompile/keymap/README.md index 4891de51529..37737b7c3cb 100644 --- a/linux/mcompile/keymap/README.md +++ b/linux/mcompile/keymap/README.md @@ -1,4 +1,3 @@ # Keymap -Sample program that loops over the key codes 10-61 and outputs the key -values for groups 0 and 1. +Sample program that reads US basic keyboard and compares to key value group diff --git a/linux/mcompile/keymap/keymap.cpp b/linux/mcompile/keymap/keymap.cpp index f0882cdc829..a39a15fa96b 100644 --- a/linux/mcompile/keymap/keymap.cpp +++ b/linux/mcompile/keymap/keymap.cpp @@ -349,7 +349,6 @@ int main(gint argc, gchar *argv[]) // I assume we use Keyboard US basic as base printf("-°°°°°°°° write_US_ToVector\n"); std::string US_language = "us"; - //const char* text_us = "xkb_symbols \"intl\""; const char* text_us = "xkb_symbols \"basic\""; v_str_3D All_Vector; From 8a2f053d4dacb1adba5b5eb380400b1781847c69 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 31 May 2023 17:30:25 +0200 Subject: [PATCH 07/16] feature(Linux): mcompile write some functions to get map and test --- linux/mcompile/keymap/keymap.cpp | 76 +++++++++++++++++++++++++++----- linux/mcompile/keymap/keymap.h | 7 ++- 2 files changed, 72 insertions(+), 11 deletions(-) diff --git a/linux/mcompile/keymap/keymap.cpp b/linux/mcompile/keymap/keymap.cpp index a39a15fa96b..58277f78807 100644 --- a/linux/mcompile/keymap/keymap.cpp +++ b/linux/mcompile/keymap/keymap.cpp @@ -1,6 +1,6 @@ #include "keymap.h" - +/* static void PrintKeymapForCode(GdkKeymap *keymap, guint keycode) { GdkKeymapKey *maps; @@ -19,6 +19,7 @@ static void PrintKeymapForCode(GdkKeymap *keymap, guint keycode) g_free(keyvals); g_free(maps); } +*/ void write_US_ToVector( v_str_3D &vec,std::string language, const char* text) { std::string FullPathName = "/usr/share/X11/xkb/symbols/" + language; @@ -256,45 +257,50 @@ void extract_difference( v_str_3D &All_Vector) diff =" *** "; std::cout << All_Vector[0][k][0] << "\t " <<+(*(All_Vector[0][k][1].c_str()))<< "\t("<< All_Vector[0][k][1] <<")"< Other: "<< std::setw(5)< Other: (" << in << ": no match)\n"; return "-"; } std::string get_US_Char_FromOther(std::string in , v_str_3D &All_Vector) { + std::string diff; // find correct row of char in other for( int i=0; i< (int)All_Vector[1].size()-1;i++) { for( int j=0; j< (int)All_Vector[1][0].size()-1;j++) { if ( All_Vector[1][i][j] == in ) { - std::cout << " get_US_Char_FromOther : "<< All_Vector[1][i][j] << " out: " << All_Vector[0][i][j] <<"\n"; - return All_Vector[0][i][j] ; + if ( All_Vector[0][i][j] != All_Vector[1][i][j]) diff =" ** "; + std::cout << "Other -> US: "<< std::setw(5)< US: (" << in << ": no match)\n"; + return "-"; } - return "-"; -} std::string getKeyNrOf_USChar(std::string in , v_str_3D &All_Vector) { // find correct row of char in US for( int i=0; i< (int)All_Vector[0].size()-1;i++) { for( int j=0; j< (int)All_Vector[0][0].size()-1;j++) { if ( All_Vector[0][i][j] == in ) { - std::cout << " getKeyNrOf_USChar : "<< All_Vector[0][i][j] << " out: " << All_Vector[0][i][0] <<"\n"; + std::cout << "KeyNr of US char: \t"<< All_Vector[0][i][j] << " -> " << All_Vector[0][i][0] <<"\n"; return All_Vector[0][i][0] ; } } @@ -307,7 +313,7 @@ std::string getKeyNrOf_OtherChar(std::string in , v_str_3D &All_Vector) { for( int i=0; i< (int)All_Vector[1].size()-1;i++) { for( int j=0; j< (int)All_Vector[1][0].size()-1;j++) { if ( All_Vector[1][i][j] == in ) { - std::cout << " getKeyNrOf_OtherChar : "<< All_Vector[1][i][j] << " out: " << All_Vector[1][i][0] <<"\n"; + std::cout << "KeyNr of Other char : \t"<< All_Vector[1][i][j] << " -> " << All_Vector[1][i][0] <<"\n"; return All_Vector[1][i][0] ; } } @@ -328,6 +334,53 @@ bool test(v_str_3D &V) { return true; } +void test_in_out(v_str_3D &All_Vector) { +std::string diff; + printf("-----------------------------------------------------------------------------------------------------------------------------------------------\n"); + //checks mapping between US and other + std::string a = get_Other_Char_FromUS( "z", All_Vector); + std::string aa = get_Other_Char_FromUS( "Z", All_Vector); + std::string aaa = get_Other_Char_FromUS( "y", All_Vector); + std::string aaaa = get_Other_Char_FromUS( "Y", All_Vector); + + std::string b = get_US_Char_FromOther( "z", All_Vector); + std::string bb = get_US_Char_FromOther( "Z", All_Vector); + std::string bbb = get_US_Char_FromOther( "y", All_Vector); + std::string bbbb = get_US_Char_FromOther( "Y", All_Vector); + + std::string c = getKeyNrOf_OtherChar( "z", All_Vector); + std::string cc = getKeyNrOf_OtherChar( "Z", All_Vector); + std::string ccc = getKeyNrOf_OtherChar( "y", All_Vector); + std::string cccc = getKeyNrOf_OtherChar( "Y", All_Vector); + + std::string d = getKeyNrOf_USChar( "z", All_Vector); + std::string dd = getKeyNrOf_USChar( "Z", All_Vector); + std::string ddd = getKeyNrOf_USChar( "y", All_Vector); + std::string dddd = getKeyNrOf_USChar( "Y", All_Vector); + + std::cout << "get_Other_Char_FromUS z-Z-y-Y: " << ".." << a<< ".." < v_str_1D; typedef std::vector > v_str_2D; typedef std::vector > > v_str_3D; -int keyval_value =0; // get first group (0: small letters) std::vector used_shift_state ={0,1}; // use shiftstate : no shift, shift // read configuration file, split and write to 3D-Vector (Data for US on [0][ ][ ] ) @@ -54,6 +53,12 @@ std::string getKeyNrOf_USChar(std::string in , v_str_3D &All_Vector); // get KeyNr from Other std::string getKeyNrOf_OtherChar(std::string in , v_str_3D &All_Vector); +// prints out a 1:1 mapping US->Other +void print_simple_map_US(v_str_3D &All_Vector, int shiftstate); + +// prints out a 1:1 mapping Other->US +void print_simple_map_Other(v_str_3D &All_Vector, int shiftstate); + // test of above functions (character mapping US <-> Other; KeyNr <-> CHaracter) void test_in_out(v_str_3D &All_Vector); From da4e71638344b23a5644c5fb812f17759ee2c2ec Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 31 May 2023 17:40:08 +0200 Subject: [PATCH 08/16] feature(Linux): mcompile ToDo added; remove old file --- linux/mcompile/keymap/Xmain.cpp | 148 ------------------------------- linux/mcompile/keymap/keymap.cpp | 1 + 2 files changed, 1 insertion(+), 148 deletions(-) delete mode 100644 linux/mcompile/keymap/Xmain.cpp diff --git a/linux/mcompile/keymap/Xmain.cpp b/linux/mcompile/keymap/Xmain.cpp deleted file mode 100644 index b48cd273397..00000000000 --- a/linux/mcompile/keymap/Xmain.cpp +++ /dev/null @@ -1,148 +0,0 @@ -#include "keymap.h" - -static void PrintKeymapForCode(GdkKeymap *keymap, guint keycode) -{ - GdkKeymapKey *maps; - guint *keyvals; - gint count; - - if (!gdk_keymap_get_entries_for_keycode(keymap, keycode, &maps, &keyvals, &count)) - return; - - for (int i = 0; i < count; i++) { - if (maps[i].level > 0 || maps[i].group > 1) - continue; - printf(" i=%d, keycode=%d, keyval=%d (%c), level=%d, group=%d\n", i, maps[i].keycode, keyvals[i], keyvals[i], maps[i].level, maps[i].group); - } - - g_free(keyvals); - g_free(maps); -} - -std::vector > > write_US_ToVector(std::string language, const char* text) { - printf("+++++++ start to open_file \n"); - std::vector > > Vector_split; - std::string FullPathName = "/usr/share/X11/xkb/symbols/" + language; - const char* cc = FullPathName.c_str(); - FILE* fp = fopen((cc), "r"); - if ( !fp) - printf("could not open file!"); - else - printf("+++++++ file open OK \n"); - std::vector Vector_complete = CreateCompleteRow_US(fp, text, language); // creates vector of all . TTODO lookup other language files - - fclose(fp); - return Vector_split; -} - -std::vector CreateCompleteRow_US(FILE* fpp, const char* text, std::string language) { - printf("+++++++ start CreateCompleteRow_US\n"); - std::vector complete_List; - int buffer_size = 512; - char buffer[buffer_size]; - bool print_OK = false; - const char* key = "key <"; - std::string str_txt(text); - std::string xbk_mark = "xkb_symbol"; - std::ofstream KeyboardFile("File_" + language + ".txt"); - - printf("Keyboard %s\n", text); - KeyboardFile << "Keyboard" << text << "\n"; - - if (fpp) { - while (fgets(buffer, buffer_size, fpp) != NULL) { - std::string str_buf(buffer); - - // TODO: recursive search for other included Configuration files - // if find "include" -> recursive... - - // stop when finding the mark xkb_symbol - if (std::string(str_buf).find(xbk_mark) != std::string::npos) - print_OK = false; - - // start when finding the mark xkb_symbol + correct layout - if ((std::string(str_buf).find(str_txt) != std::string::npos)) - print_OK = true; - - if ((print_OK) && (std::string(str_buf).find(key) != std::string::npos)) { - printf("... %s", buffer); - complete_List.push_back(buffer); - KeyboardFile << buffer; - } - } - } - printf("end Keyboard %s..........................................\n\n", text); - return complete_List; -} - -void extract_difference(std::vector > > US_vector, std::string lang_Other ) -{ - printf("+++++++ start extract_difference\n"); - /* - std::ofstream Map_File("Map_" + lang_US + "_To_" + lang_Other + ".txt"); - std::string diff; - std::cout <<"key"<< std::setw(26)<< "Char US"<< std::setw(20)<<"Char other" << std::setw(10)<< "diff? \n"; - Map_File <<"key"<< std::setw(26)<< "Char US"<< std::setw(20)<<"Char other" << std::setw(10)<< "diff? \n"; - std::cout <<"---------------------------------------------------------------\n"; - Map_File <<"---------------------------------------------------------------\n"; - - //ToDo for all columns; watchout for empty fields!! - for ( int i =0; i< US_vector.size();i++) - { - for ( int j =0; j< other_vector.size();j++) - { - diff =" \t"; - if( US_vector[i][0] == other_vector[j][0] ) - { - if( US_vector[i][1] != other_vector[j][1] ) diff = " *** "; - std::cout << US_vector[i][0] << std::setw(20)<< US_vector[i][1] << std::setw(20)<< other_vector[j][1] < > > All_Vector = write_US_ToVector(US_language, text_us); - extract_difference(All_Vector,other_language); - -//------------------------------------------ - - - - - gdk_display_close(display); - - return 0; -} diff --git a/linux/mcompile/keymap/keymap.cpp b/linux/mcompile/keymap/keymap.cpp index 58277f78807..d79763749ec 100644 --- a/linux/mcompile/keymap/keymap.cpp +++ b/linux/mcompile/keymap/keymap.cpp @@ -194,6 +194,7 @@ void append_other_ToVector(v_str_3D &All_Vector,GdkKeymap * keymap) { // get key name US stored in [0][i][0] and copy to name in other-block[1][i][0] All_Vector[1][i][0] = All_Vector[0][i][0]; + // TODO see that nr of shift states are not out of range !! // write this value to 3D- Vector All_Vector[1][i][0+1] = GetKeyvalsFromKeymap(keymap,stoi(All_Vector[1][i][0]),0); //shift state: unshifted:0 All_Vector[1][i][1+1] = GetKeyvalsFromKeymap(keymap,stoi(All_Vector[1][i][0]),1); //shift state: shifted:1 From 58962db9ef7c00ff42087442cce63d5e8d43d7e5 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 31 May 2023 17:59:08 +0200 Subject: [PATCH 09/16] feature(Linux): mcompile mor TODOs in Readme.md --- linux/mcompile/keymap/README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/linux/mcompile/keymap/README.md b/linux/mcompile/keymap/README.md index 37737b7c3cb..b74985a3734 100644 --- a/linux/mcompile/keymap/README.md +++ b/linux/mcompile/keymap/README.md @@ -1,3 +1,15 @@ # Keymap Sample program that reads US basic keyboard and compares to key value group + + + +TODO check if US basic is the right Keyboard to compare with +TODO non-letter characters don't work OK yet +TODO Umlauts don't work OK yet +TODO Check for use of correct dimensions in Vector/prevent error if dims are not correct +TODO prevent crashes: handle possible Errors in CreateCompleteRow_US, Split_US_To_3D_Vector +TODO check Keycode of TLDE, BKSL, LSGT +TODO append_other_ToVector: ensure shift states of GetKeyvalsFromKeymap are not out of range +TODO remove unnecessary printf/cout +TODO ... From d21c05eb724d284034d98711ab42a222b169faf7 Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 2 Jun 2023 08:57:50 +0200 Subject: [PATCH 10/16] feature(Linux): mcompile change variable for nested loop --- linux/mcompile/keymap/keymap.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/linux/mcompile/keymap/keymap.cpp b/linux/mcompile/keymap/keymap.cpp index d79763749ec..67c86b59f9e 100644 --- a/linux/mcompile/keymap/keymap.cpp +++ b/linux/mcompile/keymap/keymap.cpp @@ -198,8 +198,8 @@ void append_other_ToVector(v_str_3D &All_Vector,GdkKeymap * keymap) { // write this value to 3D- Vector All_Vector[1][i][0+1] = GetKeyvalsFromKeymap(keymap,stoi(All_Vector[1][i][0]),0); //shift state: unshifted:0 All_Vector[1][i][1+1] = GetKeyvalsFromKeymap(keymap,stoi(All_Vector[1][i][0]),1); //shift state: shifted:1 - All_Vector[1][i][2+1] = GetKeyvalsFromKeymap(keymap,stoi(All_Vector[1][i][0]),2); //shift state: ? - All_Vector[1][i][3+1] = GetKeyvalsFromKeymap(keymap,stoi(All_Vector[1][i][0]),3); //shift state: ? + //All_Vector[1][i][2+1] = GetKeyvalsFromKeymap(keymap,stoi(All_Vector[1][i][0]),2); //shift state: ? + //All_Vector[1][i][3+1] = GetKeyvalsFromKeymap(keymap,stoi(All_Vector[1][i][0]),3); //shift state: ? //printf("Keycodes US->Other: %d(US): %s %s ---- (other):%s, %s, %s \n",stoi(All_Vector[1][i][0]),All_Vector[0][i][1].c_str(),All_Vector[0][i][2].c_str(),All_Vector[1][i][1].c_str(),All_Vector[1][i][2].c_str(),All_Vector[1][i][3].c_str()); } @@ -212,11 +212,13 @@ v_str_2D create_empty_2D( int dim_rows,int dim_shifts) v_str_2D all; for ( int i=0; i< dim_rows;i++) { - for ( int i=0; i< dim_shifts;i++) { + for ( int j=0; j< dim_shifts;j++) { shifts.push_back(empty); } all.push_back(shifts); + shifts.clear(); } + //printf("+++++++ dimensions of Vector after create_empty_2D\t\t %li..%li..%li\n", all.size(), all[0].size(),all[1].size()); return all; } From 20c045a65463dde4b7633a150c6f01a13b1d36d4 Mon Sep 17 00:00:00 2001 From: Sabine Date: Fri, 2 Jun 2023 17:27:41 +0200 Subject: [PATCH 11/16] feature(Linux): mcompile : loop variable,check count, rename keyval_value --- linux/mcompile/keymap/README.md | 5 ++++- linux/mcompile/keymap/keymap.cpp | 8 ++++++-- linux/mcompile/keymap/keymap.h | 8 ++------ 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/linux/mcompile/keymap/README.md b/linux/mcompile/keymap/README.md index b74985a3734..dc65a9d2441 100644 --- a/linux/mcompile/keymap/README.md +++ b/linux/mcompile/keymap/README.md @@ -10,6 +10,9 @@ TODO Umlauts don't work OK yet TODO Check for use of correct dimensions in Vector/prevent error if dims are not correct TODO prevent crashes: handle possible Errors in CreateCompleteRow_US, Split_US_To_3D_Vector TODO check Keycode of TLDE, BKSL, LSGT -TODO append_other_ToVector: ensure shift states of GetKeyvalsFromKeymap are not out of range TODO remove unnecessary printf/cout +TODO path for xkb/symbols absolute->relative in meson +TODO append_other_ToVector: ensure shift states of GetKeyvalsFromKeymap are not out of range +TODO check how many/which shift states we use ( at the moment we read all shiftstate-columns of US, create as many colums for Other ) + but then use only 2 colums (non-shift + shift) TODO ... diff --git a/linux/mcompile/keymap/keymap.cpp b/linux/mcompile/keymap/keymap.cpp index 67c86b59f9e..6fa794c1c31 100644 --- a/linux/mcompile/keymap/keymap.cpp +++ b/linux/mcompile/keymap/keymap.cpp @@ -110,6 +110,7 @@ void Split_US_To_3D_Vector(v_str_3D &all_US,v_str_1D completeList) { tokens[0] = std::to_string(Keycode_); // seperate rest of the vector to its elements and push to 'states' + // TODO define how many/which elements=colums=shift states we use std::istringstream split(tokens[1]); tokens.pop_back(); for (std::string each; std::getline(split, each, split_char_komma); tokens.push_back(each)); @@ -222,7 +223,7 @@ v_str_2D create_empty_2D( int dim_rows,int dim_shifts) return all; } -int GetKeyvalsFromKeymap(GdkKeymap *keymap, guint keycode, int keyval_value) { +int GetKeyvalsFromKeymap(GdkKeymap *keymap, guint keycode, int shift_state_pos) { GdkKeymapKey *maps; guint *keyvals; gint count; @@ -231,7 +232,10 @@ int GetKeyvalsFromKeymap(GdkKeymap *keymap, guint keycode, int keyval_value) { if (!gdk_keymap_get_entries_for_keycode(keymap, keycode, &maps, &keyvals, &count)) return 0; - out = keyvals[keyval_value]; + if (!(shift_state_pos < count)) + return 0; + + out = keyvals[shift_state_pos]; g_free(keyvals); g_free(maps); diff --git a/linux/mcompile/keymap/keymap.h b/linux/mcompile/keymap/keymap.h index eb1bde2e414..ec157736d7e 100644 --- a/linux/mcompile/keymap/keymap.h +++ b/linux/mcompile/keymap/keymap.h @@ -14,7 +14,7 @@ typedef std::vector v_str_1D; typedef std::vector > v_str_2D; typedef std::vector > > v_str_3D; -std::vector used_shift_state ={0,1}; // use shiftstate : no shift, shift +int shift_state_count = 2; // use shiftstate : no shift, shift // read configuration file, split and write to 3D-Vector (Data for US on [0][ ][ ] ) void write_US_ToVector( v_str_3D &vec,std::string language, const char* text) ; @@ -37,7 +37,7 @@ void append_other_ToVector(v_str_3D &All_Vector,GdkKeymap * keymap); v_str_2D create_empty_2D( int dim_rows,int dim_shifts); // find Keyvals to fill into 2D-Vector of Other Language -int GetKeyvalsFromKeymap(GdkKeymap *keymap, guint keycode, int keyval_value); +int GetKeyvalsFromKeymap(GdkKeymap *keymap, guint keycode, int shift_state_pos); // print both sets of characters (US and OtherLanguage) to console and file for comparison @@ -64,7 +64,3 @@ void test_in_out(v_str_3D &All_Vector); // testing of Vector contents ( first row of US and Other) bool test(v_str_3D &V); - - - -//---------------------------------- From 3b2e2d73fba41c2dc0cd56868c6f5b9b479ca2ef Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 5 Jun 2023 16:17:35 +0200 Subject: [PATCH 12/16] feature(Linux): mcompile : fix amount of shift_states to 2 even if layout in xkb has more --- linux/mcompile/keymap/keymap.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/linux/mcompile/keymap/keymap.h b/linux/mcompile/keymap/keymap.h index ec157736d7e..87627c4954f 100644 --- a/linux/mcompile/keymap/keymap.h +++ b/linux/mcompile/keymap/keymap.h @@ -53,14 +53,13 @@ std::string getKeyNrOf_USChar(std::string in , v_str_3D &All_Vector); // get KeyNr from Other std::string getKeyNrOf_OtherChar(std::string in , v_str_3D &All_Vector); + +// for testing/debugging - may be deleted later // prints out a 1:1 mapping US->Other void print_simple_map_US(v_str_3D &All_Vector, int shiftstate); - // prints out a 1:1 mapping Other->US void print_simple_map_Other(v_str_3D &All_Vector, int shiftstate); - // test of above functions (character mapping US <-> Other; KeyNr <-> CHaracter) void test_in_out(v_str_3D &All_Vector); - // testing of Vector contents ( first row of US and Other) bool test(v_str_3D &V); From f1d2c95f0b82f98ac9625b7d68d232ce4167fe08 Mon Sep 17 00:00:00 2001 From: Sabine Date: Mon, 5 Jun 2023 16:52:33 +0200 Subject: [PATCH 13/16] feature(Linux): mcompile : comments, rename variables,... --- linux/mcompile/keymap/README.md | 10 +++-- linux/mcompile/keymap/keymap.cpp | 64 +++++++++++++++++--------------- 2 files changed, 41 insertions(+), 33 deletions(-) diff --git a/linux/mcompile/keymap/README.md b/linux/mcompile/keymap/README.md index dc65a9d2441..a40b7d4fefb 100644 --- a/linux/mcompile/keymap/README.md +++ b/linux/mcompile/keymap/README.md @@ -11,8 +11,12 @@ TODO Check for use of correct dimensions in Vector/prevent error if dims are not TODO prevent crashes: handle possible Errors in CreateCompleteRow_US, Split_US_To_3D_Vector TODO check Keycode of TLDE, BKSL, LSGT TODO remove unnecessary printf/cout -TODO path for xkb/symbols absolute->relative in meson +TODO path for xkb/symbols as compile time option in meson TODO append_other_ToVector: ensure shift states of GetKeyvalsFromKeymap are not out of range -TODO check how many/which shift states we use ( at the moment we read all shiftstate-columns of US, create as many colums for Other ) - but then use only 2 colums (non-shift + shift) +TODO check how many/which shift states we use ( at the moment we read all shiftstate-columns of US but then use only 2 colums + (non-shift + shift) then use as many colums for Other ) + +TODO define folder to store File_US.txt" in and find better name +TODO get rid of GTK functions that are deprecated and use X11 instead +TODO retrieve name of Other keyboard and use appropriate name instead of "Other" TODO ... diff --git a/linux/mcompile/keymap/keymap.cpp b/linux/mcompile/keymap/keymap.cpp index 6fa794c1c31..109f9109335 100644 --- a/linux/mcompile/keymap/keymap.cpp +++ b/linux/mcompile/keymap/keymap.cpp @@ -24,14 +24,14 @@ static void PrintKeymapForCode(GdkKeymap *keymap, guint keycode) void write_US_ToVector( v_str_3D &vec,std::string language, const char* text) { std::string FullPathName = "/usr/share/X11/xkb/symbols/" + language; - const char* cc = FullPathName.c_str(); - FILE* fp = fopen((cc), "r"); + const char* path = FullPathName.c_str(); + FILE* fp = fopen((path), "r"); if ( !fp) printf("could not open file!"); // create 1D-vector of the complete line v_str_1D Vector_completeUS; - CreateCompleteRow_US(Vector_completeUS,fp, text, language); + CreateCompleteRow_US(Vector_completeUS,fp , text, language); // split contents of 1D Vector to 3D vector Split_US_To_3D_Vector( vec,Vector_completeUS); @@ -40,7 +40,7 @@ void write_US_ToVector( v_str_3D &vec,std::string language, const char* text) { fclose(fp); } -void CreateCompleteRow_US(v_str_1D &complete_List, FILE* fpp, const char* text, std::string language) { +void CreateCompleteRow_US(v_str_1D &complete_List, FILE* fp, const char* text, std::string language) { // in the Configuration file we find the appopriate paragraph between "xkb_symbol " and the next xkb_symbol // and then copy all rows starting with "key <" to a v1D-Vector @@ -50,13 +50,14 @@ void CreateCompleteRow_US(v_str_1D &complete_List, FILE* fpp, const char* text, const char* key = "key <"; std::string str_txt(text); std::string xbk_mark = "xkb_symbol"; + // TODO define folder to store File in std::ofstream KeyboardFile("File_" + language + ".txt"); printf("Keyboard %s\n", text); KeyboardFile << "Keyboard" << text << "\n"; - if (fpp) { - while (fgets(buffer, buffer_size, fpp) != NULL) { + if (fp) { + while (fgets(buffer, buffer_size, fp) != NULL) { std::string str_buf(buffer); // stop when finding the mark xkb_symbol @@ -67,7 +68,7 @@ void CreateCompleteRow_US(v_str_1D &complete_List, FILE* fpp, const char* text, if ((std::string(str_buf).find(str_txt) != std::string::npos)) print_OK = true; - // as long as we are in the same xkb_symbol layout and find "key <" we push the whole line into a 1D-vector + // as long as we are in the same xkb_symbol layout block and find "key <" we push the whole line into a 1D-vector if ((print_OK) && (std::string(str_buf).find(key) != std::string::npos)) { printf("%s", buffer); complete_List.push_back(buffer); @@ -79,9 +80,9 @@ void CreateCompleteRow_US(v_str_1D &complete_List, FILE* fpp, const char* text, } void Split_US_To_3D_Vector(v_str_3D &all_US,v_str_1D completeList) { - // first: take the whole line of the 1D-Vector and remove unwanted characters. - // second: split off the name e.g. key and the shiftstates - // third: push Names/Shiftstates to shift_states and then shiftstates to All_US, our 3D-Vector holding all Elements + // 1: take the whole line of the 1D-Vector and remove unwanted characters. + // 2: seperate the name e.g. key and the shiftstates + // 3: push Names/Shiftstates to shift_states and then shiftstates to All_US, our 3D-Vector holding all Elements std::vector delim{' ', '[', ']', '}', ';', '\t', '\n'}; char split_bracel = '{'; @@ -101,27 +102,32 @@ void Split_US_To_3D_Vector(v_str_3D &all_US,v_str_1D completeList) { // only lines with ("key<.. are of interest if (completeList[k].find("key<") != std::string::npos) { - //split off the keys names + //split off the key names std::istringstream split1(completeList[k]); for (std::string each; std::getline(split1, each, split_bracel); tokens.push_back(each)); // replace keys names with number ( with 29,...) - int Keycode_ = replace_PosKey_with_Keycode(tokens[0]); - tokens[0] = std::to_string(Keycode_); + int Keycde = replace_PosKey_with_Keycode(tokens[0]); + tokens[0] = std::to_string(Keycde); - // seperate rest of the vector to its elements and push to 'states' - // TODO define how many/which elements=colums=shift states we use + // seperate rest of the vector to its elements and push to 'tokens' std::istringstream split(tokens[1]); tokens.pop_back(); for (std::string each; std::getline(split, each, split_char_komma); tokens.push_back(each)); //printf("### 5 Split_US_To_3D_Vector: tokens: size:%li...tokens[0]-[4]:-name:%s\tShiftstates:%s--%s--%s--%s---.\n", tokens.size(),tokens[0].c_str(),tokens[1].c_str(),tokens[2].c_str(),tokens[3].c_str(),tokens[4].c_str()); + // at the moment we only use the first 2 shiftstates (non-shift+shift) so get rid of all others + int surplus = tokens.size() - shift_state_count -1; + for( int j=0; j < surplus;j++) { + tokens.pop_back(); + } + + // now push result to shift_states shift_states.push_back(tokens); tokens.clear(); } } all_US.push_back(shift_states); - //printf("### 6 Split_US_To_3D_clearVector %li..%li..%li\n", all_US.size(), all_US[0].size(),all_US[0][0].size()); } @@ -195,13 +201,9 @@ void append_other_ToVector(v_str_3D &All_Vector,GdkKeymap * keymap) { // get key name US stored in [0][i][0] and copy to name in other-block[1][i][0] All_Vector[1][i][0] = All_Vector[0][i][0]; - // TODO see that nr of shift states are not out of range !! // write this value to 3D- Vector All_Vector[1][i][0+1] = GetKeyvalsFromKeymap(keymap,stoi(All_Vector[1][i][0]),0); //shift state: unshifted:0 All_Vector[1][i][1+1] = GetKeyvalsFromKeymap(keymap,stoi(All_Vector[1][i][0]),1); //shift state: shifted:1 - //All_Vector[1][i][2+1] = GetKeyvalsFromKeymap(keymap,stoi(All_Vector[1][i][0]),2); //shift state: ? - //All_Vector[1][i][3+1] = GetKeyvalsFromKeymap(keymap,stoi(All_Vector[1][i][0]),3); //shift state: ? - //printf("Keycodes US->Other: %d(US): %s %s ---- (other):%s, %s, %s \n",stoi(All_Vector[1][i][0]),All_Vector[0][i][1].c_str(),All_Vector[0][i][2].c_str(),All_Vector[1][i][1].c_str(),All_Vector[1][i][2].c_str(),All_Vector[1][i][3].c_str()); } } @@ -244,6 +246,7 @@ int GetKeyvalsFromKeymap(GdkKeymap *keymap, guint keycode, int shift_state_pos) void extract_difference( v_str_3D &All_Vector) { + // TODO define which Folder; find better name std::ofstream Map_File("Map_US.txt"); std::string diff =" "; @@ -264,7 +267,7 @@ void extract_difference( v_str_3D &All_Vector) diff =" *** "; std::cout << All_Vector[0][k][0] << "\t " <<+(*(All_Vector[0][k][1].c_str()))<< "\t("<< All_Vector[0][k][1] <<")"< Other: "<< std::setw(5)< US: "<< std::setw(5)<1) - std::cout << " row 1 (Other).."< Date: Mon, 5 Jun 2023 17:39:08 +0200 Subject: [PATCH 14/16] feature(Linux): mcompile : marked places where checks might be useful --- linux/mcompile/keymap/keymap.cpp | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/linux/mcompile/keymap/keymap.cpp b/linux/mcompile/keymap/keymap.cpp index 109f9109335..2101ac12ad6 100644 --- a/linux/mcompile/keymap/keymap.cpp +++ b/linux/mcompile/keymap/keymap.cpp @@ -22,6 +22,7 @@ static void PrintKeymapForCode(GdkKeymap *keymap, guint keycode) */ void write_US_ToVector( v_str_3D &vec,std::string language, const char* text) { + // ? CHECK if ran OK-> return 0/1 std::string FullPathName = "/usr/share/X11/xkb/symbols/" + language; const char* path = FullPathName.c_str(); @@ -44,6 +45,7 @@ void CreateCompleteRow_US(v_str_1D &complete_List, FILE* fp, const char* text, // in the Configuration file we find the appopriate paragraph between "xkb_symbol " and the next xkb_symbol // and then copy all rows starting with "key <" to a v1D-Vector + // ? CHECK if ran OK-> return 0/1 int buffer_size = 512; char buffer[buffer_size]; bool print_OK = false; @@ -84,6 +86,7 @@ void Split_US_To_3D_Vector(v_str_3D &all_US,v_str_1D completeList) { // 2: seperate the name e.g. key and the shiftstates // 3: push Names/Shiftstates to shift_states and then shiftstates to All_US, our 3D-Vector holding all Elements + // ? CHECK if ran OK-> return 0/1 std::vector delim{' ', '[', ']', '}', ';', '\t', '\n'}; char split_bracel = '{'; char split_char_komma = ','; @@ -107,6 +110,8 @@ void Split_US_To_3D_Vector(v_str_3D &all_US,v_str_1D completeList) { for (std::string each; std::getline(split1, each, split_bracel); tokens.push_back(each)); // replace keys names with number ( with 29,...) + + // ? CHECK if ran OK-> return 0/1 int Keycde = replace_PosKey_with_Keycode(tokens[0]); tokens[0] = std::to_string(Keycde); @@ -128,6 +133,8 @@ void Split_US_To_3D_Vector(v_str_3D &all_US,v_str_1D completeList) { } } all_US.push_back(shift_states); + + // ? CHECK if ran OK, vector size is correct -> return 0/1 //printf("### 6 Split_US_To_3D_clearVector %li..%li..%li\n", all_US.size(), all_US[0].size(),all_US[0][0].size()); } @@ -191,6 +198,7 @@ int replace_PosKey_with_Keycode(std::string in) { void append_other_ToVector(v_str_3D &All_Vector,GdkKeymap * keymap) { // create a 2D vector all fill0ed with "--" and push to 3D-Vector + // ? CHECK if ran OK-> return 0/1 v_str_2D Other_Vector2D = create_empty_2D(All_Vector[0].size(),All_Vector[0][0].size()); All_Vector.push_back(Other_Vector2D); @@ -206,6 +214,7 @@ void append_other_ToVector(v_str_3D &All_Vector,GdkKeymap * keymap) { All_Vector[1][i][1+1] = GetKeyvalsFromKeymap(keymap,stoi(All_Vector[1][i][0]),1); //shift state: shifted:1 //printf("Keycodes US->Other: %d(US): %s %s ---- (other):%s, %s, %s \n",stoi(All_Vector[1][i][0]),All_Vector[0][i][1].c_str(),All_Vector[0][i][2].c_str(),All_Vector[1][i][1].c_str(),All_Vector[1][i][2].c_str(),All_Vector[1][i][3].c_str()); } + // ? CHECK if ran OK, vector size is correct -> return 0/1 } v_str_2D create_empty_2D( int dim_rows,int dim_shifts) @@ -246,6 +255,7 @@ int GetKeyvalsFromKeymap(GdkKeymap *keymap, guint keycode, int shift_state_pos) void extract_difference( v_str_3D &All_Vector) { + // ? CHECK if ran OK-> return 0/1 // TODO define which Folder; find better name std::ofstream Map_File("Map_US.txt"); std::string diff =" "; @@ -265,11 +275,12 @@ void extract_difference( v_str_3D &All_Vector) diff =" "; else diff =" *** "; - - std::cout << All_Vector[0][k][0] << "\t " <<+(*(All_Vector[0][k][1].c_str()))<< "\t("<< All_Vector[0][k][1] <<")"< Other: "<< std::setw(5)< US: "<< std::setw(5)< " << All_Vector[0][i][0] <<"\n"; return All_Vector[0][i][0] ; } @@ -325,6 +339,7 @@ std::string getKeyNrOf_OtherChar(std::string in , v_str_3D &All_Vector) { for( int i=0; i< (int)All_Vector[1].size()-1;i++) { for( int j=0; j< (int)All_Vector[1][0].size()-1;j++) { if ( All_Vector[1][i][j] == in ) { + // ? CHECK if index exists std::cout << "KeyNr of Other char : \t"<< All_Vector[1][i][j] << " -> " << All_Vector[1][i][0] <<"\n"; return All_Vector[1][i][0] ; } @@ -334,7 +349,7 @@ std::string getKeyNrOf_OtherChar(std::string in , v_str_3D &All_Vector) { } bool test(v_str_3D &V) { - +// ? CHECK if index exists printf("\n+++++++++ print some characters of US and Other +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"); for ( int k=13; k<43; k++) { @@ -378,7 +393,7 @@ std::string diff; void print_simple_map_US(v_str_3D &All_Vector, int shiftstate){ std::string out,diff; - + // ? CHECK if ran OK-> return 0/1 printf("-----------------------------------------------------------------------------------------------------------------------------------------------\n"); for ( int i=0; i< (int)All_Vector[0].size();i++) { out =get_Other_Char_FromUS(All_Vector[0][i][shiftstate], All_Vector); @@ -387,14 +402,13 @@ void print_simple_map_US(v_str_3D &All_Vector, int shiftstate){ void print_simple_map_Other(v_str_3D &All_Vector, int shiftstate){ std::string out, diff; - + // ? CHECK if ran OK-> return 0/1 printf("-----------------------------------------------------------------------------------------------------------------------------------------------\n"); for ( int i=0; i< (int)All_Vector[0].size();i++) { out = get_US_Char_FromOther(All_Vector[0][i][shiftstate], All_Vector); } } //-------------------------------------- - int main(gint argc, gchar *argv[]) { gdk_init(&argc, &argv); @@ -427,7 +441,7 @@ int main(gint argc, gchar *argv[]) //test_in_out(All_Vector); //print_simple_map_US(All_Vector,1); // 1 = non-shift - //print_simple_map_Other(All_Vector,1); // 1 = non-shift + //print_simple_map_Other(All_Vector,1); // 1 = non-shift gdk_display_close(display); From b8554c68db5897df660968278d7e309066cc4c31 Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 7 Jun 2023 18:40:09 +0200 Subject: [PATCH 15/16] feature(Linux): mcompile : new function testspecific_Characters , gitignore X_bak_foldercosmetics, comments --- .gitignore | 1 + linux/mcompile/keymap/keymap.cpp | 17 ++++++++-- linux/mcompile/keymap/keymap.h | 56 +++++++++++++++++--------------- 3 files changed, 45 insertions(+), 29 deletions(-) diff --git a/.gitignore b/.gitignore index 0abec10c3b1..a8a74b95f58 100644 --- a/.gitignore +++ b/.gitignore @@ -198,3 +198,4 @@ lcov.info # /developer/src/test/auto/kmcomp/*.kvk # /developer/src/test/auto/kmcomp/*.kvk* # /developer/src/test/auto/kmcomp/*.txt +/linux/mcompile/keymap/X_bak diff --git a/linux/mcompile/keymap/keymap.cpp b/linux/mcompile/keymap/keymap.cpp index 2101ac12ad6..397be17f6c2 100644 --- a/linux/mcompile/keymap/keymap.cpp +++ b/linux/mcompile/keymap/keymap.cpp @@ -242,6 +242,8 @@ int GetKeyvalsFromKeymap(GdkKeymap *keymap, guint keycode, int shift_state_pos) if (!gdk_keymap_get_entries_for_keycode(keymap, keycode, &maps, &keyvals, &count)) return 0; + //if(!gdk_wayland_keymap_get_entries_for_keycode(keymap, keycode, &maps, &keyvals, &count)) + // return 0; if (!(shift_state_pos < count)) return 0; @@ -408,6 +410,17 @@ void print_simple_map_Other(v_str_3D &All_Vector, int shiftstate){ out = get_US_Char_FromOther(All_Vector[0][i][shiftstate], All_Vector); } } + +void test_specific_Characters(v_str_3D &All_Vector){ + printf("-----------------------------------------------------------------------------------------------------------------------------------------------\n"); + v_str_1D in {"a", "b", "m", "w", "x", "y", "z"}; + std::string out; + for( int i=0; i< (int) in.size()-1; i++) { + out = get_Other_Char_FromUS(in[i], All_Vector); + } +} + + //-------------------------------------- int main(gint argc, gchar *argv[]) { @@ -442,9 +455,9 @@ int main(gint argc, gchar *argv[]) //print_simple_map_US(All_Vector,1); // 1 = non-shift //print_simple_map_Other(All_Vector,1); // 1 = non-shift - + test_specific_Characters(All_Vector); gdk_display_close(display); - printf("-°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° end\n"); + printf("°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° end\n"); return 0; } diff --git a/linux/mcompile/keymap/keymap.h b/linux/mcompile/keymap/keymap.h index 87627c4954f..cfbd5dc1df9 100644 --- a/linux/mcompile/keymap/keymap.h +++ b/linux/mcompile/keymap/keymap.h @@ -1,58 +1,58 @@ // In ths program we use a 3D-Vector Vector[language][Keys][Shiftstates] +#pragma once - +#include +#include #include -#include -#include -#include +#include #include #include -#include +#include +#include +#include + +#include "mc_kmxfile.h" +#include "mc_savekeyboard.h" -typedef std::vector v_str_1D; -typedef std::vector > v_str_2D; +typedef std::vector v_str_1D; +typedef std::vector > v_str_2D; typedef std::vector > > v_str_3D; - + int shift_state_count = 2; // use shiftstate : no shift, shift // read configuration file, split and write to 3D-Vector (Data for US on [0][ ][ ] ) -void write_US_ToVector( v_str_3D &vec,std::string language, const char* text) ; +void write_US_ToVector(v_str_3D &vec, std::string language, const char *text); -//1. step: read complete Row of Configuration file US -void CreateCompleteRow_US(v_str_1D &complete_List ,FILE* fpp, const char* text, std::string language); +// 1. step: read complete Row of Configuration file US +void CreateCompleteRow_US(v_str_1D &complete_List, FILE *fpp, const char *text, std::string language); -//2nd step: write contents to 3D vector -void Split_US_To_3D_Vector(v_str_3D &all_US,v_str_1D completeList); +// 2nd step: write contents to 3D vector +void Split_US_To_3D_Vector(v_str_3D &all_US, v_str_1D completeList); // replace Name of Key (e.g. ) wih Keycode ( e.g. 15 ) -int replace_PosKey_with_Keycode(std::string in); - - +int replace_PosKey_with_Keycode(std::string in); // append characters using GDK to 3D-Vector (Data for Other Language on [1][ ][ ] ) -void append_other_ToVector(v_str_3D &All_Vector,GdkKeymap * keymap); +void append_other_ToVector(v_str_3D &All_Vector, GdkKeymap *keymap); // create an empty 2D vector containing "--" in all fields -v_str_2D create_empty_2D( int dim_rows,int dim_shifts); +v_str_2D create_empty_2D(int dim_rows, int dim_shifts); // find Keyvals to fill into 2D-Vector of Other Language int GetKeyvalsFromKeymap(GdkKeymap *keymap, guint keycode, int shift_state_pos); - -// print both sets of characters (US and OtherLanguage) to console and file for comparison -void extract_difference(v_str_3D &All_Vector ) ; - +// print both sets of characters (US and OtherLanguage) to console and file for comparison +void extract_difference(v_str_3D &All_Vector); // get mapped key from Other (Other->US) -std::string get_Other_Char_FromUS( std::string in , v_str_3D &All_Vector); +std::string get_Other_Char_FromUS(std::string in, v_str_3D &All_Vector); // get mapped key from US->Other (US->Other) -std::string get_US_Char_FromOther(std::string in , v_str_3D &All_Vector); +std::string get_US_Char_FromOther(std::string in, v_str_3D &All_Vector); // get KeyNr from US -std::string getKeyNrOf_USChar(std::string in , v_str_3D &All_Vector); +std::string getKeyNrOf_USChar(std::string in, v_str_3D &All_Vector); // get KeyNr from Other -std::string getKeyNrOf_OtherChar(std::string in , v_str_3D &All_Vector); - +std::string getKeyNrOf_OtherChar(std::string in, v_str_3D &All_Vector); // for testing/debugging - may be deleted later // prints out a 1:1 mapping US->Other @@ -63,3 +63,5 @@ void print_simple_map_Other(v_str_3D &All_Vector, int shiftstate); void test_in_out(v_str_3D &All_Vector); // testing of Vector contents ( first row of US and Other) bool test(v_str_3D &V); +// writing out mapping of some characters: a,b,m,w,x,y,z +void test_specific_Characters(v_str_3D &All_Vector); From ae80e6f2a516936956d229087000948cef41c50e Mon Sep 17 00:00:00 2001 From: Sabine Date: Wed, 7 Jun 2023 19:09:12 +0200 Subject: [PATCH 16/16] feature(Linux): mcompile : copy files to mcompiles/keymap which may be needed; ; replace some DataTypes --- linux/mcompile/keymap/km_types.h | 88 +++ linux/mcompile/keymap/kmx_file.h | 384 +++++++++ linux/mcompile/keymap/mc_kmxfile.cpp | 297 +++++++ linux/mcompile/keymap/mc_kmxfile.h | 147 ++++ linux/mcompile/keymap/mc_savekeyboard.cpp | 423 ++++++++++ linux/mcompile/keymap/mc_savekeyboard.h | 18 + linux/mcompile/keymap/mcompile.cpp | 924 ++++++++++++++++++++++ linux/mcompile/keymap/mcompile.h | 51 ++ 8 files changed, 2332 insertions(+) create mode 100644 linux/mcompile/keymap/km_types.h create mode 100644 linux/mcompile/keymap/kmx_file.h create mode 100644 linux/mcompile/keymap/mc_kmxfile.cpp create mode 100644 linux/mcompile/keymap/mc_kmxfile.h create mode 100644 linux/mcompile/keymap/mc_savekeyboard.cpp create mode 100644 linux/mcompile/keymap/mc_savekeyboard.h create mode 100644 linux/mcompile/keymap/mcompile.cpp create mode 100644 linux/mcompile/keymap/mcompile.h diff --git a/linux/mcompile/keymap/km_types.h b/linux/mcompile/keymap/km_types.h new file mode 100644 index 00000000000..5e6c25e8136 --- /dev/null +++ b/linux/mcompile/keymap/km_types.h @@ -0,0 +1,88 @@ +#pragma once +#include + +#include + +/* +#if defined(_WIN32) || defined(_WIN64) +#define snprintf _snprintf +#define vsnprintf _vsnprintf +#define strcasecmp _stricmp +#define strncasecmp _strnicmp +#endif +*/ + +#if defined(__LP64__) || defined(_LP64) +/* 64-bit, g++ */ +#define KMX_64BIT +#endif + +#if defined(_WIN64) && !defined(USE_64) +/* 64-bit, Windows */ +#define KMX_64BIT +#endif + +typedef uint32_t KMX_DWORD; +typedef int32_t KMX_BOOL; +typedef uint8_t KMX_BYTE; +typedef uint16_t KMX_WORD; + +#if defined(__cplusplus) +typedef char16_t km_kbp_cp; +typedef char32_t km_kbp_usv; +#else +typedef uint16_t km_kbp_cp; // code point +typedef uint32_t km_kbp_usv; // Unicode Scalar Value +#endif + +typedef km_kbp_cp KMX_WCHAR; // wc, 16-bit UNICODE character + +typedef wchar_t WCHAR; // _S2 needs to be removed/ wchart-> char16 +typedef WCHAR KMX_WCHART; // _S2 needs to be removed/ wchart-> char16 +typedef KMX_WCHAR* PKMX_WCHAR; // _S2 +typedef wchar_t* PWSTR; // _S2 needs to be removed/ wchart-> char16 +typedef PWSTR PKMX_WCHART; // _S2 needs to be removed/ wchart-> char16 + +typedef wchar_t* LPKMX_WCHART; // _S2 needs to be removed/ wchart-> char16 + +typedef char* LPSTR; // _S2 needs to be removed? +typedef LPSTR LPKMX_STR; // _S2 needs to be removed? + +typedef uint8_t* LPBYTE; // _S2 needs to be removed/? +typedef LPBYTE LPKMX_BYTE; // _S2 needs to be removed? + +typedef uint8_t* PBYTE; // _S2 needs to be removed/? +typedef PBYTE PKMX_BYTE; // _S2 needs to be removed? + + // _S2 LPKEYBOARD ok to leave as is?? + +typedef char KMX_CHAR; // _S2 needs to be removed/? +typedef char* PKMX_STR; // _S2 needs to be removed/? + +typedef KMX_CHAR* PKMX_CHAR; // _S2 needs to be removed/? + +typedef uint32_t KMX_UINT; + +typedef KMX_BYTE* PKMX_BYTE; +typedef KMX_WORD* PKMX_WORD; +typedef KMX_DWORD* PKMX_DWORD; + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +// Macros and types to support char16_t vs wchar_t depending on project + +#ifdef USE_CHAR16_T +#define lpuch(x) u ## x +typedef km_kbp_cp KMX_UCHAR; +#else +#define lpuch(x) L ## x +typedef wchar_t KMX_UCHAR; +#endif + +typedef KMX_UCHAR* KMX_PUCHAR; diff --git a/linux/mcompile/keymap/kmx_file.h b/linux/mcompile/keymap/kmx_file.h new file mode 100644 index 00000000000..998c9780072 --- /dev/null +++ b/linux/mcompile/keymap/kmx_file.h @@ -0,0 +1,384 @@ +/* + Copyright: Copyright (C) 2003-2018 SIL International. + Authors: mcdurdin +*/ + +#pragma once + +#include + +#ifdef KMN_KBP +// TODO: move this to a common namespace keyman::common::kmx_file or similar in the future +namespace km { +namespace kbp { +namespace kmx { +#endif + +#define KMX_MAX_ALLOWED_FILE_SIZE (128 * 1024 * 1024) /* 128MB */ +/* */ + +#define KEYMAN_LAYOUT_DEFAULT 0x000005FE + +#define KEYMANID_NONKEYMAN 0xFFFFFFFF +#define KEYMANID_IGNORE 0xFFFFFFFE +#define KEYMANID_INVALID 0xFFFFFFFD + +/* Shift flags for hotkeys (version 1.0) */ + +#define SHIFTFLAG 0x2000 +#define CTRLFLAG 0x4000 +#define ALTFLAG 0x8000 + +/* Miscellaneous flags and defines */ + +#define MAXGROUPS 128 + +/* File version identifiers */ + +#define VERSION_30 0x00000300 +#define VERSION_31 0x00000301 +#define VERSION_32 0x00000302 +#define VERSION_40 0x00000400 +#define VERSION_50 0x00000500 +#define VERSION_501 0x00000501 +#define VERSION_60 0x00000600 +#define VERSION_70 0x00000700 +#define VERSION_80 0x00000800 +#define VERSION_90 0x00000900 +#define VERSION_100 0x00000A00 +#define VERSION_140 0x00000E00 +#define VERSION_150 0x00000F00 + +#define VERSION_160 0x00001000 + +#define VERSION_MIN VERSION_50 +#define VERSION_MAX VERSION_160 + +// +// Backspace types +// + +#define BK_DEFAULT 0 +#define BK_DEADKEY 1 + +// Different begin types +#define BEGIN_ANSI 0 +#define BEGIN_UNICODE 1 +#define BEGIN_NEWCONTEXT 2 +#define BEGIN_POSTKEYSTROKE 3 + +#define TSS_NONE 0 +#define TSS_BITMAP 1 +#define TSS_COPYRIGHT 2 +#define TSS_HOTKEY 3 +#define TSS_LANGUAGE 4 +#define TSS_LAYOUT 5 +#define TSS_MESSAGE 6 +#define TSS_NAME 7 +#define TSS_VERSION 8 +#define TSS_CAPSONONLY 9 +#define TSS_CAPSALWAYSOFF 10 +#define TSS_SHIFTFREESCAPS 11 +#define TSS_LANGUAGENAME 12 + +#define TSS_CALLDEFINITION 13 +#define TSS_CALLDEFINITION_LOADFAILED 14 + +#define TSS_ETHNOLOGUECODE 15 + +#define TSS_DEBUG_LINE 16 + +#define TSS_MNEMONIC 17 + +#define TSS_INCLUDECODES 18 + +#define TSS_OLDCHARPOSMATCHING 19 + +#define TSS_COMPILEDVERSION 20 +#define TSS_KEYMANCOPYRIGHT 21 + +#define TSS_CUSTOMKEYMANEDITION 22 +#define TSS_CUSTOMKEYMANEDITIONNAME 23 + +/* Keyman 7.0 system stores */ + +#define TSS__KEYMAN_60_MAX 23 + +#define TSS_VISUALKEYBOARD 24 +#define TSS_KMW_RTL 25 +#define TSS_KMW_HELPFILE 26 +#define TSS_KMW_HELPTEXT 27 +#define TSS_KMW_EMBEDJS 28 + +#define TSS_WINDOWSLANGUAGES 29 + +#define TSS__KEYMAN_70_MAX 29 + +/* Keyman 8.0 system stores */ + +#define TSS_COMPARISON 30 + +#define TSS__KEYMAN_80_MAX 30 + +/* Keyman 9.0 system stores */ + +#define TSS_PLATFORM 31 +#define TSS_BASELAYOUT 32 +#define TSS_LAYER 33 + +#define TSS_PLATFORM_NOMATCH 0x8001 // Reserved for internal use - after platform statement is run, set to either TSS_PLATFORM_NOMATCH or TSS_PLATFORM_MATCH +#define TSS_PLATFORM_MATCH 0x8002 // Reserved for internal use - as the result will never change for the lifetime of the process. + +#define TSS_VKDICTIONARY 34 // Dictionary of virtual key names for v9 dynamic layouts +#define TSS_LAYOUTFILE 35 // Keyman 9 layer-based JSON OSK +#define TSS_KEYBOARDVERSION 36 // &keyboardversion system store // I4140 +#define TSS_KMW_EMBEDCSS 37 + +#define TSS_TARGETS 38 + +#define TSS__KEYMAN_90_MAX 38 + +/* Keyman 14.0 system stores */ + +#define TSS_CASEDKEYS 39 + +#define TSS__KEYMAN_140_MAX 39 + +/* Keyman 15.0 system stores */ + +#define TSS_BEGIN_NEWCONTEXT 40 +#define TSS_BEGIN_POSTKEYSTROKE 41 +#define TSS_NEWLAYER 42 +#define TSS_OLDLAYER 43 + +#define TSS__KEYMAN_150_MAX 43 + +#define TSS__MAX 43 + +/* wm_keyman_control_internal message control codes */ + +#define KMCI_SELECTKEYBOARD 3 // I3933 +#define KMCI_SELECTKEYBOARD_TSF 4 // I3933 +#define KMCI_GETACTIVEKEYBOARD 5 // I3933 +#define KMCI_SETFOREGROUND 6 // I3933 +#define KMCI_SELECTKEYBOARD_BACKGROUND 7 // I4271 +#define KMCI_SELECTKEYBOARD_BACKGROUND_TSF 8 // I4271 + +#define FILEID_COMPILED 0x5354584B + +#define SZMAX_LANGUAGENAME 80 +#define SZMAX_KEYBOARDNAME 80 +#define SZMAX_COPYRIGHT 256 +#define SZMAX_MESSAGE 1024 + +#define UC_SENTINEL 0xFFFF +#define UC_SENTINEL_EXTENDEDEND 0x10 // was ((CODE_LASTCODE)+1)... what was I thinking? + +#define U_UC_SENTINEL u"\uFFFF" + +/* + * VK__MAX defines the highest virtual key code defined in the system = 0xFF. Custom VK codes start at 256 + */ +#define VK__MAX 255 + +#define CODE_ANY 0x01 +#define CODE_INDEX 0x02 +#define CODE_CONTEXT 0x03 +#define CODE_NUL 0x04 +#define CODE_USE 0x05 +#define CODE_RETURN 0x06 +#define CODE_BEEP 0x07 +#define CODE_DEADKEY 0x08 +// 0x09 = bkspace.-- we don't need to keep this separate though with UC_SENTINEL +#define CODE_EXTENDED 0x0A +//#define CODE_EXTENDEDEND 0x0B deprecated +#define CODE_SWITCH 0x0C +#define CODE_KEY 0x0D +#define CODE_CLEARCONTEXT 0x0E +#define CODE_CALL 0x0F +// UC_SENTINEL_EXTENDEDEND 0x10 +#define CODE_CONTEXTEX 0x11 + +#define CODE_NOTANY 0x12 + +#define CODE_KEYMAN70_LASTCODE 0x12 + +#define CODE_SETOPT 0x13 +#define CODE_IFOPT 0x14 +#define CODE_SAVEOPT 0x15 +#define CODE_RESETOPT 0x16 + +#define CODE_KEYMAN80_LASTCODE 0x16 + +/* Keyman 9.0 codes */ + +#define CODE_IFSYSTEMSTORE 0x17 +#define CODE_SETSYSTEMSTORE 0x18 + +#define CODE_LASTCODE 0x18 + +#define U_CODE_ANY u"\u0001" +#define U_CODE_INDEX u"\u0002" +#define U_CODE_CONTEXT u"\u0003" +#define U_CODE_NUL u"\u0004" +#define U_CODE_USE u"\u0005" +#define U_CODE_RETURN u"\u0006" +#define U_CODE_BEEP u"\u0007" +#define U_CODE_DEADKEY u"\u0008" +#define U_CODE_EXTENDED u"\u000A" +#define U_CODE_SWITCH u"\u000C" +#define U_CODE_CLEARCONTEXT u"\u000E" +#define U_CODE_CALL u"\u000F" +#define U_CODE_EXTENDEDEND u"\u0010" +#define U_CODE_CONTEXTEX u"\u0011" +#define U_CODE_NOTANY u"\u0012" +#define U_CODE_SETOPT u"\u0013" +#define U_CODE_IFOPT u"\u0014" +#define U_CODE_SAVEOPT u"\u0015" +#define U_CODE_RESETOPT u"\u0016" +#define U_CODE_IFSYSTEMSTORE u"\u0017" +#define U_CODE_SETSYSTEMSTORE u"\u0018" + +#define C_CODE_ANY(store) U_UC_SENTINEL U_CODE_ANY store +#define C_CODE_INDEX(val1, val2) U_UC_SENTINEL U_CODE_INDEX val1 val2 +#define C_CODE_CONTEXT() U_UC_SENTINEL U_CODE_CONTEXT +#define C_CODE_NUL() U_UC_SENTINEL U_CODE_NUL +#define C_CODE_USE(val) U_UC_SENTINEL U_CODE_USE val +#define C_CODE_RETURN() U_UC_SENTINEL U_CODE_RETURN +#define C_CODE_BEEP() U_UC_SENTINEL U_CODE_BEEP +#define C_CODE_DEADKEY(deadkey) U_UC_SENTINEL U_CODE_DEADKEY deadkey +#define C_CODE_EXTENDED(varargs) U_UC_SENTINEL U_CODE_EXTENDED varargs +#define C_CODE_SWITCH(val) U_UC_SENTINEL U_CODE_SWITCH val +#define C_CODE_CLEARCONTEXT() U_UC_SENTINEL U_CODE_CLEARCONTEXT +#define C_CODE_CALL(val) U_UC_SENTINEL U_CODE_CALL val +#define C_CODE_CONTEXTEX(val) U_UC_SENTINEL U_CODE_CONTEXTEX val +#define C_CODE_NOTANY(val) U_UC_SENTINEL U_CODE_NOTANY val +#define C_CODE_SETOPT(val1, val2) U_UC_SENTINEL U_CODE_SETOPT val1 val2 +#define C_CODE_IFOPT(opt, val1, val2) U_UC_SENTINEL U_CODE_IFOPT opt val1 val2 +#define C_CODE_SAVEOPT(opt) U_UC_SENTINEL U_CODE_SAVEOPT opt +#define C_CODE_RESETOPT(opt) U_UC_SENTINEL U_CODE_RESETOPT opt +#define C_CODE_IFSYSTEMSTORE(store, val1, val2) U_UC_SENTINEL U_CODE_IFSYSTEMSTORE store val1 val2 +#define C_CODE_SETSYSTEMSTORE(store, val) U_UC_SENTINEL U_CODE_SETSYSTEMSTORE store val + +#define KF_SHIFTFREESCAPS 0x0001 +#define KF_CAPSONONLY 0x0002 +#define KF_CAPSALWAYSOFF 0x0004 +#define KF_LOGICALLAYOUT 0x0008 +#define KF_AUTOMATICVERSION 0x0010 + +// 16.0: Support for LDML Keyboards in KMXPlus file format +#define KF_KMXPLUS 0x0020 + +#define HK_ALT 0x00010000 +#define HK_CTRL 0x00020000 +#define HK_SHIFT 0x00040000 + +#define LCTRLFLAG 0x0001 // Left Control flag +#define RCTRLFLAG 0x0002 // Right Control flag +#define LALTFLAG 0x0004 // Left Alt flag +#define RALTFLAG 0x0008 // Right Alt flag +#define K_SHIFTFLAG 0x0010 // Either shift flag +#define K_CTRLFLAG 0x0020 // Either ctrl flag +#define K_ALTFLAG 0x0040 // Either alt flag +//#define K_METAFLAG 0x0080 // Either Meta-key flag (tentative). Not usable in keyboard rules; + // Used internally (currently, only by KMW) to ensure Meta-key + // shortcuts safely bypass rules + // Meta key = Command key on macOS, Windows key on Windows +#define CAPITALFLAG 0x0100 // Caps lock on +#define NOTCAPITALFLAG 0x0200 // Caps lock NOT on +#define NUMLOCKFLAG 0x0400 // Num lock on +#define NOTNUMLOCKFLAG 0x0800 // Num lock NOT on +#define SCROLLFLAG 0x1000 // Scroll lock on +#define NOTSCROLLFLAG 0x2000 // Scroll lock NOT on +#define ISVIRTUALKEY 0x4000 // It is a Virtual Key Sequence +#define VIRTUALCHARKEY 0x8000 // Keyman 6.0: Virtual Key Cap Sequence NOT YET + +#define K_MODIFIERFLAG 0x007F +#define K_NOTMODIFIERFLAG 0xFF00 // I4548 + +struct COMP_STORE { + KMX_DWORD dwSystemID; + KMX_DWORD dpName; + KMX_DWORD dpString; + }; + +struct COMP_KEY { + KMX_WORD Key; + KMX_WORD _reserved; + KMX_DWORD Line; + KMX_DWORD ShiftFlags; + KMX_DWORD dpOutput; + KMX_DWORD dpContext; + }; + +struct COMP_GROUP { + KMX_DWORD dpName; + KMX_DWORD dpKeyArray; // [LPKEY] address of first item in key array + KMX_DWORD dpMatch; + KMX_DWORD dpNoMatch; + KMX_DWORD cxKeyArray; // in array entries + KMX_BOOL fUsingKeys; // group(xx) [using keys] <-- specified or not + }; + +struct COMP_KEYBOARD { + KMX_DWORD dwIdentifier; // 0000 Keyman compiled keyboard id + + KMX_DWORD dwFileVersion; // 0004 Version of the file - Keyman 4.0 is 0x0400 + + KMX_DWORD dwCheckSum; // 0008 As stored in keyboard. DEPRECATED as of 16.0 + KMX_DWORD KeyboardID; // 000C as stored in HKEY_LOCAL_MACHINE//system//currentcontrolset//control//keyboard layouts + KMX_DWORD IsRegistered; // 0010 + KMX_DWORD version; // 0014 keyboard version + + KMX_DWORD cxStoreArray; // 0018 in array entries + KMX_DWORD cxGroupArray; // 001C in array entries + + KMX_DWORD dpStoreArray; // 0020 [LPSTORE] address of first item in store array + KMX_DWORD dpGroupArray; // 0024 [LPGROUP] address of first item in group array + + KMX_DWORD StartGroup[2]; // 0028 index of starting groups [2 of them] + + KMX_DWORD dwFlags; // 0030 Flags for the keyboard file + + KMX_DWORD dwHotKey; // 0034 standard windows hotkey (hiword=shift/ctrl/alt stuff, loword=vkey) + + KMX_DWORD dpBitmapOffset; // 0038 offset of the bitmaps in the file + KMX_DWORD dwBitmapSize; // 003C size in bytes of the bitmaps +}; + +struct COMP_KEYBOARD_KMXPLUSINFO { + KMX_DWORD dpKMXPlus; // 0040 offset of KMXPlus data, header is first + KMX_DWORD dwKMXPlusSize; // 0044 size in bytes of entire KMXPlus data +}; + +/** + * Only valid if comp_keyboard.dwFlags&KF_KMXPLUS + */ +struct COMP_KEYBOARD_EX { + COMP_KEYBOARD header; // 0000 see COMP_KEYBOARD + COMP_KEYBOARD_KMXPLUSINFO kmxplus; // 0040 see COMP_KEYBOARD_EXTRA +}; + +typedef COMP_KEYBOARD *PCOMP_KEYBOARD; +typedef COMP_STORE *PCOMP_STORE; +typedef COMP_KEY *PCOMP_KEY; +typedef COMP_GROUP *PCOMP_GROUP; + +extern const int CODE__SIZE[]; +#define CODE__SIZE_MAX 5 + +#define KEYBOARDFILEHEADER_SIZE 64 +#define KEYBOARDFILESTORE_SIZE 12 +#define KEYBOARDFILEGROUP_SIZE 24 +#define KEYBOARDFILEKEY_SIZE 20 + +static_assert(sizeof(COMP_STORE) == KEYBOARDFILESTORE_SIZE, "COMP_STORE must be KEYBOARDFILESTORE_SIZE bytes"); +static_assert(sizeof(COMP_KEY) == KEYBOARDFILEKEY_SIZE, "COMP_KEY must be KEYBOARDFILEKEY_SIZE bytes"); +static_assert(sizeof(COMP_GROUP) == KEYBOARDFILEGROUP_SIZE, "COMP_GROUP must be KEYBOARDFILEGROUP_SIZE bytes"); +static_assert(sizeof(COMP_KEYBOARD) == KEYBOARDFILEHEADER_SIZE, "COMP_KEYBOARD must be KEYBOARDFILEHEADER_SIZE bytes"); + +#ifdef KMN_KBP +} // namespace kmx +} // namespace kbp +} // namespace km +#endif diff --git a/linux/mcompile/keymap/mc_kmxfile.cpp b/linux/mcompile/keymap/mc_kmxfile.cpp new file mode 100644 index 00000000000..e0a20c34ac7 --- /dev/null +++ b/linux/mcompile/keymap/mc_kmxfile.cpp @@ -0,0 +1,297 @@ + +#include "mc_kmxfile.h" + +KMX_DWORD TEST2; + +static KMX_BOOL LoadKeyboardFile(LPKMX_STR fileName, LPKEYBOARD *lpKeyboard); + +KMX_BOOL VerifyKeyboard(LPKMX_BYTE filebase, KMX_DWORD sz); + +LPKEYBOARD FixupKeyboard(PKMX_BYTE bufp, PKMX_BYTE base, KMX_DWORD dwFileSize); + +/*void Err(wchar_t *s) { + LogError(L"LoadKeyboard: %s, last error = %d\n", s, GetLastError()); +}*/ +/*BOOL LoadKeyboard(LPWSTR fileName, LPKEYBOARD *lpKeyboard) { + DWORD sz; + LPBYTE buf; + HANDLE hFile; + LPKEYBOARD kbp; + PBYTE filebase; + + if(!fileName || !lpKeyboard) { + Err(L"Bad Filename"); + return FALSE; + } + + hFile = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if(hFile == INVALID_HANDLE_VALUE) { + Err(L"Could not open file"); + return FALSE; + } + + sz = GetFileSize(hFile, NULL); + + buf = new BYTE[sz]; + + if(!buf) { + Err(L"Not allocmem"); + CloseHandle(hFile); + return FALSE; + } + + filebase = buf; + + if(!ReadFile(hFile, filebase, sz, &sz, NULL)) { + Err(L"errReadFile"); + CloseHandle(hFile); + delete[] buf; + return FALSE; + } + CloseHandle(hFile); + + if(!VerifyKeyboard(filebase, sz)) { + Err(L"errVerifyKeyboard"); + delete[] buf; + return FALSE; + } + + kbp = FixupKeyboard(buf, filebase, sz); + if(!kbp) { + Err(L"errFixupKeyboard"); + delete[] buf; + return FALSE; + } + + if(kbp->dwIdentifier != FILEID_COMPILED) { + Err(L"errNotFileID"); + delete[] buf; + return FALSE; + } + + *lpKeyboard = kbp; + return TRUE; +} +*/ + +/*PKMX_WCHART StringOffset(PKMX_BYTE base, KMX_DWORD offset) { + if(offset == 0) return NULL; + return (PKMX_WCHART)(base + offset); +}*/ + + +/*LPKEYBOARD FixupKeyboard(PBYTE bufp, PBYTE base, DWORD dwFileSize) { + UNREFERENCED_PARAMETER(dwFileSize); + + DWORD i, j; + PCOMP_KEYBOARD ckbp = (PCOMP_KEYBOARD) base; + PCOMP_GROUP cgp; + PCOMP_STORE csp; + PCOMP_KEY ckp; + LPKEYBOARD kbp = (LPKEYBOARD) bufp; + LPSTORE sp; + LPGROUP gp; + LPKEY kp; + + kbp->dpStoreArray = (LPSTORE) (base + ckbp->dpStoreArray); + kbp->dpGroupArray = (LPGROUP) (base + ckbp->dpGroupArray); + + for(sp = kbp->dpStoreArray, csp = (PCOMP_STORE) sp, i = 0; i < kbp->cxStoreArray; i++, sp++, csp++) { + sp->dpName = StringOffset(base, csp->dpName); + sp->dpString = StringOffset(base, csp->dpString); + } + + for(gp = kbp->dpGroupArray, cgp = (PCOMP_GROUP) gp, i = 0; i < kbp->cxGroupArray; i++, gp++, cgp++) { + gp->dpName = StringOffset(base, cgp->dpName); + gp->dpKeyArray = (LPKEY) (base + cgp->dpKeyArray); + if(cgp->dpMatch != NULL) gp->dpMatch = (PWSTR) (base + cgp->dpMatch); + if(cgp->dpNoMatch != NULL) gp->dpNoMatch = (PWSTR) (base + cgp->dpNoMatch); + + for(kp = gp->dpKeyArray, ckp = (PCOMP_KEY) kp, j = 0; j < gp->cxKeyArray; j++, kp++, ckp++) { + kp->dpOutput = (PWSTR) (base + ckp->dpOutput); + kp->dpContext = (PWSTR) (base + ckp->dpContext); + } + } + + return kbp; +} +*/ + + +/*BOOL VerifyKeyboard(LPBYTE filebase, DWORD sz) { + DWORD i; + PCOMP_KEYBOARD ckbp = (PCOMP_KEYBOARD) filebase; + PCOMP_STORE csp; + + // Check file version // + + if(ckbp->dwFileVersion < VERSION_MIN || + ckbp->dwFileVersion > VERSION_MAX) { + // Old or new version -- identify the desired program version // + for(csp = (PCOMP_STORE)(filebase + ckbp->dpStoreArray), i = 0; i < ckbp->cxStoreArray; i++, csp++) { + if(csp->dwSystemID == TSS_COMPILEDVERSION) { + wchar_t buf2[256]; + if(csp->dpString == 0) { + wsprintf(buf2, L"errWrongFileVersion:NULL"); + } else { + wsprintf(buf2, L"errWrongFileVersion:%10.10ls", StringOffset(filebase, csp->dpString)); + } + Err(buf2); + return FALSE; + } + } + Err(L"errWrongFileVersion"); + return FALSE; + } + + + return TRUE; +}*/ + + +//---------------------old---------------------------------------- +/* +#include "pch.h" + + +static BOOL LoadKeyboardFile(LPSTR fileName, LPKEYBOARD *lpKeyboard); +BOOL VerifyKeyboard(LPBYTE filebase, DWORD sz); + +LPKEYBOARD FixupKeyboard(PBYTE bufp, PBYTE base, DWORD dwFileSize); + +void Err(wchar_t *s) { + LogError(L"LoadKeyboard: %s, last error = %d\n", s, GetLastError()); +} + +BOOL LoadKeyboard(LPWSTR fileName, LPKEYBOARD *lpKeyboard) { + DWORD sz; + LPBYTE buf; + HANDLE hFile; + LPKEYBOARD kbp; + PBYTE filebase; + + if(!fileName || !lpKeyboard) { + Err(L"Bad Filename"); + return FALSE; + } + + hFile = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if(hFile == INVALID_HANDLE_VALUE) { + Err(L"Could not open file"); + return FALSE; + } + + sz = GetFileSize(hFile, NULL); + + buf = new BYTE[sz]; + + if(!buf) { + Err(L"Not allocmem"); + CloseHandle(hFile); + return FALSE; + } + + filebase = buf; + + if(!ReadFile(hFile, filebase, sz, &sz, NULL)) { + Err(L"errReadFile"); + CloseHandle(hFile); + delete[] buf; + return FALSE; + } + CloseHandle(hFile); + + if(!VerifyKeyboard(filebase, sz)) { + Err(L"errVerifyKeyboard"); + delete[] buf; + return FALSE; + } + + kbp = FixupKeyboard(buf, filebase, sz); + if(!kbp) { + Err(L"errFixupKeyboard"); + delete[] buf; + return FALSE; + } + + if(kbp->dwIdentifier != FILEID_COMPILED) { + Err(L"errNotFileID"); + delete[] buf; + return FALSE; + } + + *lpKeyboard = kbp; + return TRUE; +} + +PWCHAR StringOffset(PBYTE base, DWORD offset) { + if(offset == 0) return NULL; + return (PWCHAR)(base + offset); +} + +LPKEYBOARD FixupKeyboard(PBYTE bufp, PBYTE base, DWORD dwFileSize) { + UNREFERENCED_PARAMETER(dwFileSize); + + DWORD i, j; + PCOMP_KEYBOARD ckbp = (PCOMP_KEYBOARD) base; + PCOMP_GROUP cgp; + PCOMP_STORE csp; + PCOMP_KEY ckp; + LPKEYBOARD kbp = (LPKEYBOARD) bufp; + LPSTORE sp; + LPGROUP gp; + LPKEY kp; + + kbp->dpStoreArray = (LPSTORE) (base + ckbp->dpStoreArray); + kbp->dpGroupArray = (LPGROUP) (base + ckbp->dpGroupArray); + + for(sp = kbp->dpStoreArray, csp = (PCOMP_STORE) sp, i = 0; i < kbp->cxStoreArray; i++, sp++, csp++) { + sp->dpName = StringOffset(base, csp->dpName); + sp->dpString = StringOffset(base, csp->dpString); + } + + for(gp = kbp->dpGroupArray, cgp = (PCOMP_GROUP) gp, i = 0; i < kbp->cxGroupArray; i++, gp++, cgp++) { + gp->dpName = StringOffset(base, cgp->dpName); + gp->dpKeyArray = (LPKEY) (base + cgp->dpKeyArray); + if(cgp->dpMatch != NULL) gp->dpMatch = (PWSTR) (base + cgp->dpMatch); + if(cgp->dpNoMatch != NULL) gp->dpNoMatch = (PWSTR) (base + cgp->dpNoMatch); + + for(kp = gp->dpKeyArray, ckp = (PCOMP_KEY) kp, j = 0; j < gp->cxKeyArray; j++, kp++, ckp++) { + kp->dpOutput = (PWSTR) (base + ckp->dpOutput); + kp->dpContext = (PWSTR) (base + ckp->dpContext); + } + } + + return kbp; +} + +BOOL VerifyKeyboard(LPBYTE filebase, DWORD sz) { + DWORD i; + PCOMP_KEYBOARD ckbp = (PCOMP_KEYBOARD) filebase; + PCOMP_STORE csp; + + // Check file version // + + if(ckbp->dwFileVersion < VERSION_MIN || + ckbp->dwFileVersion > VERSION_MAX) { + // Old or new version -- identify the desired program version // + for(csp = (PCOMP_STORE)(filebase + ckbp->dpStoreArray), i = 0; i < ckbp->cxStoreArray; i++, csp++) { + if(csp->dwSystemID == TSS_COMPILEDVERSION) { + wchar_t buf2[256]; + if(csp->dpString == 0) { + wsprintf(buf2, L"errWrongFileVersion:NULL"); + } else { + wsprintf(buf2, L"errWrongFileVersion:%10.10ls", StringOffset(filebase, csp->dpString)); + } + Err(buf2); + return FALSE; + } + } + Err(L"errWrongFileVersion"); + return FALSE; + } + + + return TRUE; +} +*/ \ No newline at end of file diff --git a/linux/mcompile/keymap/mc_kmxfile.h b/linux/mcompile/keymap/mc_kmxfile.h new file mode 100644 index 00000000000..2d82db90b1e --- /dev/null +++ b/linux/mcompile/keymap/mc_kmxfile.h @@ -0,0 +1,147 @@ +#pragma once +#include "km_types.h" + +KMX_DWORD TEST; + +#ifndef _KMXFILE_H +#define _KMXFILE_H + +typedef struct tagSTORE { + KMX_DWORD dwSystemID; + PKMX_WCHART dpName; + PKMX_WCHART dpString; +} STORE, *LPSTORE; + + +typedef struct tagKEY { + KMX_WCHAR Key; + KMX_DWORD Line; + KMX_DWORD ShiftFlags; + PKMX_WCHART dpOutput; + PKMX_WCHART dpContext; +} KEY, *LPKEY; + + +typedef struct tagGROUP { + PKMX_WCHART dpName; + LPKEY dpKeyArray; // [LPKEY] address of first item in key array + PKMX_WCHART dpMatch; + PKMX_WCHART dpNoMatch; + KMX_DWORD cxKeyArray; // in array entries + KMX_BOOL fUsingKeys; // group(xx) [using keys] <-- specified or not +} GROUP, *LPGROUP; + + + +typedef struct tagKEYBOARD { + KMX_DWORD dwIdentifier; // Keyman compiled keyboard id + + KMX_DWORD dwFileVersion; // Version of the file - Keyman 4.0 is 0x0400 + + KMX_DWORD dwCheckSum; // As stored in keyboard. DEPRECATED as of 16.0 + KMX_DWORD xxkbdlayout; // as stored in HKEY_LOCAL_MACHINE//system//currentcontrolset//control//keyboard layouts + KMX_DWORD IsRegistered; // layout id, from same registry key + KMX_DWORD version; // keyboard version + + KMX_DWORD cxStoreArray; // in array entries + KMX_DWORD cxGroupArray; // in array entries + + LPSTORE dpStoreArray; // [LPSTORE] address of first item in store array, from start of file + LPGROUP dpGroupArray; // [LPGROUP] address of first item in group array, from start of file + + KMX_DWORD StartGroup[2]; // index of starting groups [2 of them] + // Ansi=0, Unicode=1 + + KMX_DWORD dwFlags; // Flags for the keyboard file + + KMX_DWORD dwHotKey; // standard windows hotkey (hiword=shift/ctrl/alt stuff, loword=vkey) + + //PKMX_WCHART dpName; // offset of name + //PKMX_WCHART dpLanguageName; // offset of language name; + //PKMX_WCHART dpCopyright; // offset of copyright + //PKMX_WCHART dpMessage; // offset of message in Keyboard About box + + KMX_DWORD dpBitmapOffset; // 0038 offset of the bitmaps in the file + KMX_DWORD dwBitmapSize; // 003C size in bytes of the bitmaps + //HBITMAP hBitmap; // handle to the bitmap in the file; +} KEYBOARD, *LPKEYBOARD; + +KMX_BOOL LoadKeyboard(LPKMX_WCHART fileName, LPKEYBOARD *lpKeyboard); // _S2 LPKEYBOARD ok to leave as is?? + +#endif + + + + + + +//---------------------old---------------------------------------- +/* +#include + +#ifndef _KMXFILE_H +#define _KMXFILE_H + +typedef struct tagSTORE { + DWORD dwSystemID; + PWSTR dpName; + PWSTR dpString; +} STORE, *LPSTORE; + +typedef struct tagKEY { + WCHAR Key; + DWORD Line; + DWORD ShiftFlags; + PWSTR dpOutput; + PWSTR dpContext; +} KEY, *LPKEY; + + +typedef struct tagGROUP { + PWSTR dpName; + LPKEY dpKeyArray; // [LPKEY] address of first item in key array + PWSTR dpMatch; + PWSTR dpNoMatch; + DWORD cxKeyArray; // in array entries + BOOL fUsingKeys; // group(xx) [using keys] <-- specified or not +} GROUP, *LPGROUP; + + +typedef struct tagKEYBOARD { + DWORD dwIdentifier; // Keyman compiled keyboard id + + DWORD dwFileVersion; // Version of the file - Keyman 4.0 is 0x0400 + + DWORD dwCheckSum; // As stored in keyboard. DEPRECATED as of 16.0 + DWORD xxkbdlayout; // as stored in HKEY_LOCAL_MACHINE//system//currentcontrolset//control//keyboard layouts + DWORD IsRegistered; // layout id, from same registry key + DWORD version; // keyboard version + + DWORD cxStoreArray; // in array entries + DWORD cxGroupArray; // in array entries + + LPSTORE dpStoreArray; // [LPSTORE] address of first item in store array, from start of file + LPGROUP dpGroupArray; // [LPGROUP] address of first item in group array, from start of file + + DWORD StartGroup[2]; // index of starting groups [2 of them] + // Ansi=0, Unicode=1 + + DWORD dwFlags; // Flags for the keyboard file + + DWORD dwHotKey; // standard windows hotkey (hiword=shift/ctrl/alt stuff, loword=vkey) + + //PWSTR dpName; // offset of name + //PWSTR dpLanguageName; // offset of language name; + //PWSTR dpCopyright; // offset of copyright + //PWSTR dpMessage; // offset of message in Keyboard About box + + DWORD dpBitmapOffset; // 0038 offset of the bitmaps in the file + DWORD dwBitmapSize; // 003C size in bytes of the bitmaps + //HBITMAP hBitmap; // handle to the bitmap in the file; +} KEYBOARD, *LPKEYBOARD; + +BOOL LoadKeyboard(LPWSTR fileName, LPKEYBOARD *lpKeyboard); + +#endif +*/ + diff --git a/linux/mcompile/keymap/mc_savekeyboard.cpp b/linux/mcompile/keymap/mc_savekeyboard.cpp new file mode 100644 index 00000000000..497f2d4379d --- /dev/null +++ b/linux/mcompile/keymap/mc_savekeyboard.cpp @@ -0,0 +1,423 @@ +#include "mc_savekeyboard.h" + + +/*BOOL SaveKeyboard(LPKEYBOARD kbd, PWSTR filename) { + HANDLE hOutfile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); + if(hOutfile == INVALID_HANDLE_VALUE) { + LogError(L"Failed to create output file (%d)", GetLastError()); + return FALSE; + } + + DWORD err = WriteCompiledKeyboard(kbd, hOutfile, FALSE); + + CloseHandle(hOutfile); + + if(err != CERR_None) { + LogError(L"Failed to write compiled keyboard with error %d", err); + DeleteFile(filename); + return FALSE; + } + + return TRUE; +}*/ + +/*DWORD WriteCompiledKeyboard(LPKEYBOARD fk, HANDLE hOutfile, BOOL FSaveDebug) +{ + LPGROUP fgp; + LPSTORE fsp; + LPKEY fkp; + + PCOMP_KEYBOARD ck; + PCOMP_GROUP gp; + PCOMP_STORE sp; + PCOMP_KEY kp; + PBYTE buf; + DWORD size, offset; + DWORD i, j; + + // Calculate how much memory to allocate + + size = sizeof(COMP_KEYBOARD) + + fk->cxGroupArray * sizeof(COMP_GROUP) + + fk->cxStoreArray * sizeof(COMP_STORE) + + //wcslen(fk->szName)*2 + 2 + + //wcslen(fk->szCopyright)*2 + 2 + + //wcslen(fk->szLanguageName)*2 + 2 + + //wcslen(fk->szMessage)*2 + 2 + + fk->dwBitmapSize; + + for(i = 0, fgp = fk->dpGroupArray; i < fk->cxGroupArray; i++, fgp++) { + if(fgp->dpName) + size += wcslen(fgp->dpName)*2 + 2; + size += fgp->cxKeyArray * sizeof(COMP_KEY); + for(j = 0, fkp = fgp->dpKeyArray; j < fgp->cxKeyArray; j++, fkp++) { + size += wcslen(fkp->dpOutput)*2 + 2; + size += wcslen(fkp->dpContext)*2 + 2; + } + + if( fgp->dpMatch ) size += wcslen(fgp->dpMatch)*2 + 2; + if( fgp->dpNoMatch ) size += wcslen(fgp->dpNoMatch)*2 + 2; + } + + for(i = 0; i < fk->cxStoreArray; i++) + { + size += wcslen(fk->dpStoreArray[i].dpString)*2 + 2; + if(fk->dpStoreArray[i].dpName) + size += wcslen(fk->dpStoreArray[i].dpName)*2 + 2; + } + + buf = new BYTE[size]; + if(!buf) return CERR_CannotAllocateMemory; + memset(buf, 0, size); + + ck = (PCOMP_KEYBOARD) buf; + + ck->dwIdentifier = FILEID_COMPILED; + + ck->dwFileVersion = fk->dwFileVersion; + ck->dwCheckSum = 0; // No checksum in 16.0, see #7276 + ck->KeyboardID = fk->xxkbdlayout; + ck->IsRegistered = fk->IsRegistered; + ck->cxStoreArray = fk->cxStoreArray; + ck->cxGroupArray = fk->cxGroupArray; + ck->StartGroup[0] = fk->StartGroup[0]; + ck->StartGroup[1] = fk->StartGroup[1]; + ck->dwHotKey = fk->dwHotKey; + + ck->dwFlags = fk->dwFlags; + + offset = sizeof(COMP_KEYBOARD); + + //ck->dpLanguageName = offset; + //wcscpy((PWSTR)(buf + offset), fk->szLanguageName); + //offset += wcslen(fk->szLanguageName)*2 + 2; + + //ck->dpName = offset; + //wcscpy((PWSTR)(buf + offset), fk->szName); + //offset += wcslen(fk->szName)*2 + 2; + + //ck->dpCopyright = offset; + //wcscpy((PWSTR)(buf + offset), fk->szCopyright); + //offset += wcslen(fk->szCopyright)*2 + 2; + + //ck->dpMessage = offset; + //wcscpy((PWSTR)(buf + offset), fk->szMessage); + //offset += wcslen(fk->szMessage)*2 + 2; + + ck->dpStoreArray = offset; + sp = (PCOMP_STORE)(buf+offset); + fsp = fk->dpStoreArray; + offset += sizeof(COMP_STORE) * ck->cxStoreArray; + for(i = 0; i < ck->cxStoreArray; i++, sp++, fsp++) { + sp->dwSystemID = fsp->dwSystemID; + sp->dpString = offset; + wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fsp->dpString); // I3481 // I3641 + offset += wcslen(fsp->dpString)*2 + 2; + + if(!fsp->dpName) { + sp->dpName = 0; + } else { + sp->dpName = offset; + wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fsp->dpName); // I3481 // I3641 + offset += wcslen(fsp->dpName)*2 + 2; + } + } + + ck->dpGroupArray = offset; + gp = (PCOMP_GROUP)(buf+offset); + fgp = fk->dpGroupArray; + + offset += sizeof(COMP_GROUP) * ck->cxGroupArray; + + for(i = 0; i < ck->cxGroupArray; i++, gp++, fgp++) { + gp->cxKeyArray = fgp->cxKeyArray; + gp->fUsingKeys = fgp->fUsingKeys; + + gp->dpMatch = gp->dpNoMatch = 0; + + if(fgp->dpMatch) { + gp->dpMatch = offset; + wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fgp->dpMatch); // I3481 // I3641 + offset += wcslen(fgp->dpMatch)*2 + 2; + } + if(fgp->dpNoMatch) { + gp->dpNoMatch = offset; + wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fgp->dpNoMatch); // I3481 // I3641 + offset += wcslen(fgp->dpNoMatch)*2 + 2; + } + + if(fgp->dpName) { + gp->dpName = offset; + wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fgp->dpName); // I3481 // I3641 + offset += wcslen(fgp->dpName)*2 + 2; + } else { + gp->dpName = 0; + } + + gp->dpKeyArray = offset; + kp = (PCOMP_KEY) (buf + offset); + fkp = fgp->dpKeyArray; + offset += gp->cxKeyArray * sizeof(COMP_KEY); + for(j = 0; j < gp->cxKeyArray; j++, kp++, fkp++) { + kp->Key = fkp->Key; + kp->Line = fkp->Line; + kp->ShiftFlags = fkp->ShiftFlags; + kp->dpOutput = offset; + wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fkp->dpOutput); // I3481 // I3641 + offset += wcslen(fkp->dpOutput)*2 + 2; + + + kp->dpContext = offset; + wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fkp->dpContext); // I3481 // I3641 + offset += wcslen(fkp->dpContext)*2 + 2; + } + } + + if(fk->dwBitmapSize > 0) { + ck->dwBitmapSize = fk->dwBitmapSize; + ck->dpBitmapOffset = offset; + memcpy(buf + offset, ((PBYTE)fk) + fk->dpBitmapOffset, fk->dwBitmapSize); + offset += fk->dwBitmapSize; + } else { + ck->dwBitmapSize = 0; + ck->dpBitmapOffset = 0; + } + + if(offset != size) + { + delete[] buf; + return CERR_SomewhereIGotItWrong; + } + + WriteFile(hOutfile, buf, size, &offset, NULL); + + if(offset != size) + { + delete[] buf; + return CERR_UnableToWriteFully; + } + + delete[] buf; + + return CERR_None; +}*/ + + + + +//---------------------old---------------------------------------- +/*#include "pch.h" + +// These four errors are copied from kmn_compiler_errors.h, because WriteCompiledKeyboard is +// a clone of the compiler's equivalent function. However, the functions +// diverge, as mc_savekeyboard.cpp's version is copying from an existing +// compiled keyboard. The error codes have been kept consistent with those in +// kmn_compiler_errors.h +#define CERR_None 0x00000000 +#define CERR_CannotAllocateMemory 0x00008004 +#define CERR_UnableToWriteFully 0x00008007 +#define CERR_SomewhereIGotItWrong 0x00008009 + +DWORD WriteCompiledKeyboard(LPKEYBOARD fk, HANDLE hOutfile, BOOL FSaveDebug); + +BOOL SaveKeyboard(LPKEYBOARD kbd, PWSTR filename) { + HANDLE hOutfile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); + if(hOutfile == INVALID_HANDLE_VALUE) { + LogError(L"Failed to create output file (%d)", GetLastError()); + return FALSE; + } + + DWORD err = WriteCompiledKeyboard(kbd, hOutfile, FALSE); + + CloseHandle(hOutfile); + + if(err != CERR_None) { + LogError(L"Failed to write compiled keyboard with error %d", err); + DeleteFile(filename); + return FALSE; + } + + return TRUE; +} + +DWORD WriteCompiledKeyboard(LPKEYBOARD fk, HANDLE hOutfile, BOOL FSaveDebug) +{ + LPGROUP fgp; + LPSTORE fsp; + LPKEY fkp; + + PCOMP_KEYBOARD ck; + PCOMP_GROUP gp; + PCOMP_STORE sp; + PCOMP_KEY kp; + PBYTE buf; + DWORD size, offset; + DWORD i, j; + + // Calculate how much memory to allocate + + size = sizeof(COMP_KEYBOARD) + + fk->cxGroupArray * sizeof(COMP_GROUP) + + fk->cxStoreArray * sizeof(COMP_STORE) + + //wcslen(fk->szName)*2 + 2 + + //wcslen(fk->szCopyright)*2 + 2 + + //wcslen(fk->szLanguageName)*2 + 2 + + //wcslen(fk->szMessage)*2 + 2 + + fk->dwBitmapSize; + + for(i = 0, fgp = fk->dpGroupArray; i < fk->cxGroupArray; i++, fgp++) { + if(fgp->dpName) + size += wcslen(fgp->dpName)*2 + 2; + size += fgp->cxKeyArray * sizeof(COMP_KEY); + for(j = 0, fkp = fgp->dpKeyArray; j < fgp->cxKeyArray; j++, fkp++) { + size += wcslen(fkp->dpOutput)*2 + 2; + size += wcslen(fkp->dpContext)*2 + 2; + } + + if( fgp->dpMatch ) size += wcslen(fgp->dpMatch)*2 + 2; + if( fgp->dpNoMatch ) size += wcslen(fgp->dpNoMatch)*2 + 2; + } + + for(i = 0; i < fk->cxStoreArray; i++) + { + size += wcslen(fk->dpStoreArray[i].dpString)*2 + 2; + if(fk->dpStoreArray[i].dpName) + size += wcslen(fk->dpStoreArray[i].dpName)*2 + 2; + } + + buf = new BYTE[size]; + if(!buf) return CERR_CannotAllocateMemory; + memset(buf, 0, size); + + ck = (PCOMP_KEYBOARD) buf; + + ck->dwIdentifier = FILEID_COMPILED; + + ck->dwFileVersion = fk->dwFileVersion; + ck->dwCheckSum = 0; // No checksum in 16.0, see #7276 + ck->KeyboardID = fk->xxkbdlayout; + ck->IsRegistered = fk->IsRegistered; + ck->cxStoreArray = fk->cxStoreArray; + ck->cxGroupArray = fk->cxGroupArray; + ck->StartGroup[0] = fk->StartGroup[0]; + ck->StartGroup[1] = fk->StartGroup[1]; + ck->dwHotKey = fk->dwHotKey; + + ck->dwFlags = fk->dwFlags; + + offset = sizeof(COMP_KEYBOARD); + + //ck->dpLanguageName = offset; + //wcscpy((PWSTR)(buf + offset), fk->szLanguageName); + //offset += wcslen(fk->szLanguageName)*2 + 2; + + //ck->dpName = offset; + //wcscpy((PWSTR)(buf + offset), fk->szName); + //offset += wcslen(fk->szName)*2 + 2; + + //ck->dpCopyright = offset; + //wcscpy((PWSTR)(buf + offset), fk->szCopyright); + //offset += wcslen(fk->szCopyright)*2 + 2; + + //ck->dpMessage = offset; + //wcscpy((PWSTR)(buf + offset), fk->szMessage); + //offset += wcslen(fk->szMessage)*2 + 2; + + ck->dpStoreArray = offset; + sp = (PCOMP_STORE)(buf+offset); + fsp = fk->dpStoreArray; + offset += sizeof(COMP_STORE) * ck->cxStoreArray; + for(i = 0; i < ck->cxStoreArray; i++, sp++, fsp++) { + sp->dwSystemID = fsp->dwSystemID; + sp->dpString = offset; + wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fsp->dpString); // I3481 // I3641 + offset += wcslen(fsp->dpString)*2 + 2; + + if(!fsp->dpName) { + sp->dpName = 0; + } else { + sp->dpName = offset; + wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fsp->dpName); // I3481 // I3641 + offset += wcslen(fsp->dpName)*2 + 2; + } + } + + ck->dpGroupArray = offset; + gp = (PCOMP_GROUP)(buf+offset); + fgp = fk->dpGroupArray; + + offset += sizeof(COMP_GROUP) * ck->cxGroupArray; + + for(i = 0; i < ck->cxGroupArray; i++, gp++, fgp++) { + gp->cxKeyArray = fgp->cxKeyArray; + gp->fUsingKeys = fgp->fUsingKeys; + + gp->dpMatch = gp->dpNoMatch = 0; + + if(fgp->dpMatch) { + gp->dpMatch = offset; + wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fgp->dpMatch); // I3481 // I3641 + offset += wcslen(fgp->dpMatch)*2 + 2; + } + if(fgp->dpNoMatch) { + gp->dpNoMatch = offset; + wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fgp->dpNoMatch); // I3481 // I3641 + offset += wcslen(fgp->dpNoMatch)*2 + 2; + } + + if(fgp->dpName) { + gp->dpName = offset; + wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fgp->dpName); // I3481 // I3641 + offset += wcslen(fgp->dpName)*2 + 2; + } else { + gp->dpName = 0; + } + + gp->dpKeyArray = offset; + kp = (PCOMP_KEY) (buf + offset); + fkp = fgp->dpKeyArray; + offset += gp->cxKeyArray * sizeof(COMP_KEY); + for(j = 0; j < gp->cxKeyArray; j++, kp++, fkp++) { + kp->Key = fkp->Key; + kp->Line = fkp->Line; + kp->ShiftFlags = fkp->ShiftFlags; + kp->dpOutput = offset; + wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fkp->dpOutput); // I3481 // I3641 + offset += wcslen(fkp->dpOutput)*2 + 2; + + + kp->dpContext = offset; + wcscpy_s((PWSTR)(buf+offset), (size-offset) / sizeof(WCHAR), fkp->dpContext); // I3481 // I3641 + offset += wcslen(fkp->dpContext)*2 + 2; + } + } + + if(fk->dwBitmapSize > 0) { + ck->dwBitmapSize = fk->dwBitmapSize; + ck->dpBitmapOffset = offset; + memcpy(buf + offset, ((PBYTE)fk) + fk->dpBitmapOffset, fk->dwBitmapSize); + offset += fk->dwBitmapSize; + } else { + ck->dwBitmapSize = 0; + ck->dpBitmapOffset = 0; + } + + if(offset != size) + { + delete[] buf; + return CERR_SomewhereIGotItWrong; + } + + WriteFile(hOutfile, buf, size, &offset, NULL); + + if(offset != size) + { + delete[] buf; + return CERR_UnableToWriteFully; + } + + delete[] buf; + + return CERR_None; +} +*/ \ No newline at end of file diff --git a/linux/mcompile/keymap/mc_savekeyboard.h b/linux/mcompile/keymap/mc_savekeyboard.h new file mode 100644 index 00000000000..7ac15f4ff1a --- /dev/null +++ b/linux/mcompile/keymap/mc_savekeyboard.h @@ -0,0 +1,18 @@ +#pragma once + +#include "km_types.h" +KMX_DWORD TEST3; +// this file is all new _S2 + +//#include "../../../common/include/km_types.h" + + +#define CERR_None 0x00000000 +#define CERR_CannotAllocateMemory 0x00008004 +#define CERR_UnableToWriteFully 0x00008007 +#define CERR_SomewhereIGotItWrong 0x00008009 +/* +DWORD WriteCompiledKeyboard(LPKEYBOARD fk, HANDLE hOutfile, BOOL FSaveDebug); +BOOL SaveKeyboard(LPKEYBOARD kbd, PWSTR filename) ; +DWORD WriteCompiledKeyboard(LPKEYBOARD fk, HANDLE hOutfile, BOOL FSaveDebug); +*/ \ No newline at end of file diff --git a/linux/mcompile/keymap/mcompile.cpp b/linux/mcompile/keymap/mcompile.cpp new file mode 100644 index 00000000000..b990f02806c --- /dev/null +++ b/linux/mcompile/keymap/mcompile.cpp @@ -0,0 +1,924 @@ +/* + Name: mcompile + Copyright: Copyright (C) SIL International. + Documentation: + Description: + Create Date: 24 Apr 2014 + + Modified Date: 8 Apr 2015 + Authors: mcdurdin + Related Files: + Dependencies: + + Bugs: + Todo: + Notes: + History: 24 Apr 2014 - mcdurdin - I4174 - V9 - mcompile logs should be stored in diag folder + 16 Jun 2014 - mcdurdin - I4273 - V9.0 - Convert keyboards to Unicode before installing + 23 Jun 2014 - mcdurdin - I4279 - V9.0 - mcompile fails to start when converting keyboard to Unicode + 03 Aug 2014 - mcdurdin - I4353 - V9.0 - mnemonic layout recompiler mixes up deadkey rules + 03 Aug 2014 - mcdurdin - I4327 - V9.0 - Mnemonic layout compiler follow-up + 31 Dec 2014 - mcdurdin - I4549 - V9.0 - Mnemonic layout recompiler does not translate Lctrl Ralt for deadkeys correctly + 06 Feb 2015 - mcdurdin - I4552 - V9.0 - Add mnemonic recompile option to ignore deadkeys + 08 Apr 2015 - mcdurdin - I4651 - V9.0 - Mnemonic layout recompiler maps AltGr+VK_BKSLASH rather than VK_OEM_102 +*/ +// +// m-to-p.cpp : Defines the entry point for the console application. +// +// Note: this program deliberately leaks memory as it has a very short life cycle and managing the memory allocations +// for the subcomponents of the compiled keyboard is an unnecessary optimisation. Just so you know. +// + +#include "pch.h" +#include + +#include +#include +#include + +BOOL DoConvert(LPKEYBOARD kbd, PWSTR kbid, BOOL bDeadkeyConversion); +BOOL SaveKeyboard(LPKEYBOARD kbd, PWSTR filename); +bool ImportRules(WCHAR *kbid, LPKEYBOARD kp, std::vector *FDeadkeys, BOOL bDeadkeyConversion); // I4353 // I4327 +BOOL ConvertKeyboardToUnicode(LPKEYBOARD kbd); // I4273 +int run(int argc, wchar_t * argv[]); + +std::vector FDeadkeys; // I4353 + +#define KEYMAN_SENTRY_LOGGER_DESKTOP_ENGINE_MCOMPILE KEYMAN_SENTRY_LOGGER_DESKTOP_ENGINE ".mcompile" + +int wmain(int argc, wchar_t * argv[]) +{ + return keyman_sentry_wmain(false, KEYMAN_SENTRY_LOGGER_DESKTOP_ENGINE_MCOMPILE, argc, argv, run); +} + +int run(int argc, wchar_t * argv[]) +{ + if(argc < 3 || (argc < 5 && wcscmp(argv[1], L"-u") != 0)) { // I4273 + printf( + "Usage: mcompile -u infile.kmx outfile.kmx\n" + " mcompile [-d] infile.kmx kbdfile.dll kbid outfile.kmx\n" + " With -u parameter, converts keyboard from ANSI to Unicode\n" + " Otherwise, mcompile converts a Keyman mnemonic layout to a\n" + " positional one based on the Windows keyboard\n" + " layout file given by kbdfile.dll\n\n" + " kbid should be a hexadecimal number e.g. 409 for US English\n" + " -d convert deadkeys to plain keys\n"); // I4552 + + return 1; + } + + if(wcscmp(argv[1], L"-u") == 0) { // I4273 + wchar_t *infile = argv[2], *outfile = argv[3]; + + LPKEYBOARD kmxfile; + + if(!LoadKeyboard(infile, &kmxfile)) { + LogError(L"Failed to load keyboard (%d)", GetLastError()); + return 3; + } + + if(ConvertKeyboardToUnicode(kmxfile)) { + SaveKeyboard(kmxfile, outfile); + } + + //DeleteReallocatedPointers(kmxfile); :TODO + delete[] kmxfile; + + return 0; // I4279 + } + + int bDeadkeyConversion = wcscmp(argv[1], L"-d") == 0; // I4552 + int n = (bDeadkeyConversion ? 2 : 1); + + wchar_t *infile = argv[n], *indll = argv[n+1], *kbid = argv[n+2], *outfile = argv[n+3]; + + wprintf(L"mcompile%ls \"%ls\" \"%ls\" \"%ls\" \"%ls\"\n", bDeadkeyConversion ? L" -d":L"", infile, indll, kbid, outfile); // I4174 + + // 1. Load the keyman keyboard file + + // 2. For each key on the system layout, determine its output character and perform a + // 1-1 replacement on the keyman keyboard of that character with the base VK + shift + // state. This fixup will transform the char to a vk, which will avoid any issues + // with the key. + // + // --> deadkeys we will attack after the POC + // + // For each deadkey, we need to determine its possible outputs. Then we generate a VK + // rule for that deadkey, e.g. [K_LBRKT] > dk(c101) + // + // Next, update each rule that references the output from that deadkey to add an extra + // context deadkey at the end of the context match, e.g. 'a' dk(c101) + [K_SPACE] > 'b'. + // This will require a memory layout change for the .kmx file, plus fixups on the + // context+output index offsets + // + // --> virtual character keys + // + // [CTRL ' '] : we look at the character, and replace it in the same way, but merely + // switch the shift state from the VIRTUALCHARKEY to VIRTUALKEY, without changing any + // other properties of the key. + // + + // 3. Write the new keyman keyboard file + + if(!LoadNewLibrary(indll)) { + LogError(L"Failed to load keyboard DLL (%d)", GetLastError()); + return 2; + } + + LPKEYBOARD kmxfile; + + if(!LoadKeyboard(infile, &kmxfile)) { + LogError(L"Failed to load keyboard (%d)", GetLastError()); + return 3; + } + + if(DoConvert(kmxfile, kbid, bDeadkeyConversion)) { // I4552 + SaveKeyboard(kmxfile, outfile); + } + + //DeleteReallocatedPointers(kmxfile); :TODO + delete kmxfile; + + return 0; +} + + +// +// Map of all US English virtual key codes that we can translate +// +const WORD VKMap[] = { + 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z', + '0','1','2','3','4','5','6','7','8','9', + VK_SPACE, + VK_ACCENT, VK_HYPHEN, VK_EQUAL, + VK_LBRKT, VK_RBRKT, VK_BKSLASH, + VK_COLON, VK_QUOTE, + VK_COMMA, VK_PERIOD, VK_SLASH, + VK_xDF, VK_OEM_102, + 0 +}; + + +// +// Map of all shift states that we will work with +// +const UINT VKShiftState[] = {0, K_SHIFTFLAG, LCTRLFLAG|RALTFLAG, K_SHIFTFLAG|LCTRLFLAG|RALTFLAG, 0xFFFF}; + +// +// TranslateKey +// +// For each key rule on the keyboard, remap its key to the +// correct shift state and key. Adjust the LCTRL+RALT -> RALT if necessary +// +void TranslateKey(LPKEY key, WORD vk, UINT shift, WCHAR ch) { + + // The weird LCTRL+RALT is Windows' way of mapping the AltGr key. + // We store that as just RALT, and use the option "Simulate RAlt with Ctrl+Alt" + // to provide an alternate.. + if((shift & (LCTRLFLAG|RALTFLAG)) == (LCTRLFLAG|RALTFLAG)) + shift &= ~LCTRLFLAG; + + if(key->ShiftFlags == 0 && key->Key == ch) { + // Key is a mnemonic key with no shift state defined. + // Remap the key according to the character on the key cap. + //LogError(L"Converted mnemonic rule on line %d, + '%c' TO + [%x K_%d]", key->Line, key->Key, shift, vk); + key->ShiftFlags = ISVIRTUALKEY | shift; + key->Key = vk; + } else if(key->ShiftFlags & VIRTUALCHARKEY && key->Key == ch) { + // Key is a virtual character key with a hard-coded shift state. + // Do not remap the shift state, just move the key. + // This will not result in 100% wonderful mappings as there could + // be overlap, depending on how keys are arranged on the target layout. + // But that is up to the designer. + //LogError(L"Converted mnemonic virtual char key rule on line %d, + [%x '%c'] TO + [%x K_%d]", key->Line, key->ShiftFlags, key->Key, key->ShiftFlags & ~VIRTUALCHARKEY, vk); + key->ShiftFlags &= ~VIRTUALCHARKEY; + key->Key = vk; + } +} + +void TranslateGroup(LPGROUP group, WORD vk, UINT shift, WCHAR ch) { + for(unsigned int i = 0; i < group->cxKeyArray; i++) { + TranslateKey(&group->dpKeyArray[i], vk, shift, ch); + } +} + +void TranslateKeyboard(LPKEYBOARD kbd, WORD vk, UINT shift, WCHAR ch) { + for(unsigned int i = 0; i < kbd->cxGroupArray; i++) { + if(kbd->dpGroupArray[i].fUsingKeys) { + TranslateGroup(&kbd->dpGroupArray[i], vk, shift, ch); + } + } +} + +void ReportUnconvertedKeyRule(LPKEY key) { + if(key->ShiftFlags == 0) { + LogError(L"Did not find a match for mnemonic rule on line %d, + '%c' > ...", key->Line, key->Key); + } else if(key->ShiftFlags & VIRTUALCHARKEY) { + LogError(L"Did not find a match for mnemonic virtual character key rule on line %d, + [%x '%c'] > ...", key->Line, key->ShiftFlags, key->Key); + } +} + +void ReportUnconvertedGroupRules(LPGROUP group) { + for(unsigned int i = 0; i < group->cxKeyArray; i++) { + ReportUnconvertedKeyRule(&group->dpKeyArray[i]); + } +} + +void ReportUnconvertedKeyboardRules(LPKEYBOARD kbd) { + for(unsigned int i = 0; i < kbd->cxGroupArray; i++) { + if(kbd->dpGroupArray[i].fUsingKeys) { + ReportUnconvertedGroupRules(&kbd->dpGroupArray[i]); + } + } +} + +void TranslateDeadkeyKey(LPKEY key, WCHAR deadkey, WORD vk, UINT shift, WORD ch) { + if((key->ShiftFlags == 0 || key->ShiftFlags & VIRTUALCHARKEY) && key->Key == ch) { + + // The weird LCTRL+RALT is Windows' way of mapping the AltGr key. + // We store that as just RALT, and use the option "Simulate RAlt with Ctrl+Alt" + // to provide an alternate.. + if((shift & (LCTRLFLAG|RALTFLAG)) == (LCTRLFLAG|RALTFLAG)) // I4327 + shift &= ~LCTRLFLAG; + + if(key->ShiftFlags == 0) { + //LogError("Converted mnemonic rule on line %d, + '%c' TO dk(%d) + [%x K_%d]", key->Line, key->Key, deadkey, shift, vk); + key->ShiftFlags = ISVIRTUALKEY | shift; + } else { + //LogError("Converted mnemonic virtual char key rule on line %d, + [%x '%c'] TO dk(%d) + [%x K_%d]", key->Line, key->ShiftFlags, key->Key, deadkey, key->ShiftFlags & ~VIRTUALCHARKEY, vk); + key->ShiftFlags &= ~VIRTUALCHARKEY; + } + + int len = wcslen(key->dpContext); + PWSTR context = new WCHAR[len + 4]; + memcpy(context, key->dpContext, len * sizeof(WCHAR)); + context[len] = UC_SENTINEL; + context[len+1] = CODE_DEADKEY; + context[len+2] = deadkey; + context[len+3] = 0; + key->dpContext = context; + key->Key = vk; + } +} + +void TranslateDeadkeyGroup(LPGROUP group, WCHAR deadkey, WORD vk, UINT shift, WORD ch) { + for(unsigned int i = 0; i < group->cxKeyArray; i++) { + TranslateDeadkeyKey(&group->dpKeyArray[i], deadkey, vk, shift, ch); + } +} + +void TranslateDeadkeyKeyboard(LPKEYBOARD kbd, WCHAR deadkey, WORD vk, UINT shift, WORD ch) { + for(unsigned int i = 0; i < kbd->cxGroupArray; i++) { + if(kbd->dpGroupArray[i].fUsingKeys) { + TranslateDeadkeyGroup(&kbd->dpGroupArray[i], deadkey, vk, shift, ch); + } + } +} + +void AddDeadkeyRule(LPKEYBOARD kbd, WCHAR deadkey, WORD vk, UINT shift) { + // The weird LCTRL+RALT is Windows' way of mapping the AltGr key. + // We store that as just RALT, and use the option "Simulate RAlt with Ctrl+Alt" + // to provide an alternate.. + if((shift & (LCTRLFLAG|RALTFLAG)) == (LCTRLFLAG|RALTFLAG)) // I4549 + shift &= ~LCTRLFLAG; + + // If the first group is not a matching-keys group, then we need to add into + // each subgroup, otherwise just the match group + for(unsigned int i = 0; i < kbd->cxGroupArray; i++) { + if(kbd->dpGroupArray[i].fUsingKeys) { + LPKEY keys = new KEY[kbd->dpGroupArray[i].cxKeyArray + 1]; + memcpy(keys+1, kbd->dpGroupArray[i].dpKeyArray, kbd->dpGroupArray[i].cxKeyArray * sizeof(KEY)); + keys[0].dpContext = new WCHAR[1]; + keys[0].dpContext[0] = 0; + keys[0].dpOutput = new WCHAR[4]; // UC_SENTINEL, CODE_DEADKEY, deadkey_value, 0 + keys[0].dpOutput[0] = UC_SENTINEL; + keys[0].dpOutput[1] = CODE_DEADKEY; + keys[0].dpOutput[2] = deadkey; // TODO: translate to unique index + keys[0].dpOutput[3] = 0; + keys[0].Key = vk; + keys[0].Line = 0; + keys[0].ShiftFlags = shift | ISVIRTUALKEY; + kbd->dpGroupArray[i].dpKeyArray = keys; + kbd->dpGroupArray[i].cxKeyArray++; + //LogError("Add deadkey rule: + [%d K_%d] > dk(%d)", shift, vk, deadkey); + if(i == kbd->StartGroup[1]) break; // If this is the initial group, that's all we need to do. + } + } +} + +WCHAR ScanXStringForMaxDeadkeyID(LPWSTR str) { + WCHAR dkid = 0; + while(str && *str) { + if(*str == UC_SENTINEL) { + switch(*(str+1)) { + case CODE_DEADKEY: + dkid = max(dkid, *(str+2)); + } + } + str = incxstr(str); + } + return dkid; +} + +struct dkidmap { + WCHAR src_deadkey, dst_deadkey; +}; + +WCHAR GetUniqueDeadkeyID(LPKEYBOARD kbd, WCHAR deadkey) { + LPGROUP gp; + LPKEY kp; + LPSTORE sp; + UINT i, j; + WCHAR dkid = 0; + static WCHAR s_next_dkid = 0; + static dkidmap *s_dkids = NULL; + static int s_ndkids = 0; + + if(!kbd) { + if(s_dkids) { + delete s_dkids; + } + s_dkids = NULL; + s_ndkids = 0; + s_next_dkid = 0; + return 0; + } + + for(int i = 0; i < s_ndkids; i++) { + if(s_dkids[i].src_deadkey == deadkey) { + return s_dkids[i].dst_deadkey; + } + } + + if(s_next_dkid != 0) { + s_dkids = (dkidmap*) realloc(s_dkids, sizeof(dkidmap) * (s_ndkids+1)); + s_dkids[s_ndkids].src_deadkey = deadkey; + return s_dkids[s_ndkids++].dst_deadkey = ++s_next_dkid; + } + + for(i = 0, gp = kbd->dpGroupArray; i < kbd->cxGroupArray; i++, gp++) { + for(j = 0, kp = gp->dpKeyArray; j < gp->cxKeyArray; j++, kp++) { + dkid = max(dkid, ScanXStringForMaxDeadkeyID(kp->dpContext)); + dkid = max(dkid, ScanXStringForMaxDeadkeyID(kp->dpOutput)); + } + dkid = max(dkid, ScanXStringForMaxDeadkeyID(gp->dpMatch)); + dkid = max(dkid, ScanXStringForMaxDeadkeyID(gp->dpNoMatch)); + } + + for(i = 0, sp = kbd->dpStoreArray; i < kbd->cxStoreArray; i++, sp++) { + dkid = max(dkid, ScanXStringForMaxDeadkeyID(sp->dpString)); + } + + s_dkids = (dkidmap*) realloc(s_dkids, sizeof(dkidmap) * (s_ndkids+1)); + s_dkids[s_ndkids].src_deadkey = deadkey; + return s_dkids[s_ndkids++].dst_deadkey = s_next_dkid = ++dkid; +} + + +void ConvertDeadkey(LPKEYBOARD kbd, WORD vk, UINT shift, WCHAR deadkey) { + WORD deadkeys[512], *pdk; + + // Lookup the deadkey table for the deadkey in the physical keyboard + // Then for each character, go through and map it through + + WCHAR dkid = GetUniqueDeadkeyID(kbd, deadkey); + + // Add the deadkey to the mapping table for use in the import rules phase + DeadkeyMapping deadkeyMapping = { deadkey, dkid, shift, vk }; // I4353 + FDeadkeys.push_back(deadkeyMapping); //dkid, vk, shift); // I4353 + + AddDeadkeyRule(kbd, dkid, vk, shift); + + GetDeadkeys(deadkey, pdk = deadkeys); // returns array of [usvk, ch_out] pairs + while(*pdk) { + // Look up the ch + UINT vkUnderlying = VKUnderlyingLayoutToVKUS(*pdk); + TranslateDeadkeyKeyboard(kbd, dkid, vkUnderlying, *(pdk+1), *(pdk+2)); + pdk+=3; + } +} + +BOOL SetKeyboardToPositional(LPKEYBOARD kbd) { + LPSTORE sp; + UINT i; + for(i = 0, sp = kbd->dpStoreArray; i < kbd->cxStoreArray; i++, sp++) { + if(sp->dwSystemID == TSS_MNEMONIC) { + if(!sp->dpString) { + LogError(L"Invalid &mnemoniclayout system store"); + return FALSE; + } + if(wcscmp(sp->dpString, L"1") != 0) { + LogError(L"Keyboard is not a mnemonic layout keyboard"); + return FALSE; + } + *sp->dpString = '0'; + return TRUE; + } + } + + LogError(L"Keyboard is not a mnemonic layout keyboard"); + return FALSE; +} + +BOOL DoConvert(LPKEYBOARD kbd, LPWSTR kbid, BOOL bDeadkeyConversion) { // I4552 + WCHAR DeadKey; + + if(!SetKeyboardToPositional(kbd)) return FALSE; + + // Go through each of the shift states - base, shift, ctrl+alt, ctrl+alt+shift, [caps vs ncaps?] + // Currently, we go in this order so the 102nd key works. But this is not ideal for keyboards without 102nd key: // I4651 + // it catches only the first key that matches a given rule, but multiple keys may match that rule. This is particularly + // evident for the 102nd key on UK, for example, where \ can be generated with VK_OEM_102 or AltGr+VK_QUOTE. + // For now, we get the least shifted version, which is hopefully adequate. + + for(int j = 0; VKShiftState[j] != 0xFFFF; j++) { // I4651 + // Go through each possible key on the keyboard + for(int i = 0; VKMap[i]; i++) { // I4651 + UINT vkUnderlying = VKUSToVKUnderlyingLayout(VKMap[i]); + + WCHAR ch = CharFromVK(vkUnderlying, VKShiftState[j], &DeadKey); + + //LogError("--- VK_%d -> VK_%d [%c] dk=%d", VKMap[i], vkUnderlying, ch == 0 ? 32 : ch, DeadKey); + + if(bDeadkeyConversion) { // I4552 + if(ch == 0xFFFF) { + ch = DeadKey; + } + } + + switch(ch) { + case 0x0000: break; + case 0xFFFF: ConvertDeadkey(kbd, VKMap[i], VKShiftState[j], DeadKey); break; + default: TranslateKeyboard(kbd, VKMap[i], VKShiftState[j], ch); + } + + // + } + } + + ReportUnconvertedKeyboardRules(kbd); + + if(!ImportRules(kbid, kbd, &FDeadkeys, bDeadkeyConversion)) { // I4353 // I4552 + return FALSE; + } + + return TRUE; +} + +void LogError(PWSTR fmt, ...) { + WCHAR fmtbuf[256]; + + va_list vars; + va_start(vars, fmt); + _vsnwprintf_s(fmtbuf, _countof(fmtbuf), _TRUNCATE, fmt, vars); // I2248 // I3547 + fmtbuf[255] = 0; + _putws(fmtbuf); +} + +//---------old------------------------------------------- +/*#include "pch.h" +#include + +#include +#include +#include + +BOOL DoConvert(LPKEYBOARD kbd, PWSTR kbid, BOOL bDeadkeyConversion); +BOOL SaveKeyboard(LPKEYBOARD kbd, PWSTR filename); +bool ImportRules(WCHAR *kbid, LPKEYBOARD kp, std::vector *FDeadkeys, BOOL bDeadkeyConversion); // I4353 // I4327 +BOOL ConvertKeyboardToUnicode(LPKEYBOARD kbd); // I4273 +int run(int argc, wchar_t * argv[]); + +std::vector FDeadkeys; // I4353 + +#define KEYMAN_SENTRY_LOGGER_DESKTOP_ENGINE_MCOMPILE KEYMAN_SENTRY_LOGGER_DESKTOP_ENGINE ".mcompile" + +int wmain(int argc, wchar_t * argv[]) +{ + return keyman_sentry_wmain(false, KEYMAN_SENTRY_LOGGER_DESKTOP_ENGINE_MCOMPILE, argc, argv, run); +} + +int run(int argc, wchar_t * argv[]) +{ + if(argc < 3 || (argc < 5 && wcscmp(argv[1], L"-u") != 0)) { // I4273 + printf( + "Usage: mcompile -u infile.kmx outfile.kmx\n" + " mcompile [-d] infile.kmx kbdfile.dll kbid outfile.kmx\n" + " With -u parameter, converts keyboard from ANSI to Unicode\n" + " Otherwise, mcompile converts a Keyman mnemonic layout to a\n" + " positional one based on the Windows keyboard\n" + " layout file given by kbdfile.dll\n\n" + " kbid should be a hexadecimal number e.g. 409 for US English\n" + " -d convert deadkeys to plain keys\n"); // I4552 + + return 1; + } + + if(wcscmp(argv[1], L"-u") == 0) { // I4273 + wchar_t *infile = argv[2], *outfile = argv[3]; + + LPKEYBOARD kmxfile; + + if(!LoadKeyboard(infile, &kmxfile)) { + LogError(L"Failed to load keyboard (%d)", GetLastError()); + return 3; + } + + if(ConvertKeyboardToUnicode(kmxfile)) { + SaveKeyboard(kmxfile, outfile); + } + + //DeleteReallocatedPointers(kmxfile); :TODO + delete[] kmxfile; + + return 0; // I4279 + } + + int bDeadkeyConversion = wcscmp(argv[1], L"-d") == 0; // I4552 + int n = (bDeadkeyConversion ? 2 : 1); + + wchar_t *infile = argv[n], *indll = argv[n+1], *kbid = argv[n+2], *outfile = argv[n+3]; + + wprintf(L"mcompile%ls \"%ls\" \"%ls\" \"%ls\" \"%ls\"\n", bDeadkeyConversion ? L" -d":L"", infile, indll, kbid, outfile); // I4174 + + // 1. Load the keyman keyboard file + + // 2. For each key on the system layout, determine its output character and perform a + // 1-1 replacement on the keyman keyboard of that character with the base VK + shift + // state. This fixup will transform the char to a vk, which will avoid any issues + // with the key. + // + // --> deadkeys we will attack after the POC + // + // For each deadkey, we need to determine its possible outputs. Then we generate a VK + // rule for that deadkey, e.g. [K_LBRKT] > dk(c101) + // + // Next, update each rule that references the output from that deadkey to add an extra + // context deadkey at the end of the context match, e.g. 'a' dk(c101) + [K_SPACE] > 'b'. + // This will require a memory layout change for the .kmx file, plus fixups on the + // context+output index offsets + // + // --> virtual character keys + // + // [CTRL ' '] : we look at the character, and replace it in the same way, but merely + // switch the shift state from the VIRTUALCHARKEY to VIRTUALKEY, without changing any + // other properties of the key. + // + + // 3. Write the new keyman keyboard file + + if(!LoadNewLibrary(indll)) { + LogError(L"Failed to load keyboard DLL (%d)", GetLastError()); + return 2; + } + + LPKEYBOARD kmxfile; + + if(!LoadKeyboard(infile, &kmxfile)) { + LogError(L"Failed to load keyboard (%d)", GetLastError()); + return 3; + } + + if(DoConvert(kmxfile, kbid, bDeadkeyConversion)) { // I4552 + SaveKeyboard(kmxfile, outfile); + } + + //DeleteReallocatedPointers(kmxfile); :TODO + delete kmxfile; + + return 0; +} + + +// +// Map of all US English virtual key codes that we can translate +// +const WORD VKMap[] = { + 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z', + '0','1','2','3','4','5','6','7','8','9', + VK_SPACE, + VK_ACCENT, VK_HYPHEN, VK_EQUAL, + VK_LBRKT, VK_RBRKT, VK_BKSLASH, + VK_COLON, VK_QUOTE, + VK_COMMA, VK_PERIOD, VK_SLASH, + VK_xDF, VK_OEM_102, + 0 +}; + + +// +// Map of all shift states that we will work with +// +const UINT VKShiftState[] = {0, K_SHIFTFLAG, LCTRLFLAG|RALTFLAG, K_SHIFTFLAG|LCTRLFLAG|RALTFLAG, 0xFFFF}; + +// +// TranslateKey +// +// For each key rule on the keyboard, remap its key to the +// correct shift state and key. Adjust the LCTRL+RALT -> RALT if necessary +// +void TranslateKey(LPKEY key, WORD vk, UINT shift, WCHAR ch) { + + // The weird LCTRL+RALT is Windows' way of mapping the AltGr key. + // We store that as just RALT, and use the option "Simulate RAlt with Ctrl+Alt" + // to provide an alternate.. + if((shift & (LCTRLFLAG|RALTFLAG)) == (LCTRLFLAG|RALTFLAG)) + shift &= ~LCTRLFLAG; + + if(key->ShiftFlags == 0 && key->Key == ch) { + // Key is a mnemonic key with no shift state defined. + // Remap the key according to the character on the key cap. + //LogError(L"Converted mnemonic rule on line %d, + '%c' TO + [%x K_%d]", key->Line, key->Key, shift, vk); + key->ShiftFlags = ISVIRTUALKEY | shift; + key->Key = vk; + } else if(key->ShiftFlags & VIRTUALCHARKEY && key->Key == ch) { + // Key is a virtual character key with a hard-coded shift state. + // Do not remap the shift state, just move the key. + // This will not result in 100% wonderful mappings as there could + // be overlap, depending on how keys are arranged on the target layout. + // But that is up to the designer. + //LogError(L"Converted mnemonic virtual char key rule on line %d, + [%x '%c'] TO + [%x K_%d]", key->Line, key->ShiftFlags, key->Key, key->ShiftFlags & ~VIRTUALCHARKEY, vk); + key->ShiftFlags &= ~VIRTUALCHARKEY; + key->Key = vk; + } +} + +void TranslateGroup(LPGROUP group, WORD vk, UINT shift, WCHAR ch) { + for(unsigned int i = 0; i < group->cxKeyArray; i++) { + TranslateKey(&group->dpKeyArray[i], vk, shift, ch); + } +} + +void TranslateKeyboard(LPKEYBOARD kbd, WORD vk, UINT shift, WCHAR ch) { + for(unsigned int i = 0; i < kbd->cxGroupArray; i++) { + if(kbd->dpGroupArray[i].fUsingKeys) { + TranslateGroup(&kbd->dpGroupArray[i], vk, shift, ch); + } + } +} + +void ReportUnconvertedKeyRule(LPKEY key) { + if(key->ShiftFlags == 0) { + LogError(L"Did not find a match for mnemonic rule on line %d, + '%c' > ...", key->Line, key->Key); + } else if(key->ShiftFlags & VIRTUALCHARKEY) { + LogError(L"Did not find a match for mnemonic virtual character key rule on line %d, + [%x '%c'] > ...", key->Line, key->ShiftFlags, key->Key); + } +} + +void ReportUnconvertedGroupRules(LPGROUP group) { + for(unsigned int i = 0; i < group->cxKeyArray; i++) { + ReportUnconvertedKeyRule(&group->dpKeyArray[i]); + } +} + +void ReportUnconvertedKeyboardRules(LPKEYBOARD kbd) { + for(unsigned int i = 0; i < kbd->cxGroupArray; i++) { + if(kbd->dpGroupArray[i].fUsingKeys) { + ReportUnconvertedGroupRules(&kbd->dpGroupArray[i]); + } + } +} + +void TranslateDeadkeyKey(LPKEY key, WCHAR deadkey, WORD vk, UINT shift, WORD ch) { + if((key->ShiftFlags == 0 || key->ShiftFlags & VIRTUALCHARKEY) && key->Key == ch) { + + // The weird LCTRL+RALT is Windows' way of mapping the AltGr key. + // We store that as just RALT, and use the option "Simulate RAlt with Ctrl+Alt" + // to provide an alternate.. + if((shift & (LCTRLFLAG|RALTFLAG)) == (LCTRLFLAG|RALTFLAG)) // I4327 + shift &= ~LCTRLFLAG; + + if(key->ShiftFlags == 0) { + //LogError("Converted mnemonic rule on line %d, + '%c' TO dk(%d) + [%x K_%d]", key->Line, key->Key, deadkey, shift, vk); + key->ShiftFlags = ISVIRTUALKEY | shift; + } else { + //LogError("Converted mnemonic virtual char key rule on line %d, + [%x '%c'] TO dk(%d) + [%x K_%d]", key->Line, key->ShiftFlags, key->Key, deadkey, key->ShiftFlags & ~VIRTUALCHARKEY, vk); + key->ShiftFlags &= ~VIRTUALCHARKEY; + } + + int len = wcslen(key->dpContext); + PWSTR context = new WCHAR[len + 4]; + memcpy(context, key->dpContext, len * sizeof(WCHAR)); + context[len] = UC_SENTINEL; + context[len+1] = CODE_DEADKEY; + context[len+2] = deadkey; + context[len+3] = 0; + key->dpContext = context; + key->Key = vk; + } +} + +void TranslateDeadkeyGroup(LPGROUP group, WCHAR deadkey, WORD vk, UINT shift, WORD ch) { + for(unsigned int i = 0; i < group->cxKeyArray; i++) { + TranslateDeadkeyKey(&group->dpKeyArray[i], deadkey, vk, shift, ch); + } +} + +void TranslateDeadkeyKeyboard(LPKEYBOARD kbd, WCHAR deadkey, WORD vk, UINT shift, WORD ch) { + for(unsigned int i = 0; i < kbd->cxGroupArray; i++) { + if(kbd->dpGroupArray[i].fUsingKeys) { + TranslateDeadkeyGroup(&kbd->dpGroupArray[i], deadkey, vk, shift, ch); + } + } +} + +void AddDeadkeyRule(LPKEYBOARD kbd, WCHAR deadkey, WORD vk, UINT shift) { + // The weird LCTRL+RALT is Windows' way of mapping the AltGr key. + // We store that as just RALT, and use the option "Simulate RAlt with Ctrl+Alt" + // to provide an alternate.. + if((shift & (LCTRLFLAG|RALTFLAG)) == (LCTRLFLAG|RALTFLAG)) // I4549 + shift &= ~LCTRLFLAG; + + // If the first group is not a matching-keys group, then we need to add into + // each subgroup, otherwise just the match group + for(unsigned int i = 0; i < kbd->cxGroupArray; i++) { + if(kbd->dpGroupArray[i].fUsingKeys) { + LPKEY keys = new KEY[kbd->dpGroupArray[i].cxKeyArray + 1]; + memcpy(keys+1, kbd->dpGroupArray[i].dpKeyArray, kbd->dpGroupArray[i].cxKeyArray * sizeof(KEY)); + keys[0].dpContext = new WCHAR[1]; + keys[0].dpContext[0] = 0; + keys[0].dpOutput = new WCHAR[4]; // UC_SENTINEL, CODE_DEADKEY, deadkey_value, 0 + keys[0].dpOutput[0] = UC_SENTINEL; + keys[0].dpOutput[1] = CODE_DEADKEY; + keys[0].dpOutput[2] = deadkey; // TODO: translate to unique index + keys[0].dpOutput[3] = 0; + keys[0].Key = vk; + keys[0].Line = 0; + keys[0].ShiftFlags = shift | ISVIRTUALKEY; + kbd->dpGroupArray[i].dpKeyArray = keys; + kbd->dpGroupArray[i].cxKeyArray++; + //LogError("Add deadkey rule: + [%d K_%d] > dk(%d)", shift, vk, deadkey); + if(i == kbd->StartGroup[1]) break; // If this is the initial group, that's all we need to do. + } + } +} + +WCHAR ScanXStringForMaxDeadkeyID(LPWSTR str) { + WCHAR dkid = 0; + while(str && *str) { + if(*str == UC_SENTINEL) { + switch(*(str+1)) { + case CODE_DEADKEY: + dkid = max(dkid, *(str+2)); + } + } + str = incxstr(str); + } + return dkid; +} + +struct dkidmap { + WCHAR src_deadkey, dst_deadkey; +}; + +WCHAR GetUniqueDeadkeyID(LPKEYBOARD kbd, WCHAR deadkey) { + LPGROUP gp; + LPKEY kp; + LPSTORE sp; + UINT i, j; + WCHAR dkid = 0; + static WCHAR s_next_dkid = 0; + static dkidmap *s_dkids = NULL; + static int s_ndkids = 0; + + if(!kbd) { + if(s_dkids) { + delete s_dkids; + } + s_dkids = NULL; + s_ndkids = 0; + s_next_dkid = 0; + return 0; + } + + for(int i = 0; i < s_ndkids; i++) { + if(s_dkids[i].src_deadkey == deadkey) { + return s_dkids[i].dst_deadkey; + } + } + + if(s_next_dkid != 0) { + s_dkids = (dkidmap*) realloc(s_dkids, sizeof(dkidmap) * (s_ndkids+1)); + s_dkids[s_ndkids].src_deadkey = deadkey; + return s_dkids[s_ndkids++].dst_deadkey = ++s_next_dkid; + } + + for(i = 0, gp = kbd->dpGroupArray; i < kbd->cxGroupArray; i++, gp++) { + for(j = 0, kp = gp->dpKeyArray; j < gp->cxKeyArray; j++, kp++) { + dkid = max(dkid, ScanXStringForMaxDeadkeyID(kp->dpContext)); + dkid = max(dkid, ScanXStringForMaxDeadkeyID(kp->dpOutput)); + } + dkid = max(dkid, ScanXStringForMaxDeadkeyID(gp->dpMatch)); + dkid = max(dkid, ScanXStringForMaxDeadkeyID(gp->dpNoMatch)); + } + + for(i = 0, sp = kbd->dpStoreArray; i < kbd->cxStoreArray; i++, sp++) { + dkid = max(dkid, ScanXStringForMaxDeadkeyID(sp->dpString)); + } + + s_dkids = (dkidmap*) realloc(s_dkids, sizeof(dkidmap) * (s_ndkids+1)); + s_dkids[s_ndkids].src_deadkey = deadkey; + return s_dkids[s_ndkids++].dst_deadkey = s_next_dkid = ++dkid; +} + + +void ConvertDeadkey(LPKEYBOARD kbd, WORD vk, UINT shift, WCHAR deadkey) { + WORD deadkeys[512], *pdk; + + // Lookup the deadkey table for the deadkey in the physical keyboard + // Then for each character, go through and map it through + + WCHAR dkid = GetUniqueDeadkeyID(kbd, deadkey); + + // Add the deadkey to the mapping table for use in the import rules phase + DeadkeyMapping deadkeyMapping = { deadkey, dkid, shift, vk }; // I4353 + FDeadkeys.push_back(deadkeyMapping); //dkid, vk, shift); // I4353 + + AddDeadkeyRule(kbd, dkid, vk, shift); + + GetDeadkeys(deadkey, pdk = deadkeys); // returns array of [usvk, ch_out] pairs + while(*pdk) { + // Look up the ch + UINT vkUnderlying = VKUnderlyingLayoutToVKUS(*pdk); + TranslateDeadkeyKeyboard(kbd, dkid, vkUnderlying, *(pdk+1), *(pdk+2)); + pdk+=3; + } +} + +BOOL SetKeyboardToPositional(LPKEYBOARD kbd) { + LPSTORE sp; + UINT i; + for(i = 0, sp = kbd->dpStoreArray; i < kbd->cxStoreArray; i++, sp++) { + if(sp->dwSystemID == TSS_MNEMONIC) { + if(!sp->dpString) { + LogError(L"Invalid &mnemoniclayout system store"); + return FALSE; + } + if(wcscmp(sp->dpString, L"1") != 0) { + LogError(L"Keyboard is not a mnemonic layout keyboard"); + return FALSE; + } + *sp->dpString = '0'; + return TRUE; + } + } + + LogError(L"Keyboard is not a mnemonic layout keyboard"); + return FALSE; +} + +BOOL DoConvert(LPKEYBOARD kbd, LPWSTR kbid, BOOL bDeadkeyConversion) { // I4552 + WCHAR DeadKey; + + if(!SetKeyboardToPositional(kbd)) return FALSE; + + // Go through each of the shift states - base, shift, ctrl+alt, ctrl+alt+shift, [caps vs ncaps?] + // Currently, we go in this order so the 102nd key works. But this is not ideal for keyboards without 102nd key: // I4651 + // it catches only the first key that matches a given rule, but multiple keys may match that rule. This is particularly + // evident for the 102nd key on UK, for example, where \ can be generated with VK_OEM_102 or AltGr+VK_QUOTE. + // For now, we get the least shifted version, which is hopefully adequate. + + for(int j = 0; VKShiftState[j] != 0xFFFF; j++) { // I4651 + // Go through each possible key on the keyboard + for(int i = 0; VKMap[i]; i++) { // I4651 + UINT vkUnderlying = VKUSToVKUnderlyingLayout(VKMap[i]); + + WCHAR ch = CharFromVK(vkUnderlying, VKShiftState[j], &DeadKey); + + //LogError("--- VK_%d -> VK_%d [%c] dk=%d", VKMap[i], vkUnderlying, ch == 0 ? 32 : ch, DeadKey); + + if(bDeadkeyConversion) { // I4552 + if(ch == 0xFFFF) { + ch = DeadKey; + } + } + + switch(ch) { + case 0x0000: break; + case 0xFFFF: ConvertDeadkey(kbd, VKMap[i], VKShiftState[j], DeadKey); break; + default: TranslateKeyboard(kbd, VKMap[i], VKShiftState[j], ch); + } + + // + } + } + + ReportUnconvertedKeyboardRules(kbd); + + if(!ImportRules(kbid, kbd, &FDeadkeys, bDeadkeyConversion)) { // I4353 // I4552 + return FALSE; + } + + return TRUE; +} + +void LogError(PWSTR fmt, ...) { + WCHAR fmtbuf[256]; + + va_list vars; + va_start(vars, fmt); + _vsnwprintf_s(fmtbuf, _countof(fmtbuf), _TRUNCATE, fmt, vars); // I2248 // I3547 + fmtbuf[255] = 0; + _putws(fmtbuf); +} +*/ diff --git a/linux/mcompile/keymap/mcompile.h b/linux/mcompile/keymap/mcompile.h new file mode 100644 index 00000000000..3b1e2abad10 --- /dev/null +++ b/linux/mcompile/keymap/mcompile.h @@ -0,0 +1,51 @@ +/* + Name: mcompile + Copyright: Copyright (C) 2003-2017 SIL International. + Documentation: + Description: + Create Date: 3 Aug 2014 + + Modified Date: 3 Aug 2014 + Authors: mcdurdin + Related Files: + Dependencies: + + Bugs: + Todo: + Notes: + History: 03 Aug 2014 - mcdurdin - I4353 - V9.0 - mnemonic layout recompiler mixes up deadkey rules + +*/ + + + +#include +#include "km_types.h" + +void LogError(PKMX_WCHART message, ...); + + +struct DeadkeyMapping { // I4353 + KMX_WCHART deadkey, dkid; + KMX_UINT shift; + KMX_WORD vk; +}; + +extern std::vector FDeadkeys; // I4353 + + +//--------------------old +/* +#include + +void LogError(PWSTR message, ...); + + +struct DeadkeyMapping { // I4353 + WCHAR deadkey, dkid; + UINT shift; + WORD vk; +}; + +extern std::vector FDeadkeys; // I4353 +*/