mirror of
https://github.com/keymanapp/keyman.git
synced 2026-09-24 08:37:42 +00:00
chore(web): Merge branch 'feature-esmodule-web-engine' into chore/web/hardware-event-keyboard
This commit is contained in:
commit
2fe0d3c33a
113 changed files with 1641 additions and 3312 deletions
31
HISTORY.md
31
HISTORY.md
|
|
@ -1,5 +1,36 @@
|
|||
# Keyman Version History
|
||||
|
||||
## 17.0.109 alpha 2023-05-17
|
||||
|
||||
* fix(windows): add wrap-symbols to Text Editor Makefile (#8819)
|
||||
* chore(linux): Make postinst script comply with Debian policy (#8810)
|
||||
* chore(windows): remove legacy core and flag ️ (#8593)
|
||||
|
||||
## 17.0.108 alpha 2023-05-16
|
||||
|
||||
* feat(windows): add text editor to the support makefile (#8750)
|
||||
* feat(developer): verify keyboard versions in kmc-package (#8769)
|
||||
* feat(developer): verify bcp47 tags are valid and minimal in kmc-package (#8778)
|
||||
* feat(developer): verify at least one language in package (#8783)
|
||||
* chore(developer): verify file types of content files in package (#8792)
|
||||
* chore(developer): verify that package has at least a model or keyboard (#8793)
|
||||
* chore(ios): Changes required for XCode 14.3 (#8746)
|
||||
|
||||
## 17.0.107 alpha 2023-05-15
|
||||
|
||||
* chore(linux): Fix installation build step on TC (#8784)
|
||||
* refactor(android/engine): Consolidate updateSelection (#8739)
|
||||
|
||||
## 17.0.106 alpha 2023-05-12
|
||||
|
||||
* chore(developer): move package formats to common/web/types (#8729)
|
||||
* feat(developer): add package validation (#8740)
|
||||
* feat(developer): add validation of package filenames (#8751)
|
||||
* feat(developer): validate content file names in packages (#8755)
|
||||
* feat(developer): validate package name in compiler (#8757)
|
||||
* chore(developer): rename Compiler and related classes (#8726)
|
||||
* feat(developer): uset api from wasm! (#8716)
|
||||
|
||||
## 17.0.105 alpha 2023-05-11
|
||||
|
||||
* chore(common): Update crowdin strings for Amharic (#8748)
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
17.0.106
|
||||
17.0.110
|
||||
|
|
@ -47,6 +47,9 @@ import android.view.MotionEvent;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.ExtractedText;
|
||||
import android.view.inputmethod.ExtractedTextRequest;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
import android.webkit.ConsoleMessage;
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebSettings;
|
||||
|
|
@ -139,7 +142,7 @@ final class KMKeyboard extends WebView {
|
|||
}
|
||||
|
||||
public boolean getShouldShowHelpBubble() {
|
||||
if(this._shouldShowHelpBubble == null) {
|
||||
if (this._shouldShowHelpBubble == null) {
|
||||
SharedPreferences prefs = context.getSharedPreferences(context.getString(R.string.kma_prefs_name), Context.MODE_PRIVATE);
|
||||
this._shouldShowHelpBubble = prefs.getBoolean(KMManager.KMKey_ShouldShowHelpBubble, true);
|
||||
}
|
||||
|
|
@ -151,10 +154,54 @@ final class KMKeyboard extends WebView {
|
|||
this._shouldShowHelpBubble = flag;
|
||||
}
|
||||
|
||||
protected boolean shouldIgnoreTextChange() { return shouldIgnoreTextChange; }
|
||||
protected void setShouldIgnoreTextChange(boolean ignore) { this.shouldIgnoreTextChange = ignore; }
|
||||
protected boolean shouldIgnoreSelectionChange() { return shouldIgnoreSelectionChange; }
|
||||
protected void setShouldIgnoreSelectionChange(boolean ignore) { this.shouldIgnoreSelectionChange = ignore; }
|
||||
protected boolean shouldIgnoreTextChange() {
|
||||
return shouldIgnoreTextChange;
|
||||
}
|
||||
|
||||
protected void setShouldIgnoreTextChange(boolean ignore) {
|
||||
this.shouldIgnoreTextChange = ignore;
|
||||
}
|
||||
|
||||
protected boolean shouldIgnoreSelectionChange() {
|
||||
return shouldIgnoreSelectionChange;
|
||||
}
|
||||
|
||||
protected void setShouldIgnoreSelectionChange(boolean ignore) {
|
||||
this.shouldIgnoreSelectionChange = ignore;
|
||||
}
|
||||
|
||||
protected boolean updateText(String text) {
|
||||
boolean result = false;
|
||||
String kmText = "";
|
||||
if (text != null) {
|
||||
kmText = text.toString().replace("\\", "\\u005C").replace("'", "\\u0027").replace("\n", "\\n");
|
||||
}
|
||||
|
||||
if (KMManager.isKeyboardLoaded(this.keyboardType) && !shouldIgnoreTextChange) {
|
||||
this.loadJavascript(KMString.format("updateKMText('%s')", kmText));
|
||||
result = true;
|
||||
}
|
||||
|
||||
shouldIgnoreTextChange = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
protected boolean updateSelectionRange(int selStart, int selEnd) {
|
||||
boolean result = false;
|
||||
InputConnection ic = KMManager.getInputConnection(this.keyboardType);
|
||||
if (ic != null) {
|
||||
ExtractedText icText = ic.getExtractedText(new ExtractedTextRequest(), 0);
|
||||
if (icText != null) {
|
||||
updateText(icText.text.toString());
|
||||
}
|
||||
}
|
||||
this.loadJavascript(KMString.format("updateKMSelectionRange(%d,%d)", selStart, selEnd));
|
||||
result = true;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
|
|
|
|||
|
|
@ -1952,25 +1952,11 @@ public final class KMManager {
|
|||
|
||||
public static boolean updateText(KeyboardType kbType, String text) {
|
||||
boolean result = false;
|
||||
String kmText = "";
|
||||
if (text != null) {
|
||||
kmText = text.toString().replace("\\", "\\u005C").replace("'", "\\u0027").replace("\n", "\\n");
|
||||
}
|
||||
|
||||
if (kbType == KeyboardType.KEYBOARD_TYPE_INAPP) {
|
||||
if (isKeyboardLoaded(KeyboardType.KEYBOARD_TYPE_INAPP) && !InAppKeyboard.shouldIgnoreTextChange()) {
|
||||
InAppKeyboard.loadJavascript(KMString.format("updateKMText('%s')", kmText));
|
||||
result = true;
|
||||
}
|
||||
|
||||
InAppKeyboard.setShouldIgnoreTextChange(false);
|
||||
return InAppKeyboard.updateText(text);
|
||||
} else if (kbType == KeyboardType.KEYBOARD_TYPE_SYSTEM) {
|
||||
if (isKeyboardLoaded(KeyboardType.KEYBOARD_TYPE_SYSTEM) && !SystemKeyboard.shouldIgnoreTextChange()) {
|
||||
SystemKeyboard.loadJavascript(KMString.format("updateKMText('%s')", kmText));
|
||||
result = true;
|
||||
}
|
||||
|
||||
SystemKeyboard.setShouldIgnoreTextChange(false);
|
||||
return SystemKeyboard.updateText(text);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
@ -1980,23 +1966,13 @@ public final class KMManager {
|
|||
boolean result = false;
|
||||
if (kbType == KeyboardType.KEYBOARD_TYPE_INAPP) {
|
||||
if (isKeyboardLoaded(KeyboardType.KEYBOARD_TYPE_INAPP) && !InAppKeyboard.shouldIgnoreSelectionChange()) {
|
||||
InAppKeyboard.loadJavascript(KMString.format("updateKMSelectionRange(%d,%d)", selStart, selEnd));
|
||||
result = true;
|
||||
result = InAppKeyboard.updateSelectionRange(selStart, selEnd);
|
||||
}
|
||||
|
||||
InAppKeyboard.setShouldIgnoreSelectionChange(false);
|
||||
} else if (kbType == KeyboardType.KEYBOARD_TYPE_SYSTEM) {
|
||||
if (isKeyboardLoaded(KeyboardType.KEYBOARD_TYPE_SYSTEM) && !SystemKeyboard.shouldIgnoreSelectionChange()) {
|
||||
InputConnection ic = getInputConnection(KeyboardType.KEYBOARD_TYPE_SYSTEM);
|
||||
if (ic != null) {
|
||||
ExtractedText icText = ic.getExtractedText(new ExtractedTextRequest(), 0);
|
||||
if (icText != null) {
|
||||
updateText(kbType, icText.text.toString());
|
||||
}
|
||||
}
|
||||
|
||||
SystemKeyboard.loadJavascript(KMString.format("updateKMSelectionRange(%d,%d)", selStart, selEnd));
|
||||
result = true;
|
||||
result = SystemKeyboard.updateSelectionRange(selStart, selEnd);
|
||||
}
|
||||
|
||||
SystemKeyboard.setShouldIgnoreSelectionChange(false);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export { default as LDMLKeyboardXMLSourceFileReader } from './ldml-keyboard/ldml
|
|||
|
||||
export * as Constants from './consts/virtual-key-constants.js';
|
||||
|
||||
export { CompilerCallbacks, CompilerSchema, CompilerEvent, CompilerErrorNamespace, CompilerErrorSeverity, CompilerPathCallbacks, CompilerFileSystemCallbacks, CompilerMessageSpec, compilerErrorSeverityName } from './util/compiler-interfaces.js';
|
||||
export { CompilerCallbacks, CompilerSchema, CompilerEvent, CompilerErrorNamespace, CompilerErrorSeverity, CompilerPathCallbacks, CompilerFileSystemCallbacks, CompilerMessageSpec, compilerErrorSeverityName, compilerExceptionToString, compilerErrorFormatCode } from './util/compiler-interfaces.js';
|
||||
export { CommonTypesMessages } from './util/common-events.js';
|
||||
|
||||
export * as TouchLayout from './keyman-touch-layout/keyman-touch-layout-file.js';
|
||||
|
|
|
|||
|
|
@ -32,6 +32,18 @@ export function compilerErrorSeverityName(code: number): string {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the error code number
|
||||
* example: "FATAL:0x03004"
|
||||
*/
|
||||
export function compilerErrorFormatCode(code: number): string {
|
||||
const severity = code & CompilerErrorSeverity.Severity_Mask;
|
||||
const severityName = compilerErrorSeverityName(severity);
|
||||
const errorCode = code & CompilerErrorSeverity.Error_Mask;
|
||||
const errorCodeString = Number(errorCode).toString(16).padStart(5,'0');
|
||||
return `${severityName}:0x${errorCodeString}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the error code ranges for various compilers. Once defined, these
|
||||
* ranges must not be changed as external modules may depend on specific error
|
||||
|
|
@ -137,3 +149,10 @@ export interface CompilerCallbacks {
|
|||
* @returns
|
||||
*/
|
||||
export const CompilerMessageSpec = (code: number, message: string) : CompilerEvent => { return { code, message } };
|
||||
|
||||
/**
|
||||
* @param e Error-like
|
||||
*/
|
||||
export function compilerExceptionToString(e?: any) : string {
|
||||
return `${(e ?? 'unknown error').toString()}\n\nCall stack:\n${(e instanceof Error ? e.stack : (new Error()).stack)}`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,9 +129,6 @@
|
|||
|
||||
#define REGSZ_Flag_UseCachedHotkeyModifierState "Flag_UseCachedHotkeyModifierState"
|
||||
|
||||
/* REGSZ_Flag_UseKeymanCore DWORD: Turns on the common core - instead of windows core */
|
||||
#define REGSZ_Flag_UseKeymanCore "Flag_UseKeymanCore"
|
||||
|
||||
/* DWORD: Enable/disable deep TSF integration, default enabled; 0 = disabled, 1 = enabled, 2 = default */
|
||||
|
||||
#define REGSZ_DeepTSFIntegration "deep tsf integration"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { CompilerEvent, CompilerCallbacks, CompilerSchema, CompilerPathCallbacks, CompilerFileSystemCallbacks } from '@keymanapp/common-types';
|
||||
import { CompilerEvent, CompilerCallbacks, CompilerSchema, CompilerPathCallbacks, CompilerFileSystemCallbacks, compilerErrorSeverityName } from '@keymanapp/common-types';
|
||||
export { verifyCompilerMessagesObject } from './verifyCompilerMessagesObject.js';
|
||||
|
||||
// TODO: schemas are only used by kmc-ldml for now, so this works at this
|
||||
|
|
@ -19,6 +19,17 @@ export class TestCompilerCallbacks implements CompilerCallbacks {
|
|||
this.messages = [];
|
||||
}
|
||||
|
||||
printMessages() {
|
||||
this.messages.forEach(event => {
|
||||
const code = event.code.toString(16);
|
||||
if(event.line) {
|
||||
console.log(`${compilerErrorSeverityName(event.code)} ${code} [${event.line}]: ${event.message}`);
|
||||
} else {
|
||||
console.log(`${compilerErrorSeverityName(event.code)} ${code}: ${event.message}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
hasMessage(code: number): boolean {
|
||||
return this.messages.find((item) => item.code == code) === undefined ? false : true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,13 +19,13 @@ import {assert, expect} from 'chai';
|
|||
const toTitleCase = (s: string) => s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();
|
||||
|
||||
export function verifyCompilerMessagesObject(source: Record<string,any>) {
|
||||
let keys = Object.keys(source);
|
||||
const keys = Object.keys(source);
|
||||
|
||||
const m = source as Record<string,any>;
|
||||
|
||||
let codes: number[] = [];
|
||||
const codes: number[] = [];
|
||||
|
||||
for(let key of keys) {
|
||||
for(const key of keys) {
|
||||
|
||||
// Verify each object member matches the pattern we expect
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ export function verifyCompilerMessagesObject(source: Record<string,any>) {
|
|||
const c = o[1].toUpperCase() + '_' + o[2];
|
||||
expect(m[c]).to.be.a('number', `Expected constant name ${c} to exist`);
|
||||
|
||||
let v = m[key]('','','','','','','','','','','','' /* ignore arguments*/);
|
||||
const v = m[key]('','','','','','','','','','','','' /* ignore arguments*/);
|
||||
expect(v.code).to.equal(m[c], `Function ${key} returns the wrong code`);
|
||||
}
|
||||
else if(typeof m[key] == 'number') {
|
||||
|
|
@ -63,4 +63,4 @@ export function verifyCompilerMessagesObject(source: Record<string,any>) {
|
|||
codes.push(code);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ TODO: implement additional interfaces:
|
|||
*/
|
||||
|
||||
// TODO: rename wasm-host?
|
||||
import { CompilerCallbacks } from '@keymanapp/common-types';
|
||||
import { CompilerCallbacks, CompilerEvent } from '@keymanapp/common-types';
|
||||
import loadWasmHost from '../import/kmcmplib/wasm-host.js';
|
||||
import { CompilerMessages, mapErrorFromKmcmplib } from './messages.js';
|
||||
|
||||
|
|
@ -47,33 +47,87 @@ const baseOptions: CompilerOptions = {
|
|||
*/
|
||||
let callbackProcIdentifier = 0;
|
||||
|
||||
export class Compiler {
|
||||
wasmModule: any;
|
||||
compileKeyboardFile: any;
|
||||
setCompilerOptions: any;
|
||||
/**
|
||||
* Pointer in wasm-space
|
||||
*/
|
||||
type WasmPtr = number;
|
||||
|
||||
/**
|
||||
* The wrapped functions
|
||||
*/
|
||||
class WasmWrapper {
|
||||
Module: any;
|
||||
|
||||
compileKeyboardFile?: (pszInfile: string, pszOutfile: string, aSaveDebug: number, aCompilerWarningsAsErrors: number, aWarnDeprecatedCode: number, msgProc: string) => boolean;
|
||||
parseUnicodeSet?: (pat: string, buf: WasmPtr, length: number) => number;
|
||||
setCompilerOptions?: (shouldAddCompilerVersion: number) => boolean;
|
||||
|
||||
constructor(wasmModule: any) {
|
||||
this.Module = wasmModule;
|
||||
if (!wasmModule) {
|
||||
throw Error(`wasm host did not load`);
|
||||
}
|
||||
this.compileKeyboardFile = this.Module.cwrap('kmcmp_Wasm_CompileKeyboardFile', 'boolean', ['string', 'string', 'number', 'number', 'number', 'string']);
|
||||
this.parseUnicodeSet = this.Module.cwrap('kmcmp_Wasm_ParseUnicodeSet', 'number', ['string', 'number', 'number']);
|
||||
this.setCompilerOptions = this.Module.cwrap('kmcmp_Wasm_SetCompilerOptions', 'boolean', ['number']);
|
||||
|
||||
if (this.parseUnicodeSet === undefined
|
||||
|| this.setCompilerOptions === undefined
|
||||
|| this.compileKeyboardFile === undefined) {
|
||||
throw Error(`some wasm functions did not load properly.`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Entry point into Wasm functions
|
||||
* @returns WasmWrapper
|
||||
*/
|
||||
public static async load() : Promise<WasmWrapper> {
|
||||
return new WasmWrapper(await loadWasmHost());
|
||||
}
|
||||
};
|
||||
|
||||
export class KmnCompiler {
|
||||
callbackName: string;
|
||||
callbacks: CompilerCallbacks;
|
||||
wasm: WasmWrapper;
|
||||
|
||||
constructor() {
|
||||
this.callbackName = 'kmnCompilerCallback' + callbackProcIdentifier;
|
||||
callbackProcIdentifier++;
|
||||
}
|
||||
|
||||
public async init(): Promise<boolean> {
|
||||
if(!this.wasmModule) {
|
||||
this.wasmModule = await loadWasmHost();
|
||||
this.compileKeyboardFile = this.wasmModule.cwrap('kmcmp_Wasm_CompileKeyboardFile', 'boolean', ['string', 'string',
|
||||
'number', 'number', 'number', 'string']);
|
||||
this.setCompilerOptions = this.wasmModule.cwrap('kmcmp_Wasm_SetCompilerOptions', 'boolean', ['number']);
|
||||
public async init(callbacks: CompilerCallbacks): Promise<boolean> {
|
||||
this.callbacks = callbacks;
|
||||
if(!this.wasm) {
|
||||
try {
|
||||
this.wasm = await WasmWrapper.load();
|
||||
} catch(e: any) {
|
||||
this.callbacks.reportMessage(CompilerMessages.Fatal_MissingWasmModule({e}));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return this.compileKeyboardFile !== undefined && this.setCompilerOptions !== undefined;
|
||||
return this.verifyInitialized();
|
||||
}
|
||||
|
||||
public run(infile: string, outfile: string, callbacks: CompilerCallbacks, options?: CompilerOptions): boolean {
|
||||
this.callbacks = callbacks;
|
||||
/**
|
||||
* Verify that wasm is spun up OK.
|
||||
* @returns true if OK
|
||||
*/
|
||||
public verifyInitialized() : boolean {
|
||||
if(!this.callbacks) {
|
||||
// Can't report a message here.
|
||||
throw Error('Must call Compiler.init(callbacks) before proceeding');
|
||||
}
|
||||
if(!this.wasm) { // fail if wasm not loaded or function not found
|
||||
this.callbacks.reportMessage(CompilerMessages.Fatal_MissingWasmModule({}));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!this.wasmModule) {
|
||||
this.callbacks.reportMessage(CompilerMessages.Fatal_MissingWasmModule());
|
||||
public run(infile: string, outfile: string, options?: CompilerOptions): boolean {
|
||||
if(!this.verifyInitialized()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -92,10 +146,10 @@ export class Compiler {
|
|||
|
||||
private runCompiler(infile: string, outfile: string, options: CompilerOptions): boolean {
|
||||
try {
|
||||
if(!this.setCompilerOptions(options.shouldAddCompilerVersion)) {
|
||||
if (!this.wasm.setCompilerOptions(options.shouldAddCompilerVersion ? 1 : 0)) {
|
||||
this.callbacks.reportMessage(CompilerMessages.Fatal_UnableToSetCompilerOptions());
|
||||
}
|
||||
return this.compileKeyboardFile(
|
||||
return this.wasm.compileKeyboardFile(
|
||||
infile,
|
||||
outfile,
|
||||
options.saveDebug ? 1 : 0,
|
||||
|
|
@ -107,4 +161,85 @@ export class Compiler {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param pattern UnicodeSet pattern such as `[a-z]`
|
||||
* @param bufferSize guess as to the buffer size
|
||||
* @returns UnicodeSet accessor object, or null on failure
|
||||
*/
|
||||
public parseUnicodeSet(pattern: string, bufferSize: number) : UnicodeSet | null {
|
||||
if(!this.verifyInitialized()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!bufferSize) {
|
||||
bufferSize = 100; // TODO-LDML: Preflight mode? Reuse buffer?
|
||||
}
|
||||
const { Module } = this.wasm;
|
||||
const buf = Module.asm.malloc(bufferSize * 2 * Module.HEAPU32.BYTES_PER_ELEMENT);
|
||||
// TODO-LDML: Catch OOM
|
||||
const rc = this.wasm.parseUnicodeSet(pattern, buf, bufferSize);
|
||||
if (rc >= 0) {
|
||||
const ranges = [];
|
||||
const startu = (buf / Module.HEAPU32.BYTES_PER_ELEMENT);
|
||||
for (let i = 0; i < rc; i++) {
|
||||
const low = Module.HEAPU32[startu + (i * 2) + 0];
|
||||
const high = Module.HEAPU32[startu + (i * 2) + 1];
|
||||
ranges.push([low, high]);
|
||||
}
|
||||
// TODO-LDML: no free??
|
||||
// Module.asm.free(buf);
|
||||
return new UnicodeSet(pattern, ranges);
|
||||
} else {
|
||||
// translate error
|
||||
// TODO-LDML: no free??
|
||||
// Module.asm.free(buf);
|
||||
this.callbacks.reportMessage(getUnicodeSetError(rc));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* translate UnicodeSet return code into a compiler event
|
||||
* @param rc parseUnicodeSet error code
|
||||
* @returns the compiler event
|
||||
*/
|
||||
function getUnicodeSetError(rc: number) : CompilerEvent {
|
||||
// from kmcmplib.h
|
||||
const KMCMP_ERROR_SYNTAX_ERR = -1;
|
||||
const KMCMP_ERROR_HAS_STRINGS = -2;
|
||||
const KMCMP_ERROR_UNSUPPORTED_PROPERTY = -3;
|
||||
const KMCMP_FATAL_OUT_OF_RANGE = -4;
|
||||
switch(rc) {
|
||||
case KMCMP_ERROR_SYNTAX_ERR:
|
||||
return CompilerMessages.Error_UnicodeSetSyntaxError();
|
||||
case KMCMP_ERROR_HAS_STRINGS:
|
||||
return CompilerMessages.Error_UnicodeSetHasStrings();
|
||||
case KMCMP_ERROR_UNSUPPORTED_PROPERTY:
|
||||
return CompilerMessages.Error_UnicodeSetHasProperties();
|
||||
case KMCMP_FATAL_OUT_OF_RANGE:
|
||||
return CompilerMessages.Fatal_UnicodeSetOutOfRange();
|
||||
default:
|
||||
return CompilerMessages.Fatal_UnexpectedException({e: `Unexpected UnicodeSet error code ${rc}`});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a parsed UnicodeSet
|
||||
*/
|
||||
export class UnicodeSet {
|
||||
constructor(public pattern: string, public ranges: number[][]) {
|
||||
}
|
||||
/**
|
||||
* Number of ranges
|
||||
*/
|
||||
get length() : number {
|
||||
return this.ranges.length;
|
||||
}
|
||||
|
||||
toString() : string {
|
||||
return this.pattern;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerEvent, CompilerMessageSpec as m } from "@keymanapp/common-types";
|
||||
import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerEvent, CompilerMessageSpec as m, compilerExceptionToString as exc } from "@keymanapp/common-types";
|
||||
|
||||
const Namespace = CompilerErrorNamespace.KmnCompiler;
|
||||
const SevInfo = CompilerErrorSeverity.Info | Namespace;
|
||||
|
|
@ -44,14 +44,29 @@ export const enum KmnCompilerMessageRanges {
|
|||
and the below ranges are reserved.
|
||||
*/
|
||||
export class CompilerMessages {
|
||||
static Fatal_UnexpectedException = (o:{e: any}) => m(this.FATAL_UnexpectedException, `Unexpected exception: ${(o.e ?? 'unknown error').toString()}\n\nCall stack:\n${(o.e instanceof Error ? o.e.stack : (new Error()).stack)}`);
|
||||
static Fatal_UnexpectedException = (o:{e: any}) => m(this.FATAL_UnexpectedException, `Unexpected exception: ${exc(o.e)}`);
|
||||
static FATAL_UnexpectedException = SevFatal | 0x1000;
|
||||
|
||||
static Fatal_MissingWasmModule = () => m(this.FATAL_MissingWasmModule, `Could not instanatiate WASM compiler module`);
|
||||
static Fatal_MissingWasmModule = (o:{e?: any}) => m(this.FATAL_MissingWasmModule, `Could not instantiate WASM compiler module or initialization failed: ${exc(o.e)}`);
|
||||
static FATAL_MissingWasmModule = SevFatal | 0x1001;
|
||||
|
||||
static Fatal_UnableToSetCompilerOptions = () => m(this.FATAL_UnableToSetCompilerOptions, `Unable to set compiler options`);
|
||||
static FATAL_UnableToSetCompilerOptions = SevFatal | 0x1002;
|
||||
|
||||
static Fatal_CallbacksNotSet = () => m(this.FATAL_CallbacksNotSet, `Callbacks were not set with init`);
|
||||
static FATAL_CallbacksNotSet = SevFatal | 0x1003;
|
||||
|
||||
static Fatal_UnicodeSetOutOfRange = () => m(this.FATAL_UnicodeSetOutOfRange, `UnicodeSet buffer was too small`);
|
||||
static FATAL_UnicodeSetOutOfRange = SevFatal | 0x1004;
|
||||
|
||||
static Error_UnicodeSetHasStrings = () => m(this.ERROR_UnicodeSetHasStrings, `UnicodeSet contains strings, not allowed`);
|
||||
static ERROR_UnicodeSetHasStrings = SevError | 0x1005;
|
||||
|
||||
static Error_UnicodeSetHasProperties = () => m(this.ERROR_UnicodeSetHasProperties, `UnicodeSet contains properties, not allowed`);
|
||||
static ERROR_UnicodeSetHasProperties = SevError | 0x1006;
|
||||
|
||||
static Error_UnicodeSetSyntaxError = () => m(this.ERROR_UnicodeSetSyntaxError, `UnicodeSet had a Syntax Error while parsing`);
|
||||
static ERROR_UnicodeSetSyntaxError = SevError | 0x1007;
|
||||
}
|
||||
|
||||
export function mapErrorFromKmcmplib(line: number, code: number, msg: string): CompilerEvent {
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
|
||||
export { Compiler } from './compiler/compiler.js';
|
||||
export { KmnCompiler } from './compiler/compiler.js';
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import 'mocha';
|
|||
import sinon from 'sinon';
|
||||
import chai, { assert } from 'chai';
|
||||
import sinonChai from 'sinon-chai';
|
||||
import { Compiler } from '../src/main.js';
|
||||
import { KmnCompiler } from '../src/main.js';
|
||||
import { dirname } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import fs from 'fs';
|
||||
|
|
@ -15,6 +15,7 @@ chai.use(sinonChai);
|
|||
describe('Compiler class', function() {
|
||||
let consoleLog: any;
|
||||
|
||||
// TODO: do we need this?
|
||||
beforeEach(function() {
|
||||
consoleLog = sinon.spy(console, 'log');
|
||||
});
|
||||
|
|
@ -23,21 +24,36 @@ describe('Compiler class', function() {
|
|||
consoleLog.restore();
|
||||
});
|
||||
|
||||
it('should throw on failure', async function() {
|
||||
const compiler = new KmnCompiler();
|
||||
const callbacks : any = null; // ERROR
|
||||
try {
|
||||
await compiler.init(callbacks)
|
||||
assert.fail('Expected exception');
|
||||
} catch(e) {
|
||||
assert.ok(e);
|
||||
}
|
||||
assert.throws(() => compiler.verifyInitialized());
|
||||
});
|
||||
|
||||
it('should start', async function() {
|
||||
const compiler = new Compiler();
|
||||
assert(await compiler.init());
|
||||
const compiler = new KmnCompiler();
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
assert(await compiler.init(callbacks));
|
||||
assert(compiler.verifyInitialized());
|
||||
});
|
||||
|
||||
it('should compile a basic keyboard', async function() {
|
||||
const compiler = new Compiler();
|
||||
const compiler = new KmnCompiler();
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
assert(await compiler.init());
|
||||
assert(await compiler.init(callbacks));
|
||||
assert(compiler.verifyInitialized());
|
||||
|
||||
const fixtureName = baselineDir + 'k_000___null_keyboard.kmx';
|
||||
const infile = baselineDir + 'k_000___null_keyboard.kmn';
|
||||
const outfile = __dirname + '/k_000___null_keyboard.kmx';
|
||||
|
||||
assert(compiler.run(infile, outfile, callbacks, {saveDebug: true, shouldAddCompilerVersion: false}));
|
||||
assert(compiler.run(infile, outfile, {saveDebug: true, shouldAddCompilerVersion: false}));
|
||||
|
||||
assert(fs.existsSync(outfile));
|
||||
const outfileData = fs.readFileSync(outfile);
|
||||
|
|
@ -49,9 +65,10 @@ describe('Compiler class', function() {
|
|||
// Note, above test case is essentially a subset of this one, but will leave both because
|
||||
// the basic keyboard test is slightly simpler to read
|
||||
it('should build all baseline fixtures', async function() {
|
||||
const compiler = new Compiler();
|
||||
const compiler = new KmnCompiler();
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
assert(await compiler.init());
|
||||
assert(await compiler.init(callbacks));
|
||||
assert(compiler.verifyInitialized());
|
||||
|
||||
const files = fs.readdirSync(baselineDir);
|
||||
for(let file of files) {
|
||||
|
|
@ -60,7 +77,7 @@ describe('Compiler class', function() {
|
|||
const infile = baselineDir + file.replace(/x$/, 'n');
|
||||
const outfile = __dirname + '/' + file;
|
||||
|
||||
assert(compiler.run(infile, outfile, callbacks, {saveDebug: true, shouldAddCompilerVersion: false}));
|
||||
assert(compiler.run(infile, outfile, {saveDebug: true, shouldAddCompilerVersion: false}));
|
||||
|
||||
assert(fs.existsSync(outfile));
|
||||
const outfileData = fs.readFileSync(outfile);
|
||||
|
|
@ -69,6 +86,5 @@ describe('Compiler class', function() {
|
|||
assert.deepEqual(outfileData, fixtureData);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
66
developer/src/kmc-kmn/test/test-wasm-uset.ts
Normal file
66
developer/src/kmc-kmn/test/test-wasm-uset.ts
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
import 'mocha';
|
||||
import { assert } from 'chai';
|
||||
import { KmnCompiler } from '../src/main.js';
|
||||
import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers';
|
||||
import { CompilerMessages } from '../src/compiler/messages.js';
|
||||
import { compilerErrorFormatCode } from '@keymanapp/common-types';
|
||||
|
||||
describe('Compiler UnicodeSet function', function() {
|
||||
it('should start', async function() {
|
||||
const compiler = new KmnCompiler();
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
assert(await compiler.init(callbacks));
|
||||
assert(compiler.verifyInitialized());
|
||||
});
|
||||
|
||||
it('should compile a basic uset', async function() {
|
||||
const compiler = new KmnCompiler();
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
assert(await compiler.init(callbacks));
|
||||
assert(compiler.verifyInitialized());
|
||||
|
||||
const pat = "[abc]";
|
||||
const set = compiler.parseUnicodeSet(pat, 23);
|
||||
|
||||
assert(set.length === 1);
|
||||
assert(set.ranges[0][0] === 'a'.charCodeAt(0));
|
||||
assert(set.ranges[0][1] === 'c'.charCodeAt(0));
|
||||
});
|
||||
it('should compile a more complex uset', async function() {
|
||||
const compiler = new KmnCompiler();
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
assert(await compiler.init(callbacks));
|
||||
assert(compiler.verifyInitialized());
|
||||
|
||||
const pat = "[[🙀A-C]-[CB]]";
|
||||
const set = compiler.parseUnicodeSet(pat, 23);
|
||||
|
||||
assert.equal(set.length, 2);
|
||||
assert.equal(set.ranges[0][0], 'A'.charCodeAt(0));
|
||||
assert.equal(set.ranges[0][1], 'A'.charCodeAt(0));
|
||||
assert.equal(set.ranges[1][0], 0x1F640);
|
||||
assert.equal(set.ranges[1][1], 0x1F640);
|
||||
});
|
||||
it('should fail in various ways', async function() {
|
||||
const compiler = new KmnCompiler();
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
assert(await compiler.init(callbacks));
|
||||
assert(compiler.verifyInitialized());
|
||||
// map from string to failing error
|
||||
const failures = {
|
||||
'[:Adlm:]': CompilerMessages.ERROR_UnicodeSetHasProperties, // what it saye
|
||||
'[acegik]': CompilerMessages.FATAL_UnicodeSetOutOfRange, // 6 ranges, allocated 1
|
||||
'[[\\p{Mn}]&[A-Z]]': CompilerMessages.ERROR_UnicodeSetHasProperties,
|
||||
'[abc{def}]': CompilerMessages.ERROR_UnicodeSetHasStrings,
|
||||
'[[]': CompilerMessages.ERROR_UnicodeSetSyntaxError,
|
||||
};
|
||||
for(const [pat, expected] of Object.entries(failures)) {
|
||||
callbacks.clear();
|
||||
assert.notOk(compiler.parseUnicodeSet(pat, 1));
|
||||
assert.equal(callbacks.messages.length, 1);
|
||||
const firstMessage = callbacks.messages[0];
|
||||
const code = firstMessage.code;
|
||||
assert.equal(code, expected, `${compilerErrorFormatCode(code)}≠${compilerErrorFormatCode(expected)} got ${firstMessage.message} for ${pat}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
|
||||
export default interface CompilerOptions {
|
||||
export interface CompilerOptions {
|
||||
/**
|
||||
* Add debug information to the .kmx file when compiling
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { LDMLKeyboardXMLSourceFileReader, LDMLKeyboard, KMXPlus, CompilerCallbacks, LDMLKeyboardTestDataXMLSourceFile } from '@keymanapp/common-types';
|
||||
import CompilerOptions from './compiler-options.js';
|
||||
import { CompilerOptions } from './compiler-options.js';
|
||||
import { CompilerMessages } from './messages.js';
|
||||
import { BkspCompiler, FinlCompiler, TranCompiler } from './tran.js';
|
||||
import { DispCompiler } from './disp.js';
|
||||
|
|
@ -28,7 +28,7 @@ const SECTION_COMPILERS = [
|
|||
VkeyCompiler,
|
||||
];
|
||||
|
||||
export default class Compiler {
|
||||
export class LdmlKeyboardCompiler {
|
||||
private readonly callbacks: CompilerCallbacks;
|
||||
// private readonly options: CompilerOptions; // not currently used
|
||||
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
import { CompilerCallbacks, VisualKeyboard, LDMLKeyboard, TouchLayoutFileWriter } from "@keymanapp/common-types";
|
||||
import CompilerOptions from "./compiler-options.js";
|
||||
import { CompilerOptions } from "./compiler-options.js";
|
||||
import { TouchLayoutCompiler } from "./touch-layout-compiler.js";
|
||||
import VisualKeyboardCompiler from "./visual-keyboard-compiler.js";
|
||||
import { LdmlKeyboardVisualKeyboardCompiler } from "./visual-keyboard-compiler.js";
|
||||
|
||||
const MINIMUM_KMW_VERSION = '16.0';
|
||||
|
||||
export interface KeymanWebCompilerOptions extends CompilerOptions {
|
||||
export interface LdmlKeyboardKeymanWebCompilerOptions extends CompilerOptions {
|
||||
};
|
||||
|
||||
export class KeymanWebCompiler {
|
||||
private readonly options: KeymanWebCompilerOptions;
|
||||
export class LdmlKeyboardKeymanWebCompiler {
|
||||
private readonly options: LdmlKeyboardKeymanWebCompilerOptions;
|
||||
private readonly nl: string;
|
||||
private readonly tab: string;
|
||||
|
||||
constructor(private callbacks: CompilerCallbacks, options?: KeymanWebCompilerOptions) {
|
||||
constructor(private callbacks: CompilerCallbacks, options?: LdmlKeyboardKeymanWebCompilerOptions) {
|
||||
this.options = { ...options };
|
||||
this.nl = this.options.debug ? "\n" : '';
|
||||
this.tab = this.options.debug ? " " : '';
|
||||
|
|
@ -21,7 +21,7 @@ export class KeymanWebCompiler {
|
|||
|
||||
public compileVisualKeyboard(source: LDMLKeyboard.LDMLKeyboardXMLSourceFile) {
|
||||
const nl = this.nl, tab = this.tab;
|
||||
const vkc = new VisualKeyboardCompiler();
|
||||
const vkc = new LdmlKeyboardVisualKeyboardCompiler();
|
||||
const vk: VisualKeyboard.VisualKeyboard = vkc.compile(source);
|
||||
|
||||
let result =
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import { KMX, KMXPlus } from '@keymanapp/common-types';
|
||||
import CompilerOptions from "./compiler-options.js";
|
||||
import { CompilerOptions } from "./compiler-options.js";
|
||||
import KEYMAN_VERSION from "@keymanapp/keyman-version";
|
||||
|
||||
import KMXPlusData = KMXPlus.KMXPlusData;
|
||||
import KMXFile = KMX.KMXFile;
|
||||
import KEYBOARD = KMX.KEYBOARD;
|
||||
|
||||
export default class KMXPlusMetadataCompiler {
|
||||
export class KMXPlusMetadataCompiler {
|
||||
/**
|
||||
* Look for metadata fields in the KMXPlus data and copy them
|
||||
* through to the relevant KMX stores
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Constants, VisualKeyboard, LDMLKeyboard } from "@keymanapp/common-types";
|
||||
|
||||
export default class VisualKeyboardCompiler {
|
||||
export class LdmlKeyboardVisualKeyboardCompiler {
|
||||
public compile(source: LDMLKeyboard.LDMLKeyboardXMLSourceFile): VisualKeyboard.VisualKeyboard {
|
||||
let result = new VisualKeyboard.VisualKeyboard();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
|
||||
export { default as Compiler } from './compiler/compiler.js';
|
||||
export { KeymanWebCompiler } from './compiler/keymanweb-compiler.js';
|
||||
export { default as VisualKeyboardCompiler } from './compiler/visual-keyboard-compiler.js';
|
||||
export { LdmlKeyboardCompiler } from './compiler/compiler.js';
|
||||
export { LdmlKeyboardKeymanWebCompiler } from './compiler/keymanweb-compiler.js';
|
||||
export { LdmlKeyboardVisualKeyboardCompiler } from './compiler/visual-keyboard-compiler.js';
|
||||
export { TouchLayoutCompiler } from './compiler/touch-layout-compiler.js';
|
||||
export { default as CompilerOptions } from './compiler/compiler-options.js';
|
||||
export { CompilerOptions } from './compiler/compiler-options.js';
|
||||
export { CompilerMessages } from './compiler/messages.js';
|
||||
export { default as KMXPlusMetadataCompiler } from './compiler/metadata-compiler.js';
|
||||
export { KMXPlusMetadataCompiler } from './compiler/metadata-compiler.js';
|
||||
|
||||
export { KMXBuilder } from "@keymanapp/common-types";
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ import * as path from 'path';
|
|||
import { fileURLToPath } from 'url';
|
||||
import { SectionCompiler } from '../../src/compiler/section-compiler.js';
|
||||
import { KMXPlus, LDMLKeyboardXMLSourceFileReader, VisualKeyboard, CompilerEvent, LDMLKeyboardTestDataXMLSourceFile } from '@keymanapp/common-types';
|
||||
import Compiler from '../../src/compiler/compiler.js';
|
||||
import { LdmlKeyboardCompiler } from '../../src/compiler/compiler.js';
|
||||
import { assert } from 'chai';
|
||||
import KMXPlusMetadataCompiler from '../../src/compiler/metadata-compiler.js';
|
||||
import CompilerOptions from '../../src/compiler/compiler-options.js';
|
||||
import VisualKeyboardCompiler from '../../src/compiler/visual-keyboard-compiler.js';
|
||||
import { KMXPlusMetadataCompiler } from '../../src/compiler/metadata-compiler.js';
|
||||
import { CompilerOptions } from '../../src/compiler/compiler-options.js';
|
||||
import { LdmlKeyboardVisualKeyboardCompiler } from '../../src/compiler/visual-keyboard-compiler.js';
|
||||
import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers';
|
||||
|
||||
import KMXPlusFile = KMXPlus.KMXPlusFile;
|
||||
|
|
@ -76,13 +76,13 @@ export function loadSectionFixture(compilerClass: typeof SectionCompiler, filena
|
|||
}
|
||||
|
||||
export function loadTestdata(inputFilename: string, options: CompilerOptions) : LDMLKeyboardTestDataXMLSourceFile {
|
||||
const k = new Compiler(compilerTestCallbacks, options);
|
||||
const k = new LdmlKeyboardCompiler(compilerTestCallbacks, options);
|
||||
const source = k.loadTestData(inputFilename);
|
||||
return source;
|
||||
}
|
||||
|
||||
export function compileKeyboard(inputFilename: string, options: CompilerOptions): KMXPlusFile {
|
||||
const k = new Compiler(compilerTestCallbacks, options);
|
||||
const k = new LdmlKeyboardCompiler(compilerTestCallbacks, options);
|
||||
const source = k.load(inputFilename);
|
||||
checkMessages();
|
||||
assert.isNotNull(source, 'k.load should not have returned null');
|
||||
|
|
@ -103,7 +103,7 @@ export function compileKeyboard(inputFilename: string, options: CompilerOptions)
|
|||
}
|
||||
|
||||
export function compileVisualKeyboard(inputFilename: string, options: CompilerOptions): VisualKeyboard.VisualKeyboard {
|
||||
const k = new Compiler(compilerTestCallbacks, options);
|
||||
const k = new LdmlKeyboardCompiler(compilerTestCallbacks, options);
|
||||
const source = k.load(inputFilename);
|
||||
checkMessages();
|
||||
assert.isNotNull(source, 'k.load should not have returned null');
|
||||
|
|
@ -112,9 +112,9 @@ export function compileVisualKeyboard(inputFilename: string, options: CompilerOp
|
|||
checkMessages();
|
||||
assert.isTrue(valid, 'k.validate should not have failed');
|
||||
|
||||
const vk = (new VisualKeyboardCompiler()).compile(source);
|
||||
const vk = (new LdmlKeyboardVisualKeyboardCompiler()).compile(source);
|
||||
checkMessages();
|
||||
assert.isNotNull(vk, 'VisualKeyboardCompiler.compile should not have returned null');
|
||||
assert.isNotNull(vk, 'LdmlKeyboardVisualKeyboardCompiler.compile should not have returned null');
|
||||
|
||||
return vk;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import 'mocha';
|
||||
import { assert } from 'chai';
|
||||
import { checkMessages, compilerTestCallbacks, makePathToFixture } from './helpers/index.js';
|
||||
import { KeymanWebCompiler } from '../src/compiler/keymanweb-compiler.js';
|
||||
import Compiler from '../src/compiler/compiler.js';
|
||||
import { LdmlKeyboardKeymanWebCompiler } from '../src/compiler/keymanweb-compiler.js';
|
||||
import { LdmlKeyboardCompiler } from '../src/compiler/compiler.js';
|
||||
import * as fs from 'fs';
|
||||
|
||||
describe('KeymanWebCompiler', function() {
|
||||
describe('LdmlKeyboardKeymanWebCompiler', function() {
|
||||
|
||||
it('should build a .js file', async function() {
|
||||
// Let's build basic.xml
|
||||
|
|
@ -16,7 +16,7 @@ describe('KeymanWebCompiler', function() {
|
|||
|
||||
// Load input data; we'll use the LDML keyboard compiler loader to save us
|
||||
// effort here
|
||||
const k = new Compiler(compilerTestCallbacks, {debug: true, addCompilerVersion: false});
|
||||
const k = new LdmlKeyboardCompiler(compilerTestCallbacks, {debug: true, addCompilerVersion: false});
|
||||
const source = k.load(inputFilename);
|
||||
checkMessages();
|
||||
assert.isNotNull(source, 'k.load should not have returned null');
|
||||
|
|
@ -27,7 +27,7 @@ describe('KeymanWebCompiler', function() {
|
|||
assert.isTrue(valid, 'k.validate should not have failed');
|
||||
|
||||
// Actual test: compile to javascript
|
||||
const jsCompiler = new KeymanWebCompiler(compilerTestCallbacks, {debug: true});
|
||||
const jsCompiler = new LdmlKeyboardKeymanWebCompiler(compilerTestCallbacks, {debug: true});
|
||||
const output = jsCompiler.compile('basic.xml', source);
|
||||
assert.isNotNull(output);
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ describe('KeymanWebCompiler', function() {
|
|||
assert.strictEqual(output, outputFixture);
|
||||
|
||||
// Second test: compile to javascript without debug formatting
|
||||
const jsCompilerNoDebug = new KeymanWebCompiler(compilerTestCallbacks, {debug: false});
|
||||
const jsCompilerNoDebug = new LdmlKeyboardKeymanWebCompiler(compilerTestCallbacks, {debug: false});
|
||||
const outputNoDebug = jsCompilerNoDebug.compile('basic.xml', source);
|
||||
assert.isNotNull(outputNoDebug);
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ builder_describe "Build Keyman kmc Package Compiler module" \
|
|||
"--dry-run,-n don't actually publish, just dry run"
|
||||
builder_describe_outputs \
|
||||
configure /node_modules \
|
||||
build /developer/src/kmc-package/build/src/kmp-compiler.js
|
||||
build /developer/src/kmc-package/build/src/main.js
|
||||
builder_parse "$@"
|
||||
|
||||
#-------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ import KEYMAN_VERSION from "@keymanapp/keyman-version";
|
|||
|
||||
import { CompilerCallbacks, KvkFile } from '@keymanapp/common-types';
|
||||
import { CompilerMessages } from './messages.js';
|
||||
import { KmpJsonFile, KpsFile, KMX, KmxFileReader } from '@keymanapp/common-types';
|
||||
import { KmpJsonFile, KpsFile } from '@keymanapp/common-types';
|
||||
import { PackageVersionValidation } from './package-version-validation.js';
|
||||
|
||||
const FILEVERSION_KMP_JSON = '12.0';
|
||||
|
||||
|
|
@ -104,16 +105,16 @@ export class KmpCompiler {
|
|||
//
|
||||
|
||||
if(kps.keyboards && kps.keyboards.keyboard) {
|
||||
kmp.keyboards = this.arrayWrap(kps.keyboards.keyboard).map((keyboard: KpsFile.KpsFileKeyboard) => {
|
||||
return {
|
||||
displayFont: keyboard.displayFont ? this.callbacks.path.basename(keyboard.displayFont) : undefined,
|
||||
oskFont: keyboard.oSKFont ? this.callbacks.path.basename(keyboard.oSKFont) : undefined,
|
||||
name:keyboard.name,
|
||||
id:keyboard.iD,
|
||||
version:keyboard.version,
|
||||
languages: this.kpsLanguagesToKmpLanguages(this.arrayWrap(keyboard.languages.language) as KpsFile.KpsFileLanguage[])
|
||||
};
|
||||
});
|
||||
kmp.keyboards = this.arrayWrap(kps.keyboards.keyboard).map((keyboard: KpsFile.KpsFileKeyboard) => ({
|
||||
displayFont: keyboard.displayFont ? this.callbacks.path.basename(keyboard.displayFont) : undefined,
|
||||
oskFont: keyboard.oSKFont ? this.callbacks.path.basename(keyboard.oSKFont) : undefined,
|
||||
name:keyboard.name,
|
||||
id:keyboard.iD,
|
||||
version:keyboard.version,
|
||||
languages: keyboard.languages ?
|
||||
this.kpsLanguagesToKmpLanguages(this.arrayWrap(keyboard.languages.language) as KpsFile.KpsFileLanguage[]) :
|
||||
[]
|
||||
}));
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -121,20 +122,22 @@ export class KmpCompiler {
|
|||
//
|
||||
|
||||
if(kps.lexicalModels && kps.lexicalModels.lexicalModel) {
|
||||
kmp.lexicalModels = this.arrayWrap(kps.lexicalModels.lexicalModel).map((model: KpsFile.KpsFileLexicalModel) => {
|
||||
return { name:model.name, id:model.iD, languages: this.kpsLanguagesToKmpLanguages(this.arrayWrap(model.languages.language) as KpsFile.KpsFileLanguage[]) }
|
||||
});
|
||||
kmp.lexicalModels = this.arrayWrap(kps.lexicalModels.lexicalModel).map((model: KpsFile.KpsFileLexicalModel) => ({
|
||||
name:model.name,
|
||||
id:model.iD,
|
||||
languages: model.languages ?
|
||||
this.kpsLanguagesToKmpLanguages(this.arrayWrap(model.languages.language) as KpsFile.KpsFileLanguage[]) : []
|
||||
}));
|
||||
}
|
||||
|
||||
//
|
||||
// FollowKeyboardVersion support
|
||||
// Verify version metadata; doing this in the transform
|
||||
// while we have access to the .kps metadata, and keeping the
|
||||
//
|
||||
|
||||
if(kps.options?.followKeyboardVersion !== undefined) {
|
||||
kmp.info.version = {
|
||||
description: this.extractKeyboardVersionFromKmx(kpsFilename, kmp)
|
||||
};
|
||||
// TODO: compare the extracted version with other keyboards in the package
|
||||
const versionValidator = new PackageVersionValidation(this.callbacks);
|
||||
if(!versionValidator.validateAndUpdateVersions(kpsFilename, kps, kmp)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -195,67 +198,7 @@ export class KmpCompiler {
|
|||
return language.map((element) => { return { name: element._, id: element.$.ID } });
|
||||
};
|
||||
|
||||
private extractKeyboardVersionFromKmx(kpsFilename: string, kmp: KmpJsonFile.KmpJsonFile) {
|
||||
// The DEFAULT_VERSION used to be '1.0', but we now use '0.0' to allow
|
||||
// pre-release 0.x keyboards to be considered later than a keyboard without
|
||||
// any version metadata at all.
|
||||
const DEFAULT_VERSION = '0.0';
|
||||
|
||||
// Note: there is often version metadata in the .kps <Keyboard> element, but
|
||||
// we don't read from the metadata because we want to ensure we have the
|
||||
// most up-to-date keyboard version data here, from the compiled keyboard.
|
||||
|
||||
// Lexical model packages do not allow FollowKeyboardVersion
|
||||
if(kmp.lexicalModels && kmp.lexicalModels.length) {
|
||||
this.callbacks.reportMessage(CompilerMessages.Error_FollowKeyboardVersionNotAllowedForModelPackages());
|
||||
return DEFAULT_VERSION;
|
||||
}
|
||||
|
||||
if(!kmp.keyboards || !kmp.keyboards.length) {
|
||||
this.callbacks.reportMessage(CompilerMessages.Warn_FollowKeyboardVersionButNoKeyboards());
|
||||
return DEFAULT_VERSION;
|
||||
}
|
||||
|
||||
// Reset the keyboard version to the default in the kmp.json metadata, for
|
||||
// warning/failure code paths in this file
|
||||
kmp.keyboards[0].version = DEFAULT_VERSION;
|
||||
|
||||
const file = kmp.files.find(file => this.callbacks.path.basename(file.name, '.kmx') == kmp.keyboards[0].id);
|
||||
if(!file) {
|
||||
this.callbacks.reportMessage(CompilerMessages.Error_KeyboardFileNotFound({id:kmp.keyboards[0].id}));
|
||||
return DEFAULT_VERSION;
|
||||
}
|
||||
|
||||
const filename = this.callbacks.resolveFilename(kpsFilename, file.name);
|
||||
if(!this.callbacks.fs.existsSync(filename)) {
|
||||
// The zip phase will emit an error later if the file is missing, so
|
||||
// we can just bail cleanly here
|
||||
// console.debug(`The file ${filename} was not found`);
|
||||
return DEFAULT_VERSION;
|
||||
}
|
||||
|
||||
//
|
||||
// load the .kmx and extract the version number
|
||||
//
|
||||
const kmxFileData = this.callbacks.loadFile(filename);
|
||||
const kmxReader: KmxFileReader = new KmxFileReader();
|
||||
const kmx: KMX.KEYBOARD = kmxReader.read(kmxFileData);
|
||||
if(!kmx) {
|
||||
// The file couldn't be read, it might be invalid or locked
|
||||
this.callbacks.reportMessage(CompilerMessages.Error_KeyboardFileNotValid({filename}));
|
||||
return DEFAULT_VERSION;
|
||||
}
|
||||
|
||||
const store = kmx.stores.find(store => store.dwSystemID == KMX.KMXFile.TSS_KEYBOARDVERSION);
|
||||
if(!store) {
|
||||
// We have no version number store, so use default version
|
||||
this.callbacks.reportMessage(CompilerMessages.Warn_KeyboardFileHasNoKeyboardVersion({filename}));
|
||||
return DEFAULT_VERSION;
|
||||
}
|
||||
|
||||
kmp.keyboards[0].version = store.dpString;
|
||||
return store.dpString;
|
||||
}
|
||||
|
||||
private stripUndefined(o: any) {
|
||||
for(const key in o) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageSpec as m } from "@keymanapp/common-types";
|
||||
|
||||
const Namespace = CompilerErrorNamespace.PackageCompiler;
|
||||
// const SevInfo = CompilerErrorSeverity.Info | Namespace;
|
||||
const SevInfo = CompilerErrorSeverity.Info | Namespace;
|
||||
// const SevHint = CompilerErrorSeverity.Hint | Namespace;
|
||||
const SevWarn = CompilerErrorSeverity.Warn | Namespace;
|
||||
const SevError = CompilerErrorSeverity.Error | Namespace;
|
||||
|
|
@ -31,28 +31,28 @@ export class CompilerMessages {
|
|||
`FollowKeyboardVersion is not allowed in model packages`);
|
||||
static ERROR_FollowKeyboardVersionNotAllowedForModelPackages = SevError | 0x0006;
|
||||
|
||||
static Warn_FollowKeyboardVersionButNoKeyboards = () => m(this.WARN_FollowKeyboardVersionButNoKeyboards,
|
||||
static Error_FollowKeyboardVersionButNoKeyboards = () => m(this.ERROR_FollowKeyboardVersionButNoKeyboards,
|
||||
`FollowKeyboardVersion is set, but the package contains no keyboards`);
|
||||
static WARN_FollowKeyboardVersionButNoKeyboards = SevWarn | 0x0007;
|
||||
static ERROR_FollowKeyboardVersionButNoKeyboards = SevError | 0x0007;
|
||||
|
||||
static Error_KeyboardFileNotFound = (o:{id:string}) => m(this.ERROR_KeyboardFileNotFound,
|
||||
static Error_KeyboardContentFileNotFound = (o:{id:string}) => m(this.ERROR_KeyboardContentFileNotFound,
|
||||
`Keyboard ${o.id} was listed in <Keyboards> but a corresponding .kmx file was not found in <Files>`);
|
||||
static ERROR_KeyboardFileNotFound = SevError | 0x0008;
|
||||
static ERROR_KeyboardContentFileNotFound = SevError | 0x0008;
|
||||
|
||||
static Error_KeyboardFileNotValid = (o:{filename:string}) => m(this.ERROR_KeyboardFileNotValid,
|
||||
`Keyboard file ${o.filename} is not a valid .kmx file`);
|
||||
static ERROR_KeyboardFileNotValid = SevError | 0x0009;
|
||||
|
||||
static Warn_KeyboardFileHasNoKeyboardVersion = (o:{filename:string}) => m(this.WARN_KeyboardFileHasNoKeyboardVersion,
|
||||
`Keyboard file ${o.filename} has no &KeyboardVersion store`);
|
||||
static WARN_KeyboardFileHasNoKeyboardVersion = SevWarn | 0x000A;
|
||||
static Info_KeyboardFileHasNoKeyboardVersion = (o:{filename:string}) => m(this.INFO_KeyboardFileHasNoKeyboardVersion,
|
||||
`Keyboard file ${o.filename} has no &KeyboardVersion store, using default '0.0'`);
|
||||
static INFO_KeyboardFileHasNoKeyboardVersion = SevInfo | 0x000A;
|
||||
|
||||
static Error_PackageCannotContainBothModelsAndKeyboards = () => m(this.ERROR_PackageCannotContainBothModelsAndKeyboards,
|
||||
`The package contains both lexical models and keyboards, which is not permitted.`);
|
||||
static ERROR_PackageCannotContainBothModelsAndKeyboards = SevError | 0x000B;
|
||||
|
||||
static Warn_PackageShouldNotRepeatLanguages = (o:{resourceType: string, id: string, tag: string}) => m(this.WARN_PackageShouldNotRepeatLanguages,
|
||||
`The ${o.resourceType} ${o.id} has a repeated language "${o.tag}".`);
|
||||
static Warn_PackageShouldNotRepeatLanguages = (o:{resourceType: string, id: string, minimalTag: string, firstTag: string, secondTag: string}) => m(this.WARN_PackageShouldNotRepeatLanguages,
|
||||
`Two language tags in ${o.resourceType} ${o.id}, '${o.firstTag}' and '${o.secondTag}', reduce to the same minimal tag '${o.minimalTag}'.`);
|
||||
static WARN_PackageShouldNotRepeatLanguages = SevWarn | 0x000C;
|
||||
|
||||
static Warn_PackageNameDoesNotFollowLexicalModelConventions = (o:{filename: string}) => m(this.WARN_PackageNameDoesNotFollowLexicalModelConventions,
|
||||
|
|
@ -74,5 +74,41 @@ export class CompilerMessages {
|
|||
static Error_PackageNameCannotBeBlank = () => m(this.ERROR_PackageNameCannotBeBlank,
|
||||
`Package name cannot be an empty string.`);
|
||||
static ERROR_PackageNameCannotBeBlank = SevError | 0x0010;
|
||||
|
||||
static Error_KeyboardFileNotFound = (o:{filename:string}) => m(this.ERROR_KeyboardFileNotFound,
|
||||
`Keyboard file ${o.filename} was not found. Has it been compiled?`);
|
||||
static ERROR_KeyboardFileNotFound = SevError | 0x0011;
|
||||
|
||||
static Warn_KeyboardVersionsDoNotMatch = (o: {keyboard:string, version:string, firstKeyboard:string, firstVersion:string}) => m(this.WARN_KeyboardVersionsDoNotMatch,
|
||||
`Keyboard ${o.keyboard} version ${o.version} does not match keyboard ${o.firstKeyboard} version ${o.firstVersion}.`);
|
||||
static WARN_KeyboardVersionsDoNotMatch = SevWarn | 0x0012;
|
||||
|
||||
static Warn_KeyboardVersionsDoNotMatchPackageVersion = (o: {keyboard:string, keyboardVersion: string, packageVersion: string}) => m(this.WARN_KeyboardVersionsDoNotMatchPackageVersion,
|
||||
`Keyboard ${o.keyboard} version ${o.keyboardVersion} does not match package version ${o.packageVersion}.`);
|
||||
static WARN_KeyboardVersionsDoNotMatchPackageVersion = SevWarn | 0x0013;
|
||||
|
||||
static Error_LanguageTagIsNotValid = (o: {resourceType: string, id:string, lang:string, e:any}) => m(this.ERROR_LanguageTagIsNotValid,
|
||||
`Language tag '${o.lang}' in ${o.resourceType} ${o.id} is invalid.`);
|
||||
static ERROR_LanguageTagIsNotValid = SevError | 0x0014;
|
||||
|
||||
static Warn_LanguageTagIsNotMinimal = (o: {resourceType: string, id:string, actual:string, expected:string}) => m(this.WARN_LanguageTagIsNotMinimal,
|
||||
`Language tag '${o.actual}' in ${o.resourceType} ${o.id} is not minimal, and should be '${o.expected}'.`);
|
||||
static WARN_LanguageTagIsNotMinimal = SevWarn | 0x0015;
|
||||
|
||||
static Error_MustHaveAtLeastOneLanguage = (o:{resourceType:string, id:string}) => m(this.ERROR_MustHaveAtLeastOneLanguage,
|
||||
`The ${o.resourceType} ${o.id} must have at least one language specified.`);
|
||||
static ERROR_MustHaveAtLeastOneLanguage = SevError | 0x0016;
|
||||
|
||||
static Warn_RedistFileShouldNotBeInPackage = (o:{filename:string}) => m(this.WARN_RedistFileShouldNotBeInPackage,
|
||||
`The Keyman system file '${o.filename}' should not be compiled into the package.`);
|
||||
static WARN_RedistFileShouldNotBeInPackage = SevWarn | 0x0017;
|
||||
|
||||
static Warn_DocFileDangerous = (o:{filename:string}) => m(this.WARN_DocFileDangerous,
|
||||
`Microsoft Word .doc or .docx files ('${o.filename}') are not portable. You should instead use HTML or PDF format.`);
|
||||
static WARN_DocFileDangerous = SevWarn | 0x0018;
|
||||
|
||||
static Error_PackageMustContainAModelOrAKeyboard = () => m(this.ERROR_PackageMustContainAModelOrAKeyboard,
|
||||
`Package must contain a lexical model or a keyboard.`);
|
||||
static ERROR_PackageMustContainAModelOrAKeyboard = SevError | 0x0019;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { KmpJsonFile, CompilerCallbacks } from '@keymanapp/common-types';
|
||||
import { CompilerMessages } from './messages.js';
|
||||
import { keymanEngineForWindowsFiles, keymanForWindowsInstallerFiles, keymanForWindowsRedistFiles } from './redist-files.js';
|
||||
|
||||
// const SLexicalModelExtension = '.model.js';
|
||||
|
||||
|
|
@ -41,16 +42,38 @@ export class PackageValidation {
|
|||
return true;
|
||||
}
|
||||
|
||||
private checkForDuplicatedLanguages(resourceType: 'keyboard'|'model', id: string, languages: KmpJsonFile.KmpJsonFileLanguage[]) {
|
||||
let tags: {[index:string]: boolean} = {};
|
||||
private checkForDuplicatedOrNonMinimalLanguages(resourceType: 'keyboard'|'model', id: string, languages: KmpJsonFile.KmpJsonFileLanguage[]): boolean {
|
||||
let minimalTags: {[tag: string]: string} = {};
|
||||
|
||||
if(languages.length == 0) {
|
||||
this.callbacks.reportMessage(CompilerMessages.Error_MustHaveAtLeastOneLanguage({resourceType, id}));
|
||||
return false;
|
||||
}
|
||||
|
||||
for(let lang of languages) {
|
||||
const langTag = lang.id.toLowerCase();
|
||||
if(tags[langTag]) {
|
||||
this.callbacks.reportMessage(CompilerMessages.Warn_PackageShouldNotRepeatLanguages({resourceType:resourceType, id:id, tag:lang.id}));
|
||||
} else {
|
||||
tags[langTag] = true;
|
||||
let locale;
|
||||
try {
|
||||
locale = new Intl.Locale(lang.id);
|
||||
} catch(e: any) {
|
||||
this.callbacks.reportMessage(CompilerMessages.Error_LanguageTagIsNotValid({resourceType, id, lang: lang.id, e}));
|
||||
return false;
|
||||
}
|
||||
|
||||
const minimalTag = locale.minimize().toString();
|
||||
|
||||
if(minimalTag.toLowerCase() !== lang.id.toLowerCase()) {
|
||||
this.callbacks.reportMessage(CompilerMessages.Warn_LanguageTagIsNotMinimal({resourceType, id, actual: lang.id, expected: minimalTag}));
|
||||
}
|
||||
|
||||
if(minimalTags[minimalTag]) {
|
||||
this.callbacks.reportMessage(CompilerMessages.Warn_PackageShouldNotRepeatLanguages({resourceType, id, minimalTag, firstTag: lang.id, secondTag: minimalTags[minimalTag]}));
|
||||
}
|
||||
else {
|
||||
minimalTags[minimalTag] = lang.id;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private checkForModelsAndKeyboardsInSamePackage(kmpJson: KmpJsonFile.KmpJsonFile): boolean {
|
||||
|
|
@ -59,6 +82,16 @@ export class PackageValidation {
|
|||
return false;
|
||||
}
|
||||
|
||||
if(!kmpJson.lexicalModels?.length && !kmpJson.keyboards?.length) {
|
||||
// Note: we require at least 1 keyboard or model in the package. This may
|
||||
// change in the future if we start to use packages to distribute, e.g.
|
||||
// localizations or themes.
|
||||
this.callbacks.reportMessage(CompilerMessages.Error_PackageMustContainAModelOrAKeyboard());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -74,7 +107,9 @@ export class PackageValidation {
|
|||
}
|
||||
|
||||
for(let model of kmpJson.lexicalModels) {
|
||||
this.checkForDuplicatedLanguages('model', model.id, model.languages);
|
||||
if(!this.checkForDuplicatedOrNonMinimalLanguages('model', model.id, model.languages)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -92,7 +127,9 @@ export class PackageValidation {
|
|||
}
|
||||
|
||||
for(let keyboard of kmpJson.keyboards) {
|
||||
this.checkForDuplicatedLanguages('keyboard', keyboard.id, keyboard.languages);
|
||||
if(!this.checkForDuplicatedOrNonMinimalLanguages('keyboard', keyboard.id, keyboard.languages)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -116,6 +153,23 @@ export class PackageValidation {
|
|||
this.callbacks.reportMessage(CompilerMessages.Warn_FileInPackageDoesNotFollowFilenameConventions({filename}));
|
||||
}
|
||||
|
||||
if(!this.checkIfContentFileIsDangerous(file)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private checkIfContentFileIsDangerous(file: KmpJsonFile.KmpJsonFileContentFile): boolean {
|
||||
let filename = this.callbacks.path.basename(file.name).toLowerCase();
|
||||
if(keymanForWindowsInstallerFiles.includes(filename) ||
|
||||
keymanForWindowsRedistFiles.includes(filename) ||
|
||||
keymanEngineForWindowsFiles.includes(filename)) {
|
||||
this.callbacks.reportMessage(CompilerMessages.Warn_RedistFileShouldNotBeInPackage({filename}));
|
||||
}
|
||||
if(filename.match(/\.doc(x?)$/)) {
|
||||
this.callbacks.reportMessage(CompilerMessages.Warn_DocFileDangerous({filename}));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,139 @@
|
|||
import { KmpJsonFile, CompilerCallbacks, KpsFile, KmxFileReader, KMX } from '@keymanapp/common-types';
|
||||
import { CompilerMessages } from './messages.js';
|
||||
|
||||
export class PackageVersionValidation {
|
||||
|
||||
constructor(private callbacks: CompilerCallbacks) {}
|
||||
|
||||
/**
|
||||
* Verifies version information in corresponding keyboards and updates kmpJson
|
||||
* metadata as the version information can be out of sync in the .kps file
|
||||
* after updating a contained keyboard.
|
||||
* @param kpsFilename
|
||||
* @param kps
|
||||
* @param kmp
|
||||
* @returns
|
||||
*/
|
||||
public validateAndUpdateVersions(kpsFilename: string, kps: KpsFile.KpsFile, kmp: KmpJsonFile.KmpJsonFile) {
|
||||
const followKeyboardVersion = kps.options?.followKeyboardVersion !== undefined;
|
||||
|
||||
if(followKeyboardVersion) {
|
||||
if(!this.checkFollowKeyboardVersion(kps, kmp)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!kmp.keyboards) {
|
||||
// Lexical models don't have version metadata; only their packages.
|
||||
return true;
|
||||
}
|
||||
|
||||
let result = true;
|
||||
|
||||
// We now know we have at least one keyboard in the package
|
||||
|
||||
for(let keyboard of kmp.keyboards) {
|
||||
result = this.updateKeyboardVersionFromKmx(kpsFilename, kmp, keyboard) && result;
|
||||
if(result) {
|
||||
if(kmp.keyboards[0].version !== keyboard.version) {
|
||||
this.callbacks.reportMessage(CompilerMessages.Warn_KeyboardVersionsDoNotMatch({
|
||||
keyboard:keyboard.id,
|
||||
version:keyboard.version,
|
||||
firstKeyboard:kmp.keyboards[0].id,
|
||||
firstVersion:kmp.keyboards[0].version
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(result) {
|
||||
if(followKeyboardVersion) {
|
||||
kmp.info.version.description = kmp.keyboards[0].version;
|
||||
}
|
||||
else if(kmp.info.version?.description != kmp.keyboards[0].version) {
|
||||
// Only need to compare against first keyboard as we compare keyboards above
|
||||
this.callbacks.reportMessage(CompilerMessages.Warn_KeyboardVersionsDoNotMatchPackageVersion({
|
||||
keyboard: kmp.keyboards[0].id,
|
||||
keyboardVersion: kmp.keyboards[0].version,
|
||||
packageVersion: kmp.info.version?.description
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private checkFollowKeyboardVersion(kps: KpsFile.KpsFile, kmp: KmpJsonFile.KmpJsonFile) {
|
||||
// Lexical model packages do not allow FollowKeyboardVersion
|
||||
if(kmp.lexicalModels && kmp.lexicalModels.length) {
|
||||
this.callbacks.reportMessage(CompilerMessages.Error_FollowKeyboardVersionNotAllowedForModelPackages());
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!kmp.keyboards || !kmp.keyboards.length) {
|
||||
this.callbacks.reportMessage(CompilerMessages.Error_FollowKeyboardVersionButNoKeyboards());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private updateKeyboardVersionFromKmx(
|
||||
kpsFilename: string,
|
||||
kmp: KmpJsonFile.KmpJsonFile,
|
||||
keyboard: KmpJsonFile.KmpJsonFileKeyboard
|
||||
): boolean {
|
||||
// The DEFAULT_VERSION used to be '1.0', but we now use '0.0' to allow
|
||||
// pre-release 0.x keyboards to be considered later than a keyboard without
|
||||
// any version metadata at all.
|
||||
const DEFAULT_VERSION = '0.0';
|
||||
|
||||
// Note: there is often version metadata in the .kps <Keyboard> element, but
|
||||
// we don't read from the metadata because we want to ensure we have the
|
||||
// most up-to-date keyboard version data here, from the compiled keyboard.
|
||||
|
||||
// Reset the keyboard version to the default in the kmp.json metadata, for
|
||||
// warning/failure code paths in this file
|
||||
keyboard.version = DEFAULT_VERSION;
|
||||
|
||||
const file = kmp.files.find(file => this.callbacks.path.basename(file.name, '.kmx') == keyboard.id);
|
||||
if(!file) {
|
||||
this.callbacks.reportMessage(CompilerMessages.Error_KeyboardContentFileNotFound({id:keyboard.id}));
|
||||
return false;
|
||||
}
|
||||
|
||||
const filename = this.callbacks.resolveFilename(kpsFilename, file.name);
|
||||
if(!this.callbacks.fs.existsSync(filename)) {
|
||||
this.callbacks.reportMessage(CompilerMessages.Error_KeyboardFileNotFound({filename}));
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// load the .kmx and extract the version number
|
||||
//
|
||||
let kmxFileData;
|
||||
try {
|
||||
kmxFileData = this.callbacks.loadFile(filename);
|
||||
} catch(e) {
|
||||
this.callbacks.reportMessage(CompilerMessages.Error_FileCouldNotBeRead({filename, e}));
|
||||
return false;
|
||||
}
|
||||
const kmxReader: KmxFileReader = new KmxFileReader();
|
||||
const kmx: KMX.KEYBOARD = kmxReader.read(kmxFileData);
|
||||
if(!kmx) {
|
||||
// The file couldn't be read, it might not be a .kmx file
|
||||
this.callbacks.reportMessage(CompilerMessages.Error_KeyboardFileNotValid({filename}));
|
||||
return false;
|
||||
}
|
||||
|
||||
const store = kmx.stores.find(store => store.dwSystemID == KMX.KMXFile.TSS_KEYBOARDVERSION);
|
||||
if(!store) {
|
||||
// We have no version number store, so use default version
|
||||
this.callbacks.reportMessage(CompilerMessages.Info_KeyboardFileHasNoKeyboardVersion({filename}));
|
||||
return true;
|
||||
}
|
||||
|
||||
keyboard.version = store.dpString;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
64
developer/src/kmc-package/src/compiler/redist-files.ts
Normal file
64
developer/src/kmc-package/src/compiler/redist-files.ts
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
|
||||
/**
|
||||
* This is a set of known redistributable files for Keyman for Windows that
|
||||
* should not be included in packages. It is not critical that this list matches
|
||||
* the current deployment; it is just for warning against accidental inclusion
|
||||
* of these files by package authors. Some redistributable files have been
|
||||
* intentionally excluded because they could legitimately be a different file
|
||||
* with the same name.
|
||||
*
|
||||
* This matches behaviour from the legacy package compiler; we may want to
|
||||
* reconsider how this is done in the future.
|
||||
*
|
||||
* These lists have been constructed from 17.0.109 alpha build. Filenames
|
||||
* intentionally in lower case.
|
||||
*/
|
||||
|
||||
export const
|
||||
keymanForWindowsInstallerFiles: string[] = [
|
||||
'keymandesktop.msi',
|
||||
'keymanengine.msm'
|
||||
];
|
||||
|
||||
|
||||
export const
|
||||
keymanEngineForWindowsFiles: string[] = [
|
||||
'base.xslt',
|
||||
'crashpad_handler.exe',
|
||||
'keyman-debug-etw.man',
|
||||
'keyman.exe',
|
||||
'keyman32.dll',
|
||||
'keyman64.dll',
|
||||
'keymanmc.dll',
|
||||
'keymanx64.exe',
|
||||
'kmcomapi.dll',
|
||||
'kmcomapi.x64.dll',
|
||||
'kmrefresh.x64.exe',
|
||||
'kmrefresh.x86.exe',
|
||||
'kmtip.dll',
|
||||
'kmtip64.dll',
|
||||
'mcompile.exe',
|
||||
'sentry.dll',
|
||||
'sentry.x64.dll',
|
||||
'si_browsers.xslt',
|
||||
'si_fonts.xslt',
|
||||
'si_hookdlls.xslt',
|
||||
'si_keyman.xslt',
|
||||
'si_language.xslt',
|
||||
'si_office.xslt',
|
||||
'si_overview.xslt',
|
||||
'si_processes.xslt',
|
||||
'si_processes_x64.xslt',
|
||||
'si_startup.xslt',
|
||||
'tsysinfo.exe',
|
||||
];
|
||||
|
||||
export const
|
||||
keymanForWindowsRedistFiles: string[] = [
|
||||
'desktop_resources.dll',
|
||||
'keymandesktop.chm',
|
||||
'kmbrowserhost.exe',
|
||||
'kmconfig.exe',
|
||||
'kmshell.exe',
|
||||
'unicodedata.mdb',
|
||||
];
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
</StartMenu>
|
||||
<Info>
|
||||
<Name URL="">Binary KVK File</Name>
|
||||
<Version>1.3</Version>
|
||||
</Info>
|
||||
<Files>
|
||||
<File>
|
||||
|
|
@ -25,5 +26,21 @@
|
|||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.kvk</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>../../invalid/khmer_angkor.kmx</Name>
|
||||
<Description>Keyboard Khmer Angkor</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.kmx</FileType>
|
||||
</File>
|
||||
</Files>
|
||||
<Keyboards>
|
||||
<Keyboard>
|
||||
<Name>Khmer Angkor</Name>
|
||||
<ID>khmer_angkor</ID>
|
||||
<Version>1.3</Version>
|
||||
<Languages>
|
||||
<Language ID="KM">Khmer</Language>
|
||||
</Languages>
|
||||
</Keyboard>
|
||||
</Keyboards>
|
||||
</Package>
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@
|
|||
<Name URL="">SENĆOŦEN (Saanich Dialect) Lexical Model</Name>
|
||||
<Copyright URL="">© 2019 National Research Council Canada</Copyright>
|
||||
<Author URL="mailto:Eddie.Santos@nrc-cnrc.gc.ca">Eddie Antonio Santos</Author>
|
||||
<Version>1.0.3</Version>
|
||||
<Version>1.3</Version>
|
||||
</Info>
|
||||
<Files>
|
||||
<File>
|
||||
<Name>nokeyboardversion.kmx</Name>
|
||||
<Name>khmer_angkor.kmx</Name>
|
||||
<Description>Keyboard Khmer Angkor</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.kmx</FileType>
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
<Keyboards>
|
||||
<Keyboard>
|
||||
<Name>Khmer Angkor</Name>
|
||||
<ID>nokeyboardversion</ID>
|
||||
<ID>khmer_angkor</ID>
|
||||
<Version>1.3</Version>
|
||||
<Languages>
|
||||
<Language ID="km">Central Khmer (Khmer, Cambodia)</Language>
|
||||
|
|
|
|||
32
developer/src/kmc-package/test/fixtures/invalid/error_language_tag_is_not_valid.kps
vendored
Normal file
32
developer/src/kmc-package/test/fixtures/invalid/error_language_tag_is_not_valid.kps
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package>
|
||||
<System>
|
||||
<KeymanDeveloperVersion>15.0.266.0</KeymanDeveloperVersion>
|
||||
<FileVersion>7.0</FileVersion>
|
||||
</System>
|
||||
<Info>
|
||||
<Name URL="">SENĆOŦEN (Saanich Dialect) Lexical Model</Name>
|
||||
<Copyright URL="">© 2019 National Research Council Canada</Copyright>
|
||||
<Author URL="mailto:Eddie.Santos@nrc-cnrc.gc.ca">Eddie Antonio Santos</Author>
|
||||
<Version>1.3</Version>
|
||||
</Info>
|
||||
<Files>
|
||||
<File>
|
||||
<Name>khmer_angkor.kmx</Name>
|
||||
<Description>Keyboard Khmer Angkor</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.kmx</FileType>
|
||||
</File>
|
||||
</Files>
|
||||
<Keyboards>
|
||||
<Keyboard>
|
||||
<Name>Khmer Angkor</Name>
|
||||
<ID>khmer_angkor</ID>
|
||||
<Version>1.3</Version>
|
||||
<Languages>
|
||||
<!-- ERROR_LanguageTagIsNotValid -->
|
||||
<Language ID="en-au-latn">English (Australian script) as spoken in Latin</Language>
|
||||
</Languages>
|
||||
</Keyboard>
|
||||
</Keyboards>
|
||||
</Package>
|
||||
|
|
@ -8,12 +8,12 @@
|
|||
<Name URL="">Khmer Angkor</Name>
|
||||
<Copyright URL="">© 2015-2022 SIL International</Copyright>
|
||||
<Author URL="mailto:makara_sok@sil.org">Makara Sok</Author>
|
||||
<Version URL=""></Version>
|
||||
<Version URL="">1.3</Version>
|
||||
<WebSite URL="https://keyman.com/keyboards/khmer_angkor">https://keyman.com/keyboards/khmer_angkor</WebSite>
|
||||
</Info>
|
||||
<Files>
|
||||
<File>
|
||||
<Name>nokeyboardversion.kmx</Name>
|
||||
<Name>khmer_angkor.kmx</Name>
|
||||
<Description>Keyboard Khmer Angkor</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.kmx</FileType>
|
||||
|
|
@ -39,7 +39,7 @@
|
|||
<Keyboards>
|
||||
<Keyboard>
|
||||
<Name>Khmer Angkor</Name>
|
||||
<ID>nokeyboardversion</ID>
|
||||
<ID>khmer_angkor</ID>
|
||||
<Version>1.3</Version>
|
||||
<Languages>
|
||||
<Language ID="km">Central Khmer (Khmer, Cambodia)</Language>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package>
|
||||
<System>
|
||||
<KeymanDeveloperVersion>15.0.266.0</KeymanDeveloperVersion>
|
||||
<FileVersion>7.0</FileVersion>
|
||||
</System>
|
||||
<Info>
|
||||
<Name URL="">error_package_must_contain_a_model_or_a_keyboard</Name>
|
||||
<Version>1.3</Version>
|
||||
</Info>
|
||||
<Files>
|
||||
<File>
|
||||
<!-- error_package_must_contain_a_model_or_a_keyboard. This is a common error:
|
||||
to include a .kmn instead of a .kmx -->
|
||||
<Name>khmer_angkor.kmn</Name>
|
||||
<Description>Keyboard Khmer Angkor</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.kmn</FileType>
|
||||
</File>
|
||||
</Files>
|
||||
</Package>
|
||||
|
|
@ -9,11 +9,11 @@
|
|||
<Name URL=""> </Name>
|
||||
<Copyright URL="">© 2019 National Research Council Canada</Copyright>
|
||||
<Author URL="mailto:Eddie.Santos@nrc-cnrc.gc.ca">Eddie Antonio Santos</Author>
|
||||
<Version>1.0.3</Version>
|
||||
<Version>1.3</Version>
|
||||
</Info>
|
||||
<Files>
|
||||
<File>
|
||||
<Name>nokeyboardversion.kmx</Name>
|
||||
<Name>khmer_angkor.kmx</Name>
|
||||
<Description>Keyboard Khmer Angkor</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.kmx</FileType>
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
<Keyboards>
|
||||
<Keyboard>
|
||||
<Name>Khmer Angkor</Name>
|
||||
<ID>nokeyboardversion</ID>
|
||||
<ID>khmer_angkor</ID>
|
||||
<Version>1.3</Version>
|
||||
<Languages>
|
||||
<Language ID="km">Central Khmer (Khmer, Cambodia)</Language>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<!-- missing <Name/> -->
|
||||
<Copyright URL="">© 2019 National Research Council Canada</Copyright>
|
||||
<Author URL="mailto:Eddie.Santos@nrc-cnrc.gc.ca">Eddie Antonio Santos</Author>
|
||||
<Version>1.0.3</Version>
|
||||
<Version>1.3</Version>
|
||||
</Info>
|
||||
<Files>
|
||||
<File>
|
||||
<Name>nokeyboardversion.kmx</Name>
|
||||
<Name>khmer_angkor.kmx</Name>
|
||||
<Description>Keyboard Khmer Angkor</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.kmx</FileType>
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
<Keyboards>
|
||||
<Keyboard>
|
||||
<Name>Khmer Angkor</Name>
|
||||
<ID>nokeyboardversion</ID>
|
||||
<ID>khmer_angkor</ID>
|
||||
<Version>1.3</Version>
|
||||
<Languages>
|
||||
<Language ID="km">Central Khmer (Khmer, Cambodia)</Language>
|
||||
|
|
|
|||
128
developer/src/kmc-package/test/fixtures/invalid/keyboardcontentfilenotfound.kps
vendored
Normal file
128
developer/src/kmc-package/test/fixtures/invalid/keyboardcontentfilenotfound.kps
vendored
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package>
|
||||
<System>
|
||||
<KeymanDeveloperVersion>15.0.266.0</KeymanDeveloperVersion>
|
||||
<FileVersion>7.0</FileVersion>
|
||||
</System>
|
||||
<Options>
|
||||
<ExecuteProgram></ExecuteProgram>
|
||||
<ReadMeFile>readme.htm</ReadMeFile>
|
||||
<GraphicFile>splash.gif</GraphicFile>
|
||||
<MSIFileName></MSIFileName>
|
||||
<MSIOptions></MSIOptions>
|
||||
<FollowKeyboardVersion/>
|
||||
</Options>
|
||||
<StartMenu>
|
||||
<Folder></Folder>
|
||||
<Items/>
|
||||
</StartMenu>
|
||||
<Info>
|
||||
<Name URL="">Khmer Angkor</Name>
|
||||
<Copyright URL="">© 2015-2022 SIL International</Copyright>
|
||||
<Author URL="mailto:makara_sok@sil.org">Makara Sok</Author>
|
||||
<Version URL=""></Version>
|
||||
<WebSite URL="https://keyman.com/keyboards/khmer_angkor">https://keyman.com/keyboards/khmer_angkor</WebSite>
|
||||
</Info>
|
||||
<Files>
|
||||
<!-- missing .kmx triggers this warning: We're moving towards requiring .kmx
|
||||
even for mobile-only keyboards, and have made the decision not to attempt
|
||||
to parse .js for the kmp compiler, because it is too fragile. -->
|
||||
<File>
|
||||
<Name>..\build\khmer_angkor.js</Name>
|
||||
<Description>File khmer_angkor.js</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.js</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>..\build\khmer_angkor.kvk</Name>
|
||||
<Description>File khmer_angkor.kvk</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.kvk</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>welcome\keyboard_layout.png</Name>
|
||||
<Description>File keyboard_layout.png</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.png</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>welcome\welcome.htm</Name>
|
||||
<Description>File welcome.htm</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.htm</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>..\shared\fonts\khmer\mondulkiri\FONTLOG.txt</Name>
|
||||
<Description>File FONTLOG.txt</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.txt</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>..\shared\fonts\khmer\mondulkiri\Mondulkiri-R.ttf</Name>
|
||||
<Description>Font Khmer Mondulkiri</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.ttf</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>..\shared\fonts\khmer\mondulkiri\OFL.txt</Name>
|
||||
<Description>File OFL.txt</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.txt</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>..\shared\fonts\khmer\mondulkiri\OFL-FAQ.txt</Name>
|
||||
<Description>File OFL-FAQ.txt</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.txt</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>welcome\KAK_Documentation_EN.pdf</Name>
|
||||
<Description>File KAK_Documentation_EN.pdf</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.pdf</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>welcome\KAK_Documentation_KH.pdf</Name>
|
||||
<Description>File KAK_Documentation_KH.pdf</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.pdf</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>readme.htm</Name>
|
||||
<Description>File readme.htm</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.htm</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>welcome\image002.png</Name>
|
||||
<Description>File image002.png</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.png</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>..\shared\fonts\khmer\busrakbd\khmer_busra_kbd.ttf</Name>
|
||||
<Description>Font KhmerBusraKbd</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.ttf</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>splash.gif</Name>
|
||||
<Description>File splash.gif</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.gif</FileType>
|
||||
</File>
|
||||
</Files>
|
||||
<Keyboards>
|
||||
<Keyboard>
|
||||
<Name>Khmer Angkor</Name>
|
||||
<ID>khmer_angkor</ID>
|
||||
<Version>1.3</Version>
|
||||
<OSKFont>..\shared\fonts\khmer\busrakbd\khmer_busra_kbd.ttf</OSKFont>
|
||||
<DisplayFont>..\shared\fonts\khmer\mondulkiri\Mondulkiri-R.ttf</DisplayFont>
|
||||
<Languages>
|
||||
<Language ID="km">Central Khmer (Khmer, Cambodia)</Language>
|
||||
</Languages>
|
||||
</Keyboard>
|
||||
</Keyboards>
|
||||
<Strings/>
|
||||
</Package>
|
||||
|
|
@ -5,11 +5,6 @@
|
|||
<FileVersion>7.0</FileVersion>
|
||||
</System>
|
||||
<Options>
|
||||
<ExecuteProgram></ExecuteProgram>
|
||||
<ReadMeFile>readme.htm</ReadMeFile>
|
||||
<GraphicFile>splash.gif</GraphicFile>
|
||||
<MSIFileName></MSIFileName>
|
||||
<MSIOptions></MSIOptions>
|
||||
<FollowKeyboardVersion/>
|
||||
</Options>
|
||||
<StartMenu>
|
||||
|
|
@ -25,97 +20,18 @@
|
|||
</Info>
|
||||
<Files>
|
||||
<File>
|
||||
<Name>..\build\khmer_angkor.js</Name>
|
||||
<Description>File khmer_angkor.js</Description>
|
||||
<!-- File is missing -->
|
||||
<Name>keyboardfilenotfound.kmx</Name>
|
||||
<Description>Keyboard Khmer Angkor</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.js</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>..\build\khmer_angkor.kvk</Name>
|
||||
<Description>File khmer_angkor.kvk</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.kvk</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>welcome\keyboard_layout.png</Name>
|
||||
<Description>File keyboard_layout.png</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.png</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>welcome\welcome.htm</Name>
|
||||
<Description>File welcome.htm</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.htm</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>..\shared\fonts\khmer\mondulkiri\FONTLOG.txt</Name>
|
||||
<Description>File FONTLOG.txt</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.txt</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>..\shared\fonts\khmer\mondulkiri\Mondulkiri-R.ttf</Name>
|
||||
<Description>Font Khmer Mondulkiri</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.ttf</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>..\shared\fonts\khmer\mondulkiri\OFL.txt</Name>
|
||||
<Description>File OFL.txt</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.txt</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>..\shared\fonts\khmer\mondulkiri\OFL-FAQ.txt</Name>
|
||||
<Description>File OFL-FAQ.txt</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.txt</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>welcome\KAK_Documentation_EN.pdf</Name>
|
||||
<Description>File KAK_Documentation_EN.pdf</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.pdf</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>welcome\KAK_Documentation_KH.pdf</Name>
|
||||
<Description>File KAK_Documentation_KH.pdf</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.pdf</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>readme.htm</Name>
|
||||
<Description>File readme.htm</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.htm</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>welcome\image002.png</Name>
|
||||
<Description>File image002.png</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.png</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>..\shared\fonts\khmer\busrakbd\khmer_busra_kbd.ttf</Name>
|
||||
<Description>Font KhmerBusraKbd</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.ttf</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>splash.gif</Name>
|
||||
<Description>File splash.gif</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.gif</FileType>
|
||||
<FileType>.kmx</FileType>
|
||||
</File>
|
||||
</Files>
|
||||
<Keyboards>
|
||||
<Keyboard>
|
||||
<Name>Khmer Angkor</Name>
|
||||
<ID>khmer_angkor</ID>
|
||||
<ID>keyboardfilenotfound</ID>
|
||||
<Version>1.3</Version>
|
||||
<OSKFont>..\shared\fonts\khmer\busrakbd\khmer_busra_kbd.ttf</OSKFont>
|
||||
<DisplayFont>..\shared\fonts\khmer\mondulkiri\Mondulkiri-R.ttf</DisplayFont>
|
||||
<Languages>
|
||||
<Language ID="km">Central Khmer (Khmer, Cambodia)</Language>
|
||||
</Languages>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package>
|
||||
<System>
|
||||
<KeymanDeveloperVersion>15.0.266.0</KeymanDeveloperVersion>
|
||||
<FileVersion>7.0</FileVersion>
|
||||
</System>
|
||||
<Info>
|
||||
<Name URL="">SENĆOŦEN (Saanich Dialect) Lexical Model</Name>
|
||||
<Copyright URL="">© 2019 National Research Council Canada</Copyright>
|
||||
<Author URL="mailto:Eddie.Santos@nrc-cnrc.gc.ca">Eddie Antonio Santos</Author>
|
||||
<Version>1.0.3</Version>
|
||||
</Info>
|
||||
<Files>
|
||||
<File>
|
||||
<Name>example.qaa.sencoten.model.js</Name>
|
||||
<Description>Lexical model example.qaa.sencoten.model.js</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.model.js</FileType>
|
||||
</File>
|
||||
</Files>
|
||||
<LexicalModels>
|
||||
<LexicalModel>
|
||||
<Name>SENĆOŦEN dictionary</Name>
|
||||
<ID>example.qaa.sencoten</ID>
|
||||
<!-- ERROR_LexicalModelMustHaveAtLeastOneLanguage -->
|
||||
</LexicalModel>
|
||||
</LexicalModels>
|
||||
</Package>
|
||||
BIN
developer/src/kmc-package/test/fixtures/invalid/khmer_angkor.kmx
vendored
Normal file
BIN
developer/src/kmc-package/test/fixtures/invalid/khmer_angkor.kmx
vendored
Normal file
Binary file not shown.
BIN
developer/src/kmc-package/test/fixtures/invalid/my special keyboard.kmx
vendored
Normal file
BIN
developer/src/kmc-package/test/fixtures/invalid/my special keyboard.kmx
vendored
Normal file
Binary file not shown.
BIN
developer/src/kmc-package/test/fixtures/invalid/my_special-keyboard.kmx
vendored
Normal file
BIN
developer/src/kmc-package/test/fixtures/invalid/my_special-keyboard.kmx
vendored
Normal file
Binary file not shown.
6
developer/src/kmc-package/test/fixtures/invalid/version_four.kmn
vendored
Normal file
6
developer/src/kmc-package/test/fixtures/invalid/version_four.kmn
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
store(&name) 'version 4'
|
||||
store(&keyboardversion) '4.0'
|
||||
|
||||
begin unicode > use(main)
|
||||
|
||||
group(main) using keys
|
||||
BIN
developer/src/kmc-package/test/fixtures/invalid/version_four.kmx
vendored
Normal file
BIN
developer/src/kmc-package/test/fixtures/invalid/version_four.kmx
vendored
Normal file
Binary file not shown.
38
developer/src/kmc-package/test/fixtures/invalid/warn_doc_file_dangerous.kps
vendored
Normal file
38
developer/src/kmc-package/test/fixtures/invalid/warn_doc_file_dangerous.kps
vendored
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package>
|
||||
<System>
|
||||
<KeymanDeveloperVersion>15.0.266.0</KeymanDeveloperVersion>
|
||||
<FileVersion>7.0</FileVersion>
|
||||
</System>
|
||||
<Info>
|
||||
<Name URL="">SENĆOŦEN (Saanich Dialect) Lexical Model</Name>
|
||||
<Copyright URL="">© 2019 National Research Council Canada</Copyright>
|
||||
<Author URL="mailto:Eddie.Santos@nrc-cnrc.gc.ca">Eddie Antonio Santos</Author>
|
||||
<Version>1.3</Version>
|
||||
</Info>
|
||||
<Files>
|
||||
<File>
|
||||
<Name>khmer_angkor.kmx</Name>
|
||||
<Description>Keyboard Khmer Angkor</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.kmx</FileType>
|
||||
</File>
|
||||
<!-- warn_doc_file_dangerous -->
|
||||
<File>
|
||||
<Name>khmer_angkor.docx</Name>
|
||||
<Description>Documentation</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.docx</FileType>
|
||||
</File>
|
||||
</Files>
|
||||
<Keyboards>
|
||||
<Keyboard>
|
||||
<Name>Khmer Angkor</Name>
|
||||
<ID>khmer_angkor</ID>
|
||||
<Version>1.3</Version>
|
||||
<Languages>
|
||||
<Language ID="KM">Khmer</Language>
|
||||
</Languages>
|
||||
</Keyboard>
|
||||
</Keyboards>
|
||||
</Package>
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
<Name URL="">SENĆOŦEN (Saanich Dialect) Lexical Model</Name>
|
||||
<Copyright URL="">© 2019 National Research Council Canada</Copyright>
|
||||
<Author URL="mailto:Eddie.Santos@nrc-cnrc.gc.ca">Eddie Antonio Santos</Author>
|
||||
<Version>1.0.3</Version>
|
||||
<Version>1.3</Version>
|
||||
</Info>
|
||||
<Files>
|
||||
<File>
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
<Keyboards>
|
||||
<Keyboard>
|
||||
<Name>Khmer Angkor</Name>
|
||||
<ID>nokeyboardversion</ID>
|
||||
<ID>my special keyboard</ID>
|
||||
<Version>1.3</Version>
|
||||
<Languages>
|
||||
<Language ID="km">Central Khmer (Khmer, Cambodia)</Language>
|
||||
|
|
|
|||
|
|
@ -8,12 +8,19 @@
|
|||
<Name URL="">SENĆOŦEN (Saanich Dialect) Lexical Model</Name>
|
||||
<Copyright URL="">© 2019 National Research Council Canada</Copyright>
|
||||
<Author URL="mailto:Eddie.Santos@nrc-cnrc.gc.ca">Eddie Antonio Santos</Author>
|
||||
<Version>1.0.3</Version>
|
||||
<Version>1.3</Version>
|
||||
</Info>
|
||||
<Files>
|
||||
<File>
|
||||
<!-- extension should not have capitals -->
|
||||
<Name>my_special-keyboard.KMX</Name>
|
||||
<Name>my_file.PDF</Name>
|
||||
<Description>My Documentation</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.PDF</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<!-- extension should not have capitals -->
|
||||
<Name>khmer_angkor.kmx</Name>
|
||||
<Description>Keyboard my special keyboard</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.kmx</FileType>
|
||||
|
|
@ -22,7 +29,7 @@
|
|||
<Keyboards>
|
||||
<Keyboard>
|
||||
<Name>Khmer Angkor</Name>
|
||||
<ID>nokeyboardversion</ID>
|
||||
<ID>khmer_angkor</ID>
|
||||
<Version>1.3</Version>
|
||||
<Languages>
|
||||
<Language ID="km">Central Khmer (Khmer, Cambodia)</Language>
|
||||
|
|
|
|||
45
developer/src/kmc-package/test/fixtures/invalid/warn_keyboard_versions_do_not_match.kps
vendored
Normal file
45
developer/src/kmc-package/test/fixtures/invalid/warn_keyboard_versions_do_not_match.kps
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package>
|
||||
<System>
|
||||
<KeymanDeveloperVersion>15.0.266.0</KeymanDeveloperVersion>
|
||||
<FileVersion>7.0</FileVersion>
|
||||
</System>
|
||||
<Info>
|
||||
<Name URL="">SENĆOŦEN (Saanich Dialect) Lexical Model</Name>
|
||||
<Copyright URL="">© 2019 National Research Council Canada</Copyright>
|
||||
<Author URL="mailto:Eddie.Santos@nrc-cnrc.gc.ca">Eddie Antonio Santos</Author>
|
||||
<Version>1.3</Version>
|
||||
</Info>
|
||||
<Files>
|
||||
<File>
|
||||
<Name>khmer_angkor.kmx</Name>
|
||||
<Description>Keyboard Khmer Angkor</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.kmx</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>version_four.kmx</Name>
|
||||
<Description>Keyboard Version Four</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.kmx</FileType>
|
||||
</File>
|
||||
</Files>
|
||||
<Keyboards>
|
||||
<Keyboard>
|
||||
<Name>Khmer Angkor</Name>
|
||||
<ID>khmer_angkor</ID>
|
||||
<Version>1.3</Version>
|
||||
<Languages>
|
||||
<Language ID="km">Khmer</Language>
|
||||
</Languages>
|
||||
</Keyboard>
|
||||
<Keyboard>
|
||||
<Name>Version 4</Name>
|
||||
<ID>version_four</ID>
|
||||
<Version>4.0</Version>
|
||||
<Languages>
|
||||
<Language ID="km">Khmer</Language>
|
||||
</Languages>
|
||||
</Keyboard>
|
||||
</Keyboards>
|
||||
</Package>
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package>
|
||||
<System>
|
||||
<KeymanDeveloperVersion>15.0.266.0</KeymanDeveloperVersion>
|
||||
<FileVersion>7.0</FileVersion>
|
||||
</System>
|
||||
<Info>
|
||||
<Name URL="">SENĆOŦEN (Saanich Dialect) Lexical Model</Name>
|
||||
<Copyright URL="">© 2019 National Research Council Canada</Copyright>
|
||||
<Author URL="mailto:Eddie.Santos@nrc-cnrc.gc.ca">Eddie Antonio Santos</Author>
|
||||
<Version>1.3</Version>
|
||||
</Info>
|
||||
<Files>
|
||||
<File>
|
||||
<Name>version_four.kmx</Name>
|
||||
<Description>Keyboard Version Four</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.kmx</FileType>
|
||||
</File>
|
||||
</Files>
|
||||
<Keyboards>
|
||||
<Keyboard>
|
||||
<Name>Version 4</Name>
|
||||
<ID>version_four</ID>
|
||||
<Version>4.0</Version>
|
||||
<Languages>
|
||||
<Language ID="km">Khmer</Language>
|
||||
</Languages>
|
||||
</Keyboard>
|
||||
</Keyboards>
|
||||
</Package>
|
||||
|
|
@ -4,10 +4,15 @@
|
|||
<KeymanDeveloperVersion>15.0.266.0</KeymanDeveloperVersion>
|
||||
<FileVersion>7.0</FileVersion>
|
||||
</System>
|
||||
<!-- Missing <Info>/<Name/> -->
|
||||
<Info>
|
||||
<Name URL="">SENĆOŦEN (Saanich Dialect) Lexical Model</Name>
|
||||
<Copyright URL="">© 2019 National Research Council Canada</Copyright>
|
||||
<Author URL="mailto:Eddie.Santos@nrc-cnrc.gc.ca">Eddie Antonio Santos</Author>
|
||||
<Version>1.3</Version>
|
||||
</Info>
|
||||
<Files>
|
||||
<File>
|
||||
<Name>nokeyboardversion.kmx</Name>
|
||||
<Name>khmer_angkor.kmx</Name>
|
||||
<Description>Keyboard Khmer Angkor</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.kmx</FileType>
|
||||
|
|
@ -16,10 +21,11 @@
|
|||
<Keyboards>
|
||||
<Keyboard>
|
||||
<Name>Khmer Angkor</Name>
|
||||
<ID>nokeyboardversion</ID>
|
||||
<ID>khmer_angkor</ID>
|
||||
<Version>1.3</Version>
|
||||
<Languages>
|
||||
<Language ID="km">Central Khmer (Khmer, Cambodia)</Language>
|
||||
<!-- WARN_LanguageTagIsNotMinimal -->
|
||||
<Language ID="km-Khmr-KH">Central Khmer (Khmer, Cambodia)</Language>
|
||||
</Languages>
|
||||
</Keyboard>
|
||||
</Keyboards>
|
||||
|
|
@ -8,11 +8,11 @@
|
|||
<Name URL="">SENĆOŦEN (Saanich Dialect) Lexical Model</Name>
|
||||
<Copyright URL="">© 2019 National Research Council Canada</Copyright>
|
||||
<Author URL="mailto:Eddie.Santos@nrc-cnrc.gc.ca">Eddie Antonio Santos</Author>
|
||||
<Version>1.0.3</Version>
|
||||
<Version>1.3</Version>
|
||||
</Info>
|
||||
<Files>
|
||||
<File>
|
||||
<Name>nokeyboardversion.kmx</Name>
|
||||
<Name>khmer_angkor.kmx</Name>
|
||||
<Description>Keyboard Khmer Angkor</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.kmx</FileType>
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
<Keyboards>
|
||||
<Keyboard>
|
||||
<Name>Khmer Angkor</Name>
|
||||
<ID>nokeyboardversion</ID>
|
||||
<ID>khmer_angkor</ID>
|
||||
<Version>1.3</Version>
|
||||
<Languages>
|
||||
<!-- WARN_PackageShouldNotRepeatLanguages -->
|
||||
|
|
|
|||
38
developer/src/kmc-package/test/fixtures/invalid/warn_redist_file_should_not_be_in_package.kps
vendored
Normal file
38
developer/src/kmc-package/test/fixtures/invalid/warn_redist_file_should_not_be_in_package.kps
vendored
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package>
|
||||
<System>
|
||||
<KeymanDeveloperVersion>15.0.266.0</KeymanDeveloperVersion>
|
||||
<FileVersion>7.0</FileVersion>
|
||||
</System>
|
||||
<Info>
|
||||
<Name URL="">SENĆOŦEN (Saanich Dialect) Lexical Model</Name>
|
||||
<Copyright URL="">© 2019 National Research Council Canada</Copyright>
|
||||
<Author URL="mailto:Eddie.Santos@nrc-cnrc.gc.ca">Eddie Antonio Santos</Author>
|
||||
<Version>1.3</Version>
|
||||
</Info>
|
||||
<Files>
|
||||
<File>
|
||||
<Name>khmer_angkor.kmx</Name>
|
||||
<Description>Keyboard Khmer Angkor</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.kmx</FileType>
|
||||
</File>
|
||||
<!-- warn_redist_file_should_not_be_in_package -->
|
||||
<File>
|
||||
<Name>keyman.exe</Name>
|
||||
<Description>Keyman Program</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.exe</FileType>
|
||||
</File>
|
||||
</Files>
|
||||
<Keyboards>
|
||||
<Keyboard>
|
||||
<Name>Khmer Angkor</Name>
|
||||
<ID>khmer_angkor</ID>
|
||||
<Version>1.3</Version>
|
||||
<Languages>
|
||||
<Language ID="KM">Khmer</Language>
|
||||
</Languages>
|
||||
</Keyboard>
|
||||
</Keyboards>
|
||||
</Package>
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
</StartMenu>
|
||||
<Info>
|
||||
<Name URL="">XML KVK File</Name>
|
||||
<Version>1.3</Version>
|
||||
</Info>
|
||||
<Files>
|
||||
<File>
|
||||
|
|
@ -25,5 +26,21 @@
|
|||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.kvk</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>../../invalid/khmer_angkor.kmx</Name>
|
||||
<Description>Keyboard Khmer Angkor</Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.kmx</FileType>
|
||||
</File>
|
||||
</Files>
|
||||
<Keyboards>
|
||||
<Keyboard>
|
||||
<Name>Khmer Angkor</Name>
|
||||
<ID>khmer_angkor</ID>
|
||||
<Version>1.3</Version>
|
||||
<Languages>
|
||||
<Language ID="KM">Khmer</Language>
|
||||
</Languages>
|
||||
</Keyboard>
|
||||
</Keyboards>
|
||||
</Package>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ import { KmpCompiler } from '../src/compiler/kmp-compiler.js';
|
|||
import { PackageValidation } from '../src/compiler/package-validation.js';
|
||||
import { CompilerMessages } from '../src/compiler/messages.js';
|
||||
|
||||
const debug = true;
|
||||
|
||||
describe('KmpCompiler', function () {
|
||||
const MODELS : string[] = [
|
||||
'example.qaa.sencoten',
|
||||
|
|
@ -141,6 +143,8 @@ describe('KmpCompiler', function () {
|
|||
|
||||
await assert.isNull(kmpCompiler.buildKmpFile(kpsPath, kmpJson));
|
||||
|
||||
if(debug) callbacks.printMessages();
|
||||
|
||||
assert.lengthOf(callbacks.messages, 2);
|
||||
assert.deepEqual(callbacks.messages[0].code, CompilerMessages.WARN_AbsolutePath);
|
||||
assert.deepEqual(callbacks.messages[1].code, CompilerMessages.ERROR_FileDoesNotExist);
|
||||
|
|
@ -169,7 +173,7 @@ describe('KmpCompiler', function () {
|
|||
kmpCompiler.buildKmpFile(kpsPath, kmpJson)
|
||||
}
|
||||
|
||||
//TODO: callbacks.printMessages(); after #8711 is merged
|
||||
if(debug) callbacks.printMessages();
|
||||
|
||||
if(messageId) {
|
||||
assert.lengthOf(callbacks.messages, 1);
|
||||
|
|
@ -195,16 +199,16 @@ describe('KmpCompiler', function () {
|
|||
testForMessage(this, ['invalid', 'followkeyboardversion.qaa.sencoten.model.kps'], CompilerMessages.ERROR_FollowKeyboardVersionNotAllowedForModelPackages);
|
||||
});
|
||||
|
||||
// WARN_FollowKeyboardVersionButNoKeyboards
|
||||
// ERROR_FollowKeyboardVersionButNoKeyboards
|
||||
|
||||
it('should generate WARN_FollowKeyboardVersionButNoKeyboards if <FollowKeyboardVersion> is set for a package with no keyboards or models', async function() {
|
||||
testForMessage(this, ['invalid', 'followkeyboardversion.empty.kps'], CompilerMessages.WARN_FollowKeyboardVersionButNoKeyboards);
|
||||
it('should generate ERROR_FollowKeyboardVersionButNoKeyboards if <FollowKeyboardVersion> is set for a package with no keyboards', async function() {
|
||||
testForMessage(this, ['invalid', 'followkeyboardversion.empty.kps'], CompilerMessages.ERROR_FollowKeyboardVersionButNoKeyboards);
|
||||
});
|
||||
|
||||
// ERROR_KeyboardFileNotFound
|
||||
// ERROR_KeyboardContentFileNotFound
|
||||
|
||||
it('should generate ERROR_KeyboardFileNotFound if a <Keyboard> is listed in a package but not found in <Files>', async function() {
|
||||
testForMessage(this, ['invalid', 'keyboardfilenotfound.kps'], CompilerMessages.ERROR_KeyboardFileNotFound);
|
||||
it('should generate ERROR_KeyboardContentFileNotFound if a <Keyboard> is listed in a package but not found in <Files>', async function() {
|
||||
testForMessage(this, ['invalid', 'keyboardcontentfilenotfound.kps'], CompilerMessages.ERROR_KeyboardContentFileNotFound);
|
||||
});
|
||||
|
||||
// ERROR_KeyboardFileNotValid
|
||||
|
|
@ -213,16 +217,16 @@ describe('KmpCompiler', function () {
|
|||
testForMessage(this, ['invalid', 'keyboardfilenotvalid.kps'], CompilerMessages.ERROR_KeyboardFileNotValid);
|
||||
});
|
||||
|
||||
// WARN_KeyboardFileHasNoKeyboardVersion
|
||||
// INFO_KeyboardFileHasNoKeyboardVersion
|
||||
|
||||
it('should generate WARN_KeyboardFileHasNoKeyboardVersion if <FollowKeyboardVersion> is set but keyboard has no version', async function() {
|
||||
testForMessage(this, ['invalid', 'nokeyboardversion.kps'], CompilerMessages.WARN_KeyboardFileHasNoKeyboardVersion);
|
||||
it('should generate INFO_KeyboardFileHasNoKeyboardVersion if <FollowKeyboardVersion> is set but keyboard has no version', async function() {
|
||||
testForMessage(this, ['invalid', 'nokeyboardversion.kps'], CompilerMessages.INFO_KeyboardFileHasNoKeyboardVersion);
|
||||
});
|
||||
|
||||
// ERROR_PackageCannotContainBothModelsAndKeyboards
|
||||
|
||||
it('should generate ERROR_PackageCannotContainBothModelsAndKeyboards if package has both keyboards and models', async function() {
|
||||
testForMessage(this, ['invalid', 'ERROR_PackageCannotContainBothModelsAndKeyboards.kps'], CompilerMessages.ERROR_PackageCannotContainBothModelsAndKeyboards);
|
||||
testForMessage(this, ['invalid', 'error_package_cannot_contain_both_models_and_keyboards.kps'], CompilerMessages.ERROR_PackageCannotContainBothModelsAndKeyboards);
|
||||
});
|
||||
|
||||
// WARN_PackageShouldNotRepeatLanguages (models)
|
||||
|
|
@ -261,7 +265,63 @@ describe('KmpCompiler', function () {
|
|||
it('should generate ERROR_PackageNameCannotBeBlank if package info has empty name', async function() {
|
||||
testForMessage(this, ['invalid', 'error_package_name_cannot_be_blank.kps'], CompilerMessages.ERROR_PackageNameCannotBeBlank); // blank field
|
||||
testForMessage(this, ['invalid', 'error_package_name_cannot_be_blank_2.kps'], CompilerMessages.ERROR_PackageNameCannotBeBlank); // missing field
|
||||
testForMessage(this, ['invalid', 'error_package_name_cannot_be_blank_3.kps'], CompilerMessages.ERROR_PackageNameCannotBeBlank); // missing info section
|
||||
});
|
||||
|
||||
// ERROR_KeyboardFileNotFound
|
||||
|
||||
it('should generate ERROR_KeyboardFileNotFound if a <Keyboard> is listed in a package but not found in <Files>', async function() {
|
||||
testForMessage(this, ['invalid', 'keyboardfilenotfound.kps'], CompilerMessages.ERROR_KeyboardFileNotFound);
|
||||
});
|
||||
|
||||
// WARN_KeyboardVersionsDoNotMatch
|
||||
|
||||
it('should generate WARN_KeyboardVersionsDoNotMatch if two <Keyboards> have different versions', async function() {
|
||||
testForMessage(this, ['invalid', 'warn_keyboard_versions_do_not_match.kps'], CompilerMessages.WARN_KeyboardVersionsDoNotMatch);
|
||||
});
|
||||
|
||||
// WARN_KeyboardVersionsDoNotMatchPackageVersion
|
||||
|
||||
it('should generate WARN_KeyboardVersionsDoNotMatchPackageVersion if <Keyboard> version does not match package version', async function() {
|
||||
testForMessage(this, ['invalid', 'warn_keyboard_versions_do_not_match_package_version.kps'], CompilerMessages.WARN_KeyboardVersionsDoNotMatchPackageVersion);
|
||||
});
|
||||
|
||||
// ERROR_LanguageTagIsNotValid
|
||||
|
||||
it('should generate ERROR_LanguageTagIsNotValid if keyboard has an invalid language tag', async function() {
|
||||
testForMessage(this, ['invalid', 'error_language_tag_is_not_valid.kps'], CompilerMessages.ERROR_LanguageTagIsNotValid);
|
||||
});
|
||||
|
||||
// WARN_LanguageTagIsNotMinimal
|
||||
|
||||
it('should generate WARN_LanguageTagIsNotMinimal if keyboard has a non-minimal language tag', async function() {
|
||||
testForMessage(this, ['invalid', 'warn_language_tag_is_not_minimal.kps'], CompilerMessages.WARN_LanguageTagIsNotMinimal);
|
||||
});
|
||||
|
||||
// ERROR_MustHaveAtLeastOneLanguage
|
||||
|
||||
it('should generate ERROR_MustHaveAtLeastOneLanguage if model or keyboard has zero language tags', async function() {
|
||||
testForMessage(this, ['invalid', 'keyman.en.error_must_have_at_least_one_language.model.kps'],
|
||||
CompilerMessages.ERROR_MustHaveAtLeastOneLanguage);
|
||||
});
|
||||
|
||||
// WARN_RedistFileShouldNotBeInPackage
|
||||
|
||||
it('should generate WARN_RedistFileShouldNotBeInPackage if package contains a redist file', async function() {
|
||||
testForMessage(this, ['invalid', 'warn_redist_file_should_not_be_in_package.kps'],
|
||||
CompilerMessages.WARN_RedistFileShouldNotBeInPackage);
|
||||
});
|
||||
|
||||
// WARN_DocFileDangerous
|
||||
|
||||
it('should generate WARN_DocFileDangerous if package contains a .doc file', async function() {
|
||||
testForMessage(this, ['invalid', 'warn_doc_file_dangerous.kps'],
|
||||
CompilerMessages.WARN_DocFileDangerous);
|
||||
});
|
||||
|
||||
// ERROR_PackageMustContainAPackageOrAKeyboard
|
||||
|
||||
it('should generate ERROR_PackageMustContainAModelOrAKeyboard if package contains a .doc file', async function() {
|
||||
testForMessage(this, ['invalid', 'error_package_must_contain_a_model_or_a_keyboard.kps'],
|
||||
CompilerMessages.ERROR_PackageMustContainAModelOrAKeyboard);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import * as path from 'path';
|
||||
import { BuildActivity, BuildActivityOptions } from './BuildActivity.js';
|
||||
import { Compiler } from '@keymanapp/kmc-kmn';
|
||||
import { KmnCompiler } from '@keymanapp/kmc-kmn';
|
||||
import { platform } from 'os';
|
||||
import { CompilerCallbacks } from '@keymanapp/common-types';
|
||||
|
||||
|
|
@ -10,8 +10,8 @@ export class BuildKmnKeyboard extends BuildActivity {
|
|||
public get compiledExtension(): string { return '.kmx'; }
|
||||
public get description(): string { return 'Build a Keyman keyboard'; }
|
||||
public async build(infile: string, callbacks: CompilerCallbacks, options: BuildActivityOptions): Promise<boolean> {
|
||||
let compiler = new Compiler();
|
||||
if(!await compiler.init()) {
|
||||
let compiler = new KmnCompiler();
|
||||
if(!await compiler.init(callbacks)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -23,7 +23,7 @@ export class BuildKmnKeyboard extends BuildActivity {
|
|||
|
||||
// TODO: Currently this only builds .kmn->.kmx, and targeting .js is as-yet unsupported
|
||||
// TODO: Support additional options compilerWarningsAsErrors, warnDeprecatedCode
|
||||
return compiler.run(infile, outfile, callbacks,
|
||||
return compiler.run(infile, outfile,
|
||||
{
|
||||
saveDebug: options.debug,
|
||||
shouldAddCompilerVersion: options.compilerVersion,
|
||||
|
|
@ -49,4 +49,4 @@ function getPosixAbsolutePath(filename: string): string {
|
|||
filename = filename.replace(/\\/g, '/');
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as kmc from '@keymanapp/kmc-ldml';
|
||||
import * as kmcLdml from '@keymanapp/kmc-ldml';
|
||||
import { KvkFileWriter, CompilerCallbacks } from '@keymanapp/common-types';
|
||||
import { BuildActivity, BuildActivityOptions } from './BuildActivity.js';
|
||||
|
||||
|
|
@ -43,14 +43,14 @@ export class BuildLdmlKeyboard extends BuildActivity {
|
|||
}
|
||||
|
||||
function buildLdmlKeyboardToMemory(inputFilename: string, callbacks: CompilerCallbacks, options: BuildActivityOptions): [Uint8Array, Uint8Array, Uint8Array] {
|
||||
let compilerOptions: kmc.CompilerOptions = {
|
||||
let compilerOptions: kmcLdml.CompilerOptions = {
|
||||
debug: options.debug ?? false,
|
||||
addCompilerVersion: options.compilerVersion ?? true,
|
||||
// TODO: warnDeprecatedCode: options.warnDeprecatedCode,
|
||||
// TODO: treatWarningsAsErrors: options.treatWarningsAsErrors,
|
||||
}
|
||||
|
||||
const k = new kmc.Compiler(callbacks, options);
|
||||
const k = new kmcLdml.LdmlKeyboardCompiler(callbacks, options);
|
||||
let source = k.load(inputFilename);
|
||||
if (!source) {
|
||||
return [null, null, null];
|
||||
|
|
@ -62,13 +62,13 @@ function buildLdmlKeyboardToMemory(inputFilename: string, callbacks: CompilerCal
|
|||
|
||||
// In order for the KMX file to be loaded by non-KMXPlus components, it is helpful
|
||||
// to duplicate some of the metadata
|
||||
kmc.KMXPlusMetadataCompiler.addKmxMetadata(kmx.kmxplus, kmx.keyboard, compilerOptions);
|
||||
kmcLdml.KMXPlusMetadataCompiler.addKmxMetadata(kmx.kmxplus, kmx.keyboard, compilerOptions);
|
||||
|
||||
// Use the builder to generate the binary output file
|
||||
const builder = new kmc.KMXBuilder(kmx, options.debug);
|
||||
const builder = new kmcLdml.KMXBuilder(kmx, options.debug);
|
||||
const kmx_binary = builder.compile();
|
||||
|
||||
const vkcompiler = new kmc.VisualKeyboardCompiler();
|
||||
const vkcompiler = new kmcLdml.LdmlKeyboardVisualKeyboardCompiler();
|
||||
const vk = vkcompiler.compile(source);
|
||||
const writer = new KvkFileWriter();
|
||||
const kvk_binary = writer.write(vk);
|
||||
|
|
@ -78,7 +78,7 @@ function buildLdmlKeyboardToMemory(inputFilename: string, callbacks: CompilerCal
|
|||
// const tlcompiler = new kmc.TouchLayoutCompiler();
|
||||
// const tl = tlcompiler.compile(source);
|
||||
// const tlwriter = new TouchLayoutFileWriter();
|
||||
const kmwcompiler = new kmc.KeymanWebCompiler(callbacks, compilerOptions);
|
||||
const kmwcompiler = new kmcLdml.LdmlKeyboardKeymanWebCompiler(callbacks, compilerOptions);
|
||||
const kmw_string = kmwcompiler.compile(inputFilename, source);
|
||||
const encoder = new TextEncoder();
|
||||
const kmw_binary = encoder.encode(kmw_string);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ export function buildTestData(infile: string, options: BuildTestDataOptions) {
|
|||
|
||||
function loadTestData(inputFilename: string, options: kmc.CompilerOptions): LDMLKeyboardTestDataXMLSourceFile {
|
||||
const c: CompilerCallbacks = new NodeCompilerCallbacks();
|
||||
const k = new kmc.Compiler(c, options);
|
||||
const k = new kmc.LdmlKeyboardCompiler(c, options);
|
||||
let source = k.loadTestData(inputFilename);
|
||||
if (!source) {
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -48,6 +48,9 @@ let jsFilename = program.opts().jsFilename ? program.opts().jsFilename : path.jo
|
|||
const callbacks = new NodeCompilerCallbacks();
|
||||
let kmpCompiler = new KmpCompiler(callbacks);
|
||||
let kmpJsonData = kmpCompiler.transformKpsToKmpObject(kpsFilename);
|
||||
if(!kmpJsonData) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
//
|
||||
// Validate the package file
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
<Name URL="">k_000___null_keyboard</Name>
|
||||
<Copyright URL="">Copyright (C) Keyman Team</Copyright>
|
||||
<Author URL="">Keyman Team</Author>
|
||||
<Version URL=""></Version>
|
||||
<Version URL="">0.0</Version>
|
||||
</Info>
|
||||
<Files>
|
||||
<File>
|
||||
|
|
|
|||
|
|
@ -16,8 +16,9 @@ describe('BuildProject', function () {
|
|||
debug: false,
|
||||
warnDeprecatedCode: true,
|
||||
});
|
||||
// 4 messages == starting build, build successful x 2
|
||||
assert.equal(callbacks.messages.length, 4);
|
||||
// 5 messages == starting build, info: no keyboard version, build successful x 2
|
||||
// callbacks.printMessages();
|
||||
assert.equal(callbacks.messages.length, 5);
|
||||
assert.isTrue(result);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -76,14 +76,10 @@ static const int KMCMP_ERROR_HAS_STRINGS = -2;
|
|||
* Error: Invalid, uses properties \p{Mn} or [:Mn:]
|
||||
*/
|
||||
static const int KMCMP_ERROR_UNSUPPORTED_PROPERTY = -3;
|
||||
/**
|
||||
* Error: Invalid, other unsupported feature
|
||||
*/
|
||||
static const int KMCMP_ERROR_UNSUPPORTED = -4;
|
||||
/**
|
||||
* Fatal: output buffer too small
|
||||
*/
|
||||
static const int KMCMP_FATAL_OUT_OF_RANGE = -5;
|
||||
static const int KMCMP_FATAL_OUT_OF_RANGE = -4;
|
||||
|
||||
/**
|
||||
* Function pointer to kmcmp_ParseUnicodeSet
|
||||
|
|
|
|||
|
|
@ -65,6 +65,15 @@ EXTERN bool kmcmp_Wasm_CompileKeyboardFile(char* pszInfile,
|
|||
msgProc
|
||||
);
|
||||
}
|
||||
|
||||
EXTERN int kmcmp_Wasm_ParseUnicodeSet(char* pat,
|
||||
uint32_t* buf, int length
|
||||
) {
|
||||
return kmcmp_ParseUnicodeSet(
|
||||
pat, buf, length
|
||||
);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
EXTERN bool kmcmp_CompileKeyboardFile(char* pszInfile,
|
||||
|
|
@ -365,4 +374,4 @@ bool CompileKeyboardHandle(FILE* fp_in, PFILE_KEYBOARD fk)
|
|||
kmcmp::CheckForDeprecatedFeatures(fk);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,108 +0,0 @@
|
|||
unit keyman32_int;
|
||||
|
||||
interface
|
||||
|
||||
uses Windows, SysUtils, Forms;
|
||||
|
||||
function Keyman_Initialise(Handle: HWND; FSingleApp: Boolean): Boolean;
|
||||
function Keyman_Exit: Boolean;
|
||||
function Keyman_ForceKeyboard(const s: string): Boolean;
|
||||
function Keyman_StopForcingKeyboard: Boolean;
|
||||
|
||||
implementation
|
||||
|
||||
uses TikeUtils;
|
||||
|
||||
type TKeyman_ForceKeyboard = function (s: PChar): Boolean; stdcall;
|
||||
type TKeyman_StopForcingKeyboard = function: Boolean; stdcall;
|
||||
type TKeyman_Initialise = function(h: THandle; FSingleApp: LongBool): Boolean; stdcall;
|
||||
type TKeyman_Exit = function: Boolean; stdcall;
|
||||
|
||||
var
|
||||
FInitKeyman: Boolean = False;
|
||||
FKeyman32Path: string = '';
|
||||
|
||||
function Keyman_Initialise(Handle: HWND; FSingleApp: Boolean): Boolean;
|
||||
var
|
||||
hkeyman: THandle;
|
||||
FLoad: Boolean;
|
||||
ki: TKeyman_Initialise;
|
||||
begin
|
||||
Result := False;
|
||||
FLoad := False;
|
||||
hkeyman := GetModuleHandle('keyman32.dll');
|
||||
if hkeyman = 0 then
|
||||
begin
|
||||
hkeyman := LoadLibrary(PChar(GetKeymanInstallPath+'keyman32.dll'));
|
||||
if hkeyman = 0 then Exit;
|
||||
FLoad := True;
|
||||
end;
|
||||
ki := TKeyman_Initialise(GetProcAddress(hkeyman, 'Keyman_Initialise'));
|
||||
if not Assigned(@ki) then Exit;
|
||||
if not ki(Handle, FSingleApp) then
|
||||
begin
|
||||
if FLoad then FreeLibrary(hkeyman);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
FInitKeyman := True;
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
function Keyman_Exit: Boolean;
|
||||
var
|
||||
hkeyman: THandle;
|
||||
ke: TKeyman_Exit;
|
||||
begin
|
||||
if not FInitKeyman then
|
||||
begin
|
||||
Result := True;
|
||||
Exit;
|
||||
end;
|
||||
Result := False;
|
||||
hkeyman := GetModuleHandle('keyman32.dll');
|
||||
if hkeyman = 0 then Exit;
|
||||
ke := TKeyman_Exit(GetProcAddress(hkeyman, 'Keyman_Exit'));
|
||||
if not Assigned(@ke) then Exit;
|
||||
if not ke then Exit;
|
||||
if FInitKeyman then FreeLibrary(hkeyman);
|
||||
FInitKeyman := False;
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
function Keyman_ForceKeyboard(const s: string): Boolean;
|
||||
var
|
||||
hkeyman: THandle;
|
||||
fk: TKeyman_ForceKeyboard;
|
||||
begin
|
||||
Result := False;
|
||||
hkeyman := GetModuleHandle('keyman32.dll');
|
||||
if hkeyman = 0 then
|
||||
begin
|
||||
if not Keyman_Initialise(Application.MainForm.Handle, True) then Exit;
|
||||
hkeyman := GetModuleHandle('keyman32.dll');
|
||||
if hkeyman = 0 then Exit;
|
||||
end;
|
||||
fk := TKeyman_ForceKeyboard(GetProcAddress(hkeyman, 'Keyman_ForceKeyboard'));
|
||||
if(Assigned(@fk)) then
|
||||
Result := fk(PChar(s));
|
||||
end;
|
||||
|
||||
function Keyman_StopForcingKeyboard: Boolean;
|
||||
var
|
||||
hkeyman: THandle;
|
||||
sfk: TKeyman_StopForcingKeyboard;
|
||||
begin
|
||||
Result := False;
|
||||
hkeyman := GetModuleHandle('keyman32.dll');
|
||||
if hkeyman = 0 then Exit;
|
||||
sfk := TKeyman_StopForcingKeyboard(GetProcAddress(hkeyman, 'Keyman_StopForcingKeyboard'));
|
||||
if(Assigned(@sfk)) then
|
||||
Result := sfk;
|
||||
Keyman_Exit;
|
||||
end;
|
||||
|
||||
initialization
|
||||
finalization
|
||||
Keyman_Exit;
|
||||
end.
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
github "marmelroy/Zip"
|
||||
github "DaveWoodCom/XCGLogger" ~> 6.1.0
|
||||
github "keymanapp/dependency-XCGLogger" "master"
|
||||
github "devicekit/DeviceKit" ~> 5.0
|
||||
github "ashleymills/Reachability.swift"
|
||||
github "getsentry/sentry-cocoa" ~> 6.2.1
|
||||
github "getsentry/sentry-cocoa" ~> 8.7.0
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
github "DaveWoodCom/XCGLogger" "6.1.0"
|
||||
github "ashleymills/Reachability.swift" "v5.1.0"
|
||||
github "devicekit/DeviceKit" "5.0.0"
|
||||
github "getsentry/sentry-cocoa" "6.2.1"
|
||||
github "getsentry/sentry-cocoa" "8.7.0"
|
||||
github "keymanapp/dependency-XCGLogger" "57a7b975dbb6fe4fe90cef3d1bc52b8adbd89113"
|
||||
github "marmelroy/Zip" "2.1.2"
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ public class SentryManager {
|
|||
public static func breadcrumbAndLog(crumb: Sentry.Breadcrumb, logLevel: XCGLogger.Level? = nil) {
|
||||
// Guarded in case a library consumer decides against initializing Sentry.
|
||||
if _started {
|
||||
SentrySDK.addBreadcrumb(crumb: crumb)
|
||||
SentrySDK.addBreadcrumb(crumb)
|
||||
}
|
||||
|
||||
let level = logLevel ?? mapLoggingLevel(crumb.level)
|
||||
|
|
@ -193,7 +193,7 @@ public class SentryManager {
|
|||
}
|
||||
|
||||
public static func forceError() {
|
||||
SentrySDK.addBreadcrumb(crumb: Sentry.Breadcrumb(level: .info, category: "Deliberate testing error"))
|
||||
SentrySDK.addBreadcrumb(Sentry.Breadcrumb(level: .info, category: "Deliberate testing error"))
|
||||
SentrySDK.crash()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
|
||||
# Don't call `set -e`. Even if some commands should fail, it's still
|
||||
# worth running the rest of the commands.
|
||||
# Exit on errors - Debian policy 10.4
|
||||
set -e
|
||||
|
||||
case "$1" in
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ case "$1" in
|
|||
if which sudo > /dev/null && which ps > /dev/null; then
|
||||
|
||||
# check for gnome-shell as it works differently
|
||||
gspid=$(ps -C gnome-shell -o pid=|head -n 1)
|
||||
! gspid=$(ps -C gnome-shell -o pid=|head -n 1)
|
||||
if [ "$gspid" != "" ]; then
|
||||
# gnome-shell has multiple ibus-daemon processes and needs exit instead of restart
|
||||
is_gnome_shell=1
|
||||
|
|
@ -21,7 +21,7 @@ case "$1" in
|
|||
fi
|
||||
|
||||
# Restart IBus if it is running
|
||||
ibuspid=$(ps -C ibus-daemon -o pid=|head -n 1)
|
||||
! ibuspid=$(ps -C ibus-daemon -o pid=|head -n 1)
|
||||
|
||||
if [ "$ibuspid" != "" ]; then
|
||||
if [ "$is_gnome_shell" = "1" ]; then
|
||||
|
|
@ -41,7 +41,7 @@ case "$1" in
|
|||
|
||||
# Verify that it's running now
|
||||
if [ -n "$SUDO_USER" ] && id "$SUDO_USER" > /dev/null 2>/dev/null; then
|
||||
ibusdaemon=$(ps --user "$SUDO_USER" -o s= -o cmd | grep --regexp="^[^ZT] \(/usr/bin/\)\?ibus-daemon .*--xim.*")
|
||||
! ibusdaemon=$(ps --user "$SUDO_USER" -o s= -o cmd | grep --regexp="^[^ZT] \(/usr/bin/\)\?ibus-daemon .*--xim.*")
|
||||
if [ "$ibusdaemon" = "" ]; then
|
||||
# otherwise try to start it for the user installing the package
|
||||
if [ "$is_gnome_shell" = "1" ]; then
|
||||
|
|
|
|||
|
|
@ -6,7 +6,14 @@ default: clean version man langtags
|
|||
langtags:
|
||||
cd buildtools && python3 ./build-langtags.py
|
||||
|
||||
install: # run as sudo
|
||||
install:
|
||||
if [ -n "${SUDO_USER}" ]; then \
|
||||
make install-sudo; \
|
||||
else \
|
||||
make install-temp; \
|
||||
fi
|
||||
|
||||
install-sudo: # run as sudo
|
||||
pip3 install qrcode sentry-sdk
|
||||
# eventually change this to: pip3 install .
|
||||
python3 setup.py install
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
github "DaveWoodCom/XCGLogger" ~> 6.1.0
|
||||
github "keymanapp/dependency-XCGLogger" "master"
|
||||
github "devicekit/DeviceKit" ~> 5.0
|
||||
github "ashleymills/Reachability.swift"
|
||||
github "getsentry/sentry-cocoa" ~> 6.2.1
|
||||
github "getsentry/sentry-cocoa" ~> 8.7.0
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
github "DaveWoodCom/XCGLogger" "6.1.0"
|
||||
github "ashleymills/Reachability.swift" "v5.1.0"
|
||||
github "devicekit/DeviceKit" "5.0.0"
|
||||
github "getsentry/sentry-cocoa" "6.2.1"
|
||||
github "getsentry/sentry-cocoa" "8.7.0"
|
||||
github "keymanapp/dependency-XCGLogger" "57a7b975dbb6fe4fe90cef3d1bc52b8adbd89113"
|
||||
|
|
|
|||
|
|
@ -359,7 +359,7 @@ _builder_failure_trap() {
|
|||
# finishes.
|
||||
#
|
||||
_builder_cleanup_deps() {
|
||||
if ! builder_is_dep_build && [[ ! -z ${_builder_deps_built+x} ]]; then
|
||||
if ! builder_is_dep_build && ! builder_is_child_build && [[ ! -z ${_builder_deps_built+x} ]]; then
|
||||
if $_builder_debug_internal; then
|
||||
builder_echo_debug "Dependencies that were built:"
|
||||
cat "$_builder_deps_built"
|
||||
|
|
@ -558,7 +558,6 @@ builder_has_action() {
|
|||
function builder_run_action() {
|
||||
local action=$1
|
||||
shift
|
||||
echo "builder_run_action $action $@"
|
||||
if builder_start_action $action; then
|
||||
($@)
|
||||
builder_finish_action success $action
|
||||
|
|
@ -1758,6 +1757,7 @@ builder_has_dependencies() {
|
|||
builder_has_module_been_built() {
|
||||
local module="$1"
|
||||
|
||||
|
||||
if [[ -z ${_builder_deps_built+x} ]]; then
|
||||
# not in a builder context, so we assume a build is needed
|
||||
return 1
|
||||
|
|
|
|||
|
|
@ -6,10 +6,6 @@
|
|||
"types": "./build/engine/attachment/obj/index.d.ts",
|
||||
"import": "./build/engine/attachment/obj/index.js"
|
||||
},
|
||||
"./engine/attachment/lib": {
|
||||
"types": "./build/engine/attachment/obj/index.d.ts",
|
||||
"import": "./build/engine/attachment/lib/index.mjs"
|
||||
},
|
||||
"./engine/paths": {
|
||||
"types": "./build/engine/paths/obj/index.d.ts",
|
||||
"import": "./build/engine/paths/obj/index.js"
|
||||
|
|
@ -18,10 +14,6 @@
|
|||
"types": "./build/engine/device-detect/obj/index.d.ts",
|
||||
"import": "./build/engine/device-detect/obj/index.js"
|
||||
},
|
||||
"./engine/device-detect/lib": {
|
||||
"types": "./build/engine/device-detect/lib/index.d.ts",
|
||||
"import": "./build/engine/device-detect/lib/index.mjs"
|
||||
},
|
||||
"./engine/dom-utils": {
|
||||
"types": "./build/engine/dom-utils/obj/index.d.ts",
|
||||
"import": "./build/engine/dom-utils/obj/index.js"
|
||||
|
|
@ -30,10 +22,6 @@
|
|||
"types": "./build/engine/element-wrappers/obj/index.d.ts",
|
||||
"import": "./build/engine/element-wrappers/obj/index.js"
|
||||
},
|
||||
"./engine/element-wrappers/lib": {
|
||||
"types": "./build/engine/element-wrappers/lib/index.d.ts",
|
||||
"import": "./build/engine/element-wrappers/lib/index.mjs"
|
||||
},
|
||||
"./engine/events": {
|
||||
"types": "./build/engine/events/obj/index.d.ts",
|
||||
"import": "./build/engine/events/obj/index.js"
|
||||
|
|
@ -43,41 +31,21 @@
|
|||
"import": "./build/engine/package-cache/obj/index.js",
|
||||
"require": "./build/engine/package-cache/obj/index.js"
|
||||
},
|
||||
"./engine/package-cache/lib": {
|
||||
"types": "./build/engine/package-cache/lib/index.d.ts",
|
||||
"import": "./build/engine/package-cache/lib/index.mjs"
|
||||
},
|
||||
"./engine/package-cache/dom-requester": {
|
||||
"types": "./build/engine/package-cache/obj/domCloudRequester.d.ts",
|
||||
"import": "./build/engine/package-cache/obj/domCloudRequester.js"
|
||||
},
|
||||
"./engine/package-cache/dom-requester/lib": {
|
||||
"types": "./build/engine/package-cache/lib/index.d.ts",
|
||||
"import": "./build/engine/package-cache/lib/dom-cloud-requester.mjs"
|
||||
},
|
||||
"./engine/package-cache/node-requester": {
|
||||
"types": "./build/engine/package-cache/obj/nodeCloudRequester.d.ts",
|
||||
"import": "./build/engine/package-cache/obj/nodeCloudRequester.js"
|
||||
},
|
||||
"./engine/package-cache/node-requester/lib": {
|
||||
"types": "./build/engine/package-cache/lib/index.d.ts",
|
||||
"import": "./build/engine/package-cache/lib/node-cloud-requester.mjs"
|
||||
},
|
||||
"./engine/main": {
|
||||
"types": "./build/engine/main/obj/index.d.ts",
|
||||
"import": "./build/engine/main/obj/index.js"
|
||||
},
|
||||
"./engine/main/lib": {
|
||||
"types": "./build/engine/main/lib/index.d.ts",
|
||||
"import": "./build/engine/main/lib/index.mjs"
|
||||
},
|
||||
"./engine/osk": {
|
||||
"types": "./build/engine/osk/obj/index.d.ts",
|
||||
"import": "./build/engine/osk/obj/index.js"
|
||||
},
|
||||
"./engine/osk/lib": {
|
||||
"types": "./build/engine/osk/lib/index.d.ts",
|
||||
"import": "./build/engine/osk/lib/index.mjs"
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
|
|
|
|||
|
|
@ -34,24 +34,24 @@ export default class DefaultBrowserRules extends DefaultRules {
|
|||
applyCommand(Lkc: KeyEvent, outputTarget: OutputTarget): void {
|
||||
let code = this.codeForEvent(Lkc);
|
||||
|
||||
const contextManager = this.contextManager;
|
||||
const moveToNext = (back: boolean) => {
|
||||
const contextManager = this.contextManager;
|
||||
const activeElement = contextManager.activeTarget?.getElement();
|
||||
const nextElement = contextManager.page.findNeighboringInput(activeElement, back);
|
||||
nextElement.focus();
|
||||
}
|
||||
|
||||
let elem: HTMLElement;
|
||||
switch(code) {
|
||||
// This method will be handled between `ContextManager` and PageContextAttachment:
|
||||
// pageContextAttachment.findNeighboringInput(contextManager.activeTarget.getElement(), <same flag>)
|
||||
case Codes.keyCodes['K_TAB']:
|
||||
const bBack = (Lkc.Lmodifiers & Codes.modifierCodes['SHIFT']) != 0;
|
||||
elem = contextManager.page.findNeighboringInput(contextManager.activeTarget.getElement(), bBack);
|
||||
elem.focus();
|
||||
moveToNext((Lkc.Lmodifiers & Codes.modifierCodes['SHIFT']) != 0);
|
||||
break;
|
||||
case Codes.keyCodes['K_TABBACK']:
|
||||
elem = contextManager.page.findNeighboringInput(contextManager.activeTarget.getElement(), true);
|
||||
elem.focus();
|
||||
moveToNext(true);
|
||||
break;
|
||||
case Codes.keyCodes['K_TABFWD']:
|
||||
elem = contextManager.page.findNeighboringInput(contextManager.activeTarget.getElement(), false);
|
||||
elem.focus();
|
||||
moveToNext(false);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,11 +37,9 @@ export class KeymanEngine extends KeymanEngineBase<ContextManager, HardwareEvent
|
|||
// Get the absolute position of the caret
|
||||
const y = getAbsoluteY(e);
|
||||
const t = window.pageYOffset;
|
||||
let dy = 0;
|
||||
if(y < t) {
|
||||
dy=y-t;
|
||||
} else {
|
||||
dy=y-t-(window.innerHeight - this.osk._Box.offsetHeight-e.offsetHeight-2);
|
||||
let dy = y-t;
|
||||
if(y >= t) {
|
||||
dy -= (window.innerHeight - this.osk._Box.offsetHeight - e.offsetHeight - 2);
|
||||
if(dy < 0) {
|
||||
dy=0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ export function setupOskListeners(engine: KeymanEngine, osk: OSKView, contextMan
|
|||
|
||||
osk.on('showBuild', () => {
|
||||
internalAlert('KeymanWeb Version ' + KEYMAN_VERSION.VERSION + '<br /><br />'
|
||||
+'<span style="font-size:0.8em">Copyright © 2021 SIL International</span>');
|
||||
+'<span style="font-size:0.8em">Copyright © 2007-2023 SIL International</span>');
|
||||
});
|
||||
|
||||
osk.on('dragMove', async (promise) => {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,4 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
|
||||
# set -x
|
||||
set -eu
|
||||
|
||||
## START STANDARD BUILD SCRIPT INCLUDE
|
||||
# adjust relative paths as necessary
|
||||
|
|
@ -10,15 +6,14 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
|
|||
. "${THIS_SCRIPT%/*}/../../../../resources/build/build-utils.sh"
|
||||
## END STANDARD BUILD SCRIPT INCLUDE
|
||||
|
||||
# Imports common Web build-script definitions & functions
|
||||
SUBPROJECT_NAME=engine/attachment
|
||||
. "$KEYMAN_ROOT/resources/shellHelperFunctions.sh"
|
||||
. "$KEYMAN_ROOT/web/common.inc.sh"
|
||||
|
||||
# This script runs from its own folder
|
||||
cd "$THIS_SCRIPT_PATH"
|
||||
|
||||
# Imports common Web build-script definitions & functions
|
||||
SUBPROJECT_NAME=engine/attachment
|
||||
. "$KEYMAN_ROOT/web/common.inc.sh"
|
||||
|
||||
# ################################ Main script ################################
|
||||
|
||||
builder_describe "Builds the Keyman Engine for Web (KMW) attachment engine." \
|
||||
|
|
@ -40,26 +35,7 @@ builder_parse "$@"
|
|||
|
||||
#### Build action definitions ####
|
||||
|
||||
if builder_start_action configure; then
|
||||
verify_npm_setup
|
||||
|
||||
builder_finish_action success configure
|
||||
fi
|
||||
|
||||
if builder_start_action clean; then
|
||||
rm -rf "$KEYMAN_ROOT/web/build/$SUBPROJECT_NAME"
|
||||
builder_finish_action success clean
|
||||
fi
|
||||
|
||||
if builder_start_action build; then
|
||||
compile $SUBPROJECT_NAME
|
||||
|
||||
builder_finish_action success build
|
||||
fi
|
||||
|
||||
if builder_start_action test; then
|
||||
# No HEADLESS tests yet.
|
||||
|
||||
# TODO: DOM tests
|
||||
builder_finish_action success test
|
||||
fi
|
||||
builder_run_action configure verify_npm_setup
|
||||
builder_run_action clean rm -rf "$KEYMAN_ROOT/web/build/$SUBPROJECT_NAME"
|
||||
builder_run_action build compile $SUBPROJECT_NAME
|
||||
builder_run_action test # No headless tests; TODO (next PR): DOM tests
|
||||
|
|
@ -45,12 +45,6 @@ BOOL GetKeyboardFileName(LPSTR kbname, LPSTR buf, int nbuf)
|
|||
{
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if(!_td) return FALSE;
|
||||
if(_td->ForceFileName[0])
|
||||
{
|
||||
strncpy_s(buf, nbuf, _td->ForceFileName, nbuf - 1);
|
||||
buf[nbuf-1] = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int n = 0;
|
||||
RegistryReadOnly *reg = Reg_GetKeymanInstalledKeyboard(kbname);
|
||||
|
|
@ -75,9 +69,9 @@ BOOL GetKeyboardFileName(LPSTR kbname, LPSTR buf, int nbuf)
|
|||
return n;
|
||||
}
|
||||
|
||||
BOOL LoadlpKeyboardCore(int i)
|
||||
BOOL LoadlpKeyboard(int i)
|
||||
{
|
||||
SendDebugMessageFormat(0, sdmLoad, 0, "LoadlpKeyboardCore: Enter ---");
|
||||
SendDebugMessageFormat(0, sdmLoad, 0, "%s: Enter ---", __FUNCTION__);
|
||||
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if (!_td) return FALSE;
|
||||
|
|
@ -85,7 +79,7 @@ BOOL LoadlpKeyboardCore(int i)
|
|||
if (_td->lpActiveKeyboard == &_td->lpKeyboards[i]) _td->lpActiveKeyboard = NULL; // I822 TSF not working
|
||||
|
||||
if (_td->lpKeyboards[i].lpCoreKeyboardState) {
|
||||
SendDebugMessageFormat(0, sdmLoad, 0, "LoadlpKeyboardCore: a keyboard km_kbp_state exits without matching keyboard - disposing of state");
|
||||
SendDebugMessageFormat(0, sdmLoad, 0, "LoadlpKeyboard: a keyboard km_kbp_state exits without matching keyboard - disposing of state");
|
||||
km_kbp_state_dispose(_td->lpKeyboards[i].lpCoreKeyboardState);
|
||||
_td->lpKeyboards[i].lpCoreKeyboardState = NULL;
|
||||
}
|
||||
|
|
@ -95,7 +89,7 @@ BOOL LoadlpKeyboardCore(int i)
|
|||
PWCHAR keyboardPath = strtowstr(buf);
|
||||
km_kbp_status err_status = km_kbp_keyboard_load(keyboardPath, &_td->lpKeyboards[i].lpCoreKeyboard);
|
||||
if (err_status != KM_KBP_STATUS_OK) {
|
||||
SendDebugMessageFormat(0, sdmLoad, 0, "LoadlpKeyboardCore: km_kbp_keyboard_load failed for %ls with error status [%d]", keyboardPath, err_status);
|
||||
SendDebugMessageFormat(0, sdmLoad, 0, "LoadlpKeyboard: km_kbp_keyboard_load failed for %ls with error status [%d]", keyboardPath, err_status);
|
||||
delete keyboardPath;
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -104,7 +98,7 @@ BOOL LoadlpKeyboardCore(int i)
|
|||
km_kbp_option_item *core_environment = nullptr;
|
||||
|
||||
if(!SetupCoreEnvironment(&core_environment)) {
|
||||
SendDebugMessageFormat(0, sdmLoad, 0, "LoadlpKeyboardCore: Unable to set environment options for keyboard %ls", keyboardPath);
|
||||
SendDebugMessageFormat(0, sdmLoad, 0, "LoadlpKeyboard: Unable to set environment options for keyboard %ls", keyboardPath);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -114,7 +108,7 @@ BOOL LoadlpKeyboardCore(int i)
|
|||
|
||||
if (err_status != KM_KBP_STATUS_OK) {
|
||||
SendDebugMessageFormat(
|
||||
0, sdmLoad, 0, "LoadlpKeyboardCore: km_kbp_state_create failed with error status [%d]", err_status);
|
||||
0, sdmLoad, 0, "LoadlpKeyboard: km_kbp_state_create failed with error status [%d]", err_status);
|
||||
// Dispose of the keyboard to leave us in a consistent state
|
||||
ReleaseKeyboardMemoryCore(&_td->lpKeyboards[i].lpCoreKeyboard);
|
||||
return FALSE;
|
||||
|
|
@ -122,38 +116,15 @@ BOOL LoadlpKeyboardCore(int i)
|
|||
// Register callback?
|
||||
err_status = km_kbp_keyboard_get_imx_list(_td->lpKeyboards[i].lpCoreKeyboard, &_td->lpKeyboards[i].lpIMXList);
|
||||
if (err_status != KM_KBP_STATUS_OK) {
|
||||
SendDebugMessageFormat(0, sdmLoad, 0, "LoadlpKeyboardCore: km_kbp_keyboard_get_imx_list failed with error status [%d]", err_status);
|
||||
SendDebugMessageFormat(0, sdmLoad, 0, "LoadlpKeyboard: km_kbp_keyboard_get_imx_list failed with error status [%d]", err_status);
|
||||
// Dispose of the keyboard to leave us in a consistent state
|
||||
ReleaseKeyboardMemoryCore(&_td->lpKeyboards[i].lpCoreKeyboard);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LoadDLLsCore(&_td->lpKeyboards[i]);
|
||||
|
||||
LoadKeyboardOptionsREGCore(&_td->lpKeyboards[i], _td->lpKeyboards[i].lpCoreKeyboardState);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL LoadlpKeyboard(int i)
|
||||
{
|
||||
if (Globals::get_CoreIntegration())
|
||||
{
|
||||
return LoadlpKeyboardCore(i);
|
||||
}
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if(!_td) return FALSE;
|
||||
if(_td->lpKeyboards[i].Keyboard) return TRUE;
|
||||
if(_td->lpActiveKeyboard == &_td->lpKeyboards[i]) _td->lpActiveKeyboard = NULL; // I822 TSF not working
|
||||
|
||||
char buf[256];
|
||||
if(!GetKeyboardFileName(_td->lpKeyboards[i].Name, buf, 255)) return FALSE;
|
||||
|
||||
if(!LoadKeyboard(buf, &_td->lpKeyboards[i].Keyboard)) return FALSE; // I5136
|
||||
|
||||
LoadDLLs(&_td->lpKeyboards[i]);
|
||||
|
||||
LoadKeyboardOptions(&_td->lpKeyboards[i]);
|
||||
LoadKeyboardOptionsRegistrytoCore(&_td->lpKeyboards[i], _td->lpKeyboards[i].lpCoreKeyboardState);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,263 +0,0 @@
|
|||
/*
|
||||
Name: addins
|
||||
Copyright: Copyright (C) SIL International.
|
||||
Documentation:
|
||||
Description:
|
||||
Create Date: 14 Jun 2008
|
||||
|
||||
Modified Date: 14 May 2010
|
||||
Authors: mcdurdin
|
||||
Related Files:
|
||||
Dependencies:
|
||||
|
||||
Bugs:
|
||||
Todo:
|
||||
Notes:
|
||||
History: 14 Jun 2008 - mcdurdin - I1488 - Fix registry handle leak
|
||||
11 Mar 2009 - mcdurdin - I1894 - Fix threading bugs introduced in I1888
|
||||
11 Dec 2009 - mcdurdin - I934 - x64 - Initial version
|
||||
12 Mar 2010 - mcdurdin - I934 - x64 - Complete
|
||||
12 Mar 2010 - mcdurdin - I2229 - Remove hints and warnings
|
||||
04 May 2010 - mcdurdin - I2351 - Robustness - verify _td return value
|
||||
14 May 2010 - mcdurdin - I2374 - Fix crash in some situations
|
||||
*/
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
void Addin_Release()
|
||||
{
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if(!_td) return;
|
||||
|
||||
//SendDebugMessageFormat(GetFocus(), sdmGlobal, 0, "Addin_Release: ENTER [%d]", nAddins);
|
||||
if(_td->Addins)
|
||||
{
|
||||
for(int i = 0; i < _td->nAddins; i++)
|
||||
if(_td->Addins[i].hAddin)
|
||||
{
|
||||
if(_td->Addins[i].Uninitialise) (*_td->Addins[i].Uninitialise)();
|
||||
FreeLibrary(_td->Addins[i].hAddin);
|
||||
}
|
||||
delete[] _td->Addins;
|
||||
}
|
||||
_td->Addins = NULL;
|
||||
_td->nAddins = 0;
|
||||
_td->CurrentAddin = -1;
|
||||
//SendDebugMessageFormat(GetFocus(), sdmGlobal, 0, "Addin_Release: EXIT");
|
||||
}
|
||||
|
||||
void ReadAddins(HKEY hkey)
|
||||
{
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if(!_td) return;
|
||||
|
||||
//SendDebugMessageFormat(GetFocus(), sdmGlobal, 0, "Addins: ReadAddins: ENTER");
|
||||
RegistryReadOnly *reg = new RegistryReadOnly(hkey);
|
||||
if(reg->OpenKeyReadOnly(hkey == HKEY_CURRENT_USER ? REGSZ_KeymanAddinsCU : REGSZ_KeymanAddinsLM))
|
||||
{
|
||||
int n = _td->nAddins;
|
||||
char buf[128];
|
||||
while(reg->GetValueNames(buf, 128, n))
|
||||
{
|
||||
Addin *a = new Addin[n+1];
|
||||
if(_td->Addins)
|
||||
{
|
||||
memcpy(a, _td->Addins, n * sizeof(Addin));
|
||||
delete[] _td->Addins;
|
||||
}
|
||||
_td->Addins = a;
|
||||
_td->Addins[n].hAddin = 0;
|
||||
_td->Addins[n].FocusChanged = NULL;
|
||||
_td->Addins[n].Initialise = NULL;
|
||||
_td->Addins[n].OutputBackspace = NULL;
|
||||
_td->Addins[n].OutputChar = NULL;
|
||||
_td->Addins[n].Uninitialise = NULL;
|
||||
_td->Addins[n].ShouldProcess = NULL;
|
||||
strcpy(_td->Addins[n].ClassName, buf);
|
||||
reg->ReadString(buf, _td->Addins[n].AddinName, 260);
|
||||
_td->Addins[n].Application[0] = 0;
|
||||
n++;
|
||||
}
|
||||
_td->nAddins = n;
|
||||
}
|
||||
delete reg;
|
||||
//SendDebugMessageFormat(GetFocus(), sdmGlobal, 0, "Addins: ReadAddins: EXIT");
|
||||
}
|
||||
|
||||
void Addin_Refresh()
|
||||
{
|
||||
//SendDebugMessageFormat(GetFocus(), sdmGlobal, 0, "Addin_Refresh: ENTER");
|
||||
Addin_Release();
|
||||
ReadAddins(HKEY_CURRENT_USER);
|
||||
ReadAddins(HKEY_LOCAL_MACHINE);
|
||||
//SendDebugMessageFormat(GetFocus(), sdmGlobal, 0, "Addin_Refresh: EXIT");
|
||||
}
|
||||
|
||||
BOOL LoadAddin()
|
||||
{
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if(!_td) return FALSE;
|
||||
if(_td->CurrentAddin == -1) return FALSE;
|
||||
|
||||
Addin *a = &_td->Addins[_td->CurrentAddin];
|
||||
if(!a->hAddin)
|
||||
{
|
||||
//SendDebugMessageFormat(GetFocus(), sdmGlobal, 0, "Addins: LoadAddin: ENTER");
|
||||
a->hAddin = LoadLibrary(a->AddinName);
|
||||
if(!a->hAddin)
|
||||
{
|
||||
a->hAddin = 0;
|
||||
a->ClassName[0] = 0; // prevent add-in attempting to load again
|
||||
_td->CurrenthWnd = 0;
|
||||
_td->CurrentAddin = -1;
|
||||
//SendDebugMessageFormat(GetFocus(), sdmGlobal, 0, "Addins: LoadAddin: EXIT - FALSE - LoadLibrary");
|
||||
return FALSE;
|
||||
}
|
||||
a->OutputBackspace = (PKeymanOutputBackspace) GetProcAddress(a->hAddin, "KeymanOutputBackspace");
|
||||
a->OutputChar = (PKeymanOutputChar) GetProcAddress(a->hAddin, "KeymanOutputChar");
|
||||
a->FocusChanged = (PKeymanFocusChanged) GetProcAddress(a->hAddin, "KeymanFocusChanged");
|
||||
a->ShouldProcess = (PKeymanShouldProcess) GetProcAddress(a->hAddin, "KeymanShouldProcess");
|
||||
a->Initialise = (PKeymanInit) GetProcAddress(a->hAddin, "KeymanInitialise");
|
||||
a->Uninitialise = (PKeymanInit) GetProcAddress(a->hAddin, "KeymanUninitialise");
|
||||
|
||||
if(a->Initialise && !(*a->Initialise)())
|
||||
{
|
||||
FreeLibrary(a->hAddin);
|
||||
a->hAddin = 0;
|
||||
a->ClassName[0] = 0;
|
||||
_td->CurrenthWnd = 0;
|
||||
_td->CurrentAddin = -1;
|
||||
//SendDebugMessageFormat(GetFocus(), sdmGlobal, 0, "Addins: LoadAddin: EXIT - FALSE - Initialise");
|
||||
return FALSE;
|
||||
}
|
||||
//SendDebugMessageFormat(GetFocus(), sdmGlobal, 0, "Addins: LoadAddin: EXIT - TRUE - Loaded");
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL Addin_ShouldProcessUnichar(HWND hwnd)
|
||||
{
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if(!_td) return FALSE;
|
||||
|
||||
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ShouldProcessUnichar: ENTER");
|
||||
_td->CurrenthWnd = hwnd;
|
||||
GetClassName(hwnd, _td->CurrentClassName, 128);
|
||||
if(_td->CurrentAddin >= 0 && !_strcmpi(_td->CurrentClassName, _td->Addins[_td->CurrentAddin].ClassName))
|
||||
{
|
||||
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ShouldProcessUnichar: EXIT - TRUE - CurrentAddin okay");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
for(int i = 0; i < _td->nAddins; i++)
|
||||
if(!_strcmpi(_td->CurrentClassName, _td->Addins[i].ClassName))
|
||||
{
|
||||
_td->CurrentAddin = i;
|
||||
if(!LoadAddin())
|
||||
{
|
||||
_td->CurrentAddin = -1;
|
||||
_td->Addins[i].ClassName[0] = 0; // prevent add-in attempting to load again
|
||||
}
|
||||
else if(_td->Addins[i].ShouldProcess && !(*_td->Addins[i].ShouldProcess)(hwnd))
|
||||
_td->CurrentAddin = -1;
|
||||
else
|
||||
{
|
||||
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ShouldProcessUnichar: EXIT - TRUE - FoundAddin");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
_td->CurrentAddin = -1;
|
||||
_td->CurrenthWnd = 0;
|
||||
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ShouldProcessUnichar: EXIT - FALSE");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL Addin_ProcessUnichar(HWND hwnd, DWORD chr)
|
||||
{
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if(!_td) return FALSE;
|
||||
|
||||
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ProcessUnichar: ENTER");
|
||||
if(_td->CurrenthWnd != hwnd)
|
||||
if(!Addin_ShouldProcessUnichar(hwnd))
|
||||
{
|
||||
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ProcessUnichar: EXIT - FALSE - Addin_ShouldProcessUnichar");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(!LoadAddin())
|
||||
{
|
||||
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ProcessUnichar: EXIT - FALSE - !LoadAddin)");
|
||||
return FALSE;
|
||||
}
|
||||
if(!_td->Addins[_td->CurrentAddin].OutputChar)
|
||||
{
|
||||
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ProcessUnichar: EXIT - FALSE !OutputChar");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL b = (*_td->Addins[_td->CurrentAddin].OutputChar)(hwnd, chr);
|
||||
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ProcessUnichar: EXIT (b) == %d", b);
|
||||
return b;
|
||||
}
|
||||
|
||||
BOOL Addin_ProcessBackspace(HWND hwnd)
|
||||
{
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if(!_td) return FALSE;
|
||||
|
||||
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ProcessBackspace: ENTER");
|
||||
if(_td->CurrenthWnd != hwnd)
|
||||
if(!Addin_ShouldProcessUnichar(hwnd))
|
||||
{
|
||||
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ProcessBackspace: EXIT - !ShouldProcess");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(!LoadAddin())
|
||||
{
|
||||
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ProcessBackspace: EXIT - !LoadAddin");
|
||||
return FALSE;
|
||||
}
|
||||
if(!_td->Addins[_td->CurrentAddin].OutputBackspace)
|
||||
{
|
||||
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ProcessBackspace: EXIT - !OutputBackspace");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL b = (*_td->Addins[_td->CurrentAddin].OutputBackspace)(hwnd);
|
||||
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_ProcessBackspace: EXIT - (b) = %d", b);
|
||||
return b;
|
||||
}
|
||||
|
||||
void Addin_FocusChanged(HWND hwnd)
|
||||
{
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if(!_td) return;
|
||||
|
||||
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_FocusChanged: ENTER");
|
||||
|
||||
if(_td->CurrenthWnd != hwnd)
|
||||
if(!Addin_ShouldProcessUnichar(hwnd))
|
||||
{
|
||||
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_FocusChanged: EXIT - !ShouldProcess");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!LoadAddin())
|
||||
{
|
||||
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_FocusChanged: EXIT - !LoadAddin");
|
||||
return;
|
||||
}
|
||||
|
||||
// Addin variables must be valid now
|
||||
|
||||
if(!_td->Addins[_td->CurrentAddin].FocusChanged)
|
||||
{
|
||||
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_FocusChanged: EXIT - !FocusChanged");
|
||||
return;
|
||||
}
|
||||
|
||||
(*_td->Addins[_td->CurrentAddin].FocusChanged)();
|
||||
//SendDebugMessageFormat(hwnd, sdmGlobal, 0, "Addin_FocusChanged: EXIT");
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
/*
|
||||
Name: addins
|
||||
Copyright: Copyright (C) SIL International.
|
||||
Documentation:
|
||||
Description:
|
||||
Create Date: 11 Dec 2009
|
||||
|
||||
Modified Date: 11 Dec 2009
|
||||
Authors: mcdurdin
|
||||
Related Files:
|
||||
Dependencies:
|
||||
|
||||
Bugs:
|
||||
Todo:
|
||||
Notes:
|
||||
History: 11 Dec 2009 - mcdurdin - I934 - x64 - Initial version
|
||||
*/
|
||||
void Addin_Release();
|
||||
void Addin_Refresh();
|
||||
BOOL Addin_ShouldProcessUnichar(HWND hwnd);
|
||||
BOOL Addin_ProcessUnichar(HWND hwnd, DWORD chr);
|
||||
BOOL Addin_ProcessBackspace(HWND hwnd);
|
||||
void Addin_FocusChanged(HWND hwnd);
|
||||
|
|
@ -126,7 +126,6 @@ extern "C" __declspec(dllexport) BOOL WINAPI TIPProcessKey(WPARAM wParam, LPARAM
|
|||
BOOL isUp = keyFlags & KF_UP ? TRUE : FALSE;
|
||||
BOOL extended = keyFlags & KF_EXTENDED ? TRUE : FALSE;
|
||||
BYTE scan = keyFlags & 0xFF;
|
||||
BOOL isUsingCoreProcessor = Globals::get_CoreIntegration();
|
||||
|
||||
SendDebugMessageFormat(0, sdmAIDefault, 0, "TIPProcessKey: Enter VirtualKey=%s lParam=%x IsUp=%d Extended=%d Updateable=%d Preserved=%d", Debug_VirtualKey((WORD) wParam), lParam, isUp, extended, Updateable, Preserved);
|
||||
|
||||
|
|
@ -163,72 +162,31 @@ extern "C" __declspec(dllexport) BOOL WINAPI TIPProcessKey(WPARAM wParam, LPARAM
|
|||
// core processor. The core processor has the keyboard Caps Lock stores and will
|
||||
// queue an action 'KM_KBP_IT_CAPSLOCK'. In processing the action the Windows engine will synthesise keystrokes
|
||||
// to ensure caps lock is in the correct state.
|
||||
if (isUsingCoreProcessor) {
|
||||
if (!Preserved) {
|
||||
switch (wParam) {
|
||||
case VK_MENU:
|
||||
case VK_CONTROL:
|
||||
ProcessModifierChange((UINT)wParam, isUp, extended);
|
||||
return FALSE;
|
||||
case VK_NUMLOCK:
|
||||
if (!Preserved) {
|
||||
switch (wParam) {
|
||||
case VK_MENU:
|
||||
case VK_CONTROL:
|
||||
ProcessModifierChange((UINT)wParam, isUp, extended);
|
||||
return FALSE;
|
||||
case VK_NUMLOCK:
|
||||
if (!isUp)
|
||||
ProcessToggleChange((UINT)wParam); // I4793
|
||||
return FALSE;
|
||||
case VK_CAPITAL:
|
||||
if (!isUp)
|
||||
ProcessToggleChange((UINT)wParam); // I4793
|
||||
return FALSE;
|
||||
case VK_CAPITAL:
|
||||
if (!isUp)
|
||||
ProcessToggleChange((UINT)wParam); // I4793
|
||||
break;
|
||||
case VK_SHIFT:
|
||||
ProcessModifierChange((UINT)wParam, isUp, extended);
|
||||
ProcessToggleChange((UINT)wParam); // I4793
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Mask out Ctrl, Shift and Alt and include new modifiers // I4548
|
||||
DWORD NewShiftState = TSFShiftToShift(lParam); // I3588
|
||||
SendDebugMessageFormat(
|
||||
0, sdmGlobal, 0, "TIPProcessKey: TSFShiftToShift start with %x, include %x", LocalShiftState, NewShiftState);
|
||||
*Globals::ShiftState() = (LocalShiftState & K_NOTMODIFIERFLAG) | NewShiftState; // I3588
|
||||
case VK_SHIFT:
|
||||
ProcessModifierChange((UINT)wParam, isUp, extended);
|
||||
break;
|
||||
}
|
||||
} else { // using windows processor TODO: #5442 Remove this else block
|
||||
if (!Preserved) {
|
||||
switch (wParam) {
|
||||
case VK_CAPITAL:
|
||||
if (!isUp)
|
||||
ProcessToggleChange((UINT)wParam); // I4793
|
||||
if (!Updateable) {
|
||||
// We only want to process the Caps Lock key event once --
|
||||
// in the first pass (!Updateable).
|
||||
KeyCapsLockPress(isUp); // I4548
|
||||
}
|
||||
return FALSE;
|
||||
case VK_SHIFT:
|
||||
if (!Updateable) {
|
||||
// We only want to process the Shift key event once --
|
||||
// in the first pass (!Updateable).
|
||||
KeyShiftPress(isUp); // I4548
|
||||
}
|
||||
// Fall through
|
||||
case VK_MENU:
|
||||
case VK_CONTROL:
|
||||
ProcessModifierChange((UINT)wParam, isUp, extended);
|
||||
return FALSE;
|
||||
case VK_NUMLOCK:
|
||||
if (!isUp)
|
||||
ProcessToggleChange((UINT)wParam); // I4793
|
||||
return FALSE;
|
||||
}
|
||||
// This would only get here if none of the above cases matched why not use default in the switch?
|
||||
if (isUp) {
|
||||
return FALSE; // return value ignored in this case; we only needed it for testing anyway
|
||||
}
|
||||
} else {
|
||||
// Mask out Ctrl, Shift and Alt and include new modifiers // I4548
|
||||
DWORD NewShiftState = TSFShiftToShift(lParam); // I3588
|
||||
SendDebugMessageFormat(
|
||||
0, sdmGlobal, 0, "TIPProcessKey: TSFShiftToShift start with %x, include %x", LocalShiftState, NewShiftState);
|
||||
*Globals::ShiftState() = (LocalShiftState & K_NOTMODIFIERFLAG) | NewShiftState; // I3588
|
||||
}
|
||||
} // TODO: #5442 Remove this else block ^^
|
||||
} else {
|
||||
// Mask out Ctrl, Shift and Alt and include new modifiers // I4548
|
||||
DWORD NewShiftState = TSFShiftToShift(lParam); // I3588
|
||||
SendDebugMessageFormat(
|
||||
0, sdmGlobal, 0, "TIPProcessKey: TSFShiftToShift start with %x, include %x", LocalShiftState, NewShiftState);
|
||||
*Globals::ShiftState() = (LocalShiftState & K_NOTMODIFIERFLAG) | NewShiftState; // I3588
|
||||
}
|
||||
|
||||
_td->TIPFUpdateable = Updateable;
|
||||
_td->TIPFPreserved = Preserved; // I4290
|
||||
|
|
@ -239,16 +197,7 @@ extern "C" __declspec(dllexport) BOOL WINAPI TIPProcessKey(WPARAM wParam, LPARAM
|
|||
_td->state.vkey = (WORD) wParam;
|
||||
_td->state.isDown = !isUp;
|
||||
|
||||
if (isUsingCoreProcessor) {
|
||||
_td->state.lpCoreKb = _td->lpActiveKeyboard->lpCoreKeyboard;
|
||||
|
||||
} else {
|
||||
_td->state.lpkb = _td->lpActiveKeyboard->Keyboard;
|
||||
_td->state.startgroup = &_td->state.lpkb->dpGroupArray[_td->state.lpkb->StartGroup[BEGIN_UNICODE]];
|
||||
_td->state.NoMatches = TRUE;
|
||||
_td->state.LoopTimes = 0;
|
||||
_td->state.StopOutput = FALSE;
|
||||
}
|
||||
_td->state.lpCoreKb = _td->lpActiveKeyboard->lpCoreKeyboard;
|
||||
|
||||
_td->state.windowunicode = TRUE;
|
||||
|
||||
|
|
@ -257,30 +206,8 @@ extern "C" __declspec(dllexport) BOOL WINAPI TIPProcessKey(WPARAM wParam, LPARAM
|
|||
_td->TIPProcessOutput = outfunc;
|
||||
_td->TIPGetContext = ctfunc;
|
||||
|
||||
AppContextWithStores *savedContext = NULL; // I4370 // I4978
|
||||
|
||||
if (!Updateable) {
|
||||
// The core processor km_kbp_process_event is only called once per key stroke
|
||||
// therefore there is no need to preserve context and keyboard actions
|
||||
if (!isUsingCoreProcessor) {
|
||||
savedContext = new AppContextWithStores(_td->lpActiveKeyboard->Keyboard->cxStoreArray); // I4370 // I4978
|
||||
_td->app->SaveContext(savedContext);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL res = ProcessHook();
|
||||
|
||||
if (!Updateable) {
|
||||
if (!isUsingCoreProcessor) {
|
||||
if (res) { // I4585 // I4370
|
||||
// Reset the context if match found
|
||||
_td->app->RestoreContext(savedContext);
|
||||
delete savedContext;
|
||||
savedContext = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_td->TIPProcessOutput = NULL;
|
||||
_td->TIPGetContext = NULL;
|
||||
|
||||
|
|
@ -439,65 +366,6 @@ void AITIP::ReadContext() {
|
|||
}
|
||||
}
|
||||
|
||||
AppContextWithStores::AppContextWithStores(int nKeyboardOptions) : AppContext() { // I4978
|
||||
this->nKeyboardOptions = nKeyboardOptions;
|
||||
KeyboardOptions = new INTKEYBOARDOPTIONS[nKeyboardOptions];
|
||||
memset(KeyboardOptions, 0, sizeof(INTKEYBOARDOPTIONS) * nKeyboardOptions);
|
||||
}
|
||||
|
||||
AppContextWithStores::~AppContextWithStores() { // I4978
|
||||
for(DWORD i = 0; i < nKeyboardOptions; i++) {
|
||||
if(KeyboardOptions[i].Value) delete KeyboardOptions[i].Value;
|
||||
}
|
||||
delete KeyboardOptions;
|
||||
}
|
||||
|
||||
void AITIP::SaveContext(AppContextWithStores *savedContext) { // I4370 // I4978
|
||||
savedContext->CopyFrom(context);
|
||||
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if(!_td || !_td->lpActiveKeyboard || !_td->lpActiveKeyboard->Keyboard) return;
|
||||
|
||||
assert(savedContext->nKeyboardOptions == _td->lpActiveKeyboard->Keyboard->cxStoreArray);
|
||||
|
||||
for(DWORD i = 0; i < savedContext->nKeyboardOptions; i++) { // I4978
|
||||
if(_td->lpActiveKeyboard->KeyboardOptions[i].Value != NULL) {
|
||||
savedContext->KeyboardOptions[i].Value = new WCHAR[wcslen(_td->lpActiveKeyboard->KeyboardOptions[i].Value)+1];
|
||||
wcscpy_s(savedContext->KeyboardOptions[i].Value, wcslen(_td->lpActiveKeyboard->KeyboardOptions[i].Value)+1, _td->lpActiveKeyboard->KeyboardOptions[i].Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AITIP::RestoreContext(AppContextWithStores *savedContext) { // I4370 // I4978
|
||||
context->CopyFrom(savedContext);
|
||||
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if(!_td || !_td->lpActiveKeyboard || !_td->lpActiveKeyboard->Keyboard) return;
|
||||
LPINTKEYBOARDINFO kp = _td->lpActiveKeyboard;
|
||||
|
||||
assert(savedContext->nKeyboardOptions == kp->Keyboard->cxStoreArray);
|
||||
|
||||
for(DWORD i = 0; i < savedContext->nKeyboardOptions; i++) { // I4978
|
||||
if(kp->KeyboardOptions[i].Value == NULL && savedContext->KeyboardOptions[i].Value != NULL) {
|
||||
// Restore the previously saved value as it was reset
|
||||
kp->KeyboardOptions[i].OriginalStore = kp->Keyboard->dpStoreArray[i].dpString;
|
||||
kp->Keyboard->dpStoreArray[i].dpString = kp->KeyboardOptions[i].Value = savedContext->KeyboardOptions[i].Value;
|
||||
savedContext->KeyboardOptions[i].Value = NULL;
|
||||
} else if(kp->KeyboardOptions[i].Value != NULL && savedContext->KeyboardOptions[i].Value == NULL) {
|
||||
// Clear the newly saved value back to the default
|
||||
delete kp->KeyboardOptions[i].Value;
|
||||
kp->KeyboardOptions[i].Value = NULL;
|
||||
kp->Keyboard->dpStoreArray[i].dpString = kp->KeyboardOptions[i].OriginalStore;
|
||||
} else if(kp->KeyboardOptions[i].Value != NULL && savedContext->KeyboardOptions[i].Value != NULL &&
|
||||
wcscmp(kp->KeyboardOptions[i].Value, savedContext->KeyboardOptions[i].Value) != 0) {
|
||||
// Restore the previously saved value as it was changed
|
||||
delete kp->KeyboardOptions[i].Value;
|
||||
kp->Keyboard->dpStoreArray[i].dpString = kp->KeyboardOptions[i].Value = savedContext->KeyboardOptions[i].Value;
|
||||
savedContext->KeyboardOptions[i].Value = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AITIP::CopyContext(AppContext *savedContext) {
|
||||
savedContext->CopyFrom(context);
|
||||
}
|
||||
|
|
@ -722,49 +590,3 @@ void FillStoreOffsets(AIDEBUGINFO *di)
|
|||
}
|
||||
di->StoreOffsets[n] = 0xFFFF;
|
||||
}
|
||||
|
||||
BOOL AITIP::QueueDebugInformation(int ItemType, LPGROUP Group, LPKEY Rule, PWSTR fcontext, PWSTR foutput, DWORD_PTR dwExtraFlags)
|
||||
{
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if(!_td) return TRUE;
|
||||
if(!_td->ForceFileName[0]) return TRUE;
|
||||
|
||||
SendDebugMessageFormat(0, sdmAIDefault, 0, "AIDebugger::QueueDebugInformation ItemType=%d", ItemType);
|
||||
AIDEBUGINFO di;
|
||||
di.cbSize = sizeof(AIDEBUGINFO);
|
||||
di.ItemType = ItemType; // int
|
||||
di.Context = fcontext; // PWSTR
|
||||
di.Rule = Rule; // LPKEY
|
||||
di.Group = Group; // LPGROUP
|
||||
di.Output = foutput; // PWSTR
|
||||
di.Flags = dwExtraFlags; // DWORD
|
||||
|
||||
if(di.Rule) FillStoreOffsets(&di);
|
||||
|
||||
// data required
|
||||
// keystroke
|
||||
// context for rule
|
||||
// if rule, then output of rule
|
||||
// match positions for all stores in rule
|
||||
|
||||
if(DebugControlled())
|
||||
SendMessage(GetDebugControlWindow(), WM_KEYMANDEBUG_RULEMATCH, ItemType, (LPARAM) &di);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef BOOL(WINAPI *PREFRESHPRESERVEDKEYSFUNC)(BOOL Activating);
|
||||
|
||||
void RefreshPreservedKeys(BOOL Activating) {
|
||||
#ifdef _WIN64
|
||||
HMODULE hModule = GetModuleHandle("kmtip64");
|
||||
#else
|
||||
HMODULE hModule = GetModuleHandle("kmtip");
|
||||
#endif
|
||||
if (hModule != NULL) {
|
||||
PREFRESHPRESERVEDKEYSFUNC pRefreshPreservedKeys = (PREFRESHPRESERVEDKEYSFUNC)GetProcAddress(hModule, "RefreshPreservedKeys");
|
||||
if (pRefreshPreservedKeys) {
|
||||
pRefreshPreservedKeys(Activating);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,11 +71,6 @@ public:
|
|||
|
||||
BOOL DebugControlled();
|
||||
|
||||
// TODO: 5442 This would be better to called SaveContextWithStores or SaveContextWithKbdOptions
|
||||
// Will be removed with 5442 when removing window core
|
||||
void SaveContext(AppContextWithStores *savedContext); // I4370 // I4978
|
||||
void RestoreContext(AppContextWithStores *savedContext); // I4370 // I4978
|
||||
|
||||
/**
|
||||
* Copy the member context
|
||||
*
|
||||
|
|
@ -106,7 +101,6 @@ public:
|
|||
/* Queue and sending functions */
|
||||
|
||||
virtual BOOL SendActions(); // I4196
|
||||
virtual BOOL QueueDebugInformation(int ItemType, LPGROUP Group, LPKEY Rule, PWSTR fcontext, PWSTR foutput, DWORD_PTR dwExtraFlags);
|
||||
|
||||
/* TIP interactions */
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
/*
|
||||
Name: AIWin2000Unicode
|
||||
Copyright: Copyright (C) SIL International.
|
||||
Documentation:
|
||||
Description:
|
||||
Documentation:
|
||||
Description:
|
||||
Create Date: 22 Jan 2007
|
||||
|
||||
Modified Date: 9 Aug 2015
|
||||
Authors: mcdurdin
|
||||
Related Files:
|
||||
Dependencies:
|
||||
Related Files:
|
||||
Dependencies:
|
||||
|
||||
Bugs:
|
||||
Todo:
|
||||
Notes:
|
||||
Bugs:
|
||||
Todo:
|
||||
Notes:
|
||||
History: 22 Jan 2007 - mcdurdin - Fix for K_NPENTER
|
||||
13 Jul 2007 - mcdurdin - I934 - Prep fox x64
|
||||
23 Aug 2007 - mcdurdin - I719 - Fix Alt+LeftShift and Word interactions
|
||||
|
|
@ -43,12 +43,6 @@
|
|||
#include "pch.h" // I4128 // I4287
|
||||
#include "serialkeyeventclient.h"
|
||||
|
||||
#define KEYMAN_MOREPOST "WM_KMMOREPOST"
|
||||
|
||||
#ifndef WM_UNICHAR
|
||||
#define WM_UNICHAR 0x0109
|
||||
#define UNICODE_NOCHAR 0xFFFF
|
||||
#endif
|
||||
|
||||
AIWin2000Unicode::AIWin2000Unicode()
|
||||
{
|
||||
|
|
@ -70,13 +64,13 @@ BOOL AIWin2000Unicode::CanHandleWindow(HWND ahwnd)
|
|||
}
|
||||
|
||||
BOOL AIWin2000Unicode::HandleWindow(HWND ahwnd)
|
||||
{
|
||||
{
|
||||
if(hwnd != ahwnd)
|
||||
{
|
||||
hwnd = ahwnd;
|
||||
hwnd = ahwnd;
|
||||
context->Reset();
|
||||
}
|
||||
return TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL AIWin2000Unicode::IsWindowHandled(HWND ahwnd)
|
||||
|
|
@ -84,11 +78,11 @@ BOOL AIWin2000Unicode::IsWindowHandled(HWND ahwnd)
|
|||
return (hwnd == ahwnd);
|
||||
}
|
||||
|
||||
BOOL AIWin2000Unicode::IsUnicode()
|
||||
{
|
||||
BOOL AIWin2000Unicode::IsUnicode()
|
||||
{
|
||||
BOOL Result = IsWindowUnicode(hwnd);
|
||||
SendDebugMessageFormat(0, sdmAIDefault, 0, "IsWindowUnicode=%s", Result ? "Yes" : "No");
|
||||
return Result;
|
||||
return Result;
|
||||
}
|
||||
|
||||
/* Context functions */
|
||||
|
|
@ -96,7 +90,7 @@ BOOL AIWin2000Unicode::IsUnicode()
|
|||
void AIWin2000Unicode::ReadContext()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void AIWin2000Unicode::AddContext(WCHAR ch) //I2436
|
||||
{
|
||||
context->Add(ch);
|
||||
|
|
@ -121,7 +115,7 @@ void AIWin2000Unicode::SetContext(const WCHAR* buf)
|
|||
{
|
||||
return context->Set(buf);
|
||||
}
|
||||
|
||||
|
||||
BYTE SavedKbdState[256];
|
||||
|
||||
BOOL AIWin2000Unicode::SendActions() // I4196
|
||||
|
|
@ -137,7 +131,7 @@ BOOL AIWin2000Unicode::QueueAction(int ItemType, DWORD dwData)
|
|||
int result = AppIntegration::QueueAction(ItemType, dwData);
|
||||
|
||||
//SendDebugMessageFormat(hwnd, sdmAIDefault, 0, "App::QueueAction ItemType=%d dwData=%x", ItemType, dwData);
|
||||
|
||||
|
||||
switch(ItemType)
|
||||
{
|
||||
case QIT_VKEYDOWN:
|
||||
|
|
@ -166,27 +160,16 @@ BOOL AIWin2000Unicode::QueueAction(int ItemType, DWORD dwData)
|
|||
return result;
|
||||
}
|
||||
|
||||
BOOL AIWin2000Unicode::QueueDebugInformation(int ItemType, LPGROUP Group, LPKEY Rule, PWSTR fcontext, PWSTR foutput, DWORD_PTR dwExtraFlags)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(ItemType);
|
||||
UNREFERENCED_PARAMETER(Group);
|
||||
UNREFERENCED_PARAMETER(Rule);
|
||||
UNREFERENCED_PARAMETER(fcontext);
|
||||
UNREFERENCED_PARAMETER(foutput);
|
||||
UNREFERENCED_PARAMETER(dwExtraFlags);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// I1512 - SendInput with VK_PACKET for greater robustness
|
||||
|
||||
BOOL AIWin2000Unicode::PostKeys()
|
||||
{
|
||||
{
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if(!_td) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(QueueSize == 0)
|
||||
if(QueueSize == 0)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -208,7 +191,7 @@ BOOL AIWin2000Unicode::PostKeys()
|
|||
switch(Queue[n].ItemType) {
|
||||
case QIT_VKEYDOWN:
|
||||
if((Queue[n].dwData & QVK_KEYMASK) == 0x05) Queue[n].dwData = (Queue[n].dwData & QVK_FLAGMASK) | VK_RETURN; // I649 // I3438
|
||||
|
||||
|
||||
/* 6.0.153.0: Fix repeat state for virtual keys */
|
||||
|
||||
if((Queue[n].dwData & QVK_KEYMASK) <= VK__MAX) // I3438
|
||||
|
|
@ -277,7 +260,6 @@ BOOL AIWin2000Unicode::PostKeys()
|
|||
break;
|
||||
case QIT_BACK:
|
||||
if(Queue[n].dwData & BK_DEADKEY) break;
|
||||
if(Addin_ProcessBackspace(hwnd)) break;
|
||||
|
||||
pInputs[i].type = INPUT_KEYBOARD;
|
||||
pInputs[i].ki.wVk = VK_BACK;
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
/*
|
||||
Name: aiWin2000Unicode
|
||||
Copyright: Copyright (C) SIL International.
|
||||
Documentation:
|
||||
Description:
|
||||
Documentation:
|
||||
Description:
|
||||
Create Date: 27 Jan 2009
|
||||
|
||||
Modified Date: 23 Jun 2014
|
||||
Authors: mcdurdin
|
||||
Related Files:
|
||||
Dependencies:
|
||||
Related Files:
|
||||
Dependencies:
|
||||
|
||||
Bugs:
|
||||
Todo:
|
||||
Notes:
|
||||
Bugs:
|
||||
Todo:
|
||||
Notes:
|
||||
History: 27 Jan 2009 - mcdurdin - I1797 - Add fallback for AIWin2000 app integration
|
||||
11 Dec 2009 - mcdurdin - I934 - x64 - Initial version
|
||||
24 Jun 2010 - mcdurdin - I2436 - Add space to context for AIWin2000Unicode when not matched
|
||||
|
|
@ -43,7 +43,7 @@ public:
|
|||
virtual BOOL QueueAction(int ItemType, DWORD dwData);
|
||||
|
||||
/* Information functions */
|
||||
|
||||
|
||||
virtual BOOL CanHandleWindow(HWND ahwnd);
|
||||
virtual BOOL IsWindowHandled(HWND ahwnd);
|
||||
virtual BOOL HandleWindow(HWND ahwnd);
|
||||
|
|
@ -59,9 +59,8 @@ public:
|
|||
virtual void SetContext(const WCHAR* buf);
|
||||
|
||||
/* Queue and sending functions */
|
||||
|
||||
|
||||
virtual BOOL SendActions(); // I4196
|
||||
virtual BOOL QueueDebugInformation(int ItemType, LPGROUP Group, LPKEY Rule, PWSTR fcontext, PWSTR foutput, DWORD_PTR dwExtraFlags);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -43,22 +43,6 @@ typedef struct
|
|||
#define QIT_CAPSLOCK 8
|
||||
#define QIT_INVALIDATECONTEXT 9
|
||||
|
||||
// QueueDebugInformation ItemTypes
|
||||
#define QID_BEGIN_UNICODE 0
|
||||
#define QID_BEGIN_ANSI 1
|
||||
#define QID_GROUP_ENTER 2
|
||||
#define QID_GROUP_EXIT 3
|
||||
#define QID_RULE_ENTER 4
|
||||
#define QID_RULE_EXIT 5
|
||||
#define QID_MATCH_ENTER 6
|
||||
#define QID_MATCH_EXIT 7
|
||||
#define QID_NOMATCH_ENTER 8
|
||||
#define QID_NOMATCH_EXIT 9
|
||||
#define QID_END 10
|
||||
|
||||
#define QID_FLAG_RECURSIVE_OVERFLOW 0x0001
|
||||
#define QID_FLAG_NOMATCH 0x0002
|
||||
|
||||
#define QVK_EXTENDED 0x00010000 // Flag for QIT_VKEYDOWN to indicate an extended key
|
||||
#define QVK_KEYMASK 0x0000FFFF
|
||||
#define QVK_FLAGMASK 0xFFFF0000
|
||||
|
|
@ -178,15 +162,6 @@ public:
|
|||
|
||||
};
|
||||
|
||||
class AppContextWithStores : public AppContext // I4978
|
||||
{
|
||||
public:
|
||||
AppContextWithStores(int nKeyboardOptions);
|
||||
~AppContextWithStores();
|
||||
DWORD nKeyboardOptions;
|
||||
LPINTKEYBOARDOPTIONS KeyboardOptions;
|
||||
};
|
||||
|
||||
class AppIntegration:public AppActionQueue
|
||||
{
|
||||
protected:
|
||||
|
|
@ -214,7 +189,6 @@ public:
|
|||
|
||||
/* Queue and sending functions */
|
||||
|
||||
virtual BOOL QueueDebugInformation(int ItemType, LPGROUP Group, LPKEY Rule, PWSTR fcontext, PWSTR foutput, DWORD_PTR dwExtraFlags) = 0;
|
||||
void SetCurrentShiftState(int ShiftFlags) { FShiftFlags = ShiftFlags; }
|
||||
virtual BOOL SendActions() = 0; // I4196
|
||||
};
|
||||
|
|
|
|||
|
|
@ -93,34 +93,6 @@ static LPIMDLL AddIMDLL(LPINTKEYBOARDINFO lpkbi, LPSTR kbdpath, LPSTR dllfilenam
|
|||
return imd;
|
||||
}
|
||||
|
||||
/* Add a dll hook function to the list of hook functions associated with a single dll */
|
||||
|
||||
static BOOL AddIMDLLHook(LPIMDLL imd, LPSTR funcname, DWORD storeno, PWCHAR *dpString)
|
||||
{
|
||||
//SendDebugMessageFormat(0, sdmKeyboard, 0, "AddIMDLLHook: Enter");
|
||||
/* Get the procedure address for the function */
|
||||
|
||||
IMDLLHOOKProc dhp = (IMDLLHOOKProc) GetProcAddress(imd->hModule, funcname);
|
||||
if(!dhp) return FALSE;
|
||||
|
||||
/* Add the function to the list of functions in the DLL */
|
||||
|
||||
LPIMDLLHOOK hooks = new IMDLLHOOK[imd->nHooks+1];
|
||||
if(imd->nHooks > 0)
|
||||
{
|
||||
memcpy(hooks, imd->Hooks, sizeof(IMDLLHOOK) * imd->nHooks);
|
||||
delete imd->Hooks;
|
||||
}
|
||||
imd->Hooks = hooks;
|
||||
strncpy(imd->Hooks[imd->nHooks].name, funcname, 31);
|
||||
imd->Hooks[imd->nHooks].name[31] = 0;
|
||||
imd->Hooks[imd->nHooks].storeno = storeno;
|
||||
imd->Hooks[imd->nHooks].function = dhp;
|
||||
*dpString = (PWCHAR) &imd->Hooks[imd->nHooks++];
|
||||
//SendDebugMessageFormat(0, sdmKeyboard, 0, "AddIMDLLHook: Exit");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static km_kbp_action_item*
|
||||
kmnToCoreActionItem(int ItemType, DWORD dwData, WORD wVkey) {
|
||||
|
||||
|
|
@ -232,55 +204,6 @@ BOOL CallbackDLLs(LPINTKEYBOARDINFO lpkbi, PSTR cmd)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* Load the dlls associated with a keyboard */
|
||||
|
||||
BOOL LoadDLLs(LPINTKEYBOARDINFO lpkbi)
|
||||
{
|
||||
char fullname[_MAX_PATH];
|
||||
//SendDebugMessageFormat(0, sdmKeyboard, 0, "LoadDLLs: Enter");
|
||||
|
||||
if(lpkbi->nIMDLLs > 0) if(!UnloadDLLs(lpkbi)) return FALSE;
|
||||
|
||||
if (!GetKeyboardFileName(lpkbi->Name, fullname, _MAX_PATH)) {
|
||||
SendDebugMessageFormat(0, sdmKeyboard, 0, "LoadDLLs: Filename not found[%s]", lpkbi->Name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!lpkbi->Keyboard) {
|
||||
SendDebugMessageFormat(0, sdmKeyboard, 0, "LoadDLLs: Keyboard is null");
|
||||
return FALSE;
|
||||
}
|
||||
for(DWORD i = 0; i < lpkbi->Keyboard->cxStoreArray; i++)
|
||||
{
|
||||
LPSTORE s = &lpkbi->Keyboard->dpStoreArray[i];
|
||||
if(s->dwSystemID == TSS_CALLDEFINITION)
|
||||
{
|
||||
/* Break the store string into components */
|
||||
|
||||
PCHAR p = wstrtostr(s->dpString), q, r, context;
|
||||
|
||||
q = strtok_s(p, ":", &context);
|
||||
r = strtok_s(NULL, ":", &context);
|
||||
|
||||
if(!q || !r)
|
||||
{
|
||||
s->dwSystemID = TSS_CALLDEFINITION_LOADFAILED;
|
||||
delete[] p;
|
||||
continue;
|
||||
}
|
||||
|
||||
LPIMDLL imd = AddIMDLL(lpkbi, fullname, q);
|
||||
if(imd && AddIMDLLHook(imd, r, i, &s->dpString)) s->dwSystemID = TSS_CALLDEFINITION;
|
||||
else s->dwSystemID = TSS_CALLDEFINITION_LOADFAILED;
|
||||
|
||||
delete[] p;
|
||||
}
|
||||
}
|
||||
|
||||
//SendDebugMessageFormat(0, sdmKeyboard, 0, "LoadDLLs: Exit");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Both Core and Window keyboard processor can use this function
|
||||
BOOL UnloadDLLs(LPINTKEYBOARDINFO lpkbi)
|
||||
{
|
||||
|
|
@ -302,7 +225,7 @@ BOOL UnloadDLLs(LPINTKEYBOARDINFO lpkbi)
|
|||
lpkbi->IMDLLs = NULL;
|
||||
lpkbi->nIMDLLs = 0;
|
||||
|
||||
if (Globals::get_CoreIntegration() && lpkbi->lpCoreKeyboardState) {
|
||||
if (lpkbi->lpCoreKeyboardState) {
|
||||
km_kbp_state_imx_deregister_callback(lpkbi->lpCoreKeyboardState);
|
||||
}
|
||||
return TRUE;
|
||||
|
|
@ -330,26 +253,6 @@ BOOL DeactivateDLLs(LPINTKEYBOARDINFO lpkbi)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
void CallDLL(LPINTKEYBOARDINFO lpkbi, DWORD storenum)
|
||||
{
|
||||
//SendDebugMessageFormat(0, sdmKeyboard, 0, "CallDll: Enter");
|
||||
if (!lpkbi->Keyboard) return;
|
||||
if(storenum >= lpkbi->Keyboard->cxStoreArray) return;
|
||||
|
||||
LPSTORE s = &lpkbi->Keyboard->dpStoreArray[storenum];
|
||||
if(s->dwSystemID != TSS_CALLDEFINITION) return;
|
||||
if(s->dpString == NULL) return;
|
||||
LPIMDLLHOOK imdh = (LPIMDLLHOOK) s->dpString;
|
||||
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if(!_td) return;
|
||||
|
||||
if(_td->TIPFUpdateable) { // I4452
|
||||
(*imdh->function)(_td->state.msg.hwnd, _td->state.vkey, _td->state.charCode, Globals::get_ShiftState());
|
||||
}
|
||||
//SendDebugMessageFormat(0, sdmKeyboard, 0, "CallDll: Exit");
|
||||
}
|
||||
|
||||
// The callback function called by the Core Keyboardprocessor
|
||||
extern "C" uint8_t IM_CallBackCore(km_kbp_state *km_state, uint32_t UniqueStoreNo, void *callbackObject) {
|
||||
//SendDebugMessageFormat(0, sdmKeyboard, 0, "IM_CallBackCore: Enter");
|
||||
|
|
@ -402,90 +305,84 @@ extern "C" BOOL _declspec(dllexport) WINAPI KMSetOutput(PWSTR buf, DWORD backlen
|
|||
if (!_td->app)
|
||||
return FALSE;
|
||||
|
||||
if (!Globals::get_CoreIntegration()) { // TODO: 5442 Remove If and fix indent
|
||||
while (backlen-- > 0)
|
||||
_td->app->QueueAction(QIT_BACK, BK_DEFAULT);
|
||||
while (*buf)
|
||||
_td->app->QueueAction(QIT_CHAR, *buf++);
|
||||
return TRUE;
|
||||
} else {
|
||||
if (!_td->lpActiveKeyboard || !_td->lpActiveKeyboard->lpCoreKeyboardState) {
|
||||
SendDebugMessageFormat(0, sdmKeyboard, 0, "KMSetOutputCore: no active state");
|
||||
return FALSE;
|
||||
}
|
||||
DWORD numActions = backlen + (DWORD)wcslen(buf);
|
||||
DWORD idx = 0;
|
||||
km_kbp_action_item *actionItems = new km_kbp_action_item[numActions + 1];
|
||||
|
||||
// The actions sent to the core processor need to set the expected_type
|
||||
// correctly. To do this need to check the context as we process the
|
||||
// backspaces.
|
||||
km_kbp_context_item *citems = nullptr;
|
||||
if (KM_KBP_STATUS_OK != kbp_state_get_intermediate_context(_td->lpActiveKeyboard->lpCoreKeyboardState, &citems)) {
|
||||
delete[] actionItems;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DWORD context_length = (DWORD)km_kbp_context_item_list_size(citems);
|
||||
WCHAR *contextString = new WCHAR[(context_length * 3) + 1]; // *3 if every context item was a deadkey
|
||||
if (!ContextItemToAppContext(citems, contextString, context_length)) {
|
||||
km_kbp_context_items_dispose(citems);
|
||||
delete[] contextString;
|
||||
delete[] actionItems;
|
||||
return FALSE;
|
||||
}
|
||||
km_kbp_context_items_dispose(citems);
|
||||
AppContext context;
|
||||
context.Set(contextString);
|
||||
delete[] contextString;
|
||||
|
||||
while (backlen-- > 0) {
|
||||
actionItems[idx].type = KM_KBP_IT_BACK;
|
||||
WCHAR *CodeUnitPtr;
|
||||
const int DeadKeyLength = 3;
|
||||
const int SurrogateLength = 2;
|
||||
const int SingleCharLength = 1;
|
||||
if (context.CharIsDeadkey()) {
|
||||
CodeUnitPtr = context.BufMax(DeadKeyLength);
|
||||
CodeUnitPtr += 2;
|
||||
actionItems[idx].backspace.expected_type = KM_KBP_BT_MARKER;
|
||||
actionItems[idx].backspace.expected_value = (uintptr_t)*CodeUnitPtr;
|
||||
} else if (context.CharIsSurrogatePair()) {
|
||||
CodeUnitPtr = context.BufMax(SurrogateLength);
|
||||
actionItems[idx].backspace.expected_type = KM_KBP_BT_CHAR;
|
||||
actionItems[idx].backspace.expected_value = (DWORD)Uni_SurrogateToUTF32(*CodeUnitPtr, *(CodeUnitPtr + 1));
|
||||
} else if (!context.IsEmpty()) {
|
||||
CodeUnitPtr = context.BufMax(SingleCharLength);
|
||||
actionItems[idx].backspace.expected_type = KM_KBP_BT_CHAR;
|
||||
actionItems[idx].backspace.expected_value = (DWORD)*CodeUnitPtr;
|
||||
} else {
|
||||
actionItems[idx].backspace.expected_type = KM_KBP_BT_UNKNOWN;
|
||||
actionItems[idx].backspace.expected_value = 0;
|
||||
}
|
||||
context.Delete();
|
||||
idx++;
|
||||
}
|
||||
|
||||
while (*buf) {
|
||||
actionItems[idx].type = KM_KBP_IT_CHAR;
|
||||
if (Uni_IsSurrogate1(*buf) && Uni_IsSurrogate2(*(buf + 1))) {
|
||||
actionItems[idx].character = Uni_SurrogateToUTF32(*buf, *(buf + 1));
|
||||
buf++;
|
||||
} else {
|
||||
actionItems[idx].character = (DWORD)(*buf);
|
||||
}
|
||||
buf++;
|
||||
idx++;
|
||||
}
|
||||
actionItems[idx].type = KM_KBP_IT_END;
|
||||
if (KM_KBP_STATUS_OK != km_kbp_state_queue_action_items(_td->lpActiveKeyboard->lpCoreKeyboardState, actionItems)) {
|
||||
delete[] actionItems;
|
||||
return FALSE;
|
||||
}
|
||||
delete[] actionItems;
|
||||
//SendDebugMessageFormat(0, sdmKeyboard, 0, "KMSetOutputCore: Exit");
|
||||
return TRUE;
|
||||
if (!_td->lpActiveKeyboard || !_td->lpActiveKeyboard->lpCoreKeyboardState) {
|
||||
SendDebugMessageFormat(0, sdmKeyboard, 0, "KMSetOutputCore: no active state");
|
||||
return FALSE;
|
||||
}
|
||||
DWORD numActions = backlen + (DWORD)wcslen(buf);
|
||||
DWORD idx = 0;
|
||||
km_kbp_action_item *actionItems = new km_kbp_action_item[numActions + 1];
|
||||
|
||||
// The actions sent to the core processor need to set the expected_type
|
||||
// correctly. To do this need to check the context as we process the
|
||||
// backspaces.
|
||||
km_kbp_context_item *citems = nullptr;
|
||||
if (KM_KBP_STATUS_OK != kbp_state_get_intermediate_context(_td->lpActiveKeyboard->lpCoreKeyboardState, &citems)) {
|
||||
delete[] actionItems;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DWORD context_length = (DWORD)km_kbp_context_item_list_size(citems);
|
||||
WCHAR *contextString = new WCHAR[(context_length * 3) + 1]; // *3 if every context item was a deadkey
|
||||
if (!ContextItemToAppContext(citems, contextString, context_length)) {
|
||||
km_kbp_context_items_dispose(citems);
|
||||
delete[] contextString;
|
||||
delete[] actionItems;
|
||||
return FALSE;
|
||||
}
|
||||
km_kbp_context_items_dispose(citems);
|
||||
AppContext context;
|
||||
context.Set(contextString);
|
||||
delete[] contextString;
|
||||
|
||||
while (backlen-- > 0) {
|
||||
actionItems[idx].type = KM_KBP_IT_BACK;
|
||||
WCHAR *CodeUnitPtr;
|
||||
const int DeadKeyLength = 3;
|
||||
const int SurrogateLength = 2;
|
||||
const int SingleCharLength = 1;
|
||||
if (context.CharIsDeadkey()) {
|
||||
CodeUnitPtr = context.BufMax(DeadKeyLength);
|
||||
CodeUnitPtr += 2;
|
||||
actionItems[idx].backspace.expected_type = KM_KBP_BT_MARKER;
|
||||
actionItems[idx].backspace.expected_value = (uintptr_t)*CodeUnitPtr;
|
||||
} else if (context.CharIsSurrogatePair()) {
|
||||
CodeUnitPtr = context.BufMax(SurrogateLength);
|
||||
actionItems[idx].backspace.expected_type = KM_KBP_BT_CHAR;
|
||||
actionItems[idx].backspace.expected_value = (DWORD)Uni_SurrogateToUTF32(*CodeUnitPtr, *(CodeUnitPtr + 1));
|
||||
} else if (!context.IsEmpty()) {
|
||||
CodeUnitPtr = context.BufMax(SingleCharLength);
|
||||
actionItems[idx].backspace.expected_type = KM_KBP_BT_CHAR;
|
||||
actionItems[idx].backspace.expected_value = (DWORD)*CodeUnitPtr;
|
||||
} else {
|
||||
actionItems[idx].backspace.expected_type = KM_KBP_BT_UNKNOWN;
|
||||
actionItems[idx].backspace.expected_value = 0;
|
||||
}
|
||||
context.Delete();
|
||||
idx++;
|
||||
}
|
||||
|
||||
while (*buf) {
|
||||
actionItems[idx].type = KM_KBP_IT_CHAR;
|
||||
if (Uni_IsSurrogate1(*buf) && Uni_IsSurrogate2(*(buf + 1))) {
|
||||
actionItems[idx].character = Uni_SurrogateToUTF32(*buf, *(buf + 1));
|
||||
buf++;
|
||||
} else {
|
||||
actionItems[idx].character = (DWORD)(*buf);
|
||||
}
|
||||
buf++;
|
||||
idx++;
|
||||
}
|
||||
actionItems[idx].type = KM_KBP_IT_END;
|
||||
if (KM_KBP_STATUS_OK != km_kbp_state_queue_action_items(_td->lpActiveKeyboard->lpCoreKeyboardState, actionItems)) {
|
||||
delete[] actionItems;
|
||||
return FALSE;
|
||||
}
|
||||
delete[] actionItems;
|
||||
//SendDebugMessageFormat(0, sdmKeyboard, 0, "KMSetOutputCore: Exit");
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
extern "C" BOOL _declspec(dllexport) WINAPI KMQueueAction(int ItemType, DWORD dwData) {
|
||||
|
|
@ -496,61 +393,53 @@ extern "C" BOOL _declspec(dllexport) WINAPI KMQueueAction(int ItemType, DWORD dw
|
|||
if (!_td->app)
|
||||
return FALSE;
|
||||
|
||||
if (!Globals::get_CoreIntegration()) {
|
||||
return _td->app->QueueAction(ItemType, dwData); // TODO: 5442 Remove
|
||||
} else {
|
||||
if (!_td->lpActiveKeyboard || !_td->lpActiveKeyboard->lpCoreKeyboardState) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
km_kbp_action_item *actionItem = kmnToCoreActionItem(ItemType, dwData, _td->state.vkey);
|
||||
km_kbp_status_codes error_status =
|
||||
(km_kbp_status_codes)km_kbp_state_queue_action_items(_td->lpActiveKeyboard->lpCoreKeyboardState, actionItem);
|
||||
if (error_status != KM_KBP_STATUS_OK) {
|
||||
delete[] actionItem;
|
||||
SendDebugMessageFormat(0, sdmKeyboard, 0, "KMQueueAction: Error core queue_action_items error status:[%lu]",error_status);
|
||||
return FALSE;
|
||||
}
|
||||
delete[] actionItem;
|
||||
//SendDebugMessageFormat(0, sdmKeyboard, 0, "KMQueueActionCore: Exit");
|
||||
return TRUE;
|
||||
if (!_td->lpActiveKeyboard || !_td->lpActiveKeyboard->lpCoreKeyboardState) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
km_kbp_action_item *actionItem = kmnToCoreActionItem(ItemType, dwData, _td->state.vkey);
|
||||
km_kbp_status_codes error_status =
|
||||
(km_kbp_status_codes)km_kbp_state_queue_action_items(_td->lpActiveKeyboard->lpCoreKeyboardState, actionItem);
|
||||
if (error_status != KM_KBP_STATUS_OK) {
|
||||
delete[] actionItem;
|
||||
SendDebugMessageFormat(0, sdmKeyboard, 0, "KMQueueAction: Error core queue_action_items error status:[%lu]",error_status);
|
||||
return FALSE;
|
||||
}
|
||||
delete[] actionItem;
|
||||
//SendDebugMessageFormat(0, sdmKeyboard, 0, "KMQueueActionCore: Exit");
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
extern "C" BOOL _declspec(dllexport) WINAPI KMGetContext(PWSTR buf, DWORD len)
|
||||
{
|
||||
//SendDebugMessageFormat(0, sdmKeyboard, 0, "KMGetContext: Enter");
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if(!_td) return FALSE;
|
||||
if(!_td->app) return FALSE;
|
||||
// TODO: 5442 KMGetContext is already public call (even though it is pointer) Rather then making a new KMGetContextCore
|
||||
// This has been modified to check for core processor once we move to core processor the old Windows Platmform calling of
|
||||
// ContextBuff can be removed
|
||||
//
|
||||
if(!Globals::get_CoreIntegration()){
|
||||
PWSTR q = _td->app->ContextBufMax(len);
|
||||
if (!q)
|
||||
return FALSE; // context buf does not exist
|
||||
|
||||
wcscpy_s(buf, len + 1, q); // I3091
|
||||
return TRUE;
|
||||
} else {
|
||||
if (!_td->lpActiveKeyboard || !_td->lpActiveKeyboard->lpCoreKeyboardState) {
|
||||
return FALSE;
|
||||
}
|
||||
km_kbp_context_item *citems = nullptr;
|
||||
if (KM_KBP_STATUS_OK != kbp_state_get_intermediate_context(_td->lpActiveKeyboard->lpCoreKeyboardState, &citems)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!ContextItemToAppContext(citems, buf, len)) {
|
||||
km_kbp_context_items_dispose(citems);
|
||||
return FALSE;
|
||||
}
|
||||
km_kbp_context_items_dispose(citems);
|
||||
//SendDebugMessageFormat(0, sdmKeyboard, 0, "KMGetContext: Exit");
|
||||
return TRUE;
|
||||
if(!_td) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(!_td->app) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!_td->lpActiveKeyboard || !_td->lpActiveKeyboard->lpCoreKeyboardState) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
km_kbp_context_item *citems = nullptr;
|
||||
if (KM_KBP_STATUS_OK != kbp_state_get_intermediate_context(_td->lpActiveKeyboard->lpCoreKeyboardState, &citems)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!ContextItemToAppContext(citems, buf, len)) {
|
||||
km_kbp_context_items_dispose(citems);
|
||||
return FALSE;
|
||||
}
|
||||
km_kbp_context_items_dispose(citems);
|
||||
//SendDebugMessageFormat(0, sdmKeyboard, 0, "KMGetContext: Exit");
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
extern "C" BOOL _declspec(dllexport) WINAPI KMDisplayIM(HWND hwnd, BOOL FShowAlways)
|
||||
|
|
@ -650,8 +539,8 @@ BOOL IsIMWindow(HWND hwnd)
|
|||
/* Add a dll hook function to the list of hook functions associated with a single dll */
|
||||
|
||||
static BOOL
|
||||
AddIMDLLHookCore(LPIMDLL imd, LPSTR funcname, DWORD storeno) {
|
||||
//SendDebugMessageFormat(0, sdmKeyboard, 0, "AddIMDLLHookCore: Enter");
|
||||
AddIMDLLHook(LPIMDLL imd, LPSTR funcname, DWORD storeno) {
|
||||
//SendDebugMessageFormat(0, sdmKeyboard, 0, "AddIMDLLHook: Enter");
|
||||
/* Get the procedure address for the function */
|
||||
IMDLLHOOKProc dhp = (IMDLLHOOKProc)GetProcAddress(imd->hModule, funcname);
|
||||
if (!dhp)
|
||||
|
|
@ -670,15 +559,15 @@ AddIMDLLHookCore(LPIMDLL imd, LPSTR funcname, DWORD storeno) {
|
|||
imd->Hooks[imd->nHooks].storeno = storeno;
|
||||
imd->Hooks[imd->nHooks].function = dhp;
|
||||
imd->nHooks++;
|
||||
//SendDebugMessageFormat(0, sdmKeyboard, 0, "AddIMDLLHookCore: Exit");
|
||||
//SendDebugMessageFormat(0, sdmKeyboard, 0, "AddIMDLLHook: Exit");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Load the dlls associated with a keyboard */
|
||||
BOOL
|
||||
LoadDLLsCore(LPINTKEYBOARDINFO lpkbi) {
|
||||
LoadDLLs(LPINTKEYBOARDINFO lpkbi) {
|
||||
char fullname[_MAX_PATH];
|
||||
//SendDebugMessageFormat(0, sdmKeyboard, 0, "LoadDLLsCore: Enter");
|
||||
//SendDebugMessageFormat(0, sdmKeyboard, 0, "LoadDLLs: Enter");
|
||||
|
||||
if (lpkbi->nIMDLLs > 0)
|
||||
if (!UnloadDLLs(lpkbi))
|
||||
|
|
@ -694,11 +583,11 @@ LoadDLLsCore(LPINTKEYBOARDINFO lpkbi) {
|
|||
BOOL result = false;
|
||||
for (; imx_list->library_name; ++imx_list) {
|
||||
LPIMDLL imd = AddIMDLL(lpkbi, fullname, wstrtostr(reinterpret_cast<LPCWSTR>(imx_list->library_name)));
|
||||
if (imd && AddIMDLLHookCore(imd, wstrtostr(reinterpret_cast<LPCWSTR>(imx_list->function_name)), imx_list->imx_id)) {
|
||||
if (imd && AddIMDLLHook(imd, wstrtostr(reinterpret_cast<LPCWSTR>(imx_list->function_name)), imx_list->imx_id)) {
|
||||
result = TRUE;
|
||||
}
|
||||
else {
|
||||
SendDebugMessageFormat(0, sdmKeyboard, 0, "LoadDLLsCore: Error Loading Library name [%s], Function name [%s]",
|
||||
SendDebugMessageFormat(0, sdmKeyboard, 0, "LoadDLLs: Error Loading Library name [%s], Function name [%s]",
|
||||
wstrtostr(reinterpret_cast<PCWSTR>(imx_list->library_name)),
|
||||
wstrtostr(reinterpret_cast<PCWSTR>(imx_list->function_name)));
|
||||
}
|
||||
|
|
@ -707,7 +596,7 @@ LoadDLLsCore(LPINTKEYBOARDINFO lpkbi) {
|
|||
if (result) {
|
||||
km_kbp_state_imx_register_callback(lpkbi->lpCoreKeyboardState, IM_CallBackCore, (void *)lpkbi);
|
||||
}
|
||||
//SendDebugMessageFormat(0, sdmKeyboard, 0, "LoadDLLsCore: Exit");
|
||||
//SendDebugMessageFormat(0, sdmKeyboard, 0, "LoadDLLs: Exit");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,24 +19,19 @@
|
|||
#ifndef __CALLDLL_H
|
||||
#define __CALLDLL_H
|
||||
|
||||
BOOL LoadDLLs(LPINTKEYBOARDINFO lpkbi);
|
||||
BOOL UnloadDLLs(LPINTKEYBOARDINFO lpkbi);
|
||||
BOOL DeactivateDLLs(LPINTKEYBOARDINFO lpkbi);
|
||||
BOOL ActivateDLLs(LPINTKEYBOARDINFO lpkbi);
|
||||
|
||||
// TODO: 5444 This will become the only LoadDLLs function
|
||||
/**
|
||||
* Load the all the dlls used by the current keyboard
|
||||
* @param lpkbi The keyboard for which to load the dlls
|
||||
* @return BOOL True on success
|
||||
*/
|
||||
BOOL LoadDLLsCore(LPINTKEYBOARDINFO lpkbi);
|
||||
BOOL LoadDLLs(LPINTKEYBOARDINFO lpkbi);
|
||||
BOOL UnloadDLLs(LPINTKEYBOARDINFO lpkbi);
|
||||
BOOL DeactivateDLLs(LPINTKEYBOARDINFO lpkbi);
|
||||
BOOL ActivateDLLs(LPINTKEYBOARDINFO lpkbi);
|
||||
|
||||
|
||||
BOOL IsIMWindow(HWND hwnd);
|
||||
|
||||
void CallDLL(LPINTKEYBOARDINFO lpkbi, DWORD storenum);
|
||||
|
||||
// Callback function used by the core processor to call out to 3rd Party Library functions
|
||||
extern "C" uint8_t IM_CallBackCore(km_kbp_state *km_state, uint32_t UniqueStoreNo, void *callbackObject);
|
||||
|
||||
|
|
|
|||
|
|
@ -29,73 +29,3 @@
|
|||
BOOL IsCapsLockOn(void) {
|
||||
return GetKeyState(VK_CAPITAL) & 1;
|
||||
}
|
||||
|
||||
void ResetCapsLock(void)
|
||||
{
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if (!_td) return;
|
||||
if (!_td->lpActiveKeyboard) return;
|
||||
if (!_td->lpActiveKeyboard->Keyboard) return;
|
||||
|
||||
SendDebugMessageFormat(0, sdmGlobal, 0, "ResetCapsLock: enter");
|
||||
|
||||
if (_td->lpActiveKeyboard->Keyboard->dwFlags & KF_CAPSALWAYSOFF)
|
||||
{
|
||||
SendDebugMessageFormat(0, sdmGlobal, 0, "ResetCapsLock: caps lock should be always off");
|
||||
if (IsCapsLockOn())
|
||||
{
|
||||
SendDebugMessageFormat(0, sdmGlobal, 0, "ResetCapsLock: caps lock is on, switching off caps lock");
|
||||
keybd_event(VK_CAPITAL, 0x3A, 0, 0);
|
||||
keybd_event(VK_CAPITAL, 0x3A, 0 | KEYEVENTF_KEYUP, 0);
|
||||
}
|
||||
}
|
||||
SendDebugMessageFormat(0, sdmGlobal, 0, "ResetCapsLock: exit");
|
||||
}
|
||||
|
||||
|
||||
void KeyCapsLockPress(BOOL FIsUp) // I3284 - void // I3529
|
||||
{
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if (!_td) return;
|
||||
if (!_td->lpActiveKeyboard) return; // pass through to window
|
||||
if (!_td->lpActiveKeyboard->Keyboard) return;
|
||||
|
||||
if (_td->lpActiveKeyboard->Keyboard->dwFlags & KF_CAPSONONLY)
|
||||
{
|
||||
SendDebugMessageFormat(0, sdmAIDefault, 0, "KeyCapsLockPress: KF_CAPSONONLY: FIsUp=%d CapsState=%d", FIsUp, IsCapsLockOn());
|
||||
if (FIsUp && !IsCapsLockOn()) // I267 - 24/11/2006 invert GetKeyState test
|
||||
{
|
||||
keybd_event(VK_CAPITAL, SCAN_FLAG_KEYMAN_KEY_EVENT, 0, 0);
|
||||
keybd_event(VK_CAPITAL, SCAN_FLAG_KEYMAN_KEY_EVENT, KEYEVENTF_KEYUP, 0);
|
||||
}
|
||||
}
|
||||
else if (_td->lpActiveKeyboard->Keyboard->dwFlags & KF_CAPSALWAYSOFF)
|
||||
{
|
||||
SendDebugMessageFormat(0, sdmAIDefault, 0, "KeyCapsLockPress: KF_CAPSALWAYSOFF: FIsUp=%d CapsState=%d", FIsUp, IsCapsLockOn());
|
||||
if (!FIsUp && IsCapsLockOn())
|
||||
{ // I267 - 24/11/2006 invert GetKeyState test
|
||||
keybd_event(VK_CAPITAL, SCAN_FLAG_KEYMAN_KEY_EVENT, KEYEVENTF_KEYUP, 0);
|
||||
keybd_event(VK_CAPITAL, SCAN_FLAG_KEYMAN_KEY_EVENT, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void KeyShiftPress(BOOL FIsUp) // I3284 - void // I3529
|
||||
{
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if (!_td) return;
|
||||
if (!_td->lpActiveKeyboard) return; // pass through to window
|
||||
if (!_td->lpActiveKeyboard->Keyboard) return;
|
||||
|
||||
if (_td->lpActiveKeyboard->Keyboard->dwFlags & KF_SHIFTFREESCAPS)
|
||||
{
|
||||
SendDebugMessageFormat(0, sdmAIDefault, 0, "KeyShiftPress: KF_SHIFTFREESCAPS: FIsUp=%d CapsState=%d", FIsUp, IsCapsLockOn());
|
||||
if (!FIsUp && IsCapsLockOn())
|
||||
{
|
||||
keybd_event(VK_CAPITAL, SCAN_FLAG_KEYMAN_KEY_EVENT, 0, 0);
|
||||
keybd_event(VK_CAPITAL, SCAN_FLAG_KEYMAN_KEY_EVENT, KEYEVENTF_KEYUP, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,5 @@
|
|||
#define __CAPSSTATE_H
|
||||
|
||||
BOOL IsCapsLockOn(void);
|
||||
void ResetCapsLock(void);
|
||||
void KeyCapsLockPress(BOOL FIsUp);
|
||||
void KeyShiftPress(BOOL FIsUp);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -151,7 +151,6 @@ public:
|
|||
|
||||
static BOOL get_debug_KeymanLog();
|
||||
static BOOL get_debug_ToConsole();
|
||||
static BOOL get_CoreIntegration();
|
||||
static void LoadDebugSettings();
|
||||
};
|
||||
|
||||
|
|
@ -216,8 +215,6 @@ typedef struct tagKEYMAN64THREADDATA
|
|||
FInitialised,
|
||||
FInitialising;
|
||||
|
||||
char ForceFileName[MAX_PATH];
|
||||
|
||||
DWORD ActiveKeymanID;
|
||||
|
||||
/* TIP Globals */
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
/*
|
||||
Name: glossary
|
||||
Copyright: Copyright (C) SIL International.
|
||||
Documentation:
|
||||
Description:
|
||||
Documentation:
|
||||
Description:
|
||||
Create Date: 20 Jul 2008
|
||||
|
||||
Modified Date: 28 May 2014
|
||||
Authors: mcdurdin
|
||||
Related Files:
|
||||
Dependencies:
|
||||
Related Files:
|
||||
Dependencies:
|
||||
|
||||
Bugs:
|
||||
Todo:
|
||||
Notes:
|
||||
Bugs:
|
||||
Todo:
|
||||
Notes:
|
||||
History: 20 Jul 2008 - mcdurdin - I1498 - Fix keyboard switching for Shadow keyboards on Vista+
|
||||
20 Jul 2008 - mcdurdin - I1546 - Fix language switch with ids >= x80000000
|
||||
20 Jul 2008 - mcdurdin - I1545 - Fix registry leak
|
||||
|
|
@ -38,9 +38,9 @@ BOOL HKLIsIME(HKL hkl) // I1498 - fix keyboard switching for shadow keyboards o
|
|||
if( (GetVersion() & 0xFF) >= 6 ) return FALSE;
|
||||
if( (GetVersion() & 0x8000000) == 0x8000000 || (GetVersion() & 0xFF) == 4 )
|
||||
r = GetSystemMetrics(SM_DBCSENABLED);
|
||||
else
|
||||
else
|
||||
r = GetSystemMetrics(SM_IMMENABLED);
|
||||
|
||||
|
||||
return r && ImmIsIME(hkl);
|
||||
}
|
||||
#pragma warning(default: 4996)
|
||||
|
|
@ -99,12 +99,12 @@ DWORD HKLToKeyboardID(HKL hkl)
|
|||
return (DWORD) LOWORD(hkl);
|
||||
}
|
||||
|
||||
for(len=16, n = i = 0; RegEnumKeyEx(hkey, i, str, &len, 0, NULL, NULL, &ft) == ERROR_SUCCESS;
|
||||
len = 16, i++, n=0)
|
||||
for(len=16, n = i = 0; RegEnumKeyEx(hkey, i, str, &len, 0, NULL, NULL, &ft) == ERROR_SUCCESS;
|
||||
len = 16, i++, n=0)
|
||||
{
|
||||
RegOpenKeyEx(hkey, str, NULL, KEY_READ, &hsubkey);
|
||||
len = 16;
|
||||
if(RegQueryValueEx(hsubkey, REGSZ_LayoutID, NULL, NULL, (LPBYTE) str2, &len) == ERROR_SUCCESS)
|
||||
if(RegQueryValueEx(hsubkey, REGSZ_LayoutID, NULL, NULL, (LPBYTE) str2, &len) == ERROR_SUCCESS)
|
||||
{
|
||||
n = strtoul(str2, NULL, 16); // I1546
|
||||
if(n == LayoutID)
|
||||
|
|
@ -120,7 +120,7 @@ DWORD HKLToKeyboardID(HKL hkl)
|
|||
}
|
||||
|
||||
RegCloseKey(hkey);
|
||||
|
||||
|
||||
//SendDebugMessageFormat(0, sdmGlobal, 0, "HKLToKeyboardID: fails[2], return LOWORD(hkl)=%x", LOWORD(hkl));
|
||||
return (DWORD) LOWORD(hkl); // should never happen
|
||||
}
|
||||
|
|
@ -143,11 +143,11 @@ WORD HKLToLayoutNumber(HKL hkl)
|
|||
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSZ_SystemKeyboardLayouts, NULL, KEY_READ, &hkey) != ERROR_SUCCESS)
|
||||
return 0;
|
||||
|
||||
for(len=16, n = i = 0; RegEnumKeyEx(hkey, i, str, &len, 0, NULL, NULL, &ft) == ERROR_SUCCESS; len = 16, i++, n=0)
|
||||
for(len=16, n = i = 0; RegEnumKeyEx(hkey, i, str, &len, 0, NULL, NULL, &ft) == ERROR_SUCCESS; len = 16, i++, n=0)
|
||||
{
|
||||
RegOpenKeyEx(hkey, str, NULL, KEY_READ, &hsubkey);
|
||||
len = 16;
|
||||
if(RegQueryValueEx(hsubkey, REGSZ_LayoutID, NULL, NULL, (LPBYTE) str2, &len) == ERROR_SUCCESS)
|
||||
if(RegQueryValueEx(hsubkey, REGSZ_LayoutID, NULL, NULL, (LPBYTE) str2, &len) == ERROR_SUCCESS)
|
||||
{
|
||||
if(strtoul(str2, NULL, 16) == LayoutID) break; // strtoul - I1546
|
||||
}
|
||||
|
|
@ -166,37 +166,3 @@ WORD HKLToLayoutID(HKL hkl)
|
|||
|
||||
return HIWORD(hkl) & 0x0FFF;
|
||||
}
|
||||
|
||||
DWORD EthnologueCodeToKeymanID(DWORD EthCode)
|
||||
{
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if(!_td) return KEYMANID_NONKEYMAN;
|
||||
|
||||
for(int i = 0; i < _td->nKeyboards; i++)
|
||||
{
|
||||
if(!_td->lpKeyboards[i].Keyboard && !LoadlpKeyboard(i))
|
||||
{
|
||||
SendDebugMessageFormat(0,sdmGlobal,0,
|
||||
"EthnologueCodeToKeymanID: Unable to load keyboard %s", _td->lpKeyboards[i].Name);
|
||||
return KEYMANID_NONKEYMAN;
|
||||
}
|
||||
|
||||
PWSTR ps = GetSystemStore(_td->lpKeyboards[i].Keyboard, TSS_ETHNOLOGUECODE);
|
||||
if(ps)
|
||||
{
|
||||
SendDebugMessageFormat(0,sdmGlobal,0,"EthnologueCodeToKeymanID: %s %ws %x", _td->lpKeyboards[i].Name, ps, EthnologueStringCodeToDWord(ps));
|
||||
if(EthnologueStringCodeToDWord(ps) == EthCode) return _td->lpKeyboards[i].KeymanID;
|
||||
}
|
||||
}
|
||||
|
||||
return KEYMANID_NONKEYMAN;
|
||||
}
|
||||
|
||||
DWORD EthnologueStringCodeToDWord(PWSTR EthCode)
|
||||
{
|
||||
if(wcslen(EthCode) < 3 || wcslen(EthCode) > 4) return (DWORD)-1;
|
||||
return (LOBYTE(EthCode[0])) |
|
||||
(LOBYTE(EthCode[1]) << 8) |
|
||||
(LOBYTE(EthCode[2]) << 16) |
|
||||
(LOBYTE(EthCode[3]) << 24);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -288,9 +288,6 @@ static BOOL
|
|||
f_debug_KeymanLog = FALSE,
|
||||
f_debug_ToConsole = FALSE;
|
||||
|
||||
static BOOL
|
||||
f_CoreIntegration = TRUE;
|
||||
|
||||
#pragma data_seg()
|
||||
/***************************************************************************/
|
||||
|
||||
|
|
@ -365,8 +362,6 @@ BOOL Globals::get_MnemonicDeadkeyConversionMode() { return f_MnemonicDeadkeyConv
|
|||
BOOL Globals::get_debug_KeymanLog() { return f_debug_KeymanLog; }
|
||||
BOOL Globals::get_debug_ToConsole() { return f_debug_ToConsole; }
|
||||
|
||||
BOOL Globals::get_CoreIntegration() { return f_CoreIntegration; }
|
||||
|
||||
void Globals::SetBaseKeyboardName(wchar_t *baseKeyboardName, wchar_t *baseKeyboardNameAlt) { // I4583
|
||||
wcscpy_s(f_BaseKeyboardName, baseKeyboardName);
|
||||
wcscpy_s(f_BaseKeyboardNameAlt, baseKeyboardNameAlt);
|
||||
|
|
@ -385,9 +380,6 @@ void Globals::SetBaseKeyboardFlags(char *baseKeyboard, BOOL simulateAltGr, BOOL
|
|||
be changed until Keyman is restarted.
|
||||
*/
|
||||
BOOL Globals::InitSettings() {
|
||||
/* Check for common core vs windows core */
|
||||
f_CoreIntegration = Reg_GetDebugFlag(REGSZ_Flag_UseKeymanCore, TRUE);
|
||||
SendDebugMessageFormat(0, sdmAIDefault, 0, "Globals::InitSettings - Coreintegration set in '" REGSZ_Flag_UseKeymanCore "' to %x", f_CoreIntegration);
|
||||
f_vk_prefix = _VK_PREFIX_DEFAULT;
|
||||
RegistryReadOnly reg(HKEY_LOCAL_MACHINE);
|
||||
if (reg.OpenKeyReadOnly(REGSZ_KeymanLM) &&
|
||||
|
|
|
|||
|
|
@ -19,10 +19,8 @@
|
|||
*/
|
||||
#include "pch.h"
|
||||
|
||||
void IntSaveKeyboardOption(LPCSTR key, LPINTKEYBOARDINFO kp, int nStoreToSave);
|
||||
BOOL IntLoadKeyboardOptions(LPCSTR key, LPINTKEYBOARDINFO kp);
|
||||
BOOL IntLoadKeyboardOptionsCore(LPCSTR key, LPINTKEYBOARDINFO kp, km_kbp_state* const state);
|
||||
void IntSaveKeyboardOptionREGCore(LPCSTR REGKey, LPINTKEYBOARDINFO kp, LPCWSTR key, LPWSTR value);
|
||||
BOOL IntLoadKeyboardOptionsRegistrytoCore(LPCSTR key, LPINTKEYBOARDINFO kp, km_kbp_state* const state);
|
||||
void IntSaveKeyboardOptionCoretoRegistry(LPCSTR REGKey, LPINTKEYBOARDINFO kp, LPCWSTR key, LPWSTR value);
|
||||
|
||||
static km_kbp_cp* CloneKMKBPCP(const km_kbp_cp* cp) {
|
||||
LPCWSTR buf = reinterpret_cast<LPCWSTR>(cp);
|
||||
|
|
@ -37,123 +35,12 @@ static km_kbp_cp* CloneKMKBPCPFromWSTR(LPWSTR buf) {
|
|||
return clone;
|
||||
}
|
||||
|
||||
void LoadKeyboardOptions(LPINTKEYBOARDINFO kp)
|
||||
{ // I3594
|
||||
IntLoadKeyboardOptions(REGSZ_KeyboardOptions, kp);
|
||||
}
|
||||
|
||||
void LoadSharedKeyboardOptions(LPINTKEYBOARDINFO kp)
|
||||
void SaveKeyboardOptionCoretoRegistry(LPINTKEYBOARDINFO kp, LPCWSTR key, LPWSTR value)
|
||||
{
|
||||
if(!DebugAssert(!Globals::get_CoreIntegration(), "LoadSharedKeyboardOptions: Error called in core integration mode")) {
|
||||
return;
|
||||
}
|
||||
// Called when another thread changes keyboard options and we are sharing keyboard settings
|
||||
assert(kp != NULL);
|
||||
assert(kp->Keyboard != NULL);
|
||||
|
||||
if(kp->KeyboardOptions != NULL) FreeKeyboardOptions(kp);
|
||||
|
||||
IntLoadKeyboardOptions(REGSZ_SharedKeyboardOptions, kp);
|
||||
IntSaveKeyboardOptionCoretoRegistry(REGSZ_KeyboardOptions, kp, key, value);
|
||||
}
|
||||
|
||||
void FreeKeyboardOptions(LPINTKEYBOARDINFO kp)
|
||||
{
|
||||
// This is a cleanup routine; we don't want to precondition all calls to it
|
||||
// so we do not assert
|
||||
if (kp == NULL || kp->Keyboard == NULL || kp->KeyboardOptions == NULL)
|
||||
return;
|
||||
|
||||
for(DWORD i = 0; i < kp->Keyboard->cxStoreArray; i++)
|
||||
if(kp->KeyboardOptions[i].Value)
|
||||
{
|
||||
kp->Keyboard->dpStoreArray[i].dpString = kp->KeyboardOptions[i].OriginalStore;
|
||||
delete kp->KeyboardOptions[i].Value;
|
||||
}
|
||||
delete kp->KeyboardOptions;
|
||||
kp->KeyboardOptions = NULL;
|
||||
}
|
||||
|
||||
void SetKeyboardOption(LPINTKEYBOARDINFO kp, int nStoreToSet, int nStoreToRead)
|
||||
{
|
||||
if (!DebugAssert(!Globals::get_CoreIntegration(), "SetKeyboardOption: Error called in core integration mode")) {
|
||||
return;
|
||||
}
|
||||
assert(kp != NULL);
|
||||
assert(kp->Keyboard != NULL);
|
||||
assert(kp->KeyboardOptions != NULL);
|
||||
assert(nStoreToSet >= 0);
|
||||
assert(nStoreToSet < (int) kp->Keyboard->cxStoreArray);
|
||||
assert(nStoreToRead >= 0);
|
||||
assert(nStoreToRead < (int) kp->Keyboard->cxStoreArray);
|
||||
|
||||
LPSTORE sp = &kp->Keyboard->dpStoreArray[nStoreToRead];
|
||||
if(kp->KeyboardOptions[nStoreToSet].Value)
|
||||
{
|
||||
delete kp->KeyboardOptions[nStoreToSet].Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
kp->KeyboardOptions[nStoreToSet].OriginalStore = kp->Keyboard->dpStoreArray[nStoreToSet].dpString;
|
||||
}
|
||||
|
||||
kp->KeyboardOptions[nStoreToSet].Value = new WCHAR[wcslen(sp->dpString)+1];
|
||||
wcscpy_s(kp->KeyboardOptions[nStoreToSet].Value, wcslen(sp->dpString)+1, sp->dpString);
|
||||
kp->Keyboard->dpStoreArray[nStoreToSet].dpString = kp->KeyboardOptions[nStoreToSet].Value;
|
||||
}
|
||||
|
||||
void ResetKeyboardOption(LPINTKEYBOARDINFO kp, int nStoreToReset)
|
||||
{
|
||||
if (!DebugAssert(!Globals::get_CoreIntegration(), "ResetKeyboardOption: Error called in core integration mode")) {
|
||||
return;
|
||||
}
|
||||
assert(kp != NULL);
|
||||
assert(kp->Keyboard != NULL);
|
||||
assert(kp->KeyboardOptions != NULL);
|
||||
assert(nStoreToReset >= 0);
|
||||
assert(nStoreToReset < (int) kp->Keyboard->cxStoreArray);
|
||||
|
||||
if(kp->KeyboardOptions[nStoreToReset].Value)
|
||||
{
|
||||
kp->Keyboard->dpStoreArray[nStoreToReset].dpString = kp->KeyboardOptions[nStoreToReset].OriginalStore;
|
||||
delete kp->KeyboardOptions[nStoreToReset].Value;
|
||||
kp->KeyboardOptions[nStoreToReset].Value = NULL;
|
||||
|
||||
if(kp->Keyboard->dpStoreArray[nStoreToReset].dpName == NULL) return;
|
||||
|
||||
RegistryReadOnly r(HKEY_CURRENT_USER);
|
||||
if(r.OpenKeyReadOnly(REGSZ_KeymanActiveKeyboards) && r.OpenKeyReadOnly(kp->Name) && r.OpenKeyReadOnly(REGSZ_KeyboardOptions))
|
||||
{
|
||||
if(r.ValueExists(kp->Keyboard->dpStoreArray[nStoreToReset].dpName))
|
||||
{
|
||||
WCHAR val[256];
|
||||
if(!r.ReadString(kp->Keyboard->dpStoreArray[nStoreToReset].dpName, val, sizeof(val) / sizeof(val[0]))) return;
|
||||
if(!val[0]) return;
|
||||
val[255] = 0;
|
||||
kp->KeyboardOptions[nStoreToReset].Value = new WCHAR[wcslen(val)+1];
|
||||
wcscpy_s(kp->KeyboardOptions[nStoreToReset].Value, wcslen(val)+1, val);
|
||||
|
||||
kp->KeyboardOptions[nStoreToReset].OriginalStore = kp->Keyboard->dpStoreArray[nStoreToReset].dpString;
|
||||
kp->Keyboard->dpStoreArray[nStoreToReset].dpString = kp->KeyboardOptions[nStoreToReset].Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SaveKeyboardOption(LPINTKEYBOARDINFO kp, int nStoreToSave)
|
||||
{
|
||||
if (!DebugAssert(!Globals::get_CoreIntegration(), "SaveKeyboardOption: Error called in core integration mode")) {
|
||||
return;
|
||||
}
|
||||
IntSaveKeyboardOption(REGSZ_KeyboardOptions, kp, nStoreToSave);
|
||||
}
|
||||
|
||||
void SaveKeyboardOptionREGCore(LPINTKEYBOARDINFO kp, LPCWSTR key, LPWSTR value)
|
||||
{
|
||||
IntSaveKeyboardOptionREGCore(REGSZ_KeyboardOptions, kp, key, value);
|
||||
}
|
||||
|
||||
void IntSaveKeyboardOptionREGCore(LPCSTR REGKey, LPINTKEYBOARDINFO kp, LPCWSTR key, LPWSTR value)
|
||||
void IntSaveKeyboardOptionCoretoRegistry(LPCSTR REGKey, LPINTKEYBOARDINFO kp, LPCWSTR key, LPWSTR value)
|
||||
{
|
||||
assert(REGKey != NULL);
|
||||
assert(kp != NULL);
|
||||
|
|
@ -167,73 +54,13 @@ void IntSaveKeyboardOptionREGCore(LPCSTR REGKey, LPINTKEYBOARDINFO kp, LPCWSTR k
|
|||
}
|
||||
}
|
||||
|
||||
BOOL IntLoadKeyboardOptions(LPCSTR key, LPINTKEYBOARDINFO kp)
|
||||
void LoadKeyboardOptionsRegistrytoCore(LPINTKEYBOARDINFO kp, km_kbp_state* const state)
|
||||
{
|
||||
assert(key != NULL);
|
||||
assert(kp != NULL);
|
||||
assert(kp->Keyboard != NULL);
|
||||
assert(kp->KeyboardOptions == NULL);
|
||||
|
||||
kp->KeyboardOptions = new INTKEYBOARDOPTIONS[kp->Keyboard->cxStoreArray];
|
||||
memset(kp->KeyboardOptions, 0, sizeof(INTKEYBOARDOPTIONS) * kp->Keyboard->cxStoreArray);
|
||||
RegistryReadOnly r(HKEY_CURRENT_USER);
|
||||
if(r.OpenKeyReadOnly(REGSZ_KeymanActiveKeyboards) && r.OpenKeyReadOnly(kp->Name) && r.OpenKeyReadOnly(key))
|
||||
{
|
||||
WCHAR buf[256];
|
||||
int n = 0;
|
||||
while(r.GetValueNames(buf, sizeof(buf) / sizeof(buf[0]), n))
|
||||
{
|
||||
buf[255] = 0;
|
||||
WCHAR val[256];
|
||||
if(r.ReadString(buf, val, sizeof(val) / sizeof(val[0])) && val[0])
|
||||
{
|
||||
val[255] = 0;
|
||||
for(DWORD i = 0; i < kp->Keyboard->cxStoreArray; i++)
|
||||
{
|
||||
if(kp->Keyboard->dpStoreArray[i].dpName != NULL && _wcsicmp(kp->Keyboard->dpStoreArray[i].dpName, buf) == 0)
|
||||
{
|
||||
kp->KeyboardOptions[i].Value = new WCHAR[wcslen(val)+1];
|
||||
wcscpy_s(kp->KeyboardOptions[i].Value, wcslen(val)+1, val);
|
||||
|
||||
kp->KeyboardOptions[i].OriginalStore = kp->Keyboard->dpStoreArray[i].dpString;
|
||||
kp->Keyboard->dpStoreArray[i].dpString = kp->KeyboardOptions[i].Value;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
n++;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
SendDebugMessageFormat(0, sdmKeyboard, 0, "LoadKeyboardOptionsRegistrytoCore: Enter");
|
||||
IntLoadKeyboardOptionsRegistrytoCore(REGSZ_KeyboardOptions, kp, state);
|
||||
}
|
||||
|
||||
void IntSaveKeyboardOption(LPCSTR key, LPINTKEYBOARDINFO kp, int nStoreToSave)
|
||||
{
|
||||
assert(key != NULL);
|
||||
assert(kp != NULL);
|
||||
assert(kp->Keyboard != NULL);
|
||||
assert(kp->KeyboardOptions != NULL);
|
||||
assert(nStoreToSave >= 0);
|
||||
assert(nStoreToSave < (int) kp->Keyboard->cxStoreArray);
|
||||
|
||||
if(kp->Keyboard->dpStoreArray[nStoreToSave].dpName == NULL) return;
|
||||
|
||||
RegistryFullAccess r(HKEY_CURRENT_USER);
|
||||
if(r.OpenKey(REGSZ_KeymanActiveKeyboards, TRUE) && r.OpenKey(kp->Name, TRUE) && r.OpenKey(key, TRUE))
|
||||
{
|
||||
r.WriteString(kp->Keyboard->dpStoreArray[nStoreToSave].dpName, kp->Keyboard->dpStoreArray[nStoreToSave].dpString);
|
||||
}
|
||||
}
|
||||
|
||||
void LoadKeyboardOptionsREGCore(LPINTKEYBOARDINFO kp, km_kbp_state* const state)
|
||||
{
|
||||
SendDebugMessageFormat(0, sdmKeyboard, 0, "LoadKeyboardOptionsREGCore: Enter");
|
||||
IntLoadKeyboardOptionsCore(REGSZ_KeyboardOptions, kp, state);
|
||||
}
|
||||
|
||||
BOOL IntLoadKeyboardOptionsCore(LPCSTR key, LPINTKEYBOARDINFO kp, km_kbp_state* const state)
|
||||
BOOL IntLoadKeyboardOptionsRegistrytoCore(LPCSTR key, LPINTKEYBOARDINFO kp, km_kbp_state* const state)
|
||||
{
|
||||
assert(key != NULL);
|
||||
assert(kp != NULL);
|
||||
|
|
@ -243,7 +70,7 @@ BOOL IntLoadKeyboardOptionsCore(LPCSTR key, LPINTKEYBOARDINFO kp, km_kbp_state*
|
|||
km_kbp_status err_status = km_kbp_keyboard_get_attrs(kp->lpCoreKeyboard, &keyboardAttrs);
|
||||
if (err_status != KM_KBP_STATUS_OK) {
|
||||
SendDebugMessageFormat(
|
||||
0, sdmKeyboard, 0, "LoadKeyboardOptionsREGCore: km_kbp_keyboard_get_attrs failed with error status [%d]", err_status);
|
||||
0, sdmKeyboard, 0, "LoadKeyboardOptionsRegistrytoCore: km_kbp_keyboard_get_attrs failed with error status [%d]", err_status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -275,7 +102,7 @@ BOOL IntLoadKeyboardOptionsCore(LPCSTR key, LPINTKEYBOARDINFO kp, km_kbp_state*
|
|||
err_status = km_kbp_state_options_update(state, keyboardOpts);
|
||||
if (err_status != KM_KBP_STATUS_OK) {
|
||||
SendDebugMessageFormat(
|
||||
0, sdmKeyboard, 0, "LoadKeyboardOptionsREGCore: km_kbp_state_options_update failed with error status [%d]", err_status);
|
||||
0, sdmKeyboard, 0, "LoadKeyboardOptionsRegistrytoCore: km_kbp_state_options_update failed with error status [%d]", err_status);
|
||||
}
|
||||
for (int i = 0; i < n; i++) {
|
||||
delete[] keyboardOpts[i].value;
|
||||
|
|
@ -283,89 +110,3 @@ BOOL IntLoadKeyboardOptionsCore(LPCSTR key, LPINTKEYBOARDINFO kp, km_kbp_state*
|
|||
delete[] keyboardOpts;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
UpdateKeyboardOptionsCore(
|
||||
km_kbp_state* const lpCoreKeyboardState,
|
||||
km_kbp_option_item *lpCoreKeyboardOptions) {
|
||||
|
||||
int listSize = (int)km_kbp_options_list_size(lpCoreKeyboardOptions);
|
||||
// Create a option list based on this size look up each key and store the return value in it.
|
||||
// then at the end return this options list.
|
||||
BOOL changed = FALSE;
|
||||
km_kbp_cp const* retValue = nullptr;
|
||||
for (int i = 0; i < listSize; i++) {
|
||||
km_kbp_status err_status = km_kbp_state_option_lookup(lpCoreKeyboardState, lpCoreKeyboardOptions[i].scope, lpCoreKeyboardOptions[i].key,
|
||||
&retValue);
|
||||
if (err_status != KM_KBP_STATUS_OK) {
|
||||
SendDebugMessageFormat(
|
||||
0, sdmKeyboard, 0, "UpdateKeyboardOptionsCore: km_kbp_state_option_lookup failed with error status [%d]", err_status);
|
||||
continue;
|
||||
}
|
||||
// compare to see if changed
|
||||
if (wcscmp(reinterpret_cast<LPCWSTR>(retValue), reinterpret_cast<LPCWSTR>(lpCoreKeyboardOptions[i].value)) != 0) {
|
||||
delete lpCoreKeyboardOptions[i].value;
|
||||
lpCoreKeyboardOptions[i].value = CloneKMKBPCP(retValue);
|
||||
changed = TRUE;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
km_kbp_option_item*
|
||||
SaveKeyboardOptionsCore(LPINTKEYBOARDINFO kp) {
|
||||
|
||||
// Get the list of default options to determine size of list
|
||||
const km_kbp_keyboard_attrs* keyboardAttrs;
|
||||
km_kbp_status err_status = km_kbp_keyboard_get_attrs(kp->lpCoreKeyboard, &keyboardAttrs);
|
||||
if (err_status != KM_KBP_STATUS_OK) {
|
||||
SendDebugMessageFormat(
|
||||
0, sdmKeyboard, 0, "SaveKeyboardOptionsCore: km_kbp_keyboard_get_attrs failed with error status [%d]", err_status);
|
||||
return nullptr;
|
||||
}
|
||||
int listSize = (int)km_kbp_options_list_size(keyboardAttrs->default_options);
|
||||
km_kbp_option_item* savedKeyboardOpts = new km_kbp_option_item[listSize + 1];
|
||||
km_kbp_cp const* retValue = nullptr;
|
||||
|
||||
km_kbp_option_item const* kbDefaultOpts = keyboardAttrs->default_options;
|
||||
for (int i = 0; i < listSize; i++, ++kbDefaultOpts) {
|
||||
if (kbDefaultOpts->scope != KM_KBP_OPT_KEYBOARD)
|
||||
continue;
|
||||
err_status =
|
||||
km_kbp_state_option_lookup(kp->lpCoreKeyboardState, KM_KBP_OPT_KEYBOARD, kbDefaultOpts->key, &retValue);
|
||||
if (err_status != KM_KBP_STATUS_OK) {
|
||||
SendDebugMessageFormat(
|
||||
0, sdmKeyboard, 0, "SaveKeyboardOptionsCore: km_kbp_state_option_lookup failed with error status [%d]", err_status);
|
||||
continue;
|
||||
}
|
||||
savedKeyboardOpts[i].key = CloneKMKBPCP(kbDefaultOpts->key);
|
||||
savedKeyboardOpts[i].value = CloneKMKBPCP(retValue);
|
||||
savedKeyboardOpts[i].scope = KM_KBP_OPT_KEYBOARD;
|
||||
}
|
||||
savedKeyboardOpts[listSize] = KM_KBP_OPTIONS_END;
|
||||
return savedKeyboardOpts;
|
||||
}
|
||||
|
||||
BOOL
|
||||
RestoreKeyboardOptionsCore(
|
||||
km_kbp_state* const lpCoreKeyboardState,
|
||||
km_kbp_option_item* lpCoreKeyboardOptions) {
|
||||
km_kbp_status err_status = km_kbp_state_options_update(lpCoreKeyboardState, lpCoreKeyboardOptions);
|
||||
if (err_status != KM_KBP_STATUS_OK) {
|
||||
SendDebugMessageFormat(
|
||||
0, sdmKeyboard, 0, "RestoreKeyboardOptionsCore: km_kbp_state_options_update failed with error status [%d]", err_status);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
DisposeKeyboardOptionsCore(km_kbp_option_item** lpCoreKeyboardOptions) {
|
||||
size_t listSize = km_kbp_options_list_size(*lpCoreKeyboardOptions);
|
||||
for (int i = 0; i < (int)listSize; i++) {
|
||||
delete[] (*lpCoreKeyboardOptions)[i].key;
|
||||
delete[] (*lpCoreKeyboardOptions)[i].value;
|
||||
}
|
||||
delete[] *lpCoreKeyboardOptions;
|
||||
*lpCoreKeyboardOptions = NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,44 +16,6 @@
|
|||
History: 25 May 2010 - mcdurdin - I1632 - Keyboard Options
|
||||
*/
|
||||
|
||||
void LoadKeyboardOptions(LPINTKEYBOARDINFO kp);
|
||||
void FreeKeyboardOptions(LPINTKEYBOARDINFO kp);
|
||||
void SetKeyboardOption(LPINTKEYBOARDINFO kp, int nStoreToSet, int nStoreToRead);
|
||||
void ResetKeyboardOption(LPINTKEYBOARDINFO kp, int nStoreToReset);
|
||||
void SaveKeyboardOption(LPINTKEYBOARDINFO kp, int nStoreToSave);
|
||||
void LoadSharedKeyboardOptions(LPINTKEYBOARDINFO kp);
|
||||
/**
|
||||
* Updates the supplied Keyboard processor options list from the keyboard processor pointed
|
||||
* to by the state pointer.
|
||||
*
|
||||
* @param lpCoreKeyboardState The core keyboardprocessor state which has the source options
|
||||
* @param[in,out] lpCoreKeyboardOptions The core keyboard options to be updated
|
||||
* @return BOOL True if one or more options were updated
|
||||
*/
|
||||
BOOL UpdateKeyboardOptionsCore(km_kbp_state* const lpCoreKeyboardState, km_kbp_option_item *lpCoreKeyboardOptions);
|
||||
|
||||
/**
|
||||
* Returns a copy of the core keyboard processors current keyboard options
|
||||
* The caller is responsible for freeing the returned km_kbp_option_item's list.
|
||||
*
|
||||
* @param kp A pointer to the keyboard info object that contains the
|
||||
* keyboardprocessor state and keyboard for the source options list.
|
||||
*
|
||||
* @return km_kbp_option_item* The copy of the options list or NULL if copy failed
|
||||
*/
|
||||
km_kbp_option_item* SaveKeyboardOptionsCore(LPINTKEYBOARDINFO kp);
|
||||
|
||||
/**
|
||||
* Restore the core keyboard processor options to the supplied keyboard
|
||||
* list of `km_kbp_option_item`s
|
||||
*
|
||||
* @param lpCoreKeyboardState The state pointer for the keyboard processor
|
||||
* @param lpCoreKeyboardOptions The list of `km_kbp_option_item`s to restore
|
||||
*
|
||||
* return BOOL TRUE when the call to update keyboard processor was successful
|
||||
*/
|
||||
BOOL RestoreKeyboardOptionsCore(km_kbp_state* const lpCoreKeyboardState, km_kbp_option_item* lpCoreKeyboardOptions);
|
||||
|
||||
/* Common core integration functions */
|
||||
|
||||
/**
|
||||
|
|
@ -62,7 +24,7 @@ BOOL RestoreKeyboardOptionsCore(km_kbp_state* const lpCoreKeyboardState, km_kbp_
|
|||
* @param kp keyboard info object with options to be updated
|
||||
* @param state core keyboard state used to update keyboard options
|
||||
*/
|
||||
void LoadKeyboardOptionsREGCore(LPINTKEYBOARDINFO kp, km_kbp_state* state);
|
||||
void LoadKeyboardOptionsRegistrytoCore(LPINTKEYBOARDINFO kp, km_kbp_state* state);
|
||||
|
||||
/**
|
||||
* Saves the keyboard option to the windows registry
|
||||
|
|
@ -71,12 +33,6 @@ void LoadKeyboardOptionsREGCore(LPINTKEYBOARDINFO kp, km_kbp_state* state);
|
|||
* @param key keyboard key to save
|
||||
* @param value keyboard option value to save
|
||||
*/
|
||||
void SaveKeyboardOptionREGCore(LPINTKEYBOARDINFO kp, LPCWSTR key, LPWSTR value);
|
||||
void SaveKeyboardOptionCoretoRegistry(LPINTKEYBOARDINFO kp, LPCWSTR key, LPWSTR value);
|
||||
|
||||
|
||||
/**
|
||||
* Free the allocated resources belonging to a key_kbp_option_items object
|
||||
* that was created on the heap most likely using SaveKeyboardOptionREGCore
|
||||
*
|
||||
* @param lpCoreKeyboardOptions keyboard options items to be freed
|
||||
*/
|
||||
void DisposeKeyboardOptionsCore(km_kbp_option_item** lpCoreKeyboardOptions);
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@
|
|||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LibraryPath>$(ProjectDir)..\..\..\..\core\build\x86\$(Configuration)\src;$(ProjectDir)..\..\..\..\core\build\rust\x86\$(Configuration);$(LibraryPath)</LibraryPath>
|
||||
<IncludePath>$(ProjectDir)..\..\..\..\core\build\x86\$(Configuration)\include;$(IncludePath)</IncludePath>
|
||||
<IncludePath>$(ProjectDir)..\..\..\..\common\include;$(ProjectDir)..\..\..\..\core\include;$(ProjectDir)..\..\..\..\core\build\x86\$(Configuration)\include;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Midl>
|
||||
|
|
@ -186,12 +186,6 @@
|
|||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="$(KEYMAN_ROOT)\common\windows\cpp\src\xstring.cpp" />
|
||||
<ClCompile Include="addins.cpp">
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<ClCompile Include="appint\aiTIP.cpp">
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
|
|
@ -403,4 +397,4 @@
|
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -15,9 +15,6 @@
|
|||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="addins.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="appint\aiTIP.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -492,7 +492,6 @@ extern "C" BOOL _declspec(dllexport) WINAPI Keyman_Exit(void)
|
|||
*Globals::Keyman_Shutdown() = TRUE;
|
||||
|
||||
ReleaseKeyboards(TRUE);
|
||||
Addin_Release();
|
||||
|
||||
if(!Globals::get_Keyman_Initialised())
|
||||
{
|
||||
|
|
@ -529,138 +528,6 @@ extern "C" BOOL _declspec(dllexport) WINAPI Keyman_RestartEngine()
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/*******************************************************************************************/
|
||||
/* */
|
||||
/* Keyman Keyboard Override Functions */
|
||||
/* */
|
||||
/*******************************************************************************************/
|
||||
|
||||
extern "C" BOOL _declspec(dllexport) WINAPI Keyman_StopForcingKeyboard();
|
||||
|
||||
void RefreshPreservedKeys(BOOL Activating);
|
||||
|
||||
extern "C" BOOL _declspec(dllexport) WINAPI Keyman_ForceKeyboard(PCSTR FileName)
|
||||
{
|
||||
SendDebugMessageFormat(0,sdmGlobal,0,"Keyman_ForceKeyboard: ENTER %s", FileName);
|
||||
|
||||
Keyman_StopForcingKeyboard(); // 7.0.219.0
|
||||
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if(!_td) return FALSE;
|
||||
|
||||
strncpy(_td->ForceFileName, FileName, MAX_PATH - 1);
|
||||
_td->ForceFileName[MAX_PATH-1] = 0;
|
||||
|
||||
if(_td->lpActiveKeyboard)
|
||||
{
|
||||
DeactivateDLLs(_td->lpActiveKeyboard);
|
||||
}
|
||||
|
||||
_td->lpActiveKeyboard = new INTKEYBOARDINFO;
|
||||
memset(_td->lpActiveKeyboard, 0, sizeof(INTKEYBOARDINFO)); // I2437 - Crash unloading keyboard due to keyboard options not init
|
||||
/*_td->lpActiveKeyboard->KeymanID = 0;
|
||||
_td->lpActiveKeyboard->nIMDLLs = 0;
|
||||
_td->lpActiveKeyboard->IMDLLs = NULL;
|
||||
_td->lpActiveKeyboard->KeyboardOptions = NULL;*/
|
||||
_splitpath_s(FileName, NULL, 0, NULL, 0, _td->lpActiveKeyboard->Name, sizeof(_td->lpActiveKeyboard->Name), NULL, 0);
|
||||
// TODO: 5442 - remove if/ else as there will no longer be the old LoadKeyboard option
|
||||
if (Globals::get_CoreIntegration()) {
|
||||
PWCHAR keyboardPath = strtowstr(_td->ForceFileName);
|
||||
km_kbp_status err_status = km_kbp_keyboard_load(keyboardPath, &_td->lpActiveKeyboard->lpCoreKeyboard);
|
||||
if (err_status != KM_KBP_STATUS_OK) {
|
||||
SendDebugMessageFormat(0, sdmGlobal, 0, "Keyman_ForceKeyboard Core: km_kbp_keyboard_load failed for %ls with error status [%d]", keyboardPath, err_status); // TODO: 5442 - remove word Core
|
||||
delete keyboardPath;
|
||||
return FALSE;
|
||||
}
|
||||
delete keyboardPath;
|
||||
SendDebugMessageFormat(0, sdmGlobal, 0, "Keyman_ForceKeyboard Core: %s OK", FileName); // TODO: 5442 - remove word Core
|
||||
|
||||
km_kbp_option_item *core_environment = nullptr;
|
||||
|
||||
if(!SetupCoreEnvironment(&core_environment)) {
|
||||
SendDebugMessageFormat(0, sdmLoad, 0, "Keyman_ForceKeyboard Core: Unable to set environment options for keyboard %s", FileName); // TODO: 5442 - remove word Core
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
err_status =
|
||||
km_kbp_state_create(_td->lpActiveKeyboard->lpCoreKeyboard, core_environment, &_td->lpActiveKeyboard->lpCoreKeyboardState);
|
||||
|
||||
DeleteCoreEnvironment(core_environment);
|
||||
|
||||
if (err_status != KM_KBP_STATUS_OK) {
|
||||
SendDebugMessageFormat(
|
||||
0, sdmGlobal, 0, "Keyman_ForceKeyboard Core: km_kbp_state_create failed with error status [%d]", err_status);
|
||||
// Dispose of the keyboard to leave us in a consitent state
|
||||
ReleaseKeyboardMemoryCore(&_td->lpActiveKeyboard->lpCoreKeyboard);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ResetCapsLock();
|
||||
err_status = km_kbp_keyboard_get_imx_list(_td->lpActiveKeyboard->lpCoreKeyboard, &_td->lpActiveKeyboard->lpIMXList);
|
||||
if (err_status != KM_KBP_STATUS_OK) {
|
||||
SendDebugMessageFormat(0, sdmLoad, 0, "Keyman_ForceKeyboard Core: km_kbp_keyboard_get_imx_list failed with error status [%d]", err_status);
|
||||
// Dispose of the keyboard to leave us in a consistent state
|
||||
ReleaseKeyboardMemoryCore(&_td->lpActiveKeyboard->lpCoreKeyboard);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LoadDLLsCore(_td->lpActiveKeyboard);
|
||||
ActivateDLLs(_td->lpActiveKeyboard);
|
||||
LoadKeyboardOptionsREGCore(_td->lpActiveKeyboard, _td->lpActiveKeyboard->lpCoreKeyboardState);
|
||||
RefreshPreservedKeys(TRUE);
|
||||
return TRUE;
|
||||
} else {
|
||||
if (LoadKeyboard(_td->ForceFileName, &_td->lpActiveKeyboard->Keyboard)) {
|
||||
SendDebugMessageFormat(0, sdmGlobal, 0, "Keyman_ForceKeyboard: %s OK", FileName);
|
||||
ResetCapsLock();
|
||||
LoadDLLs(_td->lpActiveKeyboard);
|
||||
ActivateDLLs(_td->lpActiveKeyboard);
|
||||
LoadKeyboardOptions(_td->lpActiveKeyboard); // I2437 - Crash unloading keyboard due to keyboard options not set
|
||||
RefreshPreservedKeys(TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
SendDebugMessageFormat(0,sdmGlobal,0,"Keyman_ForceKeyboard: %s FAIL", FileName);
|
||||
|
||||
delete _td->lpActiveKeyboard;
|
||||
_td->lpActiveKeyboard = NULL;
|
||||
|
||||
_td->ForceFileName[0] = 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
extern "C" BOOL _declspec(dllexport) WINAPI Keyman_StopForcingKeyboard()
|
||||
{
|
||||
PKEYMAN64THREADDATA _td = ThreadGlobals();
|
||||
if(!_td)
|
||||
{
|
||||
SetLastError(ERROR_KEYMAN_THREAD_DATA_NOT_READY); // I3173 // I3525
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(!_td->lpActiveKeyboard)
|
||||
{
|
||||
SetLastError(ERROR_KEYMAN_KEYBOARD_NOT_ACTIVE); // I3173 // I3525
|
||||
return FALSE;
|
||||
}
|
||||
SendDebugMessageFormat(0,sdmGlobal,0,"Keyman_StopForcingKeyboard");
|
||||
if(_td->ForceFileName[0])
|
||||
{
|
||||
SendDebugMessageFormat(0,sdmGlobal,0,"Keyman_StopForcingKeyboard: Stopping forcing");
|
||||
if(!DeactivateDLLs(_td->lpActiveKeyboard)) return FALSE; // I3173 // I3525
|
||||
if(!UnloadDLLs(_td->lpActiveKeyboard)) return FALSE; // I3173 // I3525
|
||||
_td->ForceFileName[0] = 0;
|
||||
FreeKeyboardOptions(_td->lpActiveKeyboard);
|
||||
ReleaseKeyboardMemory(_td->lpActiveKeyboard->Keyboard);
|
||||
ReleaseStateMemoryCore(&_td->lpActiveKeyboard->lpCoreKeyboardState);
|
||||
ReleaseKeyboardMemoryCore(&_td->lpActiveKeyboard->lpCoreKeyboard);
|
||||
RefreshPreservedKeys(FALSE);
|
||||
delete _td->lpActiveKeyboard;
|
||||
_td->lpActiveKeyboard = NULL;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Utility guff functions
|
||||
|
|
@ -936,8 +803,6 @@ void RefreshKeyboards(BOOL Initialising)
|
|||
|
||||
// Can happen when multiple top-level windows for one process
|
||||
|
||||
Addin_Refresh();
|
||||
|
||||
SendDebugMessageFormat(0,sdmGlobal,0,"---ENTER RefreshKeyboards---");
|
||||
//FInRefreshKeyboards = TRUE;
|
||||
|
||||
|
|
@ -1006,8 +871,6 @@ void RefreshKeyboards(BOOL Initialising)
|
|||
RefreshKeyboardProfiles(kp, FALSE); // Read standard profiles
|
||||
RefreshKeyboardProfiles(kp, TRUE); // Read transient profiles
|
||||
|
||||
kp->Keyboard = NULL;
|
||||
|
||||
SendDebugMessageFormat(0,sdmGlobal,0,"RefreshKeyboards: Added keyboard %s, %d",
|
||||
kp->Name, kp->KeymanID);
|
||||
i++;
|
||||
|
|
@ -1035,13 +898,15 @@ void ReleaseKeyboards(BOOL Lock)
|
|||
if(!_td || !_td->lpKeyboards) return;
|
||||
|
||||
|
||||
if(Lock) if(_td->lpActiveKeyboard && !_td->ForceFileName[0]) DeactivateDLLs(_td->lpActiveKeyboard);
|
||||
if(Lock) {
|
||||
if(_td->lpActiveKeyboard) {
|
||||
DeactivateDLLs(_td->lpActiveKeyboard);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < _td->nKeyboards; i++)
|
||||
{
|
||||
if(Lock) UnloadDLLs(&_td->lpKeyboards[i]);
|
||||
FreeKeyboardOptions(&_td->lpKeyboards[i]);
|
||||
ReleaseKeyboardMemory(_td->lpKeyboards[i].Keyboard);
|
||||
ReleaseStateMemoryCore(&_td->lpKeyboards[i].lpCoreKeyboardState);
|
||||
ReleaseKeyboardMemoryCore(&_td->lpKeyboards[i].lpCoreKeyboard);
|
||||
if(_td->lpKeyboards[i].Profiles) delete _td->lpKeyboards[i].Profiles; // I3581
|
||||
|
|
@ -1051,7 +916,6 @@ void ReleaseKeyboards(BOOL Lock)
|
|||
delete _td->lpKeyboards;
|
||||
|
||||
_td->lpKeyboards = NULL;
|
||||
if(!_td->ForceFileName[0]) _td->lpActiveKeyboard = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@ EXPORTS
|
|||
Keyman_GetInitialised
|
||||
Keyman_Initialise
|
||||
Keyman_Exit
|
||||
Keyman_ForceKeyboard
|
||||
Keyman_StopForcingKeyboard
|
||||
Keyman_GetLastActiveWindow
|
||||
Keyman_GetLastFocusWindow
|
||||
KMSetOutput
|
||||
|
|
|
|||
|
|
@ -176,12 +176,6 @@
|
|||
<ItemGroup>
|
||||
<ClCompile Include="..\..\global\cpp\kmtip_guids.cpp" />
|
||||
<ClCompile Include="$(KEYMAN_ROOT)\common\windows\cpp\src\xstring.cpp" />
|
||||
<ClCompile Include="addins.cpp">
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<ClCompile Include="appint\aiTIP.cpp">
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
|
|
@ -362,7 +356,6 @@
|
|||
<ItemGroup>
|
||||
<ClInclude Include="keymanengine.h" />
|
||||
<ClInclude Include="..\..\..\include\kmtip_guids.h" />
|
||||
<ClInclude Include="addins.h" />
|
||||
<ClInclude Include="appint\aiTIP.h" />
|
||||
<ClInclude Include="appint\aiWin2000Unicode.h" />
|
||||
<ClInclude Include="appint\appint.h" />
|
||||
|
|
|
|||
|
|
@ -15,9 +15,6 @@
|
|||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="addins.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="appint\aiTIP.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
|
@ -162,9 +159,6 @@
|
|||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="addins.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="appint\aiTIP.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
|||
|
|
@ -81,11 +81,9 @@ typedef struct tagINTKEYBOARDINFO
|
|||
DWORD __filler_Hotkey;
|
||||
DWORD __filler; // makes same as KEYBOARDINFO // I4462
|
||||
char Name[256];
|
||||
LPKEYBOARD Keyboard;
|
||||
DWORD nIMDLLs;
|
||||
LPIMDLL IMDLLs;
|
||||
int __filler2; // makes same as KEYBOARDINFO
|
||||
LPINTKEYBOARDOPTIONS KeyboardOptions;
|
||||
int nProfiles;
|
||||
LPINTKEYBOARDPROFILE Profiles;
|
||||
km_kbp_keyboard* lpCoreKeyboard;
|
||||
|
|
@ -105,17 +103,11 @@ typedef struct tagKMSTATE
|
|||
{
|
||||
BOOL NoMatches;
|
||||
MSG msg;
|
||||
// TODO: 5442 will remove these once windows core is deprecated
|
||||
BOOL StopOutput;
|
||||
int LoopTimes;
|
||||
// TODO: 5442
|
||||
WORD vkey; // I934
|
||||
WCHAR charCode; // I4582
|
||||
BOOL windowunicode; // I4287
|
||||
BOOL isDown;
|
||||
LPKEYBOARD lpkb;
|
||||
km_kbp_keyboard* lpCoreKb; // future use with IMDLL
|
||||
LPGROUP startgroup; // TODO: 5442 will remove this once windows core is deprecated
|
||||
} KMSTATE;
|
||||
|
||||
// I3616
|
||||
|
|
@ -129,7 +121,6 @@ LRESULT CALLBACK kmnLowLevelKeyboardProc( // I4124
|
|||
_In_ LPARAM lParam
|
||||
);
|
||||
|
||||
BOOL ReleaseKeyboardMemory(LPKEYBOARD kbd);
|
||||
BOOL ReleaseStateMemoryCore(km_kbp_state** state);
|
||||
BOOL ReleaseKeyboardMemoryCore(km_kbp_keyboard** kbd);
|
||||
|
||||
|
|
@ -230,8 +221,6 @@ DWORD HKLToKeyboardID(HKL hkl);
|
|||
WORD HKLToLanguageID(HKL hkl);
|
||||
WORD HKLToLayoutNumber(HKL hkl);
|
||||
WORD HKLToLayoutID(HKL hkl);
|
||||
DWORD EthnologueCodeToKeymanID(DWORD EthCode);
|
||||
DWORD EthnologueStringCodeToDWord(PWSTR EthCode);
|
||||
|
||||
PWSTR GetSystemStore(LPKEYBOARD kb, DWORD SystemID);
|
||||
|
||||
|
|
@ -254,7 +243,6 @@ void keybd_shift(LPINPUT pInputs, int* n, BOOL isReset, LPBYTE const kbd);
|
|||
#include "keystate.h"
|
||||
|
||||
#include "calldll.h"
|
||||
#include "addins.h"
|
||||
#include "keymancontrol.h"
|
||||
#include "keyboardoptions.h"
|
||||
#include "kmprocessactions.h"
|
||||
|
|
|
|||
|
|
@ -248,19 +248,6 @@ LRESULT _kmnGetMessageProc(int nCode, WPARAM wParam, LPARAM lParam)
|
|||
return CallNextHookEx(Globals::get_hhookGetMessage(), nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
/*
|
||||
Handle WM_UNICHAR messages for RichEdit control -- should we test RichEdit version?
|
||||
*/
|
||||
|
||||
if(mp->message == WM_UNICHAR && Addin_ShouldProcessUnichar(mp->hwnd))
|
||||
{
|
||||
if(Addin_ProcessUnichar(mp->hwnd, (DWORD) mp->wParam))
|
||||
{
|
||||
mp->message = 0;
|
||||
return CallNextHookEx(Globals::get_hhookGetMessage(), nCode, wParam, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Handle wm_keyman_control_internal messages
|
||||
*/
|
||||
|
|
@ -271,7 +258,6 @@ LRESULT _kmnGetMessageProc(int nCode, WPARAM wParam, LPARAM lParam)
|
|||
|
||||
if(_td->lpActiveKeyboard)
|
||||
{
|
||||
_td->state.lpkb = _td->lpActiveKeyboard->Keyboard;
|
||||
_td->state.lpCoreKb = _td->lpActiveKeyboard->lpCoreKeyboard;
|
||||
}
|
||||
// I4412
|
||||
|
|
@ -297,20 +283,17 @@ LRESULT _kmnGetMessageProc(int nCode, WPARAM wParam, LPARAM lParam)
|
|||
{
|
||||
if(_td->app)
|
||||
{
|
||||
BOOL isUsingCoreProcessor = Globals::get_CoreIntegration();
|
||||
|
||||
if (isUsingCoreProcessor) {
|
||||
// Call the core keyboard processor to process the queued actions
|
||||
if (!_td->lpActiveKeyboard) {
|
||||
return CallNextHookEx(Globals::get_hhookGetMessage(), nCode, wParam, lParam);
|
||||
}
|
||||
if (KM_KBP_STATUS_OK != km_kbp_process_queued_actions(_td->lpActiveKeyboard->lpCoreKeyboardState)) {
|
||||
SendDebugMessageFormat(0, sdmGlobal, 0, "_kmnGetMessageProc wm_keymanim_close process event fail");
|
||||
return CallNextHookEx(Globals::get_hhookGetMessage(), nCode, wParam, lParam);
|
||||
}
|
||||
BOOL emitKeyStroke;
|
||||
ProcessActions(&emitKeyStroke);
|
||||
// Call the core keyboard processor to process the queued actions
|
||||
if (!_td->lpActiveKeyboard) {
|
||||
return CallNextHookEx(Globals::get_hhookGetMessage(), nCode, wParam, lParam);
|
||||
}
|
||||
if (KM_KBP_STATUS_OK != km_kbp_process_queued_actions(_td->lpActiveKeyboard->lpCoreKeyboardState)) {
|
||||
SendDebugMessageFormat(0, sdmGlobal, 0, "_kmnGetMessageProc wm_keymanim_close process event fail");
|
||||
return CallNextHookEx(Globals::get_hhookGetMessage(), nCode, wParam, lParam);
|
||||
}
|
||||
BOOL emitKeyStroke;
|
||||
ProcessActions(&emitKeyStroke);
|
||||
|
||||
_td->app->SetCurrentShiftState(Globals::get_ShiftState());
|
||||
_td->app->SendActions();
|
||||
}
|
||||
|
|
@ -372,7 +355,6 @@ void ProcessWMKeyman(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|||
hwnd = GetFocus();
|
||||
|
||||
if(_td->lpActiveKeyboard) {
|
||||
_td->state.lpkb = _td->lpActiveKeyboard->Keyboard;
|
||||
_td->state.lpCoreKb = _td->lpActiveKeyboard->lpCoreKeyboard;
|
||||
}
|
||||
|
||||
|
|
@ -384,7 +366,6 @@ void ProcessWMKeyman(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|||
{
|
||||
if(_td->app) _td->app->ResetQueue();
|
||||
GetCapsAndNumlockState();
|
||||
Addin_FocusChanged(hwnd);
|
||||
UpdateActiveWindows();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue