Fixes#4830.
There remain some additional buffer size checks we should be doing in
`GetXString` but this will address the current issue by using the
standard maximum buffer size.
This does not trigger a build failure; validation warnings currently always pass.
Info messages are currently suppressed with -s which also suppresses the banner,
which is more plumbing than we should change just now.
Fixes#2241.
The `&CasedKeys` system store is a compiler feature that reduces the
repetitive nature of keyboard rules for `CAPS` and `NCAPS`. The
`&CasedKeys` system store defines a list of virtual keys for which
'normal' Caps Lock rules apply. This store has no default value, for
backward compatibility.
Once this store is defined, then you can define just the unshifted and
shifted versions of a rule, and Keyman Developer will synthesize the
`CAPS` and `NCAPS` versions of the rule. For example, you may have the
following rules:
```
store(&CasedKeys) [K_A]
+ [K_A] > 'α'
+ [SHIFT K_A] > 'Α'
```
These would be replaced by the compiler with:
```
store(&CasedKeys) [K_A]
+ [NCAPS K_A] > 'α'
+ [SHIFT CAPS K_A] > 'α'
+ [CAPS K_A] > 'Α'
+ [SHIFT NCAPS K_A] > 'Α'
```
You can also use this functionality with characters in the key part of
the rule:
```
store(&CasedKeys) 'a'..'c'
+ 'a' > 'α'
+ 'A' > 'Α'
```
and the compiled expansion would be similar:
```
store(&CasedKeys) [K_A] [K_B] [K_C]
+ [NCAPS K_A] > 'α'
+ [SHIFT CAPS K_A] > 'α'
+ [CAPS K_A] > 'Α'
+ [SHIFT NCAPS K_A] > 'Α'
```
This feature is backwardly compatible with Keyman 6.0, as it is entirely
implemented in the compiler.
This feature is not compatible with mnemonic layouts, and the keys
defined in the `&CasedKeys` store must be the unshifted base keys as
found on a US English keyboard, or you can use ISO9995 identifiers if
you prefer.
If you define a rule where you specify either `NCAPS` or `CAPS`, for a
key found in the store, then no change will be made to that rule. You
can also continue to define rules which use `NCAPS` or `CAPS` for keys
not found in the store.
As a side-benefit, this allows the visual designer to be used and
support Caps Lock, although at this stage, the `&CasedKeys` store is not
surfaced in the visual designer.
Relates to #2241.
Range expansions are a new language feature that reduce verbosity in
Keyman Keyboard Language (.kmn) files by making it possible to collapse
sequential ranges with a new `..` operator. It is envisioned that these
will be used primarily in stores.
Two kinds of expansions are available: character ranges, and virtual key
ranges.
The syntax is:
```
char '..' char
vkey '..' vkey
```
Where the `char` terminator is a single normal character, and the `vkey`
terminator is a single virtual key. `outs` is permissible for
terminators but no other statement is allowed. Whitespace is per normal
Keyman keyboard language syntax.
Character ranges will replace the range with the set of characters
between the terminators, based on the Unicode value of the terminators.
Examples:
```
store(alphabet) 'a' .. 'z'
store(alpha_not_bq) 'ac'..'pr'..'z'
store(capitals) U+0041 .. U+005A
```
Virtual key ranges work in a similar fashion, but with virtual keys. The
starting and terminating virtual key must have the same shift state.
This will be most useful for character and numeric virtual keys, as the
ranges are based on the numeric value of the virtual key as defined by
Windows, not its position on the keyboard.
Examples:
```
store(alphakeys) [K_A] .. [K_Z]
store(numkeys) [K_0] .. [K_9]
```
Ranges must be positive, that is, you cannot use `'z' .. 'a'`.
While this expansion is not expected to be very useful in rules, it is
still permitted. `context()` and other offsets are calculated on the
expanded form, not the collapsed form. Similarly, `any()`/`index()`
offsets are calculated on the expanded form.
'a' .. 'z' > context(3) c this produces 'c', not 'z'
Because ranges are expanded at compile time, ranges that are overly
long will result in an error, so you cannot use, for example:
```
store(AllUnicode) U+0020 .. U+10FFFF
```
The precise maximum length of a range is dependent on the context where
it is used.
The changes are entirely compiler-based; no change is made to the .kmx
file format or to the Keyman apps.
Fixes#2789.
The Keyboard Fonts dialog skipped some fonts which it did not recognise
as valid TrueType fonts. As a bonus, I've rewritten a few parts of it to
make it significantly faster to load.
I also turned off the font formatting for the list, as it was not very
helpful and hurt performance considerably.
Fixes#4278.
When Keyman Developer is installed without Keyman for Windows, the
program silently crashes, because it is looking for libcef.dll in the
Keyman Desktop install folder rather than using its own copy of it.
This improves the search for libcef.dll and kmbrowserhost.exe, and
includes kmbrowserhost.exe with the Keyman Developer installation.
In the future, we could consider moving kmbrowserhost.exe into a common
folder (perhaps when we split Keyman for Windows and Keyman Developer
projects in 15.0).
I threw in a one-liner addressing a deprecated function warning in the
Developer build.
Fixes#3011.
Keys that have only whitespace will no longer generate separate key data
for the on screen keyboard, as they have no visual presentation anyway.
Fixes#3337.
In some situations, the wordlist editor was not tracking modified state
100% correctly, which meant that edits could be lost. This resolves that
by simplifying the modification state tracking.
Fixes#2556.
This adds support for `isRTL`, `insertAfterWord`, and
`quotesForKeepSuggestions` punctuation options for lexical models, both
in the parsing and in the user interface. A number of options are
presented to the user for the quotes and word breaking characters.
The parser continues to be a regex-based typescriptish parser. Expect it
to be gross. It's too big a job to do properly right now, so it is
somewhat limited and will bail if it finds structures it can't
understand.
I would hope to use something a bit smarter in the future to interface
with the editor. Probably when we are actually fully web-based and can
depend on a Typescript compiler directly.
Please don't get mad at me! 😟😟😟
Fixes#2740.
The definitions for several of the combined modifiers was incorrect,
which led to a mismatch when attempting to import those layers from a
visual keyboard into the touch layout editor.
Fixes#4423.
Using a named character constant with a store name that included
characters outside ascii could cause kmcmpdll to crash with an assertion
failure.
This fix allows store names defined in the .kmn file to use characters
outside ascii.
Note that more work needs to be done on which characters are acceptable
to use, as this is somewhat implementation-specific according to the C++
specification for `iswalpha`.
Added a test case to verify various named code constant examples.
Also removes dead code for `IsCJKUnifiedIdeograph` as this was never
used and somewhat pointless in any case.
NamedCodeConstants.cpp could stand to be rewritten using `std::map` or
equivalent. Current implementation is pretty icky.
Ensures we get a canonical tag per langtags.json as far as we possibly
can. This is a breaking change for the compiler as tags which were
formerly regarded as canonical are no longer regarded that way. This
mostly relates to script subtag but a secondary bug meant that some
other tags would have lost data in the canonicalization process
(because we did a lookup based only on the language subtag previously,
which is a no-no).
See keymanapp/keyboards#1452 for related work.
Fixes#4280.
Adds checks to verify that `if()`, `platform()`, `baselayout()` and
`nul` are at the start of the context in the appropriate order.
Adds unit tests to validate these checks.
These are conditions that have been present in earlier versions of
Keyman but not enforced until now. Keyboards that do not meet these
conditions would not work correctly in all circumstances and should be
updated to meet the requirements.
An alternative would have been to reorder the context string but that is
much more complex as manipulation would also have been required for the
output string. The enforced order is logical and reduces confusion in
any case.
Updated documentation coming along shortly.
Fixes#4250.
This implements @jahorton's suggestion of including the original name
in a comment alongside the munged name, as well as appending the unique
integer identifier of each symbol.
Note: the error reporting code needed a massage to support Unicode error
strings; in the future we should update the C++ compiler to emit
Unicode error strings also.
Fixes#4393.
Fixes KEYMAN-DEVELOPER-46.
Fixes KEYMAN-DEVELOPER-45.
This arose because deleting a tab caused Delphi VCL to switch to another
tab in the page control, which is IMHO a bug in the TPageControl VCL
component. Furthermore, when the active page is changed under these
circumstances, the normal OnChange and OnChanging events are not fired,
which means that the Source tab (which is the lucky tab to be activated)
never gets initialised. This cascades eventually to a crash due to the
Source tab's text editor not being properly loaded.
Two parts to this fix:
1. Restore the active page when we delete a wordlist tab (RSP-32327);
this does not resolve the crash but does avoid weird side-effect of
the active tab changing.
2. Initialise the source tab when we load the form so that the
initialisation issue described above is avoided.
A separate fix in modelTsProjectFile avoids a (handled) null variant
conversion exception.
Fixes#2657.
Importing a Windows Keyboard had an option to select default targets for
the imported keyboard, but the option was ignored. This propagates the
option setting through the import process.
Fixes#2679.
If web is specified but not a touch platform, exclude touch layout from
a generated project. Also, fixup list of supported platforms in the
generated README.md.
The character grid in the debugger would become very slow as the number
of characters increased, with substantial flickering. This refactor
removes the unnecessary recalculations of the grid cell count and
thus resolves performance problems.