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:
ShikiSuen 2022-01-16 11:55:04 +08:00
parent 5f0a0bad6f
commit 56f76b71d5
11 changed files with 668 additions and 448 deletions

View File

@ -203,7 +203,7 @@
<constraints>
<constraint firstAttribute="height" constant="16" id="o6K-VN-uxe"/>
</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"/>
<font key="font" metaFont="cellTitle"/>
</buttonCell>

View File

@ -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;
}
}

View File

@ -80,11 +80,5 @@
// current input mode
NSString *_inputMode;
// if Chinese conversion is enabled
BOOL _chineseConversionEnabled;
// if half-width punctuation is enabled
BOOL _halfWidthPunctuationEnabled;
}
@end

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
//
// PreferencesWindowController.swift
// OpenCCBridge.swift
//
// Copyright (c) 2011-2022 The OpenVanilla Project.
//
@ -34,22 +34,23 @@
import Foundation
import OpenCC
// Since SwiftyLibreCC only provide Swift classes, we create an NSObject subclass
// in Swift in order to bridge the Swift classes into our Objective-C++ project.
class OpenCCBridge : NSObject {
/// A bridge to let Objctive-C code to access SwiftyOpenCC.
///
/// 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 var converter: ChineseConverter?
private override init() {
try? converter = ChineseConverter(options: .twStandardRev)
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)
}
private func convert(_ string: String) -> String? {
converter?.convert(string)
}
}

View File

@ -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
}
}

View File

@ -36,9 +36,13 @@
import Cocoa
import Carbon
private let kBasisKeyboardLayoutPreferenceKey = "BasisKeyboardLayout"
private let kCandidateKeys = "CandidateKeys"
private let kDefaultKeys = "123456789"
// Extend the RangeReplaceableCollection to allow it clean duplicated characters.
extension RangeReplaceableCollection where Element: Hashable {
var charDeDuplicate: Self {
var set = Set<Element>()
return filter{ set.insert($0).inserted }
}
}
// 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
@ -47,55 +51,78 @@ private let kDefaultKeys = "123456789"
@IBOutlet weak var fontSizePopUpButton: NSPopUpButton!
@IBOutlet weak var basisKeyboardLayoutButton: NSPopUpButton!
@IBOutlet weak var selectionKeyComboBox: NSComboBox!
override func awakeFromNib() {
let list = TISCreateInputSourceList(nil, true).takeRetainedValue() as! [TISInputSource]
var usKeyboardLayoutItem: NSMenuItem? = nil
var chosenItem: NSMenuItem? = nil
basisKeyboardLayoutButton.menu?.removeAllItems()
let basisKeyboardLayoutID = UserDefaults.standard.string(forKey: kBasisKeyboardLayoutPreferenceKey)
let basisKeyboardLayoutID = Preferences.basisKeyboardLayout
for source in list {
if let categoryPtr = TISGetInputSourceProperty(source, kTISPropertyInputSourceCategory) {
let category = Unmanaged<CFString>.fromOpaque(categoryPtr).takeUnretainedValue()
if category != kTISCategoryKeyboardInputSource {
func getString(_ key: CFString) -> String? {
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
}
} else {
continue
}
if let asciiCapablePtr = TISGetInputSourceProperty(source, kTISPropertyInputSourceIsASCIICapable) {
let asciiCapable = Unmanaged<CFBoolean>.fromOpaque(asciiCapablePtr).takeUnretainedValue()
if asciiCapable != kCFBooleanTrue {
if let asciiCapable = getBool(kTISPropertyInputSourceIsASCIICapable) {
if !asciiCapable {
continue
}
} else {
continue
}
if let sourceTypePtr = TISGetInputSourceProperty(source, kTISPropertyInputSourceType) {
let sourceType = Unmanaged<CFString>.fromOpaque(sourceTypePtr).takeUnretainedValue()
if sourceType != kTISTypeKeyboardLayout {
if let sourceType = getString(kTISPropertyInputSourceType) {
if sourceType != String(kTISTypeKeyboardLayout) {
continue
}
} else {
continue
}
guard let sourceIDPtr = TISGetInputSourceProperty(source, kTISPropertyInputSourceID),
let localizedNamePtr = TISGetInputSourceProperty(source, kTISPropertyLocalizedName) else {
continue
}
let sourceID = String(Unmanaged<CFString>.fromOpaque(sourceIDPtr).takeUnretainedValue())
let localizedName = String(Unmanaged<CFString>.fromOpaque(localizedNamePtr).takeUnretainedValue())
guard let sourceID = getString(kTISPropertyInputSourceID),
let localizedName = getString(kTISPropertyLocalizedName) else {
continue
}
let menuItem = NSMenuItem()
menuItem.title = localizedName
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" {
usKeyboardLayoutItem = menuItem
}
@ -104,41 +131,41 @@ private let kDefaultKeys = "123456789"
}
basisKeyboardLayoutButton.menu?.addItem(menuItem)
}
basisKeyboardLayoutButton.select(chosenItem ?? usKeyboardLayoutItem)
selectionKeyComboBox.usesDataSource = false
selectionKeyComboBox.addItems(withObjectValues: [kDefaultKeys, "asdfghjkl", "asdfzxcvb"])
var candidateSelectionKeys = (UserDefaults.standard.string(forKey: kCandidateKeys) ?? kDefaultKeys)
.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
selectionKeyComboBox.removeAllItems()
selectionKeyComboBox.addItems(withObjectValues: [Preferences.defaultKeys, "ASDFGHJKL", "ASDFZXCVB"])
var candidateSelectionKeys = Preferences.candidateKeys ?? Preferences.defaultKeys
if candidateSelectionKeys.isEmpty {
candidateSelectionKeys = kDefaultKeys
candidateSelectionKeys = Preferences.defaultKeys
}
selectionKeyComboBox.stringValue = candidateSelectionKeys
}
@IBAction func updateBasisKeyboardLayoutAction(_ sender:Any) {
if let sourceID = basisKeyboardLayoutButton.selectedItem?.representedObject {
UserDefaults.standard.set(sourceID, forKey: kBasisKeyboardLayoutPreferenceKey)
@IBAction func updateBasisKeyboardLayoutAction(_ sender: Any) {
if let sourceID = basisKeyboardLayoutButton.selectedItem?.representedObject as? String {
Preferences.basisKeyboardLayout = sourceID
}
}
@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) {
selectionKeyComboBox.stringValue = kDefaultKeys
UserDefaults.standard.removeObject(forKey: kCandidateKeys)
selectionKeyComboBox.stringValue = Preferences.defaultKeys
Preferences.candidateKeys = nil
NSSound.beep()
return
}
selectionKeyComboBox.stringValue = keys
if keys == kDefaultKeys {
UserDefaults.standard.removeObject(forKey: kCandidateKeys)
if keys == Preferences.defaultKeys {
Preferences.candidateKeys = nil
} else {
UserDefaults.standard.set(keys, forKey: kCandidateKeys)
Preferences.candidateKeys = keys
}
}
}

View 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?%@" = "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";
"NotificationSwitchON" = " ON";
"NotificationSwitchOFF" = " OFF";
"NotificationSwitchON" = " ON";
"NotificationSwitchOFF" = " OFF";
"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.";

View File

@ -17,8 +17,8 @@
"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$@";
"Chinese Conversion" = "优先使用康熙繁体字";
"NotificationSwitchON" = " 已启用";
"NotificationSwitchOFF" = " 已停用";
"NotificationSwitchON" = " 已启用";
"NotificationSwitchOFF" = " 已停用";
"Edit User Phrases" = "编辑自订语汇";
"Reload User Phrases" = "重载自订语汇";
"Unable to create the user phrase file." = "无法创建自订语汇档案。";

View File

@ -17,8 +17,8 @@
"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$@";
"Chinese Conversion" = "優先使用康熙繁體字";
"NotificationSwitchON" = " 已啟用";
"NotificationSwitchOFF" = " 已停用";
"NotificationSwitchON" = " 已啟用";
"NotificationSwitchOFF" = " 已停用";
"Edit User Phrases" = "編輯自訂語彙";
"Reload User Phrases" = "重載自訂語彙";
"Unable to create the user phrase file." = "無法創建自訂語彙檔案。";

View File

@ -17,6 +17,8 @@
5B5F4F972792A4EA00922DC2 /* UserPhrasesLM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5B5F4F962792A4EA00922DC2 /* UserPhrasesLM.cpp */; };
5BC2D2872793B434002C0BEC /* CMakeLists.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BC2D2852793B434002C0BEC /* CMakeLists.txt */; };
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 */; };
5BC3EE1C278FC48C00F5E44C /* VTCandidateController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC3EE19278FC48C00F5E44C /* VTCandidateController.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>"; };
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>"; };
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>"; };
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>"; };
@ -272,6 +276,14 @@
path = vChewing;
sourceTree = "<group>";
};
5BC2D2892793B8DB002C0BEC /* Keyboard */ = {
isa = PBXGroup;
children = (
5BC2D28A2793B8FB002C0BEC /* EmacsKeyHelper.swift */,
);
path = Keyboard;
sourceTree = "<group>";
};
5BE798A12792E50F00337FF9 /* UI */ = {
isa = PBXGroup;
children = (
@ -336,7 +348,6 @@
6A0D4F1215FC0EB100ABF4B3 /* Engine */,
6ACA41E715FC1D9000935EF6 /* Installer */,
6A0D4F4715FC0EB900ABF4B3 /* Resources */,
5BDF2D052791DA6700838ADB /* AppDelegate.swift */,
5BF4A6FB27844738007DC6E7 /* frmAboutWindow.h */,
5BF4A6FC27844738007DC6E7 /* frmAboutWindow.m */,
6A0D4EC615FC0D6400ABF4B3 /* InputMethodController.h */,
@ -345,10 +356,12 @@
5B5F4F92279294A300922DC2 /* LanguageModelManager.mm */,
6A0D4EC815FC0D6400ABF4B3 /* main.m */,
6A0D4EF615FC0DA600ABF4B3 /* vChewing-Prefix.pch */,
5BDF2D022791C71200838ADB /* NonModalAlertWindowController.swift */,
5BDF2D002791C03B00838ADB /* PreferencesWindowController.swift */,
D427A9C025ED28CC005D43E0 /* OpenCCBridge.swift */,
5BDF2D052791DA6700838ADB /* AppDelegate.swift */,
5BDF2CFD2791BE4400838ADB /* InputSourceHelper.swift */,
5BDF2D022791C71200838ADB /* NonModalAlertWindowController.swift */,
D427A9C025ED28CC005D43E0 /* OpenCCBridge.swift */,
5BC2D28C2793B98F002C0BEC /* PreferencesModule.swift */,
5BDF2D002791C03B00838ADB /* PreferencesWindowController.swift */,
D427A9BF25ED28CC005D43E0 /* vChewing-Bridging-Header.h */,
5BA923AC2791B7C20001323A /* vChewingInstaller-Bridging-Header.h */,
);
@ -380,6 +393,7 @@
6A0D4F1215FC0EB100ABF4B3 /* Engine */ = {
isa = PBXGroup;
children = (
5BC2D2892793B8DB002C0BEC /* Keyboard */,
5BC2D2832793B434002C0BEC /* vChewing */,
5BA8DAFE27928120009C9FFF /* LanguageModel */,
6A0D4F1315FC0EB100ABF4B3 /* Gramambular */,
@ -688,6 +702,7 @@
buildActionMask = 2147483647;
files = (
5BDF2CFE2791BE4400838ADB /* InputSourceHelper.swift in Sources */,
5BC2D28B2793B8FB002C0BEC /* EmacsKeyHelper.swift in Sources */,
5BE798A72793280C00337FF9 /* NotifierController.swift in Sources */,
5B5F4F93279294A300922DC2 /* LanguageModelManager.mm in Sources */,
6A0D4ED215FC0D6400ABF4B3 /* InputMethodController.mm in Sources */,
@ -704,6 +719,7 @@
6A0D4F4515FC0EB100ABF4B3 /* Mandarin.cpp in Sources */,
6A0421A815FEF3F50061ED63 /* FastLM.cpp in Sources */,
5BDF2D012791C03B00838ADB /* PreferencesWindowController.swift in Sources */,
5BC2D28D2793B98F002C0BEC /* PreferencesModule.swift in Sources */,
5BC3EE1C278FC48C00F5E44C /* VTCandidateController.swift in Sources */,
5BDF2D032791C71200838ADB /* NonModalAlertWindowController.swift in Sources */,
5BC3EE1D278FC48C00F5E44C /* HorizontalCandidateController.swift in Sources */,