diff --git a/android/KMEA/app/src/main/assets/keyboard.html b/android/KMEA/app/src/main/assets/keyboard.html index 9d36add930..242a0dc050 100644 --- a/android/KMEA/app/src/main/assets/keyboard.html +++ b/android/KMEA/app/src/main/assets/keyboard.html @@ -18,7 +18,7 @@ //document.body.style.backgroundColor="transparent"; window.console.log('Device type = '+device); window.console.log('Keyboard height = '+oskHeight); - var kmw=window['tavultesoft']['keymanweb']; + var kmw=window['keyman']; kmw.init({'app':device,'fonts':'fonts/'}); kmw['util']['setOption']('attachType','manual'); kmw['oninserttext'] = insertText; @@ -38,7 +38,7 @@ if(h > 0) { oskHeight = h; } - var kmw=window['tavultesoft']['keymanweb']; + var kmw=window['keyman']; kmw['correctOSKTextSize'](); } @@ -63,7 +63,8 @@ // Query KMW if a given keyboard uses chiral modifiers. function setIsChiral(keyboardProperties) { var name = typeof(keyboardProperties.internalName) == "undefined" ? keyboardProperties.keyboardName : keyboardProperties.internalName; - var isChiral = tavultesoft.keymanweb.isChiral(name); + var kmw=window['keyman']; + var isChiral = kmw.isChiral(name); window.console.log('For keyboard "' + name + '"'); window.console.log('setIsChiral = ' + isChiral); @@ -74,7 +75,9 @@ function setKeymanLanguage(keyboardName, internalName, languageName, langId, version, font, oskFont) { //oskFont.files = ['NotoSansSyriacWestern-Regular.svg#NotoSansSyriacWesternRegular']; //window.console.log('oskFonts = '+JSON.stringify(oskFont)); - var kmw=window['tavultesoft']['keymanweb']; + var kmw=window['keyman']; + var kbdInterface=kmw['interface']; + // Defaults for mising arguments switch (arguments.length) { case 1: @@ -94,7 +97,7 @@ break; } - kmw['KRS']({KN:keyboardName,KI:'Keyboard_'+internalName,KLC:langId,KL:languageName, + kbdInterface.registerStub({KN:keyboardName,KI:'Keyboard_'+internalName,KLC:langId,KL:languageName, KF:internalName+'-'+version+'.js',KFont:font,KOskFont:oskFont}); kmw['setActiveKeyboard']('Keyboard_'+internalName,langId); kmw['osk']['show'](true); @@ -106,7 +109,8 @@ } function resetContext() { - tavultesoft.keymanweb.resetContext(); + var kmw=window['keyman']; + kmw.resetContext(); } function updateKMText(text) { @@ -114,14 +118,14 @@ text = ''; } var ta = document.getElementById('ta'); - var kmw = window['tavultesoft']['keymanweb']; + var kmw = window['keyman']; ta.value = text; kmw['setActiveElement'](ta); } function updateKMSelectionRange(start, end) { var ta = document.getElementById('ta'); - var kmw = window['tavultesoft']['keymanweb']; + var kmw = window['keyman']; ta.selectionStart = ta._KeymanWebSelectionStart = start; ta.selectionEnd = ta._KeymanWebSelectionEnd = end; kmw['setActiveElement'](ta); @@ -175,22 +179,22 @@ function showHelpBubble() { fragmentToggle = (fragmentToggle + 1) % 100; - var kmw = window['tavultesoft']['keymanweb']; + var kmw = window['keyman']; var pos = kmw['touchMenuPos'](); window.console.log('showHelpBubble ' + pos); window.location.hash = 'showHelpBubble-' + fragmentToggle + '+keyPos=' + pos; } function executePopupKey(keyID, keyText) { - var kmw=window['tavultesoft']['keymanweb']; - + var kmw=window['keyman']; + // KMW only needs keyID to process the popup key. keyText merely logged to console window.console.log('executePopupKey('+keyID+'); keyText: ' + keyText); kmw['executePopupKey'](keyID); } function executeHardwareKeystroke(code, shift, lstates) { - var kmw=window['tavultesoft']['keymanweb']; + var kmw=window['keyman']; window.console.log('executeHardwareKeystroke:('+code+', ' + shift + ', ' + lstates + ');'); try { var r = kmw['executeHardwareKeystroke'](code, shift, lstates); @@ -201,7 +205,7 @@ } function popupVisible(value) { - var kmw=window['tavultesoft']['keymanweb']; + var kmw=window['keyman']; kmw['popupVisible'](value); } diff --git a/android/Tests/KeyboardHarness/app/src/main/assets/languages/chirality.js b/android/Tests/KeyboardHarness/app/src/main/assets/languages/chirality.js index ade1c50d02..ac8bc720a8 100644 --- a/android/Tests/KeyboardHarness/app/src/main/assets/languages/chirality.js +++ b/android/Tests/KeyboardHarness/app/src/main/assets/languages/chirality.js @@ -12,8 +12,8 @@ function Keyboard_chirality() { this.KI = "Keyboard_chirality"; this.KN = "Development Chirality Test Keyboard"; + this.KMBM = 0x001F; this.KV = { - KMBM: 0x001F, F: ' 1em "Arial"', K102: 0, KLS: { 'default': new Array("`", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "=", "", "", "", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "[", "]", "\\", "", "", "", "a", "s", "d", "f", "g", "h", "j", "k", "l", ";", "'", "", "", "", "", "", "", "z", "x", "c", "v", "b", "n", "m", ",", ".", "/", "", "", "", "", "", ""), @@ -42,6 +42,7 @@ function Keyboard_chirality() { }; this.g0 = function (t, e) { var k = KeymanWeb, r = 0, m = 0; + var osk = keyman.osk; // Handwritten time! var kls = this.KV.KLS; @@ -52,7 +53,7 @@ function Keyboard_chirality() { for(var i = 0; i < layers.length; i++) { // Obtain the modifier code to match for the selected layer. // The following uses a non-public property potentially subject to change in the future. - var modCode = k.osk.modifierCodes['VIRTUAL_KEY'] | k.osk.getModifierState(layers[i]); + var modCode = osk.modifierCodes['VIRTUAL_KEY'] | osk.getModifierState(layers[i]); var layer = layers[i]; for(var key=0; key < kls[layer].length; key++) { @@ -61,9 +62,9 @@ function Keyboard_chirality() { if(keySymbol == "K_*") { continue; } else if(kls[layer][key] != '') { - if (k.KKM(e, modCode, k.osk.keyCodes[keySymbol])) { + if (k.KKM(e, modCode, osk.keyCodes[keySymbol])) { r = m = 1; - if(k.KSM(e, k.osk.modifierCodes['CAPS'])) { + if(k.KSM(e, osk.modifierCodes['CAPS'])) { k.KO(0, t, kls[layer][key].toUpperCase()); } else { k.KO(0, t, kls[layer][key]); diff --git a/ios/engine/KMEI/KeymanEngine.xcodeproj/project.pbxproj b/ios/engine/KMEI/KeymanEngine.xcodeproj/project.pbxproj index f1e0ea0ae4..2d9dabc5f4 100644 --- a/ios/engine/KMEI/KeymanEngine.xcodeproj/project.pbxproj +++ b/ios/engine/KMEI/KeymanEngine.xcodeproj/project.pbxproj @@ -43,6 +43,7 @@ C0452BAB1F9F1FE10064431A /* Language.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0452BAA1F9F1FE10064431A /* Language.swift */; }; C0452BAD1F9F21270064431A /* Keyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0452BAC1F9F21270064431A /* Keyboard.swift */; }; C0452BAF1F9F22A80064431A /* Font.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0452BAE1F9F22A80064431A /* Font.swift */; }; + C055E6EB1F99ED090035C2DD /* RegisteredFont.swift in Sources */ = {isa = PBXBuildFile; fileRef = C055E6EA1F99ED090035C2DD /* RegisteredFont.swift */; }; C06085B41F9485E40057E5B9 /* UIButton+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = C06085B31F9485E40057E5B9 /* UIButton+Helpers.swift */; }; C06D372F1F81F4E100F61AE0 /* KeymanEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = C06D372D1F81F4E100F61AE0 /* KeymanEngine.h */; settings = {ATTRIBUTES = (Public, ); }; }; C06D37331F81F5C300F61AE0 /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = CECB38941F2199BC0098882F /* Reachability.m */; }; @@ -169,6 +170,8 @@ C0452BAC1F9F21270064431A /* Keyboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Keyboard.swift; sourceTree = ""; }; C0452BAE1F9F22A80064431A /* Font.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Font.swift; sourceTree = ""; }; C04C2A6C1F6B7D9A00BA42B6 /* LanguageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LanguageViewController.swift; sourceTree = ""; }; + C055E6EA1F99ED090035C2DD /* RegisteredFont.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; +path = RegisteredFont.swift; sourceTree = ""; }; C06085B31F9485E40057E5B9 /* UIButton+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIButton+Helpers.swift"; sourceTree = ""; }; C06D372B1F81F4E100F61AE0 /* KeymanEngine.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = KeymanEngine.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C06D372D1F81F4E100F61AE0 /* KeymanEngine.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeymanEngine.h; sourceTree = ""; }; @@ -376,6 +379,7 @@ C0D3F35D1F9F33490055C7CF /* Options.swift */, C0D3F35F1F9F3AD80055C7CF /* InstallableKeyboard.swift */, C007C4641F9F52D8006461B9 /* LanguagesAPICall.swift */, + C055E6EA1F99ED090035C2DD /* RegisteredFont.swift */, ); path = Model; sourceTree = ""; @@ -606,7 +610,7 @@ F243887514BBD43000A3E055 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0900; + LastUpgradeCheck = 0910; ORGANIZATIONNAME = "SIL International"; TargetAttributes = { 98F9D6961954112F0087AA43 = { @@ -763,6 +767,7 @@ C0EF3E7B1F95B65300CE9BD4 /* KeymanWebViewDelegate.swift in Sources */, C06D37411F81F5C400F61AE0 /* LanguageViewController.swift in Sources */, C06D37421F81F5C400F61AE0 /* KeyboardPickerButton.swift in Sources */, + C055E6EB1F99ED090035C2DD /* RegisteredFont.swift in Sources */, C0324B931F87689B00AF3785 /* KeymanURLProtocol.swift in Sources */, C0452BAB1F9F1FE10064431A /* Language.swift in Sources */, C06D37431F81F5C400F61AE0 /* KeyboardPickerBarButtonItem.swift in Sources */, @@ -907,7 +912,6 @@ isa = XCBuildConfiguration; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; - ARCHS = "$(ARCHS_STANDARD)"; CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; @@ -919,7 +923,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; @@ -961,7 +965,6 @@ isa = XCBuildConfiguration; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; - ARCHS = "$(ARCHS_STANDARD)"; CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; @@ -973,7 +976,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_IDENTITY = "iPhone Distribution: Summer Institute of Linguistics, Inc (SIL) (3YE4W86L3G)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; @@ -1008,11 +1011,6 @@ isa = XCBuildConfiguration; baseConfigurationReference = F27FCAF6157FD95E00FBBA20 /* Keyman-lib.xcconfig */; buildSettings = { - ARCHS = ( - "$(ARCHS_STANDARD)", - x86_64, - i386, - ); IPHONEOS_DEPLOYMENT_TARGET = 8.0; ONLY_ACTIVE_ARCH = NO; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1024,11 +1022,6 @@ isa = XCBuildConfiguration; baseConfigurationReference = F27FCAF6157FD95E00FBBA20 /* Keyman-lib.xcconfig */; buildSettings = { - ARCHS = ( - "$(ARCHS_STANDARD)", - x86_64, - i386, - ); IPHONEOS_DEPLOYMENT_TARGET = 8.0; PRODUCT_NAME = "$(TARGET_NAME)"; VALID_ARCHS = "arm64 armv7s armv7 x86_64 i386"; @@ -1040,7 +1033,6 @@ baseConfigurationReference = 6C0A140E151EA930007FA4AD /* Debug.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD)"; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; @@ -1082,7 +1074,6 @@ baseConfigurationReference = 6C0A1411151EA930007FA4AD /* Release.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD)"; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Constants.swift b/ios/engine/KMEI/KeymanEngine/Classes/Constants.swift index 91a0e73409..0126e9b672 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/Constants.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/Constants.swift @@ -15,8 +15,6 @@ public struct Key { public static let fontFiles = "files" // Font filename is deprecated public static let fontFilename = "filename" - public static let fontName = "fontname" - public static let fontRegistered = "fontregistered" public static let keyboardInfo = "keyboardInfo" /// Array of user keyboards info list in UserDefaults diff --git a/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/KeyboardInfoViewController.swift b/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/KeyboardInfoViewController.swift index d87a16d0e6..2cfa92e19e 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/KeyboardInfoViewController.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/KeyboardInfoViewController.swift @@ -68,7 +68,7 @@ class KeyboardInfoViewController: UITableViewController, UIAlertViewDelegate { override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { if !isCustomKeyboard { if indexPath.row == 1 { - let url = URL(string:"http://help.keyman.com/keyboard/\(keyboardID)/\(keyboardVersion)/")! + let url = URL(string: "http://help.keyman.com/keyboard/\(keyboardID)/\(keyboardVersion)/")! if let openURL = Manager.shared.openURL { openURL(url) } else { diff --git a/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/KeyboardPickerBarButtonItem.swift b/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/KeyboardPickerBarButtonItem.swift index 473dbeff3f..ed46f1d18f 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/KeyboardPickerBarButtonItem.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/KeyboardPickerBarButtonItem.swift @@ -30,7 +30,7 @@ public class KeyboardPickerBarButtonItem: UIBarButtonItem { if UIDevice.current.userInterfaceIdiom == .phone { let landscapeImagePath = keymanBundle.path( - forResource:"keyboard_icon_landscape\(retinaSuffix)", ofType: "png")! + forResource: "keyboard_icon_landscape\(retinaSuffix)", ofType: "png")! landscapeImagePhone = UIImage(contentsOfFile: landscapeImagePath) } } diff --git a/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/KeyboardPickerButton.swift b/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/KeyboardPickerButton.swift index 2c3f54572b..344345ec6e 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/KeyboardPickerButton.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/LanguagePicker/KeyboardPickerButton.swift @@ -21,7 +21,7 @@ public class KeyboardPickerButton: UIButton { setColor(UIColor(red: 0.62, green: 0.68, blue: 0.76, alpha: 1.0)) addTarget(self, action: #selector(self.showKeyboardPicker), for: .touchUpInside) - let bundlePath = Bundle(for: type(of :self)).path(forResource: "Keyman", ofType: "bundle")! + let bundlePath = Bundle(for: type(of: self)).path(forResource: "Keyman", ofType: "bundle")! let retinaSuffix = Manager.shared.retinaScreen ? "@2x" : "" let imagePath = Bundle(path: bundlePath)!.path(forResource: "keyboard_icon\(retinaSuffix)", ofType: "png")! diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Manager.swift b/ios/engine/KMEI/KeymanEngine/Classes/Manager.swift index cd1c295f81..c619644dfa 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/Manager.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/Manager.swift @@ -107,8 +107,8 @@ UIGestureRecognizerDelegate { /// The key format is $languageID_$keyboardID. For example, "eng_european2" returns the English EuroLatin2 keyboard public private(set) var keyboardsDictionary: [String: InstallableKeyboard] = [:] - /// Dictionary of available Keyman keyboard fonts - public private(set) var keymanFonts: [String: [String: Any]] = [:] + /// Dictionary of available Keyman keyboard fonts keyed by font filename + public private(set) var keymanFonts: [String: RegisteredFont] = [:] /// Keyman system-wide keyboard public let isSystemKeyboard: Bool @@ -422,7 +422,7 @@ UIGestureRecognizerDelegate { let kb = activeUserDefaults().userKeyboard(withID: keyboardID, languageID: languageID) ?? repositoryKeyboard(withID: keyboardID, languageID: languageID) if let filename = kb?.font?.source.first(where: { $0.hasFontExtension }) { - return keymanFonts[filename]?[Key.fontName] as? String + return keymanFonts[filename]?.name } return nil } @@ -434,7 +434,7 @@ UIGestureRecognizerDelegate { let kb = activeUserDefaults().userKeyboard(withID: keyboardID, languageID: languageID) ?? repositoryKeyboard(withID: keyboardID, languageID: languageID) if let filename = kb?.oskFont?.source.first(where: { $0.hasFontExtension }) { - return keymanFonts[filename]?[Key.fontName] as? String + return keymanFonts[filename]?.name } return nil } @@ -998,15 +998,13 @@ UIGestureRecognizerDelegate { for fontFilename in directoryContents where fontFilename.hasFontExtension { if let fontInfo = keymanFonts[fontFilename] { - if fontInfo[Key.fontRegistered] as? Int == 0 { + if !fontInfo.isRegistered { if let newFontInfo = registerFont(withFilename: fontFilename) { keymanFonts[fontFilename] = newFontInfo } } - } else { - if let fontInfo = registerFont(withFilename: fontFilename) { - keymanFonts[fontFilename] = fontInfo - } + } else if let fontInfo = registerFont(withFilename: fontFilename) { + keymanFonts[fontFilename] = fontInfo } } } @@ -1022,16 +1020,16 @@ UIGestureRecognizerDelegate { } for fontFilename in directoryContents where fontFilename.hasFontExtension { - if var fontInfo = keymanFonts[fontFilename], fontInfo[Key.fontRegistered] as? Int != 0 { + if var fontInfo = keymanFonts[fontFilename], fontInfo.isRegistered { if unregisterFont(withFilename: fontFilename) { - fontInfo[Key.fontRegistered] = 0 + fontInfo.isRegistered = false keymanFonts[fontFilename] = fontInfo } } } } - private func registerFont(withFilename fontFilename: String) -> [String: Any]? { + private func registerFont(withFilename fontFilename: String) -> RegisteredFont? { guard let fontURL = activeFontDirectory()?.appendingPathComponent(fontFilename), FileManager.default.fileExists(atPath: fontURL.path) else { return nil @@ -1041,13 +1039,14 @@ UIGestureRecognizerDelegate { kmLog("Failed to open \(fontURL)", checkDebugPrinting: false) return nil } - guard let font = CGFont(provider) else { + guard let font = CGFont(provider), + let cfFontName = font.postScriptName else { kmLog("Failed to read font at \(fontURL)", checkDebugPrinting: false) return nil } - var didRegister: Bool = false - let fontName = font.postScriptName! as String + var didRegister = false + let fontName = cfFontName as String if !fontExists(fontName) { var errorRef: Unmanaged? didRegister = CTFontManagerRegisterFontsForURL(fontURL as CFURL, .none, &errorRef) @@ -1059,11 +1058,7 @@ UIGestureRecognizerDelegate { kmLog("Registered font: \(fontURL)", checkDebugPrinting: true) } } - return [ - Key.fontName: fontName, - // TODO: Check if didRegister should be true if font exists - Key.fontRegistered: didRegister ? 1 : 0 - ] + return RegisteredFont(name: fontName, isRegistered: didRegister) } private func unregisterFont(withFilename fontFilename: String) -> Bool { diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Model/RegisteredFont.swift b/ios/engine/KMEI/KeymanEngine/Classes/Model/RegisteredFont.swift new file mode 100644 index 0000000000..4b529b5ead --- /dev/null +++ b/ios/engine/KMEI/KeymanEngine/Classes/Model/RegisteredFont.swift @@ -0,0 +1,17 @@ +// +// RegisteredFont.swift +// KeymanEngine +// +// Created by Gabriel Wong on 2017-10-20. +// Copyright © 2017 SIL International. All rights reserved. +// + +public struct RegisteredFont { + public let name: String + public var isRegistered: Bool + + public init(name: String, isRegistered: Bool) { + self.name = name + self.isRegistered = isRegistered + } +} diff --git a/ios/engine/KMEI/KeymanEngine/resources/Keyman.bundle/Contents/Resources/keyboard.html b/ios/engine/KMEI/KeymanEngine/resources/Keyman.bundle/Contents/Resources/keyboard.html index 48a4fe8842..4dc257bdc1 100644 --- a/ios/engine/KMEI/KeymanEngine/resources/Keyman.bundle/Contents/Resources/keyboard.html +++ b/ios/engine/KMEI/KeymanEngine/resources/Keyman.bundle/Contents/Resources/keyboard.html @@ -30,7 +30,7 @@ window.addEventListener('load', init, false); function init() { - var kmw=window['tavultesoft']['keymanweb']; + var kmw=window['keyman']; kmw.init({'app':device,'fonts':'fonts/'}); kmw['util']['setOption']('attachType','manual'); kmw['oninserttext'] = insertText; @@ -49,7 +49,7 @@ function setOskHeight(height) { oskHeight = height; - var kmw=window['tavultesoft']['keymanweb']; + var kmw=window['keyman']; kmw['correctOSKTextSize'](); } @@ -73,7 +73,7 @@ var keyboardOffset = 0; function setKeymanLanguage(keyboardName,internalName,languageName,langId,version,font,oskFont) { - var kmw=window['tavultesoft']['keymanweb']; + var kmw=window['keyman']; // Defaults for mising arguments switch(arguments.length) { @@ -86,7 +86,7 @@ langId=''; } - kmw['KRS']({KN:keyboardName,KI:'Keyboard_'+internalName,KLC:langId,KL:languageName,KF:internalName+'-'+version+'.js',KFont:font,KOskFont:oskFont}); + kmw.interface['registerStub']({KN:keyboardName,KI:'Keyboard_'+internalName,KLC:langId,KL:languageName,KF:internalName+'-'+version+'.js',KFont:font,KOskFont:oskFont}); kmw['setActiveKeyboard']('Keyboard_'+internalName,langId); kmw['osk']['show'](true); } @@ -166,23 +166,14 @@ } function langMenuPos() { - var kmw = window['tavultesoft']['keymanweb']; + var kmw = window['keyman']; var pos = kmw['touchMenuPos'](); return pos; } - /* - function oskRowCount() { - var rowCount = 5; - if (typeof(tavultesoft.keymanweb.osk.layers[0]) != 'undefined') - rowCount = tavultesoft.keymanweb.osk.layers[0].row.length; - - return rowCount; - }*/ - function setCursorRange(pos, length) { var ta = document.getElementById('ta'); - var kmw = window['tavultesoft']['keymanweb']; + var kmw = window['keyman']; ta.selectionStart = ta._KeymanWebSelectionStart = pos; ta.selectionEnd = ta._KeymanWebSelectionEnd = pos + length; kmw['setActiveElement'](ta); @@ -192,19 +183,19 @@ function setKeymanVal(text) { if(undefined == text) text = ''; var ta = document.getElementById('ta'); - var kmw = window['tavultesoft']['keymanweb']; + var kmw = window['keyman']; ta.value = text; kmw['setActiveElement'](ta); return ta.value; } function executePopupKey(keyID, keyText) { - var kmw=window['tavultesoft']['keymanweb']; + var kmw=window['keyman']; kmw['executePopupKey'](keyID, keyText); } function popupVisible(value) { - var kmw=window['tavultesoft']['keymanweb']; + var kmw=window['keyman']; kmw['popupVisible'](value); } diff --git a/ios/engine/KMEI/KeymanEngineDemo/AppDelegate.swift b/ios/engine/KMEI/KeymanEngineDemo/AppDelegate.swift index 20387d9d45..80678ea5ef 100644 --- a/ios/engine/KMEI/KeymanEngineDemo/AppDelegate.swift +++ b/ios/engine/KMEI/KeymanEngineDemo/AppDelegate.swift @@ -14,7 +14,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool { + didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? = nil) -> Bool { Manager.applicationGroupIdentifier = "group.KMEI" Manager.shared.isDebugPrintingOn = true Manager.shared.canRemoveDefaultKeyboard = true diff --git a/ios/keyman/Keyman/Keyman/ActivityItemProvider.swift b/ios/keyman/Keyman/Keyman/ActivityItemProvider.swift index e6f02a6271..e1815aed1f 100644 --- a/ios/keyman/Keyman/Keyman/ActivityItemProvider.swift +++ b/ios/keyman/Keyman/Keyman/ActivityItemProvider.swift @@ -36,10 +36,7 @@ class ActivityItemProvider: UIActivityItemProvider { case UIActivityType.postToFacebook?: return "\(text)\n\n\(fbText)" case UIActivityType.postToTwitter?: - if text.characters.count > 140 { - return text[.. Bool { + didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? = nil) -> Bool { Manager.applicationGroupIdentifier = "group.KM4I" #if DEBUG Manager.shared.isDebugPrintingOn = true diff --git a/ios/keyman/Keyman/Keyman/MainViewController.swift b/ios/keyman/Keyman/Keyman/MainViewController.swift index a8faabae1c..7096f4816f 100644 --- a/ios/keyman/Keyman/Keyman/MainViewController.swift +++ b/ios/keyman/Keyman/Keyman/MainViewController.swift @@ -125,10 +125,10 @@ class MainViewController: UIViewController, TextViewDelegate, UIActionSheetDeleg // Check for configuration profiles/fonts to install let kmFonts = Manager.shared.keymanFonts var profilesByFontName = [String: String](minimumCapacity: kmFonts.count - 1) - for (key, value) in kmFonts where key != "keymanweb-osk.ttf" { - let fontName = value[Key.fontName] as! String - let type = key[key.range(of: ".", options: .backwards)!.lowerBound...] - profilesByFontName[fontName] = key.replacingOccurrences(of: type, with: ".mobileconfig") + for (filename, font) in kmFonts where filename != "keymanweb-osk.ttf" { + let fontName = font.name + let type = filename[filename.range(of: ".", options: .backwards)!.lowerBound...] + profilesByFontName[fontName] = filename.replacingOccurrences(of: type, with: ".mobileconfig") } let customFonts = UIFont.familyNames.filter { !systemFonts.contains($0) && !($0 == "KeymanwebOsk") } diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMAboutWindow/KMBarView.m b/mac/Keyman4MacIM/Keyman4MacIM/KMAboutWindow/KMBarView.m index 4e0c674fc0..dafbfa0afc 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMAboutWindow/KMBarView.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMAboutWindow/KMBarView.m @@ -17,19 +17,19 @@ NSRect rect2 = NSMakeRect(rect1.size.width, 0, rect.size.width*0.23, rect.size.height); NSRect rect3 = NSMakeRect(rect2.origin.x + rect2.size.width, 0, rect.size.width*0.21, rect.size.height); - CGContextSetFillColorWithColor(context, [NSColor colorWithRed:246.0/255.0 green:137.0/255.0 blue:36.0/255.0 alpha:1.0].CGColor); + CGContextSetFillColorWithColor(context, [NSColor colorWithSRGBRed:246.0/255.0 green:137.0/255.0 blue:36.0/255.0 alpha:1.0].CGColor); CGContextBeginPath(context); CGContextAddRect(context, rect1); CGContextClosePath(context); CGContextDrawPath(context, kCGPathFill); - CGContextSetFillColorWithColor(context, [NSColor colorWithRed:204.0/255.0 green:56.0/255.0 blue:70.0/255.0 alpha:1.0].CGColor); + CGContextSetFillColorWithColor(context, [NSColor colorWithSRGBRed:204.0/255.0 green:56.0/255.0 blue:70.0/255.0 alpha:1.0].CGColor); CGContextBeginPath(context); CGContextAddRect(context, rect2); CGContextClosePath(context); CGContextDrawPath(context, kCGPathFill); - CGContextSetFillColorWithColor(context, [NSColor colorWithRed:121.0/255.0 green:195.0/255.0 blue:218.0/255.0 alpha:1.0].CGColor); + CGContextSetFillColorWithColor(context, [NSColor colorWithSRGBRed:121.0/255.0 green:195.0/255.0 blue:218.0/255.0 alpha:1.0].CGColor); CGContextBeginPath(context); CGContextAddRect(context, rect3); CGContextClosePath(context); diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMConfiguration/KMConfigurationWindowController.m b/mac/Keyman4MacIM/Keyman4MacIM/KMConfiguration/KMConfigurationWindowController.m index 90f13f0747..555cda2874 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMConfiguration/KMConfigurationWindowController.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMConfiguration/KMConfigurationWindowController.m @@ -164,7 +164,7 @@ [textField setBackgroundColor:[NSColor clearColor]]; [textField setAlignment:NSLeftTextAlignment]; [textField setFont:[NSFont systemFontOfSize:tableView.rowHeight*0.5]]; - [textField setTextColor:[NSColor colorWithRed:0.0 green:0.0 blue:0.1 alpha:1.0]]; + [textField setTextColor:[NSColor colorWithSRGBRed:0.0 green:0.0 blue:0.1 alpha:1.0]]; [textField setStringValue:[info objectForKey:@"HeaderTitle"]]; [rowView addSubview:textField]; return rowView; @@ -177,7 +177,7 @@ NSDictionary *info = [self.tableContents objectAtIndex:row]; BOOL isHeader = ([info objectForKey:@"HeaderTitle"] != nil); if (isHeader) - [rowView setBackgroundColor:[NSColor colorWithRed:186.0/255.0 green:211.0/255.0 blue:1.0 alpha:1.0]]; + [rowView setBackgroundColor:[NSColor colorWithSRGBRed:186.0/255.0 green:211.0/255.0 blue:1.0 alpha:1.0]]; } - (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.m b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.m index 8dc3b8a356..8f0ed47a90 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.m @@ -91,8 +91,16 @@ typedef enum { NSUInteger index = NSNotFound; if ((index = [value rangeOfString:@"filename="].location) != NSNotFound) _downloadFilename = [NSString stringWithString:[value substringFromIndex:index+9]]; - else if ((index = [value rangeOfString:@"url="].location) != NSNotFound) - downloadUrl = [NSURL URLWithString:[[NSString stringWithString:[value substringFromIndex:index+4]] stringByRemovingPercentEncoding]]; + else if ((index = [value rangeOfString:@"url="].location) != NSNotFound) { + NSString *urlString = [NSString stringWithString:[value substringFromIndex:index+4]]; + if ([urlString respondsToSelector:@selector(stringByRemovingPercentEncoding)]) + urlString = [urlString stringByRemovingPercentEncoding]; + else if ([urlString respondsToSelector:@selector(stringByReplacingPercentEscapesUsingEncoding:)]) { + // OS version prior to 10.9 - use this (now deprecated) method instead: + urlString = [urlString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + } + downloadUrl = [NSURL URLWithString:urlString]; + } } if (downloadUrl && _downloadFilename) { diff --git a/mac/Keyman4MacIM/Keyman4MacIM/OnScreenKeyboard/OSKWindowController.m b/mac/Keyman4MacIM/Keyman4MacIM/OnScreenKeyboard/OSKWindowController.m index e53b0e274b..02f76bf837 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/OnScreenKeyboard/OSKWindowController.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/OnScreenKeyboard/OSKWindowController.m @@ -34,7 +34,7 @@ NSSize size = self.window.frame.size; [self.window setMaxSize:NSMakeSize(size.width*1.6, size.height*1.6)]; [self.window setMinSize:NSMakeSize(size.width*0.8, size.height*0.8)]; - [self.window setBackgroundColor:[NSColor colorWithRed:241.0/255.0 green:242.0/255.0 blue:242.0/255.0 alpha:1.0]]; + [self.window setBackgroundColor:[NSColor colorWithSRGBRed:241.0/255.0 green:242.0/255.0 blue:242.0/255.0 alpha:1.0]]; _helpButton = [[NSButton alloc] initWithFrame:NSMakeRect(0, 0, 17, 17)]; [_helpButton setTitle:@""]; diff --git a/web/history.md b/web/history.md index f3320ff23f..2859a36a31 100644 --- a/web/history.md +++ b/web/history.md @@ -10,6 +10,7 @@ * Refactored code paths relating to KMW's embedding in the iOS and Android apps. (#211) * Added support for L/R Alt and Ctrl modifiers for keyboards. (#9) (#52) * Added support for use of the Caps Lock state within keyboards if specified by a keyboard designer. +* Reworked the keyboard-interfacing API calls and base layout of KeymanWeb (#349) * Fixed keyboard loading upon initialization, redundant cloud requests for keyboards. (#103) * Fixed next-layer processing (#116) (#358) * Fixed auto-attaching mode bug. (#352) diff --git a/web/samples/compiled.html b/web/samples/compiled.html index 457b8d8716..42725d12b7 100644 --- a/web/samples/compiled.html +++ b/web/samples/compiled.html @@ -36,7 +36,7 @@ - - - - - - - - - - - - - - - - - - - - - - -

KeymanWeb Sample Page - Uncompiled Source

- -
- -
- -

Type in your language in this text area:

- - -

or in this input field:

- - - -

Add a keyboard by keyboard name:

- - - -

Add a keyboard by ISO 639 language code:

- - - -

Add a keyboard by language name:

- - - - -

Return to samples home page

-
- - - - - diff --git a/web/samples/uncompiled.html b/web/samples/uncompiled.html index 2fc4de778d..1797823c18 100644 --- a/web/samples/uncompiled.html +++ b/web/samples/uncompiled.html @@ -44,9 +44,9 @@ diff --git a/web/source/build.bat b/web/source/build.bat index 17b0b245bf..12fceb625d 100644 --- a/web/source/build.bat +++ b/web/source/build.bat @@ -64,7 +64,7 @@ del %EMBED_OUTPUT%\kmw-smpstring.js 2>nul if not exist %EMBED_OUTPUT%\kmw-smpstring.js goto fail del kmwtemp.js 2>nul -%compilecmd% --define tavultesoft.__BUILD__=%BUILD% --externs %SOURCE%\kmwreleasestub.js --js %SOURCE%\kmwbase.js --js %SOURCE%\keymanweb.js --js %SOURCE%\kmwosk.js --js %SOURCE%\kmwembedded.js --js %SOURCE%\kmwcallback.js --js %SOURCE%\kmwkeymaps.js --js %SOURCE%\kmwlayout.js --js %SOURCE%\kmwinit.js --compilation_level SIMPLE_OPTIMIZATIONS --js_output_file kmwtemp.js --warning_level VERBOSE +%compilecmd% --define keyman.__BUILD__=%BUILD% --externs %SOURCE%\kmwreleasestub.js --js %SOURCE%\kmwbase.js --js %SOURCE%\keymanweb.js --js %SOURCE%\kmwosk.js --js %SOURCE%\kmwembedded.js --js %SOURCE%\kmwcallback.js --js %SOURCE%\kmwkeymaps.js --js %SOURCE%\kmwlayout.js --js %SOURCE%\kmwinit.js --compilation_level SIMPLE_OPTIMIZATIONS --js_output_file kmwtemp.js --warning_level VERBOSE if not exist kmwtemp.js goto fail echo Append SMP extensions @@ -109,7 +109,7 @@ rem Compile KeymanWeb code modules for native keymanweb use, stubbing out and re echo Compile Keymanweb del %WEB_OUTPUT%\kmwtemp.js 2>nul -%compilecmd% --define tavultesoft.__BUILD__=%BUILD% --externs %SOURCE%\kmwreleasestub.js --js %SOURCE%\kmwbase.js --js %SOURCE%\keymanweb.js --js %SOURCE%\kmwosk.js --js %SOURCE%\kmwnative.js --js %SOURCE%\kmwcallback.js --js %SOURCE%\kmwkeymaps.js --js %SOURCE%\kmwlayout.js --js %SOURCE%\kmwinit.js --compilation_level SIMPLE_OPTIMIZATIONS --js_output_file %WEB_OUTPUT%\kmwtemp.js --warning_level VERBOSE +%compilecmd% --define keyman.__BUILD__=%BUILD% --externs %SOURCE%\kmwreleasestub.js --js %SOURCE%\kmwbase.js --js %SOURCE%\keymanweb.js --js %SOURCE%\kmwosk.js --js %SOURCE%\kmwnative.js --js %SOURCE%\kmwcallback.js --js %SOURCE%\kmwkeymaps.js --js %SOURCE%\kmwlayout.js --js %SOURCE%\kmwinit.js --compilation_level SIMPLE_OPTIMIZATIONS --js_output_file %WEB_OUTPUT%\kmwtemp.js --warning_level VERBOSE if not exist %WEB_OUTPUT%\kmwtemp.js goto fail echo Append SMP string extensions to Keymanweb diff --git a/web/source/build.sh b/web/source/build.sh index dcc4f3ac08..4efbc8b190 100755 --- a/web/source/build.sh +++ b/web/source/build.sh @@ -134,7 +134,7 @@ if [ $BUILD_EMBED = true ]; then assert $EMBED_OUTPUT/kmw-smpstring.js rm kmwtemp.js 2>/dev/null - $compilecmd --define tavultesoft.__BUILD__=$BUILD --externs $SOURCE/kmwreleasestub.js --js $SOURCE/kmwbase.js --js $SOURCE/keymanweb.js --js $SOURCE/kmwosk.js --js $SOURCE/kmwembedded.js --js $SOURCE/kmwcallback.js --js $SOURCE/kmwkeymaps.js --js $SOURCE/kmwlayout.js --js $SOURCE/kmwinit.js --compilation_level SIMPLE_OPTIMIZATIONS --js_output_file kmwtemp.js --warning_level VERBOSE + $compilecmd --define keyman.__BUILD__=$BUILD --externs $SOURCE/kmwreleasestub.js --js $SOURCE/kmwbase.js --js $SOURCE/keymanweb.js --js $SOURCE/kmwosk.js --js $SOURCE/kmwembedded.js --js $SOURCE/kmwcallback.js --js $SOURCE/kmwkeymaps.js --js $SOURCE/kmwlayout.js --js $SOURCE/kmwinit.js --compilation_level SIMPLE_OPTIMIZATIONS --js_output_file kmwtemp.js --warning_level VERBOSE assert kmwtemp.js echo Append SMP extensions @@ -179,7 +179,7 @@ if [ $BUILD_COREWEB = true ]; then # Compile KeymanWeb code modules for native keymanweb use, stubbing out and removing references to debug functions echo Compile Keymanweb rm $WEB_OUTPUT/kmwtemp.js 2>/dev/null - $compilecmd --define tavultesoft.__BUILD__=$BUILD --externs $SOURCE/kmwreleasestub.js --js $SOURCE/kmwbase.js --js $SOURCE/keymanweb.js --js $SOURCE/kmwosk.js --js $SOURCE/kmwnative.js --js $SOURCE/kmwcallback.js --js $SOURCE/kmwkeymaps.js --js $SOURCE/kmwlayout.js --js $SOURCE/kmwinit.js --compilation_level SIMPLE_OPTIMIZATIONS --js_output_file $WEB_OUTPUT/kmwtemp.js --warning_level VERBOSE + $compilecmd --define keyman.__BUILD__=$BUILD --externs $SOURCE/kmwreleasestub.js --js $SOURCE/kmwbase.js --js $SOURCE/keymanweb.js --js $SOURCE/kmwosk.js --js $SOURCE/kmwnative.js --js $SOURCE/kmwcallback.js --js $SOURCE/kmwkeymaps.js --js $SOURCE/kmwlayout.js --js $SOURCE/kmwinit.js --compilation_level SIMPLE_OPTIMIZATIONS --js_output_file $WEB_OUTPUT/kmwtemp.js --warning_level VERBOSE assert $WEB_OUTPUT/kmwtemp.js echo Append SMP string extensions to Keymanweb diff --git a/web/source/keymanweb.js b/web/source/keymanweb.js index fc29627eb8..2734f799f5 100644 --- a/web/source/keymanweb.js +++ b/web/source/keymanweb.js @@ -6,7 +6,7 @@ // If KMW is already initialized, the KMW script has been loaded more than once. We wish to prevent resetting the // KMW system, so we use the fact that 'initialized' is only 1 / true after all scripts are loaded for the initial // load of KMW. -if(!window['tavultesoft']['keymanweb']['initialized']) { +if(!window['keyman']['initialized']) { /****************************************************************** * Main Keyman Web Module @@ -18,7 +18,8 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { (function() { // Declare KeymanWeb, OnScreen Keyboard and Util objects - var keymanweb=window['tavultesoft']['keymanweb'],osk=keymanweb['osk'],util=keymanweb['util'],device=util.device; + var keymanweb=window['keyman'],osk=keymanweb['osk'],util=keymanweb['util'],device=util.device; + var kbdInterface=keymanweb['interface']; /** * Function debug @@ -1510,7 +1511,7 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { tFlag,Lscript = util._CreateElement('SCRIPT'); URL=URL+((arguments.length > 1) && byLanguage ? 'languages' : 'keyboards') - +'?jsonp=tavultesoft.keymanweb.register'; + +'?jsonp=keyman.register'; // Set callback timer tFlag='&timerid='+window.setTimeout( @@ -3133,14 +3134,14 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { // Support backspace in simulated input DIV from physical keyboard where not matched in rule I3363 (Build 301) if(Levent.Lcode == 8 && !LeventMatched && Levent.Ltarg.className != null && Levent.Ltarg.className.indexOf('keymanweb-input') >= 0) { - keymanweb.KO(1,keymanweb._LastActiveElement,""); + kbdInterface.output(1,keymanweb._LastActiveElement,""); } } else { // Mnemonic layout if(Levent.Lcode == 8) { // I1595 - Backspace for mnemonic keymanweb._KeyPressToSwallow = 1; if(!keymanweb.callKeyboardStartGroup(Levent.Ltarg,Levent)) { - keymanweb.KO(1,keymanweb._LastActiveElement,""); // I3363 (Build 301) + kbdInterface.output(1,keymanweb._LastActiveElement,""); // I3363 (Build 301) } return false; //added 16/3/13 to fix double backspace on mnemonic layouts on desktop } @@ -3158,7 +3159,7 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { } else { Lch = Levent.Lcode-64; } - keymanweb.KO(0, Levent.Ltarg, String._kmwFromCharCode(Lch)); //I3319 + kbdInterface.output(0, Levent.Ltarg, String._kmwFromCharCode(Lch)); //I3319 LeventMatched = 1; } @@ -4231,15 +4232,17 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { keymanweb.addKeyboardArray(keymanweb.deferredStubs); // KRS stubs (legacy format registration) - for(j=0; j 1) keymanweb._KeyboardStubs.sort(function(a,b){ - var ax,bx; - switch(a['KLC']) - { - case 'eng': ax=0; break; - case 'fra': ax=1; break; - case 'deu': ax=2; break; - default: ax=10; break; - } - switch(b['KLC']) - { - case 'eng': bx=0; break; - case 'fra': bx=1; break; - case 'deu': bx=2; break; - default: bx=10; break; - } - return ax-bx; - }); - */ + // TODO: Need to distinguish between initial loading of a large number of stubs and any subsequent loading. // UI initialization should not be needed for each registration, only at end. // Reload this keyboard if it was the last active keyboard and @@ -206,18 +189,19 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { * KC(10,10,Pelem) == "abcdef" i.e. return as much as possible of the requested string */ - keymanweb['KC'] = keymanweb.KC = function(n, ln, Pelem) - { + KeymanWeb['KC'] = kbdInterface['context'] = kbdInterface.context = function(n, ln, Pelem) { var v = keymanweb.cachedContext.get(n, ln); - if(v !== null) return v; + if(v !== null) { + return v; + } - var r = keymanweb.KC_(n, ln, Pelem); + var r = keymanweb.KC_(n, ln, Pelem); keymanweb.cachedContext.set(n, ln, r); return r; } /** - * Function KN + * Function nul KN * Scope Public * @param {number} n Length of context to check * @param {Object} Ptarg Element to work with (must be currently focused element) @@ -229,21 +213,15 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { * KN(2,Pelem) == FALSE * KN(4,Pelem) == TRUE */ - keymanweb['KN'] = keymanweb.KN = function(n, Ptarg) // KeyboardNul - { - var cx=this.KC(n+1, 1, Ptarg); - if(cx === false) { - // It appears that this can no longer be returned with KMW so probably should be removed - // after testing - return true; - } + KeymanWeb['KN'] = kbdInterface['nul'] = kbdInterface.nul = function(n, Ptarg) { + var cx=kbdInterface.context(n+1, 1, Ptarg); // With #31, the result will be a replacement character if context is empty. return cx === "\uFFFE"; } /** - * Function KCM + * Function contextMatch KCM * Scope Public * @param {number} n Number of characters to move back from caret * @param {Object} Ptarg Focused element @@ -252,12 +230,13 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { * @return {boolean} True if selected context matches val * Description Test keyboard context for match */ - keymanweb['KCM'] = keymanweb.KCM = function(n, Ptarg, val, ln) // Keyboard_ContextMatch - { - //KeymanWeb._Debug('KeymanWeb.KCM(n='+n+', Ptarg, val='+val+', ln='+ln+'): return '+(this.KC(n,ln,Ptarg)==val)); - var cx=this.KC(n, ln, Ptarg); - if(cx !== false && cx === val) return true; // I3318 - this._DeadkeyResetMatched(); // I3318 + KeymanWeb['KCM'] = kbdInterface['contextMatch'] = kbdInterface.contextMatch = function(n, Ptarg, val, ln) { + //KeymanWeb._Debug('KeymanWeb.KCM(n='+n+', Ptarg, val='+val+', ln='+ln+'): return '+(kbdInterface.context(n,ln,Ptarg)==val)); + var cx=kbdInterface.context(n, ln, Ptarg); + if(cx === val) { + return true; // I3318 + } + keymanweb._DeadkeyResetMatched(); // I3318 return false; } @@ -268,19 +247,16 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { * @return {boolean} true if keypress event * Description Test if event as a keypress event */ - keymanweb['KIK'] = keymanweb.KIK = function(e) // Keyboard_IsKeypress - { - if(keymanweb._ActiveKeyboard['KM']) // I1380 - support KIK for positional layouts + KeymanWeb['KIK'] = kbdInterface['isKeypress'] = kbdInterface.isKeypress = function(e) { + if(keymanweb._ActiveKeyboard['KM']) { // I1380 - support KIK for positional layouts return !e.LisVirtualKey; // will now return true for U_xxxx keys, but not for T_xxxx keys - else + } else { return keymanweb._USKeyCodeToCharCode(e) ? true : false; // I1380 - support KIK for positional layouts - //if(e.charCode != 0) != null) - // return e.charCode != 0; - //return e.type == 'keypress'; + } } /** - * Function KKM + * Function keyMatch KKM * Scope Public * @param {Object} e keystroke event * @param {number} Lruleshift @@ -288,57 +264,57 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { * @return {boolean} True if key matches rule * Description Test keystroke with modifiers against rule */ - keymanweb['KKM'] = keymanweb.KKM = function(e,Lruleshift,Lrulekey) // Keyboard_KeyMatch - { + KeymanWeb['KKM'] = kbdInterface['keyMatch'] = kbdInterface.keyMatch = function(e,Lruleshift,Lrulekey) { var retVal = 0; // I3318 var keyCode = (e.Lcode == 173 ? 189 : e.Lcode); //I3555 (Firefox hyphen issue) var bitmask = keymanweb.getKeyboardModifierBitmask(); - if(e.vkCode > 255) keyCode = e.vkCode; // added to support extended (touch-hold) keys for mnemonic layouts + if(e.vkCode > 255) { + keyCode = e.vkCode; // added to support extended (touch-hold) keys for mnemonic layouts + } - if(e.LisVirtualKey || keyCode > 255) - { - if((Lruleshift & 0x4000) == 0x4000 || (keyCode > 255)) // added keyCode test to support extended keys - { - retVal = ((Lrulekey == keyCode) && ((Lruleshift & bitmask) == e.Lmodifiers)); //I3318, I3555 + if(e.LisVirtualKey || keyCode > 255) { + if((Lruleshift & 0x4000) == 0x4000 || (keyCode > 255)) { // added keyCode test to support extended keys + retVal = ((Lrulekey == keyCode) && ((Lruleshift & bitmask) == e.Lmodifiers)); //I3318, I3555 } + } else if((Lruleshift & 0x4000) == 0) { + retVal = (keyCode == Lrulekey); // I3318, I3555 } - else if((Lruleshift & 0x4000) == 0) - { - retVal = (keyCode == Lrulekey); // I3318, I3555 + if(!retVal) { + keymanweb._DeadkeyResetMatched(); // I3318 } - if(!retVal) this._DeadkeyResetMatched(); // I3318 - return retVal != 0; // I3318 + return retVal != 0; // I3318 }; /** - * Function KSM + * Function stateMatch KSM * Scope Public * @param {Object} e keystroke event * @param {number} Lstate * Description Test keystroke against state key rules */ - keymanweb['KSM'] = keymanweb.KSM = function(e, Lstate) { // Keyboard_StateMatch + KeymanWeb['KSM'] = kbdInterface['stateMatch'] = kbdInterface.stateMatch = function(e, Lstate) { return ((Lstate & e.Lstates) == Lstate); } /** - * Function KKI + * Function keyInformation KKI * Scope Public * @param {Object} e * @return {Object} Object with event's virtual key flag, key code, and modifiers * Description Get object with extended key event information */ - keymanweb['KKI'] = keymanweb.KKI = function(e) - { + KeymanWeb['KKI'] = kbdInterface['keyInformation'] = kbdInterface.keyInformation = function(e) { var ei = {}; - ei['vk'] = e.LisVirtualKey; ei['code'] = e.Lcode; ei['modifiers'] = e.Lmodifiers; + ei['vk'] = e.LisVirtualKey; + ei['code'] = e.Lcode; + ei['modifiers'] = e.Lmodifiers; return ei; }; /** - * Function KDM + * Function deadkeyMatch KDM * Scope Public * @param {number} n current cursor position * @param {Object} Ptarg target element @@ -346,70 +322,74 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { * @return {boolean} True if deadkey found selected context matches val * Description Match deadkey at current cursor position */ - keymanweb['KDM'] = keymanweb.KDM = function(n, Ptarg, d) - { - if(keymanweb._DeadKeys.length == 0) return false; // I3318 - - var sp=keymanweb._SelPos(Ptarg); - n = sp - n; - for(var i = 0; i < keymanweb._DeadKeys.length; i++) + KeymanWeb['KDM'] = kbdInterface['deadkeyMatch'] = kbdInterface.deadkeyMatch = function(n, Ptarg, d) { + if(keymanweb._DeadKeys.length == 0) { + return false; // I3318 + } + + var sp=keymanweb._SelPos(Ptarg); + n = sp - n; + for(var i = 0; i < keymanweb._DeadKeys.length; i++) { if(keymanweb._DeadKeys[i].p == n && keymanweb._DeadKeys[i].d == d) { - keymanweb._DeadKeys[i].matched = 1; return true; // I3318 + keymanweb._DeadKeys[i].matched = 1; + return true; // I3318 } - this._DeadkeyResetMatched(); // I3318 + } + keymanweb._DeadkeyResetMatched(); // I3318 return false; } /** - * Function KBR + * Function beepReset KBR * Scope Public * Description Reset/terminate beep or flash (not currently used: Aug 2011) */ - keymanweb['KBR'] = keymanweb.KBR = function() // KeyboardBeepReset - { + KeymanWeb['KBR'] = kbdInterface['beepReset'] = kbdInterface.beepReset = function() { keymanweb.cachedContext.reset(); var Lbo; keymanweb._BeepTimeout = 0; - for(Lbo=0;Lbo= 0) - { + if(Pelem.className.indexOf('keymanweb-input') >= 0) { var t=keymanweb.getTextBeforeCaret(Pelem); - if(dn > 0) t=t._kmwSubstr(0,t._kmwLength()-dn)+s; else t=t+s; + if(dn > 0) { + t=t._kmwSubstr(0,t._kmwLength()-dn)+s; + } else { + t=t+s; + } keymanweb.setTextBeforeCaret(Pelem,t); return; } - if (keymanweb.legacy) - { - if(dn>0) + if (keymanweb.legacy) { + if(dn>0) { Pelem.value=Pelem.value._kmwSubstr(0,Pelem.value._kmwLength()-dn)+s; //I3319 - else + } else { Pelem.value=Pelem.value+s; - } - else if (Ldoc && (Ldv=Ldoc.defaultView) && Ldv.getSelection && + } + } else if (Ldoc && (Ldv=Ldoc.defaultView) && Ldv.getSelection && (Ldoc.designMode.toLowerCase() == 'on' || Pelem.contentEditable == 'true' || Pelem.contentEditable == 'plaintext-only' || Pelem.contentEditable === '') - ) // I2457 - support contentEditable elements in mozilla, webkit - { + ) { // I2457 - support contentEditable elements in mozilla, webkit /* Editable iframe and contentEditable elements for mozilla */ var _IsEditableIframe = Ldoc.designMode.toLowerCase() == 'on'; - if(_IsEditableIframe) var _CacheableCommands = keymanweb._CacheCommands(Ldoc); + if(_IsEditableIframe) { + var _CacheableCommands = keymanweb._CacheCommands(Ldoc); + } var Lsel = Ldv.getSelection(); var LselectionStart = Lsel.focusNode.nodeValue ? Lsel.focusNode.substringData(0,Lsel.focusOffset)._kmwLength() : 0; // I3319 - if(!Lsel.isCollapsed) Lsel.deleteFromDocument(); // I2134, I2192 + if(!Lsel.isCollapsed) { + Lsel.deleteFromDocument(); // I2134, I2192 + } //KeymanWeb._Debug('KO: focusOffset='+Lsel.focusOffset+', dn='+dn+', s='+s+' focusNode.type='+Lsel.focusNode.nodeType+', focusNode.parentNode.tagName='+(Lsel.focusNode.parentNode?Lsel.focusNode.parentNode.tagName:'NULL') ); var Lrange = Lsel.getRangeAt(0); - if(dn > 0) { + if(dn > 0) { Lrange.setStart(Lsel.focusNode, Lsel.focusOffset - Lsel.focusNode.nodeValue.substr(0,Lsel.focusOffset)._kmwSubstr(-dn).length); // I3319 - Lrange.deleteContents(); + Lrange.deleteContents(); } //KeymanWeb._Debug('KO: focusOffset='+Lsel.focusOffset+', dn='+dn+', s='+s+' focusNode.type='+Lsel.focusNode.nodeType+', focusNode.parentNode.tagName='+(Lsel.focusNode.parentNode?Lsel.focusNode.parentNode.tagName:'NULL') ); - if(s._kmwLength() > 0) // I2132 - exception if s.length > 0, I3319 - { - if(Lsel.focusNode.nodeType == 3) - { + if(s._kmwLength() > 0) { // I2132 - exception if s.length > 0, I3319 + if(Lsel.focusNode.nodeType == 3) { // I2134, I2192 // Already in a text node //KeymanWeb._Debug('KO: Already in a text node, adding "'+s+'": '+Lsel.focusOffset + '-> '+Lsel.toString()); var LfocusOffset = Lsel.focusOffset; //KeymanWeb._Debug('KO: node.text="'+Lsel.focusNode.data+'", node.length='+Lsel.focusNode.length); Lsel.focusNode.insertData(Lsel.focusOffset, s); - try - { + try { Lsel.extend(Lsel.focusNode, LfocusOffset + s.length); - } - catch(e) - { + } catch(e) { // Chrome (through 4.0 at least) throws an exception because it has not synchronised its content with the selection. scrollIntoView synchronises the content for selection Lsel.focusNode.parentNode.scrollIntoView(); Lsel.extend(Lsel.focusNode, LfocusOffset + s.length); } - } - else - { + } else { // Create a new text node - empty control //KeymanWeb._Debug('KO: Creating a new text node for "'+s+'"'); var n = Ldoc.createTextNode(s); @@ -515,46 +494,43 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { Lsel.extend(n,s.length); } } - if(_IsEditableIframe) keymanweb._CacheCommandsReset(Ldoc, _CacheableCommands, null);// I2457 - support contentEditable elements in mozilla, webkit + + if(_IsEditableIframe) { + keymanweb._CacheCommandsReset(Ldoc, _CacheableCommands, null);// I2457 - support contentEditable elements in mozilla, webkit + } Lsel.collapseToEnd(); // Adjust deadkey positions - if(dn >= 0) - { + if(dn >= 0) { keymanweb._DeadkeyDeleteMatched(); // I3318 keymanweb._DeadkeyAdjustPos(LselectionStart, -dn + s._kmwLength()); // I3318 - } - } - - // Internet Explorer (including IE9) - else if(Ldoc && (Ldv=Ldoc.selection)) // build 77 - use elem.ownerDocument.selection - { - if(Ldoc.body.isContentEditable || Ldoc.designMode.toLowerCase()=='on') // I1295 - isContentEditable - { + } // Internet Explorer (including IE9) + } else if(Ldoc && (Ldv=Ldoc.selection)) { // build 77 - use elem.ownerDocument.selection + if(Ldoc.body.isContentEditable || Ldoc.designMode.toLowerCase()=='on') { // I1295 - isContentEditable var _CacheableCommands = keymanweb._CacheCommands(Ldoc); } var Lrange = Ldv.createRange(), Ls1; - if(Lrange.text != '') - { + if(Lrange.text != '') { Ldv.clear(); dn = 0; + } else { + Lrange.collapse(true); } - else Lrange.collapse(true); if(dn > 0) { Lrange.moveStart('character',-2*dn); // I3319 (next four lines var s0=Lrange.text,s1=s0._kmwSubstr(-dn); Lrange.collapse(false); //move start back to end Lrange.moveStart('character',-s1.length); + } else { + dn = 0; } - else dn = 0; Lrange.text = s; - if(Ldoc.body.isContentEditable || Ldoc.designMode.toLowerCase()=='on') // I1295 - isContentEditable - { + if(Ldoc.body.isContentEditable || Ldoc.designMode.toLowerCase()=='on') { // I1295 - isContentEditable Lrange.moveStart('character',-s.length); keymanweb._CacheCommandsReset(Ldoc, _CacheableCommands,Lrange.select); @@ -562,8 +538,7 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { Lrange.select(); } // Adjust deadkey positions - if(dn >= 0) - { + if(dn >= 0) { keymanweb._DeadkeyDeleteMatched(); // I3318 keymanweb._DeadkeyAdjustPos(LselectionStart, -dn + s._kmwLength()); // I3318 } @@ -571,20 +546,14 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { keymanweb._Selection = Ldv.createRange(); keymanweb._Selection.select(); keymanweb._Selection.scrollIntoView(); - } - - // Mozilla et al; IE9+ also recognizes setSelectionRange, but does not seem to work in exactly the same way as Mozilla - else if (Pelem.setSelectionRange) - { + // Mozilla et al; IE9+ also recognizes setSelectionRange, but does not seem to work in exactly the same way as Mozilla + } else if (Pelem.setSelectionRange) { var LselectionStart, LselectionEnd; - if(Pelem._KeymanWebSelectionStart != null) // changed to allow a value of 0 - { + if(Pelem._KeymanWebSelectionStart != null) {// changed to allow a value of 0 LselectionStart = Pelem._KeymanWebSelectionStart; LselectionEnd = Pelem._KeymanWebSelectionEnd; - } - else - { + } else { LselectionStart = Pelem.value._kmwCodeUnitToCodePoint(Pelem.selectionStart); // I3319 LselectionEnd = Pelem.value._kmwCodeUnitToCodePoint(Pelem.selectionEnd); // I3319 } @@ -594,19 +563,17 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { LscrollTop = Pelem.scrollTop; LscrollLeft = Pelem.scrollLeft; } - if(dn < 0) // Don't delete, leave context alone (dn = -1) - { + if(dn < 0) {// Don't delete, leave context alone (dn = -1) Pelem.value = Pelem.value._kmwSubstring(0,LselectionStart) + s + Pelem.value._kmwSubstring(LselectionEnd); //I3319 dn = 0; - } - else if(LselectionStart < dn) + } else if(LselectionStart < dn) { Pelem.value = s + Pelem.value._kmwSubstring(LselectionEnd); //I3319 - else + } else { Pelem.value = Pelem.value._kmwSubstring(0,LselectionStart-dn) + s + Pelem.value._kmwSubstring(LselectionEnd); //I3319 + } // Adjust deadkey positions - if(dn >= 0) - { + if(dn >= 0) { keymanweb._DeadkeyDeleteMatched(); // I3318 keymanweb._DeadkeyAdjustPos(LselectionStart, -dn + s._kmwLength()); // I3318,I3319 } @@ -623,30 +590,34 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { } // Refresh element content after change (if needed) - if(typeof(keymanweb.refreshElementContent) == 'function') keymanweb.refreshElementContent(Pelem); + if(typeof(keymanweb.refreshElementContent) == 'function') { + keymanweb.refreshElementContent(Pelem); + } } /** - * Function KDO + * Function deadkeyOutput KDO * Scope Public * @param {number} Pdn no of character to overwrite (delete) * @param {Object} Pelem element to output to * @param {number} Pd deadkey id * Description Record a deadkey at current cursor position, deleting Pdn characters first */ - keymanweb['KDO'] = keymanweb.KDO = function(Pdn,Pelem,Pd) - { - keymanweb.cachedContext.reset(); - var Lc = new Object(); - if(Pdn >= 0) keymanweb.KO(Pdn,Pelem,""); //I3318 corrected to >= - Lc.p=keymanweb._SelPos(Pelem); Lc.d=Pd; - keymanweb._DeadKeys=keymanweb._push(keymanweb._DeadKeys,Lc); - - // _DebugDeadKeys(Pelem, 'KDeadKeyOutput: dn='+Pdn+'; deadKey='+Pd); + KeymanWeb['KDO'] = kbdInterface['deadkeyOutput'] = kbdInterface.deadkeyOutput = function(Pdn,Pelem,Pd) { + keymanweb.cachedContext.reset(); + var Lc = new Object(); + if(Pdn >= 0) { + kbdInterface.output(Pdn,Pelem,""); //I3318 corrected to >= + } + Lc.p=keymanweb._SelPos(Pelem); + Lc.d=Pd; + keymanweb._DeadKeys=keymanweb._push(keymanweb._DeadKeys,Lc); + + // _DebugDeadKeys(Pelem, 'KDeadKeyOutput: dn='+Pdn+'; deadKey='+Pd); } /** - * Function KIO + * Function indexOutput KIO * Scope Public * @param {number} Pdn no of character to overwrite (delete) * @param {string} Ps string @@ -654,30 +625,35 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { * @param {Object} Pelem element to output to * Description Output a character selected from the string according to the offset in the index array */ - keymanweb['KIO'] = keymanweb.KIO = function(Pdn,Ps,Pn,Pelem) - { + KeymanWeb['KIO'] = kbdInterface['indexOutput'] = kbdInterface.indexOutput = function(Pdn,Ps,Pn,Pelem) { keymanweb.cachedContext.reset(); - if(keymanweb._AnyIndices[Pn-1] < Ps._kmwLength()) //I3319 - keymanweb.KO(Pdn,Pelem,Ps._kmwCharAt(keymanweb._AnyIndices[Pn-1])); //I3319 + if(keymanweb._AnyIndices[Pn-1] < Ps._kmwLength()) { //I3319 + kbdInterface.output(Pdn,Pelem,Ps._kmwCharAt(keymanweb._AnyIndices[Pn-1])); //I3319 + } } - - /** - * Function _CacheCommands - * Scope Private - * @param {Object} _Document - * @return {Array.} List of style commands that are cacheable - * Description Build reate list of styles that can be applied in iframes - */ - keymanweb._CacheCommands = function(_Document) // I1204 - style application in IFRAMEs, I2192, I2134, I2192 - { + + /** + * Function _CacheCommands + * Scope Private + * @param {Object} _Document + * @return {Array.} List of style commands that are cacheable + * Description Build reate list of styles that can be applied in iframes + */ + KeymanWeb._CacheCommands = function(_Document) { // I1204 - style application in IFRAMEs, I2192, I2134, I2192 //var _CacheableBackColor=(_Document.selection?'hilitecolor':'backcolor'); - var _CacheableCommands=[['backcolor',1],['fontname',1],['fontsize',1],['forecolor',1],['bold',0],['italic',0],['strikethrough',0],['subscript',0],['superscript',0],['underline',0]]; - if(_Document.defaultView) keymanweb._push(_CacheableCommands,['hilitecolor',1]); + var _CacheableCommands=[ + ['backcolor',1],['fontname',1],['fontsize',1],['forecolor',1],['bold',0], + ['italic',0],['strikethrough',0],['subscript',0],['superscript',0],['underline',0] + ]; + if(_Document.defaultView) { + keymanweb._push(_CacheableCommands,['hilitecolor',1]); + } - for(var n=0;n < _CacheableCommands.length; n++) // I1511 - array prototype extended - { + for(var n=0;n < _CacheableCommands.length; n++) { // I1511 - array prototype extended //KeymanWeb._Debug('Command:'+_CacheableCommands[n][0]); - keymanweb._push(_CacheableCommands[n],_CacheableCommands[n][1] ? _Document.queryCommandValue(_CacheableCommands[n][0]) : _Document.queryCommandState(_CacheableCommands[n][0])); + keymanweb._push(_CacheableCommands[n],_CacheableCommands[n][1] ? + _Document.queryCommandValue(_CacheableCommands[n][0]) : + _Document.queryCommandState(_CacheableCommands[n][0])); } return _CacheableCommands; } @@ -691,21 +667,20 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { * @return Nothing * Description Restore styles in IFRAMEs (??) */ - keymanweb._CacheCommandsReset = function(_Document, _CacheableCommands, _func) - { - for(var n=0;n < _CacheableCommands.length; n++) // I1511 - array prototype extended - { + KeymanWeb._CacheCommandsReset = function(_Document, _CacheableCommands, _func) { + for(var n=0;n < _CacheableCommands.length; n++) { // I1511 - array prototype extended //KeymanWeb._Debug('ResetCacheCommand:'+_CacheableCommands[n][0]+'='+_CacheableCommands[n][2]); - if(_CacheableCommands[n][1]) - { - if(_Document.queryCommandValue(_CacheableCommands[n][0]) != _CacheableCommands[n][2]) - { - if(_func)_func(); + if(_CacheableCommands[n][1]) { + if(_Document.queryCommandValue(_CacheableCommands[n][0]) != _CacheableCommands[n][2]) { + if(_func) { + _func(); + } _Document.execCommand(_CacheableCommands[n][0], false, _CacheableCommands[n][2]); } - } - else if(_Document.queryCommandState(_CacheableCommands[n][0]) != _CacheableCommands[n][2]) - {if(_func)_func(); + } else if(_Document.queryCommandState(_CacheableCommands[n][0]) != _CacheableCommands[n][2]) { + if(_func) { + _func(); + } //KeymanWeb._Debug('executing command '+_CacheableCommand[n][0]); _Document.execCommand(_CacheableCommands[n][0], false, null); } @@ -719,44 +694,48 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { * @param {string} strValue String value to compare to * @param {Object} Pelem Currently active element (may be needed by future tests) * @return {boolean} True if the test succeeds - */ - keymanweb['KIFS'] = keymanweb.KIFS = function(systemId,strValue,Pelem) - { - var result=true; - if(systemId == keymanweb.TSS_LAYER) + */ + KeymanWeb['KIFS'] = kbdInterface['ifStore'] = kbdInterface.ifStore = function(systemId,strValue,Pelem) { + var result=true; + if(systemId == keymanweb.TSS_LAYER) { result = (osk.layerId === strValue); - else if(systemId == keymanweb.TSS_PLATFORM) - { + } else if(systemId == keymanweb.TSS_PLATFORM) { var i,constraint,constraints=strValue.split(' '); - for(i=0; i Lp) Lp = keymanweb._DeadKeys[Li].p; } - Ls = keymanweb.KC(Lp+1, Lp+1, Pelem); Lt = ''; + Ls = kbdInterface.context(Lp+1, Lp+1, Pelem); Lt = ''; if(Ls !== false && Ls._kmwLength() > Lp) //I3319 { /* We want to show the previous character in the context */ @@ -219,7 +219,7 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { if(keymanweb._DeadKeys[Li].p > Lp) Lp = keymanweb._DeadKeys[Li].p; } - var Ls = keymanweb.KC(Lp, Lp, Pelem); + var Ls = kbdInterface.context(Lp, Lp, Pelem); Lt = keymanweb._DebugDepth + '   Context='+Ls+'
'; for(Li = 0; Li < keymanweb._DeadKeys.length; Li++) diff --git a/web/source/kmwembedded.js b/web/source/kmwembedded.js index 4fa4cc1323..360658890c 100644 --- a/web/source/kmwembedded.js +++ b/web/source/kmwembedded.js @@ -9,7 +9,8 @@ (function() { // Declare KeymanWeb and related objects - var keymanweb=window['tavultesoft']['keymanweb'],osk=keymanweb['osk'],util=keymanweb['util'],device=util.device; + var keymanweb=window['keyman'],osk=keymanweb['osk'],util=keymanweb['util'],device=util.device; + var kbdInterface=keymanweb['interface']; // Allow definition of application name keymanweb.options['app']=''; @@ -532,16 +533,16 @@ */ keymanweb.processDefaultMapping = function(code, shift, Lelem, keyName) { if (code == osk.keyCodes.K_SPACE) { - keymanweb.KO(0, Lelem, ' '); + kbdInterface.output(0, Lelem, ' '); return true; } else if (code == osk.keyCodes.K_ENTER) { - keymanweb.KO(0, Lelem, '\n'); + kbdInterface.output(0, Lelem, '\n'); return true; } var ch = osk.defaultKeyOutput(keyName, code, shift); if(ch) { - keymanweb.KO(0, Lelem, ch); + kbdInterface.output(0, Lelem, ch); return true; } diff --git a/web/source/kmwinit.js b/web/source/kmwinit.js index ced5f6c646..17719c959c 100644 --- a/web/source/kmwinit.js +++ b/web/source/kmwinit.js @@ -10,18 +10,16 @@ /* */ /********************************************************/ -(function() -{ +(function() { // Declare KeymanWeb object - var keymanweb=window['tavultesoft']['keymanweb']; + var keymanweb=window['keyman']; // We don't want to instantly init() in case this code is used via bookmarklet. var readyStateCheckInterval = window.setInterval(function() { - if (document.readyState === "complete") - { + if (document.readyState === "complete") { window.clearInterval(readyStateCheckInterval); keymanweb.init(null); } - }, 10); - + }, 10); + })(); diff --git a/web/source/kmwkeymaps.js b/web/source/kmwkeymaps.js index fbffe6f643..f79016beb4 100644 --- a/web/source/kmwkeymaps.js +++ b/web/source/kmwkeymaps.js @@ -6,16 +6,15 @@ // If KMW is already initialized, the KMW script has been loaded more than once. We wish to prevent resetting the // KMW system, so we use the fact that 'initialized' is only 1 / true after all scripts are loaded for the initial // load of KMW. -if(!window['tavultesoft']['keymanweb']['initialized']) { +if(!window['keyman']['initialized']) { /** * Cross-browser compatibility keymaps */ - (function() - { + (function() { // Declare KeymanWeb object - var keymanweb=window['tavultesoft']['keymanweb']; + var keymanweb=window['keyman']; - /* I732 START - 13/03/2007 MCD: Swedish: Start mapping of keystroke to US keyboard #2 */ + /* I732 START - 13/03/2007 MCD: Swedish: Start mapping of keystroke to US keyboard #2 */ var ffie = keymanweb._VKMap_FF_IE = {}; //ffie['k109'] = 189; // - // These two number-pad VK rules are *not* correct for more recent FF! JMD 8/11/12 @@ -148,7 +147,7 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { s1['k191'] = 63; keymanweb._USCharCode = [s0,s1]; - + /** * Function _USKeyCodeToCharCode * Scope Private @@ -156,10 +155,9 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { * @return {number} Character code * Description Translate keyboard codes to standard US layout codes */ - keymanweb._USKeyCodeToCharCode = function(Levent) - { + keymanweb._USKeyCodeToCharCode = function(Levent) { return keymanweb._USCharCode[Levent.Lmodifiers & 0x10 ? 1 : 0]['k'+Levent.Lcode]; }; - - })(); + + })(); } \ No newline at end of file diff --git a/web/source/kmwlayout.js b/web/source/kmwlayout.js index 4fe3e354cf..fdf47416bd 100644 --- a/web/source/kmwlayout.js +++ b/web/source/kmwlayout.js @@ -2,8 +2,8 @@ KeymanWeb 10.0 Copyright 2017 SIL International ***/ -if (!window['tavultesoft']['keymanweb']['initialized']) { - window['tavultesoft']['keymanweb']['dfltLayout'] = { +if (!window['keyman']['initialized']) { + window['keyman']['dfltLayout'] = { "desktop": { "font": "Tahoma,Helvetica", diff --git a/web/source/kmwnative.js b/web/source/kmwnative.js index 9b1b438ec3..14a68fc21c 100644 --- a/web/source/kmwnative.js +++ b/web/source/kmwnative.js @@ -6,7 +6,7 @@ // If KMW is already initialized, the KMW script has been loaded more than once. We wish to prevent resetting the // KMW system, so we use the fact that 'initialized' is only 1 / true after all scripts are loaded for the initial // load of KMW. -if(!window['tavultesoft']['keymanweb']['initialized']) { +if(!window['keyman']['initialized']) { /*****************************************/ /* */ /* On-Screen (Visual) Keyboard Code */ @@ -14,48 +14,50 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { /*****************************************/ (function() { // Declare KeymanWeb object - var keymanweb=window['tavultesoft']['keymanweb'],osk=keymanweb['osk'],util=keymanweb['util'],device=util.device; + var keymanweb=window['keyman'],osk=keymanweb['osk'],util=keymanweb['util'],device=util.device; var dbg=keymanweb.debug; // Force full initialization - keymanweb.isEmbedded = false; + keymanweb.isEmbedded = false; /** * Set default device options * @param {Object} opt device options object - */ + */ keymanweb.setDefaultDeviceOptions=function(opt) { - // Element attachment type - if(opt['attachType'] == '') opt['attachType'] = (device.touchable ? 'manual' : 'auto'); + // Element attachment type + if(opt['attachType'] == '') opt['attachType'] = (device.touchable ? 'manual' : 'auto'); } /** - * Customized wait display - * + * Customized wait display + * * @param {string|boolean} s displayed text (or false) - */ - util.wait = function(s) { + */ + util.wait = function(s) { // Keyboards loaded with page are initialized before the page is ready, // so cannot use the wait indicater (and don't need it, anyway) // Do not display if a blocking cloud server error has occurred (to prevent multiple errors) var bg=keymanweb.waiting; - if(typeof(bg) == 'undefined' || bg == null || keymanweb.warned) return; + if(typeof(bg) == 'undefined' || bg == null || keymanweb.warned) { + return; + } var nn=bg.firstChild.childNodes; - if(s) { + if(s) { bg.pending=true; - window.setTimeout(function() { - if(bg.pending) { - window.scrollTo(0,0); + window.setTimeout(function() { + if(bg.pending) { + window.scrollTo(0,0); nn[0].style.display='none'; - nn[1].className='kmw-wait-text'; nn[1].innerHTML=s; + nn[1].className='kmw-wait-text'; nn[1].innerHTML=s; nn[2].style.display='block'; bg.style.display='block'; } },1000); - } else { + } else { if(bg.pending) { - nn[1].innerHTML=''; + nn[1].innerHTML=''; bg.pending=false; bg.style.display='none'; } } @@ -64,7 +66,7 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { // Get default style sheet path keymanweb.getStyleSheetPath=function(ssName) { var ssPath = util['getOption']('resources')+'osk/'+ssName; - return ssPath; + return ssPath; } /** @@ -97,7 +99,11 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { */ keymanweb.KC_ = function(n, ln, Pelem) { var Ldv, tempContext = ''; - if(Pelem.body) var Ldoc=Pelem; else var Ldoc=Pelem.ownerDocument; // I1481 - use Ldoc to get the ownerDocument when no selection is found + if(Pelem.body) { + var Ldoc=Pelem; + } else { + var Ldoc=Pelem.ownerDocument; // I1481 - use Ldoc to get the ownerDocument when no selection is found + } if(device.touchable) { tempContext = keymanweb.getTextBeforeCaret(Pelem); diff --git a/web/source/kmwosk.js b/web/source/kmwosk.js index 37ab706287..c52c35f8e6 100644 --- a/web/source/kmwosk.js +++ b/web/source/kmwosk.js @@ -6,18 +6,17 @@ // If KMW is already initialized, the KMW script has been loaded more than once. We wish to prevent resetting the // KMW system, so we use the fact that 'initialized' is only 1 / true after all scripts are loaded for the initial // load of KMW. -if(!window['tavultesoft']['keymanweb']['initialized']) { +if(!window['keyman']['initialized']) { /*****************************************/ /* */ /* On-Screen (Visual) Keyboard Code */ /* */ /*****************************************/ - (function() - { + (function() { // Declare KeymanWeb and member objects - var keymanweb=window['tavultesoft']['keymanweb'], osk=keymanweb['osk'], - util=keymanweb['util'],device=util.device,dbg=keymanweb.debug; + var keymanweb=window['keyman'], osk=keymanweb['osk'], util=keymanweb['util'], device=util.device, dbg=keymanweb.debug; + var kbdInterface=keymanweb['interface']; // Define Keyman Developer modifier bit-flags (exposed for use by other modules) osk.modifierCodes = { @@ -965,7 +964,7 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { switch(keyName) { case 'K_BKSP': //Only desktop UI, not touch devices. TODO: add repeat while mouse down for desktop UI - keymanweb.KO(1,keymanweb._LastActiveElement,""); + kbdInterface.output(1,keymanweb._LastActiveElement,""); break; case 'K_TAB': var bBack=(osk.layerId == 'shift'); @@ -980,7 +979,7 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { case 'K_ENTER': // Insert new line in text area fields if(Lelem.nodeName == 'TEXTAREA' || (typeof Lelem.base != 'undefined' && Lelem.base.nodeName == 'TEXTAREA')) - keymanweb.KO(0, Lelem, '\n'); + kbdInterface.output(0, Lelem, '\n'); // Or move to next field from TEXT fields else { @@ -996,7 +995,7 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { } break; case 'K_SPACE': - keymanweb.KO(0, Lelem, ' '); + kbdInterface.output(0, Lelem, ' '); break; case 'K_CAPS': case 'K_NUMLOCK': @@ -1007,7 +1006,9 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { default: // The following is physical layout dependent, so should be avoided if possible. All keys should be mapped. var ch = osk.defaultKeyOutput(keyName,Lkc.Lcode,keyShiftState); - if(ch)keymanweb.KO(0, Lelem, ch); + if(ch) { + kbdInterface.output(0, Lelem, ch); + } } } @@ -2391,12 +2392,13 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { // Get nearest key if touching a hidden key or the end of a key row if((key && (key.className.indexOf('key-hidden') >= 0)) - || t.className.indexOf('kmw-key-row') >= 0) - { + || t.className.indexOf('kmw-key-row') >= 0) { key = osk.findNearestKey(e,t); } // Do not do anything if no key identified! - if(key == null) return; + if(key == null) { + return; + } // Get key name (K_...) from element ID var keyIdComponents = key.id.split('-'); @@ -2412,25 +2414,19 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { osk.keyPending = null; } // Also backspace, to allow delete to repeat while key held - else if(keyName == 'K_BKSP') - { - keymanweb.KO(1,keymanweb._LastActiveElement,""); + else if(keyName == 'K_BKSP') { + kbdInterface.output(1,keymanweb._LastActiveElement,""); osk.deleting = window.setTimeout(osk.repeatDelete,500); osk.keyPending = null; - } - else - { - if(osk.keyPending) - { + } else { + if(osk.keyPending) { osk.highlightKey(osk.keyPending,false); osk.clickKey(osk.keyPending); osk.clearPopup(); // Decrement the number of unreleased touch points to prevent // sending the keystroke again when the key is actually released osk.touchCount--; - } - else - { + } else { // If this key has subkey, start timer to display subkeys after delay, set up release osk.touchHold(key); //if(key.subKeys != null) osk.subkeyDelayTimer=window.setTimeout(function(){osk.showSubKeys(key);},osk.popupDelay); @@ -2724,11 +2720,9 @@ if(!window['tavultesoft']['keymanweb']['initialized']) { /** * Repeat backspace as long as the backspace key is held down **/ - osk.repeatDelete = function() - { - if(osk.deleting) - { - keymanweb.KO(1,keymanweb._LastActiveElement,""); + osk.repeatDelete = function() { + if(osk.deleting) { + kbdInterface.output(1,keymanweb._LastActiveElement,""); osk.deleting = window.setTimeout(osk.repeatDelete,100); } } diff --git a/web/source/kmwuibutton.js b/web/source/kmwuibutton.js index df70d331a4..0bf8a8bcd1 100644 --- a/web/source/kmwuibutton.js +++ b/web/source/kmwuibutton.js @@ -6,7 +6,7 @@ // If a UI module has been loaded, we can rely on the publically-published 'name' property // having been set as a way to short-out a UI reload. Its parent object always exists by // this point in the build process. -if(!window['tavultesoft']['keymanweb']['ui']['name']) { +if(!window['keyman']['ui']['name']) { /********************************/ /* */ @@ -25,7 +25,7 @@ if(!window['tavultesoft']['keymanweb']['ui']['name']) { try { // Declare KeymanWeb, OnScreen keyboard and Util objects - var keymanweb=window['tavultesoft']['keymanweb'],osk=keymanweb['osk'], + var keymanweb=window['keyman'],osk=keymanweb['osk'], util=keymanweb['util'],dbg=keymanweb['debug']; // Disable UI for touch devices diff --git a/web/source/kmwuifloat.js b/web/source/kmwuifloat.js index 0de3ad1bf1..d6d3f5e203 100644 --- a/web/source/kmwuifloat.js +++ b/web/source/kmwuifloat.js @@ -6,7 +6,7 @@ // If a UI module has been loaded, we can rely on the publically-published 'name' property // having been set as a way to short-out a UI reload. Its parent object always exists by // this point in the build process. -if(!window['tavultesoft']['keymanweb']['ui']['name']) { +if(!window['keyman']['ui']['name']) { /********************************/ /* */ /* Floating User Interface */ @@ -25,7 +25,7 @@ if(!window['tavultesoft']['keymanweb']['ui']['name']) { try { // Declare KeymanWeb, OnScreen keyboard and Util objects - var keymanweb=window['tavultesoft']['keymanweb']; + var keymanweb=window['keyman']; var util=keymanweb['util']; var osk=keymanweb['osk']; var dbg=keymanweb['debug']; diff --git a/web/source/kmwuitoggle.js b/web/source/kmwuitoggle.js index ca156fc3c5..bab841e989 100644 --- a/web/source/kmwuitoggle.js +++ b/web/source/kmwuitoggle.js @@ -6,7 +6,7 @@ // If a UI module has been loaded, we can rely on the publically-published 'name' property // having been set as a way to short-out a UI reload. Its parent object always exists by // this point in the build process. -if(!window['tavultesoft']['keymanweb']['ui']['name']) { +if(!window['keyman']['ui']['name']) { /********************************/ /* */ /* Toggle User Interface Code */ @@ -25,7 +25,7 @@ if(!window['tavultesoft']['keymanweb']['ui']['name']) { try { // Declare KeymanWeb, OnScreen Keyboard and Util objects - var keymanweb=window['tavultesoft']['keymanweb'],osk=keymanweb['osk'],util=keymanweb['util']; + var keymanweb=window['keyman'],osk=keymanweb['osk'],util=keymanweb['util']; var dbg=keymanweb['debug']; // Disable UI for touch devices diff --git a/web/source/kmwuitoolbar.js b/web/source/kmwuitoolbar.js index eb78c68e84..5965491f7a 100644 --- a/web/source/kmwuitoolbar.js +++ b/web/source/kmwuitoolbar.js @@ -6,7 +6,7 @@ // If a UI module has been loaded, we can rely on the publically-published 'name' property // having been set as a way to short-out a UI reload. Its parent object always exists by // this point in the build process. -if(!window['tavultesoft']['keymanweb']['ui']['name']) { +if(!window['keyman']['ui']['name']) { /********************************/ /* */ /* Toolbar User Interface */ @@ -25,7 +25,7 @@ if(!window['tavultesoft']['keymanweb']['ui']['name']) { try { // Declare KeymanWeb, OnScreen keyboard and Util objects - var keymanweb=window['tavultesoft']['keymanweb'],osk=keymanweb['osk'],util=keymanweb['util'],dbg=keymanweb['debug']; + var keymanweb=window['keyman'],osk=keymanweb['osk'],util=keymanweb['util'],dbg=keymanweb['debug']; // Disable UI for touch devices if(util['isTouchDevice']()) throw ''; diff --git a/web/testing/attachment-api/index.html b/web/testing/attachment-api/index.html index 6f6e3e9aaf..9aa9431dd7 100644 --- a/web/testing/attachment-api/index.html +++ b/web/testing/attachment-api/index.html @@ -59,7 +59,7 @@ var attachType = GetURLParameter("mode"); var attachText = attachType ? attachType : "default"; - var kmw=window.tavultesoft.keymanweb; + var kmw=window.keyman; kmw.init({ attachType: attachType ? attachType : '', resources:'resources' diff --git a/web/testing/attachment-api/utilities.js b/web/testing/attachment-api/utilities.js index 9688431185..dcae4c75c7 100644 --- a/web/testing/attachment-api/utilities.js +++ b/web/testing/attachment-api/utilities.js @@ -1,6 +1,6 @@ function loadKeyboards() { - var kmw=tavultesoft.keymanweb; + var kmw=keyman; // The first keyboard added will be the default keyboard for touch devices. // For faster loading, it may be best for the default keybaord to be diff --git a/web/testing/chirality/chirality.js b/web/testing/chirality/chirality.js index a51c733ce4..ac8bc720a8 100644 --- a/web/testing/chirality/chirality.js +++ b/web/testing/chirality/chirality.js @@ -42,6 +42,7 @@ function Keyboard_chirality() { }; this.g0 = function (t, e) { var k = KeymanWeb, r = 0, m = 0; + var osk = keyman.osk; // Handwritten time! var kls = this.KV.KLS; @@ -52,7 +53,7 @@ function Keyboard_chirality() { for(var i = 0; i < layers.length; i++) { // Obtain the modifier code to match for the selected layer. // The following uses a non-public property potentially subject to change in the future. - var modCode = k.osk.modifierCodes['VIRTUAL_KEY'] | k.osk.getModifierState(layers[i]); + var modCode = osk.modifierCodes['VIRTUAL_KEY'] | osk.getModifierState(layers[i]); var layer = layers[i]; for(var key=0; key < kls[layer].length; key++) { @@ -61,9 +62,9 @@ function Keyboard_chirality() { if(keySymbol == "K_*") { continue; } else if(kls[layer][key] != '') { - if (k.KKM(e, modCode, k.osk.keyCodes[keySymbol])) { + if (k.KKM(e, modCode, osk.keyCodes[keySymbol])) { r = m = 1; - if(k.KSM(e, k.osk.modifierCodes['CAPS'])) { + if(k.KSM(e, osk.modifierCodes['CAPS'])) { k.KO(0, t, kls[layer][key].toUpperCase()); } else { k.KO(0, t, kls[layer][key]); diff --git a/web/testing/chirality/index.html b/web/testing/chirality/index.html index 62042cde50..a7a1f6554d 100644 --- a/web/testing/chirality/index.html +++ b/web/testing/chirality/index.html @@ -44,7 +44,7 @@ diff --git a/web/testing/samplehdr.js b/web/testing/samplehdr.js index d9d0540f09..17bd5b81d0 100644 --- a/web/testing/samplehdr.js +++ b/web/testing/samplehdr.js @@ -42,7 +42,7 @@ function loadKeyboards() { - var kmw=tavultesoft.keymanweb; + var kmw=keyman; // The first keyboard added will be the default keyboard for touch devices. // For faster loading, it may be best for the default keybaord to be @@ -84,7 +84,7 @@ // Script to allow a user to add any keyboard to the keyboard menu function addKeyboard(n) { - var sKbd,kmw=tavultesoft.keymanweb; + var sKbd,kmw=keyman; switch(n) { case 1: diff --git a/web/testing/uncompiled - manual.html b/web/testing/uncompiled - manual.html index a281eb6f8f..7b67ce2d34 100644 --- a/web/testing/uncompiled - manual.html +++ b/web/testing/uncompiled - manual.html @@ -44,7 +44,7 @@ diff --git a/windows/src/developer/history.md b/windows/src/developer/history.md index 46425271d2..64a2399bfb 100644 --- a/windows/src/developer/history.md +++ b/windows/src/developer/history.md @@ -3,6 +3,7 @@ ## 10.0 alpha * Keyman Developer moved to open source (#121) * KeymanWeb is now continuously integrated with Developer, ensuring that each update uses the most current version possible (#122) + - Additional KeymanWeb compatibility fixes (#349) * Keyman Developer compiler now generates keyboards that distinguish left and right ctrl/alt (#313) * Keyman Developer visual editors now supports keyboards that distinguish left and right ctrl/alt for web/mobile targets (#342) * The `&version` store is now optional and the compiler will determine and report on the minimum version required if it is not present (#334) diff --git a/windows/src/developer/kmcmpdll/Compiler.cpp b/windows/src/developer/kmcmpdll/Compiler.cpp index c39808250a..7cc226c73e 100644 --- a/windows/src/developer/kmcmpdll/Compiler.cpp +++ b/windows/src/developer/kmcmpdll/Compiler.cpp @@ -1254,7 +1254,9 @@ DWORD ProcessSystemStore(PFILE_KEYBOARD fk, DWORD SystemID, PFILE_STORE sp) case TSS_VERSION: if((fk->dwFlags & KF_AUTOMATICVERSION) == 0) return CERR_VersionAlreadyIncluded; p = sp->dpString; - if(*p < '5') AddWarning(CWARN_OldVersion); + if (wcstof(p, NULL) < 5.0) { + AddWarning(CWARN_OldVersion); + } if(wcsncmp(p, L"3.0", 3) == 0) fk->version = VERSION_50; //0x0a0b000n= a.bn else if(wcsncmp(p, L"3.1", 3) == 0) fk->version = VERSION_50; //all versions < 5.0 @@ -1266,7 +1268,8 @@ DWORD ProcessSystemStore(PFILE_KEYBOARD fk, DWORD SystemID, PFILE_STORE sp) else if(wcsncmp(p, L"7.0", 3) == 0) fk->version = VERSION_70; else if(wcsncmp(p, L"8.0", 3) == 0) fk->version = VERSION_80; else if(wcsncmp(p, L"9.0", 3) == 0) fk->version = VERSION_90; - else return CERR_InvalidVersion; + else if (wcsncmp(p, L"10.0", 4) == 0) fk->version = VERSION_100; + else return CERR_InvalidVersion; if(fk->version < VERSION_60) FOldCharPosMatching = TRUE; @@ -2251,6 +2254,16 @@ DWORD GetXString(PFILE_KEYBOARD fk, PWSTR str, PWSTR token, PWSTR output, int ma if ((sFlag & (LCTRLFLAG | LALTFLAG)) && (sFlag & (RCTRLFLAG | RALTFLAG))) { AddWarning(CWARN_MixingLeftAndRightModifiers); } + + // If we use chiral modifiers, or we use state keys, and we target web in the keyboard, and we don't manually specify a keyboard version, bump the minimum + // version to 10.0. This makes an assumption that if we are using these features in a keyboard and it has no version specified, that we want to use the features + // in the web target platform, even if there are platform() rules excluding this possibility. In that (rare) situation, the keyboard developer should simply specify + // the &version to be 9.0 or whatever to avoid this behaviour. + if (sFlag & (LCTRLFLAG | LALTFLAG | RCTRLFLAG | RALTFLAG | CAPITALFLAG | NOTCAPITALFLAG | NUMLOCKFLAG | NOTNUMLOCKFLAG | SCROLLFLAG | NOTSCROLLFLAG) && + CompileTarget == CKF_KEYMANWEB && + fk->dwFlags & KF_AUTOMATICVERSION) { + VERIFY_KEYBOARD_VERSION(fk, VERSION_100, 0); + } //printf("sFlag: %x\n", sFlag); tstr[mx++] = UC_SENTINEL; diff --git a/windows/src/global/delphi/general/KeymanVersion.pas b/windows/src/global/delphi/general/KeymanVersion.pas index bba12e647e..7531ee0832 100644 --- a/windows/src/global/delphi/general/KeymanVersion.pas +++ b/windows/src/global/delphi/general/KeymanVersion.pas @@ -29,9 +29,7 @@ const SKeymanVersion = SKeymanVersion100; - // At present, we have no features in version 10 of Keyman that are not in - // version 9, so we can force version 9 for keyboards for back-compat - SKeymanKeyboardVersion = SKeymanVersion90; + SKeymanKeyboardVersion = SKeymanVersion100; SKeymanInstallerComponentCode = '{C289B903-7EE8-49C7-B186-BE98259EC540}'; implementation diff --git a/windows/src/global/delphi/general/kmxfile.pas b/windows/src/global/delphi/general/kmxfile.pas index e93b401d65..0791f32d72 100644 --- a/windows/src/global/delphi/general/kmxfile.pas +++ b/windows/src/global/delphi/general/kmxfile.pas @@ -83,6 +83,22 @@ type PKeyboardInfo = ^TKeyboardInfo; +const + VERSION_30 = $00000300; + VERSION_31 = $00000301; + VERSION_32 = $00000302; + VERSION_40 = $00000400; + VERSION_50 = $00000500; + VERSION_501 = $00000501; + VERSION_60 = $00000600; + VERSION_70 = $00000700; + VERSION_80 = $00000800; + VERSION_90 = $00000900; + VERSION_100 = $00000A00; + + VERSION_MIN = VERSION_50; + VERSION_MAX = VERSION_100; + const HK_ALT = $00010000; HK_CTRL = $00020000; diff --git a/windows/src/global/inc/Compiler.h b/windows/src/global/inc/Compiler.h index caf87411fc..cbdbe6934d 100644 --- a/windows/src/global/inc/Compiler.h +++ b/windows/src/global/inc/Compiler.h @@ -68,9 +68,10 @@ #define VERSION_70 0x00000700 #define VERSION_80 0x00000800 #define VERSION_90 0x00000900 +#define VERSION_100 0x00000A00 #define VERSION_MIN VERSION_50 -#define VERSION_MAX VERSION_90 +#define VERSION_MAX VERSION_100 /* Special flag for WM_CHAR/WM_KEY???/WM_SYSKEY???: says that key has been diff --git a/windows/src/test/version-10-keyboards/.gitignore b/windows/src/test/version-10-keyboards/.gitignore new file mode 100644 index 0000000000..42f34e54ea --- /dev/null +++ b/windows/src/test/version-10-keyboards/.gitignore @@ -0,0 +1,3 @@ +*.kmx +*.js +*.json diff --git a/windows/src/test/version-10-keyboards/version10chiral.kmn b/windows/src/test/version-10-keyboards/version10chiral.kmn new file mode 100644 index 0000000000..56580a7a3f --- /dev/null +++ b/windows/src/test/version-10-keyboards/version10chiral.kmn @@ -0,0 +1,10 @@ +store(&VERSION) '10.0' +store(&NAME) 'Version 10 Chiral' +store(&TARGETS) 'any' + + +begin Unicode > use(main) + +group(main) using keys + ++ [LALT K_A] > 'LALT K_A' diff --git a/windows/src/test/version-10-keyboards/version10keyboards.kpj b/windows/src/test/version-10-keyboards/version10keyboards.kpj new file mode 100644 index 0000000000..68eb3a397b --- /dev/null +++ b/windows/src/test/version-10-keyboards/version10keyboards.kpj @@ -0,0 +1,50 @@ + + + + + False + True + + + + id_9572b9cbe3b74bafc127d47ca531dad4 + version10chiral.kmn + version10chiral.kmn + 1.0 + .kmn +
+ Version 10 Chiral +
+
+ + id_1743b3bf01d8aeb93df498c08ca4db46 + version10nonchiral.kmn + version10nonchiral.kmn + 1.0 + .kmn +
+ Version 10 Non-Chiral +
+
+ + id_9e738c3aaaf2c7c392b5c242c5682eeb + version9chiral.kmn + version9chiral.kmn + 1.0 + .kmn +
+ Version 9 Chiral +
+
+ + id_491347ca21b6f633239efa7d7a0a1f8b + version9nonchiral.kmn + version9nonchiral.kmn + 1.0 + .kmn +
+ Version 9 non-chiral +
+
+
+
diff --git a/windows/src/test/version-10-keyboards/version10nonchiral.kmn b/windows/src/test/version-10-keyboards/version10nonchiral.kmn new file mode 100644 index 0000000000..2ba86cdfef --- /dev/null +++ b/windows/src/test/version-10-keyboards/version10nonchiral.kmn @@ -0,0 +1,9 @@ +store(&VERSION) '10.0' +store(&NAME) 'Version 10 Non-Chiral' +store(&TARGETS) 'any' +begin Unicode > use(main) + + +group(main) using keys + ++ [ALT K_A] > 'ALT K_A' diff --git a/windows/src/test/version-10-keyboards/version9chiral.kmn b/windows/src/test/version-10-keyboards/version9chiral.kmn new file mode 100644 index 0000000000..2ce68b49d3 --- /dev/null +++ b/windows/src/test/version-10-keyboards/version9chiral.kmn @@ -0,0 +1,10 @@ +c Should build with warnings or errors +store(&VERSION) '9.0' +store(&NAME) 'Version 9 Chiral' +store(&TARGETS) 'any' +begin Unicode > use(main) + + +group(main) using keys + ++ [LALT K_A] > 'LALT K_A' diff --git a/windows/src/test/version-10-keyboards/version9nonchiral.kmn b/windows/src/test/version-10-keyboards/version9nonchiral.kmn new file mode 100644 index 0000000000..23d54b61dc --- /dev/null +++ b/windows/src/test/version-10-keyboards/version9nonchiral.kmn @@ -0,0 +1,9 @@ +store(&VERSION) '9.0' +store(&NAME) 'Version 9 non-chiral' +store(&TARGETS) 'any' +begin Unicode > use(main) + + +group(main) using keys + ++ [ALT K_A] > 'ALT K_A'