Relates to #3621.
Adds `readonly` group support and verifies that keyboards meet
constraints around usage of these groups.
(Note: fixes test_valid.kps and test.bat which seemed to have some
invalid tests?)
Relates to #3621.
Add support for `&layerChanged` system store. This store is set to `1`
before a `begin postKeystroke`, if the keystroke it follows resulted in
a layer change, either programatically through a keyboard rule, or
through a `nextlayer` property of the touched key.
Relates to #3621.
This adds basic compiler support for the `begin newContext` and
`begin postKeystroke` statements, along with the corresponding `gn` and
`gpk` entry points in the compiled JavaScript keyboard.
TODO: `readonly` semantics, usage constraints, `&layerChanged`.
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.
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#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.
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.
This is part 1 of 2 of a fix for #917. This adds in version 14.0
targeting and a new function `KNO` which is used in one specific place:
when a context() statement references a notany() statement. This
minimizes any risk in this change because existing supported patterns
should compile identically.
If the compiler finds this pattern, it will enforce 14.0 minimum version
for web targets.
Addresses Coverity reports for compiler.cpp and other files.
Note that whitespace was reformatted on this PR. You may want to compare
with ignore-whitespace.
Fixes#3084.
This does two things:
1. Cleans up a bunch of places where we used to use `(int)` typecasts
for pointer math, which was problematic. We now use `(INT_PTR)` per
MSDN https://docs.microsoft.com/en-us/windows/win32/winprog64/rules-for-using-pointers
and then cast that down to `(int)` where necessary, e.g. when storing
string lengths which are never going to be more than a few hundred
characters! Doing this explicitly helps to clarify that we are aware
of the typecast and believe it to be safe.
2. Adds in some build infrastructure for future use of Coverity Scan
https://scan.coverity.com/ which we plan to use for further code
quality updates. I have submitted the project to Coverity and are
now waiting for approval so we can check results. Once we have
approval, I do plan to add this to the nightly build (we need to
keep submissions under 3 builds/day).
Note: I have not yet added Keyman Core (Windows) to this project,
nor are we currently building Keyman Core (macOS) or Keyman for
Linux, but we should consider adding those in future.
ISO9995 describes keys by positions, where E00 is 5th (top) row,
left-most key. This feature allows keyboard developers to use
clearly positional identifiers in place of K_ identifiers.
Fixes#138. Hotkeys in .kmn files no longer need to be quoted. This
update does not change compatibility with earlier versions of Keyman
Engine as the difference is entirely in the compiler.
[Windows] More tidyup and robustness for metro app support - debug cleanup and serialization of input (not quite finished)
[windows] Refactor serialized input code when used with key event thread model
[windows] Add consistent precompiled headers for other projects
[windows] Merge console window test into metro support
[Windows] Tidy up work and identify additional TODOs for metro-style app support
[Windows] Ensure error case falls through to default hook processing for console windows
[Windows] Refactor shared memory into memory mapped file so we can cross 32-64 bit boundary
[Windows] Tweaks to C++ security calls and parameters
[Windows] Start refactor of SerialKeyEvent* classes
[Windows] Rename to SerialKeyEventServer (refactoring)
[Windows] Complete refactoring of SerialKeyEventClient class
[Windows] Further encapsulation and cleanup with 'interfaces' to reduce header pollution
[Windows] Complete serialization fix with move of modifier state management from client thread to server thread to guarantee consistency
[Windows] Replace atom-based keyboard switching with memory mapped file indexed to avoid security constraints
[Windows] Fixup Left Alt+Shift interaction with serializer
[Windows] Use Windows 8.1 SDK for test