Merge branch 'epic/kmc-convert' into feat/developer/kmc-convert
Some checks are pending
Keyman Build Summary / Summarize build status checks (push) Waiting to run
84
HISTORY.md
|
|
@ -1,5 +1,65 @@
|
|||
# Keyman Version History
|
||||
|
||||
## 19.0.214 alpha 2026-03-12
|
||||
|
||||
* chore(linux): Update debian changelog (#15718)
|
||||
* maint(resources): use x86_64 emscripten on arm/windows builds (#15715)
|
||||
|
||||
## 19.0.213 alpha 2026-03-10
|
||||
|
||||
* maint(linux): set git credential for linux help on the correct repo (#15707)
|
||||
|
||||
## 19.0.212 alpha 2026-03-09
|
||||
|
||||
* chore(android): Cleanup unused Extracted Text (#15671)
|
||||
* chore(deps): bump fast-xml-parser from 5.3.4 to 5.3.8 (#15649)
|
||||
* fix(developer): resolve input project path for `kmc copy` (#15700)
|
||||
* fix(developer): await copier result before reporting success or failure (#15701)
|
||||
* fix(developer): correct INVALID_HANDLE_VALUE check in UnlockProject (#15704)
|
||||
* fix(developer): use trimmed version of paths when verifying in New Project (#15705)
|
||||
|
||||
## 19.0.211 alpha 2026-03-06
|
||||
|
||||
* chore(deps-dev): bump basic-ftp from 5.0.5 to 5.2.0 (#15631)
|
||||
* chore(deps-dev): bump rollup from 4.22.4 to 4.59.0 (#15632)
|
||||
* chore(deps): bump minimatch and @microsoft/api-extractor (#15647)
|
||||
* chore(deps): bump minimatch from 10.1.1 to 10.2.4 in /developer/src/server/src/win32/trayicon/addon-src (#15648)
|
||||
* chore(deps): bump tar from 7.5.7 to 7.5.10 in /developer/src/server/src/win32/trayicon/addon-src (#15682)
|
||||
* chore(deps): bump multer from 2.0.2 to 2.1.1 (#15681)
|
||||
* chore(web): remove implicit any type when setting processingConfig.itemIdentifier (#15689)
|
||||
* maint(common): rollback from Typescript 5.8.2 to 5.4.x (#15690)
|
||||
* docs: tweak build bot docs and update imsample gitignore (#15691)
|
||||
* maint(developer): make `TestCompilerCallbacks` usage more consistent and simplify (#15665)
|
||||
* maint(developer): cleanup additional TestCompilerCallbacks references (#15684)
|
||||
* fix(developer): prevent new projects from overwriting existing projects (#15669)
|
||||
* fix(developer): retrieve debug memo anchor without side effects (#15672)
|
||||
* fix(developer): ngrok upgrade (#15626)
|
||||
* chore(deps-dev): bump minimatch from 9.0.5 to 9.0.9 in /resources/build/pr-build-status (#15650)
|
||||
|
||||
## 19.0.210 alpha 2026-03-05
|
||||
|
||||
* fix(developer): apply keyboard description in Windows keyboard import (#15667)
|
||||
* fix(developer): improve UI feedback on upgrade (#15670)
|
||||
|
||||
## 19.0.209 alpha 2026-03-04
|
||||
|
||||
* maint(ios): update fv Cartfile for Xcode 26 (#15655)
|
||||
* feat(linux): implement diagnostic report (#15576)
|
||||
* refactor(core): cleanup (#15656)
|
||||
|
||||
## 19.0.208 alpha 2026-03-03
|
||||
|
||||
* docs(core): add keyhandling doc (#15629)
|
||||
* fix(developer): handle CRLF as CR internally in LDML debugger (#15616)
|
||||
* fix(developer): handle .kps file that has no `<Package>` element (#15622)
|
||||
* fix(developer): use correct return values and nullish checks in package-validation (#15653)
|
||||
|
||||
## 19.0.207 alpha 2026-03-02
|
||||
|
||||
* chore(ios): Cleanup `RELEASE_OEM_FIRSTVOICES` var in build.sh scripts (#15605)
|
||||
* fix(developer): package compiler handle missing `info` section in .kps file (#15620)
|
||||
* fix(developer): handle window already destroyed when closing editor (#15618)
|
||||
|
||||
## 19.0.206 alpha 2026-02-25
|
||||
|
||||
* maint(ios): upgrade to Xcode 26.2 (#15498)
|
||||
|
|
@ -1223,6 +1283,30 @@
|
|||
* refactor(windows): rename `TKeymanMutex.MutexOwned` to `TakeOwnership` and add `ReleaseOwnership` (#13168)
|
||||
* chore: increment to alpha 19.0 (#13187)
|
||||
|
||||
## 18.0.248 stable 2026-03-12
|
||||
|
||||
* fix(ios): Revert Sentry to 8.38.0 to fix FirstVoices crash on startup with 18.0.247 (#15726)
|
||||
|
||||
## 18.0.247 stable 2026-03-09
|
||||
|
||||
* chore(linux): Update debian changelog (#15556)
|
||||
* chore(linux): update copyright year and standards version (#15558)
|
||||
* fix(mac): retry for mac disk detach (#15577)
|
||||
* maint(mac): upgrade to Xcode 26.2 (#15575)
|
||||
* maint(ios): upgrade to Xcode 26.2 (#15614)
|
||||
* fix(developer): handle CRLF as CR internally in LDML debugger (#15660)
|
||||
* fix(developer): handle .kps file that has no `<Package>` element (#15661)
|
||||
* fix(developer): use correct return values and nullish checks in package-validation (#15662)
|
||||
* fix(developer): handle window already destroyed when closing editor (#15663)
|
||||
* fix(developer): package compiler handle missing `info` section in .kps file (#15664)
|
||||
* fix(developer): apply keyboard description in Windows keyboard import (#15668)
|
||||
* fix(developer): improve UI feedback on upgrade (#15686)
|
||||
* fix(developer): prevent new projects from overwriting existing projects (#15694)
|
||||
* fix(developer): retrieve debug memo anchor without side effects (#15695)
|
||||
* fix(developer): ngrok upgrade (#15633)
|
||||
* fix(developer): await copier result before reporting success or failure (#15702)
|
||||
* fix(developer): resolve input project path for `kmc copy` (#15703)
|
||||
|
||||
## 18.0.246 stable 2026-02-04
|
||||
|
||||
* cherrypick(common): Update FirstVoices versions in keyboards.csv (#15273)
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
19.0.207
|
||||
19.0.215
|
||||
|
|
@ -43,7 +43,6 @@ import io.sentry.Sentry;
|
|||
public class SystemKeyboard extends InputMethodService implements OnKeyboardEventListener {
|
||||
|
||||
private static View inputView = null;
|
||||
private static ExtractedText exText = null;
|
||||
private KMHardwareKeyboardInterpreter interpreter = null;
|
||||
private int inputType = InputType.TYPE_NULL;
|
||||
private int lastOrientation = Configuration.ORIENTATION_UNDEFINED;
|
||||
|
|
@ -204,10 +203,9 @@ public class SystemKeyboard extends InputMethodService implements OnKeyboardEven
|
|||
return value, so we test for that as well (#11479)
|
||||
*/
|
||||
if (icText != null && icText.text != null) {
|
||||
boolean didUpdateText = KMManager.updateText(KeyboardType.KEYBOARD_TYPE_SYSTEM, icText.text.toString());
|
||||
boolean didUpdateSelection = KMManager.updateSelectionRange(KeyboardType.KEYBOARD_TYPE_SYSTEM);
|
||||
if (!didUpdateText || !didUpdateSelection)
|
||||
exText = icText;
|
||||
// Update the text selection but ignore the returned statuses
|
||||
KMManager.updateText(KeyboardType.KEYBOARD_TYPE_SYSTEM, icText.text.toString());
|
||||
KMManager.updateSelectionRange(KeyboardType.KEYBOARD_TYPE_SYSTEM);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -278,10 +276,7 @@ public class SystemKeyboard extends InputMethodService implements OnKeyboardEven
|
|||
|
||||
@Override
|
||||
public void onKeyboardLoaded(KeyboardType keyboardType) {
|
||||
if (keyboardType == KeyboardType.KEYBOARD_TYPE_SYSTEM) {
|
||||
if (exText != null)
|
||||
exText = null;
|
||||
}
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -36,9 +36,7 @@
|
|||
"restructure": "3.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mocha": "^5.2.7",
|
||||
"@types/node": "^20.4.1",
|
||||
"ajv": "^8.17.1",
|
||||
"ajv": "^8.12.0",
|
||||
"ajv-cli": "^5.0.0",
|
||||
"ajv-formats": "^2.1.1",
|
||||
"c8": "^7.12.0",
|
||||
|
|
|
|||
|
|
@ -303,7 +303,7 @@ end;
|
|||
function TframeCEFHost.HasFocus: Boolean;
|
||||
begin
|
||||
AssertVclThread;
|
||||
Result := cefwp.HandleAllocated and IsChild(cefwp.Handle, GetFocus);
|
||||
Result := Assigned(cefwp) and cefwp.HandleAllocated and IsChild(cefwp.Handle, GetFocus);
|
||||
end;
|
||||
|
||||
procedure TframeCEFHost.Handle_CEF_SHOW(var message: TMessage);
|
||||
|
|
@ -373,7 +373,7 @@ end;
|
|||
procedure TframeCEFHost.SetFocus;
|
||||
begin
|
||||
AssertVclThread;
|
||||
if not FIsClosing and cefwp.CanFocus and Assigned(cef) then
|
||||
if not FIsClosing and Assigned(cefwp) and Assigned(cef) and cefwp.CanFocus then
|
||||
begin
|
||||
GetParentForm(Self).ActiveControl := Self;
|
||||
cef.SetFocus(True);
|
||||
|
|
@ -574,7 +574,8 @@ end;
|
|||
procedure TframeCEFHost.Handle_CEF_DESTROY(var Message: TMessage);
|
||||
begin
|
||||
AssertVclThread;
|
||||
cefwp.DestroyChildWindow;
|
||||
if Assigned(cefwp) then
|
||||
cefwp.DestroyChildWindow;
|
||||
FreeAndNil(cefwp);
|
||||
end;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ This is an internal API intended for use only within Keyman Engine.
|
|||
* [Options](options)
|
||||
* [Processor](processor)
|
||||
* [State and Actions](state)
|
||||
* [Key Handling](keyhandling)
|
||||
* [JSON introspection Schema](json-schema)
|
||||
* [Building Keyman Core](building)
|
||||
|
||||
|
|
@ -122,4 +123,4 @@ Caps Lock.
|
|||
[km_core_event_flags]: processor#km_core_event_flags "km_core_event_flags enum"
|
||||
[km_core_process_event]: processor#km_core_process_event "km_core_process_event function"
|
||||
[km_core_event]: processor#km_core_event "km_core_event function"
|
||||
[km_core_event_code]: processor#km_core_event_code "km_core_event_code enum"
|
||||
[km_core_event_code]: processor#km_core_event_code "km_core_event_code enum"
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ title: JSON Introspection Schema
|
|||
|
||||
The [`km_core_state_to_json()`](state#km_core_state_to_json) call
|
||||
generates a JSON document describing the internal state of the keyboard
|
||||
processor, this is the schema describing that document.
|
||||
processor. This is the schema describing that document.
|
||||
|
||||
**WARNING**: The structure and format of the JSON document is independently
|
||||
versioned is not considered part of C API. It is intended solely for use in
|
||||
versioned and is not considered part of the C API. It is intended solely for use in
|
||||
diagnostics or by development and debugging tools which may need to be aware of
|
||||
keyboard processor engine implementation details.
|
||||
|
||||
|
|
@ -74,4 +74,4 @@ keyboard processor engine implementation details.
|
|||
"context": { "$ref": "#/definitions/context" }
|
||||
}
|
||||
}
|
||||
```
|
||||
```
|
||||
|
|
|
|||
42
core/docs/api/keyhandling.md
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# Key Handling
|
||||
|
||||
For each key press the processor will called twice, for the key down event
|
||||
as well as for the key up event. Depending on the type of key pressed the
|
||||
processor might handle the key itself or pass it on to the application.
|
||||
The value of `emit_keystroke` in `km_core_actions` struct tells if the
|
||||
processor handled the key (`emit_keystroke=0`) or not (`emit_keystroke=1`).
|
||||
It is important that the same value gets set for both key down and key up
|
||||
events, otherwise the application might miss some events which then looks
|
||||
to the user like keys are stuck.
|
||||
|
||||
Usually the processor won't handle any frame keys and let the application
|
||||
deal with it. This allows shortcut keys like <kbd>Ctrl</kbd>+<kbd>C</kbd>
|
||||
to work. The only exception is the <kbd>Backspace</kbd> key which is
|
||||
handled internally if enough context is available. Regular keys will be
|
||||
handled by the processor.
|
||||
|
||||
Note that there is a difference between CLDR/LDML and KMN keyboards if
|
||||
there are no rules/transforms defined for a key: KMN keyboards will
|
||||
output the cap value of the key (e.g. pressing <kbd>a</kbd> will output
|
||||
`a` if no rule is defined), whereas CLDR/LDML keyboards will suppress
|
||||
any output for that key.
|
||||
|
||||
The following table lists the state of `km_core_actions.emit_keystroke`
|
||||
on return of `km_core_process_event` when the following type of key is
|
||||
pressed:
|
||||
|
||||
|Type | KeyDown | KeyUp |
|
||||
|-----------------------------|---------------|----------|
|
||||
|Key with rule | FALSE | FALSE |
|
||||
|Key w/o rule | FALSE | FALSE |
|
||||
|Framekeys: | | |
|
||||
|<kbd>Enter</kbd> | TRUE | TRUE |
|
||||
|<kbd>Backspace</kbd>¹ | FALSE | FALSE |
|
||||
|<kbd>Backspace</kbd>² | TRUE | TRUE |
|
||||
|<kbd>Ctrl</kbd>+Key | TRUE | TRUE |
|
||||
|Modifier key <kbd>Shift</kbd>| TRUE | TRUE |
|
||||
|Modifier key <kbd>Ctrl</kbd> | TRUE | TRUE |
|
||||
|Modifier key <kbd>LAlt</kbd> | TRUE | TRUE |
|
||||
|
||||
1: context available<br/>
|
||||
2: without or with empty context
|
||||
|
|
@ -3,7 +3,7 @@ title: Options - Keyman Core API
|
|||
---
|
||||
|
||||
A state’s default options are set from the keyboard at creation time and the
|
||||
environment. The Platform layer is then is expected to apply any persisted
|
||||
environment. The Platform layer is then expected to apply any persisted
|
||||
options it is maintaining. Options are passed into and out of API functions as
|
||||
simple C arrays of [km_core_option_item] terminated with a `KM_CORE_OPTIONS_END`
|
||||
sentinel value. A state's options are exposed and manipulatable via the
|
||||
|
|
@ -281,4 +281,4 @@ km_core_state_options_to_json(km_core_state const *state,
|
|||
[km_core_event_flags]: processor#km_core_event_flags "km_core_event_flags enum"
|
||||
[km_core_process_event]: processor#km_core_process_event "km_core_process_event function"
|
||||
[km_core_event]: processor#km_core_event "km_core_event function"
|
||||
[km_core_event_code]: processor#km_core_event_code "km_core_event_code enum"
|
||||
[km_core_event_code]: processor#km_core_event_code "km_core_event_code enum"
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ enum km_core_event_flags {
|
|||
KM_CORE_EVENT_FLAG_DEFAULT = 0,
|
||||
KM_CORE_EVENT_FLAG_TOUCH = 1,
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Values
|
||||
|
||||
`KM_CORE_EVENT_FLAG_DEFAULT`
|
||||
|
|
@ -195,4 +195,4 @@ enum km_core_event_code {
|
|||
[km_core_event_flags]: processor#km_core_event_flags "km_core_event_flags enum"
|
||||
[km_core_process_event]: processor#km_core_process_event "km_core_process_event function"
|
||||
[km_core_event]: processor#km_core_event "km_core_event function"
|
||||
[km_core_event_code]: processor#km_core_event_code "km_core_event_code enum"
|
||||
[km_core_event_code]: processor#km_core_event_code "km_core_event_code enum"
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ owned by the state object.
|
|||
|
||||
## Description
|
||||
|
||||
Describes the
|
||||
Describes a change to the hardware caps lock indicator state requested by
|
||||
Keyman Core to the Platform layer.
|
||||
|
||||
## Specification
|
||||
```c
|
||||
|
|
@ -50,6 +51,7 @@ This API replaces the Action items APIs, which are now deprecated and will be
|
|||
removed in the future.
|
||||
|
||||
## Specification
|
||||
|
||||
```c
|
||||
typedef struct {
|
||||
unsigned int code_points_to_delete;
|
||||
|
|
@ -60,8 +62,8 @@ typedef struct {
|
|||
km_core_caps_state new_caps_lock_state;
|
||||
const km_core_usv* deleted_context;
|
||||
} km_core_actions;
|
||||
|
||||
```
|
||||
|
||||
## Members
|
||||
|
||||
`code_points_to_delete`
|
||||
|
|
@ -78,15 +80,17 @@ typedef struct {
|
|||
|
||||
`emit_keystroke`
|
||||
: Emit the (unmodified) input keystroke to the application, 0 = no, 1 = yes.
|
||||
On most platforms this signals whether the processor handled the event
|
||||
(0) or not (1). See also [key handling](keyhandling).
|
||||
|
||||
`new_caps_lock_state`
|
||||
: -1=unchanged, 0=off, 1=on
|
||||
|
||||
`deleted_context`
|
||||
: Reference copy of actual UTF32 codepoints deleted from end of context
|
||||
(closest to caret) exactly code_points_to_delete in length (plus null
|
||||
(closest to caret) exactly `code_points_to_delete` in length (plus null
|
||||
terminator). Used to determine encoding conversion differences when
|
||||
deleting; only set when using [km_core_state_get_actions], otherwise nullptr.
|
||||
deleting; only set when using [km_core_state_get_actions], otherwise `nullptr`.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -282,4 +286,4 @@ An opaque pointer to a state object.
|
|||
[km_core_event_flags]: processor#km_core_event_flags "km_core_event_flags enum"
|
||||
[km_core_process_event]: processor#km_core_process_event "km_core_process_event function"
|
||||
[km_core_event]: processor#km_core_event "km_core_event function"
|
||||
[km_core_event_code]: processor#km_core_event_code "km_core_event_code enum"
|
||||
[km_core_event_code]: processor#km_core_event_code "km_core_event_code enum"
|
||||
|
|
|
|||
|
|
@ -576,15 +576,17 @@ typedef struct {
|
|||
|
||||
`emit_keystroke`
|
||||
: Emit the (unmodified) input keystroke to the application, 0 = no, 1 = yes.
|
||||
On most platforms this signals whether the processor handled the event
|
||||
(0) or not (1). See also [key handling](keyhandling).
|
||||
|
||||
`new_caps_lock_state`
|
||||
: -1=unchanged, 0=off, 1=on
|
||||
|
||||
`deleted_context`
|
||||
: Reference copy of actual UTF32 codepoints deleted from end of context
|
||||
(closest to caret) exactly code_points_to_delete in length (plus null
|
||||
(closest to caret) exactly `code_points_to_delete` in length (plus null
|
||||
terminator). Used to determine encoding conversion differences when
|
||||
deleting; only set when using [km_core_state_get_actions], otherwise nullptr.
|
||||
deleting; only set when using [km_core_state_get_actions], otherwise `nullptr`.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -744,7 +746,7 @@ title: Options - Keyman Core API
|
|||
---
|
||||
|
||||
A state’s default options are set from the keyboard at creation time and the
|
||||
environment. The Platform layer is then is expected to apply any persisted
|
||||
environment. The Platform layer is then expected to apply any persisted
|
||||
options it is maintaining. Options are passed into and out of API functions as
|
||||
simple C arrays of [km_core_option_item] terminated with a `KM_CORE_OPTIONS_END`
|
||||
sentinel value. A state's options are exposed and manipulatable via the
|
||||
|
|
|
|||
|
|
@ -243,7 +243,7 @@ void ldml_event_state::emit_backspace() {
|
|||
// else loop again
|
||||
assert(end.type != KM_CORE_CT_END); // inappropriate here.
|
||||
state->context().pop_back();
|
||||
}
|
||||
}
|
||||
/*
|
||||
We couldn't find a character at end of context (context is empty),
|
||||
so we'll pass the backspace keystroke on to the app to process; the
|
||||
|
|
@ -532,10 +532,10 @@ ldml_event_state::ldml_event_state(
|
|||
uint8_t i,
|
||||
uint16_t e) {
|
||||
this->state = s;
|
||||
this->vk = v;
|
||||
this->modifier_state = m;
|
||||
this->is_key_down = i;
|
||||
this->event_flags = e;
|
||||
this->_vk = v;
|
||||
this->_modifier_state = m;
|
||||
this->_is_key_down = i;
|
||||
this->_event_flags = e;
|
||||
|
||||
actions.persist_options = new km_core_option_item[1];
|
||||
actions.persist_options[0] = NULL_OPTIONS[0];
|
||||
|
|
|
|||
|
|
@ -178,10 +178,10 @@ public:
|
|||
size_t context_to_string(std::u32string &str, bool include_markers = true);
|
||||
|
||||
private:
|
||||
km_core_virtual_key vk;
|
||||
uint16_t modifier_state;
|
||||
uint8_t is_key_down;
|
||||
uint16_t event_flags;
|
||||
km_core_virtual_key _vk;
|
||||
uint16_t _modifier_state;
|
||||
uint8_t _is_key_down;
|
||||
uint16_t _event_flags;
|
||||
km_core_state *state;
|
||||
|
||||
// our in-flight action struct.
|
||||
|
|
@ -194,12 +194,12 @@ public:
|
|||
// implementation
|
||||
km_core_virtual_key
|
||||
ldml_event_state::get_vk() const {
|
||||
return vk;
|
||||
return _vk;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
ldml_event_state::get_modifier_state() const {
|
||||
return modifier_state;
|
||||
return _modifier_state;
|
||||
}
|
||||
|
||||
} // namespace core
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ protected:
|
|||
km_core_keyboard_dispose(this->keyboard);
|
||||
this->keyboard = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(KmCoreKeyboardApiTests, LoadFromBlob) {
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ kbd_log = custom_target(test_kbd + '.kmx'.underscorify(),
|
|||
input: kbd_src,
|
||||
command: kmc_cmd + ['build', '--debug', '--no-compiler-version', '@INPUT@', '--out-file', kbd_obj]
|
||||
)
|
||||
test('imx_list', imx_e, depends: kbd_log, args: [kbd_obj] )
|
||||
test('imx_list', imx_e, depends: kbd_log, args: [kbd_obj] )
|
||||
|
||||
external_e = executable('ext_event_tests', ['kmx_external_event.tests.cpp', common_test_files],
|
||||
cpp_args: defns + warns,
|
||||
|
|
@ -258,4 +258,4 @@ kbd_log = custom_target(test_kbd + '.kmx'.underscorify(),
|
|||
input: kbd_src,
|
||||
command: kmc_cmd + ['build', '--debug', '--no-compiler-version', '@INPUT@', '--out-file', kbd_obj]
|
||||
)
|
||||
test('ext_event', external_e, depends: kbd_log, args: [kbd_obj] )
|
||||
test('ext_event', external_e, depends: kbd_log, args: [kbd_obj] )
|
||||
|
|
|
|||
|
|
@ -125,42 +125,73 @@ Update database
|
|||
|
||||

|
||||
|
||||
There are two configurations in the Keyman Developer Server section:
|
||||
1. Configure Server...
|
||||
2. List local URLs for Server
|
||||
### Configure Server dialog
|
||||
|
||||
Configure Server...
|
||||
After clicking the **Configure Server...** button, a new window will pop-up:
|
||||
|
||||
: After clicking the button, a new window will pop-up
|
||||

|
||||
|
||||

|
||||
You can customize the Keyman Developer Server for testing your keyboard online
|
||||
and on other devices. Features of the Keyman Developer Server include:
|
||||
|
||||
You can customize the Keyman Developer server for testing the usability of your keyboard. Features of the Keyman Developer server include:
|
||||
* Seamless integration with the IDE (Start, Stop, Live reload, Recompile...)
|
||||
* Sharing keyboards for testing online and on other devices
|
||||
* Allowing testing across devices and networks
|
||||
|
||||
* Seamless integration with the IDE (Start, Stop, Live reload, Recompile...)
|
||||
* Port configuration
|
||||
* Allow testing cross devices
|
||||
* Wider range support for NGROK...
|
||||
Keyman Developer Server integrates with a free tool called
|
||||
[ngrok](https://ngrok.com) that provides a public URL to your instance of Keyman
|
||||
Developer Server. This URL is dynamic and can change over time, and is only
|
||||
available while Keyman Developer Server is running. This URL can be accessed
|
||||
from any mobile device that is online, whether or not it is on your local
|
||||
network. This means you can also quickly share keyboards, packages, and models
|
||||
with other users, with a minimum of difficulty.
|
||||
|
||||
[Find out more](https://github.com/keymanapp/keyman/pull/6073)
|
||||
* [Learn more about ngrok](server#ngrok)
|
||||
|
||||
Understanding the three tick boxes will enhance the usability of Keyman Developer:
|
||||
- **Leave Server running after closing IDE**: allows keyboard testing on local URLs after closing Keyman Developer.
|
||||
- **Use ngrok to provide public url for web debugger**: configure NGROK as instructed, once it looks something like this:
|
||||

|
||||
**Options available in this dialog:**
|
||||
|
||||
Please restart the machine, and the URL (*link ending in .ngrok-free.app*) will appear in the specified locations:
|
||||

|
||||

|
||||
- **Leave Server running after closing IDE**: allows keyboard testing on local
|
||||
URLs even if Keyman Developer is not running.
|
||||
|
||||
Now, freely share it across multiple devices using the link or QR code.
|
||||

|
||||
- **Use ngrok to provide public url for web debugger**: enable ngrok
|
||||
integration; you may need to download additional components; see below:
|
||||
|
||||
- **Show server console window on start**: once ticked, Keyman Developer's server console will appear as an independent window as a node application with the default message:
|
||||
`Starting Keyman Developer Server 17.0.290-beta, listening on port 8008.`
|
||||
- **Download or update ngrok**: If the text next to this button shows 'Not
|
||||
installed', press the button to download the required component
|
||||
|
||||
List local URLs for Server
|
||||
: Below Configure Server, untick the box, and it will quit displaying any local URLs for keyboard testing.
|
||||

|
||||
- **Install required redistributable**: ngrok requires an additional Microsoft
|
||||
VC++ redistributable component; if the text next to this button shows 'Not
|
||||
installed', press the button and follow the prompts to install the
|
||||
redistributable component.
|
||||
|
||||
Explore more: [Keyman Developer Server](server#toc-configuring-keyman-developer-server)
|
||||
After enabling ngrok, a URL with ending a domain such as `.ngrok-free.app` will
|
||||
appear in the Tools/Server menu and the Web and Mobile debugger pages in the
|
||||
Keyboard Editor and the Package Editor:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Once this is active, you can access Keyman Developer Server across multiple
|
||||
devices and networks using the link or QR code.
|
||||
|
||||
- **Show server console window on start**: once ticked, Keyman Developer's
|
||||
server console will appear as an independent window as a node application,
|
||||
which may be helpful if you encounter errors as they will appear in the
|
||||
console.
|
||||
|
||||
A default message will appear when the server console starts, similar to:
|
||||
`Starting Keyman Developer Server <version>-beta, listening on port 8008.`
|
||||
|
||||
### List local URLs for Server
|
||||
|
||||
When selected, Keyman Developer will show you more local URLs in the
|
||||
Tools/Server menu for accessing Keyman Developer Server from your browser. Some
|
||||
of these URLs will work only on your local computer, and will not work on other
|
||||
devices. Deselect this option in order to show only the most relevant access
|
||||
URLs. (On some networks, it may be helpful to see all the available URLs.)
|
||||
|
||||
|
||||
## Related links
|
||||
|
||||
* [Keyman Developer Server](server#toc-configuring-keyman-developer-server)
|
||||
|
|
|
|||
|
|
@ -296,7 +296,7 @@ context as well.
|
|||
The devices listed are representative of the various types of platforms that
|
||||
Keyman supports, to allow testing on each of the available form factors.
|
||||
|
||||
## Making your Keyman Developer Server instance globally available with ngrok
|
||||
## Making your Keyman Developer Server instance globally available with ngrok {#ngrok}
|
||||
|
||||
One of the fiddliest parts of testing keyboards and models with mobile devices
|
||||
is transferring the files to your phone or tablet. Keyman Developer Server will
|
||||
|
|
@ -324,28 +324,30 @@ configure ngrok manually.
|
|||
click **Configure Server...**. You should be presented with a window similar
|
||||
to this:
|
||||
|
||||

|
||||

|
||||
|
||||
2. Tick the box **Use ngrok to provide public url for Server**
|
||||
3. If ngrok is available, a version number will be shown to the right of the
|
||||
3. If ngrok is available, the text 'Installed' will be shown to the right of the
|
||||
**Download or update ngrok** button. Otherwise, click this button to download
|
||||
the latest version.
|
||||
4. You'll need a free ngrok account, so click the **Create free ngrok
|
||||
4. **Install required redistributable**: ngrok requires an additional Microsoft
|
||||
VC++ redistributable component; if the text next to this button shows 'Not
|
||||
installed', press the button and follow the prompts to install the
|
||||
redistributable component.
|
||||
5. You'll need a free ngrok account, so click the **Create free ngrok
|
||||
account...** button to open the ngrok website, and follow the steps there
|
||||
to finish the account creation process.
|
||||
5. After creating the account, you should be presented with an authentication
|
||||
6. After creating the account, you should be presented with an authentication
|
||||
token. You can also access this by clicking the **Get token** link in the
|
||||
Keyman Developer Server Options dialog box. Paste this token into the
|
||||
**Authentication token** edit box.
|
||||
6. Select the most appropriate region for your location, to minimize the latency
|
||||
(delay) when using the ngrok service.
|
||||
7. Click **OK** to save changes, and start the ngrok service within Keyman
|
||||
Developer Server.
|
||||
|
||||
Once ngrok is configured, you should see an additional **Server** menu item in
|
||||
Keyman Developer's **Tools** menu, with three items:
|
||||
|
||||
**Open `https://some-url.ngrok.io` in browser**
|
||||
**Open `https://some-url.ngrok-free.app` in browser**
|
||||
|
||||
: Opens the public URL to your current Keyman Developer Server instance in the
|
||||
default browser on your computer.
|
||||
|
|
@ -357,15 +359,7 @@ Keyman Developer's **Tools** menu, with three items:
|
|||
|
||||
**Configure...**
|
||||
|
||||
: Opens the Keyman Developer Server Options dialog box.
|
||||
|
||||
# Configuring Keyman Developer Server
|
||||
|
||||
Keyman Developer Server has a number of configuration options. On Windows, using
|
||||
Keyman Developer is the easiest way to manage these options. Open **Tools |
|
||||
Options**, select **Server** tab, and click **Configure Server...**.
|
||||
|
||||

|
||||
: Opens the [Keyman Developer Server Options](options#server-tab) dialog box.
|
||||
|
||||
## Configuration Files
|
||||
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 130 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
|
|
@ -21,6 +21,7 @@ interface
|
|||
|
||||
uses
|
||||
System.Classes,
|
||||
Winapi.ActiveX,
|
||||
Winapi.Messages,
|
||||
Winapi.RichEdit,
|
||||
Winapi.Windows,
|
||||
|
|
@ -35,7 +36,7 @@ type
|
|||
|
||||
TMemoSelection = record
|
||||
Start, Finish: Integer;
|
||||
Anchor: Integer;
|
||||
Caret: Integer; // In a non-empty selection, Anchor is at the other end of the selection
|
||||
function ToString: string;
|
||||
end;
|
||||
|
||||
|
|
@ -43,7 +44,6 @@ type
|
|||
private
|
||||
FOnMessage: TKeymanDeveloperDebuggerMessageEvent;
|
||||
FAllowUnicodeInput: Boolean;
|
||||
FSelectionChanging: Boolean;
|
||||
FIsDebugging: Boolean;
|
||||
procedure SetAllowUnicode(const Value: Boolean);
|
||||
function GetSelection: TMemoSelection;
|
||||
|
|
@ -60,7 +60,6 @@ type
|
|||
property AllowUnicode: Boolean read FAllowUnicodeInput write SetAllowUnicode default True;
|
||||
property OnMessage: TKeymanDeveloperDebuggerMessageEvent read FOnMessage write FOnMessage;
|
||||
property Selection: TMemoSelection read GetSelection write SetSelection;
|
||||
property SelectionChanging: Boolean read FSelectionChanging;
|
||||
property IsDebugging: Boolean read FIsDebugging write FIsDebugging;
|
||||
end;
|
||||
|
||||
|
|
@ -69,6 +68,7 @@ procedure Register;
|
|||
implementation
|
||||
|
||||
uses
|
||||
tom_TLB,
|
||||
System.SysUtils;
|
||||
|
||||
{ TKeymanDeveloperDebuggerMemo }
|
||||
|
|
@ -107,26 +107,29 @@ begin
|
|||
end;
|
||||
|
||||
function TKeymanDeveloperDebuggerMemo.GetSelection: TMemoSelection;
|
||||
var
|
||||
Unk: IUnknown;
|
||||
TextDoc: ITextDocument;
|
||||
TextSel: ITextSelection;
|
||||
begin
|
||||
Result.Anchor := 0;
|
||||
|
||||
// EM_GETSEL doesn't tell us the anchor position, but we can figure
|
||||
// it out with this kludge. I am not aware of side effects from this
|
||||
// at this time.
|
||||
SendMessage(Handle, EM_GETSEL, NativeUInt(@Result.Start), NativeUInt(@Result.Finish));
|
||||
if Result.Start <> Result.Finish then
|
||||
Result.Caret := Result.Finish;
|
||||
|
||||
if Result.Finish <> Result.Start then
|
||||
begin
|
||||
// We only need to play the selection test game if there is a non-zero
|
||||
// selection length
|
||||
FSelectionChanging := True;
|
||||
Lines.BeginUpdate;
|
||||
try
|
||||
SendMessage(Handle, EM_SETSEL, -1, 0);
|
||||
SendMessage(Handle, EM_GETSEL, NativeUInt(@Result.Anchor), 0);
|
||||
SetSelection(Result);
|
||||
finally
|
||||
Lines.EndUpdate;
|
||||
FSelectionChanging := False;
|
||||
if SendMessage(Handle, EM_GETOLEINTERFACE, 0, LPARAM(@Unk)) <> 0 then
|
||||
begin
|
||||
if Unk.QueryInterface(IID_ITextDocument, TextDoc) = S_OK then
|
||||
begin
|
||||
TextSel := TextDoc.Selection;
|
||||
if TextSel <> nil then
|
||||
begin
|
||||
if (TextSel.Flags and tomSelStartActive) <> 0 then
|
||||
begin
|
||||
Result.Caret := Result.Start;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
|
@ -153,7 +156,7 @@ end;
|
|||
procedure TKeymanDeveloperDebuggerMemo.SetSelection(
|
||||
const Value: TMemoSelection);
|
||||
begin
|
||||
if Value.Anchor = Value.Start
|
||||
if Value.Caret = Value.Start
|
||||
then SendMessage(Handle, EM_SETSEL, Value.Finish, Value.Start)
|
||||
else SendMessage(Handle, EM_SETSEL, Value.Start, Value.Finish);
|
||||
end;
|
||||
|
|
@ -174,10 +177,10 @@ begin
|
|||
end;
|
||||
|
||||
{ TMemoSelection }
|
||||
|
||||
|
||||
function TMemoSelection.ToString: string;
|
||||
begin
|
||||
Result := Format('%d %d %d', [Start, Finish, Anchor]);
|
||||
end;
|
||||
|
||||
begin
|
||||
Result := Format('TMemoSelection(start=%d finish=%d caret=%d)', [Start, Finish, Caret]);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ contains
|
|||
TextFileFormat in '..\general\TextFileFormat.pas',
|
||||
LeftTabbedPageControl in 'LeftTabbedPageControl.pas',
|
||||
MenuImgList in 'MenuImgList.pas',
|
||||
StringGridEditControlled in 'StringGridEditControlled.pas';
|
||||
StringGridEditControlled in 'StringGridEditControlled.pas',
|
||||
tom_TLB in 'tom_TLB.pas';
|
||||
|
||||
end.
|
||||
|
|
|
|||
|
|
@ -139,6 +139,7 @@
|
|||
<DCCReference Include="LeftTabbedPageControl.pas"/>
|
||||
<DCCReference Include="MenuImgList.pas"/>
|
||||
<DCCReference Include="StringGridEditControlled.pas"/>
|
||||
<DCCReference Include="tom_TLB.pas"/>
|
||||
<BuildConfiguration Include="Release">
|
||||
<Key>Cfg_2</Key>
|
||||
<CfgParent>Base</CfgParent>
|
||||
|
|
|
|||
942
developer/src/common/delphi/components/tom_TLB.pas
generated
Normal file
|
|
@ -0,0 +1,942 @@
|
|||
unit tom_TLB;
|
||||
|
||||
// ************************************************************************ //
|
||||
// WARNING
|
||||
// -------
|
||||
// The types declared in this file were generated from data read from a
|
||||
// Type Library. If this type library is explicitly or indirectly (via
|
||||
// another type library referring to this type library) re-imported, or the
|
||||
// 'Refresh' command of the Type Library Editor activated while editing the
|
||||
// Type Library, the contents of this file will be regenerated and all
|
||||
// manual modifications will be lost.
|
||||
// ************************************************************************ //
|
||||
|
||||
// $Rev: 52393 $
|
||||
// File generated on 4/03/2026 10:48:24 AM from Type Library described below.
|
||||
|
||||
// ************************************************************************ //
|
||||
// Type Lib: C:\Windows\SysWOW64\RICHED20.dll (1)
|
||||
// LIBID: {8CC497C9-A1DF-11CE-8098-00AA0047BE5D}
|
||||
// LCID: 0
|
||||
// Helpfile:
|
||||
// HelpString:
|
||||
// DepndLst:
|
||||
// (1) v2.0 stdole, (C:\Windows\SysWOW64\stdole2.tlb)
|
||||
// SYS_KIND: SYS_WIN32
|
||||
// Errors:
|
||||
// Hint: Symbol 'Type' renamed to 'type_'
|
||||
// Hint: Parameter 'Unit' of ITextSelection.MoveLeft changed to 'Unit_'
|
||||
// Hint: Parameter 'Unit' of ITextSelection.MoveRight changed to 'Unit_'
|
||||
// Hint: Parameter 'Unit' of ITextSelection.MoveUp changed to 'Unit_'
|
||||
// Hint: Parameter 'Unit' of ITextSelection.MoveDown changed to 'Unit_'
|
||||
// Hint: Parameter 'Unit' of ITextSelection.HomeKey changed to 'Unit_'
|
||||
// Hint: Parameter 'Unit' of ITextSelection.EndKey changed to 'Unit_'
|
||||
// Hint: Member 'End' of 'ITextRange' changed to 'End_'
|
||||
// Hint: Parameter 'Unit' of ITextRange.Expand changed to 'Unit_'
|
||||
// Hint: Parameter 'Unit' of ITextRange.GetIndex changed to 'Unit_'
|
||||
// Hint: Parameter 'Unit' of ITextRange.SetIndex changed to 'Unit_'
|
||||
// Hint: Parameter 'Unit' of ITextRange.StartOf changed to 'Unit_'
|
||||
// Hint: Parameter 'Unit' of ITextRange.EndOf changed to 'Unit_'
|
||||
// Hint: Parameter 'Unit' of ITextRange.Move changed to 'Unit_'
|
||||
// Hint: Parameter 'Unit' of ITextRange.MoveStart changed to 'Unit_'
|
||||
// Hint: Parameter 'Unit' of ITextRange.MoveEnd changed to 'Unit_'
|
||||
// Hint: Parameter 'Unit' of ITextRange.Delete changed to 'Unit_'
|
||||
// Hint: Parameter 'Type' of ITextRange.ChangeCase changed to 'Type_'
|
||||
// Hint: Parameter 'Type' of ITextRange.GetPoint changed to 'Type_'
|
||||
// Hint: Parameter 'Type' of ITextRange.SetPoint changed to 'Type_'
|
||||
// Hint: Member 'Protected' of 'ITextFont' changed to 'Protected_'
|
||||
// Hint: Parameter 'Type' of ITextDocument2.GetClientRect changed to 'Type_'
|
||||
// ************************************************************************ //
|
||||
{$TYPEDADDRESS OFF} // Unit must be compiled without type-checked pointers.
|
||||
{$WARN SYMBOL_PLATFORM OFF}
|
||||
{$WRITEABLECONST ON}
|
||||
{$VARPROPSETTER ON}
|
||||
{$ALIGN 4}
|
||||
|
||||
interface
|
||||
|
||||
uses Winapi.Windows, System.Classes, System.Variants, System.Win.StdVCL, Vcl.Graphics, Winapi.ActiveX;
|
||||
|
||||
|
||||
// *********************************************************************//
|
||||
// GUIDS declared in the TypeLibrary. Following prefixes are used:
|
||||
// Type Libraries : LIBID_xxxx
|
||||
// CoClasses : CLASS_xxxx
|
||||
// DISPInterfaces : DIID_xxxx
|
||||
// Non-DISP interfaces: IID_xxxx
|
||||
// *********************************************************************//
|
||||
const
|
||||
// TypeLibrary Major and minor versions
|
||||
tomMajorVersion = 1;
|
||||
tomMinorVersion = 0;
|
||||
|
||||
LIBID_tom: TGUID = '{8CC497C9-A1DF-11CE-8098-00AA0047BE5D}';
|
||||
|
||||
IID_ITextDocument: TGUID = '{8CC497C0-A1DF-11CE-8098-00AA0047BE5D}';
|
||||
IID_ITextRange: TGUID = '{8CC497C2-A1DF-11CE-8098-00AA0047BE5D}';
|
||||
IID_ITextSelection: TGUID = '{8CC497C1-A1DF-11CE-8098-00AA0047BE5D}';
|
||||
IID_ITextFont: TGUID = '{8CC497C3-A1DF-11CE-8098-00AA0047BE5D}';
|
||||
IID_ITextPara: TGUID = '{8CC497C4-A1DF-11CE-8098-00AA0047BE5D}';
|
||||
IID_ITextStoryRanges: TGUID = '{8CC497C5-A1DF-11CE-8098-00AA0047BE5D}';
|
||||
IID_ITextDocument2: TGUID = '{01C25500-4268-11D1-883A-3C8B00C10000}';
|
||||
IID_ITextMsgFilter: TGUID = '{A3787420-4267-11D1-883A-3C8B00C10000}';
|
||||
|
||||
// *********************************************************************//
|
||||
// Declaration of Enumerations defined in Type Library
|
||||
// *********************************************************************//
|
||||
// Constants for enum __MIDL___MIDL_itf_tom_0000_0000_0001
|
||||
type
|
||||
__MIDL___MIDL_itf_tom_0000_0000_0001 = TOleEnum;
|
||||
const
|
||||
tomFalse = $00000000;
|
||||
tomTrue = $FFFFFFFF;
|
||||
tomUndefined = $FF676981;
|
||||
tomToggle = $FF676982;
|
||||
tomAutoColor = $FF676983;
|
||||
tomDefault = $FF676984;
|
||||
tomSuspend = $FF676985;
|
||||
tomResume = $FF676986;
|
||||
tomApplyNow = $00000000;
|
||||
tomApplyLater = $00000001;
|
||||
tomTrackParms = $00000002;
|
||||
tomCacheParms = $00000003;
|
||||
tomBackward = $C0000001;
|
||||
tomForward = $3FFFFFFF;
|
||||
tomMove = $00000000;
|
||||
tomExtend = $00000001;
|
||||
tomNoSelection = $00000000;
|
||||
tomSelectionIP = $00000001;
|
||||
tomSelectionNormal = $00000002;
|
||||
tomSelectionFrame = $00000003;
|
||||
tomSelectionColumn = $00000004;
|
||||
tomSelectionRow = $00000005;
|
||||
tomSelectionBlock = $00000006;
|
||||
tomSelectionInlineShape = $00000007;
|
||||
tomSelectionShape = $00000008;
|
||||
tomSelStartActive = $00000001;
|
||||
tomSelAtEOL = $00000002;
|
||||
tomSelOvertype = $00000004;
|
||||
tomSelActive = $00000008;
|
||||
tomSelReplace = $00000010;
|
||||
tomEnd = $00000000;
|
||||
tomStart = $00000020;
|
||||
tomCollapseEnd = $00000000;
|
||||
tomCollapseStart = $00000001;
|
||||
tomClientCoord = $00000100;
|
||||
tomNone = $00000000;
|
||||
tomSingle = $00000001;
|
||||
tomWords = $00000002;
|
||||
tomDouble = $00000003;
|
||||
tomDotted = $00000004;
|
||||
tomDash = $00000005;
|
||||
tomDashDot = $00000006;
|
||||
tomDashDotDot = $00000007;
|
||||
tomWave = $00000008;
|
||||
tomThick = $00000009;
|
||||
tomHair = $0000000A;
|
||||
tomLineSpaceSingle = $00000000;
|
||||
tomLineSpace1pt5 = $00000001;
|
||||
tomLineSpaceDouble = $00000002;
|
||||
tomLineSpaceAtLeast = $00000003;
|
||||
tomLineSpaceExactly = $00000004;
|
||||
tomLineSpaceMultiple = $00000005;
|
||||
tomAlignLeft = $00000000;
|
||||
tomAlignCenter = $00000001;
|
||||
tomAlignRight = $00000002;
|
||||
tomAlignJustify = $00000003;
|
||||
tomAlignDecimal = $00000003;
|
||||
tomAlignBar = $00000004;
|
||||
tomAlignInterWord = $00000003;
|
||||
tomAlignInterLetter = $00000004;
|
||||
tomAlignScaled = $00000005;
|
||||
tomAlignGlyphs = $00000006;
|
||||
tomAlignSnapGrid = $00000007;
|
||||
tomSpaces = $00000000;
|
||||
tomDots = $00000001;
|
||||
tomDashes = $00000002;
|
||||
tomLines = $00000003;
|
||||
tomThickLines = $00000004;
|
||||
tomEquals = $00000005;
|
||||
tomTabBack = $FFFFFFFD;
|
||||
tomTabNext = $FFFFFFFE;
|
||||
tomTabHere = $FFFFFFFF;
|
||||
tomListNone = $00000000;
|
||||
tomListBullet = $00000001;
|
||||
tomListNumberAsArabic = $00000002;
|
||||
tomListNumberAsLCLetter = $00000003;
|
||||
tomListNumberAsUCLetter = $00000004;
|
||||
tomListNumberAsLCRoman = $00000005;
|
||||
tomListNumberAsUCRoman = $00000006;
|
||||
tomListNumberAsSequence = $00000007;
|
||||
tomListParentheses = $00010000;
|
||||
tomListPeriod = $00020000;
|
||||
tomListPlain = $00030000;
|
||||
tomCharacter = $00000001;
|
||||
tomWord = $00000002;
|
||||
tomSentence = $00000003;
|
||||
tomParagraph = $00000004;
|
||||
tomLine = $00000005;
|
||||
tomStory = $00000006;
|
||||
tomScreen = $00000007;
|
||||
tomSection = $00000008;
|
||||
tomColumn = $00000009;
|
||||
tomRow = $0000000A;
|
||||
tomWindow = $0000000B;
|
||||
tomCell = $0000000C;
|
||||
tomCharFormat = $0000000D;
|
||||
tomParaFormat = $0000000E;
|
||||
tomTable = $0000000F;
|
||||
tomObject = $00000010;
|
||||
tomMatchWord = $00000002;
|
||||
tomMatchCase = $00000004;
|
||||
tomMatchPattern = $00000008;
|
||||
tomUnknownStory = $00000000;
|
||||
tomMainTextStory = $00000001;
|
||||
tomFootnotesStory = $00000002;
|
||||
tomEndnotesStory = $00000003;
|
||||
tomCommentsStory = $00000004;
|
||||
tomTextFrameStory = $00000005;
|
||||
tomEvenPagesHeaderStory = $00000006;
|
||||
tomPrimaryHeaderStory = $00000007;
|
||||
tomEvenPagesFooterStory = $00000008;
|
||||
tomPrimaryFooterStory = $00000009;
|
||||
tomFirstPageHeaderStory = $0000000A;
|
||||
tomFirstPageFooterStory = $0000000B;
|
||||
tomNoAnimation = $00000000;
|
||||
tomLasVegasLights = $00000001;
|
||||
tomBlinkingBackground = $00000002;
|
||||
tomSparkleText = $00000003;
|
||||
tomMarchingBlackAnts = $00000004;
|
||||
tomMarchingRedAnts = $00000005;
|
||||
tomShimmer = $00000006;
|
||||
tomWipeDown = $00000007;
|
||||
tomWipeRight = $00000008;
|
||||
tomAnimationMax = $00000008;
|
||||
tomLowerCase = $00000000;
|
||||
tomUpperCase = $00000001;
|
||||
tomTitleCase = $00000002;
|
||||
tomSentenceCase = $00000004;
|
||||
tomToggleCase = $00000005;
|
||||
tomReadOnly = $00000100;
|
||||
tomShareDenyRead = $00000200;
|
||||
tomShareDenyWrite = $00000400;
|
||||
tomPasteFile = $00001000;
|
||||
tomCreateNew = $00000010;
|
||||
tomCreateAlways = $00000020;
|
||||
tomOpenExisting = $00000030;
|
||||
tomOpenAlways = $00000040;
|
||||
tomTruncateExisting = $00000050;
|
||||
tomRTF = $00000001;
|
||||
tomText = $00000002;
|
||||
tomHTML = $00000003;
|
||||
tomWordDocument = $00000004;
|
||||
tomBold = $80000001;
|
||||
tomItalic = $80000002;
|
||||
tomUnderline = $80000004;
|
||||
tomStrikeout = $80000008;
|
||||
tomProtected = $80000010;
|
||||
tomLink = $80000020;
|
||||
tomSmallCaps = $80000040;
|
||||
tomAllCaps = $80000080;
|
||||
tomHidden = $80000100;
|
||||
tomOutline = $80000200;
|
||||
tomShadow = $80000400;
|
||||
tomEmboss = $80000800;
|
||||
tomImprint = $80001000;
|
||||
tomDisabled = $80002000;
|
||||
tomRevised = $80004000;
|
||||
tomNormalCaret = $00000000;
|
||||
tomKoreanBlockCaret = $00000001;
|
||||
tomIncludeInset = $00000001;
|
||||
tomIgnoreCurrentFont = $00000000;
|
||||
tomMatchFontCharset = $00000001;
|
||||
tomMatchFontSignature = $00000002;
|
||||
tomCharset = $80000000;
|
||||
tomRE10Mode = $00000001;
|
||||
tomNoIME = $00080000;
|
||||
tomSelfIME = $00040000;
|
||||
|
||||
type
|
||||
|
||||
// *********************************************************************//
|
||||
// Forward declaration of types defined in TypeLibrary
|
||||
// *********************************************************************//
|
||||
ITextDocument = interface;
|
||||
ITextDocumentDisp = dispinterface;
|
||||
ITextRange = interface;
|
||||
ITextRangeDisp = dispinterface;
|
||||
ITextSelection = interface;
|
||||
ITextSelectionDisp = dispinterface;
|
||||
ITextFont = interface;
|
||||
ITextFontDisp = dispinterface;
|
||||
ITextPara = interface;
|
||||
ITextParaDisp = dispinterface;
|
||||
ITextStoryRanges = interface;
|
||||
ITextStoryRangesDisp = dispinterface;
|
||||
ITextDocument2 = interface;
|
||||
ITextDocument2Disp = dispinterface;
|
||||
ITextMsgFilter = interface;
|
||||
|
||||
// *********************************************************************//
|
||||
// Declaration of structures, unions and aliases.
|
||||
// *********************************************************************//
|
||||
wireHWND = ^_RemotableHandle;
|
||||
POleVariant1 = ^OleVariant; {*}
|
||||
PInteger1 = ^Integer; {*}
|
||||
|
||||
tomConstants = __MIDL___MIDL_itf_tom_0000_0000_0001;
|
||||
|
||||
__MIDL_IWinTypes_0009 = record
|
||||
case Integer of
|
||||
0: (hInproc: Integer);
|
||||
1: (hRemote: Integer);
|
||||
end;
|
||||
|
||||
_RemotableHandle = record
|
||||
fContext: Integer;
|
||||
u: __MIDL_IWinTypes_0009;
|
||||
end;
|
||||
|
||||
UINT_PTR = LongWord;
|
||||
LONG_PTR = Integer;
|
||||
|
||||
// *********************************************************************//
|
||||
// Interface: ITextDocument
|
||||
// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable
|
||||
// GUID: {8CC497C0-A1DF-11CE-8098-00AA0047BE5D}
|
||||
// *********************************************************************//
|
||||
ITextDocument = interface(IDispatch)
|
||||
['{8CC497C0-A1DF-11CE-8098-00AA0047BE5D}']
|
||||
function Get_Name: WideString; safecall;
|
||||
function Get_Selection: ITextSelection; safecall;
|
||||
function Get_StoryCount: Integer; safecall;
|
||||
function Get_StoryRanges: ITextStoryRanges; safecall;
|
||||
function Get_Saved: Integer; safecall;
|
||||
procedure Set_Saved(pValue: Integer); safecall;
|
||||
function Get_DefaultTabStop: Single; safecall;
|
||||
procedure Set_DefaultTabStop(pValue: Single); safecall;
|
||||
procedure New; safecall;
|
||||
procedure Open(const pVar: OleVariant; Flags: Integer; CodePage: Integer); safecall;
|
||||
procedure Save(const pVar: OleVariant; Flags: Integer; CodePage: Integer); safecall;
|
||||
function Freeze: Integer; safecall;
|
||||
function Unfreeze: Integer; safecall;
|
||||
procedure BeginEditCollection; safecall;
|
||||
procedure EndEditCollection; safecall;
|
||||
function Undo(Count: Integer): Integer; safecall;
|
||||
function Redo(Count: Integer): Integer; safecall;
|
||||
function Range(cp1: Integer; cp2: Integer): ITextRange; safecall;
|
||||
function RangeFromPoint(x: Integer; y: Integer): ITextRange; safecall;
|
||||
property Name: WideString read Get_Name;
|
||||
property Selection: ITextSelection read Get_Selection;
|
||||
property StoryCount: Integer read Get_StoryCount;
|
||||
property StoryRanges: ITextStoryRanges read Get_StoryRanges;
|
||||
property Saved: Integer read Get_Saved write Set_Saved;
|
||||
property DefaultTabStop: Single read Get_DefaultTabStop write Set_DefaultTabStop;
|
||||
end;
|
||||
|
||||
// *********************************************************************//
|
||||
// DispIntf: ITextDocumentDisp
|
||||
// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable
|
||||
// GUID: {8CC497C0-A1DF-11CE-8098-00AA0047BE5D}
|
||||
// *********************************************************************//
|
||||
ITextDocumentDisp = dispinterface
|
||||
['{8CC497C0-A1DF-11CE-8098-00AA0047BE5D}']
|
||||
property Name: WideString readonly dispid 0;
|
||||
property Selection: ITextSelection readonly dispid 1;
|
||||
property StoryCount: Integer readonly dispid 2;
|
||||
property StoryRanges: ITextStoryRanges readonly dispid 3;
|
||||
property Saved: Integer dispid 4;
|
||||
property DefaultTabStop: Single dispid 5;
|
||||
procedure New; dispid 6;
|
||||
procedure Open(const pVar: OleVariant; Flags: Integer; CodePage: Integer); dispid 7;
|
||||
procedure Save(const pVar: OleVariant; Flags: Integer; CodePage: Integer); dispid 8;
|
||||
function Freeze: Integer; dispid 9;
|
||||
function Unfreeze: Integer; dispid 10;
|
||||
procedure BeginEditCollection; dispid 11;
|
||||
procedure EndEditCollection; dispid 12;
|
||||
function Undo(Count: Integer): Integer; dispid 13;
|
||||
function Redo(Count: Integer): Integer; dispid 14;
|
||||
function Range(cp1: Integer; cp2: Integer): ITextRange; dispid 15;
|
||||
function RangeFromPoint(x: Integer; y: Integer): ITextRange; dispid 16;
|
||||
end;
|
||||
|
||||
// *********************************************************************//
|
||||
// Interface: ITextRange
|
||||
// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable
|
||||
// GUID: {8CC497C2-A1DF-11CE-8098-00AA0047BE5D}
|
||||
// *********************************************************************//
|
||||
ITextRange = interface(IDispatch)
|
||||
['{8CC497C2-A1DF-11CE-8098-00AA0047BE5D}']
|
||||
function Get_Text: WideString; safecall;
|
||||
procedure Set_Text(const pbstr: WideString); safecall;
|
||||
function Get_Char: Integer; safecall;
|
||||
procedure Set_Char(pch: Integer); safecall;
|
||||
function Get_Duplicate: ITextRange; safecall;
|
||||
function Get_FormattedText: ITextRange; safecall;
|
||||
procedure Set_FormattedText(const ppRange: ITextRange); safecall;
|
||||
function Get_Start: Integer; safecall;
|
||||
procedure Set_Start(pcpFirst: Integer); safecall;
|
||||
function Get_End_: Integer; safecall;
|
||||
procedure Set_End_(pcpLim: Integer); safecall;
|
||||
function Get_Font: ITextFont; safecall;
|
||||
procedure Set_Font(const pFont: ITextFont); safecall;
|
||||
function Get_Para: ITextPara; safecall;
|
||||
procedure Set_Para(const pPara: ITextPara); safecall;
|
||||
function Get_StoryLength: Integer; safecall;
|
||||
function Get_StoryType: Integer; safecall;
|
||||
procedure Collapse(bStart: Integer); safecall;
|
||||
function Expand(Unit_: Integer): Integer; safecall;
|
||||
function GetIndex(Unit_: Integer): Integer; safecall;
|
||||
procedure SetIndex(Unit_: Integer; Index: Integer; Extend: Integer); safecall;
|
||||
procedure SetRange(cpActive: Integer; cpOther: Integer); safecall;
|
||||
function InRange(const pRange: ITextRange): Integer; safecall;
|
||||
function InStory(const pRange: ITextRange): Integer; safecall;
|
||||
function IsEqual(const pRange: ITextRange): Integer; safecall;
|
||||
procedure Select; safecall;
|
||||
function StartOf(Unit_: Integer; Extend: Integer): Integer; safecall;
|
||||
function EndOf(Unit_: Integer; Extend: Integer): Integer; safecall;
|
||||
function Move(Unit_: Integer; Count: Integer): Integer; safecall;
|
||||
function MoveStart(Unit_: Integer; Count: Integer): Integer; safecall;
|
||||
function MoveEnd(Unit_: Integer; Count: Integer): Integer; safecall;
|
||||
function MoveWhile(const Cset: OleVariant; Count: Integer): Integer; safecall;
|
||||
function MoveStartWhile(const Cset: OleVariant; Count: Integer): Integer; safecall;
|
||||
function MoveEndWhile(const Cset: OleVariant; Count: Integer): Integer; safecall;
|
||||
function MoveUntil(const Cset: OleVariant; Count: Integer): Integer; safecall;
|
||||
function MoveStartUntil(const Cset: OleVariant; Count: Integer): Integer; safecall;
|
||||
function MoveEndUntil(const Cset: OleVariant; Count: Integer): Integer; safecall;
|
||||
function FindText(const bstr: WideString; cch: Integer; Flags: Integer): Integer; safecall;
|
||||
function FindTextStart(const bstr: WideString; cch: Integer; Flags: Integer): Integer; safecall;
|
||||
function FindTextEnd(const bstr: WideString; cch: Integer; Flags: Integer): Integer; safecall;
|
||||
function Delete(Unit_: Integer; Count: Integer): Integer; safecall;
|
||||
procedure Cut(out pVar: OleVariant); safecall;
|
||||
procedure Copy(out pVar: OleVariant); safecall;
|
||||
procedure Paste(const pVar: OleVariant; Format: Integer); safecall;
|
||||
function CanPaste(const pVar: OleVariant; Format: Integer): Integer; safecall;
|
||||
function CanEdit: Integer; safecall;
|
||||
procedure ChangeCase(Type_: Integer); safecall;
|
||||
procedure GetPoint(Type_: Integer; out px: Integer; out py: Integer); safecall;
|
||||
procedure SetPoint(x: Integer; y: Integer; Type_: Integer; Extend: Integer); safecall;
|
||||
procedure ScrollIntoView(Value: Integer); safecall;
|
||||
function GetEmbeddedObject: IUnknown; safecall;
|
||||
property Text: WideString read Get_Text write Set_Text;
|
||||
property Char: Integer read Get_Char write Set_Char;
|
||||
property Duplicate: ITextRange read Get_Duplicate;
|
||||
property FormattedText: ITextRange read Get_FormattedText write Set_FormattedText;
|
||||
property Start: Integer read Get_Start write Set_Start;
|
||||
property End_: Integer read Get_End_ write Set_End_;
|
||||
property Font: ITextFont read Get_Font write Set_Font;
|
||||
property Para: ITextPara read Get_Para write Set_Para;
|
||||
property StoryLength: Integer read Get_StoryLength;
|
||||
property StoryType: Integer read Get_StoryType;
|
||||
end;
|
||||
|
||||
// *********************************************************************//
|
||||
// DispIntf: ITextRangeDisp
|
||||
// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable
|
||||
// GUID: {8CC497C2-A1DF-11CE-8098-00AA0047BE5D}
|
||||
// *********************************************************************//
|
||||
ITextRangeDisp = dispinterface
|
||||
['{8CC497C2-A1DF-11CE-8098-00AA0047BE5D}']
|
||||
property Text: WideString dispid 0;
|
||||
property Char: Integer dispid 513;
|
||||
property Duplicate: ITextRange readonly dispid 514;
|
||||
property FormattedText: ITextRange dispid 515;
|
||||
property Start: Integer dispid 516;
|
||||
property End_: Integer dispid 517;
|
||||
property Font: ITextFont dispid 518;
|
||||
property Para: ITextPara dispid 519;
|
||||
property StoryLength: Integer readonly dispid 520;
|
||||
property StoryType: Integer readonly dispid 521;
|
||||
procedure Collapse(bStart: Integer); dispid 528;
|
||||
function Expand(Unit_: Integer): Integer; dispid 529;
|
||||
function GetIndex(Unit_: Integer): Integer; dispid 530;
|
||||
procedure SetIndex(Unit_: Integer; Index: Integer; Extend: Integer); dispid 531;
|
||||
procedure SetRange(cpActive: Integer; cpOther: Integer); dispid 532;
|
||||
function InRange(const pRange: ITextRange): Integer; dispid 533;
|
||||
function InStory(const pRange: ITextRange): Integer; dispid 534;
|
||||
function IsEqual(const pRange: ITextRange): Integer; dispid 535;
|
||||
procedure Select; dispid 536;
|
||||
function StartOf(Unit_: Integer; Extend: Integer): Integer; dispid 537;
|
||||
function EndOf(Unit_: Integer; Extend: Integer): Integer; dispid 544;
|
||||
function Move(Unit_: Integer; Count: Integer): Integer; dispid 545;
|
||||
function MoveStart(Unit_: Integer; Count: Integer): Integer; dispid 546;
|
||||
function MoveEnd(Unit_: Integer; Count: Integer): Integer; dispid 547;
|
||||
function MoveWhile(const Cset: OleVariant; Count: Integer): Integer; dispid 548;
|
||||
function MoveStartWhile(const Cset: OleVariant; Count: Integer): Integer; dispid 549;
|
||||
function MoveEndWhile(const Cset: OleVariant; Count: Integer): Integer; dispid 550;
|
||||
function MoveUntil(const Cset: OleVariant; Count: Integer): Integer; dispid 551;
|
||||
function MoveStartUntil(const Cset: OleVariant; Count: Integer): Integer; dispid 552;
|
||||
function MoveEndUntil(const Cset: OleVariant; Count: Integer): Integer; dispid 553;
|
||||
function FindText(const bstr: WideString; cch: Integer; Flags: Integer): Integer; dispid 560;
|
||||
function FindTextStart(const bstr: WideString; cch: Integer; Flags: Integer): Integer; dispid 561;
|
||||
function FindTextEnd(const bstr: WideString; cch: Integer; Flags: Integer): Integer; dispid 562;
|
||||
function Delete(Unit_: Integer; Count: Integer): Integer; dispid 563;
|
||||
procedure Cut(out pVar: OleVariant); dispid 564;
|
||||
procedure Copy(out pVar: OleVariant); dispid 565;
|
||||
procedure Paste(const pVar: OleVariant; Format: Integer); dispid 566;
|
||||
function CanPaste(const pVar: OleVariant; Format: Integer): Integer; dispid 567;
|
||||
function CanEdit: Integer; dispid 568;
|
||||
procedure ChangeCase(Type_: Integer); dispid 569;
|
||||
procedure GetPoint(Type_: Integer; out px: Integer; out py: Integer); dispid 576;
|
||||
procedure SetPoint(x: Integer; y: Integer; Type_: Integer; Extend: Integer); dispid 577;
|
||||
procedure ScrollIntoView(Value: Integer); dispid 578;
|
||||
function GetEmbeddedObject: IUnknown; dispid 579;
|
||||
end;
|
||||
|
||||
// *********************************************************************//
|
||||
// Interface: ITextSelection
|
||||
// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable
|
||||
// GUID: {8CC497C1-A1DF-11CE-8098-00AA0047BE5D}
|
||||
// *********************************************************************//
|
||||
ITextSelection = interface(ITextRange)
|
||||
['{8CC497C1-A1DF-11CE-8098-00AA0047BE5D}']
|
||||
function Get_Flags: Integer; safecall;
|
||||
procedure Set_Flags(pFlags: Integer); safecall;
|
||||
function Get_type_: Integer; safecall;
|
||||
function MoveLeft(Unit_: Integer; Count: Integer; Extend: Integer): Integer; safecall;
|
||||
function MoveRight(Unit_: Integer; Count: Integer; Extend: Integer): Integer; safecall;
|
||||
function MoveUp(Unit_: Integer; Count: Integer; Extend: Integer): Integer; safecall;
|
||||
function MoveDown(Unit_: Integer; Count: Integer; Extend: Integer): Integer; safecall;
|
||||
function HomeKey(Unit_: Integer; Extend: Integer): Integer; safecall;
|
||||
function EndKey(Unit_: Integer; Extend: Integer): Integer; safecall;
|
||||
procedure TypeText(const bstr: WideString); safecall;
|
||||
property Flags: Integer read Get_Flags write Set_Flags;
|
||||
property type_: Integer read Get_type_;
|
||||
end;
|
||||
|
||||
// *********************************************************************//
|
||||
// DispIntf: ITextSelectionDisp
|
||||
// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable
|
||||
// GUID: {8CC497C1-A1DF-11CE-8098-00AA0047BE5D}
|
||||
// *********************************************************************//
|
||||
ITextSelectionDisp = dispinterface
|
||||
['{8CC497C1-A1DF-11CE-8098-00AA0047BE5D}']
|
||||
property Flags: Integer dispid 257;
|
||||
property type_: Integer readonly dispid 258;
|
||||
function MoveLeft(Unit_: Integer; Count: Integer; Extend: Integer): Integer; dispid 259;
|
||||
function MoveRight(Unit_: Integer; Count: Integer; Extend: Integer): Integer; dispid 260;
|
||||
function MoveUp(Unit_: Integer; Count: Integer; Extend: Integer): Integer; dispid 261;
|
||||
function MoveDown(Unit_: Integer; Count: Integer; Extend: Integer): Integer; dispid 262;
|
||||
function HomeKey(Unit_: Integer; Extend: Integer): Integer; dispid 263;
|
||||
function EndKey(Unit_: Integer; Extend: Integer): Integer; dispid 264;
|
||||
procedure TypeText(const bstr: WideString); dispid 265;
|
||||
property Text: WideString dispid 0;
|
||||
property Char: Integer dispid 513;
|
||||
property Duplicate: ITextRange readonly dispid 514;
|
||||
property FormattedText: ITextRange dispid 515;
|
||||
property Start: Integer dispid 516;
|
||||
property End_: Integer dispid 517;
|
||||
property Font: ITextFont dispid 518;
|
||||
property Para: ITextPara dispid 519;
|
||||
property StoryLength: Integer readonly dispid 520;
|
||||
property StoryType: Integer readonly dispid 521;
|
||||
procedure Collapse(bStart: Integer); dispid 528;
|
||||
function Expand(Unit_: Integer): Integer; dispid 529;
|
||||
function GetIndex(Unit_: Integer): Integer; dispid 530;
|
||||
procedure SetIndex(Unit_: Integer; Index: Integer; Extend: Integer); dispid 531;
|
||||
procedure SetRange(cpActive: Integer; cpOther: Integer); dispid 532;
|
||||
function InRange(const pRange: ITextRange): Integer; dispid 533;
|
||||
function InStory(const pRange: ITextRange): Integer; dispid 534;
|
||||
function IsEqual(const pRange: ITextRange): Integer; dispid 535;
|
||||
procedure Select; dispid 536;
|
||||
function StartOf(Unit_: Integer; Extend: Integer): Integer; dispid 537;
|
||||
function EndOf(Unit_: Integer; Extend: Integer): Integer; dispid 544;
|
||||
function Move(Unit_: Integer; Count: Integer): Integer; dispid 545;
|
||||
function MoveStart(Unit_: Integer; Count: Integer): Integer; dispid 546;
|
||||
function MoveEnd(Unit_: Integer; Count: Integer): Integer; dispid 547;
|
||||
function MoveWhile(const Cset: OleVariant; Count: Integer): Integer; dispid 548;
|
||||
function MoveStartWhile(const Cset: OleVariant; Count: Integer): Integer; dispid 549;
|
||||
function MoveEndWhile(const Cset: OleVariant; Count: Integer): Integer; dispid 550;
|
||||
function MoveUntil(const Cset: OleVariant; Count: Integer): Integer; dispid 551;
|
||||
function MoveStartUntil(const Cset: OleVariant; Count: Integer): Integer; dispid 552;
|
||||
function MoveEndUntil(const Cset: OleVariant; Count: Integer): Integer; dispid 553;
|
||||
function FindText(const bstr: WideString; cch: Integer; Flags: Integer): Integer; dispid 560;
|
||||
function FindTextStart(const bstr: WideString; cch: Integer; Flags: Integer): Integer; dispid 561;
|
||||
function FindTextEnd(const bstr: WideString; cch: Integer; Flags: Integer): Integer; dispid 562;
|
||||
function Delete(Unit_: Integer; Count: Integer): Integer; dispid 563;
|
||||
procedure Cut(out pVar: OleVariant); dispid 564;
|
||||
procedure Copy(out pVar: OleVariant); dispid 565;
|
||||
procedure Paste(const pVar: OleVariant; Format: Integer); dispid 566;
|
||||
function CanPaste(const pVar: OleVariant; Format: Integer): Integer; dispid 567;
|
||||
function CanEdit: Integer; dispid 568;
|
||||
procedure ChangeCase(Type_: Integer); dispid 569;
|
||||
procedure GetPoint(Type_: Integer; out px: Integer; out py: Integer); dispid 576;
|
||||
procedure SetPoint(x: Integer; y: Integer; Type_: Integer; Extend: Integer); dispid 577;
|
||||
procedure ScrollIntoView(Value: Integer); dispid 578;
|
||||
function GetEmbeddedObject: IUnknown; dispid 579;
|
||||
end;
|
||||
|
||||
// *********************************************************************//
|
||||
// Interface: ITextFont
|
||||
// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable
|
||||
// GUID: {8CC497C3-A1DF-11CE-8098-00AA0047BE5D}
|
||||
// *********************************************************************//
|
||||
ITextFont = interface(IDispatch)
|
||||
['{8CC497C3-A1DF-11CE-8098-00AA0047BE5D}']
|
||||
function Get_Duplicate: ITextFont; safecall;
|
||||
procedure Set_Duplicate(const ppFont: ITextFont); safecall;
|
||||
function CanChange: Integer; safecall;
|
||||
function IsEqual(const pFont: ITextFont): Integer; safecall;
|
||||
procedure Reset(Value: Integer); safecall;
|
||||
function Get_Style: Integer; safecall;
|
||||
procedure Set_Style(pValue: Integer); safecall;
|
||||
function Get_AllCaps: Integer; safecall;
|
||||
procedure Set_AllCaps(pValue: Integer); safecall;
|
||||
function Get_Animation: Integer; safecall;
|
||||
procedure Set_Animation(pValue: Integer); safecall;
|
||||
function Get_BackColor: Integer; safecall;
|
||||
procedure Set_BackColor(pValue: Integer); safecall;
|
||||
function Get_Bold: Integer; safecall;
|
||||
procedure Set_Bold(pValue: Integer); safecall;
|
||||
function Get_Emboss: Integer; safecall;
|
||||
procedure Set_Emboss(pValue: Integer); safecall;
|
||||
function Get_ForeColor: Integer; safecall;
|
||||
procedure Set_ForeColor(pValue: Integer); safecall;
|
||||
function Get_Hidden: Integer; safecall;
|
||||
procedure Set_Hidden(pValue: Integer); safecall;
|
||||
function Get_Engrave: Integer; safecall;
|
||||
procedure Set_Engrave(pValue: Integer); safecall;
|
||||
function Get_Italic: Integer; safecall;
|
||||
procedure Set_Italic(pValue: Integer); safecall;
|
||||
function Get_Kerning: Single; safecall;
|
||||
procedure Set_Kerning(pValue: Single); safecall;
|
||||
function Get_LanguageID: Integer; safecall;
|
||||
procedure Set_LanguageID(pValue: Integer); safecall;
|
||||
function Get_Name: WideString; safecall;
|
||||
procedure Set_Name(const pbstr: WideString); safecall;
|
||||
function Get_Outline: Integer; safecall;
|
||||
procedure Set_Outline(pValue: Integer); safecall;
|
||||
function Get_Position: Single; safecall;
|
||||
procedure Set_Position(pValue: Single); safecall;
|
||||
function Get_Protected_: Integer; safecall;
|
||||
procedure Set_Protected_(pValue: Integer); safecall;
|
||||
function Get_Shadow: Integer; safecall;
|
||||
procedure Set_Shadow(pValue: Integer); safecall;
|
||||
function Get_Size: Single; safecall;
|
||||
procedure Set_Size(pValue: Single); safecall;
|
||||
function Get_SmallCaps: Integer; safecall;
|
||||
procedure Set_SmallCaps(pValue: Integer); safecall;
|
||||
function Get_Spacing: Single; safecall;
|
||||
procedure Set_Spacing(pValue: Single); safecall;
|
||||
function Get_StrikeThrough: Integer; safecall;
|
||||
procedure Set_StrikeThrough(pValue: Integer); safecall;
|
||||
function Get_Subscript: Integer; safecall;
|
||||
procedure Set_Subscript(pValue: Integer); safecall;
|
||||
function Get_Superscript: Integer; safecall;
|
||||
procedure Set_Superscript(pValue: Integer); safecall;
|
||||
function Get_Underline: Integer; safecall;
|
||||
procedure Set_Underline(pValue: Integer); safecall;
|
||||
function Get_Weight: Integer; safecall;
|
||||
procedure Set_Weight(pValue: Integer); safecall;
|
||||
property Duplicate: ITextFont read Get_Duplicate write Set_Duplicate;
|
||||
property Style: Integer read Get_Style write Set_Style;
|
||||
property AllCaps: Integer read Get_AllCaps write Set_AllCaps;
|
||||
property Animation: Integer read Get_Animation write Set_Animation;
|
||||
property BackColor: Integer read Get_BackColor write Set_BackColor;
|
||||
property Bold: Integer read Get_Bold write Set_Bold;
|
||||
property Emboss: Integer read Get_Emboss write Set_Emboss;
|
||||
property ForeColor: Integer read Get_ForeColor write Set_ForeColor;
|
||||
property Hidden: Integer read Get_Hidden write Set_Hidden;
|
||||
property Engrave: Integer read Get_Engrave write Set_Engrave;
|
||||
property Italic: Integer read Get_Italic write Set_Italic;
|
||||
property Kerning: Single read Get_Kerning write Set_Kerning;
|
||||
property LanguageID: Integer read Get_LanguageID write Set_LanguageID;
|
||||
property Name: WideString read Get_Name write Set_Name;
|
||||
property Outline: Integer read Get_Outline write Set_Outline;
|
||||
property Position: Single read Get_Position write Set_Position;
|
||||
property Protected_: Integer read Get_Protected_ write Set_Protected_;
|
||||
property Shadow: Integer read Get_Shadow write Set_Shadow;
|
||||
property Size: Single read Get_Size write Set_Size;
|
||||
property SmallCaps: Integer read Get_SmallCaps write Set_SmallCaps;
|
||||
property Spacing: Single read Get_Spacing write Set_Spacing;
|
||||
property StrikeThrough: Integer read Get_StrikeThrough write Set_StrikeThrough;
|
||||
property Subscript: Integer read Get_Subscript write Set_Subscript;
|
||||
property Superscript: Integer read Get_Superscript write Set_Superscript;
|
||||
property Underline: Integer read Get_Underline write Set_Underline;
|
||||
property Weight: Integer read Get_Weight write Set_Weight;
|
||||
end;
|
||||
|
||||
// *********************************************************************//
|
||||
// DispIntf: ITextFontDisp
|
||||
// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable
|
||||
// GUID: {8CC497C3-A1DF-11CE-8098-00AA0047BE5D}
|
||||
// *********************************************************************//
|
||||
ITextFontDisp = dispinterface
|
||||
['{8CC497C3-A1DF-11CE-8098-00AA0047BE5D}']
|
||||
property Duplicate: ITextFont dispid 0;
|
||||
function CanChange: Integer; dispid 769;
|
||||
function IsEqual(const pFont: ITextFont): Integer; dispid 770;
|
||||
procedure Reset(Value: Integer); dispid 771;
|
||||
property Style: Integer dispid 772;
|
||||
property AllCaps: Integer dispid 773;
|
||||
property Animation: Integer dispid 774;
|
||||
property BackColor: Integer dispid 775;
|
||||
property Bold: Integer dispid 776;
|
||||
property Emboss: Integer dispid 777;
|
||||
property ForeColor: Integer dispid 784;
|
||||
property Hidden: Integer dispid 785;
|
||||
property Engrave: Integer dispid 786;
|
||||
property Italic: Integer dispid 787;
|
||||
property Kerning: Single dispid 788;
|
||||
property LanguageID: Integer dispid 789;
|
||||
property Name: WideString dispid 790;
|
||||
property Outline: Integer dispid 791;
|
||||
property Position: Single dispid 792;
|
||||
property Protected_: Integer dispid 793;
|
||||
property Shadow: Integer dispid 800;
|
||||
property Size: Single dispid 801;
|
||||
property SmallCaps: Integer dispid 802;
|
||||
property Spacing: Single dispid 803;
|
||||
property StrikeThrough: Integer dispid 804;
|
||||
property Subscript: Integer dispid 805;
|
||||
property Superscript: Integer dispid 806;
|
||||
property Underline: Integer dispid 807;
|
||||
property Weight: Integer dispid 808;
|
||||
end;
|
||||
|
||||
// *********************************************************************//
|
||||
// Interface: ITextPara
|
||||
// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable
|
||||
// GUID: {8CC497C4-A1DF-11CE-8098-00AA0047BE5D}
|
||||
// *********************************************************************//
|
||||
ITextPara = interface(IDispatch)
|
||||
['{8CC497C4-A1DF-11CE-8098-00AA0047BE5D}']
|
||||
function Get_Duplicate: ITextPara; safecall;
|
||||
procedure Set_Duplicate(const ppPara: ITextPara); safecall;
|
||||
function CanChange: Integer; safecall;
|
||||
function IsEqual(const pPara: ITextPara): Integer; safecall;
|
||||
procedure Reset(Value: Integer); safecall;
|
||||
function Get_Style: Integer; safecall;
|
||||
procedure Set_Style(pValue: Integer); safecall;
|
||||
function Get_Alignment: Integer; safecall;
|
||||
procedure Set_Alignment(pValue: Integer); safecall;
|
||||
function Get_Hyphenation: Integer; safecall;
|
||||
procedure Set_Hyphenation(pValue: Integer); safecall;
|
||||
function Get_FirstLineIndent: Single; safecall;
|
||||
function Get_KeepTogether: Integer; safecall;
|
||||
procedure Set_KeepTogether(pValue: Integer); safecall;
|
||||
function Get_KeepWithNext: Integer; safecall;
|
||||
procedure Set_KeepWithNext(pValue: Integer); safecall;
|
||||
function Get_LeftIndent: Single; safecall;
|
||||
function Get_LineSpacing: Single; safecall;
|
||||
function Get_LineSpacingRule: Integer; safecall;
|
||||
function Get_ListAlignment: Integer; safecall;
|
||||
procedure Set_ListAlignment(pValue: Integer); safecall;
|
||||
function Get_ListLevelIndex: Integer; safecall;
|
||||
procedure Set_ListLevelIndex(pValue: Integer); safecall;
|
||||
function Get_ListStart: Integer; safecall;
|
||||
procedure Set_ListStart(pValue: Integer); safecall;
|
||||
function Get_ListTab: Single; safecall;
|
||||
procedure Set_ListTab(pValue: Single); safecall;
|
||||
function Get_ListType: Integer; safecall;
|
||||
procedure Set_ListType(pValue: Integer); safecall;
|
||||
function Get_NoLineNumber: Integer; safecall;
|
||||
procedure Set_NoLineNumber(pValue: Integer); safecall;
|
||||
function Get_PageBreakBefore: Integer; safecall;
|
||||
procedure Set_PageBreakBefore(pValue: Integer); safecall;
|
||||
function Get_RightIndent: Single; safecall;
|
||||
procedure Set_RightIndent(pValue: Single); safecall;
|
||||
procedure SetIndents(StartIndent: Single; LeftIndent: Single; RightIndent: Single); safecall;
|
||||
procedure SetLineSpacing(LineSpacingRule: Integer; LineSpacing: Single); safecall;
|
||||
function Get_SpaceAfter: Single; safecall;
|
||||
procedure Set_SpaceAfter(pValue: Single); safecall;
|
||||
function Get_SpaceBefore: Single; safecall;
|
||||
procedure Set_SpaceBefore(pValue: Single); safecall;
|
||||
function Get_WidowControl: Integer; safecall;
|
||||
procedure Set_WidowControl(pValue: Integer); safecall;
|
||||
function Get_TabCount: Integer; safecall;
|
||||
procedure AddTab(tbPos: Single; tbAlign: Integer; tbLeader: Integer); safecall;
|
||||
procedure ClearAllTabs; safecall;
|
||||
procedure DeleteTab(tbPos: Single); safecall;
|
||||
procedure GetTab(iTab: Integer; out ptbPos: Single; out ptbAlign: Integer;
|
||||
out ptbLeader: Integer); safecall;
|
||||
property Duplicate: ITextPara read Get_Duplicate write Set_Duplicate;
|
||||
property Style: Integer read Get_Style write Set_Style;
|
||||
property Alignment: Integer read Get_Alignment write Set_Alignment;
|
||||
property Hyphenation: Integer read Get_Hyphenation write Set_Hyphenation;
|
||||
property FirstLineIndent: Single read Get_FirstLineIndent;
|
||||
property KeepTogether: Integer read Get_KeepTogether write Set_KeepTogether;
|
||||
property KeepWithNext: Integer read Get_KeepWithNext write Set_KeepWithNext;
|
||||
property LeftIndent: Single read Get_LeftIndent;
|
||||
property LineSpacing: Single read Get_LineSpacing;
|
||||
property LineSpacingRule: Integer read Get_LineSpacingRule;
|
||||
property ListAlignment: Integer read Get_ListAlignment write Set_ListAlignment;
|
||||
property ListLevelIndex: Integer read Get_ListLevelIndex write Set_ListLevelIndex;
|
||||
property ListStart: Integer read Get_ListStart write Set_ListStart;
|
||||
property ListTab: Single read Get_ListTab write Set_ListTab;
|
||||
property ListType: Integer read Get_ListType write Set_ListType;
|
||||
property NoLineNumber: Integer read Get_NoLineNumber write Set_NoLineNumber;
|
||||
property PageBreakBefore: Integer read Get_PageBreakBefore write Set_PageBreakBefore;
|
||||
property RightIndent: Single read Get_RightIndent write Set_RightIndent;
|
||||
property SpaceAfter: Single read Get_SpaceAfter write Set_SpaceAfter;
|
||||
property SpaceBefore: Single read Get_SpaceBefore write Set_SpaceBefore;
|
||||
property WidowControl: Integer read Get_WidowControl write Set_WidowControl;
|
||||
property TabCount: Integer read Get_TabCount;
|
||||
end;
|
||||
|
||||
// *********************************************************************//
|
||||
// DispIntf: ITextParaDisp
|
||||
// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable
|
||||
// GUID: {8CC497C4-A1DF-11CE-8098-00AA0047BE5D}
|
||||
// *********************************************************************//
|
||||
ITextParaDisp = dispinterface
|
||||
['{8CC497C4-A1DF-11CE-8098-00AA0047BE5D}']
|
||||
property Duplicate: ITextPara dispid 0;
|
||||
function CanChange: Integer; dispid 1025;
|
||||
function IsEqual(const pPara: ITextPara): Integer; dispid 1026;
|
||||
procedure Reset(Value: Integer); dispid 1027;
|
||||
property Style: Integer dispid 1028;
|
||||
property Alignment: Integer dispid 1029;
|
||||
property Hyphenation: Integer dispid 1030;
|
||||
property FirstLineIndent: Single readonly dispid 1031;
|
||||
property KeepTogether: Integer dispid 1032;
|
||||
property KeepWithNext: Integer dispid 1033;
|
||||
property LeftIndent: Single readonly dispid 1040;
|
||||
property LineSpacing: Single readonly dispid 1041;
|
||||
property LineSpacingRule: Integer readonly dispid 1042;
|
||||
property ListAlignment: Integer dispid 1043;
|
||||
property ListLevelIndex: Integer dispid 1044;
|
||||
property ListStart: Integer dispid 1045;
|
||||
property ListTab: Single dispid 1046;
|
||||
property ListType: Integer dispid 1047;
|
||||
property NoLineNumber: Integer dispid 1048;
|
||||
property PageBreakBefore: Integer dispid 1049;
|
||||
property RightIndent: Single dispid 1056;
|
||||
procedure SetIndents(StartIndent: Single; LeftIndent: Single; RightIndent: Single); dispid 1057;
|
||||
procedure SetLineSpacing(LineSpacingRule: Integer; LineSpacing: Single); dispid 1058;
|
||||
property SpaceAfter: Single dispid 1059;
|
||||
property SpaceBefore: Single dispid 1060;
|
||||
property WidowControl: Integer dispid 1061;
|
||||
property TabCount: Integer readonly dispid 1062;
|
||||
procedure AddTab(tbPos: Single; tbAlign: Integer; tbLeader: Integer); dispid 1063;
|
||||
procedure ClearAllTabs; dispid 1064;
|
||||
procedure DeleteTab(tbPos: Single); dispid 1065;
|
||||
procedure GetTab(iTab: Integer; out ptbPos: Single; out ptbAlign: Integer;
|
||||
out ptbLeader: Integer); dispid 1072;
|
||||
end;
|
||||
|
||||
// *********************************************************************//
|
||||
// Interface: ITextStoryRanges
|
||||
// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable
|
||||
// GUID: {8CC497C5-A1DF-11CE-8098-00AA0047BE5D}
|
||||
// *********************************************************************//
|
||||
ITextStoryRanges = interface(IDispatch)
|
||||
['{8CC497C5-A1DF-11CE-8098-00AA0047BE5D}']
|
||||
function _NewEnum: IUnknown; safecall;
|
||||
function Item(Index: Integer): ITextRange; safecall;
|
||||
function Get_Count: Integer; safecall;
|
||||
property Count: Integer read Get_Count;
|
||||
end;
|
||||
|
||||
// *********************************************************************//
|
||||
// DispIntf: ITextStoryRangesDisp
|
||||
// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable
|
||||
// GUID: {8CC497C5-A1DF-11CE-8098-00AA0047BE5D}
|
||||
// *********************************************************************//
|
||||
ITextStoryRangesDisp = dispinterface
|
||||
['{8CC497C5-A1DF-11CE-8098-00AA0047BE5D}']
|
||||
function _NewEnum: IUnknown; dispid -4;
|
||||
function Item(Index: Integer): ITextRange; dispid 0;
|
||||
property Count: Integer readonly dispid 2;
|
||||
end;
|
||||
|
||||
// *********************************************************************//
|
||||
// Interface: ITextDocument2
|
||||
// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable
|
||||
// GUID: {01C25500-4268-11D1-883A-3C8B00C10000}
|
||||
// *********************************************************************//
|
||||
ITextDocument2 = interface(ITextDocument)
|
||||
['{01C25500-4268-11D1-883A-3C8B00C10000}']
|
||||
procedure AttachMsgFilter(const pFilter: IUnknown); safecall;
|
||||
procedure SetEffectColor(Index: Integer; cr: LongWord); safecall;
|
||||
procedure GetEffectColor(Index: Integer; out pcr: LongWord); safecall;
|
||||
function Get_CaretType: Integer; safecall;
|
||||
procedure Set_CaretType(pCaretType: Integer); safecall;
|
||||
function GetImmContext: Integer; safecall;
|
||||
procedure ReleaseImmContext(Context: Integer); safecall;
|
||||
procedure GetPreferredFont(cp: Integer; CodePage: Integer; Option: Integer;
|
||||
curCodepage: Integer; curFontSize: Integer; out pbstr: WideString;
|
||||
out pPitchAndFamily: Integer; out pNewFontSize: Integer); safecall;
|
||||
function Get_NotificationMode: Integer; safecall;
|
||||
procedure Set_NotificationMode(pMode: Integer); safecall;
|
||||
procedure GetClientRect(Type_: Integer; out pLeft: Integer; out pTop: Integer;
|
||||
out pRight: Integer; out pBottom: Integer); safecall;
|
||||
function Get_SelectionEx: ITextSelection; safecall;
|
||||
procedure GetWindow(out phWnd: Integer); safecall;
|
||||
procedure GetFEFlags(out pFlags: Integer); safecall;
|
||||
procedure UpdateWindow; safecall;
|
||||
procedure CheckTextLimit(cch: Integer; var pcch: Integer); safecall;
|
||||
procedure IMEInProgress(Mode: Integer); safecall;
|
||||
procedure SysBeep; safecall;
|
||||
procedure Update(Mode: Integer); safecall;
|
||||
procedure Notify(Notify: Integer); safecall;
|
||||
property CaretType: Integer read Get_CaretType write Set_CaretType;
|
||||
property NotificationMode: Integer read Get_NotificationMode write Set_NotificationMode;
|
||||
property SelectionEx: ITextSelection read Get_SelectionEx;
|
||||
end;
|
||||
|
||||
// *********************************************************************//
|
||||
// DispIntf: ITextDocument2Disp
|
||||
// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable
|
||||
// GUID: {01C25500-4268-11D1-883A-3C8B00C10000}
|
||||
// *********************************************************************//
|
||||
ITextDocument2Disp = dispinterface
|
||||
['{01C25500-4268-11D1-883A-3C8B00C10000}']
|
||||
procedure AttachMsgFilter(const pFilter: IUnknown); dispid 21;
|
||||
procedure SetEffectColor(Index: Integer; cr: LongWord); dispid 22;
|
||||
procedure GetEffectColor(Index: Integer; out pcr: LongWord); dispid 23;
|
||||
property CaretType: Integer dispid 24;
|
||||
function GetImmContext: Integer; dispid 25;
|
||||
procedure ReleaseImmContext(Context: Integer); dispid 26;
|
||||
procedure GetPreferredFont(cp: Integer; CodePage: Integer; Option: Integer;
|
||||
curCodepage: Integer; curFontSize: Integer; out pbstr: WideString;
|
||||
out pPitchAndFamily: Integer; out pNewFontSize: Integer); dispid 27;
|
||||
property NotificationMode: Integer dispid 28;
|
||||
procedure GetClientRect(Type_: Integer; out pLeft: Integer; out pTop: Integer;
|
||||
out pRight: Integer; out pBottom: Integer); dispid 29;
|
||||
property SelectionEx: ITextSelection readonly dispid 30;
|
||||
procedure GetWindow(out phWnd: Integer); dispid 31;
|
||||
procedure GetFEFlags(out pFlags: Integer); dispid 32;
|
||||
procedure UpdateWindow; dispid 33;
|
||||
procedure CheckTextLimit(cch: Integer; var pcch: Integer); dispid 34;
|
||||
procedure IMEInProgress(Mode: Integer); dispid 35;
|
||||
procedure SysBeep; dispid 36;
|
||||
procedure Update(Mode: Integer); dispid 37;
|
||||
procedure Notify(Notify: Integer); dispid 38;
|
||||
property Name: WideString readonly dispid 0;
|
||||
property Selection: ITextSelection readonly dispid 1;
|
||||
property StoryCount: Integer readonly dispid 2;
|
||||
property StoryRanges: ITextStoryRanges readonly dispid 3;
|
||||
property Saved: Integer dispid 4;
|
||||
property DefaultTabStop: Single dispid 5;
|
||||
procedure New; dispid 6;
|
||||
procedure Open(const pVar: OleVariant; Flags: Integer; CodePage: Integer); dispid 7;
|
||||
procedure Save(const pVar: OleVariant; Flags: Integer; CodePage: Integer); dispid 8;
|
||||
function Freeze: Integer; dispid 9;
|
||||
function Unfreeze: Integer; dispid 10;
|
||||
procedure BeginEditCollection; dispid 11;
|
||||
procedure EndEditCollection; dispid 12;
|
||||
function Undo(Count: Integer): Integer; dispid 13;
|
||||
function Redo(Count: Integer): Integer; dispid 14;
|
||||
function Range(cp1: Integer; cp2: Integer): ITextRange; dispid 15;
|
||||
function RangeFromPoint(x: Integer; y: Integer): ITextRange; dispid 16;
|
||||
end;
|
||||
|
||||
// *********************************************************************//
|
||||
// Interface: ITextMsgFilter
|
||||
// Flags: (128) NonExtensible
|
||||
// GUID: {A3787420-4267-11D1-883A-3C8B00C10000}
|
||||
// *********************************************************************//
|
||||
ITextMsgFilter = interface(IUnknown)
|
||||
['{A3787420-4267-11D1-883A-3C8B00C10000}']
|
||||
function AttachDocument(var hwnd: _RemotableHandle; const pTextDoc: ITextDocument2): HResult; stdcall;
|
||||
function HandleMessage(var pmsg: SYSUINT; var pwparam: UINT_PTR; var plparam: LONG_PTR;
|
||||
out plres: LONG_PTR): HResult; stdcall;
|
||||
function AttachMsgFilter(const pMsgFilter: ITextMsgFilter): HResult; stdcall;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses System.Win.ComObj;
|
||||
|
||||
end.
|
||||
|
|
@ -5,6 +5,7 @@ import { CompilerEvent, CompilerCallbacks, CompilerPathCallbacks, CompilerFileSy
|
|||
CompilerFileSystemAsyncCallbacks,
|
||||
CompilerErrorSeverity} from '@keymanapp/developer-utils';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { Suite } from 'mocha';
|
||||
|
||||
const { TEST_SAVE_FIXTURES } = process.env;
|
||||
|
||||
|
|
@ -12,16 +13,27 @@ const { TEST_SAVE_FIXTURES } = process.env;
|
|||
* A CompilerCallbacks implementation for testing
|
||||
*/
|
||||
export class TestCompilerCallbacks implements CompilerCallbacks {
|
||||
/* TestCompilerCallbacks */
|
||||
|
||||
private readonly suite: Suite;
|
||||
messages: CompilerEvent[] = [];
|
||||
readonly _net: TestCompilerNetAsyncCallbacks;
|
||||
readonly _fsAsync: DefaultCompilerFileSystemAsyncCallbacks = new DefaultCompilerFileSystemAsyncCallbacks(this);
|
||||
|
||||
constructor(basePath?: string) {
|
||||
constructor(suite?: Suite, basePath?: string) {
|
||||
if(basePath) {
|
||||
this._net = new TestCompilerNetAsyncCallbacks(basePath);
|
||||
}
|
||||
this.suite = suite;
|
||||
if(this.suite) {
|
||||
const _this = this;
|
||||
this.suite.beforeEach(function() {
|
||||
_this.clear();
|
||||
});
|
||||
this.suite.afterEach(function() {
|
||||
if(this.currentTest?.isFailed()) {
|
||||
_this.printMessages();
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
clear() {
|
||||
|
|
@ -55,7 +67,7 @@ export class TestCompilerCallbacks implements CompilerCallbacks {
|
|||
|
||||
loadFile(filename: string): Uint8Array {
|
||||
try {
|
||||
return fs.readFileSync(filename);
|
||||
return fs.readFileSync(filename) as Uint8Array;
|
||||
} catch(e) {
|
||||
if (e.code === 'ENOENT') {
|
||||
return null;
|
||||
|
|
@ -162,7 +174,7 @@ class TestCompilerNetAsyncCallbacks implements CompilerNetAsyncCallbacks {
|
|||
// missing file, this is okay
|
||||
return null;
|
||||
}
|
||||
const data: Uint8Array = fs.readFileSync(p);
|
||||
const data = fs.readFileSync(p) as Uint8Array;
|
||||
return data;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
"dependencies": {
|
||||
"@keymanapp/common-types": "*",
|
||||
"eventemitter3": "^5.0.0",
|
||||
"fast-xml-parser": "^5.3.4",
|
||||
"fast-xml-parser": "^5.3.8",
|
||||
"path-browserify": "^1.0.1",
|
||||
"restructure": "^3.0.1",
|
||||
"sax": ">=0.6.0",
|
||||
|
|
|
|||
|
|
@ -79,4 +79,10 @@ export class DeveloperUtilsMessages {
|
|||
this.ERROR_ProjectFileCouldNotBeRead,
|
||||
`Project file could not be read`
|
||||
);
|
||||
|
||||
static ERROR_NotAPackageFile = SevError | 0x000D;
|
||||
static Error_NotAPackageFile = () => m(
|
||||
this.ERROR_NotAPackageFile,
|
||||
`Package source file is not a valid .kps file because it is missing the <Package> root element.`,
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -22,19 +22,17 @@ export class KpsFileReader {
|
|||
public read(file: Uint8Array): KpsPackage {
|
||||
const data = new TextDecoder().decode(file);
|
||||
|
||||
const kpsPackage = (() => {
|
||||
let a: KpsPackage;
|
||||
let kpsPackage: KpsPackage = null;
|
||||
try {
|
||||
kpsPackage = new KeymanXMLReader('kps')
|
||||
.parse(data) as KpsPackage;
|
||||
} catch(e) {
|
||||
this.callbacks.reportMessage(DeveloperUtilsMessages.Error_InvalidPackageFile({e}));
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
a = new KeymanXMLReader('kps')
|
||||
.parse(data) as KpsPackage;
|
||||
} catch(e) {
|
||||
this.callbacks.reportMessage(DeveloperUtilsMessages.Error_InvalidPackageFile({e}));
|
||||
}
|
||||
return a;
|
||||
})();
|
||||
|
||||
if(!kpsPackage) {
|
||||
if(!kpsPackage?.Package) {
|
||||
this.callbacks.reportMessage(DeveloperUtilsMessages.Error_NotAPackageFile());
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -42,12 +40,12 @@ export class KpsFileReader {
|
|||
}
|
||||
|
||||
private boxArrays(data: KpsPackage): KpsPackage {
|
||||
boxXmlArray(data.Package?.Files, 'File');
|
||||
boxXmlArray(data.Package?.Keyboards, 'Keyboard');
|
||||
boxXmlArray(data.Package?.LexicalModels, 'LexicalModel');
|
||||
boxXmlArray(data.Package?.RelatedPackages, 'RelatedPackage');
|
||||
boxXmlArray(data.Package.Files, 'File');
|
||||
boxXmlArray(data.Package.Keyboards, 'Keyboard');
|
||||
boxXmlArray(data.Package.LexicalModels, 'LexicalModel');
|
||||
boxXmlArray(data.Package.RelatedPackages, 'RelatedPackage');
|
||||
|
||||
if(data.Package?.Keyboards?.Keyboard) {
|
||||
if(data.Package.Keyboards?.Keyboard) {
|
||||
for(const k of data.Package.Keyboards.Keyboard) {
|
||||
boxXmlArray(k.Examples, 'Example');
|
||||
boxXmlArray(k.Languages, 'Language');
|
||||
|
|
@ -56,17 +54,17 @@ export class KpsFileReader {
|
|||
}
|
||||
}
|
||||
|
||||
if(data.Package?.LexicalModels?.LexicalModel) {
|
||||
if(data.Package.LexicalModels?.LexicalModel) {
|
||||
for(const lm of data.Package.LexicalModels.LexicalModel) {
|
||||
boxXmlArray(lm.Languages, 'Language');
|
||||
}
|
||||
}
|
||||
|
||||
boxXmlArray(data.Package?.RelatedPackages, 'RelatedPackage');
|
||||
boxXmlArray(data.Package?.StartMenu?.Items, 'Item');
|
||||
boxXmlArray(data.Package?.Strings, 'String');
|
||||
boxXmlArray(data.Package.RelatedPackages, 'RelatedPackage');
|
||||
boxXmlArray(data.Package.StartMenu?.Items, 'Item');
|
||||
boxXmlArray(data.Package.Strings, 'String');
|
||||
|
||||
if(data.Package?.Info) {
|
||||
if(data.Package.Info) {
|
||||
// If no properties are defined on an <Info> subitem, then it will be a
|
||||
// string, and needs to be boxed into a KpsInfoItem object
|
||||
const info: any = data.Package.Info;
|
||||
|
|
|
|||
4
developer/src/common/web/utils/test/fixtures/kps/error_not_a_package_file.kps
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<NotAPackage>
|
||||
<!-- root element should be <Package> -->
|
||||
</NotAPackage>
|
||||
|
|
@ -6,13 +6,15 @@ import { KPJFileReader } from "../../src/types/kpj/kpj-file-reader.js";
|
|||
import { KeymanDeveloperProjectFile10, KeymanDeveloperProjectType } from '../../src/types/kpj/keyman-developer-project.js';
|
||||
import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers';
|
||||
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
|
||||
describe('kpj-file-reader', function () {
|
||||
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
it('kpj-file-reader should read a valid file', async function() {
|
||||
const kpjPath = 'khmer_angkor.kpj';
|
||||
const path = makePathToFixture('kpj', kpjPath);
|
||||
const input = fs.readFileSync(path);
|
||||
const input = fs.readFileSync(path) as Uint8Array;
|
||||
const reader = new KPJFileReader(callbacks);
|
||||
const kpj = reader.read(input);
|
||||
reader.validate(kpj);
|
||||
|
|
@ -124,7 +126,7 @@ describe('kpj-file-reader', function () {
|
|||
|
||||
it('should load a v1.0 keyboard project with missing <File>', async function() {
|
||||
const path = makePathToFixture('kpj', 'project-missing-file', 'project_missing_file.kpj');
|
||||
const input = fs.readFileSync(path);
|
||||
const input = fs.readFileSync(path) as Uint8Array;
|
||||
const reader = new KPJFileReader(callbacks);
|
||||
const kpj = reader.read(input);
|
||||
reader.validate(kpj);
|
||||
|
|
@ -140,7 +142,7 @@ describe('kpj-file-reader', function () {
|
|||
|
||||
it('should load a v1.0 keyboard project with missing <Files>', async function() {
|
||||
const path = makePathToFixture('kpj', 'project-missing-file', 'project_missing_files.kpj');
|
||||
const input = fs.readFileSync(path);
|
||||
const input = fs.readFileSync(path) as Uint8Array;
|
||||
const reader = new KPJFileReader(callbacks);
|
||||
const kpj = reader.read(input);
|
||||
reader.validate(kpj);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
import * as fs from 'fs';
|
||||
/*
|
||||
* Keyman is copyright (C) SIL Global. MIT License.
|
||||
*/
|
||||
import * as fs from 'node:fs';
|
||||
import 'mocha';
|
||||
import {assert} from 'chai';
|
||||
import { makePathToFixture } from '../helpers/index.js';
|
||||
|
|
@ -8,13 +11,13 @@ import { KPJFileWriter } from '../../src/types/kpj/kpj-file-writer.js';
|
|||
import { KeymanDeveloperProjectOptions } from '../../src/types/kpj/keyman-developer-project.js';
|
||||
import { SymbolUtils } from '../../src/symbol-utils.js';
|
||||
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
|
||||
describe('kpj-file-writer', function () {
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
it('kpj-file-writer should write a valid v1.0 file', async function() {
|
||||
const kpjPath = 'khmer_angkor.kpj';
|
||||
const path = makePathToFixture('kpj', kpjPath);
|
||||
const input = fs.readFileSync(path);
|
||||
const input = fs.readFileSync(path) as Uint8Array;
|
||||
const reader = new KPJFileReader(callbacks);
|
||||
const inputKpj = reader.read(input);
|
||||
reader.validate(inputKpj);
|
||||
|
|
@ -53,7 +56,7 @@ describe('kpj-file-writer', function () {
|
|||
it('kpj-file-writer should write a valid v2.0 file', async function() {
|
||||
const kpjPath = 'khmer_angkor.kpj';
|
||||
const path = makePathToFixture('kpj', kpjPath);
|
||||
const input = fs.readFileSync(path);
|
||||
const input = fs.readFileSync(path) as Uint8Array;
|
||||
const reader = new KPJFileReader(callbacks);
|
||||
const inputKpj = reader.read(input);
|
||||
reader.validate(inputKpj);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
* Created by mcdurdin on 2024-10-16
|
||||
*/
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as fs from 'node:fs';
|
||||
import 'mocha';
|
||||
import {assert} from 'chai';
|
||||
|
||||
|
|
@ -17,11 +17,13 @@ import { KpsFileWriter } from '../../src/types/kps/kps-file-writer.js';
|
|||
import { SymbolUtils } from '../../src/symbol-utils.js';
|
||||
import { DeveloperUtilsMessages } from '../../src/developer-utils-messages.js';
|
||||
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
|
||||
describe('kps-file-reader', function () {
|
||||
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
it('kps-file-reader should read a valid file', function() {
|
||||
const input = fs.readFileSync(makePathToFixture('kps', 'khmer_angkor.kps'));
|
||||
const input = fs.readFileSync(makePathToFixture('kps', 'khmer_angkor.kps')) as Uint8Array;
|
||||
const reader = new KpsFileReader(callbacks);
|
||||
const kps = reader.read(input);
|
||||
|
||||
|
|
@ -58,7 +60,7 @@ describe('kps-file-reader', function () {
|
|||
});
|
||||
|
||||
it('kps-file-reader should round-trip with kps-file-writer', function() {
|
||||
const input = fs.readFileSync(makePathToFixture('kps', 'khmer_angkor.kps'));
|
||||
const input = fs.readFileSync(makePathToFixture('kps', 'khmer_angkor.kps')) as Uint8Array;
|
||||
const reader = new KpsFileReader(callbacks);
|
||||
// Remove XML metadata symbols to reduce clutter for testing purposes
|
||||
const kps = SymbolUtils.removeSymbols(reader.read(input));
|
||||
|
|
@ -75,7 +77,7 @@ describe('kps-file-reader', function () {
|
|||
// ERROR_InvalidPackageFile
|
||||
|
||||
it('should generate ERROR_InvalidPackageFile if package source file contains invalid XML', async function() {
|
||||
const input = fs.readFileSync(makePathToFixture('kps', 'error_invalid_package_file.kps'));
|
||||
const input = fs.readFileSync(makePathToFixture('kps', 'error_invalid_package_file.kps')) as Uint8Array;
|
||||
const reader = new KpsFileReader(callbacks);
|
||||
const kps = reader.read(input);
|
||||
|
||||
|
|
@ -83,4 +85,16 @@ describe('kps-file-reader', function () {
|
|||
assert.lengthOf(callbacks.messages, 1);
|
||||
assert.isTrue(callbacks.hasMessage(DeveloperUtilsMessages.ERROR_InvalidPackageFile));
|
||||
});
|
||||
|
||||
// ERROR_NotAPackageFile
|
||||
|
||||
it(`should generate ERROR_NotAPackageFile when the package source file is valid XML but does not have a <Package> root element`, function () {
|
||||
const input = fs.readFileSync(makePathToFixture('kps', 'error_not_a_package_file.kps')) as Uint8Array;
|
||||
const reader = new KpsFileReader(callbacks);
|
||||
const kps = reader.read(input);
|
||||
|
||||
assert.isNull(kps);
|
||||
assert.isTrue(callbacks.hasMessage(DeveloperUtilsMessages.ERROR_NotAPackageFile));
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -29,8 +29,6 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@keymanapp/resources-gosh": "*",
|
||||
"@types/mocha": "^5.2.7",
|
||||
"@types/node": "^20.4.1",
|
||||
"c8": "^7.12.0",
|
||||
"chalk": "^2.4.2",
|
||||
"typescript": "^5.4.5"
|
||||
|
|
|
|||
|
|
@ -11,17 +11,7 @@ import { AnalyzeOskCharacterUse } from '../src/osk-character-use/index.js';
|
|||
|
||||
describe('AnalyzerMessages', function () {
|
||||
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
|
||||
this.beforeEach(function() {
|
||||
callbacks.clear();
|
||||
});
|
||||
|
||||
this.afterEach(function() {
|
||||
if(this.currentTest?.isFailed()) {
|
||||
callbacks.printMessages();
|
||||
}
|
||||
});
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
it('should have a valid AnalyzerMessages object', function() {
|
||||
return verifyCompilerMessagesObject(AnalyzerMessages, CompilerErrorNamespace.Analyzer);
|
||||
|
|
|
|||
|
|
@ -7,23 +7,13 @@ import { AnalyzeOskCharacterUse } from '../src/osk-character-use/index.js';
|
|||
import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers';
|
||||
|
||||
describe('AnalyzeOskCharacterUse output formats', function() {
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
const dummyStrings = {
|
||||
'a': [{ filename: 'file1.kvks', count: 1 }],
|
||||
'b': [{ filename: 'file2.kvks', count: 2 }]
|
||||
};
|
||||
|
||||
this.beforeEach(function() {
|
||||
callbacks.clear();
|
||||
});
|
||||
|
||||
this.afterEach(function() {
|
||||
if (this.currentTest?.isFailed()) {
|
||||
callbacks.printMessages();
|
||||
}
|
||||
});
|
||||
|
||||
it('generates .txt format correctly', function() {
|
||||
const a = new AnalyzeOskCharacterUse(callbacks, { includeCounts: true });
|
||||
a.unitTestEndPoints.addStrings(['a', 'b'], 'testfile.kvks');
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import { AnalyzerMessages } from '../src/analyzer-messages.js';
|
|||
import { makePathToFixture } from './helpers/index.js';
|
||||
|
||||
describe('AnalyzeOskCharacterUse warnings', function() {
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
const MOCK_MAP_NO_COUNTS = makePathToFixture(
|
||||
'osk-character-use',
|
||||
|
|
@ -20,16 +20,6 @@ describe('AnalyzeOskCharacterUse warnings', function() {
|
|||
'mock-map-with-counts.json'
|
||||
);
|
||||
|
||||
this.beforeEach(function() {
|
||||
callbacks.clear();
|
||||
});
|
||||
|
||||
this.afterEach(function() {
|
||||
if (this.currentTest?.isFailed()) {
|
||||
callbacks.printMessages();
|
||||
}
|
||||
});
|
||||
|
||||
it('warns if previous map did not include counts but includeCounts=true', function() {
|
||||
const a = new AnalyzeOskCharacterUse(callbacks, {
|
||||
includeCounts: true
|
||||
|
|
@ -37,7 +27,7 @@ describe('AnalyzeOskCharacterUse warnings', function() {
|
|||
|
||||
const result = a.unitTestEndPoints.loadPreviousMap(MOCK_MAP_NO_COUNTS);
|
||||
assert.isNotNull(result, 'Expected map to be loaded successfully');
|
||||
|
||||
|
||||
assert.isTrue(
|
||||
callbacks.hasMessage(AnalyzerMessages.WARN_PreviousMapDidNotIncludeCounts),
|
||||
'Expected Warn_PreviousMapDidNotIncludeCounts warning'
|
||||
|
|
|
|||
|
|
@ -17,17 +17,7 @@ const SIL_KHMER_KVKS = makePathToFixture('khmer', "sil_khmer.kvks");
|
|||
const KBDKHMR_WITH_SIL_KHMER_JSON = makePathToFixture('khmer', "KbdKhmr-with-sil_khmer.json");
|
||||
|
||||
describe('AnalyzeOskCharacterUse', function () {
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
|
||||
this.beforeEach(function() {
|
||||
callbacks.clear();
|
||||
});
|
||||
|
||||
this.afterEach(function() {
|
||||
if(this.currentTest?.isFailed()) {
|
||||
callbacks.printMessages();
|
||||
}
|
||||
});
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
it('generates a mapping file from 2 input files', async function() {
|
||||
// functional test
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@
|
|||
"devDependencies": {
|
||||
"@keymanapp/developer-test-helpers": "*",
|
||||
"@keymanapp/resources-gosh": "*",
|
||||
"@types/mocha": "^5.2.7",
|
||||
"@types/node": "^20.4.1",
|
||||
"@types/semver": "^7.3.12",
|
||||
"ajv": "^8.12.0",
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ export class KeymanProjectCopier implements KeymanCompiler {
|
|||
*/
|
||||
private getLocalFolderProject(source: string): string {
|
||||
source = this.normalizePath(source);
|
||||
const projectSource = this.normalizePath(this.callbacks.path.join(source, this.callbacks.path.basename(source) + KeymanFileTypes.Source.Project));
|
||||
const projectSource = this.normalizePath(this.callbacks.path.resolve(this.callbacks.path.join(source, this.callbacks.path.basename(source) + KeymanFileTypes.Source.Project)));
|
||||
if(!this.callbacks.fs.existsSync(projectSource)) {
|
||||
this.callbacks.reportMessage(CopierMessages.Error_CannotFindInputProject({project: source}));
|
||||
return null;
|
||||
|
|
@ -216,7 +216,7 @@ export class KeymanProjectCopier implements KeymanCompiler {
|
|||
* @returns
|
||||
*/
|
||||
private getLocalFileProject(source: string): string {
|
||||
return this.normalizePath(source);
|
||||
return this.normalizePath(this.callbacks.path.resolve(source));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -14,17 +14,7 @@ import { KeymanProjectCopier } from '../src/KeymanProjectCopier.js';
|
|||
import { makePathToFixture } from './helpers/index.js';
|
||||
|
||||
describe('CopierMessages', function () {
|
||||
const callbacks = new TestCompilerCallbacks(makePathToFixture('online'));
|
||||
|
||||
this.beforeEach(function() {
|
||||
callbacks.clear();
|
||||
});
|
||||
|
||||
this.afterEach(function() {
|
||||
if(this.currentTest?.isFailed()) {
|
||||
callbacks.printMessages();
|
||||
}
|
||||
});
|
||||
const callbacks = new TestCompilerCallbacks(this, makePathToFixture('online'));
|
||||
|
||||
it('should have a valid CopierMessages object', function() {
|
||||
return verifyCompilerMessagesObject(CopierMessages, CompilerErrorNamespace.Copier);
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ function normalizeNewLine(s: string): string {
|
|||
}
|
||||
|
||||
describe('KeymanProjectCopier', function() {
|
||||
const callbacks = new TestCompilerCallbacks(makePathToFixture('online'));
|
||||
const callbacks = new TestCompilerCallbacks(this, makePathToFixture('online'));
|
||||
|
||||
this.beforeAll(function() {
|
||||
if(TEST_SAVE_ARTIFACTS) {
|
||||
|
|
@ -32,16 +32,6 @@ describe('KeymanProjectCopier', function() {
|
|||
}
|
||||
});
|
||||
|
||||
this.beforeEach(function() {
|
||||
callbacks.clear();
|
||||
});
|
||||
|
||||
this.afterEach(function() {
|
||||
if(this.currentTest?.isFailed()) {
|
||||
callbacks.printMessages();
|
||||
}
|
||||
});
|
||||
|
||||
const tests = [
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -3,26 +3,16 @@
|
|||
*/
|
||||
|
||||
import 'mocha';
|
||||
import * as path from 'path';
|
||||
import * as os from 'os';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'node:path';
|
||||
import * as os from 'node:os';
|
||||
import * as fs from 'node:fs';
|
||||
import { assert } from 'chai';
|
||||
import { AbstractGenerator, GeneratorArtifacts } from '../src/abstract-generator.js';
|
||||
import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers';
|
||||
import { options } from './shared-options.js';
|
||||
|
||||
describe('AbstractGenerator', function () {
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
|
||||
this.beforeEach(function() {
|
||||
callbacks.clear();
|
||||
});
|
||||
|
||||
this.afterEach(function() {
|
||||
if(this.currentTest.isFailed()) {
|
||||
callbacks.printMessages();
|
||||
}
|
||||
});
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
it('should write out files successfully', async function() {
|
||||
const ag = new AbstractGenerator();
|
||||
|
|
@ -40,7 +30,7 @@ describe('AbstractGenerator', function () {
|
|||
};
|
||||
assert.isTrue(await ag.write(artifacts));
|
||||
assert.isTrue(fs.existsSync(filename));
|
||||
const buf = fs.readFileSync(filename);
|
||||
const buf = fs.readFileSync(filename) as Uint8Array;
|
||||
assert.deepEqual(buf, data);
|
||||
|
||||
fs.unlinkSync(filename);
|
||||
|
|
|
|||
|
|
@ -32,9 +32,10 @@ class BasicGeneratorTest extends BasicGenerator {
|
|||
}
|
||||
|
||||
describe('BasicGenerator', function () {
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
it('should configure default settings', async function() {
|
||||
const bg = new BasicGenerator();
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
assert.isTrue(await bg.init(callbacks, options));
|
||||
assert.isTrue(bg.test_preGenerate());
|
||||
|
||||
|
|
@ -45,7 +46,6 @@ describe('BasicGenerator', function () {
|
|||
const bg = new BasicGeneratorTest();
|
||||
bg.setup();
|
||||
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
assert.isTrue(await bg.init(callbacks, options));
|
||||
assert.isTrue(bg.test_preGenerate());
|
||||
|
||||
|
|
|
|||
|
|
@ -22,17 +22,7 @@ import { LexicalModelGenerator } from '../src/lexical-model-generator.js';
|
|||
import { options } from './shared-options.js';
|
||||
|
||||
describe('GeneratorMessages', function () {
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
|
||||
this.beforeEach(function() {
|
||||
callbacks.clear();
|
||||
});
|
||||
|
||||
this.afterEach(function() {
|
||||
if(this.currentTest.isFailed()) {
|
||||
callbacks.printMessages();
|
||||
}
|
||||
});
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
it('should have a valid GeneratorMessages object', function() {
|
||||
return verifyCompilerMessagesObject(GeneratorMessages, CompilerErrorNamespace.Generator);
|
||||
|
|
@ -78,7 +68,6 @@ describe('GeneratorMessages', function () {
|
|||
targets: ['invalid']
|
||||
};
|
||||
const bg = new BasicGenerator();
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
assert(await bg.init(callbacks, testOptions));
|
||||
assert.isFalse(bg.test_preGenerate());
|
||||
assert.isTrue(callbacks.hasMessage(GeneratorMessages.ERROR_InvalidTarget));
|
||||
|
|
@ -89,7 +78,6 @@ describe('GeneratorMessages', function () {
|
|||
id: '???invalid',
|
||||
};
|
||||
const kkg = new KeymanKeyboardGenerator();
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
assert.isTrue(await kkg.init(callbacks, testOptions));
|
||||
assert.isNull(await kkg.run());
|
||||
assert.isTrue(callbacks.hasMessage(GeneratorMessages.ERROR_InvalidKeymanKeyboardId));
|
||||
|
|
@ -100,7 +88,6 @@ describe('GeneratorMessages', function () {
|
|||
id: '???invalid',
|
||||
};
|
||||
const lkg = new LdmlKeyboardGenerator();
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
assert.isTrue(await lkg.init(callbacks, testOptions));
|
||||
assert.isNull(await lkg.run());
|
||||
assert.isTrue(callbacks.hasMessage(GeneratorMessages.ERROR_InvalidLdmlKeyboardId));
|
||||
|
|
@ -111,7 +98,6 @@ describe('GeneratorMessages', function () {
|
|||
id: 'example.???.invalid',
|
||||
};
|
||||
const lmg = new LexicalModelGenerator();
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
assert.isTrue(await lmg.init(callbacks, testOptions));
|
||||
assert.isNull(await lmg.run());
|
||||
assert.isTrue(callbacks.hasMessage(GeneratorMessages.ERROR_InvalidLexicalModelId));
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ function getFilenames(p: string, base?: string): string[] {
|
|||
describe('KeymanKeyboardGenerator', function () {
|
||||
let clock: sinon.SinonFakeTimers;
|
||||
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
before(function() {
|
||||
// We will always be 12 April 2024 to match test fixtures
|
||||
clock = sinon.useFakeTimers(new Date(2024, 3, 12));
|
||||
|
|
@ -44,7 +46,6 @@ describe('KeymanKeyboardGenerator', function () {
|
|||
|
||||
it('should generate a Keyman keyboard from provided options', async function() {
|
||||
const generator = new KeymanKeyboardGenerator();
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
assert(await generator.init(callbacks, options));
|
||||
const result = await generator.run();
|
||||
assert.exists(result);
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ function getFilenames(p: string, base?: string): string[] {
|
|||
describe('LdmlKeyboardGenerator', function () {
|
||||
let clock: sinon.SinonFakeTimers;
|
||||
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
before(function() {
|
||||
// We will always be 12 April 2024 to match test fixtures
|
||||
clock = sinon.useFakeTimers(new Date(2024, 3, 12));
|
||||
|
|
@ -44,7 +46,6 @@ describe('LdmlKeyboardGenerator', function () {
|
|||
|
||||
it('should generate a LDML keyboard from provided options', async function() {
|
||||
const generator = new LdmlKeyboardGenerator();
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
assert(await generator.init(callbacks, options));
|
||||
const result = await generator.run();
|
||||
assert.exists(result);
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ function getFilenames(p: string, base?: string): string[] {
|
|||
describe('LexicalModelGenerator', function () {
|
||||
let clock: sinon.SinonFakeTimers;
|
||||
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
before(function() {
|
||||
// We will always be 12 April 2024 to match test fixtures
|
||||
clock = sinon.useFakeTimers(new Date(2024, 3, 12));
|
||||
|
|
@ -46,7 +48,6 @@ describe('LexicalModelGenerator', function () {
|
|||
|
||||
it('should generate a lexical model from provided options', async function() {
|
||||
const generator = new LexicalModelGenerator();
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
const opts: GeneratorOptions = {...options};
|
||||
opts.id = 'sample.en.sample';
|
||||
opts.targets = [KeymanTargets.KeymanTarget.any];
|
||||
|
|
|
|||
|
|
@ -29,8 +29,6 @@
|
|||
"@keymanapp/langtags": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mocha": "^5.2.7",
|
||||
"@types/node": "^20.4.1",
|
||||
"c8": "^7.12.0",
|
||||
"chalk": "^2.4.2",
|
||||
"typescript": "^5.4.5"
|
||||
|
|
|
|||
|
|
@ -8,8 +8,6 @@ import { makePathToFixture } from './helpers/index.js';
|
|||
import { KeyboardInfoCompiler } from '../src/keyboard-info-compiler.js';
|
||||
import { KeyboardInfoFile } from '../src/keyboard-info-file.js';
|
||||
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
|
||||
const KHMER_ANGKOR_JS = makePathToFixture('khmer_angkor', 'build', 'khmer_angkor.js');
|
||||
const KHMER_ANGKOR_KPS = makePathToFixture('khmer_angkor', 'source', 'khmer_angkor.kps');
|
||||
const KHMER_ANGKOR_KMP = makePathToFixture('khmer_angkor', 'build', 'khmer_angkor.kmp');
|
||||
|
|
@ -24,15 +22,7 @@ const KHMER_ANGKOR_SOURCES = {
|
|||
|
||||
describe('KeyboardInfoCompilerMessages', function () {
|
||||
|
||||
this.beforeEach(function() {
|
||||
callbacks.clear();
|
||||
});
|
||||
|
||||
this.afterEach(function() {
|
||||
if(this.currentTest?.isFailed()) {
|
||||
callbacks.printMessages();
|
||||
}
|
||||
})
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
it('should have a valid KeyboardInfoCompilerMessages object', function() {
|
||||
return verifyCompilerMessagesObject(KeyboardInfoCompilerMessages, CompilerErrorNamespace.KeyboardInfoCompiler);
|
||||
|
|
|
|||
|
|
@ -10,18 +10,6 @@ import { KMX, KeymanFileTypes, KeymanTargets, KmpJsonFile } from '@keymanapp/com
|
|||
import { CompilerCallbacks } from '@keymanapp/developer-utils';
|
||||
import { KeyboardInfoFile, KeyboardInfoFileLanguage, KeyboardInfoFilePlatform } from './keyboard-info-file.js';
|
||||
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
|
||||
beforeEach(function() {
|
||||
callbacks.clear();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
if(this.currentTest?.isFailed()) {
|
||||
callbacks.printMessages();
|
||||
}
|
||||
});
|
||||
|
||||
const KHMER_ANGKOR_KPJ = makePathToFixture('khmer_angkor', 'khmer_angkor.kpj');
|
||||
const KHMER_ANGKOR_JS = makePathToFixture('khmer_angkor', 'build', 'khmer_angkor.js');
|
||||
const KHMER_ANGKOR_KPS = makePathToFixture('khmer_angkor', 'source', 'khmer_angkor.kps');
|
||||
|
|
@ -87,6 +75,9 @@ const JAVA_DISPLAY_FONT_INFO = { family: "Java", source: [ JAVA_DISPLAY_FONT ] }
|
|||
const JAVA_OSK_FONT_INFO = { family: "Java Kbd", source: [ JAVA_OSK_FONT ] };
|
||||
|
||||
describe('keyboard-info-compiler', function () {
|
||||
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
it('compile a .keyboard_info file correctly', async function() {
|
||||
const kpjFilename = KHMER_ANGKOR_KPJ;
|
||||
const buildKeyboardInfoFilename = makePathToFixture('khmer_angkor', 'build', 'khmer_angkor.keyboard_info');
|
||||
|
|
@ -844,6 +835,9 @@ describe('keyboard-info-compiler', function () {
|
|||
});
|
||||
|
||||
describe('fillLanguageMetadata', function() {
|
||||
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
const tests: { bcp47: string, lang: KeyboardInfoFileLanguage, commonScript: string }[] = [
|
||||
|
||||
// 'und' language subtag
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@keymanapp/developer-test-helpers": "*",
|
||||
"@types/mocha": "^5.2.7",
|
||||
"@types/node": "^20.4.1",
|
||||
"@types/semver": "^7.3.12",
|
||||
"@types/sinon": "^10.0.13",
|
||||
"@types/sinon-chai": "^3.2.9",
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ const keyboardsDir = __dirname + '/../../../../../common/test/keyboards/';
|
|||
const baselineDir = keyboardsDir + 'baseline/';
|
||||
|
||||
describe('Compiler class', function() {
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
it('should throw on failure', async function() {
|
||||
const compiler = new KmnCompiler();
|
||||
const callbacks : any = null; // ERROR
|
||||
|
|
@ -25,14 +27,12 @@ describe('Compiler class', function() {
|
|||
|
||||
it('should start', async function() {
|
||||
const compiler = new KmnCompiler();
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
assert(await compiler.init(callbacks, null));
|
||||
assert(compiler.verifyInitialized());
|
||||
});
|
||||
|
||||
it('should compile a basic keyboard', async function() {
|
||||
const compiler = new KmnCompiler();
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
assert(await compiler.init(callbacks, {saveDebug: true, shouldAddCompilerVersion: false}));
|
||||
assert(compiler.verifyInitialized());
|
||||
|
||||
|
|
@ -60,7 +60,6 @@ describe('Compiler class', function() {
|
|||
it('should build all baseline fixtures', async function() {
|
||||
this.timeout(10000); // there are quite a few fixtures, sometimes CI agents are slow
|
||||
const compiler = new KmnCompiler();
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
assert(await compiler.init(callbacks, {saveDebug: true, shouldAddCompilerVersion: false}));
|
||||
assert(compiler.verifyInitialized());
|
||||
|
||||
|
|
@ -90,7 +89,6 @@ describe('Compiler class', function() {
|
|||
|
||||
it('should compile a keyboard with visual keyboard', async function() {
|
||||
const compiler = new KmnCompiler();
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
assert.isTrue(await compiler.init(callbacks, {
|
||||
saveDebug: true,
|
||||
shouldAddCompilerVersion: false,
|
||||
|
|
|
|||
|
|
@ -7,19 +7,14 @@ import { KMX, KmxFileReader } from '@keymanapp/common-types';
|
|||
|
||||
describe('Keyboard compiler features', function() {
|
||||
let compiler: KmnCompiler = null;
|
||||
let callbacks: TestCompilerCallbacks = null;
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
this.beforeAll(async function() {
|
||||
compiler = new KmnCompiler();
|
||||
callbacks = new TestCompilerCallbacks();
|
||||
assert(await compiler.init(callbacks, {saveDebug: true}));
|
||||
assert(compiler.verifyInitialized());
|
||||
});
|
||||
|
||||
beforeEach(function() {
|
||||
callbacks.clear();
|
||||
});
|
||||
|
||||
// Test each Keyman file version target
|
||||
|
||||
const versions = [
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { KmnCompilerMessageRanges, KmnCompilerMessages } from '../src/compiler/k
|
|||
import { makePathToFixture } from './helpers/index.js';
|
||||
|
||||
describe('KmnCompilerMessages', function () {
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
it('should have a valid KmnCompilerMessages object', function() {
|
||||
return verifyCompilerMessagesObject(KmnCompilerMessages, CompilerErrorNamespace.KmnCompiler);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ const generateTestFilenames = (id: string) => ({
|
|||
});
|
||||
|
||||
describe('KeymanWeb Compiler', function() {
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
const kmnCompiler: KmnCompiler = new KmnCompiler();
|
||||
|
||||
this.beforeAll(async function() {
|
||||
|
|
@ -35,13 +35,6 @@ describe('KeymanWeb Compiler', function() {
|
|||
}));
|
||||
});
|
||||
|
||||
this.afterEach(function() {
|
||||
if(this.currentTest?.isFailed() || debug) {
|
||||
callbacks.printMessages();
|
||||
}
|
||||
callbacks.clear();
|
||||
});
|
||||
|
||||
it('should compile a complex keyboard', async function() {
|
||||
await run_test_keyboard(kmnCompiler, 'khmer_angkor');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { KmnCompiler } from '../../src/main.js';
|
|||
import { CompilerErrorNamespace } from '@keymanapp/developer-utils';
|
||||
|
||||
describe('KmwCompilerMessages', function () {
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
it('should have a valid KmwCompilerMessages object', function() {
|
||||
return verifyCompilerMessagesObject(KmwCompilerMessages, CompilerErrorNamespace.KmwCompiler);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ import { KmnCompilerMessages } from '../src/compiler/kmn-compiler-messages.js';
|
|||
import { compilerErrorFormatCode } from '@keymanapp/developer-utils';
|
||||
|
||||
describe('Compiler UnicodeSet function', function() {
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
it('should fixup "short" \\u{} escapes', function () {
|
||||
assert.equal(KmnCompiler.fixNewPattern(`\\u{A}`), `\\u000A`); // "
|
||||
assert.equal(KmnCompiler.fixNewPattern(`\\u{22}`), `\\u0022`); // "
|
||||
|
|
@ -24,14 +26,12 @@ describe('Compiler UnicodeSet function', function() {
|
|||
|
||||
it('should start', async function() {
|
||||
const compiler = new KmnCompiler();
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
assert(await compiler.init(callbacks, null));
|
||||
assert(compiler.verifyInitialized());
|
||||
});
|
||||
|
||||
it('should compile a basic uset', async function() {
|
||||
const compiler = new KmnCompiler();
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
assert(await compiler.init(callbacks, null));
|
||||
assert(compiler.verifyInitialized());
|
||||
|
||||
|
|
@ -49,7 +49,6 @@ describe('Compiler UnicodeSet function', function() {
|
|||
});
|
||||
it('should compile a more complex uset', async function() {
|
||||
const compiler = new KmnCompiler();
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
assert(await compiler.init(callbacks, null));
|
||||
assert(compiler.verifyInitialized());
|
||||
|
||||
|
|
@ -69,7 +68,6 @@ describe('Compiler UnicodeSet function', function() {
|
|||
});
|
||||
it('should compile an even more complex uset', async function() {
|
||||
const compiler = new KmnCompiler();
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
assert(await compiler.init(callbacks, null));
|
||||
assert(compiler.verifyInitialized());
|
||||
|
||||
|
|
@ -96,7 +94,6 @@ describe('Compiler UnicodeSet function', function() {
|
|||
});
|
||||
it('should fail in various ways', async function() {
|
||||
const compiler = new KmnCompiler();
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
assert(await compiler.init(callbacks, null));
|
||||
assert(compiler.verifyInitialized());
|
||||
// map from string to failing error
|
||||
|
|
|
|||
|
|
@ -35,8 +35,6 @@
|
|||
"@keymanapp/developer-test-helpers": "*",
|
||||
"@keymanapp/resources-gosh": "*",
|
||||
"@types/common-tags": "^1.8.4",
|
||||
"@types/mocha": "^5.2.7",
|
||||
"@types/node": "^20.4.1",
|
||||
"@types/semver": "^7.3.12",
|
||||
"abnf": "^4.3.1",
|
||||
"c8": "^7.12.0",
|
||||
|
|
|
|||
|
|
@ -34,8 +34,6 @@
|
|||
"@keymanapp/developer-utils": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mocha": "^5.2.7",
|
||||
"@types/node": "^20.4.1",
|
||||
"c8": "^7.12.0",
|
||||
"chalk": "^2.4.2",
|
||||
"typescript": "^5.4.5"
|
||||
|
|
|
|||
|
|
@ -6,13 +6,9 @@ import { makePathToFixture } from './helpers/index.js';
|
|||
import { ModelInfoCompiler } from '../src/model-info-compiler.js';
|
||||
import { KmpCompiler } from '@keymanapp/kmc-package';
|
||||
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
|
||||
beforeEach(function() {
|
||||
callbacks.clear();
|
||||
});
|
||||
|
||||
describe('model-info-compiler', function () {
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
it('compile a .model_info file correctly', async function() {
|
||||
const kpjFilename = makePathToFixture('sil.cmo.bw', 'sil.cmo.bw.model.kpj');
|
||||
const kpsFilename = makePathToFixture('sil.cmo.bw', 'source', 'sil.cmo.bw.model.kps');
|
||||
|
|
|
|||
|
|
@ -37,8 +37,6 @@
|
|||
"devDependencies": {
|
||||
"@keymanapp/developer-test-helpers": "*",
|
||||
"@keymanapp/models-templates": "*",
|
||||
"@types/mocha": "^5.2.7",
|
||||
"@types/node": "^20.4.1",
|
||||
"c8": "^7.12.0",
|
||||
"chalk": "^2.4.2",
|
||||
"esbuild": "^0.25.0"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers';
|
|||
import { LexicalModelTypes } from '@keymanapp/common-types';
|
||||
|
||||
describe('LexicalModelCompiler - pseudoclosure compilation + use', function () {
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
const MODEL_ID = 'example.qaa.trivial';
|
||||
const PATH = makePathToFixture(MODEL_ID);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers';
|
|||
import { KeymanFileTypes } from '@keymanapp/common-types';
|
||||
|
||||
describe('LexicalModelCompiler', function () {
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
this.timeout(5000);
|
||||
|
||||
|
|
|
|||
|
|
@ -11,10 +11,7 @@ import { TrieModel } from '@keymanapp/models-templates';
|
|||
import { LexicalModelTypes } from '@keymanapp/common-types';
|
||||
|
||||
describe('LexicalModelCompiler', function () {
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
this.beforeEach(function() {
|
||||
callbacks.clear();
|
||||
});
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
describe('#generateLexicalModelCode', function () {
|
||||
it('should compile a trivial word list', async function () {
|
||||
|
|
|
|||
|
|
@ -8,17 +8,7 @@ import { makePathToFixture } from './helpers/index.js';
|
|||
|
||||
describe('ModelCompilerMessages', function () {
|
||||
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
|
||||
this.beforeEach(function() {
|
||||
callbacks.clear();
|
||||
});
|
||||
|
||||
this.afterEach(function() {
|
||||
if(this.currentTest?.isFailed()) {
|
||||
callbacks.printMessages();
|
||||
}
|
||||
});
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
it('should have a valid ModelCompilerMessages object', function() {
|
||||
return verifyCompilerMessagesObject(ModelCompilerMessages, CompilerErrorNamespace.ModelCompiler);
|
||||
|
|
|
|||
|
|
@ -22,11 +22,10 @@ const SENCOTEN_WORDLIST = {
|
|||
|
||||
|
||||
describe('parsing a word list', function () {
|
||||
const testCallbacks = new TestCompilerCallbacks();
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
beforeEach(function () {
|
||||
testCallbacks.clear();
|
||||
setCompilerCallbacks(testCallbacks);
|
||||
setCompilerCallbacks(callbacks);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
|
|
@ -43,12 +42,12 @@ describe('parsing a word list', function () {
|
|||
const withoutBOM: WordList = {};
|
||||
parseWordListFromContents(withoutBOM, file);
|
||||
assert.deepEqual(withoutBOM, expected, "expected regular file to parse properly");
|
||||
assert.isEmpty(testCallbacks.messages);
|
||||
assert.isEmpty(callbacks.messages);
|
||||
|
||||
const withBOM: WordList = {};
|
||||
parseWordListFromContents(withBOM, `${BOM}${file}`)
|
||||
assert.deepEqual(withBOM, expected, "expected BOM to be ignored");
|
||||
assert.isEmpty(testCallbacks.messages);
|
||||
assert.isEmpty(callbacks.messages);
|
||||
});
|
||||
|
||||
it('should read word lists in UTF-8', function () {
|
||||
|
|
@ -58,7 +57,7 @@ describe('parsing a word list', function () {
|
|||
parseWordListFromFilename(wordlist, filename);
|
||||
|
||||
assert.deepEqual(wordlist, SENCOTEN_WORDLIST);
|
||||
assert.isEmpty(testCallbacks.messages);
|
||||
assert.isEmpty(callbacks.messages);
|
||||
});
|
||||
|
||||
it('should read word lists in UTF-16 little-endian (with BOM)', function () {
|
||||
|
|
@ -69,7 +68,7 @@ describe('parsing a word list', function () {
|
|||
parseWordListFromFilename(wordlist, filename);
|
||||
|
||||
assert.deepEqual(wordlist, SENCOTEN_WORDLIST);
|
||||
assert.isEmpty(testCallbacks.messages);
|
||||
assert.isEmpty(callbacks.messages);
|
||||
});
|
||||
|
||||
it('should NOT read word lists in UTF-16 big-endian (with BOM)', function () {
|
||||
|
|
@ -106,22 +105,22 @@ describe('parsing a word list', function () {
|
|||
|
||||
assert.deepEqual(repeatedWords, expected);
|
||||
|
||||
assert.lengthOf(testCallbacks.messages, 4);
|
||||
assert.lengthOf(callbacks.messages, 4);
|
||||
// hello has been seen multiple times:
|
||||
assert.isTrue(testCallbacks.hasMessage(ModelCompilerMessages.HINT_DuplicateWordInSameFile));
|
||||
assert.isTrue(callbacks.hasMessage(ModelCompilerMessages.HINT_DuplicateWordInSameFile));
|
||||
// helló and hello + U+0301 have both been seen:
|
||||
assert.isTrue(testCallbacks.hasMessage(ModelCompilerMessages.HINT_MixedNormalizationForms));
|
||||
assert.isTrue(callbacks.hasMessage(ModelCompilerMessages.HINT_MixedNormalizationForms));
|
||||
|
||||
// Let's parse another file:
|
||||
|
||||
testCallbacks.clear();
|
||||
callbacks.clear();
|
||||
// Now, parse a DIFFERENT file, but with an NFD entry.
|
||||
parseWordListFromContents(repeatedWords, "hello\u0301\t5\n");
|
||||
assert.lengthOf(testCallbacks.messages, 1);
|
||||
assert.lengthOf(callbacks.messages, 1);
|
||||
// hello + U+0301 (NFD) has been seen, but...
|
||||
assert.isTrue(testCallbacks.hasMessage(ModelCompilerMessages.HINT_MixedNormalizationForms));
|
||||
assert.isTrue(callbacks.hasMessage(ModelCompilerMessages.HINT_MixedNormalizationForms));
|
||||
// BUT! We have not seen a duplicate **within the same file**
|
||||
assert.isFalse(testCallbacks.hasMessage(ModelCompilerMessages.HINT_DuplicateWordInSameFile));
|
||||
assert.isFalse(callbacks.hasMessage(ModelCompilerMessages.HINT_DuplicateWordInSameFile));
|
||||
|
||||
assert.deepEqual(repeatedWords, {
|
||||
hello: expected['hello'],
|
||||
|
|
|
|||
|
|
@ -6,12 +6,13 @@ import { makePathToFixture, compileModelSourceCode } from './helpers/index.js';
|
|||
import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers';
|
||||
|
||||
describe('LexicalModelCompiler', function () {
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
describe('specifying punctuation', function () {
|
||||
const MODEL_ID = 'example.qaa.trivial';
|
||||
const PATH = makePathToFixture(MODEL_ID);
|
||||
|
||||
it('should compile punctuation into the generated code', async function () {
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
|
||||
const compiler = new LexicalModelCompiler();
|
||||
assert.isTrue(await compiler.init(callbacks, null));
|
||||
|
|
|
|||
|
|
@ -36,8 +36,6 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@keymanapp/developer-test-helpers": "*",
|
||||
"@types/mocha": "^5.2.7",
|
||||
"@types/node": "^20.4.1",
|
||||
"c8": "^7.12.0",
|
||||
"chalk": "^2.4.2",
|
||||
"typescript": "^5.4.5"
|
||||
|
|
|
|||
|
|
@ -206,7 +206,8 @@ export class KmpCompiler implements KeymanCompiler {
|
|||
fileVersion: null,
|
||||
keymanDeveloperVersion: KEYMAN_VERSION.VERSION
|
||||
},
|
||||
options: {}
|
||||
options: {},
|
||||
info: {},
|
||||
};
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ export class PackageValidation {
|
|||
}
|
||||
|
||||
private checkForModelsAndKeyboardsInSamePackage(kmpJson: KmpJsonFile.KmpJsonFile): boolean {
|
||||
if(kmpJson.lexicalModels?.length > 0 && kmpJson.keyboards?.length > 0) {
|
||||
if((kmpJson.lexicalModels?.length ?? 0) > 0 && (kmpJson.keyboards?.length ?? 0) > 0) {
|
||||
this.callbacks.reportMessage(PackageCompilerMessages.Error_PackageCannotContainBothModelsAndKeyboards());
|
||||
return false;
|
||||
}
|
||||
|
|
@ -120,7 +120,7 @@ export class PackageValidation {
|
|||
}
|
||||
|
||||
for(const keyboard of kmpJson.keyboards) {
|
||||
if(!this.checkForDuplicatedOrNonMinimalLanguages('keyboard', keyboard.id, keyboard.languages)) {
|
||||
if(!this.checkForDuplicatedOrNonMinimalLanguages('keyboard', keyboard.id, keyboard.languages ?? [])) {
|
||||
return false;
|
||||
}
|
||||
// Note: package-version-validation verifies that there is a corresponding
|
||||
|
|
@ -131,7 +131,7 @@ export class PackageValidation {
|
|||
}
|
||||
|
||||
private checkContentFiles(kmpJson: KmpJsonFile.KmpJsonFile, outputFilename: string): boolean {
|
||||
for(const file of kmpJson.files) {
|
||||
for(const file of kmpJson.files ?? []) {
|
||||
if(!this.checkContentFile(file, outputFilename)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -202,7 +202,7 @@ export class PackageValidation {
|
|||
return true;
|
||||
}
|
||||
|
||||
private checkPackageInfo(file: KmpJsonFile.KmpJsonFile) {
|
||||
private checkPackageInfo(file: KmpJsonFile.KmpJsonFile): boolean {
|
||||
if(!file.info || !file.info.name || !file.info.name.description.trim()) {
|
||||
this.callbacks.reportMessage(PackageCompilerMessages.Error_PackageNameCannotBeBlank());
|
||||
return false;
|
||||
|
|
@ -214,11 +214,11 @@ export class PackageValidation {
|
|||
/* c8 ignore next 3 */
|
||||
if (match === null) {
|
||||
this.callbacks.reportMessage(PackageCompilerMessages.Error_InvalidAuthorEmail({email:file.info.author.url}));
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
if(!isValidEmail(match[2])) {
|
||||
this.callbacks.reportMessage(PackageCompilerMessages.Error_InvalidAuthorEmail({email:file.info.author.url}));
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,15 +10,10 @@ import { makePathToFixture } from './helpers/index.js';
|
|||
import { KmpCompiler } from '../src/compiler/kmp-compiler.js';
|
||||
import { CompilerErrorNamespace, CompilerOptions } from '@keymanapp/developer-utils';
|
||||
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
|
||||
describe('PackageCompilerMessages', function () {
|
||||
|
||||
this.afterEach(function() {
|
||||
if(this.currentTest.isFailed()) {
|
||||
callbacks.printMessages();
|
||||
}
|
||||
});
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
it('should have a valid PackageCompilerMessages object', function() {
|
||||
return verifyCompilerMessagesObject(PackageCompilerMessages, CompilerErrorNamespace.PackageCompiler);
|
||||
|
|
|
|||
|
|
@ -21,22 +21,14 @@ describe('KmpCompiler', function () {
|
|||
'example.qaa.sencoten',
|
||||
'withfolders.qaa.sencoten',
|
||||
];
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
let kmpCompiler: KmpCompiler = null;
|
||||
|
||||
this.beforeAll(async function() {
|
||||
callbacks.clear();
|
||||
kmpCompiler = new KmpCompiler();
|
||||
assert.isTrue(await kmpCompiler.init(callbacks, null));
|
||||
});
|
||||
|
||||
this.afterEach(function() {
|
||||
if(this.currentTest?.isFailed()) {
|
||||
callbacks.printMessages();
|
||||
}
|
||||
callbacks.clear();
|
||||
});
|
||||
|
||||
for (const modelID of MODELS) {
|
||||
const kpsPath = modelID.includes('withfolders') ?
|
||||
makePathToFixture(modelID, 'source', `${modelID}.model.kps`) : makePathToFixture(modelID, `${modelID}.model.kps`);
|
||||
|
|
@ -144,8 +136,6 @@ describe('KmpCompiler', function () {
|
|||
*/
|
||||
|
||||
it(`should transform a .kps file for a keyboard package to a correct kmp.json`, function () {
|
||||
callbacks.clear();
|
||||
|
||||
const kpsPath = makePathToFixture('kmp.json', 'ahom_star.kps');
|
||||
const kmpJsonRefPath = makePathToFixture('kmp.json', 'kmp.json');
|
||||
|
||||
|
|
@ -171,13 +161,9 @@ describe('KmpCompiler', function () {
|
|||
});
|
||||
|
||||
it(`should support .kps 17.0 metadata correctly`, function () {
|
||||
callbacks.clear();
|
||||
|
||||
const kpsPath = makePathToFixture('kmp_2.0', 'khmer_angkor.kps');
|
||||
const kmpJsonRefPath = makePathToFixture('kmp_2.0', 'kmp.json');
|
||||
|
||||
debugger;
|
||||
|
||||
const kmpJsonActual = kmpCompiler.transformKpsToKmpObject(kpsPath);
|
||||
if(kmpJsonActual == null) {
|
||||
callbacks.printMessages();
|
||||
|
|
@ -205,8 +191,6 @@ describe('KmpCompiler', function () {
|
|||
it('should warn on absolute paths', async function() {
|
||||
this.timeout(10000); // building a zip file can sometimes be slow
|
||||
|
||||
callbacks.clear();
|
||||
|
||||
const kpsPath = makePathToFixture('absolute_path', 'source', 'absolute_path.kps');
|
||||
const kmpCompiler = new KmpCompiler();
|
||||
assert.isTrue(await kmpCompiler.init(callbacks, null));
|
||||
|
|
@ -233,8 +217,6 @@ describe('KmpCompiler', function () {
|
|||
it('should normalize DOS pathnames from \\ to /', async function() {
|
||||
// this.timeout(10000); // building a zip file can sometimes be slow
|
||||
|
||||
callbacks.clear();
|
||||
|
||||
const kpsPath = makePathToFixture('normalize_paths', 'source', 'khmer_angkor.kps');
|
||||
const kmpCompiler = new KmpCompiler();
|
||||
assert.isTrue(await kmpCompiler.init(callbacks, null));
|
||||
|
|
@ -315,7 +297,7 @@ describe('KmpCompiler', function () {
|
|||
assert.isFalse(validation.validate(inputFilename, outputFilename, kmpJson));
|
||||
});
|
||||
|
||||
it(`should reject an package that contains itself`, function () {
|
||||
it(`should reject a package that contains itself`, function () {
|
||||
const inputFilename = makePathToFixture('invalid', 'error_package_must_not_contain_itself.kps');
|
||||
const outputFilename = makePathToFixture('invalid', 'error_package_must_not_contain_itself.kmp');
|
||||
const kmpJson = kmpCompiler.transformKpsToKmpObject(inputFilename);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { makePathToFixture } from './helpers/index.js';
|
|||
// test results documented below.
|
||||
|
||||
describe('package versioning', function () {
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
const cases: [string,string][] = [
|
||||
['test-single-version-1-package', 'test1.kps'],
|
||||
|
|
@ -33,7 +34,6 @@ describe('package versioning', function () {
|
|||
|
||||
for(const [ caseTitle, filename ] of cases) {
|
||||
it(caseTitle, async function () {
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
const kmpCompiler = new KmpCompiler();
|
||||
assert.isTrue(await kmpCompiler.init(callbacks, null));
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import { makePathToFixture } from './helpers/index.js';
|
|||
import { WindowsPackageInstallerCompiler, WindowsPackageInstallerSources } from '../src/compiler/windows-package-installer-compiler.js';
|
||||
|
||||
describe('WindowsPackageInstallerCompiler', function () {
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
it(`should build an SFX archive`, async function () {
|
||||
this.timeout(10000); // this test can take a little while to run
|
||||
|
||||
|
|
@ -22,7 +24,6 @@ describe('WindowsPackageInstallerCompiler', function () {
|
|||
appName: 'Testing',
|
||||
};
|
||||
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
const compiler = new WindowsPackageInstallerCompiler();
|
||||
assert.isTrue(await compiler.init(callbacks, {sources}));
|
||||
|
||||
|
|
@ -44,7 +45,7 @@ describe('WindowsPackageInstallerCompiler', function () {
|
|||
const zipBuffer = sfxBuffer.slice(setupExeSize);
|
||||
|
||||
// Verify setup.exe sfx loader
|
||||
const setupExeFixture = fs.readFileSync(sources.setupExeFilename);
|
||||
const setupExeFixture = fs.readFileSync(sources.setupExeFilename) as Uint8Array;
|
||||
assert.deepEqual(setupExe, setupExeFixture);
|
||||
|
||||
// Load the zip from the buffer
|
||||
|
|
@ -68,7 +69,7 @@ khmer_angkor.kmp
|
|||
assert.equal(setupInf.trim(), setupInfFixture.trim());
|
||||
|
||||
const verifyFile = async (filename: string) => {
|
||||
const fixture = fs.readFileSync(filename);
|
||||
const fixture = fs.readFileSync(filename) as Uint8Array;
|
||||
const file = await zipFile.file(path.basename(filename)).async('uint8array');
|
||||
assert.deepEqual(file, fixture, `File in zip '${filename}' did not match fixture`);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -54,8 +54,6 @@
|
|||
],
|
||||
"devDependencies": {
|
||||
"@sentry/cli": "^2.31.0",
|
||||
"@types/mocha": "^5.2.7",
|
||||
"@types/node": "^20.4.1",
|
||||
"c8": "^7.12.0",
|
||||
"esbuild": "^0.25.0",
|
||||
"typescript": "^5.4.5"
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ async function doCopy(callbacks: NodeCompilerCallbacks, sources: string | string
|
|||
|
||||
const dest = options.outPath;
|
||||
callbacks.reportMessage(InfrastructureMessages.Info_CopyingProject({source, dest}));
|
||||
const result = runCopier(callbacks, source, options);
|
||||
const result = await runCopier(callbacks, source, options);
|
||||
if(result) {
|
||||
callbacks.reportMessage(InfrastructureMessages.Info_ProjectCopiedSuccessfully({source, dest}));
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
/*
|
||||
* Keyman is copyright (C) SIL Global. MIT License.
|
||||
*/
|
||||
import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers';
|
||||
import { clearOptions } from '../src/util/options.js';
|
||||
import { assert } from 'chai';
|
||||
|
|
@ -5,8 +8,6 @@ import 'mocha';
|
|||
import { BuildProject } from '../src/commands/buildClasses/BuildProject.js';
|
||||
import { makePathToFixture } from './helpers/index.js';
|
||||
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
|
||||
interface CompilerWarningsAsErrorsTruthTable {
|
||||
cli: boolean;
|
||||
kpj: boolean;
|
||||
|
|
@ -14,8 +15,9 @@ interface CompilerWarningsAsErrorsTruthTable {
|
|||
};
|
||||
|
||||
describe('compilerWarningsAsErrors', function () {
|
||||
beforeEach(() => {
|
||||
callbacks.clear();
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
this.beforeEach(function() {
|
||||
clearOptions();
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
/*
|
||||
* Keyman is copyright (C) SIL Global. MIT License.
|
||||
*/
|
||||
import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers';
|
||||
import { assert } from 'chai';
|
||||
import 'mocha';
|
||||
|
|
@ -10,10 +13,7 @@ interface MessageTest {input: string, result: CompilerMessageOverride};
|
|||
interface InvalidMessageTest {input: string, code: number};
|
||||
|
||||
describe('commandOptionsMessageToCompilerOptionsMessage', function () {
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
this.beforeEach(function() {
|
||||
callbacks.clear();
|
||||
});
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
const valid: MessageTest[] = [
|
||||
// Test the allowable coercions
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
/*
|
||||
* Keyman is copyright (C) SIL Global. MIT License.
|
||||
*/
|
||||
import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers';
|
||||
import { assert } from 'chai';
|
||||
import 'mocha';
|
||||
import { makePathToFixture } from './helpers/index.js';
|
||||
import { expandFileList, expandFileLists } from '../src/util/fileLists.js';
|
||||
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
|
||||
// expandFileList expands each file name relative to the file list's supplied
|
||||
// filename, so we need to compare against the full path.
|
||||
const expectedFileList = [
|
||||
|
|
@ -21,11 +22,9 @@ const expectedFiles = [
|
|||
'file5.kmn'
|
||||
];
|
||||
|
||||
beforeEach(function() {
|
||||
callbacks.clear();
|
||||
});
|
||||
|
||||
describe('expandFileList', function () {
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
it('should report a missing filelist correctly', async function() {
|
||||
const path = makePathToFixture('file-lists', 'does-not-exist.txt');
|
||||
|
||||
|
|
@ -45,6 +44,8 @@ describe('expandFileList', function () {
|
|||
});
|
||||
|
||||
describe('expandFileLists', function () {
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
it('should splice a filelist in correctly', async function() {
|
||||
// We just use this to test the splicing so no path resolution is made
|
||||
const files = [
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
/*
|
||||
* Keyman is copyright (C) SIL Global. MIT License.
|
||||
*/
|
||||
import * as fs from 'node:fs';
|
||||
import * as os from 'node:os';
|
||||
import * as path from 'node:path';
|
||||
|
|
@ -28,17 +31,15 @@ describe('generateKeymanKeyboard', function() {
|
|||
description: 'Sample Keyboard Test',
|
||||
};
|
||||
|
||||
const callbacks: TestCompilerCallbacks = new TestCompilerCallbacks();
|
||||
const callbacks: TestCompilerCallbacks = new TestCompilerCallbacks(this);
|
||||
let outPath: string = null;
|
||||
|
||||
this.beforeEach(function() {
|
||||
callbacks.clear();
|
||||
outPath = fs.mkdtempSync(path.join(os.tmpdir(), 'kmc-'));
|
||||
});
|
||||
|
||||
this.afterEach(function() {
|
||||
if(this.currentTest.isFailed()) {
|
||||
callbacks.printMessages();
|
||||
console.error(`Output kept at ${outPath}`);
|
||||
} else {
|
||||
if(outPath) fs.rmSync(outPath, {recursive: true, force: true});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
/*
|
||||
* Keyman is copyright (C) SIL Global. MIT License.
|
||||
*/
|
||||
import * as fs from 'node:fs';
|
||||
import * as os from 'node:os';
|
||||
import * as path from 'node:path';
|
||||
|
|
@ -28,17 +31,15 @@ describe('generateLdmlKeyboard', function() {
|
|||
description: 'Sample Keyboard Test',
|
||||
};
|
||||
|
||||
const callbacks: TestCompilerCallbacks = new TestCompilerCallbacks();
|
||||
const callbacks: TestCompilerCallbacks = new TestCompilerCallbacks(this);
|
||||
let outPath: string = null;
|
||||
|
||||
this.beforeEach(function() {
|
||||
callbacks.clear();
|
||||
outPath = fs.mkdtempSync(path.join(os.tmpdir(), 'kmc-'));
|
||||
});
|
||||
|
||||
this.afterEach(function() {
|
||||
if(this.currentTest.isFailed()) {
|
||||
callbacks.printMessages();
|
||||
console.error(`Output kept at ${outPath}`);
|
||||
} else {
|
||||
if(outPath) fs.rmSync(outPath, {recursive: true, force: true});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
/*
|
||||
* Keyman is copyright (C) SIL Global. MIT License.
|
||||
*/
|
||||
import * as fs from 'node:fs';
|
||||
import * as os from 'node:os';
|
||||
import * as path from 'node:path';
|
||||
|
|
@ -27,17 +30,15 @@ describe('generateLexicalModel', function() {
|
|||
description: 'Sample Model Test',
|
||||
};
|
||||
|
||||
const callbacks: TestCompilerCallbacks = new TestCompilerCallbacks();
|
||||
const callbacks: TestCompilerCallbacks = new TestCompilerCallbacks(this);
|
||||
let outPath: string = null;
|
||||
|
||||
this.beforeEach(function() {
|
||||
callbacks.clear();
|
||||
outPath = fs.mkdtempSync(path.join(os.tmpdir(), 'kmc-'));
|
||||
});
|
||||
|
||||
this.afterEach(function() {
|
||||
if(this.currentTest.isFailed()) {
|
||||
callbacks.printMessages();
|
||||
console.error(`Output kept at ${outPath}`);
|
||||
} else {
|
||||
if(outPath) fs.rmSync(outPath, {recursive: true, force: true});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
/*
|
||||
* Keyman is copyright (C) SIL Global. MIT License.
|
||||
*/
|
||||
import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers';
|
||||
import { assert } from 'chai';
|
||||
import 'mocha';
|
||||
|
|
@ -6,9 +9,10 @@ import { makePathToFixture } from './helpers/index.js';
|
|||
import { InfrastructureMessages } from '../src/messages/infrastructureMessages.js';
|
||||
import { clearOptions } from '../src/util/options.js';
|
||||
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
|
||||
describe('BuildProject', function () {
|
||||
const callbacks = new TestCompilerCallbacks(this);
|
||||
|
||||
it('should build a keyboard project', async function() {
|
||||
clearOptions();
|
||||
const builder = new BuildProject();
|
||||
|
|
|
|||
2
developer/src/samples/imsample/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
IMSample.exp
|
||||
IMSample.lib
|
||||
|
|
@ -52,10 +52,6 @@ function clean_server() {
|
|||
|
||||
function configure_server() {
|
||||
node_select_version_and_npm_ci
|
||||
# See https://github.com/bubenshchykov/ngrok/issues/254, https://github.com/bubenshchykov/ngrok/pull/255
|
||||
# TODO: this is horrible; is there a way we can avoid this?
|
||||
rm -f "$KEYMAN_ROOT"/node_modules/ngrok/bin/ngrok
|
||||
rm -f "$KEYMAN_ROOT"/node_modules/ngrok/bin/ngrok.exe
|
||||
}
|
||||
|
||||
function build_addins() {
|
||||
|
|
@ -130,9 +126,6 @@ function installer_server() {
|
|||
|
||||
pushd "$PRODBUILDTEMP"
|
||||
npm install --omit=dev --omit=optional
|
||||
# See https://github.com/bubenshchykov/ngrok/issues/254, https://github.com/bubenshchykov/ngrok/pull/255
|
||||
rm -f node_modules/ngrok/bin/ngrok
|
||||
rm -f node_modules/ngrok/bin/ngrok.exe
|
||||
popd
|
||||
|
||||
# Dependencies are required in build/ but we need to copy them in manually
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@
|
|||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@keymanapp/developer-utils": "*",
|
||||
"@ngrok/ngrok": "^1.7.0",
|
||||
"@sentry/node": "^7.57.0",
|
||||
"chalk": "^4.1.2",
|
||||
"express": "^4.20.0",
|
||||
"multer": "^2.0.2",
|
||||
"ngrok": "^5.0.0-beta.2",
|
||||
"multer": "^2.1.1",
|
||||
"open": "^8.4.0",
|
||||
"restructure": "^3.0.1",
|
||||
"sax": ">=0.6.0",
|
||||
|
|
@ -29,9 +29,7 @@
|
|||
"@keymanapp/keyman-version": "*",
|
||||
"@keymanapp/resources-gosh": "*",
|
||||
"@types/express": "^4.17.13",
|
||||
"@types/mocha": "^9.1.0",
|
||||
"@types/multer": "^1.4.12",
|
||||
"@types/node": "^20.4.1",
|
||||
"@types/ws": "^8.2.2",
|
||||
"copyfiles": "^2.4.1",
|
||||
"node-gyp": "^10.2.0",
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ export class Configuration {
|
|||
public readonly lockFilename: string;
|
||||
public readonly pidFilename: string;
|
||||
public readonly configFilename: string;
|
||||
public readonly ngrokBinPath: string;
|
||||
|
||||
/* Configuration values - set in config.json by TIKE */
|
||||
|
||||
|
|
@ -17,7 +16,6 @@ export class Configuration {
|
|||
/* ngrok Configuration */
|
||||
|
||||
public readonly useNgrok: boolean;
|
||||
public readonly ngrokControlPort: number;
|
||||
public readonly ngrokToken: string;
|
||||
public readonly ngrokVisible: boolean;
|
||||
|
||||
|
|
@ -42,8 +40,6 @@ export class Configuration {
|
|||
|
||||
// ngrok configuration
|
||||
this.useNgrok = cfg?.useNgrok ?? false;
|
||||
this.ngrokBinPath = this.appDataPath + 'bin/';
|
||||
this.ngrokControlPort = cfg?.ngrokControlPort ?? 8009;
|
||||
this.ngrokToken = cfg?.ngrokToken ?? '';
|
||||
this.ngrokVisible = cfg?.ngrokVisible ?? false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import * as fs from 'node:fs';
|
||||
import * as os from 'node:os';
|
||||
import * as path from 'node:path';
|
||||
import chalk from 'chalk';
|
||||
import express from 'express';
|
||||
|
|
@ -77,7 +76,7 @@ export async function run() {
|
|||
|
||||
setupRoutes(app, upload, wsServer, environment);
|
||||
|
||||
/* Start the server */
|
||||
/* Start the web server */
|
||||
|
||||
let server = null;
|
||||
try {
|
||||
|
|
@ -87,6 +86,8 @@ export async function run() {
|
|||
// TODO handle and cleanup EADDRINUSE, throw anything else
|
||||
}
|
||||
|
||||
/* Attach the web socket server */
|
||||
|
||||
server.on('upgrade', (request, socket, head) => {
|
||||
wsServer.handleUpgrade(request, socket, head, socket => {
|
||||
wsServer.emit('connection', socket, request);
|
||||
|
|
@ -96,45 +97,66 @@ export async function run() {
|
|||
/* Launch ngrok if enabled */
|
||||
|
||||
configuration.ngrokEndpoint = '';
|
||||
if(configuration.useNgrok) {
|
||||
await startNGrok();
|
||||
}
|
||||
|
||||
if(configuration.useNgrok
|
||||
&& os.platform() == 'win32'
|
||||
&& fs.existsSync(path.join(configuration.ngrokBinPath, 'ngrok.exe'))
|
||||
) {
|
||||
const ngrok: any = await import('ngrok');
|
||||
(async function() {
|
||||
configuration.ngrokEndpoint = await ngrok.connect({
|
||||
proto: 'http',
|
||||
addr: configuration.port,
|
||||
authtoken: configuration.ngrokToken,
|
||||
binPath: () => configuration.ngrokBinPath,
|
||||
onLogEvent: (msg: string) => {
|
||||
if(options.ngrokLog) {
|
||||
console.log(chalk.cyan(('\n'+msg).split('\n').join('\n[ngrok] ').trim()));
|
||||
}
|
||||
},
|
||||
onStatusChange: (state: string) => {
|
||||
if(state == 'connected') {
|
||||
setTimeout(async () => {
|
||||
const api = ngrok.getApi();
|
||||
const tunnels = await api.listTunnels();
|
||||
configuration.ngrokEndpoint = tunnels.tunnels[0]?.public_url ?? '';
|
||||
console.log(chalk.blueBright('ngrok tunnel established at %s'), configuration.ngrokEndpoint);
|
||||
}, 1000);
|
||||
} else if(state == 'closed') {
|
||||
configuration.ngrokEndpoint = '';
|
||||
console.log(chalk.blueBright('ngrok tunnel closed'));
|
||||
}
|
||||
/* Load the tray icon */
|
||||
|
||||
tray.start(configuration.port, configuration.ngrokEndpoint);
|
||||
}
|
||||
|
||||
async function loadNGrok() {
|
||||
try {
|
||||
return await import('@ngrok/ngrok');
|
||||
} catch(e) {
|
||||
// ngrok can fail import if it cannot load its dependent binary library,
|
||||
// either because it is missing or because it has missing dependencies
|
||||
// itself. But we don't want to crash the server if that happens
|
||||
console.error(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function startNGrok() {
|
||||
console.log('Attempting to start ngrok');
|
||||
const ngrok = await loadNGrok();
|
||||
if(!ngrok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
let started = false;
|
||||
const listener = await ngrok.forward({
|
||||
proto: 'http',
|
||||
addr: configuration.port,
|
||||
authtoken: configuration.ngrokToken,
|
||||
onLogEvent: (msg: string) => {
|
||||
if(options.ngrokLog) {
|
||||
console.log(chalk.cyan(('\n'+msg).split('\n').join('\n[ngrok] ').trim()));
|
||||
}
|
||||
});
|
||||
console.log(chalk.blueBright('ngrok tunnel initially established at %s'), configuration.ngrokEndpoint);
|
||||
tray.start(configuration.port, configuration.ngrokEndpoint);
|
||||
})();
|
||||
}
|
||||
else {
|
||||
/* Load the tray icon */
|
||||
tray.start(configuration.port, configuration.ngrokEndpoint);
|
||||
},
|
||||
onStatusChange: (state: string) => {
|
||||
if(state == 'connected' && started) {
|
||||
// We only announce reconnection after initial start
|
||||
configuration.ngrokEndpoint = listener.url() ?? '';
|
||||
console.log(chalk.blueBright('ngrok tunnel reconnected at %s'), configuration.ngrokEndpoint);
|
||||
} else if(state == 'closed') {
|
||||
configuration.ngrokEndpoint = '';
|
||||
console.log(chalk.blueBright('ngrok tunnel closed'));
|
||||
}
|
||||
}
|
||||
});
|
||||
started = true;
|
||||
configuration.ngrokEndpoint = listener.url();
|
||||
console.log(chalk.blueBright('ngrok tunnel established at %s'), configuration.ngrokEndpoint);
|
||||
} catch(e) {
|
||||
configuration.ngrokEndpoint = '';
|
||||
console.error(chalk.red('ngrok tunnel failed to connect with an error: %s'), e);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function getRunningInstancePid(pidFilename: string) {
|
||||
|
|
|
|||
1
developer/src/server/src/ngrok.d.ts
vendored
|
|
@ -1 +0,0 @@
|
|||
declare module 'ngrok';
|
||||
|
|
@ -18,25 +18,6 @@
|
|||
"node-gyp": "^12.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/balanced-match": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
|
||||
"integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==",
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/brace-expansion": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.1.tgz",
|
||||
"integrity": "sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==",
|
||||
"dependencies": {
|
||||
"@isaacs/balanced-match": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/fs-minipass": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
|
||||
|
|
@ -90,6 +71,14 @@
|
|||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
|
||||
"integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
|
||||
"engines": {
|
||||
"node": "18 || 20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/bindings": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
|
||||
|
|
@ -98,6 +87,17 @@
|
|||
"file-uri-to-path": "1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz",
|
||||
"integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==",
|
||||
"dependencies": {
|
||||
"balanced-match": "^4.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "18 || 20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/cacache": {
|
||||
"version": "20.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cacache/-/cacache-20.0.3.tgz",
|
||||
|
|
@ -318,14 +318,14 @@
|
|||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "10.1.1",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz",
|
||||
"integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==",
|
||||
"version": "10.2.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz",
|
||||
"integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==",
|
||||
"dependencies": {
|
||||
"@isaacs/brace-expansion": "^5.0.0"
|
||||
"brace-expansion": "^5.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
"node": "18 || 20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
|
|
@ -642,9 +642,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/tar": {
|
||||
"version": "7.5.7",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-7.5.7.tgz",
|
||||
"integrity": "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==",
|
||||
"version": "7.5.10",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-7.5.10.tgz",
|
||||
"integrity": "sha512-8mOPs1//5q/rlkNSPcCegA6hiHJYDmSLEI8aMH/CdSQJNWztHC9WHNam5zdQlfpTwB9Xp7IBEsHfV5LKMJGVAw==",
|
||||
"dependencies": {
|
||||
"@isaacs/fs-minipass": "^4.0.0",
|
||||
"chownr": "^3.0.0",
|
||||
|
|
@ -717,19 +717,6 @@
|
|||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@isaacs/balanced-match": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
|
||||
"integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ=="
|
||||
},
|
||||
"@isaacs/brace-expansion": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.1.tgz",
|
||||
"integrity": "sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==",
|
||||
"requires": {
|
||||
"@isaacs/balanced-match": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"@isaacs/fs-minipass": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
|
||||
|
|
@ -768,6 +755,11 @@
|
|||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
|
||||
"integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
|
||||
"integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="
|
||||
},
|
||||
"bindings": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
|
||||
|
|
@ -776,6 +768,14 @@
|
|||
"file-uri-to-path": "1.0.0"
|
||||
}
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz",
|
||||
"integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==",
|
||||
"requires": {
|
||||
"balanced-match": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"cacache": {
|
||||
"version": "20.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cacache/-/cacache-20.0.3.tgz",
|
||||
|
|
@ -936,11 +936,11 @@
|
|||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "10.1.1",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz",
|
||||
"integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==",
|
||||
"version": "10.2.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz",
|
||||
"integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==",
|
||||
"requires": {
|
||||
"@isaacs/brace-expansion": "^5.0.0"
|
||||
"brace-expansion": "^5.0.2"
|
||||
}
|
||||
},
|
||||
"minipass": {
|
||||
|
|
@ -1166,9 +1166,9 @@
|
|||
}
|
||||
},
|
||||
"tar": {
|
||||
"version": "7.5.7",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-7.5.7.tgz",
|
||||
"integrity": "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==",
|
||||
"version": "7.5.10",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-7.5.10.tgz",
|
||||
"integrity": "sha512-8mOPs1//5q/rlkNSPcCegA6hiHJYDmSLEI8aMH/CdSQJNWztHC9WHNam5zdQlfpTwB9Xp7IBEsHfV5LKMJGVAw==",
|
||||
"requires": {
|
||||
"@isaacs/fs-minipass": "^4.0.0",
|
||||
"chownr": "^3.0.0",
|
||||
|
|
|
|||
|
|
@ -55,11 +55,13 @@ type
|
|||
InstallSize: Integer;
|
||||
end;
|
||||
|
||||
TInstallUILevel = (uiSilent, uiProgressOnly, uiFull);
|
||||
|
||||
TfrmRun = class(TSetupForm)
|
||||
public
|
||||
procedure cmdExitClick(Sender: TObject);
|
||||
procedure lblTitleClick(Sender: TObject);
|
||||
procedure cmdInstallKeymanDesktopClick(Sender: TObject);
|
||||
procedure cmdInstallKeymanDeveloperClick(Sender: TObject);
|
||||
|
||||
procedure FormCreate(Sender: TObject); override;
|
||||
procedure FormShow(Sender: TObject); override;
|
||||
|
|
@ -71,17 +73,13 @@ type
|
|||
FDownloadFilename: WideString;
|
||||
FDownloadURL: WideString;
|
||||
FNewVersion, FInstalledVersion, FInstallerVersion: TMSIInfo;
|
||||
//FInstalledVersion: WideString;
|
||||
FContinueSetup: Boolean;
|
||||
FWhiteBrush: THandle;
|
||||
FErrorLog: TStream;
|
||||
FPromptForReboot: Boolean; // I3355 // I3500
|
||||
FSilent: Boolean;
|
||||
FUILevel: TInstallUILevel;
|
||||
FOfflineByRequest: Boolean;
|
||||
FOnline: Boolean;
|
||||
//FInstalledProductCode: WideString;
|
||||
//FInstallerProductCode: WideString;
|
||||
//FNewProductCode: WideString;
|
||||
|
||||
procedure LogError(const msg: WideString; ShowDialogIfNotSilent: Boolean = True);
|
||||
|
||||
|
|
@ -107,7 +105,7 @@ type
|
|||
function DialogID: Integer; override;
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
function DoInstall(Silent, PromptForReboot: Boolean): Boolean; // I3355 // I3500
|
||||
function DoInstall(UILevel: TInstallUILevel; PromptForReboot: Boolean): Boolean; // I3355 // I3500
|
||||
property ContinueSetup: Boolean read FContinueSetup write FContinueSetup;
|
||||
property Offline: Boolean read FOfflineByRequest write SetOfflineByRequest;
|
||||
end;
|
||||
|
|
@ -225,7 +223,7 @@ end;
|
|||
function TfrmRun.InstallNewVersion: Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
if not FSilent and (MessageDlgW(FInstallInfo.Text(ssQueryUpdateVersion, [FNewVersion.InstallSize div 1024, FNewVersion.Version]), // I2680
|
||||
if (FUILevel = uiFull) and (MessageDlgW(FInstallInfo.Text(ssQueryUpdateVersion, [FNewVersion.InstallSize div 1024, FNewVersion.Version]), // I2680
|
||||
mtConfirmation, mbOkCancel, 0) = mrCancel) then
|
||||
Exit;
|
||||
|
||||
|
|
@ -320,12 +318,12 @@ end;
|
|||
procedure TfrmRun.WMUserFormShown(var Message: TMessage);
|
||||
begin
|
||||
if FContinueSetup then
|
||||
DoInstall(False, True); // I3355 // I3500
|
||||
DoInstall(uiFull, True); // I3355 // I3500
|
||||
end;
|
||||
|
||||
procedure TfrmRun.cmdInstallKeymanDesktopClick(Sender: TObject);
|
||||
procedure TfrmRun.cmdInstallKeymanDeveloperClick(Sender: TObject);
|
||||
begin
|
||||
if DoInstall(False, True) then // I1901 and I2680.4 // I3355 // I3500
|
||||
if DoInstall(uiFull, True) then // I1901 and I2680.4 // I3355 // I3500
|
||||
ModalResult := mrOk;
|
||||
end;
|
||||
|
||||
|
|
@ -392,11 +390,10 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
function TfrmRun.DoInstall(Silent, PromptForReboot: Boolean): Boolean; // I1901 // I3355 // I3500
|
||||
function TfrmRun.DoInstall(UILevel: TInstallUILevel; PromptForReboot: Boolean): Boolean; // I1901 // I3355 // I3500
|
||||
begin
|
||||
FPromptForReboot := PromptForReboot; // I3355 // I3500
|
||||
FSilent := Silent;
|
||||
|
||||
FUILevel := UILevel;
|
||||
|
||||
SetCursor(LoadCursor(0, IDC_WAIT));
|
||||
try
|
||||
|
|
@ -671,8 +668,10 @@ begin
|
|||
|
||||
FCacheFileName := CacheMSIFile(ExtPath + FInstallInfo.MSIFileName); // I3310
|
||||
|
||||
if FSilent then
|
||||
if FUILevel = uiSilent then
|
||||
MsiSetInternalUI(INSTALLUILEVEL_NONE, nil)
|
||||
else if FUILevel = uiProgressOnly then
|
||||
MsiSetInternalUI(INSTALLUILEVEL_BASIC, nil)
|
||||
else
|
||||
MsiSetInternalUI(INSTALLUILEVEL_FULL, nil);
|
||||
res := MsiInstallProductW(PWideChar(FCacheFileName), PWideChar('DISABLEFINALOPTIONS=1 '+ReinstallMode));
|
||||
|
|
@ -694,16 +693,13 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
if not FSilent then
|
||||
if FUILevel = uiFull then
|
||||
MsiSetInternalUI(INSTALLUILEVEL_FULL, nil);
|
||||
|
||||
if FNewVersion.Filename <> '' then
|
||||
begin
|
||||
//Run the setup app silently // I2680.5
|
||||
TUtilExecute.WaitForProcess('"'+ExtPath + FNewVersion.FileName+'" -s -o', ExtPath, SW_SHOW, WaitFor); // I3349
|
||||
//if not FSilent then
|
||||
// MsiSetInternalUI(INSTALLUILEVEL_BASIC, nil);
|
||||
//CheckMSIResult(MsiApplyPatchW(PWideChar(ExtPath + FNewVersion.Filename), nil, INSTALLTYPE_DEFAULT, ''));
|
||||
end;
|
||||
end;
|
||||
|
||||
|
|
@ -712,7 +708,7 @@ function TfrmRun.ProcessCommand(ID, NotificationCode: Integer;
|
|||
begin
|
||||
Result := True;
|
||||
case ID of
|
||||
IDOK: cmdInstallKeymanDesktopClick(Self);
|
||||
IDOK: cmdInstallKeymanDeveloperClick(Self);
|
||||
IDCANCEL: cmdExitClick(Self);
|
||||
else Result := False;
|
||||
end;
|
||||
|
|
@ -727,7 +723,7 @@ procedure TfrmRun.LogError(const msg: WideString; ShowDialogIfNotSilent: Boolean
|
|||
const
|
||||
nl: WideString = #13#10;
|
||||
begin
|
||||
if not FSilent and ShowDialogIfNotSilent then
|
||||
if (FUILevel = uiFull) and ShowDialogIfNotSilent then
|
||||
ShowMessageW(msg);
|
||||
if not Assigned(FErrorLog) then
|
||||
begin
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
(*
|
||||
Name: bootstrapmain
|
||||
Copyright: Copyright (C) SIL International.
|
||||
Documentation:
|
||||
Description:
|
||||
Documentation:
|
||||
Description:
|
||||
Create Date: 4 Jun 2007
|
||||
|
||||
Modified Date: 12 Aug 2014
|
||||
Authors: mcdurdin
|
||||
Related Files:
|
||||
Dependencies:
|
||||
Related Files:
|
||||
Dependencies:
|
||||
|
||||
Bugs:
|
||||
Todo:
|
||||
Notes:
|
||||
Bugs:
|
||||
Todo:
|
||||
Notes:
|
||||
History: 04 Jun 2007 - mcdurdin - Initial version
|
||||
05 Jun 2007 - mcdurdin - I817 - Fix -x option
|
||||
19 Jun 2007 - mcdurdin - I817 - Translate to Unicode and remove Forms dependence
|
||||
|
|
@ -123,12 +123,12 @@ begin
|
|||
DeletePath(TempPath); // I3310
|
||||
end;
|
||||
|
||||
procedure ProcessCommandLine(var FPromptForReboot, FSilent, FOffline, FExtractOnly, FContinueSetup: Boolean; var FExtractPath: WideString); // I3355 // I3500
|
||||
procedure ProcessCommandLine(var FUILevel: TInstallUILevel; var FPromptForReboot, FOffline, FExtractOnly, FContinueSetup: Boolean; var FExtractPath: WideString); // I3355 // I3500
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
FPromptForReboot := True; // I3355 // I3500
|
||||
FSilent := False;
|
||||
FUILevel := uiFull;
|
||||
FOffline := False;
|
||||
FExtractOnly := False;
|
||||
FContinueSetup := False;
|
||||
|
|
@ -139,13 +139,13 @@ begin
|
|||
FContinueSetup := True
|
||||
else if WideSameText(ParamStr(i), '-au') then // I2849
|
||||
begin
|
||||
FSilent := True;
|
||||
FUILevel := uiProgressOnly;
|
||||
FOffline := True;
|
||||
end
|
||||
else if WideSameText(ParamStr(i), '-s') then
|
||||
begin
|
||||
FPromptForReboot := False; // I3355 // I3500
|
||||
FSilent := True;
|
||||
FUILevel := uiSilent;
|
||||
end
|
||||
else if WideSameText(ParamStr(i), '-o') then
|
||||
FOffline := True
|
||||
|
|
@ -169,7 +169,7 @@ var
|
|||
FExtractOnly: Boolean;
|
||||
FContinueSetup: Boolean;
|
||||
FPromptForReboot: Boolean; // I3355 // I3500
|
||||
FSilent: Boolean;
|
||||
FUILevel: TInstallUILevel;
|
||||
FOffline: Boolean;
|
||||
FExtractOnly_Path: WideString;
|
||||
BEGIN
|
||||
|
|
@ -193,11 +193,11 @@ BEGIN
|
|||
{ Display the dialog }
|
||||
//Cancel_From_InfoWin := False;
|
||||
|
||||
ProcessCommandLine(FPromptForReboot, FSilent, FOffline, FExtractOnly, FContinueSetup, FExtractOnly_Path); // I3355 // I3500
|
||||
ProcessCommandLine(FUILevel, FPromptForReboot, FOffline, FExtractOnly, FContinueSetup, FExtractOnly_Path); // I3355 // I3500
|
||||
|
||||
if FExtractOnly then
|
||||
begin
|
||||
DoExtractOnly(FSilent, FExtractOnly_Path);
|
||||
DoExtractOnly(FUILevel = uiSilent, FExtractOnly_Path);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
|
|
@ -224,8 +224,8 @@ BEGIN
|
|||
try
|
||||
ContinueSetup := FContinueSetup;
|
||||
Offline := FOffline;
|
||||
if FSilent
|
||||
then DoInstall(True, FPromptForReboot) // I3355 // I3500
|
||||
if FUILevel <> uiFull
|
||||
then DoInstall(FUILevel, FPromptForReboot) // I3355 // I3500
|
||||
else ShowModal;
|
||||
finally
|
||||
Free;
|
||||
|
|
|
|||
|
|
@ -1,92 +1,94 @@
|
|||
inherited frmLdmlKeyboardDebug: TfrmLdmlKeyboardDebug
|
||||
Left = 85
|
||||
Top = 229
|
||||
BorderIcons = [biSystemMenu]
|
||||
BorderStyle = bsSizeToolWin
|
||||
Caption = 'Debug'
|
||||
ClientHeight = 132
|
||||
ClientWidth = 755
|
||||
Font.Name = 'MS Sans Serif'
|
||||
FormStyle = fsStayOnTop
|
||||
KeyPreview = True
|
||||
Position = poDefault
|
||||
OnClose = FormClose
|
||||
OnDestroy = FormDestroy
|
||||
OnResize = FormResize
|
||||
ExplicitWidth = 771
|
||||
ExplicitHeight = 171
|
||||
PixelsPerInch = 96
|
||||
TextHeight = 13
|
||||
object memo: TKeymanDeveloperDebuggerMemo
|
||||
Left = 0
|
||||
Top = 0
|
||||
Width = 755
|
||||
Height = 73
|
||||
Cursor = crIBeam
|
||||
Align = alClient
|
||||
BorderStyle = bsNone
|
||||
Font.Charset = ANSI_CHARSET
|
||||
Font.Color = clWindowText
|
||||
Font.Height = -11
|
||||
Font.Name = 'Arial'
|
||||
Font.Style = []
|
||||
ParentFont = False
|
||||
PlainText = True
|
||||
PopupMenu = mnuPopup
|
||||
ScrollBars = ssVertical
|
||||
TabOrder = 0
|
||||
OnChange = memoChange
|
||||
OnClick = memoClick
|
||||
OnEnter = memoGotFocus
|
||||
OnKeyUp = memoKeyUp
|
||||
OnMessage = memoMessage
|
||||
IsDebugging = False
|
||||
end
|
||||
object sgChars: TStringGrid
|
||||
Left = 0
|
||||
Top = 73
|
||||
Width = 755
|
||||
Height = 59
|
||||
Align = alBottom
|
||||
ColCount = 1
|
||||
DefaultDrawing = False
|
||||
FixedCols = 0
|
||||
RowCount = 2
|
||||
FixedRows = 0
|
||||
ScrollBars = ssNone
|
||||
TabOrder = 1
|
||||
OnDrawCell = sgCharsDrawCell
|
||||
ColWidths = (
|
||||
64)
|
||||
RowHeights = (
|
||||
24
|
||||
24)
|
||||
end
|
||||
object mnuPopup: TPopupMenu
|
||||
Images = frmKeymanDeveloper.lstImages
|
||||
Left = 228
|
||||
Top = 73
|
||||
object mnuPopupFont: TMenuItem
|
||||
Action = modActionsDebugger.actDebugViewFont
|
||||
end
|
||||
object mnuPopupResetToQuotedFont: TMenuItem
|
||||
Action = modActionsDebugger.actDebugViewDefaultFont
|
||||
end
|
||||
object N1: TMenuItem
|
||||
Caption = '-'
|
||||
end
|
||||
object mnuCut: TMenuItem
|
||||
Action = modActionsMain.actEditCut
|
||||
end
|
||||
object mnuCopy: TMenuItem
|
||||
Action = modActionsMain.actEditCopy
|
||||
end
|
||||
object mnuPaste: TMenuItem
|
||||
Action = modActionsMain.actEditPaste
|
||||
end
|
||||
end
|
||||
object appEvents: TApplicationEvents
|
||||
Left = 368
|
||||
Top = 72
|
||||
end
|
||||
end
|
||||
inherited frmLdmlKeyboardDebug: TfrmLdmlKeyboardDebug
|
||||
Left = 85
|
||||
Top = 229
|
||||
BorderIcons = [biSystemMenu]
|
||||
BorderStyle = bsSizeToolWin
|
||||
Caption = 'Debug'
|
||||
ClientHeight = 132
|
||||
ClientWidth = 755
|
||||
Font.Name = 'MS Sans Serif'
|
||||
FormStyle = fsStayOnTop
|
||||
KeyPreview = True
|
||||
Position = poDefault
|
||||
OnClose = FormClose
|
||||
OnDestroy = FormDestroy
|
||||
OnResize = FormResize
|
||||
ExplicitWidth = 771
|
||||
ExplicitHeight = 171
|
||||
PixelsPerInch = 96
|
||||
TextHeight = 13
|
||||
object memo: TKeymanDeveloperDebuggerMemo
|
||||
Left = 0
|
||||
Top = 0
|
||||
Width = 755
|
||||
Height = 73
|
||||
Cursor = crIBeam
|
||||
Align = alClient
|
||||
BorderStyle = bsNone
|
||||
Font.Charset = ANSI_CHARSET
|
||||
Font.Color = clWindowText
|
||||
Font.Height = -11
|
||||
Font.Name = 'Arial'
|
||||
Font.Style = []
|
||||
ParentFont = False
|
||||
PlainText = True
|
||||
PopupMenu = mnuPopup
|
||||
ScrollBars = ssVertical
|
||||
TabOrder = 0
|
||||
OnChange = memoChange
|
||||
OnClick = memoClick
|
||||
OnDblClick = memoDblClick
|
||||
OnEnter = memoGotFocus
|
||||
OnKeyUp = memoKeyUp
|
||||
OnSelectionChange = memoSelMove
|
||||
OnMessage = memoMessage
|
||||
IsDebugging = False
|
||||
end
|
||||
object sgChars: TStringGrid
|
||||
Left = 0
|
||||
Top = 73
|
||||
Width = 755
|
||||
Height = 59
|
||||
Align = alBottom
|
||||
ColCount = 1
|
||||
DefaultDrawing = False
|
||||
FixedCols = 0
|
||||
RowCount = 2
|
||||
FixedRows = 0
|
||||
ScrollBars = ssNone
|
||||
TabOrder = 1
|
||||
OnDrawCell = sgCharsDrawCell
|
||||
ColWidths = (
|
||||
64)
|
||||
RowHeights = (
|
||||
24
|
||||
24)
|
||||
end
|
||||
object mnuPopup: TPopupMenu
|
||||
Images = frmKeymanDeveloper.lstImages
|
||||
Left = 228
|
||||
Top = 73
|
||||
object mnuPopupFont: TMenuItem
|
||||
Action = modActionsDebugger.actDebugViewFont
|
||||
end
|
||||
object mnuPopupResetToQuotedFont: TMenuItem
|
||||
Action = modActionsDebugger.actDebugViewDefaultFont
|
||||
end
|
||||
object N1: TMenuItem
|
||||
Caption = '-'
|
||||
end
|
||||
object mnuCut: TMenuItem
|
||||
Action = modActionsMain.actEditCut
|
||||
end
|
||||
object mnuCopy: TMenuItem
|
||||
Action = modActionsMain.actEditCopy
|
||||
end
|
||||
object mnuPaste: TMenuItem
|
||||
Action = modActionsMain.actEditPaste
|
||||
end
|
||||
end
|
||||
object appEvents: TApplicationEvents
|
||||
Left = 368
|
||||
Top = 72
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ type
|
|||
procedure memoClick(Sender: TObject); // I4808
|
||||
procedure memoKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
|
||||
procedure FormResize(Sender: TObject);
|
||||
procedure memoDblClick(Sender: TObject);
|
||||
private
|
||||
FFileName: string;
|
||||
debugkeyboard: TDebugKeyboard;
|
||||
|
|
@ -108,6 +109,7 @@ type
|
|||
function SetKeyEventContext: Boolean;
|
||||
function HandleMemoKeydown(var Message: TMessage): Boolean;
|
||||
procedure Run(vkey: Word);
|
||||
procedure UpdateMemoSelection;
|
||||
|
||||
protected
|
||||
function GetHelpTopic: string; override;
|
||||
|
|
@ -206,13 +208,13 @@ end;
|
|||
|
||||
procedure TfrmLdmlKeyboardDebug.memoGotFocus(Sender: TObject);
|
||||
begin
|
||||
memoSelMove(memo);
|
||||
UpdateMemoSelection;
|
||||
end;
|
||||
|
||||
procedure TfrmLdmlKeyboardDebug.memoKeyUp(Sender: TObject; var Key: Word;
|
||||
Shift: TShiftState);
|
||||
begin
|
||||
memoSelMove(memo);
|
||||
UpdateMemoSelection;
|
||||
end;
|
||||
|
||||
function TfrmLdmlKeyboardDebug.HandleMemoKeydown(var Message: TMessage): Boolean;
|
||||
|
|
@ -391,7 +393,7 @@ procedure TfrmLdmlKeyboardDebug.Run(vkey: Word);
|
|||
dk: TDeadKeyInfo;
|
||||
begin
|
||||
Result.Selection := memo.Selection;
|
||||
Result.Length := Length(memo.Text);
|
||||
Result.Length := Length(memo.GetTextCR);
|
||||
for dk in FDeadkeys do
|
||||
begin
|
||||
if dk.Position >= Result.Selection.Start
|
||||
|
|
@ -406,7 +408,7 @@ procedure TfrmLdmlKeyboardDebug.Run(vkey: Word);
|
|||
L: Integer;
|
||||
s: string;
|
||||
begin
|
||||
s := memo.Text;
|
||||
s := memo.GetTextCR;
|
||||
L := Length(s);
|
||||
for dk in FDeadkeys do
|
||||
if dk.SavedPosition < 0 then
|
||||
|
|
@ -430,10 +432,6 @@ procedure TfrmLdmlKeyboardDebug.Run(vkey: Word);
|
|||
|
||||
if GetKeyState(VK_CONTROL) >= 0 then
|
||||
begin
|
||||
if (vk = VK_RETURN) and (GetKeyState(VK_MENU) >= 0) then
|
||||
begin
|
||||
memo.SelText := #13#10;
|
||||
end;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
|
|
@ -591,13 +589,13 @@ begin
|
|||
RealignMemoSelectionState(state);
|
||||
selection := memo.Selection;
|
||||
end;
|
||||
lhs := Copy(memo.Text, 1, selection.Start);
|
||||
lhs := Copy(memo.GetTextCR, 1, selection.Start);
|
||||
end
|
||||
else
|
||||
lhs := '';
|
||||
|
||||
context := Copy(memo.Text, lhs.Length + 1, selection.Start - lhs.Length);
|
||||
rhs := Copy(memo.Text, lhs.Length + context.Length + 1, MaxInt);
|
||||
context := Copy(memo.GetTextCR, lhs.Length + 1, selection.Start - lhs.Length);
|
||||
rhs := Copy(memo.GetTextCR, lhs.Length + context.Length + 1, MaxInt);
|
||||
|
||||
// Reinsert the context
|
||||
|
||||
|
|
@ -635,7 +633,7 @@ begin
|
|||
SendMessage(memo.Handle, (WM_USER + 97) {EM_SETTEXTEX}, NativeUint(@ste), NativeUInt(PChar(str)));
|
||||
selection.Start := lhs.Length + output.Length;
|
||||
selection.Finish := selection.Start;
|
||||
selection.Anchor := selection.Start;
|
||||
selection.Caret := selection.Start;
|
||||
memo.Selection := selection;
|
||||
finally
|
||||
memo.Lines.EndUpdate;
|
||||
|
|
@ -820,22 +818,32 @@ end;
|
|||
procedure TfrmLdmlKeyboardDebug.memoChange(Sender: TObject);
|
||||
begin
|
||||
UpdateDeadkeys;
|
||||
memoSelMove(memo);
|
||||
UpdateMemoSelection;
|
||||
end;
|
||||
|
||||
procedure TfrmLdmlKeyboardDebug.memoClick(Sender: TObject);
|
||||
begin
|
||||
memoSelMove(memo);
|
||||
UpdateMemoSelection;
|
||||
end;
|
||||
|
||||
procedure TfrmLdmlKeyboardDebug.memoDblClick(Sender: TObject);
|
||||
begin
|
||||
UpdateMemoSelection;
|
||||
end;
|
||||
|
||||
procedure TfrmLdmlKeyboardDebug.memoSelMove(Sender: TObject);
|
||||
begin
|
||||
UpdateMemoSelection;
|
||||
end;
|
||||
|
||||
procedure TfrmLdmlKeyboardDebug.UpdateMemoSelection;
|
||||
begin
|
||||
if memo.Focused then
|
||||
begin
|
||||
frmKeymanDeveloper.barStatus.Panels[0].Text := 'Debugger Active';
|
||||
end;
|
||||
|
||||
if not memo.ReadOnly and not memo.SelectionChanging then
|
||||
if not memo.ReadOnly then
|
||||
begin
|
||||
UpdateCharacterGrid; // I4808
|
||||
end;
|
||||
|
|
@ -844,20 +852,22 @@ end;
|
|||
procedure TfrmLdmlKeyboardDebug.UpdateCharacterGrid; // I4808
|
||||
var
|
||||
start, len: Integer;
|
||||
text: string;
|
||||
begin
|
||||
if csDestroying in ComponentState then
|
||||
Exit;
|
||||
|
||||
start := memo.SelStart;
|
||||
len := memo.SelLength;
|
||||
if start + len > Length(memo.Text) then
|
||||
text := memo.GetTextCR;
|
||||
if start + len > text.Length then
|
||||
begin
|
||||
// RichEdit has a virtual final character, which is selected when
|
||||
// pressing Ctrl+A, etc.
|
||||
len := Length(memo.Text) - start;
|
||||
len := text.Length - start;
|
||||
end;
|
||||
TCharacterGridRenderer.Fill(sgChars, memo.Text, FDeadkeys, start, len,
|
||||
memo.Selection.Anchor, True);
|
||||
TCharacterGridRenderer.Fill(sgChars, text, FDeadkeys, start, len,
|
||||
memo.Selection.Caret, True);
|
||||
TCharacterGridRenderer.Size(sgChars, memo.Font);
|
||||
end;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,93 +1,95 @@
|
|||
inherited frmDebug: TfrmDebug
|
||||
Left = 85
|
||||
Top = 229
|
||||
BorderIcons = [biSystemMenu]
|
||||
BorderStyle = bsSizeToolWin
|
||||
Caption = 'Debug'
|
||||
ClientHeight = 132
|
||||
ClientWidth = 755
|
||||
Font.Name = 'MS Sans Serif'
|
||||
FormStyle = fsStayOnTop
|
||||
KeyPreview = True
|
||||
Position = poDefault
|
||||
OnClose = FormClose
|
||||
OnDestroy = FormDestroy
|
||||
OnResize = FormResize
|
||||
ExplicitWidth = 771
|
||||
ExplicitHeight = 171
|
||||
PixelsPerInch = 96
|
||||
TextHeight = 13
|
||||
object memo: TKeymanDeveloperDebuggerMemo
|
||||
Left = 0
|
||||
Top = 0
|
||||
Width = 755
|
||||
Height = 73
|
||||
Cursor = crIBeam
|
||||
Align = alClient
|
||||
BorderStyle = bsNone
|
||||
Font.Charset = ANSI_CHARSET
|
||||
Font.Color = clWindowText
|
||||
Font.Height = -11
|
||||
Font.Name = 'Arial'
|
||||
Font.Style = []
|
||||
ParentFont = False
|
||||
PlainText = True
|
||||
PopupMenu = mnuPopup
|
||||
ScrollBars = ssVertical
|
||||
TabOrder = 0
|
||||
OnChange = memoChange
|
||||
OnClick = memoClick
|
||||
OnEnter = memoGotFocus
|
||||
OnExit = memoLostFocus
|
||||
OnKeyUp = memoKeyUp
|
||||
OnMessage = memoMessage
|
||||
IsDebugging = False
|
||||
end
|
||||
object sgChars: TStringGrid
|
||||
Left = 0
|
||||
Top = 73
|
||||
Width = 755
|
||||
Height = 59
|
||||
Align = alBottom
|
||||
ColCount = 1
|
||||
DefaultDrawing = False
|
||||
FixedCols = 0
|
||||
RowCount = 2
|
||||
FixedRows = 0
|
||||
ScrollBars = ssNone
|
||||
TabOrder = 1
|
||||
OnDrawCell = sgCharsDrawCell
|
||||
ColWidths = (
|
||||
64)
|
||||
RowHeights = (
|
||||
24
|
||||
24)
|
||||
end
|
||||
object mnuPopup: TPopupMenu
|
||||
Images = frmKeymanDeveloper.lstImages
|
||||
Left = 228
|
||||
Top = 73
|
||||
object mnuPopupFont: TMenuItem
|
||||
Action = modActionsDebugger.actDebugViewFont
|
||||
end
|
||||
object mnuPopupResetToQuotedFont: TMenuItem
|
||||
Action = modActionsDebugger.actDebugViewDefaultFont
|
||||
end
|
||||
object N1: TMenuItem
|
||||
Caption = '-'
|
||||
end
|
||||
object mnuCut: TMenuItem
|
||||
Action = modActionsMain.actEditCut
|
||||
end
|
||||
object mnuCopy: TMenuItem
|
||||
Action = modActionsMain.actEditCopy
|
||||
end
|
||||
object mnuPaste: TMenuItem
|
||||
Action = modActionsMain.actEditPaste
|
||||
end
|
||||
end
|
||||
object appEvents: TApplicationEvents
|
||||
Left = 368
|
||||
Top = 72
|
||||
end
|
||||
end
|
||||
inherited frmDebug: TfrmDebug
|
||||
Left = 85
|
||||
Top = 229
|
||||
BorderIcons = [biSystemMenu]
|
||||
BorderStyle = bsSizeToolWin
|
||||
Caption = 'Debug'
|
||||
ClientHeight = 132
|
||||
ClientWidth = 755
|
||||
Font.Name = 'MS Sans Serif'
|
||||
FormStyle = fsStayOnTop
|
||||
KeyPreview = True
|
||||
Position = poDefault
|
||||
OnClose = FormClose
|
||||
OnDestroy = FormDestroy
|
||||
OnResize = FormResize
|
||||
ExplicitWidth = 771
|
||||
ExplicitHeight = 171
|
||||
PixelsPerInch = 96
|
||||
TextHeight = 13
|
||||
object memo: TKeymanDeveloperDebuggerMemo
|
||||
Left = 0
|
||||
Top = 0
|
||||
Width = 755
|
||||
Height = 73
|
||||
Cursor = crIBeam
|
||||
Align = alClient
|
||||
BorderStyle = bsNone
|
||||
Font.Charset = ANSI_CHARSET
|
||||
Font.Color = clWindowText
|
||||
Font.Height = -11
|
||||
Font.Name = 'Arial'
|
||||
Font.Style = []
|
||||
ParentFont = False
|
||||
PlainText = True
|
||||
PopupMenu = mnuPopup
|
||||
ScrollBars = ssVertical
|
||||
TabOrder = 0
|
||||
OnChange = memoChange
|
||||
OnClick = memoClick
|
||||
OnDblClick = memoDblClick
|
||||
OnEnter = memoGotFocus
|
||||
OnExit = memoLostFocus
|
||||
OnKeyUp = memoKeyUp
|
||||
OnSelectionChange = memoSelMove
|
||||
OnMessage = memoMessage
|
||||
IsDebugging = False
|
||||
end
|
||||
object sgChars: TStringGrid
|
||||
Left = 0
|
||||
Top = 73
|
||||
Width = 755
|
||||
Height = 59
|
||||
Align = alBottom
|
||||
ColCount = 1
|
||||
DefaultDrawing = False
|
||||
FixedCols = 0
|
||||
RowCount = 2
|
||||
FixedRows = 0
|
||||
ScrollBars = ssNone
|
||||
TabOrder = 1
|
||||
OnDrawCell = sgCharsDrawCell
|
||||
ColWidths = (
|
||||
64)
|
||||
RowHeights = (
|
||||
24
|
||||
24)
|
||||
end
|
||||
object mnuPopup: TPopupMenu
|
||||
Images = frmKeymanDeveloper.lstImages
|
||||
Left = 228
|
||||
Top = 73
|
||||
object mnuPopupFont: TMenuItem
|
||||
Action = modActionsDebugger.actDebugViewFont
|
||||
end
|
||||
object mnuPopupResetToQuotedFont: TMenuItem
|
||||
Action = modActionsDebugger.actDebugViewDefaultFont
|
||||
end
|
||||
object N1: TMenuItem
|
||||
Caption = '-'
|
||||
end
|
||||
object mnuCut: TMenuItem
|
||||
Action = modActionsMain.actEditCut
|
||||
end
|
||||
object mnuCopy: TMenuItem
|
||||
Action = modActionsMain.actEditCopy
|
||||
end
|
||||
object mnuPaste: TMenuItem
|
||||
Action = modActionsMain.actEditPaste
|
||||
end
|
||||
end
|
||||
object appEvents: TApplicationEvents
|
||||
Left = 368
|
||||
Top = 72
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ type
|
|||
procedure memoClick(Sender: TObject); // I4808
|
||||
procedure memoKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
|
||||
procedure FormResize(Sender: TObject);
|
||||
procedure memoDblClick(Sender: TObject);
|
||||
private
|
||||
|
||||
FDebugVisible: Boolean;
|
||||
|
|
@ -118,6 +119,7 @@ type
|
|||
function GetStatusText: string;
|
||||
procedure SetStatusText(Value: string);
|
||||
procedure UpdateDebugStatusForm; // I4809
|
||||
procedure UpdateMemoSelection;
|
||||
|
||||
private
|
||||
FDebugCore: TDebugCore;
|
||||
|
|
@ -147,6 +149,7 @@ type
|
|||
procedure SetCurrentEvent(Value: Integer);
|
||||
procedure FinishBatch;
|
||||
procedure StartBatch;
|
||||
procedure RecordBreadcrumb(const message: string);
|
||||
|
||||
protected
|
||||
function GetHelpTopic: string; override;
|
||||
|
|
@ -306,13 +309,13 @@ begin
|
|||
if UIStatus = duiReadyForInput then
|
||||
UIStatus := duiFocusedForInput;
|
||||
|
||||
memoSelMove(memo);
|
||||
UpdateMemoSelection;
|
||||
end;
|
||||
|
||||
procedure TfrmDebug.memoKeyUp(Sender: TObject; var Key: Word;
|
||||
Shift: TShiftState);
|
||||
begin
|
||||
memoSelMove(memo);
|
||||
UpdateMemoSelection;
|
||||
end;
|
||||
|
||||
procedure TfrmDebug.memoLostFocus(Sender: TObject);
|
||||
|
|
@ -463,9 +466,8 @@ begin
|
|||
modifier := modifier and not KM_CORE_MODIFIER_LCTRL;
|
||||
end;
|
||||
|
||||
TKeymanSentryClient.Instance.Breadcrumb('default',
|
||||
Format('ProcessKeyEvent: vk=%x mod=%x scan=%x beforeText="%s" beforeSelection=%s',[vkey, modifier, scan, Copy(memo.GetTextCR, 1, 256), memo.Selection.ToString]),
|
||||
'debugger');
|
||||
RecordBreadcrumb(
|
||||
Format('ProcessKeyEvent: vk=%x mod=%x scan=%x beforeText="%s" beforeSelection=%s savedSelection=%s',[vkey, modifier, scan, Copy(memo.GetTextCR, 1, 256), memo.Selection.ToString, FSavedSelection.ToString]));
|
||||
|
||||
if not SetKeyEventContext then
|
||||
Exit(False);
|
||||
|
|
@ -601,12 +603,17 @@ end;
|
|||
|
||||
{ Stores }
|
||||
|
||||
procedure TfrmDebug.RecordBreadcrumb(const message: string);
|
||||
begin
|
||||
// TODO(v20): eliminate breadcrumbs once underlying bug #11706 is confirmed fixed
|
||||
TKeymanSentryClient.Instance.Breadcrumb('default', message, 'debugger');
|
||||
// OutputDebugString(PChar(message));
|
||||
end;
|
||||
|
||||
procedure TfrmDebug.ExecuteEvent(n: Integer);
|
||||
begin
|
||||
TKeymanSentryClient.Instance.Breadcrumb('default',
|
||||
Format('ExecuteEvent(%d/%d): [%s]; b:%s; s:%s',
|
||||
[n, FEvents.Count, FEvents[n].ToString, memo.Selection.ToString, FSavedSelection.ToString]),
|
||||
'debugger');
|
||||
RecordBreadcrumb(Format('ExecuteEvent(%d/%d): [%s] beforeSelection=%s savedSelection=%s',
|
||||
[n, FEvents.Count, FEvents[n].ToString, memo.Selection.ToString, FSavedSelection.ToString]));
|
||||
|
||||
memo.ReadOnly := False;
|
||||
memo.Selection := FSavedSelection;
|
||||
|
|
@ -1323,22 +1330,32 @@ end;
|
|||
procedure TfrmDebug.memoChange(Sender: TObject);
|
||||
begin
|
||||
UpdateDeadkeys;
|
||||
memoSelMove(memo);
|
||||
UpdateMemoSelection;
|
||||
end;
|
||||
|
||||
procedure TfrmDebug.memoClick(Sender: TObject);
|
||||
begin
|
||||
memoSelMove(memo);
|
||||
UpdateMemoSelection;
|
||||
end;
|
||||
|
||||
procedure TfrmDebug.memoDblClick(Sender: TObject);
|
||||
begin
|
||||
UpdateMemoSelection;
|
||||
end;
|
||||
|
||||
procedure TfrmDebug.memoSelMove(Sender: TObject);
|
||||
begin
|
||||
UpdateMemoSelection;
|
||||
end;
|
||||
|
||||
procedure TfrmDebug.UpdateMemoSelection;
|
||||
begin
|
||||
if memo.Focused then
|
||||
begin
|
||||
frmKeymanDeveloper.barStatus.Panels[0].Text := 'Debugger Active';
|
||||
end;
|
||||
|
||||
if not memo.ReadOnly and not memo.SelectionChanging then
|
||||
if not memo.ReadOnly then
|
||||
begin
|
||||
FSavedSelection := memo.Selection;
|
||||
UpdateCharacterGrid; // I4808
|
||||
|
|
@ -1363,7 +1380,7 @@ begin
|
|||
len := t.Length - start;
|
||||
end;
|
||||
|
||||
TCharacterGridRenderer.Fill(sgChars, t, FDeadkeys, start, len, memo.Selection.Anchor);
|
||||
TCharacterGridRenderer.Fill(sgChars, t, FDeadkeys, start, len, memo.Selection.Caret);
|
||||
TCharacterGridRenderer.Size(sgChars, memo.Font);
|
||||
end;
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ type
|
|||
|
||||
class procedure Fill(grid: TStringGrid; const text: string;
|
||||
deadkeys: TDebugDeadkeyInfoList;
|
||||
SelStart, SelLength, SelAnchor: Integer;
|
||||
SelStart, SelLength, Caret: Integer;
|
||||
DeadkeysAreCalledMarkers: Boolean = False); static;
|
||||
class procedure Render(grid: TStringGrid; ACol, ARow: Integer;
|
||||
Rect: TRect; State: TGridDrawState; CharFont: TFont); static;
|
||||
|
|
@ -37,7 +37,7 @@ uses
|
|||
|
||||
class procedure TCharacterGridRenderer.Fill(grid: TStringGrid;
|
||||
const text: string; deadkeys: TDebugDeadkeyInfoList;
|
||||
SelStart, SelLength, SelAnchor: Integer;
|
||||
SelStart, SelLength, Caret: Integer;
|
||||
DeadkeysAreCalledMarkers: Boolean);
|
||||
type
|
||||
TCellType = (ctChar, ctDeadkey);
|
||||
|
|
@ -171,10 +171,10 @@ begin
|
|||
|
||||
X := 0;
|
||||
FillGrid(Before, 0, X);
|
||||
if SelAnchor = SelStart then
|
||||
if Caret = SelStart then
|
||||
FillGridCursor(X);
|
||||
FillGrid(Selection, CELL_SELECTED, X);
|
||||
if SelAnchor <> SelStart then
|
||||
if Caret <> SelStart then
|
||||
FillGridCursor(X);
|
||||
FillGrid(After, 0, X);
|
||||
end;
|
||||
|
|
|
|||