diff --git a/HISTORY.md b/HISTORY.md index 2b501ebd152..3caaef473cb 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,23 @@ # Keyman Version History +## 17.0.120 alpha 2023-06-07 + +* chore(core): look for emcc.py, not emcc (#8934) +* chore(linux): Move some files to keyman-config (#8917) +* fix(linux): Fix title of reference page and links (#8939) +* fix(android/engine): Re-enable KMManager tests (#8940) + +## 17.0.119 alpha 2023-06-06 + +* chore(developer): ensure kmcmplib messages are all UTF-8 (#8927) +* chore(linux): Fix lintian warnings (#8931) + +## 17.0.118 alpha 2023-06-05 + +* chore(ios): replace fv cert (#8900) +* fix(core): Fix compilation if hotdoc is installed (#8912) +* feat(linux): Rename column and add tooltip (#8918) + ## 17.0.117 alpha 2023-06-04 * chore(developer): verify long lines compile correctly (#8915) diff --git a/VERSION.md b/VERSION.md index 2398e0d1031..4df3b18e589 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -17.0.118 \ No newline at end of file +17.0.121 \ No newline at end of file diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboard.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboard.java index 88dc290322c..bc0aed1d049 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboard.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboard.java @@ -29,6 +29,7 @@ import android.annotation.SuppressLint; import android.content.Context; import android.content.SharedPreferences; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.graphics.Color; @@ -223,8 +224,11 @@ public void initKMKeyboard(final Context context) { getSettings().setUseWideViewPort(true); getSettings().setLoadWithOverviewMode(true); - setWebContentsDebuggingEnabled(true); - + if (0 != (context.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE)) { + // Enable debugging of WebView via adb. Not used during unit tests + // Refer: https://developer.chrome.com/docs/devtools/remote-debugging/webviews/#configure_webviews_for_debugging + setWebContentsDebuggingEnabled(true); + } setWebChromeClient(new WebChromeClient() { public boolean onConsoleMessage(ConsoleMessage cm) { String msg = KMString.format("KMW JS Log: Line %d, %s:%s", cm.lineNumber(), cm.sourceId(), cm.message()); diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java index ebb8727bef5..c01b21db2c3 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java @@ -624,8 +624,11 @@ private static void initKeyboard(Context appContext, KeyboardType keyboardType) return; } - RelativeLayout.LayoutParams params = getKeyboardLayoutParams(); - keyboard.setLayoutParams(params); + if (!isTestMode()) { + // Keyboard layout not needed in unit tests. #5125 + RelativeLayout.LayoutParams params = getKeyboardLayoutParams(); + keyboard.setLayoutParams(params); + } keyboard.setVerticalScrollBarEnabled(false); keyboard.setHorizontalScrollBarEnabled(false); keyboard.setWebViewClient(webViewClient); diff --git a/android/KMEA/app/src/test/java/com/keyman/engine/KMManagerTest.java b/android/KMEA/app/src/test/java/com/keyman/engine/KMManagerTest.java index 97515b71908..59a0237b377 100644 --- a/android/KMEA/app/src/test/java/com/keyman/engine/KMManagerTest.java +++ b/android/KMEA/app/src/test/java/com/keyman/engine/KMManagerTest.java @@ -29,13 +29,14 @@ public class KMManagerTest { private static final String OLD_KEYBOARDS_LIST = "old_keyboards_list.dat"; ArrayList> dat_list; - @Before - public void loadOldKeyboardsList() throws FileNotFoundException { + // For some keyboard list tests, load an existing keyboard list. + // Can't use @Before because context is null before running tests. + public void loadOldKeyboardsList() { KMManager.initialize(ApplicationProvider.getApplicationContext(), KMManager.KeyboardType.KEYBOARD_TYPE_INAPP); File keyboards_dat = new File(TEST_RESOURCE_ROOT, OLD_KEYBOARDS_LIST); if (keyboards_dat == null || !keyboards_dat.exists()) { - throw new FileNotFoundException(); + Assert.fail(TAG + ": keyboards list not found"); } try { ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(keyboards_dat)); @@ -46,7 +47,6 @@ public void loadOldKeyboardsList() throws FileNotFoundException { } } - @Ignore("Investigate ResourcesNotFoundException") @Test public void test_getTier() { String versionName = "14.0.248-alpha"; @@ -109,9 +109,9 @@ public void test_getTier() { /* * This test is manually run to edit/regenerate the old keyboards list */ - @Ignore @Test public void create_newKeyboardsList() { + loadOldKeyboardsList(); dat_list = new ArrayList>(); HashMap usInfo = new HashMap(); @@ -181,9 +181,9 @@ public void create_newKeyboardsList() { } } - @Ignore("Investigate ResourcesNotFoundException") @Test public void test_updateOldKeyboardsList() { + loadOldKeyboardsList(); Assert.assertNotNull(dat_list); // Verify old keyboards list contains deprecated keyboards diff --git a/core/commands.inc.sh b/core/commands.inc.sh index 2e5fb9e7b9f..6916b61a9d9 100644 --- a/core/commands.inc.sh +++ b/core/commands.inc.sh @@ -1,4 +1,7 @@ -#!/usr/bin/env bash +# shellcheck shell=bash +# no hashbang for .inc.sh + +. "$KEYMAN_ROOT/resources/locate_emscripten.inc.sh" # ---------------------------------------------------------------------------- # clean @@ -114,34 +117,6 @@ do_uninstall() { # utility functions # ---------------------------------------------------------------------------- -# -# We don't want to rely on emcc being on the path, because Emscripten puts far -# too many things onto the path (in particular for us, node). -# -# The following comment suggests that we don't need emcc on the path. -# https://github.com/emscripten-core/emscripten/issues/4848#issuecomment-1097357775 -# -# So we try and locate emcc in common locations ourselves. The search pattern -# is: -# -# 1. Look for $EMSCRIPTEN_BASE (our primary emscripten variable), which should -# point to the folder that emcc is located in -# 2. Look for $EMCC which should point to the emcc executable -# 3. Look for emcc on the path -# -locate_emscripten() { - if [[ -z ${EMSCRIPTEN_BASE+x} ]]; then - if [[ -z ${EMCC+x} ]]; then - local EMCC=`which emcc` - [[ -z $EMCC ]] && builder_die "locate_emscripten: Could not locate emscripten (emcc) on the path or with \$EMCC or \$EMSCRIPTEN_BASE" - fi - [[ -x $EMCC ]] || builder_die "locate_emscripten: Variable EMCC ($EMCC) does not point to a valid executable emcc" - EMSCRIPTEN_BASE="$(dirname "$EMCC")" - fi - - [[ -x ${EMSCRIPTEN_BASE}/emcc ]] || builder_die "locate_emscripten: Variable EMSCRIPTEN_BASE ($EMSCRIPTEN_BASE) does not point to emcc's folder" -} - build_meson_cross_file_for_wasm() { if [ $BUILDER_OS == win ]; then local R=$(cygpath -w $(echo $EMSCRIPTEN_BASE) | sed 's_\\_\\\\_g') @@ -159,6 +134,8 @@ build_meson_cross_file_for_wasm() { # This link.exe is not a linker. # You may need to reorder entries to your %PATH% variable to resolve this. # +# TODO: is this still required with meson 1.0? +# cleanup_visual_studio_path() { local _split_path _new_path="" diff --git a/core/doc/hotdoc.json b/core/doc/hotdoc.json index 61a0028fb0b..4ece50d0f52 100644 --- a/core/doc/hotdoc.json +++ b/core/doc/hotdoc.json @@ -1,10 +1,14 @@ { "project_name": "@project_name@", "project_version": "@project_version@", - "sitemap": "../../doc/sitemap.txt", - "index": "../../doc/markdown_files/index.md", + "sitemap": "@doc_dir@/sitemap.txt", + "index": "@doc_dir@/markdown_files/index.md", "c_sources": [ - "../include/keyboardprocessor.h" + "@include_dir@/keyman/keyboardprocessor.h" + ], + "c_include_directories": [ + "@include_dir@", + "@doc_dir@/../../common/include" ], "c_smart_index" : true, "output": ".", diff --git a/core/doc/meson.build b/core/doc/meson.build index 2772819ce7f..01fcb5c98ad 100644 --- a/core/doc/meson.build +++ b/core/doc/meson.build @@ -12,18 +12,20 @@ if hotdoc.found() cfg = configuration_data() cfg.set('project_name', meson.project_name()) cfg.set('project_version', meson.project_version()) + cfg.set('doc_dir', meson.current_source_dir()) + cfg.set('include_dir', meson.current_source_dir() / '../include') configure_file(input: 'hotdoc.json', output: 'hotdoc.json', configuration: cfg) deps = files( - '../include/keyman/keyboardprocessor.h.in', + '../include/keyman/keyboardprocessor.h', '../src/jsonpp.hpp', '../src/utfcodec.hpp' ) docs = custom_target('docs', output: ['html'], - input: ['sitemap.txt', 'markdown_files/index.md'], + input: ['sitemap.txt', 'markdown_files/index.md', deps], command: [hotdoc, '--verbose', '--conf-file=doc/hotdoc.json', '--output=doc', 'run'], depend_files: deps, install: true, diff --git a/core/include/keyman/keyboardprocessor.h b/core/include/keyman/keyboardprocessor.h index 3513cdede2e..429a8ae6cbf 100644 --- a/core/include/keyman/keyboardprocessor.h +++ b/core/include/keyman/keyboardprocessor.h @@ -779,7 +779,7 @@ km_kbp_keyboard_get_key_list(km_kbp_keyboard const *keyboard, km_kbp_keyboard_key **out); -/* +/** ``` ### `km_kbp_keyboard_key_list_dispose` ##### Description: @@ -794,28 +794,41 @@ returned by `km_kbp_keyboard_get_key_list`. KMN_API void km_kbp_keyboard_key_list_dispose(km_kbp_keyboard_key *key_list); - /** - * Returns the list of IMX libraries and function names that are referenced by - * the keyboard. The matching dispose call needs to be called to free the memory. + * km_kbp_keyboard_get_imx_list: + * + * Returns: the list of IMX libraries and function names that are referenced by + * the keyboard.The matching dispose call needs to be called to free the memory. */ KMN_API -km_kbp_status km_kbp_keyboard_get_imx_list(km_kbp_keyboard const *keyboard, km_kbp_keyboard_imx** imx_list); +km_kbp_status km_kbp_keyboard_get_imx_list(km_kbp_keyboard const *keyboard, km_kbp_keyboard_imx **imx_list); /** + * km_kbp_keyboard_imx_list_dispose: + * * Disposes of the IMX list + * + * Returns: -- */ KMN_API void km_kbp_keyboard_imx_list_dispose(km_kbp_keyboard_imx *imx_list); /** + * km_kbp_state_imx_register_callback: + * * Register the IMX callback endpoint for the client. + * + * Returns: -- */ KMN_API void km_kbp_state_imx_register_callback(km_kbp_state *state, km_kbp_keyboard_imx_platform imx_callback, void *callback_object); /** + * km_kbp_state_imx_deregister_callback: + * * De-register IMX callback endpoint for the client. + * + * Returns: -- */ KMN_API void km_kbp_state_imx_deregister_callback(km_kbp_state *state); @@ -1042,6 +1055,8 @@ enum km_kbp_tech_value { }; /** + * km_kbp_event_flags: + * * Bit flags to be used with the event_flags parameter of km_kbp_process_event */ enum km_kbp_event_flags { @@ -1162,10 +1177,8 @@ km_kbp_event( ); enum km_kbp_event_code { - /** - * A keyboard has been activated by the user. The processor may use this - * event, for example, to switch caps lock state or provide other UX. - */ + // A keyboard has been activated by the user. The processor may use this + // event, for example, to switch caps lock state or provide other UX. KM_KBP_EVENT_KEYBOARD_ACTIVATED = 1, //future: KM_KBP_EVENT_KEYBOARD_DEACTIVATED = 2, }; diff --git a/developer/src/kmc-kmn/test/fixtures/invalid-keyboards/cerr_duplicate_group.kmn b/developer/src/kmc-kmn/test/fixtures/invalid-keyboards/cerr_duplicate_group.kmn new file mode 100644 index 00000000000..8382b5ea7f4 --- /dev/null +++ b/developer/src/kmc-kmn/test/fixtures/invalid-keyboards/cerr_duplicate_group.kmn @@ -0,0 +1,30 @@ +c Description: Verifies that kmcmplib picks up on duplicated groups with Unicode names, +c and that the Unicode names are correctly reported in error messages in UTF-8 + +store(&NAME) 'cerr_duplicate_group' +store(&VERSION) '9.0' + +begin unicode > use(ខ្មែរ) + +group(ខ្មែរ) using keys + +store(c_key) [K_K] [K_X] [SHIFT K_K] [SHIFT K_X] [K_G] \ + [K_C] [K_Q] [SHIFT K_C] [SHIFT K_Q] [SHIFT K_J] \ + [K_D] [K_Z] [SHIFT K_D] [SHIFT K_Z] [SHIFT K_N] \ + [K_T] [K_F] [SHIFT K_T] [SHIFT K_F] [K_N] \ + [K_B] [K_P] [SHIFT K_B] [SHIFT K_P] [K_M] \ + [K_Y] [K_R] [K_L] [K_V] [K_S] [K_H] [SHIFT K_L] [SHIFT K_G] \ + [RALT K_K] [RALT K_B] +store(c_out) U+1780 U+1781 U+1782 U+1783 U+1784 \ + U+1785 U+1786 U+1787 U+1788 U+1789 \ + U+178A U+178B U+178C U+178D U+178E \ + U+178F U+1790 U+1791 U+1792 U+1793 \ + U+1794 U+1795 U+1796 U+1797 U+1798 \ + U+1799 U+179A U+179B U+179C U+179F U+17A0 U+17A1 U+17A2 \ + U+179D U+179E c deprecated, but they are used in minority languages + ++ any(c_key) > index(c_out, 1) + +group(ខ្មែរ) using keys + ++ 'a' > 'oops two groups!' diff --git a/developer/src/kmc-kmn/test/fixtures/invalid-keyboards/cerr_duplicate_store.kmn b/developer/src/kmc-kmn/test/fixtures/invalid-keyboards/cerr_duplicate_store.kmn new file mode 100644 index 00000000000..14d27d5be60 --- /dev/null +++ b/developer/src/kmc-kmn/test/fixtures/invalid-keyboards/cerr_duplicate_store.kmn @@ -0,0 +1,13 @@ +c Description: Verifies that kmcmplib picks up on duplicated stores with Unicode names, +c and that the Unicode names are correctly reported in error messages in UTF-8 + +store(&NAME) 'cerr_duplicate_store' +store(&VERSION) '9.0' + +begin unicode > use(ខ្មែរ) + +group(ខ្មែរ) using keys + +store(ខ្មែរ) 'abc' +store(ខ្មែរ) 'def' + diff --git a/developer/src/kmc-kmn/test/test-messages.ts b/developer/src/kmc-kmn/test/test-messages.ts index 4d724daaf53..c551e1f223f 100644 --- a/developer/src/kmc-kmn/test/test-messages.ts +++ b/developer/src/kmc-kmn/test/test-messages.ts @@ -52,4 +52,18 @@ describe('CompilerMessages', function () { await testForMessage(this, ['invalid-keyboards', 'warn_invalid_vkey_in_kvks_file.kmn'], CompilerMessages.WARN_InvalidVkeyInKvksFile); }); + // CERR_DuplicateGroup + + it('should generate CERR_DuplicateGroup if the kmn contains two groups with the same name', async function() { + await testForMessage(this, ['invalid-keyboards', 'cerr_duplicate_group.kmn'], 0x302071); //TODO: consolidate messages from kmcmplib, CompilerMessages.CERR_DuplicateGroup + assert.equal(callbacks.messages[0].message, "A group with this name has already been defined. Group 'ខ្មែរ' declared on line 9"); + }); + + // CERR_DuplicateStore + + it('should generate CERR_DuplicateStore if the kmn contains two stores with the same name', async function() { + await testForMessage(this, ['invalid-keyboards', 'cerr_duplicate_store.kmn'], 0x302072); //TODO: consolidate messages from kmcmplib, CompilerMessages.CERR_DuplicateStore + assert.equal(callbacks.messages[0].message, "A store with this name has already been defined. Store 'ខ្មែរ' declared on line 11"); + }); + }); diff --git a/developer/src/kmc-kmw/README.md b/developer/src/kmc-kmw/README.md new file mode 100644 index 00000000000..27f1ebaa929 --- /dev/null +++ b/developer/src/kmc-kmw/README.md @@ -0,0 +1 @@ +# kmc-kmw \ No newline at end of file diff --git a/developer/src/kmcmplib/commands.inc.sh b/developer/src/kmcmplib/commands.inc.sh index bdb8e0f139b..d3647c41dd5 100644 --- a/developer/src/kmcmplib/commands.inc.sh +++ b/developer/src/kmcmplib/commands.inc.sh @@ -1,4 +1,7 @@ -#!/usr/bin/env bash +# shellcheck shell=bash +# no hashbang for .inc.sh + +. "$KEYMAN_ROOT/resources/locate_emscripten.inc.sh" # ---------------------------------------------------------------------------- # clean @@ -115,34 +118,6 @@ do_command() { # utility functions # ---------------------------------------------------------------------------- -# -# We don't want to rely on emcc being on the path, because Emscripten puts far -# too many things onto the path (in particular for us, node). -# -# The following comment suggests that we don't need emcc on the path. -# https://github.com/emscripten-core/emscripten/issues/4848#issuecomment-1097357775 -# -# So we try and locate emcc in common locations ourselves. The search pattern -# is: -# -# 1. Look for $EMSCRIPTEN_BASE (our primary emscripten variable), which should -# point to the folder that emcc is located in -# 2. Look for $EMCC which should point to the emcc executable -# 3. Look for emcc on the path -# -locate_emscripten() { - if [[ -z ${EMSCRIPTEN_BASE+x} ]]; then - if [[ -z ${EMCC+x} ]]; then - local EMCC=`which emcc` - [[ -z $EMCC ]] && builder_die "locate_emscripten: Could not locate emscripten (emcc) on the path or with \$EMCC or \$EMSCRIPTEN_BASE" - fi - [[ -x $EMCC ]] || builder_die "locate_emscripten: Variable EMCC ($EMCC) does not point to a valid executable emcc" - EMSCRIPTEN_BASE="$(dirname "$EMCC")" - fi - - [[ -x ${EMSCRIPTEN_BASE}/emcc ]] || builder_die "locate_emscripten: Variable EMSCRIPTEN_BASE ($EMSCRIPTEN_BASE) does not point to emcc's folder" -} - build_meson_cross_file_for_wasm() { if [ $BUILDER_OS == win ]; then local R=$(cygpath -w $(echo $EMSCRIPTEN_BASE) | sed 's_\\_\\\\_g') diff --git a/developer/src/kmcmplib/include/kmcmplibapi.h b/developer/src/kmcmplib/include/kmcmplibapi.h index 0b41af69909..f37e393eea3 100644 --- a/developer/src/kmcmplib/include/kmcmplibapi.h +++ b/developer/src/kmcmplib/include/kmcmplibapi.h @@ -35,7 +35,9 @@ struct KMCMP_COMPILER_RESULT { std::string kvksFilename; }; -// TODO: parameters in UTF-8 #8887 +/** + * @param szText UTF-8 string +*/ typedef int (*kmcmp_CompilerMessageProc)(int line, uint32_t dwMsgCode, const char* szText, void* context); // parameters in UTF-8 @@ -50,7 +52,9 @@ typedef int (*kmcmp_CompilerMessageProc)(int line, uint32_t dwMsgCode, const cha // } typedef bool (*kmcmp_LoadFileProc)(const char* loadFilename, const char* baseFilename, void* buffer, int* bufferSize, void* context); -// Parameters in UTF-8 +/** + * @param pszInfile UTF-8 path to file.kmn + */ EXTERN bool kmcmp_CompileKeyboard( const char* pszInfile, const KMCMP_COMPILER_OPTIONS& options, diff --git a/developer/src/kmcmplib/src/CheckForDuplicates.cpp b/developer/src/kmcmplib/src/CheckForDuplicates.cpp index 71268a4db59..56b6195fb42 100644 --- a/developer/src/kmcmplib/src/CheckForDuplicates.cpp +++ b/developer/src/kmcmplib/src/CheckForDuplicates.cpp @@ -18,8 +18,7 @@ KMX_DWORD CheckForDuplicateGroup(PFILE_KEYBOARD fk, PFILE_GROUP gp) noexcept { continue; } if (u16icmp(gp0->szName, gp->szName) == 0) { - u16sprintf(ErrExtraW, 256, L" Group '%ls' declared on line %d", u16fmt(gp0->szName).c_str(), gp0->Line); - strcpy(ErrExtraLIB, string_from_u16string(ErrExtraW).c_str()); + snprintf(ErrExtraLIB, ERR_EXTRA_LIB_LEN, " Group '%s' declared on line %d", string_from_u16string(gp->szName).c_str(), gp0->Line); return CERR_DuplicateGroup; } } @@ -39,8 +38,7 @@ KMX_DWORD CheckForDuplicateStore(PFILE_KEYBOARD fk, PFILE_STORE sp) noexcept { continue; } if (u16icmp(sp0->szName, sp->szName) == 0) { - u16sprintf(ErrExtraW,256, L" Store '%ls' declared on line %d", u16fmt(sp0->szName).c_str(), sp0->line); - strcpy(ErrExtraLIB, string_from_u16string(ErrExtraW).c_str()); + snprintf(ErrExtraLIB, ERR_EXTRA_LIB_LEN, " Store '%s' declared on line %d", string_from_u16string(sp0->szName).c_str(), sp0->line); return CERR_DuplicateStore; } } diff --git a/developer/src/kmcmplib/src/Compiler.cpp b/developer/src/kmcmplib/src/Compiler.cpp index e5d5f94cbc7..1a28aab0008 100644 --- a/developer/src/kmcmplib/src/Compiler.cpp +++ b/developer/src/kmcmplib/src/Compiler.cpp @@ -111,8 +111,7 @@ using namespace kmcmp; - char ErrExtraLIB[ERR_EXTRA_LIB_LEN]; - KMX_WCHAR ErrExtraW[ERR_EXTRA_W_LEN]; + char ErrExtraLIB[ERR_EXTRA_LIB_LEN]; // utf-8 KMX_BOOL AWarnDeprecatedCode_GLOBAL_LIB; namespace kmcmp{ diff --git a/developer/src/kmcmplib/src/UnreachableRules.cpp b/developer/src/kmcmplib/src/UnreachableRules.cpp index 9c6aaa23adb..d8980599a2b 100644 --- a/developer/src/kmcmplib/src/UnreachableRules.cpp +++ b/developer/src/kmcmplib/src/UnreachableRules.cpp @@ -41,8 +41,7 @@ KMX_DWORD VerifyUnreachableRules(PFILE_GROUP gp) { if (kp->Line != k1.Line && reportedLines.count(kp->Line) == 0) { reportedLines.insert(kp->Line); kmcmp::currentLine = kp->Line; - u16sprintf(ErrExtraW, ERR_EXTRA_W_LEN, L" Overridden by rule on line %d", k1.Line); - strcpy(ErrExtraLIB, string_from_u16string(ErrExtraW).c_str()); + snprintf(ErrExtraLIB, ERR_EXTRA_LIB_LEN, " Overridden by rule on line %d", k1.Line); AddWarning(CHINT_UnreachableRule); } } diff --git a/developer/src/kmcmplib/src/kmcmplib.h b/developer/src/kmcmplib/src/kmcmplib.h index f22c836baee..0d7c4f90042 100644 --- a/developer/src/kmcmplib/src/kmcmplib.h +++ b/developer/src/kmcmplib/src/kmcmplib.h @@ -28,9 +28,7 @@ extern void* msgprocContext; extern KMX_BOOL AWarnDeprecatedCode_GLOBAL_LIB; #define ERR_EXTRA_LIB_LEN 256 -#define ERR_EXTRA_W_LEN 256 extern char ErrExtraLIB[ERR_EXTRA_LIB_LEN]; -extern KMX_WCHAR ErrExtraW[ERR_EXTRA_W_LEN]; KMX_BOOL AddCompileError(KMX_DWORD msg); /// Use AddWarningBool for functions that return bool or KMX_BOOL diff --git a/docs/linux/keyman-config.md b/docs/linux/keyman-config.md index f050fd96ad0..cfea5d14370 100644 --- a/docs/linux/keyman-config.md +++ b/docs/linux/keyman-config.md @@ -35,10 +35,7 @@ or install it with pip: pip3 install sentry-sdk ``` -Run the script `./createkeymandirs.sh` to create the directories for these -programs to install the packages to. - -Also copy and compile the GSettings schema: +Copy and compile the GSettings schema: ```bash cd keyman_config @@ -50,15 +47,16 @@ sudo glib-compile-schemas /usr/share/glib-2.0/schemas Running `km-config` requires a language tag mapping file `keyman_config/standards/lang_tags_map.py`. This file gets generated during a package -build, and also when running `make`. +build, and also when running `build.sh build`. ## Installing manually from the repo -`make && sudo make install` will install locally to `/usr/local`. +`linux/keyman-config/build.sh build && sudo linux/keyman-config/build.sh install` +will install locally to `/usr/local`. `pip3 help install` will give you more install options. -To uninstall you can run `sudo make uninstall`. +To uninstall you can run `sudo linux/keyman-config/build.sh uninstall`. ## Things to run from the command line diff --git a/linux/debian/com.keyman.config.appdata.xml b/linux/debian/com.keyman.config.appdata.xml index f137be461df..9df49a37dc3 100644 --- a/linux/debian/com.keyman.config.appdata.xml +++ b/linux/debian/com.keyman.config.appdata.xml @@ -14,8 +14,8 @@

Keyman makes it possible for you to type in over 2,000 languages on Windows, macOS, Linux, iPhone, iPad, Android tablets and phones, and even instantly in your web browser. With the -world’s most powerful keyboarding engine, intuitive and rapid text input is now possible in -your language, and for over 99% of the global population’s mother tongues! +world's most powerful keyboarding engine, intuitive and rapid text input is now possible in +your language, and for over 99% of the global population's mother tongues!

Originally created in 1993 to type Lao on Windows, Keyman is now a free and @@ -40,7 +40,7 @@ and mobile platforms. The Keyman for Linux configuration window with a keyboard welcome window. - https://keyman.com/go/linux/11.0/linux-configuration.png + https://keyman.com/go/linux/17.0/linux-configuration.png diff --git a/linux/debian/com.keyman.ibus_keyman.metainfo.xml b/linux/debian/com.keyman.ibus_keyman.metainfo.xml index eb02001da0d..1f021d2fce3 100644 --- a/linux/debian/com.keyman.ibus_keyman.metainfo.xml +++ b/linux/debian/com.keyman.ibus_keyman.metainfo.xml @@ -1,39 +1,39 @@ -​ com.keyman.ibus_keyman -​ MIT + com.keyman.ibus_keyman + MIT GPL-2+ Keyman SIL International https://keyman.com/cdn/dev/img/keyman-logo.png -​ ibus-keyman -​

Keyman input method for IBus -​ -​

- This input method provides the Keyman IM engine for IBus. With this module, you can - use keyboard layouts designed for Keyman under the IBus platform. -

-

- Originally created in 1993 to type Lao on Windows, Keyman is now a free and - open source keyboarding platform which allows anyone to write a keyboard layout - for their language. Keyman is available for many platforms, including Windows, - macOS, iOS, Android, Linux and the web. -

+ ibus-keyman + Keyman input method for IBus +

- Keyboard layouts are defined with a clear and easy to understand keyboard - grammar. Keyman's contextual input model means keyboard layouts can be - intelligent and make it simple to type even the most complex languages. - Keyboard layouts are distributed through an open catalog to all major desktop - and mobile platforms. + This input method provides the Keyman IM engine for IBus. With this module, you can + use keyboard layouts designed for Keyman under the IBus platform. +

+

+ Originally created in 1993 to type Lao on Windows, Keyman is now a free and + open source keyboarding platform which allows anyone to write a keyboard layout + for their language. Keyman is available for many platforms, including Windows, + macOS, iOS, Android, Linux and the web. +

+

+ Keyboard layouts are defined with a clear and easy to understand keyboard + grammar. Keyman's contextual input model means keyboard layouts can be + intelligent and make it simple to type even the most complex languages. + Keyboard layouts are distributed through an open catalog to all major desktop + and mobile platforms. +

+

+ Input methods are typing systems allowing users to input complex languages.

-

-​ Input methods are typing systems allowing users to input complex languages. -​

-​
+
https://keyman.com/linux/ https://github.com/keymanapp/keyman/issues https://help.keyman.com/ https://community.software.sil.org/c/keyman https://donate.keyman.com/ -​ + diff --git a/linux/debian/control b/linux/debian/control index 02dd0647493..624f89fc0ad 100644 --- a/linux/debian/control +++ b/linux/debian/control @@ -191,7 +191,7 @@ Depends: libevdev2, ${misc:Depends}, ${shlibs:Depends}, -Description: Keyman system service +Description: System service for Keyman Originally created in 1993 to type Lao on Windows, Keyman is now a free and open source keyboarding platform which allows anyone to write a keyboard layout for their language. Keyman is available for many platforms, including diff --git a/linux/debian/keyman-system-service.manpages b/linux/debian/keyman-system-service.manpages new file mode 100644 index 00000000000..cb4d9f0500e --- /dev/null +++ b/linux/debian/keyman-system-service.manpages @@ -0,0 +1 @@ +linux/keyman-system-service/man/keyman-system-service.1 diff --git a/linux/debian/keyman.install b/linux/debian/keyman.install index 8096e324aec..a036eb8a736 100644 --- a/linux/debian/keyman.install +++ b/linux/debian/keyman.install @@ -1,4 +1,3 @@ -linux/keyman-config/com.keyman.gschema.xml usr/share/glib-2.0/schemas/ linux/keyman-config/icons/128/km-config.png usr/share/icons/hicolor/128x128/apps/ linux/keyman-config/icons/16/application-x-kmp.png usr/share/icons/hicolor/16x16/mimetypes/ linux/keyman-config/icons/24/application-x-kmp.png usr/share/icons/hicolor/24x24/mimetypes/ @@ -10,5 +9,6 @@ linux/keyman-config/icons/48/km-config.png usr/share/icons/hicolor/48x48/apps/ linux/keyman-config/icons/64/application-x-kmp.png usr/share/icons/hicolor/64x64/mimetypes/ linux/keyman-config/icons/64/km-config.png usr/share/icons/hicolor/64x64/apps/ linux/keyman-config/keyman_config/icons/* usr/share/keyman/icons/ -linux/keyman-config/km-config.desktop usr/share/applications +linux/keyman-config/resources/com.keyman.gschema.xml usr/share/glib-2.0/schemas/ +linux/keyman-config/resources/km-config.desktop usr/share/applications debian/com.keyman.config.appdata.xml usr/share/metainfo diff --git a/linux/debian/rules b/linux/debian/rules index db1f9250174..ec9178298ca 100755 --- a/linux/debian/rules +++ b/linux/debian/rules @@ -37,6 +37,7 @@ override_dh_auto_configure: linux/keyman-config/build.sh configure override_dh_auto_build: + cp linux/keyman-config/resources/keyman.sharedmimeinfo debian/ core/build.sh --no-tests build:arch linux/ibus-keyman/build.sh build linux/keyman-system-service/build.sh build diff --git a/linux/help/reference/index.md b/linux/help/reference/index.md index 1089382c551..7b8f704018f 100644 --- a/linux/help/reference/index.md +++ b/linux/help/reference/index.md @@ -1,8 +1,8 @@ --- -title: Keyman 16.0 for Linux Reference +title: Keyman 17.0 for Linux Reference --- -## Keyman 16.0 for Linux Overview +## Keyman 17.0 for Linux Overview Keyman for Linux makes it possible for you to type in over 2,000 languages on Linux. diff --git a/linux/ibus-keyman/src/test/run-tests.sh b/linux/ibus-keyman/src/test/run-tests.sh index 932f64b8861..44a397582b4 100755 --- a/linux/ibus-keyman/src/test/run-tests.sh +++ b/linux/ibus-keyman/src/test/run-tests.sh @@ -53,7 +53,7 @@ SCHEMA_DIR=$TEMP_DATA_DIR/glib-2.0/schemas export XDG_DATA_DIRS=$TEMP_DATA_DIR:$XDG_DATA_DIRS mkdir -p "$SCHEMA_DIR" -cp "$SRCDIR/../keyman-config/com.keyman.gschema.xml" "$SCHEMA_DIR/" +cp "$SRCDIR/../keyman-config/resources/com.keyman.gschema.xml" "$SCHEMA_DIR/" glib-compile-schemas "$SCHEMA_DIR" export GSETTINGS_BACKEND=memory diff --git a/linux/ibus-keyman/tests/scripts/test-helper.inc.sh b/linux/ibus-keyman/tests/scripts/test-helper.inc.sh index 930eb4fe2ca..2a3735d7084 100755 --- a/linux/ibus-keyman/tests/scripts/test-helper.inc.sh +++ b/linux/ibus-keyman/tests/scripts/test-helper.inc.sh @@ -183,7 +183,7 @@ function setup() { echo "export GSETTINGS_SCHEMA_DIR=\"$SCHEMA_DIR\"" >> "$ENV_FILE" mkdir -p "$SCHEMA_DIR" - cp "${TOP_SRCDIR}"/../keyman-config/com.keyman.gschema.xml "$SCHEMA_DIR"/ + cp "${TOP_SRCDIR}"/../keyman-config/resources/com.keyman.gschema.xml "$SCHEMA_DIR"/ glib-compile-schemas "$SCHEMA_DIR" export LD_LIBRARY_PATH=${COMMON_ARCH_DIR}/src:${LD_LIBRARY_PATH-} diff --git a/linux/keyman-config/MANIFEST.in b/linux/keyman-config/MANIFEST.in index e27020f36c9..20705c6fc3e 100644 --- a/linux/keyman-config/MANIFEST.in +++ b/linux/keyman-config/MANIFEST.in @@ -2,4 +2,4 @@ recursive-include keyman_config/icons * recursive-include icons * include README.md include *.bash-completion -include *.gschema.xml +include resources/*.gschema.xml diff --git a/linux/keyman-config/build-help.sh b/linux/keyman-config/build-help.sh index 97f06ca3d00..e05b8d284e4 100755 --- a/linux/keyman-config/build-help.sh +++ b/linux/keyman-config/build-help.sh @@ -3,13 +3,11 @@ set -e set -u -## START STANDARD BUILD SCRIPT INCLUDE -# adjust relative paths as necessary THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" -## END STANDARD BUILD SCRIPT INCLUDE - THIS_DIR=$(dirname "$THIS_SCRIPT") +cd "${THIS_DIR}" + function display_usage { echo "Usage: $0 [--man] [--md] [--no-reconf]" echo " $0 --help" @@ -50,13 +48,13 @@ while [[ $# -gt 0 ]] ; do shift # past the processed argument done -if [ -z "$generate_man" -a -z "$generate_help" ]; then +if [ -z "$generate_man" ] && [ -z "$generate_help" ]; then generate_man=1 generate_help=1 fi if [ -n "$reconfigure" ]; then - pushd $THIS_DIR/.. > /dev/null + pushd "$THIS_DIR/.." > /dev/null ./scripts/reconf.sh popd > /dev/null fi diff --git a/linux/keyman-config/build.sh b/linux/keyman-config/build.sh index 1cb603f091b..4828dd5ec73 100755 --- a/linux/keyman-config/build.sh +++ b/linux/keyman-config/build.sh @@ -29,19 +29,23 @@ clean_action() { keyman_config/standards/lang_tags_map.py } -build_man_pages() { +execute_with_temp_schema() { local TEMP_DATA_DIR SCHEMA_DIR TEMP_DATA_DIR=$(mktemp -d) - SCHEMA_DIR=$TEMP_DATA_DIR/glib-2.0/schemas - export XDG_DATA_DIRS=$TEMP_DATA_DIR:${XDG_DATA_DIRS-} + SCHEMA_DIR="${TEMP_DATA_DIR}/glib-2.0/schemas" + export XDG_DATA_DIRS="${TEMP_DATA_DIR}":${XDG_DATA_DIRS-} export GSETTINGS_SCHEMA_DIR="${SCHEMA_DIR}" - mkdir -p "$SCHEMA_DIR" - cp ./com.keyman.gschema.xml "$SCHEMA_DIR"/ - glib-compile-schemas "$SCHEMA_DIR" - ./build-help.sh --man --no-reconf + mkdir -p "${SCHEMA_DIR}" + cp resources/com.keyman.gschema.xml "${SCHEMA_DIR}"/ + glib-compile-schemas "${SCHEMA_DIR}" + "$@" export XDG_DATA_DIRS=${XDG_DATA_DIRS#*:} unset GSETTINGS_SCHEMA_DIR - rm -rf "$TEMP_DATA_DIR" + rm -rf "${TEMP_DATA_DIR}" +} + +build_man_and_help_pages() { + execute_with_temp_schema ./build-help.sh --no-reconf } build_action() { @@ -66,14 +70,19 @@ build_action() { builder_echo "Skip building lang_tags_map.py during package build" fi popd - builder_echo "Building man pages" - build_man_pages + builder_echo "Building man and help pages" + build_man_and_help_pages builder_echo "Building keyman-config" python3 setup.py build } +test_action() { + execute_with_temp_schema ./run-tests.sh +} + install_action() { if [ -n "${SUDO_USER:-}" ]; then + # with sudo install into /usr/local pip3 install qrcode sentry-sdk # eventually change this to: pip3 install . python3 setup.py install @@ -84,6 +93,7 @@ install_action() { mkdir -p /usr/local/share/man/man1 cp ../../debian/man/*.1 /usr/local/share/man/man1 else + # without sudo install into /tmp/keyman (or $DESTDIR) mkdir -p "/tmp/keyman/$(python3 -c 'import sys;import os;pythonver="python%d.%d" % (sys.version_info[0], sys.version_info[1]);sitedir = os.path.join("lib", pythonver, "site-packages");print(sitedir)')" # when we no longer have to support old pip version (python > 3.6) change this to: # pip3 install --prefix /tmp/keyman . @@ -108,6 +118,6 @@ uninstall_action() { builder_run_action clean clean_action builder_run_action configure # nothing to do builder_run_action build build_action -builder_run_action test ./run-tests.sh +builder_run_action test test_action builder_run_action install install_action builder_run_action uninstall uninstall_action diff --git a/linux/keyman-config/createkeymandirs.sh b/linux/keyman-config/createkeymandirs.sh deleted file mode 100755 index d9befe7f5d5..00000000000 --- a/linux/keyman-config/createkeymandirs.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh - -sudo mkdir -p /usr/local/share/keyman -sudo mkdir -p /usr/local/share/fonts/keyman -sudo mkdir -p /usr/local/share/doc/keyman -sudo chmod 00777 /usr/local/share/keyman -sudo chmod 00777 /usr/local/share/fonts/keyman -sudo chmod 00777 /usr/local/share/doc/keyman diff --git a/linux/keyman-config/keyman_config/view_installed.py b/linux/keyman-config/keyman_config/view_installed.py index aaa5196fbda..263d665d25f 100755 --- a/linux/keyman-config/keyman_config/view_installed.py +++ b/linux/keyman-config/keyman_config/view_installed.py @@ -19,7 +19,7 @@ from keyman_config.dbus_util import get_keyman_config_service from keyman_config.downloadkeyboard import DownloadKmpWindow from keyman_config.get_kmp import (InstallLocation, get_keyboard_dir, - get_keyman_dir) + get_keyman_dir, get_install_area_string) from keyman_config.install_window import InstallKmpWindow, find_keyman_image from keyman_config.keyboard_details import KeyboardDetailsView from keyman_config.kmpmetadata import get_fonts, parsemetadata @@ -166,7 +166,8 @@ def add_keyboard_layouts_widget(self): str, # version str, # packageID int, # enum InstallLocation (KmpArea is GObject version) - str, # InstallLocation path + str, # InstallLocation area + str, # Tooltip with InstallLocation path str, # path to welcome file if it exists or None str) # path to options file if it exists or None @@ -186,9 +187,11 @@ def add_keyboard_layouts_widget(self): column = Gtk.TreeViewColumn(_("Version"), renderer, text=2) self.tree.append_column(column) # i18n: column header in table displaying installed keyboards - column = Gtk.TreeViewColumn(_("Location"), renderer, text=5) + column = Gtk.TreeViewColumn(_("Area"), renderer, text=5) self.tree.append_column(column) + self.tree.set_tooltip_column(column=6) + select = self.tree.get_selection() select.connect("changed", self.on_tree_selection_changed) @@ -286,7 +289,8 @@ def addlistitems(self, installed_kmp, store, install_area): kmpdata['version'], kmpdata['packageID'], install_area, - get_keyman_dir(install_area).replace(os.path.expanduser('~'), '~'), + get_install_area_string(install_area), + path.replace(os.path.expanduser('~'), '~'), welcome_file, options_file]) diff --git a/linux/keyman-config/km-config.bash-completion b/linux/keyman-config/km-config.bash-completion index b1f46c0076f..fd0eee394c7 100644 --- a/linux/keyman-config/km-config.bash-completion +++ b/linux/keyman-config/km-config.bash-completion @@ -1,4 +1,5 @@ -#!/usr/bin/env bash +# shellcheck disable=SC2148 +# No hashbang for bash completion scripts! They are intended to be sourced, not executed. _km-config_completions() { diff --git a/linux/keyman-config/km-kvk2ldml.bash-completion b/linux/keyman-config/km-kvk2ldml.bash-completion index 3eb2950c390..1e8231a1a1f 100644 --- a/linux/keyman-config/km-kvk2ldml.bash-completion +++ b/linux/keyman-config/km-kvk2ldml.bash-completion @@ -1,4 +1,5 @@ -#!/usr/bin/env bash +# shellcheck disable=SC2148 +# No hashbang for bash completion scripts! They are intended to be sourced, not executed. _km-kvk2ldml_completions() { diff --git a/linux/keyman-config/km-package-get.bash-completion b/linux/keyman-config/km-package-get.bash-completion index 9bacb1b8fef..0fb3a4d14c7 100644 --- a/linux/keyman-config/km-package-get.bash-completion +++ b/linux/keyman-config/km-package-get.bash-completion @@ -1,4 +1,5 @@ -#!/usr/bin/env bash +# shellcheck disable=SC2148 +# No hashbang for bash completion scripts! They are intended to be sourced, not executed. _km-package-get_completions() { diff --git a/linux/keyman-config/km-package-install.bash-completion b/linux/keyman-config/km-package-install.bash-completion index 1a424e8ea6f..06bfeb6aa5c 100644 --- a/linux/keyman-config/km-package-install.bash-completion +++ b/linux/keyman-config/km-package-install.bash-completion @@ -1,4 +1,5 @@ -#!/usr/bin/env bash +# shellcheck disable=SC2148 +# No hashbang for bash completion scripts! They are intended to be sourced, not executed. _km-package-install_completions() { diff --git a/linux/keyman-config/km-package-list-installed.bash-completion b/linux/keyman-config/km-package-list-installed.bash-completion index a3758b467eb..672353b9a13 100644 --- a/linux/keyman-config/km-package-list-installed.bash-completion +++ b/linux/keyman-config/km-package-list-installed.bash-completion @@ -1,4 +1,5 @@ -#!/usr/bin/env bash +# shellcheck disable=SC2148 +# No hashbang for bash completion scripts! They are intended to be sourced, not executed. _km-package-list-installed_completions() { diff --git a/linux/keyman-config/km-package-uninstall.bash-completion b/linux/keyman-config/km-package-uninstall.bash-completion index 191e709eaba..4b81c38dacc 100644 --- a/linux/keyman-config/km-package-uninstall.bash-completion +++ b/linux/keyman-config/km-package-uninstall.bash-completion @@ -1,4 +1,5 @@ -#!/usr/bin/env bash +# shellcheck disable=SC2148 +# No hashbang for bash completion scripts! They are intended to be sourced, not executed. _km-package-uninstall_completions() { diff --git a/linux/keyman-config/com.keyman.gschema.xml b/linux/keyman-config/resources/com.keyman.gschema.xml similarity index 100% rename from linux/keyman-config/com.keyman.gschema.xml rename to linux/keyman-config/resources/com.keyman.gschema.xml diff --git a/linux/debian/keyman.sharedmimeinfo b/linux/keyman-config/resources/keyman.sharedmimeinfo similarity index 100% rename from linux/debian/keyman.sharedmimeinfo rename to linux/keyman-config/resources/keyman.sharedmimeinfo diff --git a/linux/keyman-config/km-config.desktop b/linux/keyman-config/resources/km-config.desktop similarity index 100% rename from linux/keyman-config/km-config.desktop rename to linux/keyman-config/resources/km-config.desktop diff --git a/linux/keyman-system-service/man/keyman-system-service.1 b/linux/keyman-system-service/man/keyman-system-service.1 new file mode 100644 index 00000000000..b506bd1607a --- /dev/null +++ b/linux/keyman-system-service/man/keyman-system-service.1 @@ -0,0 +1,10 @@ +.TH KEYMAN-SYSTEM-SERVICE "1" "May 2023" "keyman-system-service" "User Commands" +.SH NAME +keyman-system-service \- System service for Keyman +.SH DESCRIPTION +\&keyman\-system\-service +.TP +This command should not be run directly. It will be started as a DBUS +system service by systemd. +.SH "SEE ALSO" +.BR ibus-engine-keyman(1) diff --git a/linux/scripts/install.sh b/linux/scripts/install.sh index 55074f48481..7e497232fc8 100755 --- a/linux/scripts/install.sh +++ b/linux/scripts/install.sh @@ -53,7 +53,7 @@ if [[ "${SUDOINSTALL}" == "yes" ]]; then exit 1 fi echo "doing sudo glib-compile-schemas for keyman-config" - cp com.keyman.gschema.xml /usr/share/glib-2.0/schemas/ + cp resources/com.keyman.gschema.xml /usr/share/glib-2.0/schemas/ glib-compile-schemas /usr/share/glib-2.0/schemas/ echo "doing sudo install of keyman-config" ./build.sh install diff --git a/resources/locate_emscripten.inc.sh b/resources/locate_emscripten.inc.sh new file mode 100644 index 00000000000..a58b384089e --- /dev/null +++ b/resources/locate_emscripten.inc.sh @@ -0,0 +1,30 @@ +# shellcheck shell=bash +# no hashbang for .inc.sh + +# +# We don't want to rely on emcc.py being on the path, because Emscripten puts far +# too many things onto the path (in particular for us, node). +# +# The following comment suggests that we don't need emcc.py on the path. +# https://github.com/emscripten-core/emscripten/issues/4848#issuecomment-1097357775 +# +# So we try and locate emcc.py in common locations ourselves. The search pattern +# is: +# +# 1. Look for $EMSCRIPTEN_BASE (our primary emscripten variable), which should +# point to the folder that emcc.py is located in +# 2. Look for $EMCC which should point to the emcc.py executable +# 3. Look for emcc.py on the path +# +locate_emscripten() { + if [[ -z ${EMSCRIPTEN_BASE+x} ]]; then + if [[ -z ${EMCC+x} ]]; then + local EMCC=`which emcc.py` + [[ -z $EMCC ]] && builder_die "locate_emscripten: Could not locate emscripten (emcc.py) on the path or with \$EMCC or \$EMSCRIPTEN_BASE" + fi + [[ -x $EMCC ]] || builder_die "locate_emscripten: Variable EMCC ($EMCC) does not point to a valid executable emcc.py" + EMSCRIPTEN_BASE="$(dirname "$EMCC")" + fi + + [[ -x ${EMSCRIPTEN_BASE}/emcc.py ]] || builder_die "locate_emscripten: Variable EMSCRIPTEN_BASE ($EMSCRIPTEN_BASE) does not point to emcc.py's folder" +} \ No newline at end of file