2.3.1 // Shift key. Merge PR#119 from upd/2.3.1

This commit is contained in:
ShikiSuen 2022-09-01 23:36:40 +08:00 committed by GitHub
commit cd1cffd22e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
92 changed files with 634 additions and 2656 deletions

View File

@ -17,7 +17,6 @@ $ Contributors and volunteers of the upstream repo, having no responsibility in
- Zonble Yang: - Zonble Yang:
- McBopomofo for macOS 2.x architect, especially state-based IME behavior management. - McBopomofo for macOS 2.x architect, especially state-based IME behavior management.
- Voltaire candidate window MK2 (massively modified as MK3 in vChewing by Shiki Suen). - Voltaire candidate window MK2 (massively modified as MK3 in vChewing by Shiki Suen).
- InputSignal (previously "KeyHandlerInput").
- Notifier window and Tooltip UI. - Notifier window and Tooltip UI.
- NSStringUtils and FSEventStreamHelper. - NSStringUtils and FSEventStreamHelper.
- App-style installer (only preserved for developer purposes). - App-style installer (only preserved for developer purposes).

View File

@ -1,6 +1,6 @@
#!/usr/bin/env swift #!/usr/bin/env swift
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that: // ... with NTL restriction stating that:

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
@ -60,6 +60,7 @@ class AppDelegate: NSWindowController, NSApplicationDelegate {
guard guard
let installingVersion = Bundle.main.infoDictionary?[kCFBundleVersionKey as String] let installingVersion = Bundle.main.infoDictionary?[kCFBundleVersionKey as String]
as? String, as? String,
let window = window,
let versionString = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String let versionString = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
else { else {
return return
@ -71,7 +72,7 @@ class AppDelegate: NSWindowController, NSApplicationDelegate {
cancelButton.nextKeyView = installButton cancelButton.nextKeyView = installButton
installButton.nextKeyView = cancelButton installButton.nextKeyView = cancelButton
if let cell = installButton.cell as? NSButtonCell { if let cell = installButton.cell as? NSButtonCell {
window?.defaultButtonCell = cell window.defaultButtonCell = cell
} }
if let copyrightLabel = Bundle.main.localizedInfoDictionary?["NSHumanReadableCopyright"] if let copyrightLabel = Bundle.main.localizedInfoDictionary?["NSHumanReadableCopyright"]
@ -82,17 +83,12 @@ class AppDelegate: NSWindowController, NSApplicationDelegate {
if let eulaContent = Bundle.main.localizedInfoDictionary?["CFEULAContent"] as? String { if let eulaContent = Bundle.main.localizedInfoDictionary?["CFEULAContent"] as? String {
appEULAContent.string = eulaContent appEULAContent.string = eulaContent
} }
appVersionLabel.stringValue = String( appVersionLabel.stringValue = "\(versionString) Build \(installingVersion)"
format: "%@ Build %@", versionString, installingVersion
)
window?.title = String( window.title = "\(window.title) (v\(versionString), Build \(installingVersion))"
format: NSLocalizedString("%@ (for version %@, r%@)", comment: ""), window?.title ?? "", window.standardWindowButton(.closeButton)?.isHidden = true
versionString, installingVersion window.standardWindowButton(.miniaturizeButton)?.isHidden = true
) window.standardWindowButton(.zoomButton)?.isHidden = true
window?.standardWindowButton(.closeButton)?.isHidden = true
window?.standardWindowButton(.miniaturizeButton)?.isHidden = true
window?.standardWindowButton(.zoomButton)?.isHidden = true
if FileManager.default.fileExists( if FileManager.default.fileExists(
atPath: kTargetPartialPath) atPath: kTargetPartialPath)
@ -114,8 +110,8 @@ class AppDelegate: NSWindowController, NSApplicationDelegate {
installButton.title = NSLocalizedString("Upgrade", comment: "") installButton.title = NSLocalizedString("Upgrade", comment: "")
} }
window?.center() window.center()
window?.orderFront(self) window.orderFront(self)
NSApp.activate(ignoringOtherApps: true) NSApp.activate(ignoringOtherApps: true)
} }
@ -126,14 +122,15 @@ class AppDelegate: NSWindowController, NSApplicationDelegate {
} }
@objc func timerTick(_ timer: Timer) { @objc func timerTick(_ timer: Timer) {
guard let window = window else { return }
let elapsed = Date().timeIntervalSince(translocationRemovalStartTime ?? Date()) let elapsed = Date().timeIntervalSince(translocationRemovalStartTime ?? Date())
if elapsed >= kTranslocationRemovalDeadline { if elapsed >= kTranslocationRemovalDeadline {
timer.invalidate() timer.invalidate()
window?.endSheet(progressSheet, returnCode: .cancel) window.endSheet(progressSheet, returnCode: .cancel)
} else if isAppBundleTranslocated(atPath: kTargetPartialPath) == false { } else if isAppBundleTranslocated(atPath: kTargetPartialPath) == false {
progressIndicator.doubleValue = 1.0 progressIndicator.doubleValue = 1.0
timer.invalidate() timer.invalidate()
window?.endSheet(progressSheet, returnCode: .continue) window.endSheet(progressSheet, returnCode: .continue)
} }
} }
@ -145,15 +142,17 @@ class AppDelegate: NSWindowController, NSApplicationDelegate {
// return // return
// } // }
guard let window = window else { return }
let shouldWaitForTranslocationRemoval = let shouldWaitForTranslocationRemoval =
isAppBundleTranslocated(atPath: kTargetPartialPath) isAppBundleTranslocated(atPath: kTargetPartialPath)
&& (window?.responds(to: #selector(NSWindow.beginSheet(_:completionHandler:))) ?? false) && window.responds(to: #selector(NSWindow.beginSheet(_:completionHandler:)))
// //
do { do {
let sourceDir = kDestinationPartial let sourceDir = kDestinationPartial
let fileManager = FileManager.default let fileManager = FileManager.default
let fileURLString = String(format: "%@/%@", sourceDir, kTargetBundle) let fileURLString = sourceDir + "/" + kTargetBundle
let fileURL = URL(fileURLWithPath: fileURLString) let fileURL = URL(fileURLWithPath: fileURLString)
// //
@ -176,7 +175,7 @@ class AppDelegate: NSWindowController, NSApplicationDelegate {
if shouldWaitForTranslocationRemoval { if shouldWaitForTranslocationRemoval {
progressIndicator.startAnimation(self) progressIndicator.startAnimation(self)
window?.beginSheet(progressSheet) { returnCode in window.beginSheet(progressSheet) { returnCode in
DispatchQueue.main.async { DispatchQueue.main.async {
if returnCode == .continue { if returnCode == .continue {
self.installInputMethod( self.installInputMethod(

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================

View File

@ -17,5 +17,3 @@
"Warning" = "Warning"; "Warning" = "Warning";
"Input method may not be fully enabled. Please enable it through System Preferences > Keyboard > Input Sources." = "Input method may not be fully enabled. Please enable it through System Preferences > Keyboard > Input Sources."; "Input method may not be fully enabled. Please enable it through System Preferences > Keyboard > Input Sources." = "Input method may not be fully enabled. Please enable it through System Preferences > Keyboard > Input Sources.";
"Continue" = "Continue"; "Continue" = "Continue";
"%@ (for version %@, r%@)" = "%@ (for version %@, r%@)";

View File

@ -17,5 +17,3 @@
"Warning" = "お知らせ"; "Warning" = "お知らせ";
"Input method may not be fully enabled. Please enable it through System Preferences > Keyboard > Input Sources." = "入力アプリの自動起動はうまく出来なかったかもしれません。ご自分で「システム環境設定→キーボード→入力ソース」で起動してください。"; "Input method may not be fully enabled. Please enable it through System Preferences > Keyboard > Input Sources." = "入力アプリの自動起動はうまく出来なかったかもしれません。ご自分で「システム環境設定→キーボード→入力ソース」で起動してください。";
"Continue" = "続行"; "Continue" = "続行";
"%@ (for version %@, r%@)" = "%@ (for version %@, r%@)";

View File

@ -17,5 +17,3 @@
"Warning" = "安装不完整"; "Warning" = "安装不完整";
"Input method may not be fully enabled. Please enable it through System Preferences > Keyboard > Input Sources." = "输入法已经安装好,但可能没有完全启用。请从「系统偏好设定」 > 「键盘」 > 「输入方式」分页加入输入法。"; "Input method may not be fully enabled. Please enable it through System Preferences > Keyboard > Input Sources." = "输入法已经安装好,但可能没有完全启用。请从「系统偏好设定」 > 「键盘」 > 「输入方式」分页加入输入法。";
"Continue" = "继续"; "Continue" = "继续";
"%@ (for version %@, r%@)" = "%@ (for version %@, r%@)";

View File

@ -17,5 +17,3 @@
"Warning" = "安裝不完整"; "Warning" = "安裝不完整";
"Input method may not be fully enabled. Please enable it through System Preferences > Keyboard > Input Sources." = "輸入法已經安裝好,但可能沒有完全啟用。請從「系統偏好設定」 > 「鍵盤」 > 「輸入方式」分頁加入輸入法。"; "Input method may not be fully enabled. Please enable it through System Preferences > Keyboard > Input Sources." = "輸入法已經安裝好,但可能沒有完全啟用。請從「系統偏好設定」 > 「鍵盤」 > 「輸入方式」分頁加入輸入法。";
"Continue" = "繼續"; "Continue" = "繼續";
"%@ (for version %@, r%@)" = "%@ (for version %@, r%@)";

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that: // ... with NTL restriction stating that:

View File

@ -1,4 +1,4 @@
// Copyright (c) 2019 and onwards Robert Muckle-Jones (Apache 2.0 License). // (c) 2019 and onwards Robert Muckle-Jones (Apache 2.0 License).
import Foundation import Foundation

View File

@ -1,4 +1,4 @@
// Copyright (c) 2018 and onwards Sindre Sorhus (MIT License). // (c) 2018 and onwards Sindre Sorhus (MIT License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)

View File

@ -1,4 +1,4 @@
// Copyright (c) 2018 and onwards Sindre Sorhus (MIT License). // (c) 2018 and onwards Sindre Sorhus (MIT License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)

View File

@ -1,4 +1,4 @@
// Copyright (c) 2018 and onwards Sindre Sorhus (MIT License). // (c) 2018 and onwards Sindre Sorhus (MIT License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)

View File

@ -1,4 +1,4 @@
// Copyright (c) 2018 and onwards Sindre Sorhus (MIT License). // (c) 2018 and onwards Sindre Sorhus (MIT License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)

View File

@ -1,4 +1,4 @@
// Copyright (c) 2018 and onwards Sindre Sorhus (MIT License). // (c) 2018 and onwards Sindre Sorhus (MIT License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)

View File

@ -1,4 +1,4 @@
// Copyright (c) 2018 and onwards Sindre Sorhus (MIT License). // (c) 2018 and onwards Sindre Sorhus (MIT License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)

View File

@ -1,4 +1,4 @@
// Copyright (c) 2018 and onwards Sindre Sorhus (MIT License). // (c) 2018 and onwards Sindre Sorhus (MIT License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)

View File

@ -1,4 +1,4 @@
// Copyright (c) 2018 and onwards Sindre Sorhus (MIT License). // (c) 2018 and onwards Sindre Sorhus (MIT License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)

View File

@ -1,4 +1,4 @@
// Copyright (c) 2018 and onwards Sindre Sorhus (MIT License). // (c) 2018 and onwards Sindre Sorhus (MIT License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)

View File

@ -1,4 +1,4 @@
// Copyright (c) 2018 and onwards Sindre Sorhus (MIT License). // (c) 2018 and onwards Sindre Sorhus (MIT License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)

View File

@ -1,4 +1,4 @@
// Copyright (c) 2018 and onwards Sindre Sorhus (MIT License). // (c) 2018 and onwards Sindre Sorhus (MIT License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)

View File

@ -1,4 +1,4 @@
// Copyright (c) 2018 and onwards Sindre Sorhus (MIT License). // (c) 2018 and onwards Sindre Sorhus (MIT License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)

View File

@ -1,4 +1,4 @@
// Copyright (c) 2018 and onwards Sindre Sorhus (MIT License). // (c) 2018 and onwards Sindre Sorhus (MIT License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)

@ -1 +1 @@
Subproject commit 6bf8cdb5bfaf9a884b4317b2fa330e37fd9e1cf6 Subproject commit 4d6ed238c037c4d4f5464f6914198a503fd1f21a

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that: // ... with NTL restriction stating that:
@ -26,112 +26,6 @@ enum AppleKeyboardConverter {
AppleKeyboardConverter.arrDynamicBasicKeyLayout.contains(mgrPrefs.basicKeyboardLayout) AppleKeyboardConverter.arrDynamicBasicKeyLayout.contains(mgrPrefs.basicKeyboardLayout)
} }
// Apple
static func cnvApple2ABC(_ charCode: UniChar) -> UniChar {
var charCode = charCode
//
if isDynamicBasicKeyboardLayoutEnabled {
// Apple
switch mgrPrefs.basicKeyboardLayout {
case "com.apple.keylayout.ZhuyinBopomofo":
switch charCode {
case 97...122: charCode -= 32
default: break
}
case "com.apple.keylayout.ZhuyinEten":
switch charCode {
case 65345...65370: charCode -= 65280
default: break
}
default: break
}
//
switch charCode {
case 12573: charCode = UniChar(44)
case 12582: charCode = UniChar(45)
case 12577: charCode = UniChar(46)
case 12581: charCode = UniChar(47)
case 12578: charCode = UniChar(48)
case 12549: charCode = UniChar(49)
case 12553: charCode = UniChar(50)
case 711: charCode = UniChar(51)
case 715: charCode = UniChar(52)
case 12563: charCode = UniChar(53)
case 714: charCode = UniChar(54)
case 729: charCode = UniChar(55)
case 12570: charCode = UniChar(56)
case 12574: charCode = UniChar(57)
case 12580: charCode = UniChar(59)
case 12551: charCode = UniChar(97)
case 12566: charCode = UniChar(98)
case 12559: charCode = UniChar(99)
case 12558: charCode = UniChar(100)
case 12557: charCode = UniChar(101)
case 12561: charCode = UniChar(102)
case 12565: charCode = UniChar(103)
case 12568: charCode = UniChar(104)
case 12571: charCode = UniChar(105)
case 12584: charCode = UniChar(106)
case 12572: charCode = UniChar(107)
case 12576: charCode = UniChar(108)
case 12585: charCode = UniChar(109)
case 12569: charCode = UniChar(110)
case 12575: charCode = UniChar(111)
case 12579: charCode = UniChar(112)
case 12550: charCode = UniChar(113)
case 12560: charCode = UniChar(114)
case 12555: charCode = UniChar(115)
case 12564: charCode = UniChar(116)
case 12583: charCode = UniChar(117)
case 12562: charCode = UniChar(118)
case 12554: charCode = UniChar(119)
case 12556: charCode = UniChar(120)
case 12567: charCode = UniChar(121)
case 12552: charCode = UniChar(122)
default: break
}
//
switch charCode {
case 12289: charCode = UniChar(92)
case 12300: charCode = UniChar(91)
case 12301: charCode = UniChar(93)
case 12302: charCode = UniChar(123)
case 12303: charCode = UniChar(125)
case 65292: charCode = UniChar(60)
case 12290: charCode = UniChar(62)
default: break
}
// SHIFT
switch charCode {
case 65281: charCode = UniChar(33)
case 65312: charCode = UniChar(64)
case 65283: charCode = UniChar(35)
case 65284: charCode = UniChar(36)
case 65285: charCode = UniChar(37)
case 65087: charCode = UniChar(94)
case 65286: charCode = UniChar(38)
case 65290: charCode = UniChar(42)
case 65288: charCode = UniChar(40)
case 65289: charCode = UniChar(41)
default: break
}
// Alt
if charCode == 8212 { charCode = UniChar(45) }
// Apple
if mgrPrefs.basicKeyboardLayout == "com.apple.keylayout.ZhuyinEten" {
switch charCode {
case 65343: charCode = UniChar(95)
case 65306: charCode = UniChar(58)
case 65311: charCode = UniChar(63)
case 65291: charCode = UniChar(43)
case 65372: charCode = UniChar(124)
default: break
}
}
}
return charCode
}
static func cnvStringApple2ABC(_ strProcessed: String) -> String { static func cnvStringApple2ABC(_ strProcessed: String) -> String {
var strProcessed = strProcessed var strProcessed = strProcessed
if isDynamicBasicKeyboardLayoutEnabled { if isDynamicBasicKeyboardLayoutEnabled {

View File

@ -1,281 +0,0 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that:
// No trademark license is granted to use the trade names, trademarks, service
// marks, or product names of Contributor, except as required to fulfill notice
// requirements defined in MIT License.
import Cocoa
// Use KeyCodes as much as possible since its recognition won't be affected by macOS Base Keyboard Layouts.
// KeyCodes: https://eastmanreference.com/complete-list-of-applescript-key-codes
// Also: HIToolbox.framework/Versions/A/Headers/Events.h
enum KeyCode: UInt16 {
case kNone = 0
case kCarriageReturn = 36 // Renamed from "kReturn" to avoid nomenclatural confusions.
case kTab = 48
case kSpace = 49
case kSymbolMenuPhysicalKeyIntl = 50 // vChewing Specific (Non-JIS)
case kBackSpace = 51 // Renamed from "kDelete" to avoid nomenclatural confusions.
case kEscape = 53
case kCommand = 55
case kShift = 56
case kCapsLock = 57
case kOption = 58
case kControl = 59
case kRightShift = 60
case kRightOption = 61
case kRightControl = 62
case kFunction = 63
case kF17 = 64
case kVolumeUp = 72
case kVolumeDown = 73
case kMute = 74
case kLineFeed = 76 // Another keyCode to identify the Enter Key, typable by Fn+Enter.
case kF18 = 79
case kF19 = 80
case kF20 = 90
case kSymbolMenuPhysicalKeyJIS = 94 // vChewing Specific (JIS)
case kF5 = 96
case kF6 = 97
case kF7 = 98
case kF3 = 99
case kF8 = 100
case kF9 = 101
case kF11 = 103
case kF13 = 105 // PrtSc
case kF16 = 106
case kF14 = 107
case kF10 = 109
case kF12 = 111
case kF15 = 113
case kHelp = 114 // Insert
case kHome = 115
case kPageUp = 116
case kWindowsDelete = 117 // Renamed from "kForwardDelete" to avoid nomenclatural confusions.
case kF4 = 118
case kEnd = 119
case kF2 = 120
case kPageDown = 121
case kF1 = 122
case kLeftArrow = 123
case kRightArrow = 124
case kDownArrow = 125
case kUpArrow = 126
}
enum KeyCodeBlackListed: UInt16 {
case kF17 = 64
case kVolumeUp = 72
case kVolumeDown = 73
case kMute = 74
case kF18 = 79
case kF19 = 80
case kF20 = 90
case kF5 = 96
case kF6 = 97
case kF7 = 98
case kF3 = 99
case kF8 = 100
case kF9 = 101
case kF11 = 103
case kF13 = 105 // PrtSc
case kF16 = 106
case kF14 = 107
case kF10 = 109
case kF12 = 111
case kF15 = 113
case kHelp = 114 // Insert
case kF4 = 118
case kF2 = 120
case kF1 = 122
}
/// KeyCode
///
/// 95 Key Code JIS
let arrNumpadKeyCodes: [UInt16] = [65, 67, 69, 71, 75, 78, 81, 82, 83, 84, 85, 86, 87, 88, 89, 91, 92, 95]
/// KeyCode
let arrMainAreaNumKey: [UInt16] = [18, 19, 20, 21, 22, 23, 25, 26, 28, 29]
// CharCodes: https://theasciicode.com.ar/ascii-control-characters/horizontal-tab-ascii-code-9.html
enum CharCode: UInt16 {
case yajuusenpaiA = 114
case yajuusenpaiB = 514
case yajuusenpaiC = 1919
case yajuusenpaiD = 810
// CharCode is not reliable at all. KeyCode is the most appropriate choice due to its accuracy.
// KeyCode doesn't give a phuque about the character sent through macOS keyboard layouts ...
// ... but only focuses on which physical key is pressed.
}
struct InputSignal: CustomStringConvertible {
private(set) var isTypingVertical: Bool
private(set) var inputText: String
private(set) var inputTextIgnoringModifiers: String?
private(set) var charCode: UInt16
private(set) var keyCode: UInt16
private var isFlagChanged: Bool
private var flags: NSEvent.ModifierFlags
private var cursorForwardKey: KeyCode = .kNone // 12 o'clock
private var cursorBackwardKey: KeyCode = .kNone // 6 o'clock
private var cursorKeyClockRight: KeyCode = .kNone // 3 o'clock
private var cursorKeyClockLeft: KeyCode = .kNone // 9 o'clock
private(set) var emacsKey: EmacsKey
public var isASCIIModeInput: Bool = false
public init(
inputText: String = "", keyCode: UInt16, charCode: UInt16, flags: NSEvent.ModifierFlags,
isVerticalTyping: Bool = false, inputTextIgnoringModifiers: String? = nil
) {
self.inputText = AppleKeyboardConverter.cnvStringApple2ABC(inputText)
self.inputTextIgnoringModifiers = AppleKeyboardConverter.cnvStringApple2ABC(
inputTextIgnoringModifiers ?? inputText)
self.flags = flags
isFlagChanged = false
isTypingVertical = isVerticalTyping
self.keyCode = keyCode
self.charCode = AppleKeyboardConverter.cnvApple2ABC(charCode)
emacsKey = EmacsKeyHelper.detect(
charCode: AppleKeyboardConverter.cnvApple2ABC(charCode), flags: flags
)
// Define Arrow Keys in the same way above.
defineArrowKeys()
}
public init(event: NSEvent, isVerticalTyping: Bool = false) {
inputText = AppleKeyboardConverter.cnvStringApple2ABC(event.characters ?? "")
inputTextIgnoringModifiers = AppleKeyboardConverter.cnvStringApple2ABC(
event.charactersIgnoringModifiers ?? inputText)
keyCode = event.keyCode
flags = event.modifierFlags
isFlagChanged = (event.type == .flagsChanged)
isTypingVertical = isVerticalTyping
let charCode: UInt16 = {
// count > 0!isEmpty滿
guard let inputText = event.characters, !inputText.isEmpty else {
return 0
}
let first = inputText[inputText.startIndex].utf16.first!
return first
}()
self.charCode = AppleKeyboardConverter.cnvApple2ABC(charCode)
emacsKey = EmacsKeyHelper.detect(
charCode: AppleKeyboardConverter.cnvApple2ABC(charCode), flags: flags
)
// Define Arrow Keys in the same way above.
defineArrowKeys()
}
mutating func defineArrowKeys() {
cursorForwardKey = isTypingVertical ? .kDownArrow : .kRightArrow
cursorBackwardKey = isTypingVertical ? .kUpArrow : .kLeftArrow
cursorKeyClockLeft = isTypingVertical ? .kRightArrow : .kUpArrow
cursorKeyClockRight = isTypingVertical ? .kLeftArrow : .kDownArrow
}
var description: String {
var result = "<[InputSignal] "
result += "inputText:\(String(describing: inputText)), "
result += "inputTextIgnoringModifiers:\(String(describing: inputTextIgnoringModifiers)), "
result += "charCode:\(charCode), "
result += "keyCode:\(keyCode), "
result += "flags:\(flags), "
result += "cursorForwardKey:\(cursorForwardKey), "
result += "cursorBackwardKey:\(cursorBackwardKey), "
result += "cursorKeyClockRight:\(cursorKeyClockRight), "
result += "cursorKeyClockLeft:\(cursorKeyClockLeft), "
result += "emacsKey:\(emacsKey), "
result += "isTypingVertical:\(isTypingVertical)"
result += ">"
return result
}
// ANSI charCode Swift KeyHandler
var isInvalid: Bool { (0x20...0xFF).contains(charCode) ? false : !(isReservedKey && !isKeyCodeBlacklisted) }
var isKeyCodeBlacklisted: Bool {
guard let code = KeyCodeBlackListed(rawValue: keyCode) else { return false }
return code.rawValue != KeyCode.kNone.rawValue
}
var isReservedKey: Bool {
guard let code = KeyCode(rawValue: keyCode) else { return false }
return code.rawValue != KeyCode.kNone.rawValue
}
// Alt+Shift+ macOS
// KeyCode
let mapMainAreaNumKey: [UInt16: String] = [
18: "1", 19: "2", 20: "3", 21: "4", 23: "5", 22: "6", 26: "7", 28: "8", 25: "9", 29: "0",
]
var isCandidateKey: Bool {
mgrPrefs.candidateKeys.contains(inputText)
|| mgrPrefs.candidateKeys.contains(inputTextIgnoringModifiers ?? "114514")
}
/// flags KeyCode
var isNumericPadKey: Bool { arrNumpadKeyCodes.contains(keyCode) }
var isMainAreaNumKey: Bool { arrMainAreaNumKey.contains(keyCode) }
var isShiftHold: Bool { flags.contains([.shift]) }
var isCommandHold: Bool { flags.contains([.command]) }
var isControlHold: Bool { flags.contains([.control]) }
var isControlHotKey: Bool { flags.contains([.control]) && inputText.first?.isLetter ?? false }
var isOptionHold: Bool { flags.contains([.option]) }
var isOptionHotKey: Bool { flags.contains([.option]) && inputText.first?.isLetter ?? false }
var isCapsLockOn: Bool { flags.contains([.capsLock]) }
var isFunctionKeyHold: Bool { flags.contains([.function]) }
var isNonLaptopFunctionKey: Bool { flags.contains([.numericPad]) && !isNumericPadKey }
var isEnter: Bool { [KeyCode.kCarriageReturn, KeyCode.kLineFeed].contains(KeyCode(rawValue: keyCode)) }
var isTab: Bool { KeyCode(rawValue: keyCode) == KeyCode.kTab }
var isUp: Bool { KeyCode(rawValue: keyCode) == KeyCode.kUpArrow }
var isDown: Bool { KeyCode(rawValue: keyCode) == KeyCode.kDownArrow }
var isLeft: Bool { KeyCode(rawValue: keyCode) == KeyCode.kLeftArrow }
var isRight: Bool { KeyCode(rawValue: keyCode) == KeyCode.kRightArrow }
var isPageUp: Bool { KeyCode(rawValue: keyCode) == KeyCode.kPageUp }
var isPageDown: Bool { KeyCode(rawValue: keyCode) == KeyCode.kPageDown }
var isSpace: Bool { KeyCode(rawValue: keyCode) == KeyCode.kSpace }
var isBackSpace: Bool { KeyCode(rawValue: keyCode) == KeyCode.kBackSpace }
var isEsc: Bool { KeyCode(rawValue: keyCode) == KeyCode.kEscape }
var isHome: Bool { KeyCode(rawValue: keyCode) == KeyCode.kHome }
var isEnd: Bool { KeyCode(rawValue: keyCode) == KeyCode.kEnd }
var isDelete: Bool { KeyCode(rawValue: keyCode) == KeyCode.kWindowsDelete }
var isCursorBackward: Bool { KeyCode(rawValue: keyCode) == cursorBackwardKey }
var isCursorForward: Bool { KeyCode(rawValue: keyCode) == cursorForwardKey }
var isCursorClockRight: Bool { KeyCode(rawValue: keyCode) == cursorKeyClockRight }
var isCursorClockLeft: Bool { KeyCode(rawValue: keyCode) == cursorKeyClockLeft }
// flags == .shift Shift
var isUpperCaseASCIILetterKey: Bool { (65...90).contains(charCode) && flags == .shift }
// KeyCode macOS Apple
// ![input isShiftHold] 使 Shift
var isSymbolMenuPhysicalKey: Bool {
[KeyCode.kSymbolMenuPhysicalKeyIntl, KeyCode.kSymbolMenuPhysicalKeyJIS].contains(KeyCode(rawValue: keyCode))
}
}
enum EmacsKey: UInt16 {
case none = 0
case forward = 6 // F
case backward = 2 // B
case home = 1 // A
case end = 5 // E
case delete = 4 // D
case nextPage = 22 // V
}
enum EmacsKeyHelper {
static func detect(charCode: UniChar, flags: NSEvent.ModifierFlags) -> EmacsKey {
let charCode = AppleKeyboardConverter.cnvApple2ABC(charCode)
if flags.contains(.control) {
return EmacsKey(rawValue: charCode) ?? .none
}
return .none
}
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// Refactored from the ObjCpp-version of this class by: // Refactored from the ObjCpp-version of this class by:
// (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// ==================== // ====================
@ -392,10 +392,10 @@ public class KeyHandler {
/// 調 /// 調
/// - Parameter input: /// - Parameter input:
/// - Returns: 調 /// - Returns: 調
func isIntonationKey(_ input: InputSignal) -> Bool { func isIntonationKey(_ input: InputSignalProtocol) -> Bool {
var theComposer = composer // var theComposer = composer //
theComposer.clear() // theComposer.clear() //
theComposer.receiveKey(fromCharCode: input.charCode) theComposer.receiveKey(fromString: input.text)
return theComposer.hasToneMarker(withNothingElse: true) return theComposer.hasToneMarker(withNothingElse: true)
} }
@ -417,7 +417,7 @@ public class KeyHandler {
/// ///
/// - Parameter input: /// - Parameter input:
/// - Returns: /// - Returns:
func generatePunctuationNamePrefix(withKeyCondition input: InputSignal) -> String { func generatePunctuationNamePrefix(withKeyCondition input: InputSignalProtocol) -> String {
if mgrPrefs.halfWidthPunctuationEnabled { if mgrPrefs.halfWidthPunctuationEnabled {
return "_half_punctuation_" return "_half_punctuation_"
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// Refactored from the ObjCpp-version of this class by: // Refactored from the ObjCpp-version of this class by:
// (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// ==================== // ====================
@ -24,12 +24,10 @@ extension KeyHandler {
/// - Returns: IMK /// - Returns: IMK
func handleCandidate( func handleCandidate(
state: InputStateProtocol, state: InputStateProtocol,
input: InputSignal, input: InputSignalProtocol,
stateCallback: @escaping (InputStateProtocol) -> Void, stateCallback: @escaping (InputStateProtocol) -> Void,
errorCallback: @escaping () -> Void errorCallback: @escaping () -> Void
) -> Bool { ) -> Bool {
let inputText = input.inputText
let charCode: UniChar = input.charCode
guard var ctlCandidateCurrent = delegate?.ctlCandidate() else { guard var ctlCandidateCurrent = delegate?.ctlCandidate() else {
IME.prtDebugIntel("06661F6E") IME.prtDebugIntel("06661F6E")
errorCallback() errorCallback()
@ -275,7 +273,7 @@ extension KeyHandler {
var index: Int = NSNotFound var index: Int = NSNotFound
let match: String = let match: String =
(state is InputState.AssociatedPhrases) ? input.inputTextIgnoringModifiers ?? "" : inputText (state is InputState.AssociatedPhrases) ? input.inputTextIgnoringModifiers ?? "" : input.text
for j in 0..<ctlCandidateCurrent.keyLabels.count { for j in 0..<ctlCandidateCurrent.keyLabels.count {
let label: CandidateKeyLabel = ctlCandidateCurrent.keyLabels[j] let label: CandidateKeyLabel = ctlCandidateCurrent.keyLabels[j]
@ -307,25 +305,23 @@ extension KeyHandler {
let punctuationNamePrefix: String = generatePunctuationNamePrefix(withKeyCondition: input) let punctuationNamePrefix: String = generatePunctuationNamePrefix(withKeyCondition: input)
let parser = currentMandarinParser let parser = currentMandarinParser
let arrCustomPunctuations: [String] = [ let arrCustomPunctuations: [String] = [
punctuationNamePrefix, parser, String(format: "%c", charCode.isPrintableASCII ? CChar(charCode) : inputText), punctuationNamePrefix, parser, input.text,
] ]
let customPunctuation: String = arrCustomPunctuations.joined(separator: "") let customPunctuation: String = arrCustomPunctuations.joined(separator: "")
/// ///
let arrPunctuations: [String] = [ let arrPunctuations: [String] = [
punctuationNamePrefix, String(format: "%c", charCode.isPrintableASCII ? CChar(charCode) : inputText), punctuationNamePrefix, input.text,
] ]
let punctuation: String = arrPunctuations.joined(separator: "") let punctuation: String = arrPunctuations.joined(separator: "")
var shouldAutoSelectCandidate: Bool = var shouldAutoSelectCandidate: Bool =
composer.inputValidityCheck(key: charCode) || currentLM.hasUnigramsFor(key: customPunctuation) composer.inputValidityCheck(key: input.charCode) || currentLM.hasUnigramsFor(key: customPunctuation)
|| currentLM.hasUnigramsFor(key: punctuation) || currentLM.hasUnigramsFor(key: punctuation)
if !shouldAutoSelectCandidate, input.isUpperCaseASCIILetterKey { if !shouldAutoSelectCandidate, input.isUpperCaseASCIILetterKey {
let letter: String! = String( let letter = "_letter_\(input.text)"
format: "%@%c", "_letter_", charCode.isPrintableASCII ? CChar(charCode) : inputText
)
if currentLM.hasUnigramsFor(key: letter) { shouldAutoSelectCandidate = true } if currentLM.hasUnigramsFor(key: letter) { shouldAutoSelectCandidate = true }
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// Refactored from the ObjCpp-version of this class by: // Refactored from the ObjCpp-version of this class by:
// (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// ==================== // ====================
@ -18,7 +18,7 @@ extension KeyHandler {
/// - errorCallback: /// - errorCallback:
/// - Returns: IMK /// - Returns: IMK
func handleComposition( func handleComposition(
input: InputSignal, input: InputSignalProtocol,
stateCallback: @escaping (InputStateProtocol) -> Void, stateCallback: @escaping (InputStateProtocol) -> Void,
errorCallback: @escaping () -> Void errorCallback: @escaping () -> Void
) -> Bool? { ) -> Bool? {
@ -42,7 +42,7 @@ extension KeyHandler {
prevReading.0.charComponents.forEach { theComposer.receiveKey(fromPhonabet: $0) } prevReading.0.charComponents.forEach { theComposer.receiveKey(fromPhonabet: $0) }
// 調調 // 調調
let oldIntonation: Tekkon.Phonabet = theComposer.intonation let oldIntonation: Tekkon.Phonabet = theComposer.intonation
theComposer.receiveKey(fromCharCode: input.charCode) theComposer.receiveKey(fromString: input.text)
if theComposer.intonation == oldIntonation, mgrPrefs.specifyIntonationKeyBehavior == 1 { break proc } if theComposer.intonation == oldIntonation, mgrPrefs.specifyIntonationKeyBehavior == 1 { break proc }
theComposer.intonation.clear() theComposer.intonation.clear()
// //
@ -59,7 +59,7 @@ extension KeyHandler {
} }
} }
composer.receiveKey(fromCharCode: input.charCode) composer.receiveKey(fromString: input.text)
keyConsumedByReading = true keyConsumedByReading = true
// 調 updateClientComposingBuffer() return true // 調 updateClientComposingBuffer() return true

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// Refactored from the ObjCpp-version of this class by: // Refactored from the ObjCpp-version of this class by:
// (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// ==================== // ====================
@ -24,16 +24,15 @@ extension KeyHandler {
/// - errorCallback: /// - errorCallback:
/// - Returns: IMK /// - Returns: IMK
func handle( func handle(
input: InputSignal, input: InputSignalProtocol,
state: InputStateProtocol, state: InputStateProtocol,
stateCallback: @escaping (InputStateProtocol) -> Void, stateCallback: @escaping (InputStateProtocol) -> Void,
errorCallback: @escaping () -> Void errorCallback: @escaping () -> Void
) -> Bool { ) -> Bool {
// inputTest // inputTest
guard !input.inputText.isEmpty else { return false } guard !input.text.isEmpty else { return false }
let charCode: UniChar = input.charCode let inputText: String = input.text
let inputText: String = input.inputText
var state = state // var state = state //
// Megrez // Megrez
@ -78,7 +77,7 @@ extension KeyHandler {
/// ASCII 使insertText:replacementRange: /// ASCII 使insertText:replacementRange:
/// ASCII /// ASCII
if charCode < 0x80, !charCode.isPrintableASCII { if input.isASCII, !input.charCode.isPrintableASCII {
return false return false
} }
@ -309,7 +308,7 @@ extension KeyHandler {
if input.isMainAreaNumKey, input.isShiftHold, input.isOptionHold, !input.isControlHold, !input.isCommandHold { if input.isMainAreaNumKey, input.isShiftHold, input.isOptionHold, !input.isControlHold, !input.isCommandHold {
// NOTE: macOS 10.11 El Capitan CFStringTransform StringTransform: // NOTE: macOS 10.11 El Capitan CFStringTransform StringTransform:
// https://developer.apple.com/documentation/foundation/stringtransform // https://developer.apple.com/documentation/foundation/stringtransform
guard let stringRAW = input.mapMainAreaNumKey[input.keyCode] else { return false } guard let stringRAW = input.mainAreaNumKeyChar else { return false }
let string = NSMutableString(string: stringRAW) let string = NSMutableString(string: stringRAW)
CFStringTransform(string, nil, kCFStringTransformFullwidthHalfwidth, true) CFStringTransform(string, nil, kCFStringTransformFullwidthHalfwidth, true)
stateCallback( stateCallback(
@ -328,9 +327,7 @@ extension KeyHandler {
let punctuationNamePrefix: String = generatePunctuationNamePrefix(withKeyCondition: input) let punctuationNamePrefix: String = generatePunctuationNamePrefix(withKeyCondition: input)
let parser = currentMandarinParser let parser = currentMandarinParser
let arrCustomPunctuations: [String] = [ let arrCustomPunctuations: [String] = [punctuationNamePrefix, parser, input.text]
punctuationNamePrefix, parser, String(format: "%c", charCode.isPrintableASCII ? CChar(charCode) : inputText),
]
let customPunctuation: String = arrCustomPunctuations.joined(separator: "") let customPunctuation: String = arrCustomPunctuations.joined(separator: "")
if handlePunctuation( if handlePunctuation(
customPunctuation, customPunctuation,
@ -344,9 +341,7 @@ extension KeyHandler {
/// ///
let arrPunctuations: [String] = [ let arrPunctuations: [String] = [punctuationNamePrefix, input.text]
punctuationNamePrefix, String(format: "%c", charCode.isPrintableASCII ? CChar(charCode) : inputText),
]
let punctuation: String = arrPunctuations.joined(separator: "") let punctuation: String = arrPunctuations.joined(separator: "")
if handlePunctuation( if handlePunctuation(
@ -386,9 +381,7 @@ extension KeyHandler {
stateCallback(InputState.Empty()) stateCallback(InputState.Empty())
return true return true
default: // case 0 default: // case 0
let letter: String! = String( let letter = "_letter_\(inputText)"
format: "%@%c", "_letter_", charCode.isPrintableASCII ? CChar(charCode) : inputText
)
if handlePunctuation( if handlePunctuation(
letter, letter,
state: state, state: state,
@ -410,7 +403,7 @@ extension KeyHandler {
/// 便 /// 便
if (state is InputState.NotEmpty) || !composer.isEmpty { if (state is InputState.NotEmpty) || !composer.isEmpty {
IME.prtDebugIntel( IME.prtDebugIntel(
"Blocked data: charCode: \(charCode), keyCode: \(input.keyCode)") "Blocked data: charCode: \(input.charCode), keyCode: \(input.keyCode)")
IME.prtDebugIntel("A9BFF20E") IME.prtDebugIntel("A9BFF20E")
errorCallback() errorCallback()
stateCallback(state) stateCallback(state)

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// Refactored from the ObjCpp-version of this class by: // Refactored from the ObjCpp-version of this class by:
// (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// ==================== // ====================
@ -170,7 +170,7 @@ extension KeyHandler {
/// - Returns: ctlInputMethod IMK /// - Returns: ctlInputMethod IMK
func handleMarkingState( func handleMarkingState(
_ state: InputState.Marking, _ state: InputState.Marking,
input: InputSignal, input: InputSignalProtocol,
stateCallback: @escaping (InputStateProtocol) -> Void, stateCallback: @escaping (InputStateProtocol) -> Void,
errorCallback: @escaping () -> Void errorCallback: @escaping () -> Void
) -> Bool { ) -> Bool {
@ -416,7 +416,7 @@ extension KeyHandler {
/// - Returns: ctlInputMethod IMK /// - Returns: ctlInputMethod IMK
func handleBackSpace( func handleBackSpace(
state: InputStateProtocol, state: InputStateProtocol,
input: InputSignal, input: InputSignalProtocol,
stateCallback: @escaping (InputStateProtocol) -> Void, stateCallback: @escaping (InputStateProtocol) -> Void,
errorCallback: @escaping () -> Void errorCallback: @escaping () -> Void
) -> Bool { ) -> Bool {
@ -482,7 +482,7 @@ extension KeyHandler {
/// - Returns: ctlInputMethod IMK /// - Returns: ctlInputMethod IMK
func handleDelete( func handleDelete(
state: InputStateProtocol, state: InputStateProtocol,
input: InputSignal, input: InputSignalProtocol,
stateCallback: @escaping (InputStateProtocol) -> Void, stateCallback: @escaping (InputStateProtocol) -> Void,
errorCallback: @escaping () -> Void errorCallback: @escaping () -> Void
) -> Bool { ) -> Bool {
@ -652,7 +652,7 @@ extension KeyHandler {
/// - Returns: ctlInputMethod IMK /// - Returns: ctlInputMethod IMK
func handleForward( func handleForward(
state: InputStateProtocol, state: InputStateProtocol,
input: InputSignal, input: InputSignalProtocol,
stateCallback: @escaping (InputStateProtocol) -> Void, stateCallback: @escaping (InputStateProtocol) -> Void,
errorCallback: @escaping () -> Void errorCallback: @escaping () -> Void
) -> Bool { ) -> Bool {
@ -726,7 +726,7 @@ extension KeyHandler {
/// - Returns: ctlInputMethod IMK /// - Returns: ctlInputMethod IMK
func handleBackward( func handleBackward(
state: InputStateProtocol, state: InputStateProtocol,
input: InputSignal, input: InputSignalProtocol,
stateCallback: @escaping (InputStateProtocol) -> Void, stateCallback: @escaping (InputStateProtocol) -> Void,
errorCallback: @escaping () -> Void errorCallback: @escaping () -> Void
) -> Bool { ) -> Bool {

View File

@ -0,0 +1,302 @@
// (c) 2022 and onwards The vChewing Project (MIT-NTL License).
// ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that:
// No trademark license is granted to use the trade names, trademarks, service
// marks, or product names of Contributor, except as required to fulfill notice
// requirements defined in MIT License.
import Cocoa
// MARK: - NSEvent Extension
extension NSEvent: InputSignalProtocol {
public var isASCIIModeInput: Bool { ctlInputMethod.isASCIIModeSituation }
public var isTypingVertical: Bool { ctlInputMethod.isVerticalTypingSituation }
public var text: String { AppleKeyboardConverter.cnvStringApple2ABC(characters ?? "") }
public var inputTextIgnoringModifiers: String? {
guard let charIgnoringModifiers = charactersIgnoringModifiers else { return nil }
return AppleKeyboardConverter.cnvStringApple2ABC(charIgnoringModifiers)
}
public var charCode: UInt16 {
// count > 0!isEmpty滿
guard !text.isEmpty else { return 0 }
let scalars = text.unicodeScalars
let result = scalars[scalars.startIndex].value
return result <= UInt16.max ? UInt16(result) : UInt16.max
}
public var isFlagChanged: Bool { type == .flagsChanged }
public var emacsKey: EmacsKey {
NSEvent.detectEmacsKey(charCode: charCode, flags: modifierFlags)
}
// Alt+Shift+ macOS
// KeyCode
//
public var mainAreaNumKeyChar: String? { mapMainAreaNumKey[keyCode] }
// ANSI charCode Swift KeyHandler
public var isInvalid: Bool {
(0x20...0xFF).contains(charCode) ? false : !(isReservedKey && !isKeyCodeBlacklisted)
}
public var isKeyCodeBlacklisted: Bool {
guard let code = KeyCodeBlackListed(rawValue: keyCode) else { return false }
return code.rawValue != KeyCode.kNone.rawValue
}
public var isReservedKey: Bool {
guard let code = KeyCode(rawValue: keyCode) else { return false }
return code.rawValue != KeyCode.kNone.rawValue
}
public var isCandidateKey: Bool {
mgrPrefs.candidateKeys.contains(text)
|| mgrPrefs.candidateKeys.contains(inputTextIgnoringModifiers ?? "114514")
}
/// flags KeyCode
public var isNumericPadKey: Bool { arrNumpadKeyCodes.contains(keyCode) }
public var isMainAreaNumKey: Bool { arrMainAreaNumKey.contains(keyCode) }
public var isShiftHold: Bool { modifierFlags.contains([.shift]) }
public var isCommandHold: Bool { modifierFlags.contains([.command]) }
public var isControlHold: Bool { modifierFlags.contains([.control]) }
public var isControlHotKey: Bool { modifierFlags.contains([.control]) && text.first?.isLetter ?? false }
public var isOptionHold: Bool { modifierFlags.contains([.option]) }
public var isOptionHotKey: Bool { modifierFlags.contains([.option]) && text.first?.isLetter ?? false }
public var isCapsLockOn: Bool { modifierFlags.contains([.capsLock]) }
public var isFunctionKeyHold: Bool { modifierFlags.contains([.function]) }
public var isNonLaptopFunctionKey: Bool { modifierFlags.contains([.numericPad]) && !isNumericPadKey }
public var isEnter: Bool { [KeyCode.kCarriageReturn, KeyCode.kLineFeed].contains(KeyCode(rawValue: keyCode)) }
public var isTab: Bool { KeyCode(rawValue: keyCode) == KeyCode.kTab }
public var isUp: Bool { KeyCode(rawValue: keyCode) == KeyCode.kUpArrow }
public var isDown: Bool { KeyCode(rawValue: keyCode) == KeyCode.kDownArrow }
public var isLeft: Bool { KeyCode(rawValue: keyCode) == KeyCode.kLeftArrow }
public var isRight: Bool { KeyCode(rawValue: keyCode) == KeyCode.kRightArrow }
public var isPageUp: Bool { KeyCode(rawValue: keyCode) == KeyCode.kPageUp }
public var isPageDown: Bool { KeyCode(rawValue: keyCode) == KeyCode.kPageDown }
public var isSpace: Bool { KeyCode(rawValue: keyCode) == KeyCode.kSpace }
public var isBackSpace: Bool { KeyCode(rawValue: keyCode) == KeyCode.kBackSpace }
public var isEsc: Bool { KeyCode(rawValue: keyCode) == KeyCode.kEscape }
public var isHome: Bool { KeyCode(rawValue: keyCode) == KeyCode.kHome }
public var isEnd: Bool { KeyCode(rawValue: keyCode) == KeyCode.kEnd }
public var isDelete: Bool { KeyCode(rawValue: keyCode) == KeyCode.kWindowsDelete }
public var isCursorBackward: Bool {
isTypingVertical
? KeyCode(rawValue: keyCode) == .kUpArrow
: KeyCode(rawValue: keyCode) == .kLeftArrow
}
public var isCursorForward: Bool {
isTypingVertical
? KeyCode(rawValue: keyCode) == .kDownArrow
: KeyCode(rawValue: keyCode) == .kRightArrow
}
public var isCursorClockRight: Bool {
isTypingVertical
? KeyCode(rawValue: keyCode) == .kRightArrow
: KeyCode(rawValue: keyCode) == .kUpArrow
}
public var isCursorClockLeft: Bool {
isTypingVertical
? KeyCode(rawValue: keyCode) == .kLeftArrow
: KeyCode(rawValue: keyCode) == .kDownArrow
}
public var isASCII: Bool { charCode < 0x80 }
// flags == .shift Shift
public var isUpperCaseASCIILetterKey: Bool {
(65...90).contains(charCode) && modifierFlags == .shift
}
// KeyCode macOS Apple
// ![input isShiftHold] 使 Shift
public var isSymbolMenuPhysicalKey: Bool {
[KeyCode.kSymbolMenuPhysicalKeyIntl, KeyCode.kSymbolMenuPhysicalKeyJIS].contains(KeyCode(rawValue: keyCode))
}
static func detectEmacsKey(charCode: UniChar, flags: NSEvent.ModifierFlags) -> EmacsKey {
if flags.contains(.control) {
return EmacsKey(rawValue: charCode) ?? .none
}
return .none
}
}
// MARK: - InputSignalProtocol
public protocol InputSignalProtocol {
var isASCIIModeInput: Bool { get }
var isTypingVertical: Bool { get }
var text: String { get }
var inputTextIgnoringModifiers: String? { get }
var charCode: UInt16 { get }
var keyCode: UInt16 { get }
var isFlagChanged: Bool { get }
var emacsKey: EmacsKey { get }
var mainAreaNumKeyChar: String? { get }
var isASCII: Bool { get }
var isInvalid: Bool { get }
var isKeyCodeBlacklisted: Bool { get }
var isReservedKey: Bool { get }
var isCandidateKey: Bool { get }
var isNumericPadKey: Bool { get }
var isMainAreaNumKey: Bool { get }
var isShiftHold: Bool { get }
var isCommandHold: Bool { get }
var isControlHold: Bool { get }
var isControlHotKey: Bool { get }
var isOptionHold: Bool { get }
var isOptionHotKey: Bool { get }
var isCapsLockOn: Bool { get }
var isFunctionKeyHold: Bool { get }
var isNonLaptopFunctionKey: Bool { get }
var isEnter: Bool { get }
var isTab: Bool { get }
var isUp: Bool { get }
var isDown: Bool { get }
var isLeft: Bool { get }
var isRight: Bool { get }
var isPageUp: Bool { get }
var isPageDown: Bool { get }
var isSpace: Bool { get }
var isBackSpace: Bool { get }
var isEsc: Bool { get }
var isHome: Bool { get }
var isEnd: Bool { get }
var isDelete: Bool { get }
var isCursorBackward: Bool { get }
var isCursorForward: Bool { get }
var isCursorClockRight: Bool { get }
var isCursorClockLeft: Bool { get }
var isUpperCaseASCIILetterKey: Bool { get }
var isSymbolMenuPhysicalKey: Bool { get }
}
// MARK: - Enums of Constants
// Use KeyCodes as much as possible since its recognition won't be affected by macOS Base Keyboard Layouts.
// KeyCodes: https://eastmanreference.com/complete-list-of-applescript-key-codes
// Also: HIToolbox.framework/Versions/A/Headers/Events.h
public enum KeyCode: UInt16 {
case kNone = 0
case kCarriageReturn = 36 // Renamed from "kReturn" to avoid nomenclatural confusions.
case kTab = 48
case kSpace = 49
case kSymbolMenuPhysicalKeyIntl = 50 // vChewing Specific (Non-JIS)
case kBackSpace = 51 // Renamed from "kDelete" to avoid nomenclatural confusions.
case kEscape = 53
case kCommand = 55
case kShift = 56
case kCapsLock = 57
case kOption = 58
case kControl = 59
case kRightShift = 60
case kRightOption = 61
case kRightControl = 62
case kFunction = 63
case kF17 = 64
case kVolumeUp = 72
case kVolumeDown = 73
case kMute = 74
case kLineFeed = 76 // Another keyCode to identify the Enter Key, typable by Fn+Enter.
case kF18 = 79
case kF19 = 80
case kF20 = 90
case kSymbolMenuPhysicalKeyJIS = 94 // vChewing Specific (JIS)
case kF5 = 96
case kF6 = 97
case kF7 = 98
case kF3 = 99
case kF8 = 100
case kF9 = 101
case kF11 = 103
case kF13 = 105 // PrtSc
case kF16 = 106
case kF14 = 107
case kF10 = 109
case kF12 = 111
case kF15 = 113
case kHelp = 114 // Insert
case kHome = 115
case kPageUp = 116
case kWindowsDelete = 117 // Renamed from "kForwardDelete" to avoid nomenclatural confusions.
case kF4 = 118
case kEnd = 119
case kF2 = 120
case kPageDown = 121
case kF1 = 122
case kLeftArrow = 123
case kRightArrow = 124
case kDownArrow = 125
case kUpArrow = 126
}
enum KeyCodeBlackListed: UInt16 {
case kF17 = 64
case kVolumeUp = 72
case kVolumeDown = 73
case kMute = 74
case kF18 = 79
case kF19 = 80
case kF20 = 90
case kF5 = 96
case kF6 = 97
case kF7 = 98
case kF3 = 99
case kF8 = 100
case kF9 = 101
case kF11 = 103
case kF13 = 105 // PrtSc
case kF16 = 106
case kF14 = 107
case kF10 = 109
case kF12 = 111
case kF15 = 113
case kHelp = 114 // Insert
case kF4 = 118
case kF2 = 120
case kF1 = 122
}
// Alt+Shift+ macOS
// KeyCode
let mapMainAreaNumKey: [UInt16: String] = [
18: "1", 19: "2", 20: "3", 21: "4", 23: "5", 22: "6", 26: "7", 28: "8", 25: "9", 29: "0",
]
/// KeyCode
///
/// 95 Key Code JIS
let arrNumpadKeyCodes: [UInt16] = [65, 67, 69, 71, 75, 78, 81, 82, 83, 84, 85, 86, 87, 88, 89, 91, 92, 95]
/// KeyCode
let arrMainAreaNumKey: [UInt16] = [18, 19, 20, 21, 22, 23, 25, 26, 28, 29]
// CharCodes: https://theasciicode.com.ar/ascii-control-characters/horizontal-tab-ascii-code-9.html
enum CharCode: UInt16 {
case yajuusenpaiA = 114
case yajuusenpaiB = 514
case yajuusenpaiC = 1919
case yajuusenpaiD = 810
// CharCode is not reliable at all. KeyCode is the most appropriate choice due to its accuracy.
// KeyCode doesn't give a phuque about the character sent through macOS keyboard layouts ...
// ... but only focuses on which physical key is pressed.
}
public enum EmacsKey: UInt16 {
case none = 0
case forward = 6 // F
case backward = 2 // B
case home = 1 // A
case end = 5 // E
case delete = 4 // D
case nextPage = 22 // V
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
@ -17,19 +17,25 @@ extension ctlInputMethod {
/// - Returns: `true` IMK`false` /// - Returns: `true` IMK`false`
func commonEventHandler(_ event: NSEvent) -> Bool { func commonEventHandler(_ event: NSEvent) -> Bool {
// Shift macOS 10.15 macOS // Shift macOS 10.15 macOS
let shouldUseHandle = let shouldUseHandle: Bool = {
(IME.arrClientShiftHandlingExceptionList.contains(clientBundleIdentifier) switch mgrPrefs.shiftKeyAccommodationBehavior {
|| mgrPrefs.shouldAlwaysUseShiftKeyAccommodation) case 0: return false
case 1: return IME.arrClientShiftHandlingExceptionList.contains(clientBundleIdentifier)
case 2: return true
default: return false
}
}()
if #available(macOS 10.15, *) { if #available(macOS 10.15, *) {
if ShiftKeyUpChecker.check(event), !mgrPrefs.disableShiftTogglingAlphanumericalMode { if ShiftKeyUpChecker.check(event), !mgrPrefs.disableShiftTogglingAlphanumericalMode {
if !shouldUseHandle || (!rencentKeyHandledByKeyHandler && shouldUseHandle) { if !shouldUseHandle || (!rencentKeyHandledByKeyHandler && shouldUseHandle) {
NotifierController.notify( NotifierController.notify(
message: String( message: NSLocalizedString("Alphanumerical Mode", comment: "") + "\n"
format: "%@%@%@", NSLocalizedString("Alphanumerical Mode", comment: ""), "\n", + {
toggleASCIIMode() toggleASCIIMode()
? NSLocalizedString("NotificationSwitchON", comment: "") ? NSLocalizedString("NotificationSwitchON", comment: "")
: NSLocalizedString("NotificationSwitchOFF", comment: "") : NSLocalizedString("NotificationSwitchOFF", comment: "")
) }()
) )
} }
if shouldUseHandle { if shouldUseHandle {
@ -51,19 +57,16 @@ extension ctlInputMethod {
// //
ctlInputMethod.areWeNerfing = event.modifierFlags.contains([.shift, .command]) ctlInputMethod.areWeNerfing = event.modifierFlags.contains([.shift, .command])
var input = InputSignal(event: event, isVerticalTyping: isVerticalTyping)
input.isASCIIModeInput = isASCIIMode
// //
// KeyHandler // KeyHandler
if !input.charCode.isPrintable { if !event.charCode.isPrintable {
return false return false
} }
/// 調 /// 調
/// result bool IMK /// result bool IMK
/// keyHandler.handleCandidate() /// keyHandler.handleCandidate()
let result = keyHandler.handle(input: input, state: state) { newState in let result = keyHandler.handle(input: event, state: state) { newState in
self.handle(state: newState) self.handle(state: newState)
} errorCallback: { } errorCallback: {
clsSFX.beep() clsSFX.beep()

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
@ -38,6 +38,10 @@ class ctlInputMethod: IMKInputController {
var state: InputStateProtocol = InputState.Empty() var state: InputStateProtocol = InputState.Empty()
/// ctlInputMethod /// ctlInputMethod
var isASCIIMode: Bool = false var isASCIIMode: Bool = false
/// ctlInputMethod
static var isASCIIModeSituation: Bool = false
/// ctlInputMethod
static var isVerticalTypingSituation: Bool = false
/// ctlInputMethod /// ctlInputMethod
func toggleASCIIMode() -> Bool { func toggleASCIIMode() -> Bool {
@ -110,12 +114,13 @@ class ctlInputMethod: IMKInputController {
isASCIIMode = false isASCIIMode = false
} else { } else {
NotifierController.notify( NotifierController.notify(
message: String( message: NSLocalizedString("Alphanumerical Mode", comment: "") + "\n"
format: "%@%@%@", NSLocalizedString("Alphanumerical Mode", comment: ""), "\n", + {
isASCIIMode isASCIIMode
? NSLocalizedString("NotificationSwitchON", comment: "") ? NSLocalizedString("NotificationSwitchON", comment: "")
: NSLocalizedString("NotificationSwitchOFF", comment: "") : NSLocalizedString("NotificationSwitchOFF", comment: "")
)) }()
)
} }
} }
@ -201,6 +206,10 @@ class ctlInputMethod: IMKInputController {
// client() // client()
if !(sender is IMKTextInput) { return false } if !(sender is IMKTextInput) { return false }
//
ctlInputMethod.isASCIIModeSituation = isASCIIMode
ctlInputMethod.isVerticalTypingSituation = isVerticalTyping
// NSEvent nilApple InputMethodKit // NSEvent nilApple InputMethodKit
guard let event = event else { return false } guard let event = event else { return false }
@ -211,11 +220,10 @@ class ctlInputMethod: IMKInputController {
proc: if let ctlCandidateCurrent = ctlInputMethod.ctlCandidateCurrent as? ctlCandidateIMK { proc: if let ctlCandidateCurrent = ctlInputMethod.ctlCandidateCurrent as? ctlCandidateIMK {
guard ctlCandidateCurrent.visible else { break proc } guard ctlCandidateCurrent.visible else { break proc }
let event: NSEvent = ctlCandidateIMK.replaceNumPadKeyCodes(target: event) ?? event let event: NSEvent = ctlCandidateIMK.replaceNumPadKeyCodes(target: event) ?? event
let input = InputSignal(event: event)
// Shift+Enter delegate keyHandler // Shift+Enter delegate keyHandler
// Shift Flags // Shift Flags
if input.isShiftHold, input.isEnter { if event.isShiftHold, event.isEnter {
guard guard
let newEvent = NSEvent.keyEvent( let newEvent = NSEvent.keyEvent(
with: event.type, with: event.type,
@ -238,7 +246,7 @@ class ctlInputMethod: IMKInputController {
} }
// //
if let newChar = ctlCandidateIMK.defaultIMKSelectionKey[event.keyCode], input.isShiftHold, if let newChar = ctlCandidateIMK.defaultIMKSelectionKey[event.keyCode], event.isShiftHold,
isAssociatedPhrasesState isAssociatedPhrasesState
{ {
let newEvent = NSEvent.keyEvent( let newEvent = NSEvent.keyEvent(

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
@ -211,102 +211,109 @@ extension ctlInputMethod {
@objc func toggleSCPCTypingMode(_: Any? = nil) { @objc func toggleSCPCTypingMode(_: Any? = nil) {
resetKeyHandler() resetKeyHandler()
NotifierController.notify( NotifierController.notify(
message: String( message: NSLocalizedString("Per-Char Select Mode", comment: "") + "\n"
format: "%@%@%@", NSLocalizedString("Per-Char Select Mode", comment: ""), "\n", + {
mgrPrefs.toggleSCPCTypingModeEnabled() mgrPrefs.toggleSCPCTypingModeEnabled()
? NSLocalizedString("NotificationSwitchON", comment: "") ? NSLocalizedString("NotificationSwitchON", comment: "")
: NSLocalizedString("NotificationSwitchOFF", comment: "") : NSLocalizedString("NotificationSwitchOFF", comment: "")
)) }()
)
} }
@objc func toggleChineseConverter(_: Any?) { @objc func toggleChineseConverter(_: Any?) {
resetKeyHandler() resetKeyHandler()
NotifierController.notify( NotifierController.notify(
message: String( message: NSLocalizedString("Force KangXi Writing", comment: "") + "\n"
format: "%@%@%@", NSLocalizedString("Force KangXi Writing", comment: ""), "\n", + {
mgrPrefs.toggleChineseConversionEnabled() mgrPrefs.toggleChineseConversionEnabled()
? NSLocalizedString("NotificationSwitchON", comment: "") ? NSLocalizedString("NotificationSwitchON", comment: "")
: NSLocalizedString("NotificationSwitchOFF", comment: "") : NSLocalizedString("NotificationSwitchOFF", comment: "")
)) }()
)
} }
@objc func toggleShiftJISShinjitaiOutput(_: Any?) { @objc func toggleShiftJISShinjitaiOutput(_: Any?) {
resetKeyHandler() resetKeyHandler()
NotifierController.notify( NotifierController.notify(
message: String( message: NSLocalizedString("JIS Shinjitai Output", comment: "") + "\n"
format: "%@%@%@", NSLocalizedString("JIS Shinjitai Output", comment: ""), "\n", + {
mgrPrefs.toggleShiftJISShinjitaiOutputEnabled() mgrPrefs.toggleShiftJISShinjitaiOutputEnabled()
? NSLocalizedString("NotificationSwitchON", comment: "") ? NSLocalizedString("NotificationSwitchON", comment: "")
: NSLocalizedString("NotificationSwitchOFF", comment: "") : NSLocalizedString("NotificationSwitchOFF", comment: "")
)) }()
)
} }
@objc func toggleCurrencyNumerals(_: Any?) { @objc func toggleCurrencyNumerals(_: Any?) {
resetKeyHandler() resetKeyHandler()
NotifierController.notify( NotifierController.notify(
message: String( message: NSLocalizedString("Currency Numeral Output", comment: "") + "\n"
format: "%@%@%@", NSLocalizedString("Currency Numeral Output", comment: ""), "\n", + {
mgrPrefs.toggleCurrencyNumeralsEnabled() mgrPrefs.toggleCurrencyNumeralsEnabled()
? NSLocalizedString("NotificationSwitchON", comment: "") ? NSLocalizedString("NotificationSwitchON", comment: "")
: NSLocalizedString("NotificationSwitchOFF", comment: "") : NSLocalizedString("NotificationSwitchOFF", comment: "")
)) }()
)
} }
@objc func toggleHalfWidthPunctuation(_: Any?) { @objc func toggleHalfWidthPunctuation(_: Any?) {
resetKeyHandler() resetKeyHandler()
NotifierController.notify( NotifierController.notify(
message: String( message: NSLocalizedString("Half-Width Punctuation Mode", comment: "") + "\n"
format: "%@%@%@", NSLocalizedString("Half-Width Punctuation Mode", comment: ""), + {
"\n", mgrPrefs.toggleHalfWidthPunctuationEnabled()
mgrPrefs.toggleHalfWidthPunctuationEnabled() ? NSLocalizedString("NotificationSwitchON", comment: "")
? NSLocalizedString("NotificationSwitchON", comment: "") : NSLocalizedString("NotificationSwitchOFF", comment: "")
: NSLocalizedString("NotificationSwitchOFF", comment: "") }()
)) )
} }
@objc func toggleCNS11643Enabled(_: Any?) { @objc func toggleCNS11643Enabled(_: Any?) {
resetKeyHandler() resetKeyHandler()
NotifierController.notify( NotifierController.notify(
message: String( message: NSLocalizedString("CNS11643 Mode", comment: "") + "\n"
format: "%@%@%@", NSLocalizedString("CNS11643 Mode", comment: ""), "\n", + {
mgrPrefs.toggleCNS11643Enabled() mgrPrefs.toggleCNS11643Enabled()
? NSLocalizedString("NotificationSwitchON", comment: "") ? NSLocalizedString("NotificationSwitchON", comment: "")
: NSLocalizedString("NotificationSwitchOFF", comment: "") : NSLocalizedString("NotificationSwitchOFF", comment: "")
)) }()
)
} }
@objc func toggleSymbolEnabled(_: Any?) { @objc func toggleSymbolEnabled(_: Any?) {
resetKeyHandler() resetKeyHandler()
NotifierController.notify( NotifierController.notify(
message: String( message: NSLocalizedString("Symbol & Emoji Input", comment: "") + "\n"
format: "%@%@%@", NSLocalizedString("Symbol & Emoji Input", comment: ""), "\n", + {
mgrPrefs.toggleSymbolInputEnabled() mgrPrefs.toggleSymbolInputEnabled()
? NSLocalizedString("NotificationSwitchON", comment: "") ? NSLocalizedString("NotificationSwitchON", comment: "")
: NSLocalizedString("NotificationSwitchOFF", comment: "") : NSLocalizedString("NotificationSwitchOFF", comment: "")
)) }()
)
} }
@objc func toggleAssociatedPhrasesEnabled(_: Any?) { @objc func toggleAssociatedPhrasesEnabled(_: Any?) {
resetKeyHandler() resetKeyHandler()
NotifierController.notify( NotifierController.notify(
message: String( message: NSLocalizedString("Per-Char Associated Phrases", comment: "") + "\n"
format: "%@%@%@", NSLocalizedString("Per-Char Associated Phrases", comment: ""), + {
"\n", mgrPrefs.toggleAssociatedPhrasesEnabled()
mgrPrefs.toggleAssociatedPhrasesEnabled() ? NSLocalizedString("NotificationSwitchON", comment: "")
? NSLocalizedString("NotificationSwitchON", comment: "") : NSLocalizedString("NotificationSwitchOFF", comment: "")
: NSLocalizedString("NotificationSwitchOFF", comment: "") }()
)) )
} }
@objc func togglePhraseReplacement(_: Any?) { @objc func togglePhraseReplacement(_: Any?) {
resetKeyHandler() resetKeyHandler()
NotifierController.notify( NotifierController.notify(
message: String( message: NSLocalizedString("Use Phrase Replacement", comment: "") + "\n"
format: "%@%@%@", NSLocalizedString("Use Phrase Replacement", comment: ""), "\n", + {
mgrPrefs.togglePhraseReplacementEnabled() mgrPrefs.togglePhraseReplacementEnabled()
? NSLocalizedString("NotificationSwitchON", comment: "") ? NSLocalizedString("NotificationSwitchON", comment: "")
: NSLocalizedString("NotificationSwitchOFF", comment: "") : NSLocalizedString("NotificationSwitchOFF", comment: "")
)) }()
)
} }
@objc func selfUninstall(_: Any?) { @objc func selfUninstall(_: Any?) {

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that: // ... with NTL restriction stating that:

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
@ -58,7 +58,7 @@ public enum UserDef: String, CaseIterable {
case kUseIMKCandidateWindow = "UseIMKCandidateWindow" case kUseIMKCandidateWindow = "UseIMKCandidateWindow"
case kHandleDefaultCandidateFontsByLangIdentifier = "HandleDefaultCandidateFontsByLangIdentifier" case kHandleDefaultCandidateFontsByLangIdentifier = "HandleDefaultCandidateFontsByLangIdentifier"
case kShouldAlwaysUseShiftKeyAccommodation = "ShouldAlwaysUseShiftKeyAccommodation" case kShiftKeyAccommodationBehavior = "ShiftKeyAccommodationBehavior"
case kCandidateTextFontName = "CandidateTextFontName" case kCandidateTextFontName = "CandidateTextFontName"
case kCandidateKeyLabelFontName = "CandidateKeyLabelFontName" case kCandidateKeyLabelFontName = "CandidateKeyLabelFontName"
@ -316,7 +316,7 @@ public enum mgrPrefs {
forKey: UserDef.kHandleDefaultCandidateFontsByLangIdentifier.rawValue forKey: UserDef.kHandleDefaultCandidateFontsByLangIdentifier.rawValue
) )
UserDefaults.standard.setDefault( UserDefaults.standard.setDefault(
mgrPrefs.shouldAlwaysUseShiftKeyAccommodation, forKey: UserDef.kShouldAlwaysUseShiftKeyAccommodation.rawValue mgrPrefs.shiftKeyAccommodationBehavior, forKey: UserDef.kShiftKeyAccommodationBehavior.rawValue
) )
// ----- // -----
@ -438,7 +438,6 @@ public enum mgrPrefs {
@UserDefault(key: UserDef.kTrimUnfinishedReadingsOnCommit.rawValue, defaultValue: true) @UserDefault(key: UserDef.kTrimUnfinishedReadingsOnCommit.rawValue, defaultValue: true)
static var trimUnfinishedReadingsOnCommit: Bool static var trimUnfinishedReadingsOnCommit: Bool
// MARK: - Settings (Tier 2) // MARK: - Settings (Tier 2)
@UserDefault(key: UserDef.kUseIMKCandidateWindow.rawValue, defaultValue: false) @UserDefault(key: UserDef.kUseIMKCandidateWindow.rawValue, defaultValue: false)
@ -447,8 +446,8 @@ public enum mgrPrefs {
@UserDefault(key: UserDef.kHandleDefaultCandidateFontsByLangIdentifier.rawValue, defaultValue: false) @UserDefault(key: UserDef.kHandleDefaultCandidateFontsByLangIdentifier.rawValue, defaultValue: false)
static var handleDefaultCandidateFontsByLangIdentifier: Bool static var handleDefaultCandidateFontsByLangIdentifier: Bool
@UserDefault(key: UserDef.kShouldAlwaysUseShiftKeyAccommodation.rawValue, defaultValue: false) @UserDefault(key: UserDef.kShiftKeyAccommodationBehavior.rawValue, defaultValue: 0)
static var shouldAlwaysUseShiftKeyAccommodation: Bool static var shiftKeyAccommodationBehavior: Int
// MARK: - Settings (Tier 3) // MARK: - Settings (Tier 3)
@ -728,7 +727,7 @@ extension mgrPrefs {
} }
if #unavailable(macOS 10.15) { if #unavailable(macOS 10.15) {
mgrPrefs.handleDefaultCandidateFontsByLangIdentifier = false mgrPrefs.handleDefaultCandidateFontsByLangIdentifier = false
mgrPrefs.shouldAlwaysUseShiftKeyAccommodation = false mgrPrefs.shiftKeyAccommodationBehavior = 0
mgrPrefs.disableShiftTogglingAlphanumericalMode = false mgrPrefs.disableShiftTogglingAlphanumericalMode = false
mgrPrefs.togglingAlphanumericalModeWithLShift = false mgrPrefs.togglingAlphanumericalModeWithLShift = false
} }
@ -768,6 +767,9 @@ extension mgrPrefs {
if ![0, 1, 2].contains(upperCaseLetterKeyBehavior) { if ![0, 1, 2].contains(upperCaseLetterKeyBehavior) {
upperCaseLetterKeyBehavior = 0 upperCaseLetterKeyBehavior = 0
} }
if ![0, 1, 2].contains(shiftKeyAccommodationBehavior) {
shiftKeyAccommodationBehavior = 0
}
} }
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that: // ... with NTL restriction stating that:

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// Refactored from the ObjCpp-version of this class by: // Refactored from the ObjCpp-version of this class by:
// (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// ==================== // ====================

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that: // ... with NTL restriction stating that:

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
@ -54,54 +54,30 @@ class SymbolNode {
// MARK: - Static data. // MARK: - Static data.
static let catCommonSymbols = String( static let catCommonSymbols = NSLocalizedString("catCommonSymbols", comment: "")
format: NSLocalizedString("catCommonSymbols", comment: "")) static let catHoriBrackets = NSLocalizedString("catHoriBrackets", comment: "")
static let catHoriBrackets = String( static let catVertBrackets = NSLocalizedString("catVertBrackets", comment: "")
format: NSLocalizedString("catHoriBrackets", comment: "")) static let catAlphabets = NSLocalizedString("catAlphabets", comment: "")
static let catVertBrackets = String( static let catSpecialNumbers = NSLocalizedString("catSpecialNumbers", comment: "")
format: NSLocalizedString("catVertBrackets", comment: "")) static let catMathSymbols = NSLocalizedString("catMathSymbols", comment: "")
static let catAlphabets = String( static let catCurrencyUnits = NSLocalizedString("catCurrencyUnits", comment: "")
format: NSLocalizedString("catAlphabets", comment: "")) static let catSpecialSymbols = NSLocalizedString("catSpecialSymbols", comment: "")
static let catSpecialNumbers = String( static let catUnicodeSymbols = NSLocalizedString("catUnicodeSymbols", comment: "")
format: NSLocalizedString("catSpecialNumbers", comment: "")) static let catCircledKanjis = NSLocalizedString("catCircledKanjis", comment: "")
static let catMathSymbols = String( static let catCircledKataKana = NSLocalizedString("catCircledKataKana", comment: "")
format: NSLocalizedString("catMathSymbols", comment: "")) static let catBracketKanjis = NSLocalizedString("catBracketKanjis", comment: "")
static let catCurrencyUnits = String( static let catSingleTableLines = NSLocalizedString("catSingleTableLines", comment: "")
format: NSLocalizedString("catCurrencyUnits", comment: "")) static let catDoubleTableLines = NSLocalizedString("catDoubleTableLines", comment: "")
static let catSpecialSymbols = String( static let catFillingBlocks = NSLocalizedString("catFillingBlocks", comment: "")
format: NSLocalizedString("catSpecialSymbols", comment: "")) static let catLineSegments = NSLocalizedString("catLineSegments", comment: "")
static let catUnicodeSymbols = String( static let catKana = NSLocalizedString("catKana", comment: "")
format: NSLocalizedString("catUnicodeSymbols", comment: "")) static let catCombinations = NSLocalizedString("catCombinations", comment: "")
static let catCircledKanjis = String( static let catPhonabets = NSLocalizedString("catPhonabets", comment: "")
format: NSLocalizedString("catCircledKanjis", comment: "")) static let catCircledASCII = NSLocalizedString("catCircledASCII", comment: "")
static let catCircledKataKana = String( static let catBracketedASCII = NSLocalizedString("catBracketedASCII", comment: "")
format: NSLocalizedString("catCircledKataKana", comment: "")) static let catMusicSymbols = NSLocalizedString("catMusicSymbols", comment: "")
static let catBracketKanjis = String( static let catThai = NSLocalizedString("catThai", comment: "")
format: NSLocalizedString("catBracketKanjis", comment: "")) static let catYi = NSLocalizedString("catYi", comment: "")
static let catSingleTableLines = String(
format: NSLocalizedString("catSingleTableLines", comment: ""))
static let catDoubleTableLines = String(
format: NSLocalizedString("catDoubleTableLines", comment: ""))
static let catFillingBlocks = String(
format: NSLocalizedString("catFillingBlocks", comment: ""))
static let catLineSegments = String(
format: NSLocalizedString("catLineSegments", comment: ""))
static let catKana = String(
format: NSLocalizedString("catKana", comment: ""))
static let catCombinations = String(
format: NSLocalizedString("catCombinations", comment: ""))
static let catPhonabets = String(
format: NSLocalizedString("catPhonabets", comment: ""))
static let catCircledASCII = String(
format: NSLocalizedString("catCircledASCII", comment: ""))
static let catBracketedASCII = String(
format: NSLocalizedString("catBracketedASCII", comment: ""))
static let catMusicSymbols = String(
format: NSLocalizedString("catMusicSymbols", comment: ""))
static let catThai = String(
format: NSLocalizedString("catThai", comment: ""))
static let catYi = String(
format: NSLocalizedString("catYi", comment: ""))
private(set) static var root: SymbolNode = .init("/") private(set) static var root: SymbolNode = .init("/")

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// StringView Ranges extension by (c) 2022 and onwards Isaac Xen (MIT License). // StringView Ranges extension by (c) 2022 and onwards Isaac Xen (MIT License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// StringView Ranges extension by (c) 2022 and onwards Isaac Xen (MIT License). // StringView Ranges extension by (c) 2022 and onwards Isaac Xen (MIT License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that: // ... with NTL restriction stating that:

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// StringView Ranges extension by (c) 2022 and onwards Isaac Xen (MIT License). // StringView Ranges extension by (c) 2022 and onwards Isaac Xen (MIT License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// StringView Ranges extension by (c) 2022 and onwards Isaac Xen (MIT License). // StringView Ranges extension by (c) 2022 and onwards Isaac Xen (MIT License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// Refactored from the Cpp version of this class by Mengjuei Hsieh (MIT License). // Refactored from the Cpp version of this class by Mengjuei Hsieh (MIT License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// Refactored from the ObjCpp-version of this class by: // Refactored from the ObjCpp-version of this class by:
// (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// ==================== // ====================
@ -63,28 +63,20 @@ enum mgrLangModel {
} }
if !gLangModelCHT.isLanguageModelLoaded { if !gLangModelCHT.isLanguageModelLoaded {
NotifierController.notify( NotifierController.notify(
message: String( message: NSLocalizedString("Loading CHT Core Dict...", comment: "")
format: "%@", NSLocalizedString("Loading CHT Core Dict...", comment: "")
)
) )
loadCoreLanguageModelFile(filenameSansExtension: "data-cht", langModel: &gLangModelCHT) loadCoreLanguageModelFile(filenameSansExtension: "data-cht", langModel: &gLangModelCHT)
NotifierController.notify( NotifierController.notify(
message: String( message: NSLocalizedString("Core Dict loading complete.", comment: "")
format: "%@", NSLocalizedString("Core Dict loading complete.", comment: "")
)
) )
} }
if !gLangModelCHS.isLanguageModelLoaded { if !gLangModelCHS.isLanguageModelLoaded {
NotifierController.notify( NotifierController.notify(
message: String( message: NSLocalizedString("Loading CHS Core Dict...", comment: "")
format: "%@", NSLocalizedString("Loading CHS Core Dict...", comment: "")
)
) )
loadCoreLanguageModelFile(filenameSansExtension: "data-chs", langModel: &gLangModelCHS) loadCoreLanguageModelFile(filenameSansExtension: "data-chs", langModel: &gLangModelCHS)
NotifierController.notify( NotifierController.notify(
message: String( message: NSLocalizedString("Core Dict loading complete.", comment: "")
format: "%@", NSLocalizedString("Core Dict loading complete.", comment: "")
)
) )
} }
} }
@ -102,15 +94,11 @@ enum mgrLangModel {
} }
if !gLangModelCHS.isLanguageModelLoaded { if !gLangModelCHS.isLanguageModelLoaded {
NotifierController.notify( NotifierController.notify(
message: String( message: NSLocalizedString("Loading CHS Core Dict...", comment: "")
format: "%@", NSLocalizedString("Loading CHS Core Dict...", comment: "")
)
) )
loadCoreLanguageModelFile(filenameSansExtension: "data-chs", langModel: &gLangModelCHS) loadCoreLanguageModelFile(filenameSansExtension: "data-chs", langModel: &gLangModelCHS)
NotifierController.notify( NotifierController.notify(
message: String( message: NSLocalizedString("Core Dict loading complete.", comment: "")
format: "%@", NSLocalizedString("Core Dict loading complete.", comment: "")
)
) )
} }
} else if mode == InputMode.imeModeCHT { } else if mode == InputMode.imeModeCHT {
@ -125,15 +113,11 @@ enum mgrLangModel {
} }
if !gLangModelCHT.isLanguageModelLoaded { if !gLangModelCHT.isLanguageModelLoaded {
NotifierController.notify( NotifierController.notify(
message: String( message: NSLocalizedString("Loading CHT Core Dict...", comment: "")
format: "%@", NSLocalizedString("Loading CHT Core Dict...", comment: "")
)
) )
loadCoreLanguageModelFile(filenameSansExtension: "data-cht", langModel: &gLangModelCHT) loadCoreLanguageModelFile(filenameSansExtension: "data-cht", langModel: &gLangModelCHT)
NotifierController.notify( NotifierController.notify(
message: String( message: NSLocalizedString("Core Dict loading complete.", comment: "")
format: "%@", NSLocalizedString("Core Dict loading complete.", comment: "")
)
) )
} }
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that: // ... with NTL restriction stating that:

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that: // ... with NTL restriction stating that:
@ -206,25 +206,24 @@ public class ctlCandidateIMK: IMKCandidates, ctlCandidateProtocol {
// Objective-C nil // Objective-C nil
guard !eventArray.isEmpty else { return } guard !eventArray.isEmpty else { return }
let event = eventArray[0] let event = eventArray[0]
let input = InputSignal(event: event)
guard let delegate = delegate else { return } guard let delegate = delegate else { return }
if input.isEsc || input.isBackSpace || input.isDelete || (input.isShiftHold && !input.isSpace) { if event.isEsc || event.isBackSpace || event.isDelete || (event.isShiftHold && !event.isSpace) {
_ = delegate.sharedEventHandler(event) _ = delegate.sharedEventHandler(event)
} else if input.isSymbolMenuPhysicalKey { } else if event.isSymbolMenuPhysicalKey {
// //
switch currentLayout { switch currentLayout {
case .horizontal: input.isShiftHold ? moveUp(self) : moveDown(self) case .horizontal: event.isShiftHold ? moveUp(self) : moveDown(self)
case .vertical: input.isShiftHold ? moveLeft(self) : moveRight(self) case .vertical: event.isShiftHold ? moveLeft(self) : moveRight(self)
} }
} else if input.isSpace { } else if event.isSpace {
switch mgrPrefs.specifyShiftSpaceKeyBehavior { switch mgrPrefs.specifyShiftSpaceKeyBehavior {
case true: _ = input.isShiftHold ? highlightNextCandidate() : showNextPage() case true: _ = event.isShiftHold ? highlightNextCandidate() : showNextPage()
case false: _ = input.isShiftHold ? showNextPage() : highlightNextCandidate() case false: _ = event.isShiftHold ? showNextPage() : highlightNextCandidate()
} }
} else if input.isTab { } else if event.isTab {
switch mgrPrefs.specifyShiftTabKeyBehavior { switch mgrPrefs.specifyShiftTabKeyBehavior {
case true: _ = input.isShiftHold ? showPreviousPage() : showNextPage() case true: _ = event.isShiftHold ? showPreviousPage() : showNextPage()
case false: _ = input.isShiftHold ? highlightPreviousCandidate() : highlightNextCandidate() case false: _ = event.isShiftHold ? highlightPreviousCandidate() : highlightNextCandidate()
} }
} else { } else {
if let newChar = ctlCandidateIMK.defaultIMKSelectionKey[event.keyCode] { if let newChar = ctlCandidateIMK.defaultIMKSelectionKey[event.keyCode] {
@ -245,7 +244,7 @@ public class ctlCandidateIMK: IMKCandidates, ctlCandidateProtocol {
if let newEvent = newEvent { if let newEvent = newEvent {
if mgrPrefs.useSCPCTypingMode, delegate.isAssociatedPhrasesState { if mgrPrefs.useSCPCTypingMode, delegate.isAssociatedPhrasesState {
// input.isShiftHold ctlInputMethod.handle() // input.isShiftHold ctlInputMethod.handle()
if !input.isShiftHold { if !event.isShiftHold {
_ = delegate.sharedEventHandler(event) _ = delegate.sharedEventHandler(event)
return return
} }
@ -256,15 +255,15 @@ public class ctlCandidateIMK: IMKCandidates, ctlCandidateProtocol {
} }
} }
if mgrPrefs.useSCPCTypingMode, !input.isReservedKey { if mgrPrefs.useSCPCTypingMode, !event.isReservedKey {
_ = delegate.sharedEventHandler(event) _ = delegate.sharedEventHandler(event)
return return
} }
if delegate.isAssociatedPhrasesState, if delegate.isAssociatedPhrasesState,
!input.isPageUp, !input.isPageDown, !input.isCursorForward, !input.isCursorBackward, !event.isPageUp, !event.isPageDown, !event.isCursorForward, !event.isCursorBackward,
!input.isCursorClockLeft, !input.isCursorClockRight, !input.isSpace, !event.isCursorClockLeft, !event.isCursorClockRight, !event.isSpace,
!input.isEnter || !mgrPrefs.alsoConfirmAssociatedCandidatesByEnter !event.isEnter || !mgrPrefs.alsoConfirmAssociatedCandidatesByEnter
{ {
_ = delegate.sharedEventHandler(event) _ = delegate.sharedEventHandler(event)
return return

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards Weizhong Yang (MIT License). // (c) 2021 and onwards Weizhong Yang (MIT License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that: // ... with NTL restriction stating that:

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that: // ... with NTL restriction stating that:
@ -14,8 +14,8 @@ struct suiPrefPaneDevZone: View {
forKey: UserDef.kUseIMKCandidateWindow.rawValue) forKey: UserDef.kUseIMKCandidateWindow.rawValue)
@State private var selHandleDefaultCandidateFontsByLangIdentifier: Bool = UserDefaults.standard.bool( @State private var selHandleDefaultCandidateFontsByLangIdentifier: Bool = UserDefaults.standard.bool(
forKey: UserDef.kHandleDefaultCandidateFontsByLangIdentifier.rawValue) forKey: UserDef.kHandleDefaultCandidateFontsByLangIdentifier.rawValue)
@State private var selShouldAlwaysUseShiftKeyAccommodation: Bool = UserDefaults.standard.bool( @State private var selShiftKeyAccommodationBehavior: Int = UserDefaults.standard.integer(
forKey: UserDef.kShouldAlwaysUseShiftKeyAccommodation.rawValue) forKey: UserDef.kShiftKeyAccommodationBehavior.rawValue)
private let contentMaxHeight: Double = 432 private let contentMaxHeight: Double = 432
private let contentWidth: Double = { private let contentWidth: Double = {
@ -68,23 +68,28 @@ struct suiPrefPaneDevZone: View {
mgrPrefs.handleDefaultCandidateFontsByLangIdentifier = selHandleDefaultCandidateFontsByLangIdentifier mgrPrefs.handleDefaultCandidateFontsByLangIdentifier = selHandleDefaultCandidateFontsByLangIdentifier
} }
) )
.disabled(!isMontereyOrAbove)
Text( Text(
LocalizedStringKey( LocalizedStringKey(
"This only works since macOS 12 with non-IMK candidate window as an alternative wordaround of Apple Bug Report #FB10978412. Apple should patch that for macOS 11 and later." "This only works since macOS 12 with non-IMK candidate window as an alternative wordaround of Apple Bug Report #FB10978412. Apple should patch that for macOS 11 and later."
) )
) )
.preferenceDescription().fixedSize(horizontal: false, vertical: true) .preferenceDescription().fixedSize(horizontal: false, vertical: true)
.disabled(!isMontereyOrAbove) Picker(
Toggle( "",
LocalizedStringKey("Use Shift Key Accommodation in all cases"), selection: $selShiftKeyAccommodationBehavior.onChange {
isOn: $selShouldAlwaysUseShiftKeyAccommodation.onChange { mgrPrefs.shiftKeyAccommodationBehavior = selShiftKeyAccommodationBehavior
mgrPrefs.shouldAlwaysUseShiftKeyAccommodation = selShouldAlwaysUseShiftKeyAccommodation
} }
) ) {
.disabled(mgrPrefs.disableShiftTogglingAlphanumericalMode) Text(LocalizedStringKey("Disable Shift key accomodation in all cases")).tag(0)
Text(LocalizedStringKey("Only use this with known Chromium-based browsers")).tag(1)
Text(LocalizedStringKey("Use Shift key accommodation in all cases")).tag(2)
}
.labelsHidden()
.pickerStyle(RadioGroupPickerStyle())
Text( Text(
LocalizedStringKey( LocalizedStringKey(
"Some client apps (like Chromium-cored browsers: MS Edge, Google Chrome, etc.) may duplicate Shift-key inputs due to their internal bugs, and their devs are less likely to fix their bugs of such. vChewing has its accommodation procedures enabled by default for known Chromium-cored browsers. If you want the same accommodation for other client apps, please tick this checkbox on." "Some client apps (like Chromium-cored browsers: MS Edge, Google Chrome, etc.) may duplicate Shift-key inputs due to their internal bugs, and their devs are less likely to fix their bugs of such. vChewing has its accommodation procedures enabled by default for known Chromium-cored browsers. Here you can customize how the accommodation should work."
) )
) )
.preferenceDescription().fixedSize(horizontal: false, vertical: true) .preferenceDescription().fixedSize(horizontal: false, vertical: true)

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that: // ... with NTL restriction stating that:

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that: // ... with NTL restriction stating that:

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that: // ... with NTL restriction stating that:

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that: // ... with NTL restriction stating that:

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards Weizhong Yang (MIT License). // (c) 2021 and onwards Weizhong Yang (MIT License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================

View File

@ -187,7 +187,7 @@
"Show Hanyu-Pinyin in the inline composition buffer & tooltip" = "Show Hanyu-Pinyin in the inline composition buffer & tooltip"; "Show Hanyu-Pinyin in the inline composition buffer & tooltip" = "Show Hanyu-Pinyin in the inline composition buffer & tooltip";
"Show page buttons in candidate window" = "Show page buttons in candidate window"; "Show page buttons in candidate window" = "Show page buttons in candidate window";
"Simplified Chinese" = "Simplified Chinese"; "Simplified Chinese" = "Simplified Chinese";
"Some client apps (like Chromium-cored browsers: MS Edge, Google Chrome, etc.) may duplicate Shift-key inputs due to their internal bugs, and their devs are less likely to fix their bugs of such. vChewing has its accommodation procedures enabled by default for known Chromium-cored browsers. If you want the same accommodation for other client apps, please tick this checkbox on." = "Some client apps (like Chromium-cored browsers: MS Edge, Google Chrome, etc.) may duplicate Shift-key inputs due to their internal bugs, and their devs are less likely to fix their bugs of such. vChewing has its accommodation procedures enabled by default for known Chromium-cored browsers. If you want the same accommodation for other client apps, please tick this checkbox on."; "Some client apps (like Chromium-cored browsers: MS Edge, Google Chrome, etc.) may duplicate Shift-key inputs due to their internal bugs, and their devs are less likely to fix their bugs of such. vChewing has its accommodation procedures enabled by default for known Chromium-cored browsers. Here you can customize how the accommodation should work." = "Some client apps (like Chromium-cored browsers: MS Edge, Google Chrome, etc.) may duplicate Shift-key inputs due to their internal bugs, and their devs are less likely to fix their bugs of such. vChewing has its accommodation procedures enabled by default for known Chromium-cored browsers. Here you can customize how the accommodation should work.";
"Space to +cycle candidates, Shift+Space to +cycle pages" = "Space to +cycle candidates, Shift+Space to +cycle pages"; "Space to +cycle candidates, Shift+Space to +cycle pages" = "Space to +cycle candidates, Shift+Space to +cycle pages";
"Space to +cycle pages, Shift+Space to +cycle candidates" = "Space to +cycle pages, Shift+Space to +cycle candidates"; "Space to +cycle pages, Shift+Space to +cycle candidates" = "Space to +cycle pages, Shift+Space to +cycle candidates";
"Specify the behavior of intonation key when syllable composer is empty." = "Specify the behavior of intonation key when syllable composer is empty."; "Specify the behavior of intonation key when syllable composer is empty." = "Specify the behavior of intonation key when syllable composer is empty.";
@ -203,8 +203,10 @@
"Use .langIdentifier to handle UI fonts in candidate window" = "Use .langIdentifier to handle UI fonts in candidate window"; "Use .langIdentifier to handle UI fonts in candidate window" = "Use .langIdentifier to handle UI fonts in candidate window";
"Use ESC key to clear the entire input buffer" = "Use ESC key to clear the entire input buffer"; "Use ESC key to clear the entire input buffer" = "Use ESC key to clear the entire input buffer";
"Use IMK Candidate Window instead (will reboot the IME)" = "Use IMK Candidate Window instead (will reboot the IME)"; "Use IMK Candidate Window instead (will reboot the IME)" = "Use IMK Candidate Window instead (will reboot the IME)";
"Use Shift Key Accommodation in all cases" = "Use Shift Key Accommodation in all cases"; "Use Shift key accommodation in all cases" = "Use Shift key accommodation in all cases";
"Vertical" = "Vertical"; "Vertical" = "Vertical";
"Warning: This page is for testing future features. \nFeatures listed here may not work as expected." = "Warning: This page is for testing future features. \nFeatures listed here may not work as expected."; "Warning: This page is for testing future features. \nFeatures listed here may not work as expected." = "Warning: This page is for testing future features. \nFeatures listed here may not work as expected.";
"For example: When typing “章太炎” and you want to override the “太” with “泰”, and the raw operation index range [1,2) which bounds are cutting the current node “章太炎” in range [0,3). If having lack of the pre-consolidation process, this word will become something like “張泰言” after the candidate selection. Only if we enable this consolidation, this word will become “章泰炎” which is the expected result that the context is kept as-is." = "For example: When typing “章太炎” and you want to override the “太” with “泰”, and the raw operation index range [1,2) which bounds are cutting the current node “章太炎” in range [0,3). If having lack of the pre-consolidation process, this word will become something like “張泰言” after the candidate selection. Only if we enable this consolidation, this word will become “章泰炎” which is the expected result that the context is kept as-is."; "For example: When typing “章太炎” and you want to override the “太” with “泰”, and the raw operation index range [1,2) which bounds are cutting the current node “章太炎” in range [0,3). If having lack of the pre-consolidation process, this word will become something like “張泰言” after the candidate selection. Only if we enable this consolidation, this word will become “章泰炎” which is the expected result that the context is kept as-is." = "For example: When typing “章太炎” and you want to override the “太” with “泰”, and the raw operation index range [1,2) which bounds are cutting the current node “章太炎” in range [0,3). If having lack of the pre-consolidation process, this word will become something like “張泰言” after the candidate selection. Only if we enable this consolidation, this word will become “章泰炎” which is the expected result that the context is kept as-is.";
"Yale Pinyin with Numeral Intonation" = "Yale Pinyin with Numeral Intonation"; "Yale Pinyin with Numeral Intonation" = "Yale Pinyin with Numeral Intonation";
"Only use this with known Chromium-based browsers" = "Only use this with known Chromium-based browsers";
"Disable Shift key accomodation in all cases" = "Disable Shift key accomodation in all cases";

View File

@ -187,7 +187,7 @@
"Show Hanyu-Pinyin in the inline composition buffer & tooltip" = "Show Hanyu-Pinyin in the inline composition buffer & tooltip"; "Show Hanyu-Pinyin in the inline composition buffer & tooltip" = "Show Hanyu-Pinyin in the inline composition buffer & tooltip";
"Show page buttons in candidate window" = "Show page buttons in candidate window"; "Show page buttons in candidate window" = "Show page buttons in candidate window";
"Simplified Chinese" = "Simplified Chinese"; "Simplified Chinese" = "Simplified Chinese";
"Some client apps (like Chromium-cored browsers: MS Edge, Google Chrome, etc.) may duplicate Shift-key inputs due to their internal bugs, and their devs are less likely to fix their bugs of such. vChewing has its accommodation procedures enabled by default for known Chromium-cored browsers. If you want the same accommodation for other client apps, please tick this checkbox on." = "Some client apps (like Chromium-cored browsers: MS Edge, Google Chrome, etc.) may duplicate Shift-key inputs due to their internal bugs, and their devs are less likely to fix their bugs of such. vChewing has its accommodation procedures enabled by default for known Chromium-cored browsers. If you want the same accommodation for other client apps, please tick this checkbox on."; "Some client apps (like Chromium-cored browsers: MS Edge, Google Chrome, etc.) may duplicate Shift-key inputs due to their internal bugs, and their devs are less likely to fix their bugs of such. vChewing has its accommodation procedures enabled by default for known Chromium-cored browsers. Here you can customize how the accommodation should work." = "Some client apps (like Chromium-cored browsers: MS Edge, Google Chrome, etc.) may duplicate Shift-key inputs due to their internal bugs, and their devs are less likely to fix their bugs of such. vChewing has its accommodation procedures enabled by default for known Chromium-cored browsers. Here you can customize how the accommodation should work.";
"Space to +cycle candidates, Shift+Space to +cycle pages" = "Space to +cycle candidates, Shift+Space to +cycle pages"; "Space to +cycle candidates, Shift+Space to +cycle pages" = "Space to +cycle candidates, Shift+Space to +cycle pages";
"Space to +cycle pages, Shift+Space to +cycle candidates" = "Space to +cycle pages, Shift+Space to +cycle candidates"; "Space to +cycle pages, Shift+Space to +cycle candidates" = "Space to +cycle pages, Shift+Space to +cycle candidates";
"Specify the behavior of intonation key when syllable composer is empty." = "Specify the behavior of intonation key when syllable composer is empty."; "Specify the behavior of intonation key when syllable composer is empty." = "Specify the behavior of intonation key when syllable composer is empty.";
@ -203,8 +203,10 @@
"Use .langIdentifier to handle UI fonts in candidate window" = "Use .langIdentifier to handle UI fonts in candidate window"; "Use .langIdentifier to handle UI fonts in candidate window" = "Use .langIdentifier to handle UI fonts in candidate window";
"Use ESC key to clear the entire input buffer" = "Use ESC key to clear the entire input buffer"; "Use ESC key to clear the entire input buffer" = "Use ESC key to clear the entire input buffer";
"Use IMK Candidate Window instead (will reboot the IME)" = "Use IMK Candidate Window instead (will reboot the IME)"; "Use IMK Candidate Window instead (will reboot the IME)" = "Use IMK Candidate Window instead (will reboot the IME)";
"Use Shift Key Accommodation in all cases" = "Use Shift Key Accommodation in all cases"; "Use Shift key accommodation in all cases" = "Use Shift key accommodation in all cases";
"Vertical" = "Vertical"; "Vertical" = "Vertical";
"Warning: This page is for testing future features. \nFeatures listed here may not work as expected." = "Warning: This page is for testing future features. \nFeatures listed here may not work as expected."; "Warning: This page is for testing future features. \nFeatures listed here may not work as expected." = "Warning: This page is for testing future features. \nFeatures listed here may not work as expected.";
"For example: When typing “章太炎” and you want to override the “太” with “泰”, and the raw operation index range [1,2) which bounds are cutting the current node “章太炎” in range [0,3). If having lack of the pre-consolidation process, this word will become something like “張泰言” after the candidate selection. Only if we enable this consolidation, this word will become “章泰炎” which is the expected result that the context is kept as-is." = "For example: When typing “章太炎” and you want to override the “太” with “泰”, and the raw operation index range [1,2) which bounds are cutting the current node “章太炎” in range [0,3). If having lack of the pre-consolidation process, this word will become something like “張泰言” after the candidate selection. Only if we enable this consolidation, this word will become “章泰炎” which is the expected result that the context is kept as-is."; "For example: When typing “章太炎” and you want to override the “太” with “泰”, and the raw operation index range [1,2) which bounds are cutting the current node “章太炎” in range [0,3). If having lack of the pre-consolidation process, this word will become something like “張泰言” after the candidate selection. Only if we enable this consolidation, this word will become “章泰炎” which is the expected result that the context is kept as-is." = "For example: When typing “章太炎” and you want to override the “太” with “泰”, and the raw operation index range [1,2) which bounds are cutting the current node “章太炎” in range [0,3). If having lack of the pre-consolidation process, this word will become something like “張泰言” after the candidate selection. Only if we enable this consolidation, this word will become “章泰炎” which is the expected result that the context is kept as-is.";
"Yale Pinyin with Numeral Intonation" = "Yale Pinyin with Numeral Intonation"; "Yale Pinyin with Numeral Intonation" = "Yale Pinyin with Numeral Intonation";
"Only use this with known Chromium-based browsers" = "Only use this with known Chromium-based browsers";
"Disable Shift key accomodation in all cases" = "Disable Shift key accomodation in all cases";

View File

@ -187,7 +187,7 @@
"Show Hanyu-Pinyin in the inline composition buffer & tooltip" = "弁音合併入力(入力緩衝列とヒントで音読みを漢語弁音に)"; "Show Hanyu-Pinyin in the inline composition buffer & tooltip" = "弁音合併入力(入力緩衝列とヒントで音読みを漢語弁音に)";
"Show page buttons in candidate window" = "入力候補陳列の側にページボタンを表示"; "Show page buttons in candidate window" = "入力候補陳列の側にページボタンを表示";
"Simplified Chinese" = "簡体中国語"; "Simplified Chinese" = "簡体中国語";
"Some client apps (like Chromium-cored browsers: MS Edge, Google Chrome, etc.) may duplicate Shift-key inputs due to their internal bugs, and their devs are less likely to fix their bugs of such. vChewing has its accommodation procedures enabled by default for known Chromium-cored browsers. If you want the same accommodation for other client apps, please tick this checkbox on." = "いくつかのアプリ(例えば MS Edge や Google Chrome などのような Chromium 系ブラウザーには「Shift キーの入力イベントを複数化してしまう」という支障があり、そしてアプリそれぞれの開発元に修復される可能性はほぼゼロだと言える。威注音入力アプリは対策用の特殊措置を普段に起用している。別のアプリにも同じ特殊措置が欲しければ、これをチェックしてください。"; "Some client apps (like Chromium-cored browsers: MS Edge, Google Chrome, etc.) may duplicate Shift-key inputs due to their internal bugs, and their devs are less likely to fix their bugs of such. vChewing has its accommodation procedures enabled by default for known Chromium-cored browsers. Here you can customize how the accommodation should work." = "いくつかのアプリ(例えば MS Edge や Google Chrome などのような Chromium 系ブラウザーには「Shift キーの入力イベントを複数化してしまう」という支障があり、そしてアプリそれぞれの開発元に修復される可能性はほぼゼロだと言える。威注音入力アプリは対策用の特殊措置を普段に起用している。ご自分の必要によって設定してください。";
"Space to +cycle candidates, Shift+Space to +cycle pages" = "Shift+Space で次のページ、Space で次の候補文字を"; "Space to +cycle candidates, Shift+Space to +cycle pages" = "Shift+Space で次のページ、Space で次の候補文字を";
"Space to +cycle pages, Shift+Space to +cycle candidates" = "Space で次のページ、Shift+Space で次の候補文字を"; "Space to +cycle pages, Shift+Space to +cycle candidates" = "Space で次のページ、Shift+Space で次の候補文字を";
"Specify the behavior of intonation key when syllable composer is empty." = "音読組立緩衝列が空かされた時の音調キーの行為をご指定ください。"; "Specify the behavior of intonation key when syllable composer is empty." = "音読組立緩衝列が空かされた時の音調キーの行為をご指定ください。";
@ -203,8 +203,10 @@
"Use .langIdentifier to handle UI fonts in candidate window" = "「.langIdentifier」を使って候補陳列ウィンドウのフォントを取り扱う"; "Use .langIdentifier to handle UI fonts in candidate window" = "「.langIdentifier」を使って候補陳列ウィンドウのフォントを取り扱う";
"Use ESC key to clear the entire input buffer" = "ESC キーで入力緩衝列を消す"; "Use ESC key to clear the entire input buffer" = "ESC キーで入力緩衝列を消す";
"Use IMK Candidate Window instead (will reboot the IME)" = "IMK 候補陳列ウィンドウを起用(入力アプリは自動的に再起動)"; "Use IMK Candidate Window instead (will reboot the IME)" = "IMK 候補陳列ウィンドウを起用(入力アプリは自動的に再起動)";
"Use Shift Key Accommodation in all cases" = "いずれの客体アプリにも Shift キーの互換性措置を起用"; "Use Shift key accommodation in all cases" = "いずれの客体アプリにも Shift キーの互換性措置を起用";
"Vertical" = "縦型陳列"; "Vertical" = "縦型陳列";
"Warning: This page is for testing future features. \nFeatures listed here may not work as expected." = "警告:これからの新機能テストのために作ったページですから、\nここで陳列されている諸機能は予想通り動けるだと思わないでください。"; "Warning: This page is for testing future features. \nFeatures listed here may not work as expected." = "警告:これからの新機能テストのために作ったページですから、\nここで陳列されている諸機能は予想通り動けるだと思わないでください。";
"For example: When typing “章太炎” and you want to override the “太” with “泰”, and the raw operation index range [1,2) which bounds are cutting the current node “章太炎” in range [0,3). If having lack of the pre-consolidation process, this word will become something like “張泰言” after the candidate selection. Only if we enable this consolidation, this word will become “章泰炎” which is the expected result that the context is kept as-is." = "例えば、入力緩衝列には「章太炎」という節点があり、その範囲は [0,3) である。もし、「太」を「泰」にしたいのなら、今回の作業範囲は [1,2) で、「章太炎」の範囲と重ねてしまう。この場合、もし、事前強固措置がなければ、今回の作業でこの単語は「張泰言」のような望ましくない変換結果になってしまう。事前強固措置があるからこそ、「章泰炎」のような正確な作業結果の保証である。"; "For example: When typing “章太炎” and you want to override the “太” with “泰”, and the raw operation index range [1,2) which bounds are cutting the current node “章太炎” in range [0,3). If having lack of the pre-consolidation process, this word will become something like “張泰言” after the candidate selection. Only if we enable this consolidation, this word will become “章泰炎” which is the expected result that the context is kept as-is." = "例えば、入力緩衝列には「章太炎」という節点があり、その範囲は [0,3) である。もし、「太」を「泰」にしたいのなら、今回の作業範囲は [1,2) で、「章太炎」の範囲と重ねてしまう。この場合、もし、事前強固措置がなければ、今回の作業でこの単語は「張泰言」のような望ましくない変換結果になってしまう。事前強固措置があるからこそ、「章泰炎」のような正確な作業結果の保証である。";
"Yale Pinyin with Numeral Intonation" = "イェール弁音 (ローマ字+数字音調)"; "Yale Pinyin with Numeral Intonation" = "イェール弁音 (ローマ字+数字音調)";
"Only use this with known Chromium-based browsers" = "有名なる Chromium 系ブラウザーだけに、この装置を起用";
"Disable Shift key accomodation in all cases" = "いずれの客体アプリにも Shift キーの互換性措置を禁ず";

View File

@ -187,7 +187,7 @@
"Show Hanyu-Pinyin in the inline composition buffer & tooltip" = "拼音并击(组字区与工具提示内显示汉语拼音)"; "Show Hanyu-Pinyin in the inline composition buffer & tooltip" = "拼音并击(组字区与工具提示内显示汉语拼音)";
"Show page buttons in candidate window" = "在选字窗内显示翻页按钮"; "Show page buttons in candidate window" = "在选字窗内显示翻页按钮";
"Simplified Chinese" = "简体中文"; "Simplified Chinese" = "简体中文";
"Some client apps (like Chromium-cored browsers: MS Edge, Google Chrome, etc.) may duplicate Shift-key inputs due to their internal bugs, and their devs are less likely to fix their bugs of such. vChewing has its accommodation procedures enabled by default for known Chromium-cored browsers. If you want the same accommodation for other client apps, please tick this checkbox on." = "某些应用(比如像是 MS Edge 或者 Chrome 这样的 Chromium 核心的浏览器)可能会使输入的 Shift 按键讯号被重复输入,且其有关研发方很可能不打算修复这些产品缺陷。威注音针对这些应用预设启用了相容措施。如果您希望在任何应用当中都启用该措施的话,请勾选之。"; "Some client apps (like Chromium-cored browsers: MS Edge, Google Chrome, etc.) may duplicate Shift-key inputs due to their internal bugs, and their devs are less likely to fix their bugs of such. vChewing has its accommodation procedures enabled by default for known Chromium-cored browsers. Here you can customize how the accommodation should work." = "某些应用(比如像是 MS Edge 或者 Chrome 这样的 Chromium 核心的浏览器)可能会使输入的 Shift 按键讯号被重复输入,且其有关研发方很可能不打算修复这些产品缺陷。威注音针对这些应用预设启用了相容措施。请在此根据您的需求自订。";
"Space to +cycle candidates, Shift+Space to +cycle pages" = "Shift+空格键 换下一页,空格键 换选下一个候选字"; "Space to +cycle candidates, Shift+Space to +cycle pages" = "Shift+空格键 换下一页,空格键 换选下一个候选字";
"Space to +cycle pages, Shift+Space to +cycle candidates" = "空格键 换下一页Shift+空格键 换选下一个候选字"; "Space to +cycle pages, Shift+Space to +cycle candidates" = "空格键 换下一页Shift+空格键 换选下一个候选字";
"Specify the behavior of intonation key when syllable composer is empty." = "指定声调键(在注拼槽为「空」状态时)的行为。"; "Specify the behavior of intonation key when syllable composer is empty." = "指定声调键(在注拼槽为「空」状态时)的行为。";
@ -203,8 +203,10 @@
"Use .langIdentifier to handle UI fonts in candidate window" = "使用 .langIdentifier 来管理选字窗的预设介面字型"; "Use .langIdentifier to handle UI fonts in candidate window" = "使用 .langIdentifier 来管理选字窗的预设介面字型";
"Use ESC key to clear the entire input buffer" = "敲 ESC 键以清空整个组字缓冲区"; "Use ESC key to clear the entire input buffer" = "敲 ESC 键以清空整个组字缓冲区";
"Use IMK Candidate Window instead (will reboot the IME)" = "启用与 macOS 内建输入法相同的 IMK 选字窗(会自动重启输入法)"; "Use IMK Candidate Window instead (will reboot the IME)" = "启用与 macOS 内建输入法相同的 IMK 选字窗(会自动重启输入法)";
"Use Shift Key Accommodation in all cases" = "对任何客体应用均启用 Shift 键相容性措施"; "Use Shift key accommodation in all cases" = "对任何客体应用均启用 Shift 键相容性措施";
"Vertical" = "纵向布局"; "Vertical" = "纵向布局";
"Warning: This page is for testing future features. \nFeatures listed here may not work as expected." = "警告:该页面仅作未来功能测试所用。\n在此列出的功能并非处于完全可用之状态。"; "Warning: This page is for testing future features. \nFeatures listed here may not work as expected." = "警告:该页面仅作未来功能测试所用。\n在此列出的功能并非处于完全可用之状态。";
"For example: When typing “章太炎” and you want to override the “太” with “泰”, and the raw operation index range [1,2) which bounds are cutting the current node “章太炎” in range [0,3). If having lack of the pre-consolidation process, this word will become something like “張泰言” after the candidate selection. Only if we enable this consolidation, this word will become “章泰炎” which is the expected result that the context is kept as-is." = "打比方说,你敲了「章太炎」,你想将「太」改成「泰」。这个操作的作业索引范围是开闭区间 [1,2),会切到「章太炎」这个节点的所在索引范围 [0,3)。如果没有事前巩固处理的话,这个词会在你选字之后变成诸如「张泰言」这种你不想要的自动选字结果。当且仅当你启用了这个巩固功能的前提下,你选字之后的结果才会是「章泰炎」这种你想要的结果。"; "For example: When typing “章太炎” and you want to override the “太” with “泰”, and the raw operation index range [1,2) which bounds are cutting the current node “章太炎” in range [0,3). If having lack of the pre-consolidation process, this word will become something like “張泰言” after the candidate selection. Only if we enable this consolidation, this word will become “章泰炎” which is the expected result that the context is kept as-is." = "打比方说,你敲了「章太炎」,你想将「太」改成「泰」。这个操作的作业索引范围是开闭区间 [1,2),会切到「章太炎」这个节点的所在索引范围 [0,3)。如果没有事前巩固处理的话,这个词会在你选字之后变成诸如「张泰言」这种你不想要的自动选字结果。当且仅当你启用了这个巩固功能的前提下,你选字之后的结果才会是「章泰炎」这种你想要的结果。";
"Yale Pinyin with Numeral Intonation" = "耶鲁拼音+数字标调"; "Yale Pinyin with Numeral Intonation" = "耶鲁拼音+数字标调";
"Only use this with known Chromium-based browsers" = "仅针对知名的 Chromium 核心的浏览器启用该措施";
"Disable Shift key accomodation in all cases" = "对任何客体应用均停用 Shift 键相容性措施";

View File

@ -187,7 +187,7 @@
"Show Hanyu-Pinyin in the inline composition buffer & tooltip" = "拼音並擊(組字區與工具提示內顯示漢語拼音)"; "Show Hanyu-Pinyin in the inline composition buffer & tooltip" = "拼音並擊(組字區與工具提示內顯示漢語拼音)";
"Show page buttons in candidate window" = "在選字窗內顯示翻頁按鈕"; "Show page buttons in candidate window" = "在選字窗內顯示翻頁按鈕";
"Simplified Chinese" = "簡體中文"; "Simplified Chinese" = "簡體中文";
"Some client apps (like Chromium-cored browsers: MS Edge, Google Chrome, etc.) may duplicate Shift-key inputs due to their internal bugs, and their devs are less likely to fix their bugs of such. vChewing has its accommodation procedures enabled by default for known Chromium-cored browsers. If you want the same accommodation for other client apps, please tick this checkbox on." = "某些應用(比如像是 MS Edge 或者 Chrome 這樣的 Chromium 核心的瀏覽器)可能會使輸入的 Shift 按鍵訊號被重複輸入,且其有關研發方很可能不打算修復這些產品缺陷。威注音針對這些應用預設啟用了相容措施。如果您希望在任何應用當中都啟用該措施的話,請勾選之。"; "Some client apps (like Chromium-cored browsers: MS Edge, Google Chrome, etc.) may duplicate Shift-key inputs due to their internal bugs, and their devs are less likely to fix their bugs of such. vChewing has its accommodation procedures enabled by default for known Chromium-cored browsers. Here you can customize how the accommodation should work." = "某些應用(比如像是 MS Edge 或者 Chrome 這樣的 Chromium 核心的瀏覽器)可能會使輸入的 Shift 按鍵訊號被重複輸入,且其有關研發方很可能不打算修復這些產品缺陷。威注音針對這些應用預設啟用了相容措施。請在此根據您的需求自訂。";
"Space to +cycle candidates, Shift+Space to +cycle pages" = "Shift+空格鍵 換下一頁,空格鍵 換選下一個候選字"; "Space to +cycle candidates, Shift+Space to +cycle pages" = "Shift+空格鍵 換下一頁,空格鍵 換選下一個候選字";
"Space to +cycle pages, Shift+Space to +cycle candidates" = "空格鍵 換下一頁Shift+空格鍵 換選下一個候選字"; "Space to +cycle pages, Shift+Space to +cycle candidates" = "空格鍵 換下一頁Shift+空格鍵 換選下一個候選字";
"Specify the behavior of intonation key when syllable composer is empty." = "指定聲調鍵(在注拼槽為「空」狀態時)的行為。"; "Specify the behavior of intonation key when syllable composer is empty." = "指定聲調鍵(在注拼槽為「空」狀態時)的行為。";
@ -203,8 +203,10 @@
"Use .langIdentifier to handle UI fonts in candidate window" = "使用 .langIdentifier 來管理選字窗的預設介面字型"; "Use .langIdentifier to handle UI fonts in candidate window" = "使用 .langIdentifier 來管理選字窗的預設介面字型";
"Use ESC key to clear the entire input buffer" = "敲 ESC 鍵以清空整個組字緩衝區"; "Use ESC key to clear the entire input buffer" = "敲 ESC 鍵以清空整個組字緩衝區";
"Use IMK Candidate Window instead (will reboot the IME)" = "啟用與 macOS 內建輸入法相同的 IMK 選字窗(會自動重啟輸入法)"; "Use IMK Candidate Window instead (will reboot the IME)" = "啟用與 macOS 內建輸入法相同的 IMK 選字窗(會自動重啟輸入法)";
"Use Shift Key Accommodation in all cases" = "對任何客體應用均啟用 Shift 鍵相容性措施"; "Use Shift key accommodation in all cases" = "對任何客體應用均啟用 Shift 鍵相容性措施";
"Vertical" = "縱向佈局"; "Vertical" = "縱向佈局";
"Warning: This page is for testing future features. \nFeatures listed here may not work as expected." = "警告:該頁面僅作未來功能測試所用。\n在此列出的功能並非處於完全可用之狀態。"; "Warning: This page is for testing future features. \nFeatures listed here may not work as expected." = "警告:該頁面僅作未來功能測試所用。\n在此列出的功能並非處於完全可用之狀態。";
"For example: When typing “章太炎” and you want to override the “太” with “泰”, and the raw operation index range [1,2) which bounds are cutting the current node “章太炎” in range [0,3). If having lack of the pre-consolidation process, this word will become something like “張泰言” after the candidate selection. Only if we enable this consolidation, this word will become “章泰炎” which is the expected result that the context is kept as-is." = "打比方說,你敲了「章太炎」,你想將「太」改成「泰」。這個操作的作業索引範圍是開閉區間 [1,2),會切到「章太炎」這個節點的所在索引範圍 [0,3)。如果沒有事前鞏固處理的話,這個詞會在你選字之後變成諸如「張泰言」這種你不想要的自動選字結果。當且僅當你啟用了這個鞏固功能的前提下,你選字之後的結果才會是「章泰炎」這種你想要的結果。"; "For example: When typing “章太炎” and you want to override the “太” with “泰”, and the raw operation index range [1,2) which bounds are cutting the current node “章太炎” in range [0,3). If having lack of the pre-consolidation process, this word will become something like “張泰言” after the candidate selection. Only if we enable this consolidation, this word will become “章泰炎” which is the expected result that the context is kept as-is." = "打比方說,你敲了「章太炎」,你想將「太」改成「泰」。這個操作的作業索引範圍是開閉區間 [1,2),會切到「章太炎」這個節點的所在索引範圍 [0,3)。如果沒有事前鞏固處理的話,這個詞會在你選字之後變成諸如「張泰言」這種你不想要的自動選字結果。當且僅當你啟用了這個鞏固功能的前提下,你選字之後的結果才會是「章泰炎」這種你想要的結果。";
"Yale Pinyin with Numeral Intonation" = "耶魯拼音+數字標調"; "Yale Pinyin with Numeral Intonation" = "耶魯拼音+數字標調";
"Only use this with known Chromium-based browsers" = "僅針對知名的 Chromium 核心的瀏覽器啟用該措施";
"Disable Shift key accomodation in all cases" = "對任何客體應用均停用 Shift 鍵相容性措施";

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
@ -36,9 +36,7 @@ class ctlAboutWindow: NSWindowController {
if let eulaContent = Bundle.main.localizedInfoDictionary?["CFEULAContent"] as? String { if let eulaContent = Bundle.main.localizedInfoDictionary?["CFEULAContent"] as? String {
appEULAContent.string = eulaContent appEULAContent.string = eulaContent
} }
appVersionLabel.stringValue = String( appVersionLabel.stringValue = "\(versionString) Build \(installingVersion)"
format: "%@ Build %@", versionString, installingVersion
)
} }
@IBAction func btnBugReport(_: NSButton) { @IBAction func btnBugReport(_: NSButton) {

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
@ -100,15 +100,13 @@ class ctlPrefWindow: NSWindowController {
basicKeyboardLayoutButton.menu?.removeAllItems() basicKeyboardLayoutButton.menu?.removeAllItems()
let itmAppleZhuyinBopomofo = NSMenuItem() let itmAppleZhuyinBopomofo = NSMenuItem()
itmAppleZhuyinBopomofo.title = String( itmAppleZhuyinBopomofo.title = NSLocalizedString("Apple Zhuyin Bopomofo (Dachen)", comment: "")
format: NSLocalizedString("Apple Zhuyin Bopomofo (Dachen)", comment: ""))
itmAppleZhuyinBopomofo.representedObject = String( itmAppleZhuyinBopomofo.representedObject = String(
"com.apple.keylayout.ZhuyinBopomofo") "com.apple.keylayout.ZhuyinBopomofo")
basicKeyboardLayoutButton.menu?.addItem(itmAppleZhuyinBopomofo) basicKeyboardLayoutButton.menu?.addItem(itmAppleZhuyinBopomofo)
let itmAppleZhuyinEten = NSMenuItem() let itmAppleZhuyinEten = NSMenuItem()
itmAppleZhuyinEten.title = String( itmAppleZhuyinEten.title = NSLocalizedString("Apple Zhuyin Eten (Traditional)", comment: "")
format: NSLocalizedString("Apple Zhuyin Eten (Traditional)", comment: ""))
itmAppleZhuyinEten.representedObject = String("com.apple.keylayout.ZhuyinEten") itmAppleZhuyinEten.representedObject = String("com.apple.keylayout.ZhuyinEten")
basicKeyboardLayoutButton.menu?.addItem(itmAppleZhuyinEten) basicKeyboardLayoutButton.menu?.addItem(itmAppleZhuyinEten)

View File

@ -3,9 +3,9 @@
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>2.3.0</string> <string>2.3.1</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>2300</string> <string>2310</string>
<key>UpdateInfoEndpoint</key> <key>UpdateInfoEndpoint</key>
<string>https://gitee.com/vchewing/vChewing-macOS/raw/main/Update-Info.plist</string> <string>https://gitee.com/vchewing/vChewing-macOS/raw/main/Update-Info.plist</string>
<key>UpdateInfoSite</key> <key>UpdateInfoSite</key>

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that: // ... with NTL restriction stating that:

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that: // ... with NTL restriction stating that:

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that: // ... with NTL restriction stating that:

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that: // ... with NTL restriction stating that:

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that: // ... with NTL restriction stating that:

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that: // ... with NTL restriction stating that:

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). // (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
@ -36,9 +36,7 @@ import Cocoa
if let eulaContent = Bundle.main.localizedInfoDictionary?["CFEULAContent"] as? String { if let eulaContent = Bundle.main.localizedInfoDictionary?["CFEULAContent"] as? String {
appEULAContent.string = eulaContent appEULAContent.string = eulaContent
} }
appVersionLabel.stringValue = String( appVersionLabel.stringValue = "\(versionString) Build \(installingVersion)"
format: "%@ Build %@", versionString, installingVersion
)
} }
@IBAction func btnWebsite(_: NSButton) { @IBAction func btnWebsite(_: NSButton) {

View File

@ -726,7 +726,7 @@
<key>USE_HFS+_COMPRESSION</key> <key>USE_HFS+_COMPRESSION</key>
<false/> <false/>
<key>VERSION</key> <key>VERSION</key>
<string>2.3.0</string> <string>2.3.1</string>
</dict> </dict>
<key>TYPE</key> <key>TYPE</key>
<integer>0</integer> <integer>0</integer>

View File

@ -116,6 +116,7 @@
5BEDB723283B4C250078EB25 /* data-cht.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5BEDB720283B4AEA0078EB25 /* data-cht.plist */; }; 5BEDB723283B4C250078EB25 /* data-cht.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5BEDB720283B4AEA0078EB25 /* data-cht.plist */; };
5BEDB724283B4C250078EB25 /* data-symbols.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5BEDB71E283B4AEA0078EB25 /* data-symbols.plist */; }; 5BEDB724283B4C250078EB25 /* data-symbols.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5BEDB71E283B4AEA0078EB25 /* data-symbols.plist */; };
5BEDB725283B4C250078EB25 /* data-chs.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5BEDB71C283B4AEA0078EB25 /* data-chs.plist */; }; 5BEDB725283B4C250078EB25 /* data-chs.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5BEDB71C283B4AEA0078EB25 /* data-chs.plist */; };
5BF0B84C28C070B000795FC6 /* NSEventExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF0B84B28C070B000795FC6 /* NSEventExtension.swift */; };
5BF9DA2728840E6200DBD48E /* template-usersymbolphrases.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2228840E6200DBD48E /* template-usersymbolphrases.txt */; }; 5BF9DA2728840E6200DBD48E /* template-usersymbolphrases.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2228840E6200DBD48E /* template-usersymbolphrases.txt */; };
5BF9DA2828840E6200DBD48E /* template-exclusions.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2328840E6200DBD48E /* template-exclusions.txt */; }; 5BF9DA2828840E6200DBD48E /* template-exclusions.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2328840E6200DBD48E /* template-exclusions.txt */; };
5BF9DA2928840E6200DBD48E /* template-associatedPhrases-chs.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2428840E6200DBD48E /* template-associatedPhrases-chs.txt */; }; 5BF9DA2928840E6200DBD48E /* template-associatedPhrases-chs.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2428840E6200DBD48E /* template-associatedPhrases-chs.txt */; };
@ -133,7 +134,6 @@
6ACA41FD15FC1D9000935EF6 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6ACA41F015FC1D9000935EF6 /* MainMenu.xib */; }; 6ACA41FD15FC1D9000935EF6 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6ACA41F015FC1D9000935EF6 /* MainMenu.xib */; };
6ACA420215FC1E5200935EF6 /* vChewing.app in Resources */ = {isa = PBXBuildFile; fileRef = 6A0D4EA215FC0D2D00ABF4B3 /* vChewing.app */; }; 6ACA420215FC1E5200935EF6 /* vChewing.app in Resources */ = {isa = PBXBuildFile; fileRef = 6A0D4EA215FC0D2D00ABF4B3 /* vChewing.app */; };
D427F76C278CA2B0004A2160 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D427F76B278CA1BA004A2160 /* AppDelegate.swift */; }; D427F76C278CA2B0004A2160 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D427F76B278CA1BA004A2160 /* AppDelegate.swift */; };
D456576E279E4F7B00DF6BC9 /* InputSignal.swift in Sources */ = {isa = PBXBuildFile; fileRef = D456576D279E4F7B00DF6BC9 /* InputSignal.swift */; };
D461B792279DAC010070E734 /* InputState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D461B791279DAC010070E734 /* InputState.swift */; }; D461B792279DAC010070E734 /* InputState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D461B791279DAC010070E734 /* InputState.swift */; };
D47B92C027972AD100458394 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47B92BF27972AC800458394 /* main.swift */; }; D47B92C027972AD100458394 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47B92BF27972AC800458394 /* main.swift */; };
D47F7DCE278BFB57002F9DD7 /* ctlPrefWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47F7DCD278BFB57002F9DD7 /* ctlPrefWindow.swift */; }; D47F7DCE278BFB57002F9DD7 /* ctlPrefWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47F7DCD278BFB57002F9DD7 /* ctlPrefWindow.swift */; };
@ -344,6 +344,7 @@
5BEDB71E283B4AEA0078EB25 /* data-symbols.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; name = "data-symbols.plist"; path = "Data/data-symbols.plist"; sourceTree = "<group>"; }; 5BEDB71E283B4AEA0078EB25 /* data-symbols.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; name = "data-symbols.plist"; path = "Data/data-symbols.plist"; sourceTree = "<group>"; };
5BEDB71F283B4AEA0078EB25 /* data-zhuyinwen.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; name = "data-zhuyinwen.plist"; path = "Data/data-zhuyinwen.plist"; sourceTree = "<group>"; }; 5BEDB71F283B4AEA0078EB25 /* data-zhuyinwen.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; name = "data-zhuyinwen.plist"; path = "Data/data-zhuyinwen.plist"; sourceTree = "<group>"; };
5BEDB720283B4AEA0078EB25 /* data-cht.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; name = "data-cht.plist"; path = "Data/data-cht.plist"; sourceTree = "<group>"; }; 5BEDB720283B4AEA0078EB25 /* data-cht.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; name = "data-cht.plist"; path = "Data/data-cht.plist"; sourceTree = "<group>"; };
5BF0B84B28C070B000795FC6 /* NSEventExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSEventExtension.swift; sourceTree = "<group>"; };
5BF255CD28B2694E003ECB60 /* vChewing-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "vChewing-Bridging-Header.h"; sourceTree = "<group>"; }; 5BF255CD28B2694E003ECB60 /* vChewing-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "vChewing-Bridging-Header.h"; sourceTree = "<group>"; };
5BF9DA2228840E6200DBD48E /* template-usersymbolphrases.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; path = "template-usersymbolphrases.txt"; sourceTree = "<group>"; usesTabs = 0; }; 5BF9DA2228840E6200DBD48E /* template-usersymbolphrases.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; path = "template-usersymbolphrases.txt"; sourceTree = "<group>"; usesTabs = 0; };
5BF9DA2328840E6200DBD48E /* template-exclusions.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; path = "template-exclusions.txt"; sourceTree = "<group>"; usesTabs = 0; }; 5BF9DA2328840E6200DBD48E /* template-exclusions.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; path = "template-exclusions.txt"; sourceTree = "<group>"; usesTabs = 0; };
@ -365,7 +366,6 @@
6ACA41EF15FC1D9000935EF6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; }; 6ACA41EF15FC1D9000935EF6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
6ACA41F215FC1D9000935EF6 /* Installer-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "Installer-Info.plist"; path = "Installer/Installer-Info.plist"; sourceTree = SOURCE_ROOT; }; 6ACA41F215FC1D9000935EF6 /* Installer-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "Installer-Info.plist"; path = "Installer/Installer-Info.plist"; sourceTree = SOURCE_ROOT; };
D427F76B278CA1BA004A2160 /* AppDelegate.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = AppDelegate.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; }; D427F76B278CA1BA004A2160 /* AppDelegate.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = AppDelegate.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
D456576D279E4F7B00DF6BC9 /* InputSignal.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = InputSignal.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
D461B791279DAC010070E734 /* InputState.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = InputState.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; }; D461B791279DAC010070E734 /* InputState.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = InputState.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
D47B92BF27972AC800458394 /* main.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = main.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; }; D47B92BF27972AC800458394 /* main.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = main.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
D47F7DCD278BFB57002F9DD7 /* ctlPrefWindow.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = ctlPrefWindow.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; }; D47F7DCD278BFB57002F9DD7 /* ctlPrefWindow.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = ctlPrefWindow.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
@ -498,13 +498,13 @@
5B21176D28753B35000443A9 /* ctlInputMethod_HandleDisplay.swift */, 5B21176D28753B35000443A9 /* ctlInputMethod_HandleDisplay.swift */,
5B21176B287539BB000443A9 /* ctlInputMethod_HandleStates.swift */, 5B21176B287539BB000443A9 /* ctlInputMethod_HandleStates.swift */,
5BB802D927FABA8300CF1C19 /* ctlInputMethod_Menu.swift */, 5BB802D927FABA8300CF1C19 /* ctlInputMethod_Menu.swift */,
D456576D279E4F7B00DF6BC9 /* InputSignal.swift */,
D461B791279DAC010070E734 /* InputState.swift */, D461B791279DAC010070E734 /* InputState.swift */,
5BD0113C2818543900609769 /* KeyHandler_Core.swift */, 5BD0113C2818543900609769 /* KeyHandler_Core.swift */,
5B782EC3280C243C007276DE /* KeyHandler_HandleCandidate.swift */, 5B782EC3280C243C007276DE /* KeyHandler_HandleCandidate.swift */,
5BE3779F288FED8D0037365B /* KeyHandler_HandleComposition.swift */, 5BE3779F288FED8D0037365B /* KeyHandler_HandleComposition.swift */,
5B7F225C2808501000DDD3CB /* KeyHandler_HandleInput.swift */, 5B7F225C2808501000DDD3CB /* KeyHandler_HandleInput.swift */,
5B3133BE280B229700A4A505 /* KeyHandler_States.swift */, 5B3133BE280B229700A4A505 /* KeyHandler_States.swift */,
5BF0B84B28C070B000795FC6 /* NSEventExtension.swift */,
5B62A33727AE79CD00A19448 /* StringUtils.swift */, 5B62A33727AE79CD00A19448 /* StringUtils.swift */,
5BAA8FBD282CAF380066C406 /* SyllableComposer.swift */, 5BAA8FBD282CAF380066C406 /* SyllableComposer.swift */,
); );
@ -1220,7 +1220,6 @@
D47F7DD0278C0897002F9DD7 /* ctlNonModalAlertWindow.swift in Sources */, D47F7DD0278C0897002F9DD7 /* ctlNonModalAlertWindow.swift in Sources */,
5B2170E5289FACAD00BE7304 /* 6_Node.swift in Sources */, 5B2170E5289FACAD00BE7304 /* 6_Node.swift in Sources */,
5B949BD92816DC5400D87B5D /* LineReader.swift in Sources */, 5B949BD92816DC5400D87B5D /* LineReader.swift in Sources */,
D456576E279E4F7B00DF6BC9 /* InputSignal.swift in Sources */,
5BA9FD1027FEDB6B002DE248 /* suiPrefPaneKeyboard.swift in Sources */, 5BA9FD1027FEDB6B002DE248 /* suiPrefPaneKeyboard.swift in Sources */,
5B3133BF280B229700A4A505 /* KeyHandler_States.swift in Sources */, 5B3133BF280B229700A4A505 /* KeyHandler_States.swift in Sources */,
5B2170E1289FACAD00BE7304 /* 0_Megrez.swift in Sources */, 5B2170E1289FACAD00BE7304 /* 0_Megrez.swift in Sources */,
@ -1262,6 +1261,7 @@
5B2170E0289FACAD00BE7304 /* 7_LangModel.swift in Sources */, 5B2170E0289FACAD00BE7304 /* 7_LangModel.swift in Sources */,
5B62A34927AE7CD900A19448 /* TooltipController.swift in Sources */, 5B62A34927AE7CD900A19448 /* TooltipController.swift in Sources */,
5BA9FD4027FEF3C8002DE248 /* Localization.swift in Sources */, 5BA9FD4027FEF3C8002DE248 /* Localization.swift in Sources */,
5BF0B84C28C070B000795FC6 /* NSEventExtension.swift in Sources */,
5BAA8FBE282CAF380066C406 /* SyllableComposer.swift in Sources */, 5BAA8FBE282CAF380066C406 /* SyllableComposer.swift in Sources */,
5B20430728BEE30900BFC6FD /* BookmarkManager.swift in Sources */, 5B20430728BEE30900BFC6FD /* BookmarkManager.swift in Sources */,
5BA9FD1327FEDB6B002DE248 /* suiPrefPaneDictionary.swift in Sources */, 5BA9FD1327FEDB6B002DE248 /* suiPrefPaneDictionary.swift in Sources */,
@ -1471,7 +1471,7 @@
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2300; CURRENT_PROJECT_VERSION = 2310;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO; GCC_DYNAMIC_NO_PIC = NO;
GCC_PREPROCESSOR_DEFINITIONS = ( GCC_PREPROCESSOR_DEFINITIONS = (
@ -1481,7 +1481,7 @@
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 2.3.0; MARKETING_VERSION = 2.3.1;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests;
@ -1510,13 +1510,13 @@
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2300; CURRENT_PROJECT_VERSION = 2310;
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 2.3.0; MARKETING_VERSION = 2.3.1;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests;
@ -1548,7 +1548,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2300; CURRENT_PROJECT_VERSION = 2310;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
@ -1570,7 +1570,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MARKETING_VERSION = 2.3.0; MARKETING_VERSION = 2.3.1;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor;
@ -1600,7 +1600,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2300; CURRENT_PROJECT_VERSION = 2310;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
@ -1618,7 +1618,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MARKETING_VERSION = 2.3.0; MARKETING_VERSION = 2.3.1;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor;
@ -1734,7 +1734,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2300; CURRENT_PROJECT_VERSION = 2310;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
@ -1763,7 +1763,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MARKETING_VERSION = 2.3.0; MARKETING_VERSION = 2.3.1;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
@ -1793,7 +1793,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2300; CURRENT_PROJECT_VERSION = 2310;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
@ -1816,7 +1816,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MARKETING_VERSION = 2.3.0; MARKETING_VERSION = 2.3.1;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@ -1840,7 +1840,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2300; CURRENT_PROJECT_VERSION = 2310;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
@ -1861,7 +1861,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MARKETING_VERSION = 2.3.0; MARKETING_VERSION = 2.3.1;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingInstaller; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingInstaller;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
@ -1884,7 +1884,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2300; CURRENT_PROJECT_VERSION = 2310;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
@ -1899,7 +1899,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MARKETING_VERSION = 2.3.0; MARKETING_VERSION = 2.3.1;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingInstaller; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingInstaller;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";

File diff suppressed because it is too large Load Diff

View File

@ -1,357 +1 @@
// Copyright (c) 2021 and onwards Zonble Yang (MIT-NTL License).
// All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that:
// No trademark license is granted to use the trade names, trademarks, service
// marks, or product names of Contributor, except as required to fulfill notice
// requirements defined in MIT License.
import XCTest
@testable import vChewing
class KeyHandlerTestsSCPCCHT: XCTestCase {
func reset() {
UserDef.allCases.forEach {
UserDefaults.standard.removeObject(forKey: $0.rawValue)
}
}
func makeSnapshot() -> [String: Any] {
var dict = [String: Any]()
UserDef.allCases.forEach {
dict[$0.rawValue] = UserDefaults.standard.object(forKey: $0.rawValue)
}
return dict
}
func restore(from snapshot: [String: Any]) {
UserDef.allCases.forEach {
UserDefaults.standard.set(snapshot[$0.rawValue], forKey: $0.rawValue)
}
}
var snapshot: [String: Any]?
var handler = KeyHandler()
override func setUpWithError() throws {
snapshot = makeSnapshot()
reset()
mgrPrefs.basicKeyboardLayout = "com.apple.keylayout.ABC"
mgrPrefs.mandarinParser = 0
mgrPrefs.useSCPCTypingMode = false
mgrPrefs.associatedPhrasesEnabled = false
mgrLangModel.loadDataModel(.imeModeCHT)
handler = KeyHandler()
handler.inputMode = .imeModeCHT
_ = mgrPrefs.toggleSCPCTypingModeEnabled()
_ = mgrPrefs.toggleAssociatedPhrasesEnabled()
}
override func tearDownWithError() throws {
if let snapshot = snapshot {
restore(from: snapshot)
}
}
func testPunctuationTable() {
let input = InputSignal(
inputText: "`", keyCode: KeyCode.kSymbolMenuPhysicalKeyIntl.rawValue, charCode: 0, flags: .option
)
var state: InputStateProtocol = InputState.Empty()
_ = handler.handle(input: input, state: state) { newState in
state = newState
} errorCallback: {
}
XCTAssertTrue(state is InputState.ChoosingCandidate, "\(state)")
if let state = state as? InputState.ChoosingCandidate {
XCTAssertTrue(state.candidates.map(\.1).contains(""))
}
}
func testPunctuationComma() {
let enabled = mgrPrefs.halfWidthPunctuationEnabled
mgrPrefs.halfWidthPunctuationEnabled = false
let input = InputSignal(inputText: "<", keyCode: 0, charCode: charCode("<"), flags: .shift)
var state: InputStateProtocol = InputState.Empty()
_ = handler.handle(input: input, state: state) { newState in
state = newState
} errorCallback: {
}
XCTAssertTrue(state is InputState.ChoosingCandidate, "\(state)")
if let state = state as? InputState.ChoosingCandidate {
XCTAssertEqual(state.composingBuffer, "")
}
mgrPrefs.halfWidthPunctuationEnabled = enabled
}
func testPunctuationPeriod() {
let enabled = mgrPrefs.halfWidthPunctuationEnabled
mgrPrefs.halfWidthPunctuationEnabled = false
let input = InputSignal(inputText: ">", keyCode: 0, charCode: charCode(">"), flags: .shift)
var state: InputStateProtocol = InputState.Empty()
_ = handler.handle(input: input, state: state) { newState in
state = newState
} errorCallback: {
}
XCTAssertTrue(state is InputState.ChoosingCandidate, "\(state)")
if let state = state as? InputState.ChoosingCandidate {
XCTAssertEqual(state.composingBuffer, "")
}
mgrPrefs.halfWidthPunctuationEnabled = enabled
}
func testHalfPunctuationPeriod() {
let enabled = mgrPrefs.halfWidthPunctuationEnabled
mgrPrefs.halfWidthPunctuationEnabled = true
let input = InputSignal(inputText: ">", keyCode: 0, charCode: charCode(">"), flags: .shift)
var state: InputStateProtocol = InputState.Empty()
_ = handler.handle(input: input, state: state) { newState in
state = newState
} errorCallback: {
}
XCTAssertTrue(state is InputState.ChoosingCandidate, "\(state)")
if let state = state as? InputState.ChoosingCandidate {
XCTAssertEqual(state.composingBuffer, ".")
}
mgrPrefs.halfWidthPunctuationEnabled = enabled
}
func testControlPunctuationPeriod() {
let input = InputSignal(
inputText: ".", keyCode: 0, charCode: charCode("."), flags: [.shift, .control]
)
var state: InputStateProtocol = InputState.Empty()
var count = 0
_ = handler.handle(input: input, state: state) { newState in
if count == 0 {
state = newState
}
count += 1
} errorCallback: {
}
XCTAssertTrue(state is InputState.Inputting, "\(state)")
if let state = state as? InputState.Inputting {
XCTAssertEqual(state.composingBuffer, "")
}
}
func testEnterWithReading() {
let input = InputSignal(inputText: "s", keyCode: 0, charCode: charCode("s"), flags: .shift)
var state: InputStateProtocol = InputState.Empty()
_ = handler.handle(input: input, state: state) { newState in
state = newState
} errorCallback: {
}
XCTAssertTrue(state is InputState.Inputting, "\(state)")
if let state = state as? InputState.Inputting {
XCTAssertEqual(state.composingBuffer, "")
}
let enter = InputSignal(inputText: " ", keyCode: 0, charCode: 13, flags: [])
var count = 0
_ = handler.handle(input: enter, state: state) { newState in
if count == 0 {
state = newState
}
count += 1
} errorCallback: {
}
XCTAssertTrue(state is InputState.Inputting, "\(state)")
if let state = state as? InputState.Inputting {
XCTAssertEqual(state.composingBuffer, "")
}
}
func testInputNe() {
let input = InputSignal(inputText: "s", keyCode: 0, charCode: charCode("s"), flags: .shift)
var state: InputStateProtocol = InputState.Empty()
_ = handler.handle(input: input, state: state) { newState in
state = newState
} errorCallback: {
}
XCTAssertTrue(state is InputState.Inputting, "\(state)")
if let state = state as? InputState.Inputting {
XCTAssertEqual(state.composingBuffer, "")
}
}
func testInputNi() {
var state: InputStateProtocol = InputState.Empty()
let keys = Array("su").charComponents
for key in keys {
let input = InputSignal(inputText: key, keyCode: 0, charCode: charCode(key), flags: [])
_ = handler.handle(input: input, state: state) { newState in
state = newState
} errorCallback: {
}
}
XCTAssertTrue(state is InputState.Inputting, "\(state)")
if let state = state as? InputState.Inputting {
XCTAssertEqual(state.composingBuffer, "ㄋㄧ")
}
}
func testInputNi3() {
var state: InputStateProtocol = InputState.Empty()
let keys = Array("su3").charComponents
for key in keys {
let input = InputSignal(inputText: key, keyCode: 0, charCode: charCode(key), flags: [])
_ = handler.handle(input: input, state: state) { newState in
state = newState
} errorCallback: {
}
}
XCTAssertTrue(state is InputState.ChoosingCandidate, "\(state)")
if let state = state as? InputState.ChoosingCandidate {
XCTAssertTrue(state.candidates.map(\.1).contains(""))
}
}
// TODO: Further bug-hunting needed.
func testCancelCandidateUsingDelete() {
mgrPrefs.useSCPCTypingMode = true
var state: InputStateProtocol = InputState.Empty()
let keys = Array("su3").charComponents
for key in keys {
let input = InputSignal(inputText: key, keyCode: 0, charCode: charCode(key), flags: [])
_ = handler.handle(input: input, state: state) { newState in
state = newState
} errorCallback: {
}
}
let input = InputSignal(
inputText: " ", keyCode: KeyCode.kWindowsDelete.rawValue, charCode: charCode(" "), flags: []
)
_ = handler.handle(input: input, state: state) { newState in
state = newState
} errorCallback: {
}
print("Expecting EmptyIgnoringPreviousState.")
print("\(state)")
// XCTAssertTrue(state is InputState.Empty, "\(state)")
}
// TODO: Further bug-hunting needed.
func testCancelCandidateUsingEsc() {
mgrPrefs.useSCPCTypingMode = true
var state: InputStateProtocol = InputState.Empty()
let keys = Array("su3").charComponents
for key in keys {
let input = InputSignal(inputText: key, keyCode: 0, charCode: charCode(key), flags: [])
_ = handler.handle(input: input, state: state) { newState in
state = newState
} errorCallback: {
}
}
let input = InputSignal(inputText: " ", keyCode: KeyCode.kEscape.rawValue, charCode: charCode(" "), flags: [])
_ = handler.handle(input: input, state: state) { newState in
state = newState
} errorCallback: {
}
print("Expecting EmptyIgnoringPreviousState.")
print("\(state)")
// XCTAssertTrue(state is InputState.Empty, "\(state)")
}
// TODO: Further bug-hunting needed.
func testAssociatedPhrases() {
let enabled = mgrPrefs.associatedPhrasesEnabled
mgrPrefs.associatedPhrasesEnabled = true
mgrPrefs.useSCPCTypingMode = true
handler.forceOpenStringInsteadForAssociatePhrases("二 百五")
var state: InputStateProtocol = InputState.Empty()
let keys = Array("-41").charComponents
for key in keys {
let input = InputSignal(inputText: key, keyCode: 0, charCode: charCode(key), flags: [])
_ = handler.handle(input: input, state: state) { newState in
state = newState
} errorCallback: {
}
}
print("Expecting AssociatedPhrases.")
print("\(state)")
// XCTAssertTrue(state is InputState.AssociatedPhrases, "\(state)")
// if let state = state as? InputState.AssociatedPhrases {
// XCTAssertTrue(state.candidates.map(\.1).contains(""))
// }
mgrPrefs.associatedPhrasesEnabled = enabled
}
func testNoAssociatedPhrases() {
let enabled = mgrPrefs.associatedPhrasesEnabled
mgrPrefs.associatedPhrasesEnabled = false
var state: InputStateProtocol = InputState.Empty()
let keys = Array("aul ").charComponents
for key in keys {
let input = InputSignal(inputText: key, keyCode: 0, charCode: charCode(key), flags: [])
_ = handler.handle(input: input, state: state) { newState in
state = newState
} errorCallback: {
}
}
XCTAssertTrue(state is InputState.Empty, "\(state)")
mgrPrefs.associatedPhrasesEnabled = enabled
}
}
// MARK: - StringView Ranges Extension (by Isaac Xen)
extension String {
fileprivate func ranges(splitBy separator: Element) -> [Range<String.Index>] {
var startIndex = startIndex
return split(separator: separator).reduce(into: []) { ranges, substring in
_ = range(of: substring, range: startIndex..<endIndex).map { range in
ranges.append(range)
startIndex = range.upperBound
}
}
}
}
extension vChewing.LMAssociates {
public mutating func forceOpenStringInstead(_ strData: String) {
strData.ranges(splitBy: "\n").filter { !$0.isEmpty }.forEach {
let neta = strData[$0].split(separator: " ")
if neta.count >= 2 {
let theKey = String(neta[0])
if !theKey.isEmpty, theKey.first != "#" {
for (i, _) in neta.filter({ $0.first != "#" && !$0.isEmpty }).enumerated() {
if i == 0 { continue }
rangeMap[theKey, default: []].append(($0, i))
}
}
}
}
}
}
extension vChewing.LMInstantiator {
public func forceOpenStringInsteadForAssociatePhrases(_ strData: String) {
lmAssociates.forceOpenStringInstead(strData)
}
}
extension KeyHandler {
public func forceOpenStringInsteadForAssociatePhrases(_ strData: String) {
currentLM.forceOpenStringInsteadForAssociatePhrases(strData + "\n")
}
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards Zonble Yang (MIT-NTL License). // (c) 2021 and onwards Zonble Yang (MIT-NTL License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 and onwards Zonble Yang (MIT-NTL License). // (c) 2021 and onwards Zonble Yang (MIT-NTL License).
// All possible vChewing-specific modifications are of: // All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================