Zonble: Pref Module + Interface to choose Conv Engine
- We removed the VXHanConvert from the codes inherited from upstream. - OpenCC in vChewing is for converting things to KangXi. It doesn't convert Simplified Chinese to Traditional (nor vise versa). - Fixed a bug to ensure that the candidate keys won't be niled in the preferencesWindowController. - Fixed a bug to ensure that the customized candidate keys will always consist of unique characters. Entries like "1145141919" will be recognized as "1459" prior to the validity check process.
This commit is contained in:
parent
5f0a0bad6f
commit
56f76b71d5
|
@ -203,7 +203,7 @@
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="height" constant="16" id="o6K-VN-uxe"/>
|
<constraint firstAttribute="height" constant="16" id="o6K-VN-uxe"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<buttonCell key="cell" type="check" title="Check for updates automatically" bezelStyle="regularSquare" imagePosition="left" alignment="left" controlSize="small" state="on" inset="2" id="Z9t-P0-BLF">
|
<buttonCell key="cell" type="check" title="Check for updates automatically" bezelStyle="regularSquare" imagePosition="left" alignment="left" controlSize="small" inset="2" id="Z9t-P0-BLF">
|
||||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||||
<font key="font" metaFont="cellTitle"/>
|
<font key="font" metaFont="cellTitle"/>
|
||||||
</buttonCell>
|
</buttonCell>
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
//
|
||||||
|
// EmacsKeyHelper.swift
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011-2022 The OpenVanilla Project.
|
||||||
|
//
|
||||||
|
// Contributors:
|
||||||
|
// Weizhong Yang (@zonble) @ OpenVanilla
|
||||||
|
//
|
||||||
|
// Based on the Syrup Project and the Formosana Library
|
||||||
|
// by Lukhnos Liu (@lukhnos).
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Cocoa
|
||||||
|
|
||||||
|
@objc enum vChewingEmacsKey: 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
|
||||||
|
}
|
||||||
|
|
||||||
|
class EmacsKeyHelper: NSObject {
|
||||||
|
@objc static func detect(charCode: UniChar, flags: NSEvent.ModifierFlags) -> vChewingEmacsKey {
|
||||||
|
if flags.contains(.control) {
|
||||||
|
return vChewingEmacsKey(rawValue: charCode) ?? .none
|
||||||
|
}
|
||||||
|
return .none;
|
||||||
|
}
|
||||||
|
}
|
|
@ -80,11 +80,5 @@
|
||||||
|
|
||||||
// current input mode
|
// current input mode
|
||||||
NSString *_inputMode;
|
NSString *_inputMode;
|
||||||
|
|
||||||
// if Chinese conversion is enabled
|
|
||||||
BOOL _chineseConversionEnabled;
|
|
||||||
|
|
||||||
// if half-width punctuation is enabled
|
|
||||||
BOOL _halfWidthPunctuationEnabled;
|
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
||||||
//
|
//
|
||||||
// PreferencesWindowController.swift
|
// OpenCCBridge.swift
|
||||||
//
|
//
|
||||||
// Copyright (c) 2011-2022 The OpenVanilla Project.
|
// Copyright (c) 2011-2022 The OpenVanilla Project.
|
||||||
//
|
//
|
||||||
|
@ -34,22 +34,23 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import OpenCC
|
import OpenCC
|
||||||
|
|
||||||
// Since SwiftyLibreCC only provide Swift classes, we create an NSObject subclass
|
/// A bridge to let Objctive-C code to access SwiftyOpenCC.
|
||||||
// in Swift in order to bridge the Swift classes into our Objective-C++ project.
|
///
|
||||||
class OpenCCBridge : NSObject {
|
/// Since SwiftyOpenCC only provide Swift classes, we create an NSObject subclass
|
||||||
|
/// in Swift in order to bridge the Swift classes into our Objective-C++ project.
|
||||||
|
public class OpenCCBridge: NSObject {
|
||||||
private static let shared = OpenCCBridge()
|
private static let shared = OpenCCBridge()
|
||||||
private var converter: ChineseConverter?
|
private var converter: ChineseConverter?
|
||||||
|
|
||||||
private override init() {
|
private override init() {
|
||||||
try? converter = ChineseConverter(options: .twStandardRev)
|
try? converter = ChineseConverter(options: .twStandardRev)
|
||||||
super.init()
|
super.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc static func convert(_ string: String) -> String? {
|
/// Converts to Simplified Chinese.
|
||||||
|
///
|
||||||
|
/// - Parameter string: Text in Traditional Chinese.
|
||||||
|
/// - Returns: Text in Simplified Chinese.
|
||||||
|
@objc public static func convertToKangXi(_ string: String) -> String? {
|
||||||
shared.converter?.convert(string)
|
shared.converter?.convert(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func convert(_ string: String) -> String? {
|
|
||||||
converter?.convert(string)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,289 @@
|
||||||
|
//
|
||||||
|
// Preferences.swift
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011-2022 The OpenVanilla Project.
|
||||||
|
//
|
||||||
|
// Contributors:
|
||||||
|
// Weizhong Yang (@zonble) @ OpenVanilla
|
||||||
|
//
|
||||||
|
// Based on the Syrup Project and the Formosana Library
|
||||||
|
// by Lukhnos Liu (@lukhnos).
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Cocoa
|
||||||
|
|
||||||
|
private let kKeyboardLayoutPreferenceKey = "KeyboardLayout"
|
||||||
|
private let kBasisKeyboardLayoutPreferenceKey = "BasisKeyboardLayout"; // alphanumeric ("ASCII") input basi
|
||||||
|
private let kFunctionKeyKeyboardLayoutPreferenceKey = "FunctionKeyKeyboardLayout"; // alphanumeric ("ASCII") input basi
|
||||||
|
private let kFunctionKeyKeyboardLayoutOverrideIncludeShiftKey = "FunctionKeyKeyboardLayoutOverrideIncludeShift"; // whether include shif
|
||||||
|
private let kCandidateListTextSizeKey = "CandidateListTextSize"
|
||||||
|
private let kSelectPhraseAfterCursorAsCandidatePreferenceKey = "SelectPhraseAfterCursorAsCandidate"
|
||||||
|
private let kUseHorizontalCandidateListPreferenceKey = "UseHorizontalCandidateList"
|
||||||
|
private let kComposingBufferSizePreferenceKey = "ComposingBufferSize"
|
||||||
|
private let kChooseCandidateUsingSpaceKey = "ChooseCandidateUsingSpaceKey"
|
||||||
|
private let kChineseConversionEnabledKey = "ChineseConversionEnabled"
|
||||||
|
private let kHalfWidthPunctuationEnabledKey = "HalfWidthPunctuationEnable"
|
||||||
|
private let kEscToCleanInputBufferKey = "EscToCleanInputBuffer"
|
||||||
|
|
||||||
|
private let kCandidateTextFontName = "CandidateTextFontName"
|
||||||
|
private let kCandidateKeyLabelFontName = "CandidateKeyLabelFontName"
|
||||||
|
private let kCandidateKeys = "CandidateKeys"
|
||||||
|
private let kChineseConversionEngineKey = "ChineseConversionEngine"
|
||||||
|
|
||||||
|
private let kDefaultCandidateListTextSize: CGFloat = 18
|
||||||
|
private let kMinKeyLabelSize: CGFloat = 10
|
||||||
|
private let kMinCandidateListTextSize: CGFloat = 12
|
||||||
|
private let kMaxCandidateListTextSize: CGFloat = 196
|
||||||
|
|
||||||
|
// default, min and max composing buffer size (in codepoints)
|
||||||
|
// modern Macs can usually work up to 16 codepoints when the builder still
|
||||||
|
// walks the grid with good performance; slower Macs (like old PowerBooks)
|
||||||
|
// will start to sputter beyond 12; such is the algorithmatic complexity
|
||||||
|
// of the Viterbi algorithm used in the builder library (at O(N^2))
|
||||||
|
private let kDefaultComposingBufferSize = 10
|
||||||
|
private let kMinComposingBufferSize = 4
|
||||||
|
private let kMaxComposingBufferSize = 20
|
||||||
|
|
||||||
|
private let kDefaultKeys = "123456789"
|
||||||
|
|
||||||
|
// MARK: Property wrappers
|
||||||
|
@propertyWrapper
|
||||||
|
struct UserDefault<Value> {
|
||||||
|
let key: String
|
||||||
|
let defaultValue: Value
|
||||||
|
var container: UserDefaults = .standard
|
||||||
|
|
||||||
|
var wrappedValue: Value {
|
||||||
|
get {
|
||||||
|
return container.object(forKey: key) as? Value ?? defaultValue
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
container.set(newValue, forKey: key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@propertyWrapper
|
||||||
|
struct CandidateListTextSize {
|
||||||
|
let key: String
|
||||||
|
let defaultValue: CGFloat = kDefaultCandidateListTextSize
|
||||||
|
lazy var container: UserDefault = {
|
||||||
|
UserDefault(key: key, defaultValue: defaultValue) }()
|
||||||
|
|
||||||
|
var wrappedValue: CGFloat {
|
||||||
|
mutating get {
|
||||||
|
var value = container.wrappedValue
|
||||||
|
if value < kMinCandidateListTextSize {
|
||||||
|
value = kMinCandidateListTextSize
|
||||||
|
} else if value > kMaxCandidateListTextSize {
|
||||||
|
value = kMaxCandidateListTextSize
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
var value = newValue
|
||||||
|
if value < kMinCandidateListTextSize {
|
||||||
|
value = kMinCandidateListTextSize
|
||||||
|
} else if value > kMaxCandidateListTextSize {
|
||||||
|
value = kMaxCandidateListTextSize
|
||||||
|
}
|
||||||
|
container.wrappedValue = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@propertyWrapper
|
||||||
|
struct ComposingBufferSize {
|
||||||
|
let key: String
|
||||||
|
let defaultValue: Int = kDefaultComposingBufferSize
|
||||||
|
lazy var container: UserDefault = {
|
||||||
|
UserDefault(key: key, defaultValue: defaultValue) }()
|
||||||
|
|
||||||
|
var wrappedValue: Int {
|
||||||
|
mutating get {
|
||||||
|
let currentValue = container.wrappedValue
|
||||||
|
if currentValue < kMinComposingBufferSize {
|
||||||
|
return kMinComposingBufferSize
|
||||||
|
} else if currentValue > kMaxComposingBufferSize {
|
||||||
|
return kMaxComposingBufferSize
|
||||||
|
}
|
||||||
|
return currentValue
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
var value = newValue
|
||||||
|
if value < kMinComposingBufferSize {
|
||||||
|
value = kMinComposingBufferSize
|
||||||
|
} else if value > kMaxComposingBufferSize {
|
||||||
|
value = kMaxComposingBufferSize
|
||||||
|
}
|
||||||
|
container.wrappedValue = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@propertyWrapper
|
||||||
|
struct ComposingKeys {
|
||||||
|
let key: String
|
||||||
|
let defaultValue: String? = kCandidateKeys
|
||||||
|
lazy var container: UserDefault = {
|
||||||
|
UserDefault(key: key, defaultValue: defaultValue) }()
|
||||||
|
|
||||||
|
var wrappedValue: String? {
|
||||||
|
mutating get {
|
||||||
|
let value = container.wrappedValue
|
||||||
|
if let value = value {
|
||||||
|
if value.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
let value = newValue
|
||||||
|
if let value = value {
|
||||||
|
if value.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
|
container.wrappedValue = nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
container.wrappedValue = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: -
|
||||||
|
@objc enum KeyboardLayout: Int {
|
||||||
|
case standard
|
||||||
|
case eten
|
||||||
|
case eten26
|
||||||
|
case hsu
|
||||||
|
case hanyuPinyin
|
||||||
|
case IBM
|
||||||
|
|
||||||
|
var name: String {
|
||||||
|
switch (self) {
|
||||||
|
case .standard:
|
||||||
|
return "Standard"
|
||||||
|
case .eten:
|
||||||
|
return "ETen"
|
||||||
|
case .eten26:
|
||||||
|
return "ETen26"
|
||||||
|
case .hsu:
|
||||||
|
return "Hsu"
|
||||||
|
case .hanyuPinyin:
|
||||||
|
return "HanyuPinyin"
|
||||||
|
case .IBM:
|
||||||
|
return "IBM"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc enum ChineseConversionEngine: Int {
|
||||||
|
case openCC
|
||||||
|
case vxHanConvert
|
||||||
|
|
||||||
|
var name: String {
|
||||||
|
switch (self) {
|
||||||
|
case .openCC:
|
||||||
|
return "OpenCC"
|
||||||
|
case .vxHanConvert:
|
||||||
|
return "VXHanConvert"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: -
|
||||||
|
class Preferences: NSObject {
|
||||||
|
@UserDefault(key: kKeyboardLayoutPreferenceKey, defaultValue: 0)
|
||||||
|
@objc static var keyboardLayout: Int
|
||||||
|
|
||||||
|
@objc static var keyboardLayoutName: String {
|
||||||
|
(KeyboardLayout(rawValue: self.keyboardLayout) ?? KeyboardLayout.standard).name
|
||||||
|
}
|
||||||
|
|
||||||
|
@UserDefault(key: kBasisKeyboardLayoutPreferenceKey, defaultValue: "com.apple.keylayout.US")
|
||||||
|
@objc static var basisKeyboardLayout: String
|
||||||
|
|
||||||
|
@UserDefault(key: kFunctionKeyKeyboardLayoutPreferenceKey, defaultValue: "com.apple.keylayout.US")
|
||||||
|
@objc static var functionKeyboardLayout: String
|
||||||
|
|
||||||
|
@UserDefault(key: kFunctionKeyKeyboardLayoutOverrideIncludeShiftKey, defaultValue: false)
|
||||||
|
@objc static var functionKeyKeyboardLayoutOverrideIncludeShiftKey: Bool
|
||||||
|
|
||||||
|
@CandidateListTextSize(key: kCandidateListTextSizeKey)
|
||||||
|
@objc static var candidateListTextSize: CGFloat
|
||||||
|
|
||||||
|
@UserDefault(key: kSelectPhraseAfterCursorAsCandidatePreferenceKey, defaultValue: false)
|
||||||
|
@objc static var selectPhraseAfterCursorAsCandidate: Bool
|
||||||
|
|
||||||
|
@UserDefault(key: kUseHorizontalCandidateListPreferenceKey, defaultValue: false)
|
||||||
|
@objc static var useHorizontalCandidateList: Bool
|
||||||
|
|
||||||
|
@ComposingBufferSize(key: kComposingBufferSizePreferenceKey)
|
||||||
|
@objc static var composingBufferSize: Int
|
||||||
|
|
||||||
|
@UserDefault(key: kChooseCandidateUsingSpaceKey, defaultValue: true)
|
||||||
|
@objc static var chooseCandidateUsingSpace: Bool
|
||||||
|
|
||||||
|
@UserDefault(key: kChineseConversionEnabledKey, defaultValue: false)
|
||||||
|
@objc static var chineseConversionEnabled: Bool
|
||||||
|
|
||||||
|
@objc static func toggleChineseConversionEnabled() -> Bool {
|
||||||
|
chineseConversionEnabled = !chineseConversionEnabled
|
||||||
|
return chineseConversionEnabled
|
||||||
|
}
|
||||||
|
|
||||||
|
@UserDefault(key: kHalfWidthPunctuationEnabledKey, defaultValue: false)
|
||||||
|
@objc static var halfWidthPunctuationEnabled: Bool
|
||||||
|
|
||||||
|
@objc static func toogleHalfWidthPunctuationEnabled() -> Bool {
|
||||||
|
halfWidthPunctuationEnabled = !halfWidthPunctuationEnabled
|
||||||
|
return halfWidthPunctuationEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@UserDefault(key: kEscToCleanInputBufferKey, defaultValue: false)
|
||||||
|
@objc static var escToCleanInputBuffer: Bool
|
||||||
|
|
||||||
|
// MARK: Optional settings
|
||||||
|
@UserDefault(key: kCandidateTextFontName, defaultValue: nil)
|
||||||
|
@objc static var candidateTextFontName: String?
|
||||||
|
|
||||||
|
@UserDefault(key: kCandidateKeyLabelFontName, defaultValue: nil)
|
||||||
|
@objc static var candidateKeyLabelFontName: String?
|
||||||
|
|
||||||
|
@ComposingKeys(key: kCandidateKeys)
|
||||||
|
@objc static var candidateKeys: String?
|
||||||
|
|
||||||
|
@objc static var defaultKeys: String {
|
||||||
|
kDefaultKeys
|
||||||
|
}
|
||||||
|
|
||||||
|
@UserDefault(key: kChineseConversionEngineKey, defaultValue: 0)
|
||||||
|
@objc static var chineseConversionEngine: Int
|
||||||
|
|
||||||
|
@objc static var chineseConversionEngineName: String? {
|
||||||
|
return ChineseConversionEngine(rawValue: chineseConversionEngine)?.name
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -36,9 +36,13 @@
|
||||||
import Cocoa
|
import Cocoa
|
||||||
import Carbon
|
import Carbon
|
||||||
|
|
||||||
private let kBasisKeyboardLayoutPreferenceKey = "BasisKeyboardLayout"
|
// Extend the RangeReplaceableCollection to allow it clean duplicated characters.
|
||||||
private let kCandidateKeys = "CandidateKeys"
|
extension RangeReplaceableCollection where Element: Hashable {
|
||||||
private let kDefaultKeys = "123456789"
|
var charDeDuplicate: Self {
|
||||||
|
var set = Set<Element>()
|
||||||
|
return filter{ set.insert($0).inserted }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Please note that the class should be exposed as "PreferencesWindowController"
|
// Please note that the class should be exposed as "PreferencesWindowController"
|
||||||
// in Objective-C in order to let IMK to see the same class name as
|
// in Objective-C in order to let IMK to see the same class name as
|
||||||
|
@ -47,55 +51,78 @@ private let kDefaultKeys = "123456789"
|
||||||
@IBOutlet weak var fontSizePopUpButton: NSPopUpButton!
|
@IBOutlet weak var fontSizePopUpButton: NSPopUpButton!
|
||||||
@IBOutlet weak var basisKeyboardLayoutButton: NSPopUpButton!
|
@IBOutlet weak var basisKeyboardLayoutButton: NSPopUpButton!
|
||||||
@IBOutlet weak var selectionKeyComboBox: NSComboBox!
|
@IBOutlet weak var selectionKeyComboBox: NSComboBox!
|
||||||
|
|
||||||
override func awakeFromNib() {
|
override func awakeFromNib() {
|
||||||
let list = TISCreateInputSourceList(nil, true).takeRetainedValue() as! [TISInputSource]
|
let list = TISCreateInputSourceList(nil, true).takeRetainedValue() as! [TISInputSource]
|
||||||
var usKeyboardLayoutItem: NSMenuItem? = nil
|
var usKeyboardLayoutItem: NSMenuItem? = nil
|
||||||
var chosenItem: NSMenuItem? = nil
|
var chosenItem: NSMenuItem? = nil
|
||||||
|
|
||||||
basisKeyboardLayoutButton.menu?.removeAllItems()
|
basisKeyboardLayoutButton.menu?.removeAllItems()
|
||||||
|
|
||||||
let basisKeyboardLayoutID = UserDefaults.standard.string(forKey: kBasisKeyboardLayoutPreferenceKey)
|
let basisKeyboardLayoutID = Preferences.basisKeyboardLayout
|
||||||
for source in list {
|
for source in list {
|
||||||
if let categoryPtr = TISGetInputSourceProperty(source, kTISPropertyInputSourceCategory) {
|
|
||||||
let category = Unmanaged<CFString>.fromOpaque(categoryPtr).takeUnretainedValue()
|
func getString(_ key: CFString) -> String? {
|
||||||
if category != kTISCategoryKeyboardInputSource {
|
if let ptr = TISGetInputSourceProperty(source, key) {
|
||||||
|
return String(Unmanaged<CFString>.fromOpaque(ptr).takeUnretainedValue())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getBool(_ key: CFString) -> Bool? {
|
||||||
|
if let ptr = TISGetInputSourceProperty(source, key) {
|
||||||
|
return Unmanaged<CFBoolean>.fromOpaque(ptr).takeUnretainedValue() == kCFBooleanTrue
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if let category = getString(kTISPropertyInputSourceCategory) {
|
||||||
|
if category != String(kTISCategoryKeyboardInputSource) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if let asciiCapablePtr = TISGetInputSourceProperty(source, kTISPropertyInputSourceIsASCIICapable) {
|
if let asciiCapable = getBool(kTISPropertyInputSourceIsASCIICapable) {
|
||||||
let asciiCapable = Unmanaged<CFBoolean>.fromOpaque(asciiCapablePtr).takeUnretainedValue()
|
if !asciiCapable {
|
||||||
if asciiCapable != kCFBooleanTrue {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if let sourceTypePtr = TISGetInputSourceProperty(source, kTISPropertyInputSourceType) {
|
if let sourceType = getString(kTISPropertyInputSourceType) {
|
||||||
let sourceType = Unmanaged<CFString>.fromOpaque(sourceTypePtr).takeUnretainedValue()
|
if sourceType != String(kTISTypeKeyboardLayout) {
|
||||||
if sourceType != kTISTypeKeyboardLayout {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let sourceIDPtr = TISGetInputSourceProperty(source, kTISPropertyInputSourceID),
|
guard let sourceID = getString(kTISPropertyInputSourceID),
|
||||||
let localizedNamePtr = TISGetInputSourceProperty(source, kTISPropertyLocalizedName) else {
|
let localizedName = getString(kTISPropertyLocalizedName) else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
let sourceID = String(Unmanaged<CFString>.fromOpaque(sourceIDPtr).takeUnretainedValue())
|
|
||||||
let localizedName = String(Unmanaged<CFString>.fromOpaque(localizedNamePtr).takeUnretainedValue())
|
|
||||||
|
|
||||||
let menuItem = NSMenuItem()
|
let menuItem = NSMenuItem()
|
||||||
menuItem.title = localizedName
|
menuItem.title = localizedName
|
||||||
menuItem.representedObject = sourceID
|
menuItem.representedObject = sourceID
|
||||||
|
|
||||||
|
if let iconPtr = TISGetInputSourceProperty(source, kTISPropertyIconRef) {
|
||||||
|
let icon = IconRef(iconPtr)
|
||||||
|
let image = NSImage(iconRef: icon)
|
||||||
|
|
||||||
|
func resize( _ image: NSImage) -> NSImage {
|
||||||
|
let newImage = NSImage(size: NSSize(width: 16, height: 16))
|
||||||
|
newImage.lockFocus()
|
||||||
|
image.draw(in: NSRect(x: 0, y: 0, width: 16, height: 16))
|
||||||
|
newImage.unlockFocus()
|
||||||
|
return newImage
|
||||||
|
}
|
||||||
|
menuItem.image = resize(image)
|
||||||
|
}
|
||||||
|
|
||||||
if sourceID == "com.apple.keylayout.US" {
|
if sourceID == "com.apple.keylayout.US" {
|
||||||
usKeyboardLayoutItem = menuItem
|
usKeyboardLayoutItem = menuItem
|
||||||
}
|
}
|
||||||
|
@ -104,41 +131,41 @@ private let kDefaultKeys = "123456789"
|
||||||
}
|
}
|
||||||
basisKeyboardLayoutButton.menu?.addItem(menuItem)
|
basisKeyboardLayoutButton.menu?.addItem(menuItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
basisKeyboardLayoutButton.select(chosenItem ?? usKeyboardLayoutItem)
|
basisKeyboardLayoutButton.select(chosenItem ?? usKeyboardLayoutItem)
|
||||||
selectionKeyComboBox.usesDataSource = false
|
selectionKeyComboBox.usesDataSource = false
|
||||||
selectionKeyComboBox.addItems(withObjectValues: [kDefaultKeys, "asdfghjkl", "asdfzxcvb"])
|
selectionKeyComboBox.removeAllItems()
|
||||||
|
selectionKeyComboBox.addItems(withObjectValues: [Preferences.defaultKeys, "ASDFGHJKL", "ASDFZXCVB"])
|
||||||
var candidateSelectionKeys = (UserDefaults.standard.string(forKey: kCandidateKeys) ?? kDefaultKeys)
|
|
||||||
.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
|
var candidateSelectionKeys = Preferences.candidateKeys ?? Preferences.defaultKeys
|
||||||
if candidateSelectionKeys.isEmpty {
|
if candidateSelectionKeys.isEmpty {
|
||||||
candidateSelectionKeys = kDefaultKeys
|
candidateSelectionKeys = Preferences.defaultKeys
|
||||||
}
|
}
|
||||||
|
|
||||||
selectionKeyComboBox.stringValue = candidateSelectionKeys
|
selectionKeyComboBox.stringValue = candidateSelectionKeys
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func updateBasisKeyboardLayoutAction(_ sender:Any) {
|
@IBAction func updateBasisKeyboardLayoutAction(_ sender: Any) {
|
||||||
if let sourceID = basisKeyboardLayoutButton.selectedItem?.representedObject {
|
if let sourceID = basisKeyboardLayoutButton.selectedItem?.representedObject as? String {
|
||||||
UserDefaults.standard.set(sourceID, forKey: kBasisKeyboardLayoutPreferenceKey)
|
Preferences.basisKeyboardLayout = sourceID
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func changeSelectionKeyAction(_ sender: Any) {
|
@IBAction func changeSelectionKeyAction(_ sender: Any) {
|
||||||
let keys = (sender as AnyObject).stringValue.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
|
let keys = (sender as AnyObject).stringValue.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines).charDeDuplicate
|
||||||
if keys.count != 9 || !keys.canBeConverted(to: .ascii) {
|
if keys.count != 9 || !keys.canBeConverted(to: .ascii) {
|
||||||
selectionKeyComboBox.stringValue = kDefaultKeys
|
selectionKeyComboBox.stringValue = Preferences.defaultKeys
|
||||||
UserDefaults.standard.removeObject(forKey: kCandidateKeys)
|
Preferences.candidateKeys = nil
|
||||||
NSSound.beep()
|
NSSound.beep()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
selectionKeyComboBox.stringValue = keys
|
selectionKeyComboBox.stringValue = keys
|
||||||
if keys == kDefaultKeys {
|
if keys == Preferences.defaultKeys {
|
||||||
UserDefaults.standard.removeObject(forKey: kCandidateKeys)
|
Preferences.candidateKeys = nil
|
||||||
} else {
|
} else {
|
||||||
UserDefaults.standard.set(keys, forKey: kCandidateKeys)
|
Preferences.candidateKeys = keys
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
"Visit Website" = "Visit Website";
|
"Visit Website" = "Visit Website";
|
||||||
"You're currently using vChewing %@ (%@), a new version %@ (%@) is now available. Do you want to visit vChewing's website to download the version?%@" = "You're currently using vChewing %@ (%@), a new version %@ (%@) is now available. Do you want to visit vChewing's website to download the version?%@";
|
"You're currently using vChewing %@ (%@), a new version %@ (%@) is now available. Do you want to visit vChewing's website to download the version?%@" = "You're currently using vChewing %@ (%@), a new version %@ (%@) is now available. Do you want to visit vChewing's website to download the version?%@";
|
||||||
"Chinese Conversion" = "Convert zh-TW Kanji to KangXi Variants";
|
"Chinese Conversion" = "Convert zh-TW Kanji to KangXi Variants";
|
||||||
"NotificationSwitchON" = " ON";
|
"NotificationSwitchON" = "✔ ON";
|
||||||
"NotificationSwitchOFF" = " OFF";
|
"NotificationSwitchOFF" = "✘ OFF";
|
||||||
"Edit User Phrases" = "Edit User Phrases";
|
"Edit User Phrases" = "Edit User Phrases";
|
||||||
"Reload User Phrases" = "Reload User Phrases";
|
"Reload User Phrases" = "Reload User Phrases";
|
||||||
"Unable to create the user phrase file." = "Unable to create the user phrase file.";
|
"Unable to create the user phrase file." = "Unable to create the user phrase file.";
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
"Visit Website" = "前往网站";
|
"Visit Website" = "前往网站";
|
||||||
"You're currently using vChewing %@ (%@), a new version %@ (%@) is now available. Do you want to visit vChewing's website to download the version?%@" = "目前使用的威注音官方版本是 %1$@ (%2$@),网路上有更新版本 %3$@ (%4$@) 可供下载。是否要前往威注音网站下载新版来安装?%5$@";
|
"You're currently using vChewing %@ (%@), a new version %@ (%@) is now available. Do you want to visit vChewing's website to download the version?%@" = "目前使用的威注音官方版本是 %1$@ (%2$@),网路上有更新版本 %3$@ (%4$@) 可供下载。是否要前往威注音网站下载新版来安装?%5$@";
|
||||||
"Chinese Conversion" = "优先使用康熙繁体字";
|
"Chinese Conversion" = "优先使用康熙繁体字";
|
||||||
"NotificationSwitchON" = " 已启用";
|
"NotificationSwitchON" = "✔ 已启用";
|
||||||
"NotificationSwitchOFF" = " 已停用";
|
"NotificationSwitchOFF" = "✘ 已停用";
|
||||||
"Edit User Phrases" = "编辑自订语汇";
|
"Edit User Phrases" = "编辑自订语汇";
|
||||||
"Reload User Phrases" = "重载自订语汇";
|
"Reload User Phrases" = "重载自订语汇";
|
||||||
"Unable to create the user phrase file." = "无法创建自订语汇档案。";
|
"Unable to create the user phrase file." = "无法创建自订语汇档案。";
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
"Visit Website" = "前往網站";
|
"Visit Website" = "前往網站";
|
||||||
"You're currently using vChewing %@ (%@), a new version %@ (%@) is now available. Do you want to visit vChewing's website to download the version?%@" = "目前使用的威注音官方版本是 %1$@ (%2$@),網路上有更新版本 %3$@ (%4$@) 可供下載。是否要前往威注音網站下載新版來安裝?%5$@";
|
"You're currently using vChewing %@ (%@), a new version %@ (%@) is now available. Do you want to visit vChewing's website to download the version?%@" = "目前使用的威注音官方版本是 %1$@ (%2$@),網路上有更新版本 %3$@ (%4$@) 可供下載。是否要前往威注音網站下載新版來安裝?%5$@";
|
||||||
"Chinese Conversion" = "優先使用康熙繁體字";
|
"Chinese Conversion" = "優先使用康熙繁體字";
|
||||||
"NotificationSwitchON" = " 已啟用";
|
"NotificationSwitchON" = "✔ 已啟用";
|
||||||
"NotificationSwitchOFF" = " 已停用";
|
"NotificationSwitchOFF" = "✘ 已停用";
|
||||||
"Edit User Phrases" = "編輯自訂語彙";
|
"Edit User Phrases" = "編輯自訂語彙";
|
||||||
"Reload User Phrases" = "重載自訂語彙";
|
"Reload User Phrases" = "重載自訂語彙";
|
||||||
"Unable to create the user phrase file." = "無法創建自訂語彙檔案。";
|
"Unable to create the user phrase file." = "無法創建自訂語彙檔案。";
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
5B5F4F972792A4EA00922DC2 /* UserPhrasesLM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5B5F4F962792A4EA00922DC2 /* UserPhrasesLM.cpp */; };
|
5B5F4F972792A4EA00922DC2 /* UserPhrasesLM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5B5F4F962792A4EA00922DC2 /* UserPhrasesLM.cpp */; };
|
||||||
5BC2D2872793B434002C0BEC /* CMakeLists.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BC2D2852793B434002C0BEC /* CMakeLists.txt */; };
|
5BC2D2872793B434002C0BEC /* CMakeLists.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BC2D2852793B434002C0BEC /* CMakeLists.txt */; };
|
||||||
5BC2D2882793B434002C0BEC /* KeyValueBlobReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5BC2D2862793B434002C0BEC /* KeyValueBlobReader.cpp */; };
|
5BC2D2882793B434002C0BEC /* KeyValueBlobReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5BC2D2862793B434002C0BEC /* KeyValueBlobReader.cpp */; };
|
||||||
|
5BC2D28B2793B8FB002C0BEC /* EmacsKeyHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC2D28A2793B8FB002C0BEC /* EmacsKeyHelper.swift */; };
|
||||||
|
5BC2D28D2793B98F002C0BEC /* PreferencesModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC2D28C2793B98F002C0BEC /* PreferencesModule.swift */; };
|
||||||
5BC3EE1B278FC48C00F5E44C /* VerticalCandidateController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC3EE18278FC48C00F5E44C /* VerticalCandidateController.swift */; };
|
5BC3EE1B278FC48C00F5E44C /* VerticalCandidateController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC3EE18278FC48C00F5E44C /* VerticalCandidateController.swift */; };
|
||||||
5BC3EE1C278FC48C00F5E44C /* VTCandidateController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC3EE19278FC48C00F5E44C /* VTCandidateController.swift */; };
|
5BC3EE1C278FC48C00F5E44C /* VTCandidateController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC3EE19278FC48C00F5E44C /* VTCandidateController.swift */; };
|
||||||
5BC3EE1D278FC48C00F5E44C /* HorizontalCandidateController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC3EE1A278FC48C00F5E44C /* HorizontalCandidateController.swift */; };
|
5BC3EE1D278FC48C00F5E44C /* HorizontalCandidateController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC3EE1A278FC48C00F5E44C /* HorizontalCandidateController.swift */; };
|
||||||
|
@ -105,6 +107,8 @@
|
||||||
5BC2D2842793B434002C0BEC /* KeyValueBlobReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeyValueBlobReader.h; sourceTree = "<group>"; };
|
5BC2D2842793B434002C0BEC /* KeyValueBlobReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeyValueBlobReader.h; sourceTree = "<group>"; };
|
||||||
5BC2D2852793B434002C0BEC /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; };
|
5BC2D2852793B434002C0BEC /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; };
|
||||||
5BC2D2862793B434002C0BEC /* KeyValueBlobReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KeyValueBlobReader.cpp; sourceTree = "<group>"; };
|
5BC2D2862793B434002C0BEC /* KeyValueBlobReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KeyValueBlobReader.cpp; sourceTree = "<group>"; };
|
||||||
|
5BC2D28A2793B8FB002C0BEC /* EmacsKeyHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmacsKeyHelper.swift; sourceTree = "<group>"; };
|
||||||
|
5BC2D28C2793B98F002C0BEC /* PreferencesModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesModule.swift; sourceTree = "<group>"; };
|
||||||
5BC3EE18278FC48C00F5E44C /* VerticalCandidateController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VerticalCandidateController.swift; sourceTree = "<group>"; };
|
5BC3EE18278FC48C00F5E44C /* VerticalCandidateController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VerticalCandidateController.swift; sourceTree = "<group>"; };
|
||||||
5BC3EE19278FC48C00F5E44C /* VTCandidateController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VTCandidateController.swift; sourceTree = "<group>"; };
|
5BC3EE19278FC48C00F5E44C /* VTCandidateController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VTCandidateController.swift; sourceTree = "<group>"; };
|
||||||
5BC3EE1A278FC48C00F5E44C /* HorizontalCandidateController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HorizontalCandidateController.swift; sourceTree = "<group>"; };
|
5BC3EE1A278FC48C00F5E44C /* HorizontalCandidateController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HorizontalCandidateController.swift; sourceTree = "<group>"; };
|
||||||
|
@ -272,6 +276,14 @@
|
||||||
path = vChewing;
|
path = vChewing;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
5BC2D2892793B8DB002C0BEC /* Keyboard */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
5BC2D28A2793B8FB002C0BEC /* EmacsKeyHelper.swift */,
|
||||||
|
);
|
||||||
|
path = Keyboard;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
5BE798A12792E50F00337FF9 /* UI */ = {
|
5BE798A12792E50F00337FF9 /* UI */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -336,7 +348,6 @@
|
||||||
6A0D4F1215FC0EB100ABF4B3 /* Engine */,
|
6A0D4F1215FC0EB100ABF4B3 /* Engine */,
|
||||||
6ACA41E715FC1D9000935EF6 /* Installer */,
|
6ACA41E715FC1D9000935EF6 /* Installer */,
|
||||||
6A0D4F4715FC0EB900ABF4B3 /* Resources */,
|
6A0D4F4715FC0EB900ABF4B3 /* Resources */,
|
||||||
5BDF2D052791DA6700838ADB /* AppDelegate.swift */,
|
|
||||||
5BF4A6FB27844738007DC6E7 /* frmAboutWindow.h */,
|
5BF4A6FB27844738007DC6E7 /* frmAboutWindow.h */,
|
||||||
5BF4A6FC27844738007DC6E7 /* frmAboutWindow.m */,
|
5BF4A6FC27844738007DC6E7 /* frmAboutWindow.m */,
|
||||||
6A0D4EC615FC0D6400ABF4B3 /* InputMethodController.h */,
|
6A0D4EC615FC0D6400ABF4B3 /* InputMethodController.h */,
|
||||||
|
@ -345,10 +356,12 @@
|
||||||
5B5F4F92279294A300922DC2 /* LanguageModelManager.mm */,
|
5B5F4F92279294A300922DC2 /* LanguageModelManager.mm */,
|
||||||
6A0D4EC815FC0D6400ABF4B3 /* main.m */,
|
6A0D4EC815FC0D6400ABF4B3 /* main.m */,
|
||||||
6A0D4EF615FC0DA600ABF4B3 /* vChewing-Prefix.pch */,
|
6A0D4EF615FC0DA600ABF4B3 /* vChewing-Prefix.pch */,
|
||||||
5BDF2D022791C71200838ADB /* NonModalAlertWindowController.swift */,
|
5BDF2D052791DA6700838ADB /* AppDelegate.swift */,
|
||||||
5BDF2D002791C03B00838ADB /* PreferencesWindowController.swift */,
|
|
||||||
D427A9C025ED28CC005D43E0 /* OpenCCBridge.swift */,
|
|
||||||
5BDF2CFD2791BE4400838ADB /* InputSourceHelper.swift */,
|
5BDF2CFD2791BE4400838ADB /* InputSourceHelper.swift */,
|
||||||
|
5BDF2D022791C71200838ADB /* NonModalAlertWindowController.swift */,
|
||||||
|
D427A9C025ED28CC005D43E0 /* OpenCCBridge.swift */,
|
||||||
|
5BC2D28C2793B98F002C0BEC /* PreferencesModule.swift */,
|
||||||
|
5BDF2D002791C03B00838ADB /* PreferencesWindowController.swift */,
|
||||||
D427A9BF25ED28CC005D43E0 /* vChewing-Bridging-Header.h */,
|
D427A9BF25ED28CC005D43E0 /* vChewing-Bridging-Header.h */,
|
||||||
5BA923AC2791B7C20001323A /* vChewingInstaller-Bridging-Header.h */,
|
5BA923AC2791B7C20001323A /* vChewingInstaller-Bridging-Header.h */,
|
||||||
);
|
);
|
||||||
|
@ -380,6 +393,7 @@
|
||||||
6A0D4F1215FC0EB100ABF4B3 /* Engine */ = {
|
6A0D4F1215FC0EB100ABF4B3 /* Engine */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
5BC2D2892793B8DB002C0BEC /* Keyboard */,
|
||||||
5BC2D2832793B434002C0BEC /* vChewing */,
|
5BC2D2832793B434002C0BEC /* vChewing */,
|
||||||
5BA8DAFE27928120009C9FFF /* LanguageModel */,
|
5BA8DAFE27928120009C9FFF /* LanguageModel */,
|
||||||
6A0D4F1315FC0EB100ABF4B3 /* Gramambular */,
|
6A0D4F1315FC0EB100ABF4B3 /* Gramambular */,
|
||||||
|
@ -688,6 +702,7 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
5BDF2CFE2791BE4400838ADB /* InputSourceHelper.swift in Sources */,
|
5BDF2CFE2791BE4400838ADB /* InputSourceHelper.swift in Sources */,
|
||||||
|
5BC2D28B2793B8FB002C0BEC /* EmacsKeyHelper.swift in Sources */,
|
||||||
5BE798A72793280C00337FF9 /* NotifierController.swift in Sources */,
|
5BE798A72793280C00337FF9 /* NotifierController.swift in Sources */,
|
||||||
5B5F4F93279294A300922DC2 /* LanguageModelManager.mm in Sources */,
|
5B5F4F93279294A300922DC2 /* LanguageModelManager.mm in Sources */,
|
||||||
6A0D4ED215FC0D6400ABF4B3 /* InputMethodController.mm in Sources */,
|
6A0D4ED215FC0D6400ABF4B3 /* InputMethodController.mm in Sources */,
|
||||||
|
@ -704,6 +719,7 @@
|
||||||
6A0D4F4515FC0EB100ABF4B3 /* Mandarin.cpp in Sources */,
|
6A0D4F4515FC0EB100ABF4B3 /* Mandarin.cpp in Sources */,
|
||||||
6A0421A815FEF3F50061ED63 /* FastLM.cpp in Sources */,
|
6A0421A815FEF3F50061ED63 /* FastLM.cpp in Sources */,
|
||||||
5BDF2D012791C03B00838ADB /* PreferencesWindowController.swift in Sources */,
|
5BDF2D012791C03B00838ADB /* PreferencesWindowController.swift in Sources */,
|
||||||
|
5BC2D28D2793B98F002C0BEC /* PreferencesModule.swift in Sources */,
|
||||||
5BC3EE1C278FC48C00F5E44C /* VTCandidateController.swift in Sources */,
|
5BC3EE1C278FC48C00F5E44C /* VTCandidateController.swift in Sources */,
|
||||||
5BDF2D032791C71200838ADB /* NonModalAlertWindowController.swift in Sources */,
|
5BDF2D032791C71200838ADB /* NonModalAlertWindowController.swift in Sources */,
|
||||||
5BC3EE1D278FC48C00F5E44C /* HorizontalCandidateController.swift in Sources */,
|
5BC3EE1D278FC48C00F5E44C /* HorizontalCandidateController.swift in Sources */,
|
||||||
|
|
Loading…
Reference in New Issue