spiegel-keyman/developer/kmcompx/include/ACheckNCapsConsistency.cpp
Sabine 3e58fa76b6 get keymans version
Merge branch 'master' of https://github.com/keymanapp/keyman into refactor/developer/6026-kmcompx-compiler-cross-platform-part-2-NEW_VERSION

# Conflicts:
#	common/core/desktop/src/kmx/kmx_context.h
#	common/core/desktop/src/kmx/kmx_processor.cpp
#	common/windows/cpp/include/keymanversion.h
#	common/windows/cpp/include/kkmnkbd/Compfile.h
#	common/windows/cpp/include/kmtip_guids.h
#	common/windows/cpp/src/kmtip_guids.cpp
#	core/src/kmx/kmx_conversion.cpp
#	core/src/kmx/kmx_conversion.h
#	core/src/kmx/kmx_file.cpp
#	core/src/kmx/kmx_processevent.cpp
#	core/src/kmx/kmx_processor.hpp
#	core/src/kmx/kmx_xstring.cpp
#	developer/js/.gitignore
#	developer/js/package-lock.json
#	developer/js/tests/tsconfig.json
#	developer/src/kmcmpdll/CasedKeys.cpp
#	developer/src/kmcmpdll/CheckFilenameConsistency.cpp
#	developer/src/kmcmpdll/CheckFilenameConsistency.h
#	developer/src/kmcmpdll/CheckForDuplicates.cpp
#	developer/src/kmcmpdll/CheckForDuplicates.h
#	developer/src/kmcmpdll/CheckNCapsConsistency.cpp
#	developer/src/kmcmpdll/CheckNCapsConsistency.h
#	developer/src/kmcmpdll/Compiler.cpp
#	developer/src/kmcmpdll/DeprecationChecks.cpp
#	developer/src/kmcmpdll/NamedCodeConstants.cpp
#	developer/src/kmcmpdll/UnreachableRules.cpp
#	developer/src/kmcmpdll/UnreachableRules.h
#	developer/src/kmcmpdll/compfile.h
#	developer/src/kmcmpdll/kcframe/kcframe.cpp
#	developer/src/kmcmpdll/kcframe/kcframe.vcxproj
#	developer/src/kmcmpdll/kcframe/kcframe.vcxproj.filters
#	developer/src/kmcmpdll/kmcmpdll.vcxproj
#	developer/src/kmcmpdll/kmcmpdll.vcxproj.filters
#	developer/src/kmcmpdll/version.rc
#	developer/src/kmcmpdll/versioning.cpp
#	developer/src/kmlmc/bundle.sh
#	developer/src/kmlmc/tests/test-join-word-breaker.ts
#	developer/src/kmlmc/tests/test-override-script-defaults.ts
#	developer/src/server/tsconfig.json
#	windows/src/developer/kmcmpdll/Makefile
#	windows/src/developer/kmcmpdll/vkeys.h
#	windows/src/engine/keyman32/keymanengine.h
#	windows/src/global/inc/Vkeys.h
#	windows/src/global/inc/rc4.h
#	windows/src/global/vc/rc4.cpp
2022-07-12 10:43:20 +02:00

103 lines
3.5 KiB
C++

#include "../../../../developer/kmcompx/include/pch.h" // _S2 #include "pch.h"
#include "CheckNCapsConsistency.h"
//#include "../../../../developer/kmcompx/include/compfile.h" // _S2 #include <compfile.h>
//#include "../../../../developer/kmcompx/include/compiler.h" // _S2 #include <compiler.h>
//#include <comperr.h> // double?
//#include "../../../../developer/kmcompx/include/kmcmpdll.h" // _S2 #include <kmcmpdll.h>
#include "CharToKeyConversion.h"
#include <windows.h> // added _S2 needed?
/**
* If any rule uses CAPS or NCAPS for a given key, then every rule that
* uses that key must also use CAPS or NCAPS, as otherwise the results are
* inconsistent. For example, if Caps Lock is on, then [K_F] may still be
* matched:
*
* + [K_F] > 'foo'
* + [CAPS K_F] > 'bar'
*
* Because of the way that KeymanWeb compiles rules, this may even apply when
* we have a key rule that would otherwise be ignored due to context. In the
* following example, [Caps Lock] + [y] would result in no output (or default
* output) rather than 'bar', because the preceding rule would capture the
* Y key, ignoring Caps Lock, meaning that the subsequent rule would never
* even get tested. (Note that this was introduced in the KeymanWeb compiler
* fix for extremely long if/else ladders in Keyman 12 in #1561, and this is
* technically slightly inconsistent with Keyman Core, although in my analysis
* only in this already ambiguous situation.
*
* 'x' + [K_Y] > 'foo'
* [CAPS K_Y] > 'bar'
*
* Given all this, we'll warn any time we find a key that has inconsistent use
* of CAPS/NCAPS in its rules.
*
* @param fk Keyboard to check
*/
bool CheckNCapsConsistency(PFILE_KEYBOARD fk) {
struct CapsUsage {
int ncaps_line, caps_line, neither_line;
};
// 256 virtual key codes + sizeof the virtual key dictionary is max key code possible
const int nkeys = 256 + fk->cxVKDictionary;
const int oldCurrentLine = currentLine;
auto caps_ncaps_usage = new CapsUsage [nkeys];
memset(caps_ncaps_usage, 0, nkeys * sizeof(CapsUsage));
PFILE_GROUP gp;
KMX_DWORD gn;
for (gn = 0, gp = fk->dpGroupArray; gn < fk->cxGroupArray; gn++, gp++) {
if (!gp->fUsingKeys) {
continue;
}
PFILE_KEY kp;
KMX_DWORD kn;
for (kn = 0, kp = gp->dpKeyArray; kn < gp->cxKeyArray; kn++, kp++) {
KMX_UINT key;
KMX_UINT shift;
if (kp->ShiftFlags & ISVIRTUALKEY) {
if (kp->Key >= nkeys) {
assert(false);
continue;
}
key = kp->Key;
shift = kp->ShiftFlags;
}
else if (!MapUSCharToVK(kp->Key, &key, &shift)) {
// Not a valid key
continue;
}
if (shift & NOTCAPITALFLAG) {
if (!caps_ncaps_usage[key].ncaps_line) caps_ncaps_usage[key].ncaps_line = (kp->Line == 0 ? 1 : kp->Line);
}
else if (shift & CAPITALFLAG) {
if (!caps_ncaps_usage[key].caps_line) caps_ncaps_usage[key].caps_line = (kp->Line == 0 ? 1 : kp->Line);
}
else {
if (!caps_ncaps_usage[key].neither_line) caps_ncaps_usage[key].neither_line = (kp->Line == 0 ? 1 : kp->Line);
}
}
}
for (int i = 0; i < nkeys; i++) {
if (caps_ncaps_usage[i].neither_line && (caps_ncaps_usage[i].caps_line || caps_ncaps_usage[i].ncaps_line)) {
// We set the current line to one needing work: the developer should add the NCAPS flag
currentLine = caps_ncaps_usage[i].neither_line;
AddWarning(CWARN_KeyShouldIncludeNCaps);
}
}
delete[] caps_ncaps_usage;
currentLine = oldCurrentLine;
return TRUE;
}