diff --git a/AUTHORS b/AUTHORS index 158911b6..e9eaf28d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,11 +1,15 @@ $ Main contributors and volunteers of this repository (vChewing for macOS): -Shiki Suen // Main developer of vChewing for macOS. -Hiraku Wang // Technical assistant in Cocoa. - +- Shiki Suen // Main developer of vChewing for macOS. +- Hiraku Wang // Technical reinforcement in Cocoa during the Object-Cpp dev period of this project. +- Isaac Xen // Technical reinforcement in Swift: SFX Module and StringView Ranges Extension. $ Contributors and volunteeres of the upstream repo, having no responsibility in discussing anything in the current repo: -Mengjuei Hsieh // McBopomofo for macOS 1.x main developer and architect. -Zonble Yang // McBopomofo for macOS 2.x architect. -Lukhnos D Liu // Mandarin and Gramambular engine developer. +- Mengjuei Hsieh // McBopomofo for macOS 1.x main developer and architect. +- Zonble Yang // McBopomofo for macOS 2.x architect, especially state-based IME behavior management. +- Lukhnos D Liu // Developer of the Mandarin syllable input processor. + +$ Special thanks to: + +- All supporters from Cocoaheads Taipei and Mobile01 community. diff --git a/DataCompiler/dataCompiler.swift b/DataCompiler/dataCompiler.swift index 9122721d..08261761 100644 --- a/DataCompiler/dataCompiler.swift +++ b/DataCompiler/dataCompiler.swift @@ -356,7 +356,7 @@ func weightAndSort(_ arrStructUncalculated: [Entry], isCHS: Bool) -> [Entry] { weight = -13 case 0: // 墊底低頻漢字與詞語 weight = log10( - fscale ** (Float(entry.valPhrase.count) / 3.0 - 1.0) * 0.5 / norm) + fscale ** (Float(entry.valPhrase.count) / 3.0 - 1.0) * 0.25 / norm) default: weight = log10( fscale ** (Float(entry.valPhrase.count) / 3.0 - 1.0) diff --git a/Installer/Resources/Base.lproj/MainMenu.xib b/Installer/Resources/Base.lproj/MainMenu.xib index 2a204c55..71ebe7b7 100644 --- a/Installer/Resources/Base.lproj/MainMenu.xib +++ b/Installer/Resources/Base.lproj/MainMenu.xib @@ -198,7 +198,7 @@ McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al. -vChewing macOS Development: Shiki Suen, Hiraku Wang, etc.
vChewing Phrase Database Maintained by Shiki Suen. +vChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.
vChewing Phrase Database Maintained by Shiki Suen. diff --git a/Installer/Resources/en.lproj/MainMenu.strings b/Installer/Resources/en.lproj/MainMenu.strings index cb7ec3c0..f45a3b26 100644 --- a/Installer/Resources/en.lproj/MainMenu.strings +++ b/Installer/Resources/en.lproj/MainMenu.strings @@ -56,8 +56,8 @@ /* Class = "NSTextFieldCell"; title = "Derived from OpenVanilla McBopopmofo Project."; ObjectID = "QYf-Nf-hoi"; */ "QYf-Nf-hoi.title" = "Derived from OpenVanilla McBopopmofo Project."; -/* Class = "NSTextFieldCell"; title = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; ObjectID = "VW8-s5-Wpn"; */ -"VW8-s5-Wpn.title" = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; +/* Class = "NSTextFieldCell"; title = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; ObjectID = "VW8-s5-Wpn"; */ +"VW8-s5-Wpn.title" = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; /* Class = "NSTextFieldCell"; title = "Placeholder for showing copyright information."; ObjectID = "eo3-TK-0rB"; */ // "eo3-TK-0rB.title" = "Placeholder for showing copyright information."; diff --git a/Installer/Resources/ja.lproj/MainMenu.strings b/Installer/Resources/ja.lproj/MainMenu.strings index cf864cc7..63f67c93 100644 --- a/Installer/Resources/ja.lproj/MainMenu.strings +++ b/Installer/Resources/ja.lproj/MainMenu.strings @@ -56,8 +56,8 @@ /* Class = "NSTextFieldCell"; title = "Derived from OpenVanilla McBopopmofo Project."; ObjectID = "QYf-Nf-hoi"; */ "QYf-Nf-hoi.title" = "OpenVanilla 小麦注音プロジェクトから派生。"; -/* Class = "NSTextFieldCell"; title = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; ObjectID = "VW8-s5-Wpn"; */ -"VW8-s5-Wpn.title" = "ボポモフォエンジン開発:Lukhnos Liu。\n入力状態管理システム開発:Zonble Yang。\nmacOS 版威注音の開発:Shiki Suen, Hiraku Wang, など。\n威注音語彙データの維持:Shiki Suen。\nMegrez 辞書処理エンジン:Shiki Suen(Lukhnos の Gramambular C++ エンジンを Swift で再開発したものである)。"; +/* Class = "NSTextFieldCell"; title = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; ObjectID = "VW8-s5-Wpn"; */ +"VW8-s5-Wpn.title" = "ボポモフォエンジン開発:Lukhnos Liu。\n入力状態管理システム開発:Zonble Yang。\nmacOS 版威注音の開発:Shiki Suen, Isaac Xen, Hiraku Wang, など。\n威注音語彙データの維持:Shiki Suen。\nMegrez 辞書処理エンジン:Shiki Suen(Lukhnos の Gramambular C++ エンジンを Swift で再開発したものである)。"; /* Class = "NSTextFieldCell"; title = "Placeholder for showing copyright information."; ObjectID = "eo3-TK-0rB"; */ "eo3-TK-0rB.title" = "Placeholder for showing copyright information."; diff --git a/Installer/Resources/zh-Hans.lproj/MainMenu.strings b/Installer/Resources/zh-Hans.lproj/MainMenu.strings index 457d2d87..b5ab37d3 100644 --- a/Installer/Resources/zh-Hans.lproj/MainMenu.strings +++ b/Installer/Resources/zh-Hans.lproj/MainMenu.strings @@ -56,9 +56,9 @@ /* Class = "NSTextFieldCell"; title = "Derived from OpenVanilla McBopopmofo Project."; ObjectID = "QYf-Nf-hoi"; */ "QYf-Nf-hoi.title" = "该专案由 OpenVanilla 小麦注音专案衍生而来。"; -/* Class = "NSTextFieldCell"; title = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc. +/* Class = "NSTextFieldCell"; title = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc. vChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "VW8-s5-Wpn"; */ -"VW8-s5-Wpn.title" = "注音拼音输入处理引擎研发:Lukhnos Liu。\n输入法状态管理引擎研发:Zonble Yang。\n威注音 macOS 程式研发:Shiki Suen, Hiraku Wang, 等。\n威注音词库维护:Shiki Suen。\n天权星语汇引擎:Shiki Suen,用 Swift 将 Lukhnos 的 C++ Gramambular 重写而得。"; +"VW8-s5-Wpn.title" = "注音拼音输入处理引擎研发:Lukhnos Liu。\n输入法状态管理引擎研发:Zonble Yang。\n威注音 macOS 程式研发:Shiki Suen, Isaac Xen, Hiraku Wang, 等。\n威注音词库维护:Shiki Suen。\n天权星语汇引擎:Shiki Suen,用 Swift 将 Lukhnos 的 C++ Gramambular 重写而得。"; /* Class = "NSTextFieldCell"; title = "Placeholder for showing copyright information."; ObjectID = "eo3-TK-0rB"; */ // "eo3-TK-0rB.title" = "Placeholder for showing copyright information."; diff --git a/Installer/Resources/zh-Hant.lproj/MainMenu.strings b/Installer/Resources/zh-Hant.lproj/MainMenu.strings index f55afe6e..0996d412 100644 --- a/Installer/Resources/zh-Hant.lproj/MainMenu.strings +++ b/Installer/Resources/zh-Hant.lproj/MainMenu.strings @@ -56,9 +56,9 @@ /* Class = "NSTextFieldCell"; title = "Derived from OpenVanilla McBopopmofo Project."; ObjectID = "QYf-Nf-hoi"; */ "QYf-Nf-hoi.title" = "該專案由 OpenVanilla 小麥注音專案衍生而來。"; -/* Class = "NSTextFieldCell"; title = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc. +/* Class = "NSTextFieldCell"; title = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc. vChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "VW8-s5-Wpn"; */ -"VW8-s5-Wpn.title" = "注音拼音輸入處理引擎研發:Lukhnos Liu。\n輸入法狀態管理引擎研發:Zonble Yang。\n威注音 macOS 程式研發:Shiki Suen, Hiraku Wang, 等。\n威注音詞庫維護:Shiki Suen。\n天權星語彙引擎:Shiki Suen,用 Swift 將 Lukhnos 的 C++ Gramambular 重寫而得。"; +"VW8-s5-Wpn.title" = "注音拼音輸入處理引擎研發:Lukhnos Liu。\n輸入法狀態管理引擎研發:Zonble Yang。\n威注音 macOS 程式研發:Shiki Suen, Isaac Xen, Hiraku Wang, 等。\n威注音詞庫維護:Shiki Suen。\n天權星語彙引擎:Shiki Suen,用 Swift 將 Lukhnos 的 C++ Gramambular 重寫而得。"; /* Class = "NSTextFieldCell"; title = "Placeholder for showing copyright information."; ObjectID = "eo3-TK-0rB"; */ // "eo3-TK-0rB.title" = "Placeholder for showing copyright information."; diff --git a/LICENSE-CHS.txt b/LICENSE-CHS.txt index bdaf5b3c..3539bc05 100644 --- a/LICENSE-CHS.txt +++ b/LICENSE-CHS.txt @@ -5,7 +5,7 @@ vChewing macOS: MIT-NTL License 麻理(去商标)授权合约 © 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project. 注音拼音输入处理引擎研发:Lukhnos Liu。 输入法状态管理引擎研发:Zonble Yang。 -威注音 macOS 程式研发:Shiki Suen, Hiraku Wang, 等。 +威注音 macOS 程式研发:Shiki Suen, Isaac Xen, Hiraku Wang, 等。 威注音词库维护:Shiki Suen。 天权星语汇引擎:Shiki Suen,用 Swift 将 Lukhnos 的 C++ Gramambular 重写而得。 diff --git a/LICENSE-CHT.txt b/LICENSE-CHT.txt index e2e8a84f..b629fd9e 100644 --- a/LICENSE-CHT.txt +++ b/LICENSE-CHT.txt @@ -5,7 +5,7 @@ vChewing macOS: MIT-NTL License 麻理(去商標)授權合約 © 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project. 注音拼音輸入處理引擎研發:Lukhnos Liu。 輸入法狀態管理引擎研發:Zonble Yang。 -威注音 macOS 程式研發:Shiki Suen, Hiraku Wang, 等。 +威注音 macOS 程式研發:Shiki Suen, Isaac Xen, Hiraku Wang, 等。 威注音詞庫維護:Shiki Suen。 天權星語彙引擎:Shiki Suen,用 Swift 將 Lukhnos 的 C++ Gramambular 重寫而得。 diff --git a/LICENSE-JPN.txt b/LICENSE-JPN.txt index 6bf08d35..1061f95e 100644 --- a/LICENSE-JPN.txt +++ b/LICENSE-JPN.txt @@ -4,7 +4,7 @@ vChewing macOS: MIT商標不許可ライセンス (MIT-NTL License) ボポモフォエンジン開発:Lukhnos Liu。 入力状態管理システム開発:Zonble Yang。 -macOS 版威注音の開発:Shiki Suen, Hiraku Wang, など。 +macOS 版威注音の開発:Shiki Suen, Isaac Xen, Hiraku Wang, など。 威注音語彙データの維持:Shiki Suen。 Megrez 辞書処理エンジン:Shiki Suen(Lukhnos の Gramambular C++ エンジンを Swift で再開発したものである)。 diff --git a/LICENSE.txt b/LICENSE.txt index 1d8868ba..e37f0d24 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -5,7 +5,7 @@ vChewing macOS: MIT-NTL License © 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project. Mandarin Syllable Composer Engine by Lukhnos Liu. Input State Management Architecture by Zonble Yang. -vChewing macOS Development: Shiki Suen, Hiraku Wang, etc. +vChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc. vChewing Phrase Database Maintained by Shiki Suen. Megrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine. diff --git a/Source/Modules/IMEModules/IME.swift b/Source/Modules/IMEModules/IME.swift index fbdf2f4d..09b769eb 100644 --- a/Source/Modules/IMEModules/IME.swift +++ b/Source/Modules/IMEModules/IME.swift @@ -64,14 +64,12 @@ public class IME: NSObject { // MARK: - Initializing Language Models. static func initLangModels(userOnly: Bool) { - DispatchQueue.global(qos: .userInitiated).async { - // mgrLangModel 的 loadUserPhrases 等函數在自動讀取 dataFolderPath 時, - // 如果發現自訂目錄不可用,則會自動抹去自訂目錄設定、改採預設目錄。 - // 所以這裡不需要特別處理。 - mgrLangModel.loadUserAssociatedPhrases() - mgrLangModel.loadUserPhraseReplacement() - mgrLangModel.loadUserPhrases() - } + // mgrLangModel 的 loadUserPhrases 等函數在自動讀取 dataFolderPath 時, + // 如果發現自訂目錄不可用,則會自動抹去自訂目錄設定、改採預設目錄。 + // 所以這裡不需要特別處理。 + mgrLangModel.loadUserAssociatedPhrases() + mgrLangModel.loadUserPhraseReplacement() + mgrLangModel.loadUserPhrases() if !userOnly { // mgrLangModel.loadDataModels() } diff --git a/Source/Modules/LangModelRelated/LMInstantiator.swift b/Source/Modules/LangModelRelated/LMInstantiator.swift index c075e5cd..31b2e80c 100644 --- a/Source/Modules/LangModelRelated/LMInstantiator.swift +++ b/Source/Modules/LangModelRelated/LMInstantiator.swift @@ -31,8 +31,10 @@ import Foundation // 簡體中文模式與繁體中文模式共用全字庫擴展模組,故單獨處理。 // 塞在 LMInstantiator 內的話,每個模式都會讀入一份全字庫,會多佔用 100MB 記憶體。 -private var lmCNS = vChewing.LMLite(consolidate: false) -private var lmSymbols = vChewing.LMCore(reverse: true, consolidate: false, defaultScore: -13.0, forceDefaultScore: true) +private var lmCNS = vChewing.LMCoreEX( + reverse: true, consolidate: false, defaultScore: -11.0, forceDefaultScore: false) +private var lmSymbols = vChewing.LMCoreEX( + reverse: true, consolidate: false, defaultScore: -13.0, forceDefaultScore: false) extension vChewing { /// LMInstantiator is a facade for managing a set of models including @@ -62,26 +64,30 @@ extension vChewing { public var isCNSEnabled = false public var isSymbolEnabled = false - /// 介紹一下三個通用的語言模組型別: - /// LMCore 是全功能通用型的模組,每一筆辭典記錄以 key 為注音、以 [Unigram] 陣列作為記錄內容。 + /// 介紹一下幾個通用的語言模組型別: + /// ---------------------- + /// LMCoreEX 是全功能通用型的模組,每一筆辭典記錄以 key 為注音、以 [Unigram] 陣列作為記錄內容。 /// 比較適合那種每筆記錄都有不同的權重數值的語言模組,雖然也可以強制施加權重數值就是了。 - /// 然而缺點是:哪怕你強制施加權重數值,也不會減輕記憶體佔用。 - /// 至於像全字庫這樣所有記錄都使用同一權重數值的模組,可以用 LMLite 以節省記憶體佔用。 - /// LMLite 的辭典內不會存儲權重資料,只會在每次讀取記錄時施加您給定的權重數值。 - /// LMLite 與 LMCore 都會用到多執行緒、以加速載入(不然的話,全部資料載入會耗費八秒左右)。 - /// LMReplacements 與 LMAssociates 均為特種模組,分別擔當語彙置換表資料與使用者聯想詞的資料承載工作。 + /// LMCoreEX 的辭典陣列不承載 Unigram 本體、而是承載索引範圍,這樣可以節約記憶體。 + /// 一個 LMCoreEX 就可以滿足威注音幾乎所有語言模組副本的需求,當然也有這兩個例外: + /// LMReplacements 與 LMAssociates 分別擔當語彙置換表資料與使用者聯想詞的資料承載工作。 // 聲明原廠語言模組 /// Reverse 的話,第一欄是注音,第二欄是對應的漢字,第三欄是可能的權重。 /// 不 Reverse 的話,第一欄是漢字,第二欄是對應的注音,第三欄是可能的權重。 - var lmCore = LMCore(reverse: false, consolidate: false, defaultScore: -9.5, forceDefaultScore: false) - var lmMisc = LMCore(reverse: true, consolidate: false, defaultScore: -1, forceDefaultScore: false) + var lmCore = LMCoreEX( + reverse: false, consolidate: false, defaultScore: -9.9, forceDefaultScore: false) + var lmMisc = LMCoreEX( + reverse: true, consolidate: false, defaultScore: -1.0, forceDefaultScore: false) // 聲明使用者語言模組。 // 使用者語言模組使用多執行緒的話,可能會導致一些問題。有時間再仔細排查看看。 - var lmUserPhrases = LMLite(consolidate: true) - var lmFiltered = LMLite(consolidate: true) - var lmUserSymbols = LMLite(consolidate: true) + var lmUserPhrases = LMCoreEX( + reverse: true, consolidate: true, defaultScore: 0, forceDefaultScore: true) + var lmFiltered = LMCoreEX( + reverse: true, consolidate: true, defaultScore: 0, forceDefaultScore: true) + var lmUserSymbols = LMCoreEX( + reverse: true, consolidate: true, defaultScore: -12.0, forceDefaultScore: true) var lmReplacements = LMReplacments() var lmAssociates = LMAssociates() @@ -201,7 +207,7 @@ extension vChewing { // 用 reversed 指令讓使用者語彙檔案內的詞條優先順序隨著行數增加而逐漸增高。 // 這樣一來就可以在就地新增語彙時徹底複寫優先權。 // 將兩句差分也是為了讓 rawUserUnigrams 的類型不受可能的影響。 - rawAllUnigrams += lmUserPhrases.unigramsFor(key: key, score: 0.0).reversed() + rawAllUnigrams += lmUserPhrases.unigramsFor(key: key).reversed() if lmUserPhrases.unigramsFor(key: key).isEmpty { IME.prtDebugIntel("Not found in UserPhrasesUnigram(\(lmUserPhrases.count)): \(key)") } @@ -211,11 +217,11 @@ extension vChewing { rawAllUnigrams += lmCore.unigramsFor(key: key) if isCNSEnabled { - rawAllUnigrams += lmCNS.unigramsFor(key: key, score: -11) + rawAllUnigrams += lmCNS.unigramsFor(key: key) } if isSymbolEnabled { - rawAllUnigrams += lmUserSymbols.unigramsFor(key: key, score: -12.0) + rawAllUnigrams += lmUserSymbols.unigramsFor(key: key) if lmUserSymbols.unigramsFor(key: key).isEmpty { IME.prtDebugIntel("Not found in UserSymbolUnigram(\(lmUserSymbols.count)): \(key)") } @@ -232,15 +238,6 @@ extension vChewing { filteredPairs.insert(unigram.keyValue) } - var debugOutput = "\n" - for neta in rawAllUnigrams { - debugOutput += "RAW: \(neta.keyValue.key) \(neta.keyValue.value) \(neta.score)\n" - } - if debugOutput == "\n" { - debugOutput = "RAW: No match found in all unigrams." - } - IME.prtDebugIntel(debugOutput) - return filterAndTransform( unigrams: rawAllUnigrams, filter: filteredPairs, inserted: &insertedPairs diff --git a/Source/Modules/LangModelRelated/SubLMs/lmAssociates.swift b/Source/Modules/LangModelRelated/SubLMs/lmAssociates.swift index e5aca9f7..495ca22d 100644 --- a/Source/Modules/LangModelRelated/SubLMs/lmAssociates.swift +++ b/Source/Modules/LangModelRelated/SubLMs/lmAssociates.swift @@ -1,6 +1,5 @@ // Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). -// Refactored from the ObjCpp-version of this class by: -// (c) 2011 and onwards The OpenVanilla Project (MIT License). +// StringView Ranges extension by (c) 2022 and onwards Isaac Xen (MIT License). /* 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 @@ -28,18 +27,19 @@ import Foundation extension vChewing { @frozen public struct LMAssociates { - var keyValueMap: [String: [Megrez.KeyValuePair]] = [:] + var rangeMap: [String: [Range]] = [:] + var strData: String = "" public var count: Int { - keyValueMap.count + rangeMap.count } public init() { - keyValueMap = [:] + rangeMap = [:] } public func isLoaded() -> Bool { - !keyValueMap.isEmpty + !rangeMap.isEmpty } @discardableResult public mutating func open(_ path: String) -> Bool { @@ -50,53 +50,40 @@ extension vChewing { LMConsolidator.fixEOF(path: path) LMConsolidator.consolidate(path: path, pragma: true) - var arrData: [String] = [] - do { - arrData = try String(contentsOfFile: path, encoding: .utf8).components(separatedBy: "\n") + strData = try String(contentsOfFile: path, encoding: .utf8).replacingOccurrences(of: "\t", with: " ") + strData.ranges(splitBy: "\n").forEach { + let neta = strData[$0].components(separatedBy: " ") + if neta.count >= 2 { + let theKey = neta[0] + if !neta[0].isEmpty, !neta[1].isEmpty, theKey.first != "#" { + let theValue = $0 + rangeMap[theKey, default: []].append(theValue) + } + } + } } catch { IME.prtDebugIntel("\(error)") - IME.prtDebugIntel("↑ Exception happened when reading Associated Phrases data.") + IME.prtDebugIntel("↑ Exception happened when reading data at: \(path).") return false } - for (lineID, lineContent) in arrData.enumerated() { - if !lineContent.hasPrefix("#") { - let lineContent = lineContent.replacingOccurrences(of: "\t", with: " ") - if lineContent.components(separatedBy: " ").count < 2 { - if lineContent != "", lineContent != " " { - IME.prtDebugIntel("Line #\(lineID + 1) Wrecked: \(lineContent)") - } - continue - } - var currentKV = Megrez.KeyValuePair() - for (unitID, unitContent) in lineContent.components(separatedBy: " ").enumerated() { - switch unitID { - case 0: - currentKV.key = unitContent - case 1: - currentKV.value = unitContent - default: break - } - } - keyValueMap[currentKV.key, default: []].append(currentKV) - } - } return true } public mutating func close() { if isLoaded() { - keyValueMap.removeAll() + rangeMap.removeAll() } } public func dump() { var strDump = "" - for entry in keyValueMap { - let rows: [Megrez.KeyValuePair] = entry.value - for row in rows { - let addline = row.key + " " + row.value + "\n" + for entry in rangeMap { + let netaRanges: [Range] = entry.value + for netaRange in netaRanges { + let neta = strData[netaRange] + let addline = neta + "\n" strDump += addline } } @@ -104,17 +91,33 @@ extension vChewing { } public func valuesFor(key: String) -> [String]? { - var v: [String] = [] - if let matched = keyValueMap[key] { - for entry in matched as [Megrez.KeyValuePair] { - v.append(entry.value) + var pairs: [String] = [] + if let arrRangeRecords: [Range] = rangeMap[key] { + for netaRange in arrRangeRecords { + let neta = strData[netaRange].components(separatedBy: " ") + let theValue: String = neta[1] + pairs.append(theValue) } } - return v + return pairs } public func hasValuesFor(key: String) -> Bool { - keyValueMap[key] != nil + rangeMap[key] != nil + } + } +} + +// MARK: - StringView Ranges Extension (by Isaac Xen) + +extension String { + fileprivate func ranges(splitBy separator: Element) -> [Range] { + var startIndex = startIndex + return split(separator: separator).reduce(into: []) { ranges, substring in + _ = range(of: substring, range: startIndex..]] = [:] + var strData: String = "" var shouldReverse: Bool = false var allowConsolidation: Bool = false var defaultScore: Double = 0 var shouldForceDefaultScore: Bool = false public var count: Int { - keyValueScoreMap.count + rangeMap.count } public init( reverse: Bool = false, consolidate: Bool = false, defaultScore scoreDefault: Double = 0, forceDefaultScore: Bool = false ) { - keyValueScoreMap = [:] + rangeMap = [:] allowConsolidation = consolidate shouldReverse = reverse defaultScore = scoreDefault @@ -50,7 +55,7 @@ extension vChewing { } public func isLoaded() -> Bool { - !keyValueScoreMap.isEmpty + !rangeMap.isEmpty } @discardableResult public mutating func open(_ path: String) -> Bool { @@ -63,64 +68,30 @@ extension vChewing { LMConsolidator.consolidate(path: path, pragma: true) } - var arrData: [String] = [] - do { - arrData = try String(contentsOfFile: path, encoding: .utf8).components(separatedBy: "\n") + strData = try String(contentsOfFile: path, encoding: .utf8).replacingOccurrences(of: "\t", with: " ") + strData.ranges(splitBy: "\n").forEach { + let neta = strData[$0].components(separatedBy: " ") + if neta.count >= 2 { + let theKey = shouldReverse ? neta[1] : neta[0] + if !neta[0].isEmpty, !neta[1].isEmpty, theKey.first != "#" { + let theValue = $0 + rangeMap[theKey, default: []].append(theValue) + } + } + } } catch { IME.prtDebugIntel("\(error)") - IME.prtDebugIntel("↑ Exception happened when reading Associated Phrases data.") + IME.prtDebugIntel("↑ Exception happened when reading data at: \(path).") return false } - for (lineID, lineContent) in arrData.enumerated() { - if !lineContent.hasPrefix("#") { - let lineContent = lineContent.replacingOccurrences(of: "\t", with: " ") - if lineContent.components(separatedBy: " ").count < 2 { - if lineContent != "", lineContent != " " { - IME.prtDebugIntel("Line #\(lineID + 1) Wrecked: \(lineContent)") - } - continue - } - var currentUnigram = Megrez.Unigram(keyValue: Megrez.KeyValuePair(), score: defaultScore) - var columnOne = "" - var columnTwo = "" - for (unitID, unitContent) in lineContent.components(separatedBy: " ").enumerated() { - switch unitID { - case 0: - columnOne = unitContent - case 1: - columnTwo = unitContent - case 2: - if !shouldForceDefaultScore { - if let unitContentConverted = Double(unitContent) { - currentUnigram.score = unitContentConverted - } else { - IME.prtDebugIntel("Line #\(lineID) Score Data Wrecked: \(lineContent)") - } - } - default: break - } - } - // 標點符號的頻率最好鎖定一下。 - if columnOne.contains("_punctuation_") { - currentUnigram.score -= (Double(lineID) * 0.000001) - } - let kvPair = - shouldReverse - ? Megrez.KeyValuePair(key: columnTwo, value: columnOne) - : Megrez.KeyValuePair(key: columnOne, value: columnTwo) - currentUnigram.keyValue = kvPair - let key = shouldReverse ? columnTwo : columnOne - keyValueScoreMap[key, default: []].append(currentUnigram) - } - } return true } public mutating func close() { if isLoaded() { - keyValueScoreMap.removeAll() + rangeMap.removeAll() } } @@ -128,10 +99,11 @@ extension vChewing { public func dump() { var strDump = "" - for entry in keyValueScoreMap { - let rows: [Megrez.Unigram] = entry.value - for row in rows { - let addline = row.keyValue.key + " " + row.keyValue.value + " " + String(row.score) + "\n" + for entry in rangeMap { + let netaRanges: [Range] = entry.value + for netaRange in netaRanges { + let neta = strData[netaRange] + let addline = neta + "\n" strDump += addline } } @@ -145,11 +117,38 @@ extension vChewing { } public func unigramsFor(key: String) -> [Megrez.Unigram] { - keyValueScoreMap[key] ?? [Megrez.Unigram]() + var grams: [Megrez.Unigram] = [] + if let arrRangeRecords: [Range] = rangeMap[key] { + for netaRange in arrRangeRecords { + let neta = strData[netaRange].components(separatedBy: " ") + let theValue: String = shouldReverse ? neta[0] : neta[1] + let kvPair = Megrez.KeyValuePair(key: key, value: theValue) + var theScore = defaultScore + if neta.count >= 3, !shouldForceDefaultScore { + theScore = .init(neta[2]) ?? defaultScore + } + grams.append(Megrez.Unigram(keyValue: kvPair, score: theScore)) + } + } + return grams } public func hasUnigramsFor(key: String) -> Bool { - keyValueScoreMap[key] != nil + rangeMap[key] != nil + } + } +} + +// MARK: - StringView Ranges Extension (by Isaac Xen) + +extension String { + fileprivate func ranges(splitBy separator: Element) -> [Range] { + var startIndex = startIndex + return split(separator: separator).reduce(into: []) { ranges, substring in + _ = range(of: substring, range: startIndex.. Bool { - !keyValueMap.isEmpty - } - - @discardableResult public mutating func open(_ path: String) -> Bool { - if isLoaded() { - return false - } - - if allowConsolidation { - LMConsolidator.fixEOF(path: path) - LMConsolidator.consolidate(path: path, pragma: true) - } - - var arrData: [String] = [] - - do { - arrData = try String(contentsOfFile: path, encoding: .utf8).components(separatedBy: "\n") - } catch { - IME.prtDebugIntel("\(error)") - IME.prtDebugIntel("↑ Exception happened when reading Associated Phrases data.") - return false - } - - for (lineID, lineContent) in arrData.enumerated() { - if !lineContent.hasPrefix("#") { - let lineContent = lineContent.replacingOccurrences(of: "\t", with: " ") - if lineContent.components(separatedBy: " ").count < 2 { - if lineContent != "", lineContent != " " { - IME.prtDebugIntel("Line #\(lineID + 1) Wrecked: \(lineContent)") - } - continue - } - var currentKV = Megrez.KeyValuePair() - for (unitID, unitContent) in lineContent.components(separatedBy: " ").enumerated() { - switch unitID { - case 0: - currentKV.value = unitContent - case 1: - currentKV.key = unitContent - default: break - } - } - keyValueMap[currentKV.key, default: []].append(currentKV) - } - } - return true - } - - public mutating func close() { - if isLoaded() { - keyValueMap.removeAll() - } - } - - public func dump() { - var strDump = "" - for entry in keyValueMap { - let rows: [Megrez.KeyValuePair] = entry.value - for row in rows { - let addline = row.key + " " + row.value + "\n" - strDump += addline - } - } - IME.prtDebugIntel(strDump) - } - - public func unigramsFor(key: String, score givenScore: Double = 0.0) -> [Megrez.Unigram] { - var v: [Megrez.Unigram] = [] - if let matched = keyValueMap[key] { - for entry in matched as [Megrez.KeyValuePair] { - v.append(Megrez.Unigram(keyValue: entry, score: givenScore)) - } - } - return v - } - - public func hasUnigramsFor(key: String) -> Bool { - keyValueMap[key] != nil - } - } -} diff --git a/Source/Modules/LangModelRelated/SubLMs/lmReplacements.swift b/Source/Modules/LangModelRelated/SubLMs/lmReplacements.swift index 9cfc5ff5..3cce9a45 100644 --- a/Source/Modules/LangModelRelated/SubLMs/lmReplacements.swift +++ b/Source/Modules/LangModelRelated/SubLMs/lmReplacements.swift @@ -1,6 +1,5 @@ // Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). -// Refactored from the ObjCpp-version of this class by: -// (c) 2011 and onwards The OpenVanilla Project (MIT License). +// StringView Ranges extension by (c) 2022 and onwards Isaac Xen (MIT License). /* 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 @@ -28,18 +27,19 @@ import Foundation extension vChewing { @frozen public struct LMReplacments { - var keyValueMap: [String: String] = [:] + var rangeMap: [String: Range] = [:] + var strData: String = "" public var count: Int { - keyValueMap.count + rangeMap.count } public init() { - keyValueMap = [:] + rangeMap = [:] } public func isLoaded() -> Bool { - !keyValueMap.isEmpty + !rangeMap.isEmpty } @discardableResult public mutating func open(_ path: String) -> Bool { @@ -50,58 +50,69 @@ extension vChewing { LMConsolidator.fixEOF(path: path) LMConsolidator.consolidate(path: path, pragma: true) - var arrData: [String] = [] - do { - arrData = try String(contentsOfFile: path, encoding: .utf8).components(separatedBy: "\n") - + strData = try String(contentsOfFile: path, encoding: .utf8).replacingOccurrences(of: "\t", with: " ") + strData.ranges(splitBy: "\n").forEach { + let neta = strData[$0].components(separatedBy: " ") + if neta.count >= 2 { + let theKey = neta[0] + if !neta[0].isEmpty, !neta[1].isEmpty, theKey.first != "#" { + let theValue = $0 + rangeMap[theKey] = theValue + } + } + } } catch { IME.prtDebugIntel("\(error)") - IME.prtDebugIntel("↑ Exception happened when reading Associated Phrases data.") + IME.prtDebugIntel("↑ Exception happened when reading data at: \(path).") return false } - for (lineID, lineContent) in arrData.enumerated() { - if !lineContent.hasPrefix("#") { - let lineContent = lineContent.replacingOccurrences(of: "\t", with: " ") - if lineContent.components(separatedBy: " ").count < 2 { - if lineContent != "", lineContent != " " { - IME.prtDebugIntel("Line #\(lineID + 1) Wrecked: \(lineContent)") - } - continue - } - var currentKV = Megrez.KeyValuePair() - for (unitID, unitContent) in lineContent.components(separatedBy: " ").enumerated() { - switch unitID { - case 0: - currentKV.key = unitContent - case 1: - currentKV.value = unitContent - default: break - } - } - keyValueMap[currentKV.key] = currentKV.value - } - } return true } public mutating func close() { if isLoaded() { - keyValueMap.removeAll() + rangeMap.removeAll() } } public func dump() { var strDump = "" - for entry in keyValueMap { - strDump += entry.key + " " + entry.value + "\n" + for entry in rangeMap { + strDump += strData[entry.value] + "\n" } IME.prtDebugIntel(strDump) } public func valuesFor(key: String) -> String { - keyValueMap[key] ?? "" + guard let range = rangeMap[key] else { + return "" + } + let arrNeta = strData[range].components(separatedBy: " ") + guard arrNeta.count >= 2 else { + return "" + } + return String(arrNeta[1]) + } + + public func hasValuesFor(key: String) -> Bool { + rangeMap[key] != nil + } + + } +} + +// MARK: - StringView Ranges Extension (by Isaac Xen) + +extension String { + fileprivate func ranges(splitBy separator: Element) -> [Range] { + var startIndex = startIndex + return split(separator: separator).reduce(into: []) { ranges, substring in + _ = range(of: substring, range: startIndex.. - + - - + @@ -58,7 +57,7 @@ McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al. -vChewing macOS Development: Shiki Suen, Hiraku Wang, etc. +vChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc. vChewing Phrase Database Maintained by Shiki Suen. @@ -125,7 +124,7 @@ DQ - + diff --git a/Source/WindowNIBs/en.lproj/frmAboutWindow.strings b/Source/WindowNIBs/en.lproj/frmAboutWindow.strings index 0ab50907..1d0d5e01 100644 --- a/Source/WindowNIBs/en.lproj/frmAboutWindow.strings +++ b/Source/WindowNIBs/en.lproj/frmAboutWindow.strings @@ -23,5 +23,5 @@ /* Class = "NSTextFieldCell"; title = "© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project."; ObjectID = "lblCopyright"; */ // "lblCopyright.title" = "© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project."; -/* Class = "NSTextFieldCell"; title = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; ObjectID = "lblCredits"; */ -"lblCredits.title" = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; +/* Class = "NSTextFieldCell"; title = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; ObjectID = "lblCredits"; */ +"lblCredits.title" = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; diff --git a/Source/WindowNIBs/ja.lproj/frmAboutWindow.strings b/Source/WindowNIBs/ja.lproj/frmAboutWindow.strings index 7a918a02..1ff90c89 100644 --- a/Source/WindowNIBs/ja.lproj/frmAboutWindow.strings +++ b/Source/WindowNIBs/ja.lproj/frmAboutWindow.strings @@ -23,5 +23,5 @@ /* Class = "NSTextFieldCell"; title = "© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project."; ObjectID = "lblCopyright"; */ // "lblCopyright.title" = "© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project."; -/* Class = "NSTextFieldCell"; title = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; ObjectID = "lblCredits"; */ -"lblCredits.title" = "ボポモフォエンジン開発:Lukhnos Liu。\n入力状態管理システム開発:Zonble Yang。\nmacOS 版威注音の開発:Shiki Suen, Hiraku Wang, など。\n威注音語彙データの維持:Shiki Suen。\nMegrez 辞書処理エンジン:Shiki Suen(Lukhnos の Gramambular C++ エンジンを Swift で再開発したものである)。"; +/* Class = "NSTextFieldCell"; title = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; ObjectID = "lblCredits"; */ +"lblCredits.title" = "ボポモフォエンジン開発:Lukhnos Liu。\n入力状態管理システム開発:Zonble Yang。\nmacOS 版威注音の開発:Shiki Suen, Isaac Xen, Hiraku Wang, など。\n威注音語彙データの維持:Shiki Suen。\nMegrez 辞書処理エンジン:Shiki Suen(Lukhnos の Gramambular C++ エンジンを Swift で再開発したものである)。"; diff --git a/Source/WindowNIBs/zh-Hans.lproj/frmAboutWindow.strings b/Source/WindowNIBs/zh-Hans.lproj/frmAboutWindow.strings index b31df929..d9bf31a9 100644 --- a/Source/WindowNIBs/zh-Hans.lproj/frmAboutWindow.strings +++ b/Source/WindowNIBs/zh-Hans.lproj/frmAboutWindow.strings @@ -23,5 +23,5 @@ /* Class = "NSTextFieldCell"; title = "© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project."; ObjectID = "lblCopyright"; */ // "lblCopyright.title" = "© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project."; -/* Class = "NSTextFieldCell"; title = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; ObjectID = "lblCredits"; */ -"lblCredits.title" = "注音拼音输入处理引擎研发:Lukhnos Liu。\n输入法状态管理引擎研发:Zonble Yang。\n威注音 macOS 程式研发:Shiki Suen, Hiraku Wang, 等。\n威注音词库维护:Shiki Suen。\n天权星语汇引擎:Shiki Suen,用 Swift 将 Lukhnos 的 C++ Gramambular 重写而得。"; +/* Class = "NSTextFieldCell"; title = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; ObjectID = "lblCredits"; */ +"lblCredits.title" = "注音拼音输入处理引擎研发:Lukhnos Liu。\n输入法状态管理引擎研发:Zonble Yang。\n威注音 macOS 程式研发:Shiki Suen, Isaac Xen, Hiraku Wang, 等。\n威注音词库维护:Shiki Suen。\n天权星语汇引擎:Shiki Suen,用 Swift 将 Lukhnos 的 C++ Gramambular 重写而得。"; diff --git a/Source/WindowNIBs/zh-Hant.lproj/frmAboutWindow.strings b/Source/WindowNIBs/zh-Hant.lproj/frmAboutWindow.strings index 151c31e6..e4bd24be 100644 --- a/Source/WindowNIBs/zh-Hant.lproj/frmAboutWindow.strings +++ b/Source/WindowNIBs/zh-Hant.lproj/frmAboutWindow.strings @@ -23,5 +23,5 @@ /* Class = "NSTextFieldCell"; title = "© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project."; ObjectID = "lblCopyright"; */ // "lblCopyright.title" = "© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project."; -/* Class = "NSTextFieldCell"; title = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; ObjectID = "lblCredits"; */ -"lblCredits.title" = "注音拼音輸入處理引擎研發:Lukhnos Liu。\n輸入法狀態管理引擎研發:Zonble Yang。\n威注音 macOS 程式研發:Shiki Suen, Hiraku Wang, 等。\n威注音詞庫維護:Shiki Suen。\n天權星語彙引擎:Shiki Suen,用 Swift 將 Lukhnos 的 C++ Gramambular 重寫而得。"; +/* Class = "NSTextFieldCell"; title = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; ObjectID = "lblCredits"; */ +"lblCredits.title" = "注音拼音輸入處理引擎研發:Lukhnos Liu。\n輸入法狀態管理引擎研發:Zonble Yang。\n威注音 macOS 程式研發:Shiki Suen, Isaac Xen, Hiraku Wang, 等。\n威注音詞庫維護:Shiki Suen。\n天權星語彙引擎:Shiki Suen,用 Swift 將 Lukhnos 的 C++ Gramambular 重寫而得。"; diff --git a/vChewing.xcodeproj/project.pbxproj b/vChewing.xcodeproj/project.pbxproj index 3beae7a4..58647c9c 100644 --- a/vChewing.xcodeproj/project.pbxproj +++ b/vChewing.xcodeproj/project.pbxproj @@ -7,7 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - 5B00A230282011980058E5DB /* lmLite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B00A22F282011980058E5DB /* lmLite.swift */; }; 5B0AF8B527B2C8290096FE54 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B0AF8B427B2C8290096FE54 /* StringExtension.swift */; }; 5B11328927B94CFB00E58451 /* AppleKeyboardConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B11328827B94CFB00E58451 /* AppleKeyboardConverter.swift */; }; 5B27AD6A27CB1F9B000ED75B /* data-symbols.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5B27AD6827CB1F9B000ED75B /* data-symbols.txt */; }; @@ -48,10 +47,10 @@ 5B782EC4280C243C007276DE /* KeyHandler_HandleCandidate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B782EC3280C243C007276DE /* KeyHandler_HandleCandidate.swift */; }; 5B7BC4B027AFFBE800F66C24 /* frmPrefWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5B7BC4AE27AFFBE800F66C24 /* frmPrefWindow.xib */; }; 5B7F225D2808501000DDD3CB /* KeyHandler_HandleInput.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B7F225C2808501000DDD3CB /* KeyHandler_HandleInput.swift */; }; + 5B887F302826AEA400B6651E /* lmCoreEX.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B887F2F2826AEA400B6651E /* lmCoreEX.swift */; }; 5B949BD92816DC5400D87B5D /* LineReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B949BD82816DC5400D87B5D /* LineReader.swift */; }; 5B949BDB2816DDBC00D87B5D /* LMConsolidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B949BDA2816DDBC00D87B5D /* LMConsolidator.swift */; }; 5BA0DF312817857D009E73BB /* lmUserOverride.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA0DF2E2817857D009E73BB /* lmUserOverride.swift */; }; - 5BA0DF322817857D009E73BB /* lmCore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA0DF2F2817857D009E73BB /* lmCore.swift */; }; 5BA9FD0F27FEDB6B002DE248 /* suiPrefPaneGeneral.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA9FD0A27FEDB6B002DE248 /* suiPrefPaneGeneral.swift */; }; 5BA9FD1027FEDB6B002DE248 /* suiPrefPaneKeyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA9FD0B27FEDB6B002DE248 /* suiPrefPaneKeyboard.swift */; }; 5BA9FD1127FEDB6B002DE248 /* ctlPrefUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA9FD0C27FEDB6B002DE248 /* ctlPrefUI.swift */; }; @@ -161,7 +160,6 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 5B00A22F282011980058E5DB /* lmLite.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = lmLite.swift; sourceTree = ""; usesTabs = 0; }; 5B04305327B529D800CB65BC /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = ""; }; 5B04305427B529D800CB65BC /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; 5B04305527B529D800CB65BC /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/MainMenu.strings"; sourceTree = ""; }; @@ -225,10 +223,10 @@ 5B7BC4AF27AFFBE800F66C24 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/frmPrefWindow.xib; sourceTree = ""; }; 5B7BC4B227AFFC0B00F66C24 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/frmPrefWindow.strings; sourceTree = ""; }; 5B7F225C2808501000DDD3CB /* KeyHandler_HandleInput.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = KeyHandler_HandleInput.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; + 5B887F2F2826AEA400B6651E /* lmCoreEX.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = lmCoreEX.swift; sourceTree = ""; usesTabs = 0; }; 5B949BD82816DC5400D87B5D /* LineReader.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; lineEnding = 0; path = LineReader.swift; sourceTree = ""; usesTabs = 0; }; 5B949BDA2816DDBC00D87B5D /* LMConsolidator.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; lineEnding = 0; path = LMConsolidator.swift; sourceTree = ""; usesTabs = 0; }; 5BA0DF2E2817857D009E73BB /* lmUserOverride.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; lineEnding = 0; path = lmUserOverride.swift; sourceTree = ""; usesTabs = 0; }; - 5BA0DF2F2817857D009E73BB /* lmCore.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; lineEnding = 0; path = lmCore.swift; sourceTree = ""; usesTabs = 0; }; 5BA9FD0A27FEDB6B002DE248 /* suiPrefPaneGeneral.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = suiPrefPaneGeneral.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; 5BA9FD0B27FEDB6B002DE248 /* suiPrefPaneKeyboard.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = suiPrefPaneKeyboard.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; 5BA9FD0C27FEDB6B002DE248 /* ctlPrefUI.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = ctlPrefUI.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; @@ -393,8 +391,7 @@ isa = PBXGroup; children = ( 5B407309281672610023DFFF /* lmAssociates.swift */, - 5BA0DF2F2817857D009E73BB /* lmCore.swift */, - 5B00A22F282011980058E5DB /* lmLite.swift */, + 5B887F2F2826AEA400B6651E /* lmCoreEX.swift */, 5B40730A281672610023DFFF /* lmReplacements.swift */, 5BA0DF2E2817857D009E73BB /* lmUserOverride.swift */, ); @@ -1077,7 +1074,6 @@ 5B707CE827D9F4590099EF99 /* OpenCCBridge.swift in Sources */, D427F76C278CA2B0004A2160 /* AppDelegate.swift in Sources */, 5BA9FD4527FEF3C9002DE248 /* ToolbarItemStyleViewController.swift in Sources */, - 5BA0DF322817857D009E73BB /* lmCore.swift in Sources */, 5BA9FD4127FEF3C8002DE248 /* PreferencesStyle.swift in Sources */, 5B7F225D2808501000DDD3CB /* KeyHandler_HandleInput.swift in Sources */, 5BA9FD1227FEDB6B002DE248 /* suiPrefPaneExperience.swift in Sources */, @@ -1088,6 +1084,7 @@ 5BA9FD4827FEF3C9002DE248 /* PreferencesWindowController.swift in Sources */, 5BD0113B28180D6100609769 /* LMInstantiator.swift in Sources */, D4E569DC27A34D0E00AC2CEF /* CTools.m in Sources */, + 5B887F302826AEA400B6651E /* lmCoreEX.swift in Sources */, 5BA9FD4627FEF3C9002DE248 /* Container.swift in Sources */, D47F7DD0278C0897002F9DD7 /* ctlNonModalAlertWindow.swift in Sources */, 5B38F5A2281E2E49007D5F5D /* 0_Megrez.swift in Sources */, @@ -1130,7 +1127,6 @@ 5B62A34827AE7CD900A19448 /* ctlCandidateVertical.swift in Sources */, 5BA9FD4027FEF3C8002DE248 /* Localization.swift in Sources */, 5BA9FD1327FEDB6B002DE248 /* suiPrefPaneDictionary.swift in Sources */, - 5B00A230282011980058E5DB /* lmLite.swift in Sources */, 5BBBB77A27AEDC690023B93A /* clsSFX.swift in Sources */, 5BA9FD4727FEF3C9002DE248 /* PreferencesStyleController.swift in Sources */, 5BF8423127BAA942008E7E4C /* vChewingKanjiConverter.swift in Sources */,