Repo // Introducing IMKHelper.

This commit is contained in:
ShikiSuen 2022-09-05 14:39:00 +08:00
parent e85e3382fe
commit 790463d640
9 changed files with 256 additions and 246 deletions

View File

@ -7,23 +7,8 @@
// requirements defined in MIT License.
enum AppleKeyboardConverter {
static let arrDynamicBasicKeyLayout: [String] = [
"com.apple.keylayout.ZhuyinBopomofo",
"com.apple.keylayout.ZhuyinEten",
"org.atelierInmu.vChewing.keyLayouts.vchewingdachen",
"org.atelierInmu.vChewing.keyLayouts.vchewingmitac",
"org.atelierInmu.vChewing.keyLayouts.vchewingibm",
"org.atelierInmu.vChewing.keyLayouts.vchewingseigyou",
"org.atelierInmu.vChewing.keyLayouts.vchewingeten",
"org.unknown.keylayout.vChewingDachen",
"org.unknown.keylayout.vChewingFakeSeigyou",
"org.unknown.keylayout.vChewingETen",
"org.unknown.keylayout.vChewingIBM",
"org.unknown.keylayout.vChewingMiTAC",
]
static var isDynamicBasicKeyboardLayoutEnabled: Bool {
AppleKeyboardConverter.arrDynamicBasicKeyLayout.contains(mgrPrefs.basicKeyboardLayout)
IMKHelper.arrDynamicBasicKeyLayouts.contains(mgrPrefs.basicKeyboardLayout)
}
static func cnvStringApple2ABC(_ strProcessed: String) -> String {

View File

@ -134,7 +134,8 @@ extension IMEState {
return result
}
public static func ofCandidates(candidates: [(String, String)], displayTextSegments: [String], cursor: Int) -> IMEState
public static func ofCandidates(candidates: [(String, String)], displayTextSegments: [String], cursor: Int)
-> IMEState
{
var result = IMEState.ofNotEmpty(displayTextSegments: displayTextSegments, cursor: cursor)
result.type = .ofCandidates

View File

@ -13,7 +13,7 @@ import InputMethodKit
public enum vChewing {}
// The type of input modes.
public enum InputMode: String {
public enum InputMode: String, CaseIterable {
case imeModeCHS = "org.atelierInmu.inputmethod.vChewing.IMECHS"
case imeModeCHT = "org.atelierInmu.inputmethod.vChewing.IMECHT"
case imeModeNULL = ""
@ -223,152 +223,6 @@ public enum IME {
}
return 0
}
// MARK: - Registering the input method.
@discardableResult static func registerInputMethod() -> Int32 {
guard let bundleID = Bundle.main.bundleIdentifier else {
return -1
}
let bundleUrl = Bundle.main.bundleURL
var maybeInputSource = InputSourceHelper.inputSource(for: bundleID)
if maybeInputSource == nil {
NSLog("Registering input source \(bundleID) at \(bundleUrl.absoluteString)")
// then register
let status = InputSourceHelper.registerTnputSource(at: bundleUrl)
if !status {
NSLog(
"Fatal error: Cannot register input source \(bundleID) at \(bundleUrl.absoluteString)."
)
return -1
}
maybeInputSource = InputSourceHelper.inputSource(for: bundleID)
}
guard let inputSource = maybeInputSource else {
NSLog("Fatal error: Cannot find input source \(bundleID) after registration.")
return -1
}
if !InputSourceHelper.inputSourceEnabled(for: inputSource) {
NSLog("Enabling input source \(bundleID) at \(bundleUrl.absoluteString).")
let status = InputSourceHelper.enable(inputSource: inputSource)
if !status {
NSLog("Fatal error: Cannot enable input source \(bundleID).")
return -1
}
if !InputSourceHelper.inputSourceEnabled(for: inputSource) {
NSLog("Fatal error: Cannot enable input source \(bundleID).")
return -1
}
}
if CommandLine.arguments.count > 2, CommandLine.arguments[2] == "--all" {
let enabled = InputSourceHelper.enableAllInputMode(for: bundleID)
NSLog(
enabled
? "All input sources enabled for \(bundleID)"
: "Cannot enable all input sources for \(bundleID), but this is ignored")
}
return 0
}
// MARK: - ASCII
struct CarbonKeyboardLayout {
var strName: String = ""
var strValue: String = ""
}
static let arrWhitelistedKeyLayoutsASCII: [String] = [
"com.apple.keylayout.ABC",
"com.apple.keylayout.ABC-AZERTY",
"com.apple.keylayout.ABC-QWERTZ",
"com.apple.keylayout.British",
"com.apple.keylayout.Colemak",
"com.apple.keylayout.Dvorak",
"com.apple.keylayout.Dvorak-Left",
"com.apple.keylayout.DVORAK-QWERTYCMD",
"com.apple.keylayout.Dvorak-Right",
]
static var arrEnumerateSystemKeyboardLayouts: [IME.CarbonKeyboardLayout] {
// macOS
var arrKeyLayouts: [IME.CarbonKeyboardLayout] = []
arrKeyLayouts += [
IME.CarbonKeyboardLayout(
strName: NSLocalizedString("Apple Chewing - Dachen", comment: ""),
strValue: "com.apple.keylayout.ZhuyinBopomofo"
),
IME.CarbonKeyboardLayout(
strName: NSLocalizedString("Apple Chewing - Eten Traditional", comment: ""),
strValue: "com.apple.keylayout.ZhuyinEten"
),
]
// ASCII
var arrKeyLayoutsMACV: [IME.CarbonKeyboardLayout] = []
var arrKeyLayoutsASCII: [IME.CarbonKeyboardLayout] = []
let list = TISCreateInputSourceList(nil, true).takeRetainedValue() as! [TISInputSource]
for source in list {
if let ptrCategory = TISGetInputSourceProperty(source, kTISPropertyInputSourceCategory) {
let category = Unmanaged<CFString>.fromOpaque(ptrCategory).takeUnretainedValue()
if category != kTISCategoryKeyboardInputSource {
continue
}
} else {
continue
}
if let ptrASCIICapable = TISGetInputSourceProperty(
source, kTISPropertyInputSourceIsASCIICapable
) {
let asciiCapable = Unmanaged<CFBoolean>.fromOpaque(ptrASCIICapable)
.takeUnretainedValue()
if asciiCapable != kCFBooleanTrue {
continue
}
} else {
continue
}
if let ptrSourceType = TISGetInputSourceProperty(source, kTISPropertyInputSourceType) {
let sourceType = Unmanaged<CFString>.fromOpaque(ptrSourceType).takeUnretainedValue()
if sourceType != kTISTypeKeyboardLayout {
continue
}
} else {
continue
}
guard let ptrSourceID = TISGetInputSourceProperty(source, kTISPropertyInputSourceID),
let localizedNamePtr = TISGetInputSourceProperty(source, kTISPropertyLocalizedName)
else {
continue
}
let sourceID = String(Unmanaged<CFString>.fromOpaque(ptrSourceID).takeUnretainedValue())
let localizedName = String(
Unmanaged<CFString>.fromOpaque(localizedNamePtr).takeUnretainedValue())
if sourceID.contains("vChewing") {
arrKeyLayoutsMACV += [
IME.CarbonKeyboardLayout(strName: localizedName, strValue: sourceID)
]
}
if IME.arrWhitelistedKeyLayoutsASCII.contains(sourceID) {
arrKeyLayoutsASCII += [
IME.CarbonKeyboardLayout(strName: localizedName, strValue: sourceID)
]
}
}
arrKeyLayouts += arrKeyLayoutsMACV
arrKeyLayouts += arrKeyLayoutsASCII
return arrKeyLayouts
}
}
// MARK: - Root Extensions

View File

@ -0,0 +1,226 @@
// (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 Foundation
import InputMethodKit
// MARK: - IMKHelper by The vChewing Project (MIT License).
enum IMKHelper {
///
/// SwiftUI 便使
static let arrWhitelistedKeyLayoutsASCII: [String] = [
"com.apple.keylayout.ABC",
"com.apple.keylayout.ABC-AZERTY",
"com.apple.keylayout.ABC-QWERTZ",
"com.apple.keylayout.British",
"com.apple.keylayout.Colemak",
"com.apple.keylayout.Dvorak",
"com.apple.keylayout.Dvorak-Left",
"com.apple.keylayout.DVORAK-QWERTYCMD",
"com.apple.keylayout.Dvorak-Right",
]
static let arrDynamicBasicKeyLayouts: [String] = [
"com.apple.keylayout.ZhuyinBopomofo",
"com.apple.keylayout.ZhuyinEten",
"org.atelierInmu.vChewing.keyLayouts.vchewingdachen",
"org.atelierInmu.vChewing.keyLayouts.vchewingmitac",
"org.atelierInmu.vChewing.keyLayouts.vchewingibm",
"org.atelierInmu.vChewing.keyLayouts.vchewingseigyou",
"org.atelierInmu.vChewing.keyLayouts.vchewingeten",
"org.unknown.keylayout.vChewingDachen",
"org.unknown.keylayout.vChewingFakeSeigyou",
"org.unknown.keylayout.vChewingETen",
"org.unknown.keylayout.vChewingIBM",
"org.unknown.keylayout.vChewingMiTAC",
]
static var allowedBasicLayoutsAsTISInputSources: [TISInputSource?] {
//
var containerA: [TISInputSource?] = []
var containerB: [TISInputSource?] = []
var containerC: [TISInputSource?] = []
let rawDictionary = TISInputSource.rawTISInputSources(onlyASCII: false)
IMKHelper.arrWhitelistedKeyLayoutsASCII.forEach {
if let neta = rawDictionary[$0], !arrDynamicBasicKeyLayouts.contains(neta.identifier) {
containerC.append(neta)
}
}
IMKHelper.arrDynamicBasicKeyLayouts.forEach {
if let neta = rawDictionary[$0] {
if neta.identifier.contains("com.apple") {
containerA.append(neta)
} else {
containerB.append(neta)
}
}
}
// nil
if !containerA.isEmpty { containerA.append(nil) }
if !containerB.isEmpty { containerB.append(nil) }
return containerA + containerB + containerC
}
struct CarbonKeyboardLayout {
var strName: String = ""
var strValue: String = ""
}
}
// MARK: -
extension IMKHelper {
@discardableResult static func registerInputMethod() -> Int32 {
TISInputSource.registerInputMethod() ? 0 : -1
}
}
// MARK: - TISInputSource Extension by The vChewing Project (MIT License).
extension TISInputSource {
public static var allRegisteredInstancesOfThisInputMethod: [TISInputSource] {
TISInputSource.modes.compactMap { TISInputSource.generate(from: $0) }
}
public static var modes: [String] {
guard let components = Bundle.main.infoDictionary?["ComponentInputModeDict"] as? [String: Any],
let tsInputModeListKey = components["tsInputModeListKey"] as? [String: Any]
else {
return []
}
return tsInputModeListKey.keys.map { $0 }
}
@discardableResult public static func registerInputMethod() -> Bool {
let instances = TISInputSource.allRegisteredInstancesOfThisInputMethod
if instances.isEmpty {
//
NSLog("Registering input source.")
if !TISInputSource.registerInputSource() {
NSLog("Input source registration failed.")
return false
}
}
var succeeded = true
instances.forEach {
NSLog("Enabling input source: \($0.identifier)")
if !$0.activate() {
NSLog("Failed from enabling input source: \($0.identifier)")
succeeded = false
}
}
return succeeded
}
@discardableResult public static func registerInputSource() -> Bool {
TISRegisterInputSource(Bundle.main.bundleURL as CFURL) == noErr
}
@discardableResult public func activate() -> Bool {
TISEnableInputSource(self) == noErr
}
@discardableResult public func select() -> Bool {
if !isSelectable {
NSLog("Non-selectable: \(identifier)")
return false
}
if TISSelectInputSource(self) != noErr {
NSLog("Failed from switching to \(identifier)")
return false
}
return true
}
@discardableResult public func deactivate() -> Bool {
TISDisableInputSource(self) == noErr
}
public var isActivated: Bool {
unsafeBitCast(TISGetInputSourceProperty(self, kTISPropertyInputSourceIsEnabled), to: CFBoolean.self)
== kCFBooleanTrue
}
public var isSelectable: Bool {
unsafeBitCast(TISGetInputSourceProperty(self, kTISPropertyInputSourceIsSelectCapable), to: CFBoolean.self)
== kCFBooleanTrue
}
public static func generate(from identifier: String) -> TISInputSource? {
TISInputSource.rawTISInputSources(onlyASCII: false)[identifier] ?? nil
}
public var inputModeID: String {
unsafeBitCast(TISGetInputSourceProperty(self, kTISPropertyInputModeID), to: NSString.self) as String
}
public var vChewingLocalizedName: String {
switch identifier {
case "com.apple.keylayout.ZhuyinBopomofo":
return NSLocalizedString("Apple Zhuyin Bopomofo (Dachen)", comment: "")
case "com.apple.keylayout.ZhuyinEten":
return NSLocalizedString("Apple Zhuyin Eten (Traditional)", comment: "")
default: return localizedName
}
}
}
// MARK: - TISInputSource Extension by Mizuno Hiroki (a.k.a. "Mzp") (MIT License)
// Ref: Original source codes are written in Swift 4 from Mzp's InputMethodKit textbook.
// Note: Slightly modified by vChewing Project: Using Dictionaries when necessary.
extension TISInputSource {
public var localizedName: String {
unsafeBitCast(TISGetInputSourceProperty(self, kTISPropertyLocalizedName), to: NSString.self) as String
}
public var identifier: String {
unsafeBitCast(TISGetInputSourceProperty(self, kTISPropertyInputSourceID), to: NSString.self) as String
}
public var scriptCode: Int {
let r = TISGetInputSourceProperty(self, "TSMInputSourcePropertyScriptCode" as CFString)
return unsafeBitCast(r, to: NSString.self).integerValue
}
public static func rawTISInputSources(onlyASCII: Bool = false) -> [String: TISInputSource] {
// CFDictionary
//
let conditions = CFDictionaryCreateMutable(nil, 2, nil, nil)
if onlyASCII {
//
CFDictionaryAddValue(
conditions, unsafeBitCast(kTISPropertyInputSourceType, to: UnsafeRawPointer.self),
unsafeBitCast(kTISTypeKeyboardLayout, to: UnsafeRawPointer.self)
)
// ASCII
CFDictionaryAddValue(
conditions, unsafeBitCast(kTISPropertyInputSourceIsASCIICapable, to: UnsafeRawPointer.self),
unsafeBitCast(kCFBooleanTrue, to: UnsafeRawPointer.self)
)
}
//
var result = TISCreateInputSourceList(conditions, true).takeRetainedValue() as? [TISInputSource] ?? .init()
if onlyASCII {
result = result.filter { $0.scriptCode == 0 }
}
var resultDictionary: [String: TISInputSource] = [:]
result.forEach {
resultDictionary[$0.inputModeID] = $0
resultDictionary[$0.identifier] = $0
}
return resultDictionary
}
}

View File

@ -93,12 +93,12 @@ struct suiPrefPaneKeyboard: View {
mgrPrefs.mandarinParser = value
switch value {
case 0:
if !AppleKeyboardConverter.arrDynamicBasicKeyLayout.contains(mgrPrefs.basicKeyboardLayout) {
if !IMKHelper.arrDynamicBasicKeyLayouts.contains(mgrPrefs.basicKeyboardLayout) {
mgrPrefs.basicKeyboardLayout = "com.apple.keylayout.ZhuyinBopomofo"
selBasicKeyboardLayout = mgrPrefs.basicKeyboardLayout
}
default:
if AppleKeyboardConverter.arrDynamicBasicKeyLayout.contains(mgrPrefs.basicKeyboardLayout) {
if IMKHelper.arrDynamicBasicKeyLayouts.contains(mgrPrefs.basicKeyboardLayout) {
mgrPrefs.basicKeyboardLayout = "com.apple.keylayout.ABC"
selBasicKeyboardLayout = mgrPrefs.basicKeyboardLayout
}
@ -170,15 +170,19 @@ struct suiPrefPaneKeyboard: View {
selection: $selBasicKeyboardLayout.onChange {
let value = selBasicKeyboardLayout
mgrPrefs.basicKeyboardLayout = value
if AppleKeyboardConverter.arrDynamicBasicKeyLayout.contains(value) {
if IMKHelper.arrDynamicBasicKeyLayouts.contains(value) {
mgrPrefs.mandarinParser = 0
selMandarinParser = mgrPrefs.mandarinParser
}
}
) {
ForEach(0...(IME.arrEnumerateSystemKeyboardLayouts.count - 1), id: \.self) { id in
Text(IME.arrEnumerateSystemKeyboardLayouts[id].strName).tag(
IME.arrEnumerateSystemKeyboardLayouts[id].strValue)
ForEach(0...(IMKHelper.allowedBasicLayoutsAsTISInputSources.count - 1), id: \.self) { id in
let theEntry = IMKHelper.allowedBasicLayoutsAsTISInputSources[id]
if let theEntry = theEntry {
Text(theEntry.vChewingLocalizedName).tag(theEntry.identifier)
} else {
Divider()
}
}.id(UUID())
}
.labelsHidden()

View File

@ -23,7 +23,7 @@ switch max(CommandLine.arguments.count - 1, 0) {
switch CommandLine.arguments[1] {
case "install":
if CommandLine.arguments[1] == "install" {
let exitCode = IME.registerInputMethod()
let exitCode = IMKHelper.registerInputMethod()
exit(exitCode)
}
case "uninstall":

View File

@ -93,88 +93,24 @@ class ctlPrefWindow: NSWindowController {
currentLanguageSelectItem = chosenLanguageItem ?? autoMUISelectItem
uiLanguageButton.select(currentLanguageSelectItem)
let list = TISCreateInputSourceList(nil, true).takeRetainedValue() as! [TISInputSource]
var usKeyboardLayoutItem: NSMenuItem?
var chosenBaseKeyboardLayoutItem: NSMenuItem?
basicKeyboardLayoutButton.menu?.removeAllItems()
let itmAppleZhuyinBopomofo = NSMenuItem()
itmAppleZhuyinBopomofo.title = NSLocalizedString("Apple Zhuyin Bopomofo (Dachen)", comment: "")
itmAppleZhuyinBopomofo.representedObject = String(
"com.apple.keylayout.ZhuyinBopomofo")
basicKeyboardLayoutButton.menu?.addItem(itmAppleZhuyinBopomofo)
let itmAppleZhuyinEten = NSMenuItem()
itmAppleZhuyinEten.title = NSLocalizedString("Apple Zhuyin Eten (Traditional)", comment: "")
itmAppleZhuyinEten.representedObject = String("com.apple.keylayout.ZhuyinEten")
basicKeyboardLayoutButton.menu?.addItem(itmAppleZhuyinEten)
let basicKeyboardLayoutID = mgrPrefs.basicKeyboardLayout
for source in list {
if let categoryPtr = TISGetInputSourceProperty(source, kTISPropertyInputSourceCategory) {
let category = Unmanaged<CFString>.fromOpaque(categoryPtr).takeUnretainedValue()
if category != kTISCategoryKeyboardInputSource {
continue
}
} else {
for source in IMKHelper.allowedBasicLayoutsAsTISInputSources {
guard let source = source else {
basicKeyboardLayoutButton.menu?.addItem(NSMenuItem.separator())
continue
}
if let asciiCapablePtr = TISGetInputSourceProperty(
source, kTISPropertyInputSourceIsASCIICapable
) {
let asciiCapable = Unmanaged<CFBoolean>.fromOpaque(asciiCapablePtr)
.takeUnretainedValue()
if asciiCapable != kCFBooleanTrue {
continue
}
} else {
continue
}
if let sourceTypePtr = TISGetInputSourceProperty(source, kTISPropertyInputSourceType) {
let sourceType = Unmanaged<CFString>.fromOpaque(sourceTypePtr).takeUnretainedValue()
if sourceType != 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())
let menuItem = NSMenuItem()
menuItem.title = localizedName
menuItem.representedObject = sourceID
if sourceID == "com.apple.keylayout.US" {
usKeyboardLayoutItem = menuItem
}
if basicKeyboardLayoutID == sourceID {
chosenBaseKeyboardLayoutItem = menuItem
}
if IME.arrWhitelistedKeyLayoutsASCII.contains(sourceID) || sourceID.contains("vChewing") {
basicKeyboardLayoutButton.menu?.addItem(menuItem)
}
}
switch basicKeyboardLayoutID {
case "com.apple.keylayout.ZhuyinBopomofo":
chosenBaseKeyboardLayoutItem = itmAppleZhuyinBopomofo
case "com.apple.keylayout.ZhuyinEten":
chosenBaseKeyboardLayoutItem = itmAppleZhuyinEten
default:
break // nothing to do
menuItem.title = source.vChewingLocalizedName
menuItem.representedObject = source.identifier
if source.identifier == "com.apple.keylayout.US" { usKeyboardLayoutItem = menuItem }
if basicKeyboardLayoutID == source.identifier { chosenBaseKeyboardLayoutItem = menuItem }
basicKeyboardLayoutButton.menu?.addItem(menuItem)
}
basicKeyboardLayoutButton.select(chosenBaseKeyboardLayoutItem ?? usKeyboardLayoutItem)

View File

@ -10,6 +10,7 @@
5B09307628B6FC3B0021F8C5 /* shortcuts.html in Resources */ = {isa = PBXBuildFile; fileRef = 5B09307828B6FC3B0021F8C5 /* shortcuts.html */; };
5B0AF8B527B2C8290096FE54 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B0AF8B427B2C8290096FE54 /* StringExtension.swift */; };
5B11328927B94CFB00E58451 /* AppleKeyboardConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B11328827B94CFB00E58451 /* AppleKeyboardConverter.swift */; };
5B175FFB28C5CDDC0078D1B4 /* IMKHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B175FFA28C5CDDC0078D1B4 /* IMKHelper.swift */; };
5B20430728BEE30900BFC6FD /* BookmarkManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B20430628BEE30900BFC6FD /* BookmarkManager.swift */; };
5B21176C287539BB000443A9 /* ctlInputMethod_HandleStates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B21176B287539BB000443A9 /* ctlInputMethod_HandleStates.swift */; };
5B21176E28753B35000443A9 /* ctlInputMethod_HandleDisplay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B21176D28753B35000443A9 /* ctlInputMethod_HandleDisplay.swift */; };
@ -32,7 +33,6 @@
5B5948CE289CC04500C85824 /* LMInstantiator_DateTimeExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B5948CD289CC04500C85824 /* LMInstantiator_DateTimeExtension.swift */; };
5B5E535227EF261400C6AA1E /* IME.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B5E535127EF261400C6AA1E /* IME.swift */; };
5B62A32927AE77D100A19448 /* FSEventStreamHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A32827AE77D100A19448 /* FSEventStreamHelper.swift */; };
5B62A33227AE792F00A19448 /* InputSourceHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A33127AE792F00A19448 /* InputSourceHelper.swift */; };
5B62A33627AE795800A19448 /* mgrPrefs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A33527AE795800A19448 /* mgrPrefs.swift */; };
5B62A33D27AE7CC100A19448 /* ctlAboutWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A33C27AE7CC100A19448 /* ctlAboutWindow.swift */; };
5B62A34727AE7CD900A19448 /* ctlCandidate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A34027AE7CD900A19448 /* ctlCandidate.swift */; };
@ -116,6 +116,7 @@
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 */; };
5BF0B84C28C070B000795FC6 /* NSEventExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF0B84B28C070B000795FC6 /* NSEventExtension.swift */; };
5BF13B9428C627BB00E99EC1 /* IMKHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B175FFA28C5CDDC0078D1B4 /* IMKHelper.swift */; };
5BF56F9828C39A2700DD6839 /* IMEState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF56F9728C39A2700DD6839 /* IMEState.swift */; };
5BF56F9A28C39D1800DD6839 /* IMEStateData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF56F9928C39D1800DD6839 /* IMEStateData.swift */; };
5BF9DA2728840E6200DBD48E /* template-usersymbolphrases.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2228840E6200DBD48E /* template-usersymbolphrases.txt */; };
@ -213,6 +214,7 @@
5B0AF8B427B2C8290096FE54 /* StringExtension.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = StringExtension.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
5B0C5EDF27C7D9870078037C /* dataCompiler.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = dataCompiler.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
5B11328827B94CFB00E58451 /* AppleKeyboardConverter.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = AppleKeyboardConverter.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
5B175FFA28C5CDDC0078D1B4 /* IMKHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IMKHelper.swift; sourceTree = "<group>"; };
5B18BA6F27C7BD8B0056EB19 /* LICENSE-CHS.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = "LICENSE-CHS.txt"; sourceTree = "<group>"; };
5B18BA7027C7BD8B0056EB19 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
5B18BA7127C7BD8B0056EB19 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
@ -524,7 +526,7 @@
children = (
5BDC1CF927FDF1310052C2B9 /* apiUpdate.swift */,
5B5E535127EF261400C6AA1E /* IME.swift */,
5B62A33127AE792F00A19448 /* InputSourceHelper.swift */,
5B175FFA28C5CDDC0078D1B4 /* IMKHelper.swift */,
5B62A33527AE795800A19448 /* mgrPrefs.swift */,
);
path = IMEModules;
@ -884,6 +886,7 @@
5BBBB77827AEDB330023B93A /* Resources */,
D4F0BBE0279AF8B30071253C /* AppDelegate.swift */,
D4F0BBDE279AF1AF0071253C /* ArchiveUtil.swift */,
5B62A33127AE792F00A19448 /* InputSourceHelper.swift */,
6ACA41F215FC1D9000935EF6 /* Installer-Info.plist */,
5BC0AACA27F58472002D33E9 /* pkgPostInstall.sh */,
5BC0AAC927F58472002D33E9 /* pkgPreInstall.sh */,
@ -1250,13 +1253,13 @@
5B2170E3289FACAD00BE7304 /* 3_KeyValuePaired.swift in Sources */,
5BA9FD0F27FEDB6B002DE248 /* suiPrefPaneGeneral.swift in Sources */,
5B2170E6289FACAD00BE7304 /* 4_Span.swift in Sources */,
5B175FFB28C5CDDC0078D1B4 /* IMKHelper.swift in Sources */,
5BA9FD4927FEF3C9002DE248 /* Section.swift in Sources */,
5BA9FD3E27FEF3C8002DE248 /* Utilities.swift in Sources */,
5B242403284B0D6500520FE4 /* ctlCandidateUniversal.swift in Sources */,
5BA9FD1127FEDB6B002DE248 /* ctlPrefUI.swift in Sources */,
5B8457A12871ADBE00C93B01 /* HotenkaCCBridge.swift in Sources */,
5B40730D281672610023DFFF /* lmReplacements.swift in Sources */,
5B62A33227AE792F00A19448 /* InputSourceHelper.swift in Sources */,
5B5E535227EF261400C6AA1E /* IME.swift in Sources */,
5B2170E0289FACAD00BE7304 /* 7_LangModel.swift in Sources */,
5B62A34927AE7CD900A19448 /* TooltipController.swift in Sources */,
@ -1286,6 +1289,7 @@
D4F0BBE1279AF8B30071253C /* AppDelegate.swift in Sources */,
D4F0BBDF279AF1AF0071253C /* ArchiveUtil.swift in Sources */,
5B62A35327AE89C400A19448 /* InputSourceHelper.swift in Sources */,
5BF13B9428C627BB00E99EC1 /* IMKHelper.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};