@keymanapp/kmc-kmn 17.0.154-alpha → 17.0.156-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/build/src/compiler/compiler.d.ts +98 -50
  2. package/build/src/compiler/compiler.d.ts.map +1 -1
  3. package/build/src/compiler/compiler.js +405 -268
  4. package/build/src/compiler/compiler.js.map +1 -1
  5. package/build/src/compiler/messages.d.ts +230 -218
  6. package/build/src/compiler/messages.d.ts.map +1 -1
  7. package/build/src/compiler/messages.js +242 -234
  8. package/build/src/compiler/messages.js.map +1 -1
  9. package/build/src/import/kmcmplib/wasm-host.d.ts +5 -3
  10. package/build/src/import/kmcmplib/wasm-host.d.ts.map +1 -1
  11. package/build/src/import/kmcmplib/wasm-host.js +3264 -1145
  12. package/build/src/import/kmcmplib/wasm-host.js.map +1 -1
  13. package/build/src/import/kmcmplib/wasm-host.wasm +0 -0
  14. package/build/src/kmw-compiler/compiler-globals.d.ts +21 -0
  15. package/build/src/kmw-compiler/compiler-globals.d.ts.map +1 -0
  16. package/build/src/kmw-compiler/compiler-globals.js +37 -0
  17. package/build/src/kmw-compiler/compiler-globals.js.map +1 -0
  18. package/build/src/kmw-compiler/constants.d.ts +16 -0
  19. package/build/src/kmw-compiler/constants.d.ts.map +1 -0
  20. package/build/src/kmw-compiler/constants.js +62 -0
  21. package/build/src/kmw-compiler/constants.js.map +1 -0
  22. package/build/src/kmw-compiler/javascript-strings.d.ts +35 -0
  23. package/build/src/kmw-compiler/javascript-strings.d.ts.map +1 -0
  24. package/build/src/kmw-compiler/javascript-strings.js +854 -0
  25. package/build/src/kmw-compiler/javascript-strings.js.map +1 -0
  26. package/build/src/kmw-compiler/keymanweb-key-codes.d.ts +25 -0
  27. package/build/src/kmw-compiler/keymanweb-key-codes.d.ts.map +1 -0
  28. package/build/src/kmw-compiler/keymanweb-key-codes.js +806 -0
  29. package/build/src/kmw-compiler/keymanweb-key-codes.js.map +1 -0
  30. package/build/src/kmw-compiler/kmw-compiler.d.ts +16 -0
  31. package/build/src/kmw-compiler/kmw-compiler.d.ts.map +1 -0
  32. package/build/src/kmw-compiler/kmw-compiler.js +535 -0
  33. package/build/src/kmw-compiler/kmw-compiler.js.map +1 -0
  34. package/build/src/kmw-compiler/messages.d.ts +85 -0
  35. package/build/src/kmw-compiler/messages.d.ts.map +1 -0
  36. package/build/src/kmw-compiler/messages.js +48 -0
  37. package/build/src/kmw-compiler/messages.js.map +1 -0
  38. package/build/src/kmw-compiler/util.d.ts +77 -0
  39. package/build/src/kmw-compiler/util.d.ts.map +1 -0
  40. package/build/src/kmw-compiler/util.js +249 -0
  41. package/build/src/kmw-compiler/util.js.map +1 -0
  42. package/build/src/kmw-compiler/validate-layout-file.d.ts +10 -0
  43. package/build/src/kmw-compiler/validate-layout-file.d.ts.map +1 -0
  44. package/build/src/kmw-compiler/validate-layout-file.js +246 -0
  45. package/build/src/kmw-compiler/validate-layout-file.js.map +1 -0
  46. package/build/src/kmw-compiler/visual-keyboard-compiler.d.ts +5 -0
  47. package/build/src/kmw-compiler/visual-keyboard-compiler.d.ts.map +1 -0
  48. package/build/src/kmw-compiler/visual-keyboard-compiler.js +121 -0
  49. package/build/src/kmw-compiler/visual-keyboard-compiler.js.map +1 -0
  50. package/build/src/main.d.ts +6 -3
  51. package/build/src/main.d.ts.map +1 -1
  52. package/build/src/main.js +6 -3
  53. package/build/src/main.js.map +1 -1
  54. package/package.json +7 -5
@@ -0,0 +1,854 @@
1
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="3ab3909d-31cd-54df-a8bb-aaa1c023ca3f")}catch(e){}}();
2
+ import { GetSuppChar, ExpandSentinel, incxstr, xstrlen, xstrlen_printing } from "./util.js";
3
+ import { KMX } from "@keymanapp/common-types";
4
+ import { callbacks, FCallFunctions, FFix183_LadderLength, FMnemonic, FTabStop, FUnreachableKeys, IsKeyboardVersion10OrLater, IsKeyboardVersion14OrLater, kmxResult, nl, options } from "./compiler-globals.js";
5
+ import { KmwCompilerMessages } from "./messages.js";
6
+ import { FormatModifierAsBitflags, RuleIsExcludedByPlatform } from "./kmw-compiler.js";
7
+ import { KMXCodeNames, SValidIdentifierCharSet, UnreachableKeyCodes, USEnglishShift, USEnglishUnshift, USEnglishValues } from "./constants.js";
8
+ import { KMWVKeyNames, VKeyNames } from "./keymanweb-key-codes.js";
9
+ export function JavaScript_Name(i, pwszName, KeepNameForPersistentStorage = false) {
10
+ let FChanged = false;
11
+ let p = pwszName;
12
+ if ((pwszName == null || pwszName == undefined || pwszName == '') || (!options.saveDebug && !KeepNameForPersistentStorage)) { // I3659 // I3681
13
+ return i.toString(10); // for uniqueness
14
+ }
15
+ else {
16
+ let result = KeepNameForPersistentStorage // I3659
17
+ ? '' // Potential for overlap in theory but in practice we only use this for named option stores so can never overlap
18
+ : '_'; // Ensures we cannot overlap numbered instances
19
+ while (p.length) {
20
+ let ch = p.charAt(0);
21
+ if (SValidIdentifierCharSet.test(ch)) { // I3681
22
+ result += ch;
23
+ }
24
+ else {
25
+ result += '_';
26
+ FChanged = true;
27
+ }
28
+ p = p.substring(1);
29
+ }
30
+ if (!KeepNameForPersistentStorage) {
31
+ // Ensure each transformed name is still unique
32
+ result += '_' + i.toString(10);
33
+ if (FChanged) {
34
+ result += '/*' + pwszName.replace(/\*\//g, '*-/') + '*/';
35
+ }
36
+ }
37
+ else if (FChanged) {
38
+ // For named option stores, we are only supporting the valid identifier
39
+ // character set, which is a breaking change in 14.0.
40
+ callbacks.reportMessage(KmwCompilerMessages.Warn_OptionStoreNameInvalid({ name: pwszName }));
41
+ }
42
+ return result;
43
+ }
44
+ }
45
+ export function JavaScript_Store(fk, line, pwsz) {
46
+ let ch, rec, result;
47
+ const wcsentinel = String.fromCharCode(KMX.KMXFile.UC_SENTINEL);
48
+ let n = pwsz.indexOf(wcsentinel);
49
+ // Start: plain text store. Always use for < 10.0, conditionally for >= 10.0.
50
+ if (n < 0 || !IsKeyboardVersion10OrLater()) {
51
+ result = '"';
52
+ while (pwsz.length) {
53
+ if (pwsz.charCodeAt(0) == KMX.KMXFile.UC_SENTINEL) {
54
+ result += '.'; // UC_SENTINEL values are not supported in stores for KMW < 10.0.
55
+ }
56
+ else {
57
+ ch = GetSuppChar(pwsz, 0);
58
+ if (ch == '"'.charCodeAt(0) || ch == '\\'.charCodeAt(0)) {
59
+ result += '\\';
60
+ }
61
+ result += JavaScript_String(ch); // I2242
62
+ }
63
+ const x = incxstr(pwsz, 0);
64
+ pwsz = pwsz.substring(x);
65
+ }
66
+ result += '"';
67
+ }
68
+ else {
69
+ result = '[';
70
+ let x = 0;
71
+ while (x < pwsz.length) {
72
+ if (result != '[') {
73
+ result += ',';
74
+ }
75
+ rec = ExpandSentinel(fk, pwsz, x);
76
+ if (rec.IsSentinel) {
77
+ if (rec.Code == KMX.KMXFile.CODE_DEADKEY) {
78
+ result += `{t:'d',d:${rec.DeadKey.DeadKey}}`;
79
+ }
80
+ else if (rec.Code == KMX.KMXFile.CODE_BEEP) {
81
+ result += `{t:'b'}`;
82
+ }
83
+ else { //if rec.Code = CODE_EXTENDED then
84
+ // At some point, we may wish to filter which codes are safe to stub out like this
85
+ // versus which ones should be an error. The commented-out-code shows the way to
86
+ // handle such cases.
87
+ result += `''`;
88
+ }
89
+ // else
90
+ // begin
91
+ // //ReportError(line, CERR_SomewhereIGotItWrong, 'Internal Error: unexpected sentinel character in store definition');
92
+ // end;
93
+ }
94
+ else {
95
+ ch = GetSuppChar(pwsz, x);
96
+ result += '"';
97
+ // TODO: Refactor the section below into JavaScript_String, as it's
98
+ // quite common in our code base.
99
+ if (ch == '"'.charCodeAt(0) || ch == '\\'.charCodeAt(0)) {
100
+ result += '\\';
101
+ }
102
+ result += JavaScript_String(ch) + '"'; // I2242
103
+ }
104
+ x = incxstr(pwsz, x);
105
+ }
106
+ result += ']';
107
+ }
108
+ return result;
109
+ }
110
+ export function JavaScript_String(ch) {
111
+ if (ch < 32) {
112
+ switch (ch) {
113
+ case 9: return '\\t';
114
+ case 10: return '\\n';
115
+ case 13: return '\\r';
116
+ }
117
+ return '\\x' + zeroPadHex(ch, 2);
118
+ }
119
+ else {
120
+ // Note: unpaired surrogates will be maintained
121
+ return String.fromCodePoint(ch);
122
+ }
123
+ }
124
+ function JavaScript_Rule(FTabStops, FElse, fk, fgp, fkp) {
125
+ let predicate = '1', linecomment = '', FIndent;
126
+ let result = '';
127
+ if (fkp.Line > 0 && options.saveDebug) { // I4384
128
+ linecomment = ' // Line ' + fkp.Line.toString(); // I4373
129
+ }
130
+ if (xstrlen(fkp.dpContext) > 0) {
131
+ predicate = JavaScript_ContextMatch(fk, fkp, fkp.dpContext);
132
+ }
133
+ FIndent = FTabStops + FTabStop;
134
+ result = `${FTabStops}${FElse}if(${predicate}){${nl}`;
135
+ if (fgp.fUsingKeys) {
136
+ result += `${FIndent}r=m=1;${linecomment}${JavaScript_OutputString(fk, FIndent, fkp, fkp.dpOutput, fgp)}`; // I1959 // I3681
137
+ }
138
+ else {
139
+ result += `${FIndent}m=1;${linecomment}${JavaScript_OutputString(fk, FIndent, fkp, fkp.dpOutput, fgp)}`; // I1959 // I3681
140
+ }
141
+ result += `${nl}${FTabStops}}${nl}`;
142
+ return result;
143
+ }
144
+ export function JavaScript_Rules(keyboard, fMnemonic, fgp) {
145
+ let IsEqualKey = function (k1, k2) {
146
+ return ((JavaScript_Key(k1, FMnemonic) == JavaScript_Key(k2, FMnemonic)) &&
147
+ (JavaScript_Shift(k1, FMnemonic) == JavaScript_Shift(k2, FMnemonic)));
148
+ };
149
+ let result = '';
150
+ let HasRules = false;
151
+ let processed_rule = Array(fgp.keys.length);
152
+ for (let j = 0; j < fgp.keys.length; j++) {
153
+ processed_rule[j] = false;
154
+ }
155
+ let j = 0;
156
+ let Counter = 0;
157
+ while (j < fgp.keys.length) { // I1964
158
+ let fkp = fgp.keys[j];
159
+ if (!processed_rule[j] && !RuleIsExcludedByPlatform(keyboard, fkp)) {
160
+ // Break down by key code
161
+ // We know the rules are sorted by context length and then key code.
162
+ // First pass, break the grouping down by key code.
163
+ if (fgp.fUsingKeys) {
164
+ result +=
165
+ `${FTabStop + FTabStop}${HasRules ? 'else ' : ''}` +
166
+ `if(k.KKM(e,${JavaScript_ShiftAsString(fkp, fMnemonic)},${JavaScript_KeyAsString(fkp, fMnemonic)})) {${nl}`;
167
+ HasRules = true;
168
+ Counter++;
169
+ let LocalHasRules = false;
170
+ let fkp2 = fgp.keys[j];
171
+ let j2 = j;
172
+ let LocalCounter = 0;
173
+ while (j < fgp.keys.length) {
174
+ fkp = fgp.keys[j];
175
+ if (!processed_rule[j] && !RuleIsExcludedByPlatform(keyboard, fkp) && IsEqualKey(fkp, fkp2)) {
176
+ processed_rule[j] = true;
177
+ result += JavaScript_Rule(FTabStop + FTabStop + FTabStop, LocalHasRules ? 'else ' : '', keyboard, fgp, fkp);
178
+ LocalCounter++;
179
+ if (FFix183_LadderLength != 0 && (LocalCounter % FFix183_LadderLength) == 0) {
180
+ // Break if/else ladders
181
+ result += `${FTabStop + FTabStop + FTabStop}if(m) {}${nl}`;
182
+ }
183
+ LocalHasRules = true;
184
+ }
185
+ j++;
186
+ }
187
+ result += FTabStop + FTabStop + '}' + nl;
188
+ j = j2 + 1;
189
+ }
190
+ else {
191
+ // TODO: context character level switches instead of full context comparisons
192
+ result += JavaScript_Rule(FTabStop + FTabStop + FTabStop, HasRules ? 'else ' : '', keyboard, fgp, fkp);
193
+ HasRules = true;
194
+ Counter++;
195
+ j++;
196
+ }
197
+ if (FFix183_LadderLength != 0 && (Counter % FFix183_LadderLength) == 0) {
198
+ // Break if/else ladders
199
+ // We need to only match if no previous line is matched (i.e. m is false)
200
+ result += `${FTabStop + FTabStop + FTabStop}if(m) {}${nl}`;
201
+ }
202
+ }
203
+ else {
204
+ j++;
205
+ }
206
+ }
207
+ return result;
208
+ }
209
+ export function JavaScript_Shift(fkp, FMnemonic) {
210
+ if (FMnemonic) {
211
+ if (fkp.ShiftFlags & KMX.KMXFile.VIRTUALCHARKEY) {
212
+ callbacks.reportMessage(KmwCompilerMessages.Error_VirtualCharacterKeysNotSupportedInKeymanWeb());
213
+ return 0;
214
+ }
215
+ if (fkp.ShiftFlags & KMX.KMXFile.ISVIRTUALKEY && fkp.Key <= 255) {
216
+ // We prohibit K_ keys for mnemonic layouts. We don't block T_ and U_ keys.
217
+ // TODO: this doesn't resolve the issue of, e.g. SHIFT+K_SPACE
218
+ // https://github.com/keymanapp/keyman/issues/265
219
+ callbacks.reportMessage(KmwCompilerMessages.Error_VirtualKeysNotValidForMnemonicLayouts());
220
+ return 0;
221
+ }
222
+ }
223
+ if (fkp.ShiftFlags & KMX.KMXFile.ISVIRTUALKEY) {
224
+ if (IsKeyboardVersion10OrLater()) {
225
+ // Full chiral modifier and state key support starts with KeymanWeb 10.0
226
+ return fkp.ShiftFlags;
227
+ }
228
+ // Non-chiral support only and no support for state keys
229
+ if (fkp.ShiftFlags & (KMX.KMXFile.LCTRLFLAG | KMX.KMXFile.RCTRLFLAG | KMX.KMXFile.LALTFLAG | KMX.KMXFile.RALTFLAG)) { // I4118
230
+ callbacks.reportMessage(KmwCompilerMessages.Warn_ExtendedShiftFlagsNotSupportedInKeymanWeb({ flags: 'LALT, RALT, LCTRL, RCTRL' }));
231
+ }
232
+ if (fkp.ShiftFlags & (KMX.KMXFile.CAPITALFLAG | KMX.KMXFile.NOTCAPITALFLAG | KMX.KMXFile.NUMLOCKFLAG | KMX.KMXFile.NOTNUMLOCKFLAG |
233
+ KMX.KMXFile.SCROLLFLAG | KMX.KMXFile.NOTSCROLLFLAG)) { // I4118
234
+ callbacks.reportMessage(KmwCompilerMessages.Warn_ExtendedShiftFlagsNotSupportedInKeymanWeb({ flags: 'CAPS and NCAPS' }));
235
+ }
236
+ return KMX.KMXFile.ISVIRTUALKEY | (fkp.ShiftFlags & (KMX.KMXFile.K_SHIFTFLAG | KMX.KMXFile.K_CTRLFLAG | KMX.KMXFile.K_ALTFLAG));
237
+ }
238
+ return USEnglishShift.includes(String.fromCharCode(fkp.Key)) ? KMX.KMXFile.ISVIRTUALKEY | KMX.KMXFile.K_SHIFTFLAG : KMX.KMXFile.ISVIRTUALKEY;
239
+ }
240
+ /**
241
+ * Returns a Javascript representation of a key modifier state, either as a constant (debug mode)
242
+ * or as an integer.
243
+ *
244
+ * @param fkp Pointer to key record
245
+ * @param FMnemonic True if the keyboard is a mnemonic layout
246
+ *
247
+ * @return string representation of the key modifier state, e.g.
248
+ * 'modCodes.SHIFT | modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4110 * /' or
249
+ * '16656'
250
+ */
251
+ export function JavaScript_ShiftAsString(fkp, FMnemonic) {
252
+ if (!options.saveDebug) {
253
+ return JavaScript_Shift(fkp, FMnemonic).toString();
254
+ }
255
+ return ' ' + FormatModifierAsBitflags(JavaScript_Shift(fkp, FMnemonic));
256
+ }
257
+ function FormatKeyForErrorMessage(fkp, FMnemonic) {
258
+ function FormatShift(ShiftFlags) {
259
+ const mask = [
260
+ 'LCTRL',
261
+ 'RCTRL',
262
+ 'LALT',
263
+ 'RALT',
264
+ 'SHIFT',
265
+ 'CTRL',
266
+ 'ALT',
267
+ '???',
268
+ 'CAPS',
269
+ 'NCAPS',
270
+ 'NUMLOCK',
271
+ 'NNUMLOCK',
272
+ 'SCROLLLOCK',
273
+ 'NSCROLLLOCK' // 0X2000
274
+ ];
275
+ let result = '';
276
+ for (let i = 0; i < mask.length; i++) {
277
+ if (ShiftFlags & (1 << i)) {
278
+ result += mask[i] + ' ';
279
+ }
280
+ }
281
+ return result;
282
+ }
283
+ let result;
284
+ if (!FMnemonic) {
285
+ if (fkp.ShiftFlags & KMX.KMXFile.ISVIRTUALKEY) {
286
+ if (fkp.Key < 256) {
287
+ result = `[${FormatShift(fkp.ShiftFlags)}${VKeyNames[fkp.Key]}]`;
288
+ }
289
+ else {
290
+ result = `[${FormatShift(fkp.ShiftFlags)}K_${fkp.Key.toString(16).toUpperCase()}]`;
291
+ }
292
+ }
293
+ else {
294
+ result = `'${String.fromCharCode(fkp.Key)}'`;
295
+ }
296
+ }
297
+ else {
298
+ if (fkp.ShiftFlags & KMX.KMXFile.VIRTUALCHARKEY) {
299
+ result = `[${FormatShift(fkp.ShiftFlags)}'${String.fromCharCode(fkp.Key)}']`;
300
+ }
301
+ else {
302
+ result = `'${String.fromCharCode(fkp.Key)}'`;
303
+ }
304
+ }
305
+ return result;
306
+ }
307
+ export function JavaScript_Key(fkp, FMnemonic) {
308
+ let Result;
309
+ if (!FMnemonic) {
310
+ if (fkp.ShiftFlags & KMX.KMXFile.ISVIRTUALKEY) {
311
+ Result = fkp.Key;
312
+ }
313
+ else {
314
+ // Convert the character to a virtual key
315
+ let n = USEnglishShift.indexOf(String.fromCharCode(fkp.Key));
316
+ if (n < 0) {
317
+ n = USEnglishUnshift.indexOf(String.fromCharCode(fkp.Key));
318
+ }
319
+ if (n < 0) {
320
+ Result = 0;
321
+ }
322
+ else {
323
+ Result = USEnglishValues.charCodeAt(n);
324
+ }
325
+ }
326
+ }
327
+ else {
328
+ Result = fkp.Key;
329
+ }
330
+ // Check that key is not unreachable (e.g. K_SHIFT, touch-specific special keys 50,000+)
331
+ if (UnreachableKeyCodes.indexOf(Result) >= 0) {
332
+ Result = 0;
333
+ }
334
+ if (Result == 0 || Result >= 50001 /* TKeymanWebTouchStandardKey.K_LOPT */) { // I4141
335
+ if (!FUnreachableKeys.includes(fkp)) {
336
+ callbacks.reportMessage(KmwCompilerMessages.Hint_UnreachableKeyCode({ key: FormatKeyForErrorMessage(fkp, FMnemonic) }));
337
+ FUnreachableKeys.push(fkp);
338
+ }
339
+ }
340
+ return Result;
341
+ }
342
+ /**
343
+ * Returns a Javascript representation of a key value, either as a constant (debug mode)
344
+ * or as an integer.
345
+ *
346
+ * @param fkp Pointer to key record
347
+ * @param FMnemonic True if the keyboard is a mnemonic layout
348
+ *
349
+ * @return string representation of the key value, e.g. 'keyCodes.K_A /* 0x41 * /' or '65'
350
+ */
351
+ export function JavaScript_KeyAsString(fkp, FMnemonic) {
352
+ if (options.saveDebug) {
353
+ return ' ' + FormatKeyAsString(JavaScript_Key(fkp, FMnemonic));
354
+ }
355
+ else {
356
+ return JavaScript_Key(fkp, FMnemonic).toString();
357
+ }
358
+ }
359
+ export function JavaScript_ContextMatch(fk, fkp, context) {
360
+ if (IsKeyboardVersion10OrLater()) {
361
+ return JavaScript_FullContextValue(fk, fkp, context);
362
+ }
363
+ else {
364
+ return JavaScript_CompositeContextValue(fk, fkp, context);
365
+ }
366
+ }
367
+ function JavaScript_ContextLength(Context) {
368
+ return xstrlen_printing(Context);
369
+ }
370
+ function GetCodeName(code) {
371
+ if (code >= 0 && code < KMXCodeNames.length && KMXCodeNames[code] != '') {
372
+ return KMXCodeNames[code];
373
+ }
374
+ return code.toString();
375
+ }
376
+ function CheckStoreForInvalidFunctions(fk, key, store) {
377
+ let n, rec;
378
+ const wcsentinel = String.fromCharCode(0xFFFF);
379
+ n = store.dpString.indexOf(wcsentinel);
380
+ // Disable the check with versions >= 10.0, since we now support deadkeys in stores.
381
+ if (n >= 0 && !IsKeyboardVersion10OrLater) {
382
+ rec = ExpandSentinel(fk, store.dpString, n);
383
+ callbacks.reportMessage(KmwCompilerMessages.Error_NotSupportedInKeymanWebStore({ code: GetCodeName(rec.Code), store: store.dpName }));
384
+ }
385
+ }
386
+ // Used when targeting versions prior to 10.0, before the introduction of FullContextMatch/KFCM.
387
+ function JavaScript_CompositeContextValue(fk, fkp, pwsz) {
388
+ let Result = '';
389
+ let InQuotes = false;
390
+ let Len = JavaScript_ContextLength(pwsz);
391
+ let StartQuotes = -1;
392
+ let x = 0, Cur = 0;
393
+ while (x < pwsz.length) {
394
+ let rec = ExpandSentinel(fk, pwsz, x);
395
+ if (rec.IsSentinel) {
396
+ if (InQuotes) {
397
+ Result += `",${Cur - StartQuotes})`;
398
+ InQuotes = false;
399
+ }
400
+ if (Result != '') {
401
+ Result += '&&';
402
+ }
403
+ switch (rec.Code) {
404
+ case KMX.KMXFile.CODE_ANY:
405
+ CheckStoreForInvalidFunctions(fk, fkp, rec.Any.Store); // I1520
406
+ Result += `k.KA(${Cur},k.KC(${Len - Cur},1,t),this.s${JavaScript_Name(rec.Any.StoreIndex, rec.Any.Store.dpName)})`;
407
+ break;
408
+ case KMX.KMXFile.CODE_DEADKEY:
409
+ Result += `k.KDM(${Len - Cur},t,${rec.DeadKey.DeadKey})`;
410
+ Cur--; // don't increment on deadkeys -- correlates with AdjustIndex function // I3910
411
+ break;
412
+ case KMX.KMXFile.CODE_NUL: // I2243
413
+ Result += `k.KN(${Len - Cur},t)`;
414
+ Cur--; // don't increment on nul -- correlates with AdjustIndex function // I3910
415
+ break;
416
+ case KMX.KMXFile.CODE_IFOPT: // I3429
417
+ Result += `this.s${JavaScript_Name(rec.IfOpt.StoreIndex1, rec.IfOpt.Store1.dpName)}` +
418
+ `${rec.IfOpt.IsNot == 0 ? '!==' : '==='}` +
419
+ `this.s${JavaScript_Name(rec.IfOpt.StoreIndex2, rec.IfOpt.Store2.dpName)}`; // I3429 // I3659 // I3681
420
+ Cur--; // don't increment on ifopt -- correlates with AdjustIndex function // I3910
421
+ break;
422
+ case KMX.KMXFile.CODE_IFSYSTEMSTORE: // I3430
423
+ Result += `${rec.IfSystemStore.IsNot == 0 ? '!' : ''}` +
424
+ `k.KIFS(${rec.IfSystemStore.dwSystemID},` +
425
+ `this.s${JavaScript_Name(rec.IfSystemStore.StoreIndex, rec.IfSystemStore.Store.dpName)},t)`;
426
+ Cur--; // don't increment on ifsystemstore -- correlates with AdjustIndex function // I3910
427
+ break;
428
+ case KMX.KMXFile.CODE_CONTEXTEX: // I3980
429
+ Result += `k.KCCM(${Len - Cur},${Len - rec.ContextEx.Index + 1},t)`;
430
+ break;
431
+ case KMX.KMXFile.CODE_NOTANY: // I3981
432
+ CheckStoreForInvalidFunctions(fk, fkp, rec.Any.Store); // I1520
433
+ Result += `k.KC(${Len - Cur},1,t)!=""&&!k.KA(${Cur},k.KC(${Len - Cur},1,t),` +
434
+ `this.s${JavaScript_Name(rec.Any.StoreIndex, rec.Any.Store.dpName)})`;
435
+ break;
436
+ default:
437
+ callbacks.reportMessage(KmwCompilerMessages.Error_NotSupportedInKeymanWebContext({ code: GetCodeName(rec.Code) }));
438
+ Result += '/*.*/ 0 ';
439
+ }
440
+ }
441
+ else {
442
+ if (!InQuotes) {
443
+ if (Result != '') {
444
+ Result += '&&';
445
+ }
446
+ Result += `k.KCM(${Len - Cur},t,"`;
447
+ StartQuotes = Cur;
448
+ InQuotes = true;
449
+ }
450
+ if (rec.ChrVal == '"'.charCodeAt(0) || rec.ChrVal == '\\'.charCodeAt(0)) {
451
+ Result += '\\';
452
+ }
453
+ Result += JavaScript_String(rec.ChrVal); // I2242
454
+ }
455
+ Cur++;
456
+ x = incxstr(pwsz, x);
457
+ }
458
+ if (InQuotes) {
459
+ Result += `",${Cur - StartQuotes})`;
460
+ }
461
+ return Result;
462
+ }
463
+ // Used when targeting versions >= 10.0, after the introduction of FullContextMatch/KFCM.
464
+ function JavaScript_FullContextValue(fk, fkp, pwsz) {
465
+ let Result = '';
466
+ let FullContext = '';
467
+ let Suffix = '';
468
+ let Len = xstrlen(pwsz);
469
+ let x = 0;
470
+ while (x < pwsz.length) {
471
+ if (FullContext != '') {
472
+ FullContext += ',';
473
+ }
474
+ let rec = ExpandSentinel(fk, pwsz, x);
475
+ if (rec.IsSentinel) {
476
+ switch (rec.Code) {
477
+ case KMX.KMXFile.CODE_ANY:
478
+ CheckStoreForInvalidFunctions(fk, fkp, rec.Any.Store); // I1520
479
+ FullContext += `{t:'a',a:this.s${JavaScript_Name(rec.Any.StoreIndex, rec.Any.Store.dpName)}}`;
480
+ break;
481
+ case KMX.KMXFile.CODE_DEADKEY:
482
+ FullContext += `{t:'d',d:${rec.DeadKey.DeadKey}}`;
483
+ break;
484
+ case KMX.KMXFile.CODE_NUL: // I2243
485
+ FullContext += `{t:'n'}`;
486
+ break;
487
+ case KMX.KMXFile.CODE_IFOPT: // I3429
488
+ Len--;
489
+ if (Suffix != '') {
490
+ Suffix += '&&';
491
+ }
492
+ if (FullContext == ',') {
493
+ FullContext = '';
494
+ }
495
+ Suffix += `this.s${JavaScript_Name(rec.IfOpt.StoreIndex1, rec.IfOpt.Store1.dpName)}` +
496
+ `${rec.IfOpt.IsNot == 0 ? '!==' : '==='}this.s${JavaScript_Name(rec.IfOpt.StoreIndex2, rec.IfOpt.Store2.dpName)}`; // I3429 // I3659 // I3681
497
+ break;
498
+ case KMX.KMXFile.CODE_IFSYSTEMSTORE: // I3430
499
+ Len--;
500
+ if (Suffix != '') {
501
+ Suffix += '&&';
502
+ }
503
+ if (FullContext == ',') {
504
+ FullContext = '';
505
+ }
506
+ Suffix += `${rec.IfSystemStore.IsNot == 0 ? '!' : ''}k.KIFS(${rec.IfSystemStore.dwSystemID},` +
507
+ `this.s${JavaScript_Name(rec.IfSystemStore.StoreIndex, rec.IfSystemStore.Store.dpName)},t)`; // I3430 // I3659 // I3681
508
+ break;
509
+ case KMX.KMXFile.CODE_NOTANY: // I3981
510
+ CheckStoreForInvalidFunctions(fk, fkp, rec.Any.Store); // I1520
511
+ FullContext += `{t:'a',a:this.s${JavaScript_Name(rec.Any.StoreIndex, rec.Any.Store.dpName)},n:1}`;
512
+ break;
513
+ case KMX.KMXFile.CODE_CONTEXTEX:
514
+ FullContext += `{t:'c',c:${rec.ContextEx.Index}}`; // I4611
515
+ break;
516
+ case KMX.KMXFile.CODE_INDEX:
517
+ FullContext += `{t:'i',i:this.s${JavaScript_Name(rec.Index.StoreIndex, rec.Index.Store.dpName)},` +
518
+ `o:${rec.Index.Index}}`; // I4611
519
+ break;
520
+ default:
521
+ callbacks.reportMessage(KmwCompilerMessages.Error_NotSupportedInKeymanWebContext({ code: GetCodeName(rec.Code) }));
522
+ Result += '/*.*/ 0 ';
523
+ }
524
+ }
525
+ else { // Simple context character.
526
+ FullContext += `'`;
527
+ if (rec.ChrVal == '"'.charCodeAt(0) || rec.ChrVal == '\\'.charCodeAt(0) || rec.ChrVal == '\''.charCodeAt(0)) {
528
+ FullContext += '\\';
529
+ }
530
+ FullContext += JavaScript_String(rec.ChrVal) + `'`; // I2242
531
+ }
532
+ x = incxstr(pwsz, x);
533
+ }
534
+ if (FullContext != '') {
535
+ Result = `k.KFCM(${Len},t,[${FullContext}])`;
536
+ }
537
+ if (Result != '' && Suffix != '') {
538
+ Result += '&&' + Suffix;
539
+ }
540
+ else if (Suffix != '') {
541
+ Result = Suffix;
542
+ }
543
+ return Result;
544
+ }
545
+ function isGroupReadOnly(fk, fgp) {
546
+ const index = fk.groups.indexOf(fgp);
547
+ return kmxResult.extra.groups[index].isReadOnly;
548
+ }
549
+ function CallFunctionName(s) {
550
+ let n;
551
+ n = s.indexOf(':');
552
+ return s.substring(n + 1); // not found gives -1, substring(0) is ok :grin:
553
+ }
554
+ export function JavaScript_OutputString(fk, FTabStops, fkp, pwszOutput, fgp) {
555
+ let InQuotes = false;
556
+ let len = 0;
557
+ const nlt = nl + FTabStops; // I3681
558
+ const AdjustIndex = function (pwszContext, Index) {
559
+ let Result = Index;
560
+ let x = 0;
561
+ for (let I = 1; I < Index; I++) {
562
+ let recContext = ExpandSentinel(fk, pwszContext, x);
563
+ if (IsKeyboardVersion10OrLater()) {
564
+ if (recContext.IsSentinel && [KMX.KMXFile.CODE_NUL, KMX.KMXFile.CODE_IFOPT, KMX.KMXFile.CODE_IFSYSTEMSTORE].includes(recContext.Code)) {
565
+ Result--;
566
+ }
567
+ }
568
+ else {
569
+ if (recContext.IsSentinel && [KMX.KMXFile.CODE_DEADKEY, KMX.KMXFile.CODE_NUL, KMX.KMXFile.CODE_IFOPT, KMX.KMXFile.CODE_IFSYSTEMSTORE].includes(recContext.Code)) {
570
+ Result--;
571
+ }
572
+ }
573
+ x = incxstr(pwszContext, x);
574
+ }
575
+ return Result;
576
+ };
577
+ const ContextChar = function (ContextIndex, pwszContext, xContext) {
578
+ let Index;
579
+ let Result = '';
580
+ let recContext = ExpandSentinel(fk, pwszContext, xContext);
581
+ if (recContext.IsSentinel) {
582
+ if (InQuotes) { // I4611
583
+ Result += '");';
584
+ InQuotes = false;
585
+ }
586
+ switch (recContext.Code) {
587
+ case KMX.KMXFile.CODE_ANY:
588
+ Index = AdjustIndex(fkp.dpContext, ContextIndex) + 1; // I3910 // I4611
589
+ Result += nlt + `k.KIO(${len},this.s${JavaScript_Name(recContext.Any.StoreIndex, recContext.Any.Store.dpName)},${Index},t);`; // I4611
590
+ break;
591
+ case KMX.KMXFile.CODE_DEADKEY:
592
+ Result += nlt + `k.KDO(${len},t,${recContext.DeadKey.DeadKey});`; // I4611
593
+ break;
594
+ case KMX.KMXFile.CODE_NOTANY:
595
+ // #917: Minimum version required is 14.0: the KCXO function was only added for 14.0
596
+ // Note that this is checked in compiler.cpp as well, so this error can probably never occur
597
+ if (!IsKeyboardVersion14OrLater()) {
598
+ callbacks.reportMessage(KmwCompilerMessages.Error_NotAnyRequiresVersion14());
599
+ }
600
+ Result += nlt + `k.KCXO(${len},t,${AdjustIndex(fkp.dpContext, xstrlen(fkp.dpContext))},${AdjustIndex(fkp.dpContext, ContextIndex) + 1});`;
601
+ break;
602
+ case KMX.KMXFile.CODE_IFOPT:
603
+ case KMX.KMXFile.CODE_IFSYSTEMSTORE:
604
+ case KMX.KMXFile.CODE_NUL:
605
+ // These have no output for a context emit
606
+ break;
607
+ default:
608
+ callbacks.reportMessage(KmwCompilerMessages.Error_NotSupportedInKeymanWebContext({ code: GetCodeName(recContext.Code) }));
609
+ Result += nlt + '/*.*/ '; // I4611
610
+ }
611
+ }
612
+ else {
613
+ if (!InQuotes) {
614
+ Result += nlt + `k.KO(${len},t,"`; // I4611
615
+ InQuotes = true;
616
+ }
617
+ if (recContext.ChrVal == '"'.charCodeAt(0) || recContext.ChrVal == '\\'.charCodeAt(0)) {
618
+ Result += '\\';
619
+ }
620
+ Result += JavaScript_String(recContext.ChrVal); // I2242
621
+ }
622
+ return Result;
623
+ };
624
+ let Result = '';
625
+ InQuotes = false;
626
+ let pwsz = pwszOutput;
627
+ if (fkp != null) {
628
+ if (IsKeyboardVersion10OrLater()) {
629
+ // KMW >= 10.0 use the full, sentinel-based length for context deletions.
630
+ len = xstrlen(fkp.dpContext);
631
+ let n = len;
632
+ let x = 0;
633
+ for (let i = 0; i < n; i++) {
634
+ let rec = ExpandSentinel(fk, fkp.dpContext, x);
635
+ if (rec.IsSentinel && [KMX.KMXFile.CODE_NUL, KMX.KMXFile.CODE_IFOPT, KMX.KMXFile.CODE_IFSYSTEMSTORE].includes(rec.Code)) {
636
+ len--;
637
+ }
638
+ x = incxstr(fkp.dpContext, x);
639
+ }
640
+ }
641
+ else {
642
+ // KMW < 10.0 exclude all sentinel-based characters, including deadkeys, from direct context deletion.
643
+ // Deadkeys have alternative special handling.
644
+ len = xstrlen_printing(fkp.dpContext);
645
+ }
646
+ }
647
+ else {
648
+ len = -1;
649
+ }
650
+ let x = 0;
651
+ if (IsKeyboardVersion10OrLater() && pwsz.length > 0) {
652
+ if (!isGroupReadOnly(fk, fgp)) {
653
+ Result += nlt + `k.KDC(${len},t);`; // I3681
654
+ }
655
+ len = -1;
656
+ }
657
+ while (x < pwsz.length) {
658
+ let rec = ExpandSentinel(fk, pwsz, x);
659
+ if (rec.IsSentinel) {
660
+ if (InQuotes) {
661
+ if (!isGroupReadOnly(fk, fgp)) {
662
+ Result += '");';
663
+ }
664
+ InQuotes = false;
665
+ }
666
+ switch (rec.Code) {
667
+ case KMX.KMXFile.CODE_CONTEXT:
668
+ if (x > 0 || len == -1) {
669
+ let xContext = 0;
670
+ let n = 0;
671
+ while (xContext < fkp.dpContext.length) { // I4611
672
+ if (!isGroupReadOnly(fk, fgp)) {
673
+ Result += ContextChar(n, fkp.dpContext, xContext);
674
+ }
675
+ n++;
676
+ xContext = incxstr(fkp.dpContext, xContext);
677
+ }
678
+ //Result := Result + Format('k.KO(%d,t,k.KC(%d,%d,t));', [len, xstrlen_printing(fkp.dpContext), xstrlen_printing(fkp.dpContext)]);
679
+ }
680
+ // else, we don't need to output anything - just don't delete the context
681
+ len = -1;
682
+ break;
683
+ case KMX.KMXFile.CODE_CONTEXTEX:
684
+ let xContext = 0;
685
+ for (let i = 0; i < rec.ContextEx.Index; i++) {
686
+ xContext = incxstr(fkp.dpContext, xContext);
687
+ }
688
+ if (!isGroupReadOnly(fk, fgp)) {
689
+ Result += ContextChar(rec.ContextEx.Index, fkp.dpContext, xContext); // I4611
690
+ }
691
+ len = -1;
692
+ break;
693
+ case KMX.KMXFile.CODE_BEEP:
694
+ if (!isGroupReadOnly(fk, fgp)) {
695
+ if (len > 0) {
696
+ Result += nlt + `k.KO(${len},t,"");`; // I3681
697
+ }
698
+ Result += nlt + 'k.KB(t);'; // I3681
699
+ }
700
+ len = -1;
701
+ break;
702
+ case KMX.KMXFile.CODE_NUL:
703
+ if (!isGroupReadOnly(fk, fgp)) {
704
+ if (len > 0) {
705
+ Result += nlt + `k.KO(${len},t,"");`; // I3681
706
+ }
707
+ }
708
+ len = -1;
709
+ break;
710
+ case KMX.KMXFile.CODE_INDEX:
711
+ CheckStoreForInvalidFunctions(fk, fkp, rec.Index.Store); // I1520
712
+ // This code was wrong. We need to ignore CODE_NUL, CODE_DEADKEY in LHS context index counter.
713
+ // This is why the compiler goes wrong -- and why the previous fix was inconsistent.
714
+ // The I783 test did not test either of these cases. It seems some of the keyboards were
715
+ // compiled in-between the original fix and I783 re-fix, and then happened to work due to
716
+ // their simplicity.
717
+ let Index = AdjustIndex(fkp.dpContext, rec.Index.Index); // I3910
718
+ if (!isGroupReadOnly(fk, fgp)) {
719
+ Result += nlt + `k.KIO(${len},this.s${JavaScript_Name(rec.Index.StoreIndex, rec.Index.Store.dpName)},${Index},t);`;
720
+ // I783 - was: rec.Index.Index [2007-06-04]
721
+ // I783 again. Returned to rec.Index.Index. Was previously: [2008-08-15]
722
+ // xstrlen(fkp.dpContext) + 1 - rec.Index.Index]);
723
+ // this was wrong. Can't find any reason why this change was made
724
+ // which suggests it was in response to another bug and poorly traced (bad Marc)
725
+ // and not properly tested (bad, bad Marc). Anyway, now tested with test_i783
726
+ }
727
+ len = -1;
728
+ break;
729
+ case KMX.KMXFile.CODE_DEADKEY:
730
+ if (!isGroupReadOnly(fk, fgp)) {
731
+ Result += nlt + `k.KDO(${len},t,${rec.DeadKey.DeadKey});`; // I3681
732
+ }
733
+ len = -1;
734
+ break;
735
+ case KMX.KMXFile.CODE_USE:
736
+ if (!isGroupReadOnly(fk, fgp)) {
737
+ if (len > 0) {
738
+ Result += nlt + `k.KO(${len},t,"");`; // I3681
739
+ }
740
+ }
741
+ Result += nlt + `r=this.g${JavaScript_Name(rec.Use.GroupIndex, rec.Use.Group.dpName)}(t,e);`; // I1959 // I3681
742
+ Result += nlt + 'm=2;'; // #5440 - match desktop behavior
743
+ len = -1;
744
+ break;
745
+ case KMX.KMXFile.CODE_CALL:
746
+ if (!isGroupReadOnly(fk, fgp)) {
747
+ if (len > 0) {
748
+ Result += nlt + `k.KO(${len},t,"");`; // I3681
749
+ }
750
+ }
751
+ let n = FCallFunctions.indexOf(CallFunctionName(rec.Call.Store.dpString));
752
+ if (n == -1) {
753
+ n = FCallFunctions.push(CallFunctionName(rec.Call.Store.dpString)) - 1;
754
+ }
755
+ Result += nlt + `r=this.c${n}(t,e);`; // I1959 // I3681
756
+ Result += nlt + 'm=2;'; // #5440 - match desktop behavior
757
+ len = -1;
758
+ break;
759
+ case KMX.KMXFile.CODE_SETOPT: // I3429
760
+ if (!isGroupReadOnly(fk, fgp)) {
761
+ if (len > 0) {
762
+ Result += nlt + `k.KO(${len},t,"");`; // I3681
763
+ }
764
+ }
765
+ Result += nlt + `this.s${JavaScript_Name(rec.SetOpt.StoreIndex1, rec.SetOpt.Store1.dpName)}=` +
766
+ `this.s${JavaScript_Name(rec.SetOpt.StoreIndex2, rec.SetOpt.Store2.dpName)};`;
767
+ len = -1;
768
+ break;
769
+ case KMX.KMXFile.CODE_RESETOPT: // I3429
770
+ if (!isGroupReadOnly(fk, fgp)) {
771
+ if (len > 0) {
772
+ Result += nlt + `k.KO(${len},t,"");`; // I3681
773
+ }
774
+ }
775
+ Result += nlt + `this.s${JavaScript_Name(rec.ResetOpt.StoreIndex, rec.ResetOpt.Store.dpName)}=` +
776
+ `k.KLOAD(this.KI,"${JavaScript_Name(rec.ResetOpt.StoreIndex, rec.ResetOpt.Store.dpName, true)}",` +
777
+ `${JavaScript_Store(fk, fkp.Line, rec.ResetOpt.Store.dpString)});`; // I3429 // I3681 // I3659
778
+ len = -1;
779
+ break;
780
+ case KMX.KMXFile.CODE_SAVEOPT: // I3429
781
+ if (!isGroupReadOnly(fk, fgp)) {
782
+ if (len > 0) {
783
+ Result += nlt + `k.KO(${len},t,"");`; // I3681
784
+ }
785
+ }
786
+ Result += nlt + `k.KSAVE("${JavaScript_Name(rec.SaveOpt.StoreIndex, rec.SaveOpt.Store.dpName, true)}",` +
787
+ `this.s${JavaScript_Name(rec.SaveOpt.StoreIndex, rec.SaveOpt.Store.dpName)});`; // I3690 // I3429 // I3659 // I3681
788
+ len = -1;
789
+ break;
790
+ case KMX.KMXFile.CODE_SETSYSTEMSTORE: // I3437
791
+ if (!isGroupReadOnly(fk, fgp)) {
792
+ if (len > 0) {
793
+ Result += nlt + `k.KO(${len},t,"");`; // I3681
794
+ }
795
+ }
796
+ Result += nlt + `k.KSETS(${rec.SetSystemStore.dwSystemID},` +
797
+ `this.s${JavaScript_Name(rec.SetSystemStore.StoreIndex, rec.SetSystemStore.Store.dpName)},t);`; // I3681
798
+ len = -1;
799
+ break;
800
+ default:
801
+ callbacks.reportMessage(KmwCompilerMessages.Error_NotSupportedInKeymanWebOutput({ code: GetCodeName(rec.Code) }));
802
+ Result += '';
803
+ }
804
+ }
805
+ else {
806
+ if (!InQuotes) {
807
+ if (!isGroupReadOnly(fk, fgp)) {
808
+ Result += nlt + `k.KO(${len},t,"`; // I3681
809
+ }
810
+ InQuotes = true;
811
+ len = -1;
812
+ }
813
+ if (!isGroupReadOnly(fk, fgp)) {
814
+ if (rec.ChrVal == '"'.charCodeAt(0) || rec.ChrVal == '\\'.charCodeAt(0)) {
815
+ Result += '\\';
816
+ }
817
+ Result += JavaScript_String(rec.ChrVal); // I2242
818
+ }
819
+ }
820
+ x = incxstr(pwsz, x);
821
+ }
822
+ if (InQuotes) {
823
+ if (!isGroupReadOnly(fk, fgp)) {
824
+ Result += '");';
825
+ }
826
+ }
827
+ return Result;
828
+ }
829
+ export function zeroPadHex(n, len) {
830
+ let result = n.toString(16).toUpperCase();
831
+ if (result.length < len) {
832
+ return '0'.repeat(len - result.length) + result;
833
+ }
834
+ return result;
835
+ }
836
+ /**
837
+ * Converts a key value into a constant
838
+ *
839
+ * @param key A virtual key code
840
+ *
841
+ * @return string of JavaScript code, e.g. 'keyCodes.K_A /* 0x41 * /'
842
+ */
843
+ function FormatKeyAsString(key) {
844
+ if (IsKeyboardVersion10OrLater()) {
845
+ // Depends on flags defined in KeymanWeb 10.0
846
+ if (key <= 255 && KMWVKeyNames[key] != '') {
847
+ return 'keyCodes.' + KMWVKeyNames[key] + ' /* 0x' + zeroPadHex(key, 2) + ' */';
848
+ }
849
+ return '0x' + zeroPadHex(key, 2);
850
+ }
851
+ return '0x' + zeroPadHex(key, 2);
852
+ }
853
+ //# debugId=3ab3909d-31cd-54df-a8bb-aaa1c023ca3f
854
+ //# sourceMappingURL=javascript-strings.js.map