diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 135d82e7..7392e009 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,13 +6,8 @@ 為了不讓參與者們浪費各自的熱情,特設此文以說明該專案目前最需要協助的地方。 -1. 有人能用 Swift 將該專案內的這個源自 LibFormosa 的組件套件重寫: - - Mandarin 組件,用以分析普通話音韻數據、創建且控制 Syllable Composer 注音拼識組件。 - - 一堆記憶體指針操作,實在看不懂這個組件的處理邏輯是什麼,無能為力。 -2. 讓 Alt+波浪鍵選單能夠在諸如 MS Word 以及終端機內正常工作(可以用方向鍵控制高亮候選內容,等)。 +1. 讓 Alt+波浪鍵選單能夠在諸如 MS Word 以及終端機內正常工作(可以用方向鍵控制高亮候選內容,等)。 - 原理上而言恐怕得欺騙當前正在接受輸入的應用、使其誤以為當前有組字區。這只是推測。 -3. SQLite 實現。 - 除了上述各項以外的貢獻,除非特邀、或者有足夠的說服理由與吸引力(比如語法錯誤或更好的重構方法等),否則敝專案可能會無視或者拒絕。 diff --git a/Installer/Resources/Base.lproj/MainMenu.xib b/Installer/Resources/Base.lproj/MainMenu.xib index 71ebe7b7..b565efb0 100644 --- a/Installer/Resources/Base.lproj/MainMenu.xib +++ b/Installer/Resources/Base.lproj/MainMenu.xib @@ -132,17 +132,17 @@ - + - + - + - + @@ -162,7 +162,7 @@ - + @@ -194,11 +194,9 @@ - - + + - McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al. -vChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.
vChewing Phrase Database Maintained by Shiki Suen. @@ -207,7 +205,7 @@ vChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.
vChewing - + diff --git a/Installer/Resources/en.lproj/MainMenu.strings b/Installer/Resources/en.lproj/MainMenu.strings index f45a3b26..128b545d 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, 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 = "Tekkon Syllable Composition Engine by Shiki Suen.\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" = "Tekkon Syllable Composition Engine by Shiki Suen.\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 63f67c93..bda4245d 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, 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 = "Tekkon Syllable Composition Engine by Shiki Suen.\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" = "鉄恨ボポモフォエンジン開発:Shiki Suen。\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 b5ab37d3..49bcceef 100644 --- a/Installer/Resources/zh-Hans.lproj/MainMenu.strings +++ b/Installer/Resources/zh-Hans.lproj/MainMenu.strings @@ -56,9 +56,8 @@ /* 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, 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, Isaac Xen, Hiraku Wang, 等。\n威注音词库维护:Shiki Suen。\n天权星语汇引擎:Shiki Suen,用 Swift 将 Lukhnos 的 C++ Gramambular 重写而得。"; +/* Class = "NSTextFieldCell"; title = "Tekkon Syllable Composition Engine by Shiki Suen.\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" = "铁恨注音并击输入处理引擎研发:Shiki Suen。\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 0996d412..1da9c6a1 100644 --- a/Installer/Resources/zh-Hant.lproj/MainMenu.strings +++ b/Installer/Resources/zh-Hant.lproj/MainMenu.strings @@ -56,9 +56,8 @@ /* 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, 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, Isaac Xen, Hiraku Wang, 等。\n威注音詞庫維護:Shiki Suen。\n天權星語彙引擎:Shiki Suen,用 Swift 將 Lukhnos 的 C++ Gramambular 重寫而得。"; +/* Class = "NSTextFieldCell"; title = "Tekkon Syllable Composition Engine by Shiki Suen.\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" = "鐵恨注音並擊輸入處理引擎研發:Shiki Suen。\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/KeyboardExtension/vChewingKeyLayout.bundle/Contents/Resources/vChewing FakeSeigyou.keylayout b/KeyboardExtension/vChewingKeyLayout.bundle/Contents/Resources/vChewing FakeSeigyou.keylayout index f52ebd3a..fcf51885 100644 --- a/KeyboardExtension/vChewingKeyLayout.bundle/Contents/Resources/vChewing FakeSeigyou.keylayout +++ b/KeyboardExtension/vChewingKeyLayout.bundle/Contents/Resources/vChewing FakeSeigyou.keylayout @@ -1,7 +1,7 @@ - - + + @@ -84,7 +84,7 @@ - + diff --git a/LICENSE-CHS.txt b/LICENSE-CHS.txt index 3539bc05..a636a2f4 100644 --- a/LICENSE-CHS.txt +++ b/LICENSE-CHS.txt @@ -3,7 +3,7 @@ vChewing macOS: MIT-NTL License 麻理(去商标)授权合约 © 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project. -注音拼音输入处理引擎研发:Lukhnos Liu。 +铁恨注音并击输入处理引擎研发:Shiki Suen。 输入法状态管理引擎研发:Zonble Yang。 威注音 macOS 程式研发:Shiki Suen, Isaac Xen, Hiraku Wang, 等。 威注音词库维护:Shiki Suen。 diff --git a/LICENSE-CHT.txt b/LICENSE-CHT.txt index b629fd9e..55e191ae 100644 --- a/LICENSE-CHT.txt +++ b/LICENSE-CHT.txt @@ -3,7 +3,7 @@ vChewing macOS: MIT-NTL License 麻理(去商標)授權合約 © 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project. -注音拼音輸入處理引擎研發:Lukhnos Liu。 +鐵恨注音並擊輸入處理引擎研發:Shiki Suen。 輸入法狀態管理引擎研發:Zonble Yang。 威注音 macOS 程式研發:Shiki Suen, Isaac Xen, Hiraku Wang, 等。 威注音詞庫維護:Shiki Suen。 diff --git a/LICENSE-JPN.txt b/LICENSE-JPN.txt index 1061f95e..490f836a 100644 --- a/LICENSE-JPN.txt +++ b/LICENSE-JPN.txt @@ -2,7 +2,7 @@ vChewing macOS: MIT商標不許可ライセンス (MIT-NTL License) -ボポモフォエンジン開発:Lukhnos Liu。 +鉄恨ボポモフォエンジン開発:Shiki Suen。 入力状態管理システム開発:Zonble Yang。 macOS 版威注音の開発:Shiki Suen, Isaac Xen, Hiraku Wang, など。 威注音語彙データの維持:Shiki Suen。 diff --git a/LICENSE.txt b/LICENSE.txt index e37f0d24..803369ca 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -3,7 +3,7 @@ DISCLAIMER: The vChewing project, having no relationship of cooperation or affil vChewing macOS: MIT-NTL License © 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project. -Mandarin Syllable Composer Engine by Lukhnos Liu. +Tekkon Syllable Composition Engine by Shiki Suen. Input State Management Architecture by Zonble Yang. vChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc. vChewing Phrase Database Maintained by Shiki Suen. diff --git a/README.md b/README.md index e54d30af..d6221872 100644 --- a/README.md +++ b/README.md @@ -68,11 +68,23 @@ 小麥注音引擎程式版權(MIT 授權):© 2011-2021 OpenVanilla 專案團隊(Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, 等)。 +威注音專案僅用到小麥注音的下述程式組件: + +- 狀態管理引擎 & NSStringUtils & FSEventStreamHelper (by Zonble Yang)。 + +- 半衰記憶模組,因故障暫時無法啟用 (by Mengjuei Hsieh)。 + +- 僅供研發人員調試方便而使用的 App 版安裝程式 (by Zonble Yang)。 + 威注音輸入法 macOS 版以 MIT-NTL License 授權釋出 (與 MIT 相容):© 2021-2022 vChewing 專案。 -威注音輸入法 macOS 版程式維護:Shiki Suen。特別感謝 Hiraku Wong 等人的技術協力。 +- 威注音輸入法 macOS 版程式維護:Shiki Suen。特別感謝 Isaac Xen 與 Hiraku Wong 等人的技術協力。 -威注音詞庫由 Shiki Suen 維護,以 3-Clause BSD License 授權釋出。其中的詞頻數據[由 NAER 授權用於非商業用途](https://twitter.com/ShikiSuen/status/1479329302713831424)。 +- 鐵恨注音並擊處理引擎:Shiki Suen (MIT-NTL License)。 + +- 天權星語彙處理引擎:Shiki Suen (MIT-NTL License),針對「Lukhnos Liu 用 C++ 寫的 Gramambular」用 Swift 徹底重寫而成。 + +- 威注音詞庫由 Shiki Suen 維護,以 3-Clause BSD License 授權釋出。其中的詞頻數據[由 NAER 授權用於非商業用途](https://twitter.com/ShikiSuen/status/1479329302713831424)。 使用者可自由使用、散播本軟體,惟散播時必須完整保留版權聲明及軟體授權、且一旦經過修改便不可以再繼續使用威注音的產品名稱。 diff --git a/Source/3rdParty/OVMandarin/Composer.hh b/Source/3rdParty/OVMandarin/Composer.hh deleted file mode 100644 index fa49864f..00000000 --- a/Source/3rdParty/OVMandarin/Composer.hh +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). -// All possible vChewing-specific modifications are of: -// (c) 2021 and onwards The vChewing Project (MIT-NTL License). -/* -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: - -1. The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -2. 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 above. - -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 - -NS_ASSUME_NONNULL_BEGIN - -@interface Composer : NSObject -+ (BOOL)chkKeyValidity:(UniChar)charCode; -+ (BOOL)isBufferEmpty; -+ (void)clearBuffer; -+ (void)combineReadingKey:(UniChar)charCode; -+ (BOOL)hasToneMarker; -+ (BOOL)hasToneMarkerOnly; -+ (NSString *)getSyllableComposition; -+ (void)doBackSpaceToBuffer; -+ (NSString *)getComposition; -+ (void)ensureParser; -@end - -NS_ASSUME_NONNULL_END diff --git a/Source/3rdParty/OVMandarin/Composer.mm b/Source/3rdParty/OVMandarin/Composer.mm deleted file mode 100644 index 6efb5d08..00000000 --- a/Source/3rdParty/OVMandarin/Composer.mm +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). -// All possible vChewing-specific modifications are of: -// (c) 2021 and onwards The vChewing Project (MIT-NTL License). -/* -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: - -1. The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -2. 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 above. - -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 "Composer.hh" -#import "Mandarin.h" -#import "vChewing-Swift.h" - -static Mandarin::BopomofoReadingBuffer *PhoneticBuffer; - -@implementation Composer - -+ (BOOL)chkKeyValidity:(UniChar)charCode -{ - return PhoneticBuffer->isValidKey((char)charCode); -} - -+ (BOOL)isBufferEmpty -{ - return PhoneticBuffer->isEmpty(); -} - -+ (void)clearBuffer -{ - PhoneticBuffer->clear(); -} - -+ (void)combineReadingKey:(UniChar)charCode -{ - PhoneticBuffer->combineKey((char)charCode); -} - -+ (BOOL)hasToneMarker -{ - return PhoneticBuffer->hasToneMarker(); -} - -+ (BOOL)hasToneMarkerOnly -{ - return PhoneticBuffer->hasToneMarkerOnly(); -} - -+ (NSString *)getSyllableComposition -{ - return [NSString stringWithUTF8String:PhoneticBuffer->syllable().composedString().c_str()]; -} - -+ (void)doBackSpaceToBuffer -{ - PhoneticBuffer->backspace(); -} - -+ (NSString *)getComposition -{ - return [NSString stringWithUTF8String:PhoneticBuffer->composedString().c_str()]; -} - -+ (void)ensureParser -{ - if (PhoneticBuffer) - { - switch (mgrPrefs.mandarinParser) - { - case MandarinParserOfStandard: - PhoneticBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::StandardLayout()); - break; - case MandarinParserOfEten: - PhoneticBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::ETenLayout()); - break; - case MandarinParserOfHsu: - PhoneticBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::HsuLayout()); - break; - case MandarinParserOfEen26: - PhoneticBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::ETen26Layout()); - break; - case MandarinParserOfIBM: - PhoneticBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::IBMLayout()); - break; - case MandarinParserOfMiTAC: - PhoneticBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::MiTACLayout()); - break; - case MandarinParserOfFakeSeigyou: - PhoneticBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::FakeSeigyouLayout()); - break; - case MandarinParserOfHanyuPinyin: - PhoneticBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::HanyuPinyinLayout()); - break; - default: - PhoneticBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::StandardLayout()); - mgrPrefs.mandarinParser = MandarinParserOfStandard; - } - PhoneticBuffer->clear(); - } - else - { - PhoneticBuffer = new Mandarin::BopomofoReadingBuffer(Mandarin::BopomofoKeyboardLayout::StandardLayout()); - } -} - -@end diff --git a/Source/3rdParty/OVMandarin/Mandarin.cpp b/Source/3rdParty/OVMandarin/Mandarin.cpp deleted file mode 100644 index 4d4cb9a9..00000000 --- a/Source/3rdParty/OVMandarin/Mandarin.cpp +++ /dev/null @@ -1,1226 +0,0 @@ -// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). -// All possible vChewing-specific modifications are of: -// (c) 2021 and onwards The vChewing Project (MIT-NTL License). -/* -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: - -1. The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -2. 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 above. - -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. -*/ - -#include "Mandarin.h" - -#include -#include - -namespace Mandarin -{ - -class PinyinParseHelper -{ - public: - static const bool ConsumePrefix(std::string &target, const std::string &prefix) - { - if (target.length() < prefix.length()) - { - return false; - } - - if (target.substr(0, prefix.length()) == prefix) - { - target = target.substr(prefix.length(), target.length() - prefix.length()); - return true; - } - - return false; - } -}; - -class BopomofoCharacterMap -{ - public: - static const BopomofoCharacterMap &SharedInstance(); - - std::map componentToCharacter; - std::map characterToComponent; - - protected: - BopomofoCharacterMap(); -}; - -const BPMF BPMF::FromHanyuPinyin(const std::string &str) -{ - if (!str.length()) - { - return BPMF(); - } - - std::string pinyin = str; - transform(pinyin.begin(), pinyin.end(), pinyin.begin(), ::tolower); - - BPMF::Component firstComponent = 0; - BPMF::Component secondComponent = 0; - BPMF::Component thirdComponent = 0; - BPMF::Component toneComponent = 0; - - // lookup consonants and consume them - bool independentConsonant = false; - - // the y exceptions fist - if (0) - { - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "yuan")) - { - secondComponent = BPMF::UE; - thirdComponent = BPMF::AN; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "ying")) - { - secondComponent = BPMF::I; - thirdComponent = BPMF::ENG; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "yung")) - { - secondComponent = BPMF::UE; - thirdComponent = BPMF::ENG; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "yong")) - { - secondComponent = BPMF::UE; - thirdComponent = BPMF::ENG; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "yue")) - { - secondComponent = BPMF::UE; - thirdComponent = BPMF::E; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "yun")) - { - secondComponent = BPMF::UE; - thirdComponent = BPMF::EN; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "you")) - { - secondComponent = BPMF::I; - thirdComponent = BPMF::OU; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "yu")) - { - secondComponent = BPMF::UE; - } - - // try the first character - char c = pinyin.length() ? pinyin[0] : 0; - switch (c) - { - case 'b': - firstComponent = BPMF::B; - pinyin = pinyin.substr(1); - break; - case 'p': - firstComponent = BPMF::P; - pinyin = pinyin.substr(1); - break; - case 'm': - firstComponent = BPMF::M; - pinyin = pinyin.substr(1); - break; - case 'f': - firstComponent = BPMF::F; - pinyin = pinyin.substr(1); - break; - case 'd': - firstComponent = BPMF::D; - pinyin = pinyin.substr(1); - break; - case 't': - firstComponent = BPMF::T; - pinyin = pinyin.substr(1); - break; - case 'n': - firstComponent = BPMF::N; - pinyin = pinyin.substr(1); - break; - case 'l': - firstComponent = BPMF::L; - pinyin = pinyin.substr(1); - break; - case 'g': - firstComponent = BPMF::G; - pinyin = pinyin.substr(1); - break; - case 'k': - firstComponent = BPMF::K; - pinyin = pinyin.substr(1); - break; - case 'h': - firstComponent = BPMF::H; - pinyin = pinyin.substr(1); - break; - case 'j': - firstComponent = BPMF::J; - pinyin = pinyin.substr(1); - break; - case 'q': - firstComponent = BPMF::Q; - pinyin = pinyin.substr(1); - break; - case 'x': - firstComponent = BPMF::X; - pinyin = pinyin.substr(1); - break; - - // special hanlding for w and y - case 'w': - secondComponent = BPMF::U; - pinyin = pinyin.substr(1); - break; - case 'y': - if (!secondComponent && !thirdComponent) - { - secondComponent = BPMF::I; - } - pinyin = pinyin.substr(1); - break; - } - - // then we try ZH, CH, SH, R, Z, C, S (in that order) - if (0) - { - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "zh")) - { - firstComponent = BPMF::ZH; - independentConsonant = true; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "ch")) - { - firstComponent = BPMF::CH; - independentConsonant = true; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "sh")) - { - firstComponent = BPMF::SH; - independentConsonant = true; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "r")) - { - firstComponent = BPMF::R; - independentConsonant = true; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "z")) - { - firstComponent = BPMF::Z; - independentConsonant = true; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "c")) - { - firstComponent = BPMF::C; - independentConsonant = true; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "s")) - { - firstComponent = BPMF::S; - independentConsonant = true; - } - - // consume exceptions first: (ien, in), (iou, iu), (uen, un), (veng, iong), - // (ven, vn), (uei, ui), ung but longer sequence takes precedence - if (0) - { - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "veng")) - { - secondComponent = BPMF::UE; - thirdComponent = BPMF::ENG; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "iong")) - { - secondComponent = BPMF::UE; - thirdComponent = BPMF::ENG; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "ing")) - { - secondComponent = BPMF::I; - thirdComponent = BPMF::ENG; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "ien")) - { - secondComponent = BPMF::I; - thirdComponent = BPMF::EN; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "iou")) - { - secondComponent = BPMF::I; - thirdComponent = BPMF::OU; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "uen")) - { - secondComponent = BPMF::U; - thirdComponent = BPMF::EN; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "ven")) - { - secondComponent = BPMF::UE; - thirdComponent = BPMF::EN; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "uei")) - { - secondComponent = BPMF::U; - thirdComponent = BPMF::EI; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "ung")) - { - // f exception - if (firstComponent == BPMF::F) - { - thirdComponent = BPMF::ENG; - } - else - { - secondComponent = BPMF::U; - thirdComponent = BPMF::ENG; - } - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "ong")) - { - // f exception - if (firstComponent == BPMF::F) - { - thirdComponent = BPMF::ENG; - } - else - { - secondComponent = BPMF::U; - thirdComponent = BPMF::ENG; - } - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "un")) - { - if (firstComponent == BPMF::J || firstComponent == BPMF::Q || firstComponent == BPMF::X) - { - secondComponent = BPMF::UE; - } - else - { - secondComponent = BPMF::U; - } - thirdComponent = BPMF::EN; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "iu")) - { - secondComponent = BPMF::I; - thirdComponent = BPMF::OU; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "in")) - { - secondComponent = BPMF::I; - thirdComponent = BPMF::EN; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "vn")) - { - secondComponent = BPMF::UE; - thirdComponent = BPMF::EN; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "ui")) - { - secondComponent = BPMF::U; - thirdComponent = BPMF::EI; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "ue")) - { - secondComponent = BPMF::UE; - thirdComponent = BPMF::E; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, u8"ü")) - { - secondComponent = BPMF::UE; - } - - // then consume the middle component... - if (0) - { - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "i")) - { - secondComponent = independentConsonant ? 0 : BPMF::I; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "u")) - { - if (firstComponent == BPMF::J || firstComponent == BPMF::Q || firstComponent == BPMF::X) - { - secondComponent = BPMF::UE; - } - else - { - secondComponent = BPMF::U; - } - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "v")) - { - secondComponent = BPMF::UE; - } - - // the vowels, longer sequence takes precedence - if (0) - { - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "ang")) - { - thirdComponent = BPMF::ANG; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "eng")) - { - thirdComponent = BPMF::ENG; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "err")) - { - thirdComponent = BPMF::ERR; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "ai")) - { - thirdComponent = BPMF::AI; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "ei")) - { - thirdComponent = BPMF::EI; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "ao")) - { - thirdComponent = BPMF::AO; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "ou")) - { - thirdComponent = BPMF::OU; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "an")) - { - thirdComponent = BPMF::AN; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "en")) - { - thirdComponent = BPMF::EN; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "er")) - { - thirdComponent = BPMF::ERR; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "a")) - { - thirdComponent = BPMF::A; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "o")) - { - thirdComponent = BPMF::O; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "e")) - { - if (secondComponent) - { - thirdComponent = BPMF::E; - } - else - { - thirdComponent = BPMF::ER; - } - } - - // at last! - if (0) - { - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "1")) - { - toneComponent = BPMF::Tone1; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "2")) - { - toneComponent = BPMF::Tone2; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "3")) - { - toneComponent = BPMF::Tone3; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "4")) - { - toneComponent = BPMF::Tone4; - } - else if (PinyinParseHelper::ConsumePrefix(pinyin, "5")) - { - toneComponent = BPMF::Tone5; - } - - return BPMF(firstComponent | secondComponent | thirdComponent | toneComponent); -} - -const std::string BPMF::HanyuPinyinString(bool includesTone, bool useVForUUmlaut) const -{ - std::string consonant, middle, vowel, tone; - - Component cc = consonantComponent(), mvc = middleVowelComponent(), vc = vowelComponent(); - bool hasNoMVCOrVC = !(mvc || vc); - - switch (cc) - { - case B: - consonant = "b"; - break; - case P: - consonant = "p"; - break; - case M: - consonant = "m"; - break; - case F: - consonant = "f"; - break; - case D: - consonant = "d"; - break; - case T: - consonant = "t"; - break; - case N: - consonant = "n"; - break; - case L: - consonant = "l"; - break; - case G: - consonant = "g"; - break; - case K: - consonant = "k"; - break; - case H: - consonant = "h"; - break; - case J: - consonant = "j"; - if (hasNoMVCOrVC) - middle = "i"; - break; - case Q: - consonant = "q"; - if (hasNoMVCOrVC) - middle = "i"; - break; - case X: - consonant = "x"; - if (hasNoMVCOrVC) - middle = "i"; - break; - case ZH: - consonant = "zh"; - if (hasNoMVCOrVC) - middle = "i"; - break; - case CH: - consonant = "ch"; - if (hasNoMVCOrVC) - middle = "i"; - break; - case SH: - consonant = "sh"; - if (hasNoMVCOrVC) - middle = "i"; - break; - case R: - consonant = "r"; - if (hasNoMVCOrVC) - middle = "i"; - break; - case Z: - consonant = "z"; - if (hasNoMVCOrVC) - middle = "i"; - break; - case C: - consonant = "c"; - if (hasNoMVCOrVC) - middle = "i"; - break; - case S: - consonant = "s"; - if (hasNoMVCOrVC) - middle = "i"; - break; - } - - switch (mvc) - { - case I: - if (!cc) - { - consonant = "y"; - } - - middle = (!vc || cc) ? "i" : ""; - break; - case U: - if (!cc) - { - consonant = "w"; - } - middle = (!vc || cc) ? "u" : ""; - break; - case UE: - if (!cc) - { - consonant = "y"; - } - - if ((cc == N || cc == L) && vc != E) - { - middle = useVForUUmlaut ? "v" : "ü"; - } - else - { - middle = "u"; - } - - break; - } - - switch (vc) - { - case A: - vowel = "a"; - break; - case O: - vowel = "o"; - break; - case ER: - vowel = "e"; - break; - case E: - vowel = "e"; - break; - case AI: - vowel = "ai"; - break; - case EI: - vowel = "ei"; - break; - case AO: - vowel = "ao"; - break; - case OU: - vowel = "ou"; - break; - case AN: - vowel = "an"; - break; - case EN: - vowel = "en"; - break; - case ANG: - vowel = "ang"; - break; - case ENG: - vowel = "eng"; - break; - case ERR: - vowel = "er"; - break; - } - - // combination rules - - // ueng -> ong, but note "weng" - if ((mvc == U || mvc == UE) && vc == ENG) - { - middle = ""; - vowel = (cc == J || cc == Q || cc == X) ? "iong" : ((!cc && mvc == U) ? "eng" : "ong"); - } - - // ien, uen, üen -> in, un, ün ; but note "wen", "yin" and "yun" - if (mvc && vc == EN) - { - if (cc) - { - vowel = "n"; - } - else - { - if (mvc == UE) - { - vowel = "n"; // yun - } - else if (mvc == U) - { - vowel = "en"; // wen - } - else - { - vowel = "in"; // yin - } - } - } - - // iou -> iu - if (cc && mvc == I && vc == OU) - { - middle = ""; - vowel = "iu"; - } - - // ieng -> ing - if (mvc == I && vc == ENG) - { - middle = ""; - vowel = "ing"; - } - - // uei -> ui - if (cc && mvc == U && vc == EI) - { - middle = ""; - vowel = "ui"; - } - - if (includesTone) - { - switch (toneMarkerComponent()) - { - case Tone2: - tone = "2"; - break; - case Tone3: - tone = "3"; - break; - case Tone4: - tone = "4"; - break; - case Tone5: - tone = "5"; - break; - } - } - - return consonant + middle + vowel + tone; -} - -const BPMF BPMF::FromComposedString(const std::string &str) -{ - BPMF syllable; - auto iter = str.begin(); - while (iter != str.end()) - { - // This is a naive implementation and we bail early at anything we don't - // recognize. A sound implementation would require to either use a trie for - // the Bopomofo character map or to split the input by codepoints. This - // suffices for now. - - // Illegal. - if (!(*iter & 0x80)) - { - break; - } - - size_t utf8_length = -1; - - // These are the code points for the tone markers. - if ((*iter & (0x80 | 0x40)) && !(*iter & 0x20)) - { - utf8_length = 2; - } - else if ((*iter & (0x80 | 0x40 | 0x20)) && !(*iter & 0x10)) - { - utf8_length = 3; - } - else - { - // Illegal. - break; - } - - if (iter + (utf8_length - 1) == str.end()) - { - break; - } - - std::string component = std::string(iter, iter + utf8_length); - const std::map &charToComp = - BopomofoCharacterMap::SharedInstance().characterToComponent; - std::map::const_iterator result = charToComp.find(component); - if (result == charToComp.end()) - { - break; - } - else - { - syllable += BPMF((*result).second); - } - iter += utf8_length; - } - return syllable; -} - -const std::string BPMF::composedString() const -{ - std::string result; -#define APPEND(c) \ - if (syllable_ & c) \ - result += (*BopomofoCharacterMap::SharedInstance().componentToCharacter.find(syllable_ & c)).second - APPEND(ConsonantMask); - APPEND(MiddleVowelMask); - APPEND(VowelMask); - APPEND(ToneMarkerMask); -#undef APPEND - return result; -} - -const BopomofoCharacterMap &BopomofoCharacterMap::SharedInstance() -{ - static BopomofoCharacterMap *map = new BopomofoCharacterMap(); - return *map; -} - -BopomofoCharacterMap::BopomofoCharacterMap() -{ - characterToComponent[u8"ㄅ"] = BPMF::B; - characterToComponent[u8"ㄆ"] = BPMF::P; - characterToComponent[u8"ㄇ"] = BPMF::M; - characterToComponent[u8"ㄈ"] = BPMF::F; - characterToComponent[u8"ㄉ"] = BPMF::D; - characterToComponent[u8"ㄊ"] = BPMF::T; - characterToComponent[u8"ㄋ"] = BPMF::N; - characterToComponent[u8"ㄌ"] = BPMF::L; - characterToComponent[u8"ㄎ"] = BPMF::K; - characterToComponent[u8"ㄍ"] = BPMF::G; - characterToComponent[u8"ㄏ"] = BPMF::H; - characterToComponent[u8"ㄐ"] = BPMF::J; - characterToComponent[u8"ㄑ"] = BPMF::Q; - characterToComponent[u8"ㄒ"] = BPMF::X; - characterToComponent[u8"ㄓ"] = BPMF::ZH; - characterToComponent[u8"ㄔ"] = BPMF::CH; - characterToComponent[u8"ㄕ"] = BPMF::SH; - characterToComponent[u8"ㄖ"] = BPMF::R; - characterToComponent[u8"ㄗ"] = BPMF::Z; - characterToComponent[u8"ㄘ"] = BPMF::C; - characterToComponent[u8"ㄙ"] = BPMF::S; - characterToComponent[u8"ㄧ"] = BPMF::I; - characterToComponent[u8"ㄨ"] = BPMF::U; - characterToComponent[u8"ㄩ"] = BPMF::UE; - characterToComponent[u8"ㄚ"] = BPMF::A; - characterToComponent[u8"ㄛ"] = BPMF::O; - characterToComponent[u8"ㄜ"] = BPMF::ER; - characterToComponent[u8"ㄝ"] = BPMF::E; - characterToComponent[u8"ㄞ"] = BPMF::AI; - characterToComponent[u8"ㄟ"] = BPMF::EI; - characterToComponent[u8"ㄠ"] = BPMF::AO; - characterToComponent[u8"ㄡ"] = BPMF::OU; - characterToComponent[u8"ㄢ"] = BPMF::AN; - characterToComponent[u8"ㄣ"] = BPMF::EN; - characterToComponent[u8"ㄤ"] = BPMF::ANG; - characterToComponent[u8"ㄥ"] = BPMF::ENG; - characterToComponent[u8"ㄦ"] = BPMF::ERR; - characterToComponent[u8"ˊ"] = BPMF::Tone2; - characterToComponent[u8"ˇ"] = BPMF::Tone3; - characterToComponent[u8"ˋ"] = BPMF::Tone4; - characterToComponent[u8"˙"] = BPMF::Tone5; - - for (std::map::iterator iter = characterToComponent.begin(); - iter != characterToComponent.end(); ++iter) - componentToCharacter[(*iter).second] = (*iter).first; -} - -#define ASSIGNKEY1(m, vec, k, val) m[k] = (vec.clear(), vec.push_back((BPMF::Component)val), vec) -#define ASSIGNKEY2(m, vec, k, val1, val2) \ - m[k] = (vec.clear(), vec.push_back((BPMF::Component)val1), vec.push_back((BPMF::Component)val2), vec) -#define ASSIGNKEY3(m, vec, k, val1, val2, val3) \ - m[k] = (vec.clear(), vec.push_back((BPMF::Component)val1), vec.push_back((BPMF::Component)val2), \ - vec.push_back((BPMF::Component)val3), vec) - -static BopomofoKeyboardLayout *CreateStandardLayout() -{ - std::vector vec; - BopomofoKeyToComponentMap ktcm; - - ASSIGNKEY1(ktcm, vec, '1', BPMF::B); - ASSIGNKEY1(ktcm, vec, 'q', BPMF::P); - ASSIGNKEY1(ktcm, vec, 'a', BPMF::M); - ASSIGNKEY1(ktcm, vec, 'z', BPMF::F); - ASSIGNKEY1(ktcm, vec, '2', BPMF::D); - ASSIGNKEY1(ktcm, vec, 'w', BPMF::T); - ASSIGNKEY1(ktcm, vec, 's', BPMF::N); - ASSIGNKEY1(ktcm, vec, 'x', BPMF::L); - ASSIGNKEY1(ktcm, vec, 'e', BPMF::G); - ASSIGNKEY1(ktcm, vec, 'd', BPMF::K); - ASSIGNKEY1(ktcm, vec, 'c', BPMF::H); - ASSIGNKEY1(ktcm, vec, 'r', BPMF::J); - ASSIGNKEY1(ktcm, vec, 'f', BPMF::Q); - ASSIGNKEY1(ktcm, vec, 'v', BPMF::X); - ASSIGNKEY1(ktcm, vec, '5', BPMF::ZH); - ASSIGNKEY1(ktcm, vec, 't', BPMF::CH); - ASSIGNKEY1(ktcm, vec, 'g', BPMF::SH); - ASSIGNKEY1(ktcm, vec, 'b', BPMF::R); - ASSIGNKEY1(ktcm, vec, 'y', BPMF::Z); - ASSIGNKEY1(ktcm, vec, 'h', BPMF::C); - ASSIGNKEY1(ktcm, vec, 'n', BPMF::S); - ASSIGNKEY1(ktcm, vec, 'u', BPMF::I); - ASSIGNKEY1(ktcm, vec, 'j', BPMF::U); - ASSIGNKEY1(ktcm, vec, 'm', BPMF::UE); - ASSIGNKEY1(ktcm, vec, '8', BPMF::A); - ASSIGNKEY1(ktcm, vec, 'i', BPMF::O); - ASSIGNKEY1(ktcm, vec, 'k', BPMF::ER); - ASSIGNKEY1(ktcm, vec, ',', BPMF::E); - ASSIGNKEY1(ktcm, vec, '9', BPMF::AI); - ASSIGNKEY1(ktcm, vec, 'o', BPMF::EI); - ASSIGNKEY1(ktcm, vec, 'l', BPMF::AO); - ASSIGNKEY1(ktcm, vec, '.', BPMF::OU); - ASSIGNKEY1(ktcm, vec, '0', BPMF::AN); - ASSIGNKEY1(ktcm, vec, 'p', BPMF::EN); - ASSIGNKEY1(ktcm, vec, ';', BPMF::ANG); - ASSIGNKEY1(ktcm, vec, '/', BPMF::ENG); - ASSIGNKEY1(ktcm, vec, '-', BPMF::ERR); - ASSIGNKEY1(ktcm, vec, '3', BPMF::Tone3); - ASSIGNKEY1(ktcm, vec, '4', BPMF::Tone4); - ASSIGNKEY1(ktcm, vec, '6', BPMF::Tone2); - ASSIGNKEY1(ktcm, vec, '7', BPMF::Tone5); - - return new BopomofoKeyboardLayout(ktcm, "Standard"); -} - -static BopomofoKeyboardLayout *CreateIBMLayout() -{ - std::vector vec; - BopomofoKeyToComponentMap ktcm; - - ASSIGNKEY1(ktcm, vec, '1', BPMF::B); - ASSIGNKEY1(ktcm, vec, '2', BPMF::P); - ASSIGNKEY1(ktcm, vec, '3', BPMF::M); - ASSIGNKEY1(ktcm, vec, '4', BPMF::F); - ASSIGNKEY1(ktcm, vec, '5', BPMF::D); - ASSIGNKEY1(ktcm, vec, '6', BPMF::T); - ASSIGNKEY1(ktcm, vec, '7', BPMF::N); - ASSIGNKEY1(ktcm, vec, '8', BPMF::L); - ASSIGNKEY1(ktcm, vec, '9', BPMF::G); - ASSIGNKEY1(ktcm, vec, '0', BPMF::K); - ASSIGNKEY1(ktcm, vec, '-', BPMF::H); - ASSIGNKEY1(ktcm, vec, 'q', BPMF::J); - ASSIGNKEY1(ktcm, vec, 'w', BPMF::Q); - ASSIGNKEY1(ktcm, vec, 'e', BPMF::X); - ASSIGNKEY1(ktcm, vec, 'r', BPMF::ZH); - ASSIGNKEY1(ktcm, vec, 't', BPMF::CH); - ASSIGNKEY1(ktcm, vec, 'y', BPMF::SH); - ASSIGNKEY1(ktcm, vec, 'u', BPMF::R); - ASSIGNKEY1(ktcm, vec, 'i', BPMF::Z); - ASSIGNKEY1(ktcm, vec, 'o', BPMF::C); - ASSIGNKEY1(ktcm, vec, 'p', BPMF::S); - ASSIGNKEY1(ktcm, vec, 'a', BPMF::I); - ASSIGNKEY1(ktcm, vec, 's', BPMF::U); - ASSIGNKEY1(ktcm, vec, 'd', BPMF::UE); - ASSIGNKEY1(ktcm, vec, 'f', BPMF::A); - ASSIGNKEY1(ktcm, vec, 'g', BPMF::O); - ASSIGNKEY1(ktcm, vec, 'h', BPMF::ER); - ASSIGNKEY1(ktcm, vec, 'j', BPMF::E); - ASSIGNKEY1(ktcm, vec, 'k', BPMF::AI); - ASSIGNKEY1(ktcm, vec, 'l', BPMF::EI); - ASSIGNKEY1(ktcm, vec, ';', BPMF::AO); - ASSIGNKEY1(ktcm, vec, 'z', BPMF::OU); - ASSIGNKEY1(ktcm, vec, 'x', BPMF::AN); - ASSIGNKEY1(ktcm, vec, 'c', BPMF::EN); - ASSIGNKEY1(ktcm, vec, 'v', BPMF::ANG); - ASSIGNKEY1(ktcm, vec, 'b', BPMF::ENG); - ASSIGNKEY1(ktcm, vec, 'n', BPMF::ERR); - ASSIGNKEY1(ktcm, vec, 'm', BPMF::Tone2); - ASSIGNKEY1(ktcm, vec, ',', BPMF::Tone3); - ASSIGNKEY1(ktcm, vec, '.', BPMF::Tone4); - ASSIGNKEY1(ktcm, vec, '/', BPMF::Tone5); - - return new BopomofoKeyboardLayout(ktcm, "IBM"); -} - -static BopomofoKeyboardLayout *CreateMiTACLayout() -{ - std::vector vec; - BopomofoKeyToComponentMap ktcm; - - ASSIGNKEY1(ktcm, vec, '1', BPMF::Tone5); - ASSIGNKEY1(ktcm, vec, '2', BPMF::Tone2); - ASSIGNKEY1(ktcm, vec, '3', BPMF::Tone3); - ASSIGNKEY1(ktcm, vec, '4', BPMF::Tone4); - ASSIGNKEY1(ktcm, vec, '5', BPMF::AI); - ASSIGNKEY1(ktcm, vec, '6', BPMF::AO); - ASSIGNKEY1(ktcm, vec, '7', BPMF::AN); - ASSIGNKEY1(ktcm, vec, '8', BPMF::EN); - ASSIGNKEY1(ktcm, vec, '9', BPMF::ANG); - ASSIGNKEY1(ktcm, vec, '0', BPMF::ENG); - ASSIGNKEY1(ktcm, vec, '-', BPMF::ERR); - ASSIGNKEY1(ktcm, vec, ';', BPMF::E); - ASSIGNKEY1(ktcm, vec, ',', BPMF::ZH); - ASSIGNKEY1(ktcm, vec, '.', BPMF::CH); - ASSIGNKEY1(ktcm, vec, '/', BPMF::SH); - ASSIGNKEY1(ktcm, vec, 'a', BPMF::A); - ASSIGNKEY1(ktcm, vec, 'b', BPMF::B); - ASSIGNKEY1(ktcm, vec, 'c', BPMF::C); - ASSIGNKEY1(ktcm, vec, 'd', BPMF::D); - ASSIGNKEY1(ktcm, vec, 'e', BPMF::ER); - ASSIGNKEY1(ktcm, vec, 'f', BPMF::F); - ASSIGNKEY1(ktcm, vec, 'g', BPMF::G); - ASSIGNKEY1(ktcm, vec, 'h', BPMF::H); - ASSIGNKEY1(ktcm, vec, 'i', BPMF::EI); - ASSIGNKEY1(ktcm, vec, 'j', BPMF::J); - ASSIGNKEY1(ktcm, vec, 'k', BPMF::K); - ASSIGNKEY1(ktcm, vec, 'l', BPMF::L); - ASSIGNKEY1(ktcm, vec, 'm', BPMF::M); - ASSIGNKEY1(ktcm, vec, 'n', BPMF::N); - ASSIGNKEY1(ktcm, vec, 'o', BPMF::O); - ASSIGNKEY1(ktcm, vec, 'p', BPMF::P); - ASSIGNKEY1(ktcm, vec, 'q', BPMF::Q); - ASSIGNKEY1(ktcm, vec, 'r', BPMF::R); - ASSIGNKEY1(ktcm, vec, 's', BPMF::S); - ASSIGNKEY1(ktcm, vec, 't', BPMF::T); - ASSIGNKEY1(ktcm, vec, 'u', BPMF::OU); - ASSIGNKEY1(ktcm, vec, 'v', BPMF::UE); - ASSIGNKEY1(ktcm, vec, 'w', BPMF::U); - ASSIGNKEY1(ktcm, vec, 'x', BPMF::X); - ASSIGNKEY1(ktcm, vec, 'y', BPMF::I); - ASSIGNKEY1(ktcm, vec, 'z', BPMF::Z); - - return new BopomofoKeyboardLayout(ktcm, "MiTAC"); -} - -static BopomofoKeyboardLayout *CreateETenLayout() -{ - std::vector vec; - BopomofoKeyToComponentMap ktcm; - - ASSIGNKEY1(ktcm, vec, 'b', BPMF::B); - ASSIGNKEY1(ktcm, vec, 'p', BPMF::P); - ASSIGNKEY1(ktcm, vec, 'm', BPMF::M); - ASSIGNKEY1(ktcm, vec, 'f', BPMF::F); - ASSIGNKEY1(ktcm, vec, 'd', BPMF::D); - ASSIGNKEY1(ktcm, vec, 't', BPMF::T); - ASSIGNKEY1(ktcm, vec, 'n', BPMF::N); - ASSIGNKEY1(ktcm, vec, 'l', BPMF::L); - ASSIGNKEY1(ktcm, vec, 'v', BPMF::G); - ASSIGNKEY1(ktcm, vec, 'k', BPMF::K); - ASSIGNKEY1(ktcm, vec, 'h', BPMF::H); - ASSIGNKEY1(ktcm, vec, 'g', BPMF::J); - ASSIGNKEY1(ktcm, vec, '7', BPMF::Q); - ASSIGNKEY1(ktcm, vec, 'c', BPMF::X); - ASSIGNKEY1(ktcm, vec, ',', BPMF::ZH); - ASSIGNKEY1(ktcm, vec, '.', BPMF::CH); - ASSIGNKEY1(ktcm, vec, '/', BPMF::SH); - ASSIGNKEY1(ktcm, vec, 'j', BPMF::R); - ASSIGNKEY1(ktcm, vec, ';', BPMF::Z); - ASSIGNKEY1(ktcm, vec, '\'', BPMF::C); - ASSIGNKEY1(ktcm, vec, 's', BPMF::S); - ASSIGNKEY1(ktcm, vec, 'e', BPMF::I); - ASSIGNKEY1(ktcm, vec, 'x', BPMF::U); - ASSIGNKEY1(ktcm, vec, 'u', BPMF::UE); - ASSIGNKEY1(ktcm, vec, 'a', BPMF::A); - ASSIGNKEY1(ktcm, vec, 'o', BPMF::O); - ASSIGNKEY1(ktcm, vec, 'r', BPMF::ER); - ASSIGNKEY1(ktcm, vec, 'w', BPMF::E); - ASSIGNKEY1(ktcm, vec, 'i', BPMF::AI); - ASSIGNKEY1(ktcm, vec, 'q', BPMF::EI); - ASSIGNKEY1(ktcm, vec, 'z', BPMF::AO); - ASSIGNKEY1(ktcm, vec, 'y', BPMF::OU); - ASSIGNKEY1(ktcm, vec, '8', BPMF::AN); - ASSIGNKEY1(ktcm, vec, '9', BPMF::EN); - ASSIGNKEY1(ktcm, vec, '0', BPMF::ANG); - ASSIGNKEY1(ktcm, vec, '-', BPMF::ENG); - ASSIGNKEY1(ktcm, vec, '=', BPMF::ERR); - ASSIGNKEY1(ktcm, vec, '2', BPMF::Tone2); - ASSIGNKEY1(ktcm, vec, '3', BPMF::Tone3); - ASSIGNKEY1(ktcm, vec, '4', BPMF::Tone4); - ASSIGNKEY1(ktcm, vec, '1', BPMF::Tone5); - - return new BopomofoKeyboardLayout(ktcm, "ETen"); -} - -static BopomofoKeyboardLayout *CreateHsuLayout() -{ - std::vector vec; - BopomofoKeyToComponentMap ktcm; - - ASSIGNKEY1(ktcm, vec, 'b', BPMF::B); - ASSIGNKEY1(ktcm, vec, 'p', BPMF::P); - ASSIGNKEY2(ktcm, vec, 'm', BPMF::M, BPMF::AN); - ASSIGNKEY2(ktcm, vec, 'f', BPMF::F, BPMF::Tone3); - ASSIGNKEY2(ktcm, vec, 'd', BPMF::D, BPMF::Tone2); - ASSIGNKEY1(ktcm, vec, 't', BPMF::T); - ASSIGNKEY2(ktcm, vec, 'n', BPMF::N, BPMF::EN); - ASSIGNKEY3(ktcm, vec, 'l', BPMF::L, BPMF::ENG, BPMF::ERR); - ASSIGNKEY2(ktcm, vec, 'g', BPMF::G, BPMF::ER); - ASSIGNKEY2(ktcm, vec, 'k', BPMF::K, BPMF::ANG); - ASSIGNKEY2(ktcm, vec, 'h', BPMF::H, BPMF::O); - ASSIGNKEY3(ktcm, vec, 'j', BPMF::J, BPMF::ZH, BPMF::Tone4); - ASSIGNKEY2(ktcm, vec, 'v', BPMF::Q, BPMF::CH); - ASSIGNKEY2(ktcm, vec, 'c', BPMF::X, BPMF::SH); - ASSIGNKEY1(ktcm, vec, 'r', BPMF::R); - ASSIGNKEY1(ktcm, vec, 'z', BPMF::Z); - ASSIGNKEY2(ktcm, vec, 'a', BPMF::C, BPMF::EI); - ASSIGNKEY2(ktcm, vec, 's', BPMF::S, BPMF::Tone5); - ASSIGNKEY2(ktcm, vec, 'e', BPMF::I, BPMF::E); - ASSIGNKEY1(ktcm, vec, 'x', BPMF::U); - ASSIGNKEY1(ktcm, vec, 'u', BPMF::UE); - ASSIGNKEY1(ktcm, vec, 'y', BPMF::A); - ASSIGNKEY1(ktcm, vec, 'i', BPMF::AI); - ASSIGNKEY1(ktcm, vec, 'w', BPMF::AO); - ASSIGNKEY1(ktcm, vec, 'o', BPMF::OU); - - return new BopomofoKeyboardLayout(ktcm, "Hsu"); -} - -static BopomofoKeyboardLayout *CreateETen26Layout() -{ - std::vector vec; - BopomofoKeyToComponentMap ktcm; - - ASSIGNKEY1(ktcm, vec, 'b', BPMF::B); - ASSIGNKEY2(ktcm, vec, 'p', BPMF::P, BPMF::OU); - ASSIGNKEY2(ktcm, vec, 'm', BPMF::M, BPMF::AN); - ASSIGNKEY2(ktcm, vec, 'f', BPMF::F, BPMF::Tone2); - ASSIGNKEY2(ktcm, vec, 'd', BPMF::D, BPMF::Tone5); - ASSIGNKEY2(ktcm, vec, 't', BPMF::T, BPMF::ANG); - ASSIGNKEY2(ktcm, vec, 'n', BPMF::N, BPMF::EN); - ASSIGNKEY2(ktcm, vec, 'l', BPMF::L, BPMF::ENG); - ASSIGNKEY2(ktcm, vec, 'v', BPMF::G, BPMF::Q); - ASSIGNKEY2(ktcm, vec, 'k', BPMF::K, BPMF::Tone4); - ASSIGNKEY2(ktcm, vec, 'h', BPMF::H, BPMF::ERR); - ASSIGNKEY2(ktcm, vec, 'g', BPMF::ZH, BPMF::J); - ASSIGNKEY2(ktcm, vec, 'c', BPMF::SH, BPMF::X); - ASSIGNKEY1(ktcm, vec, 'y', BPMF::CH); - ASSIGNKEY2(ktcm, vec, 'j', BPMF::R, BPMF::Tone3); - ASSIGNKEY2(ktcm, vec, 'q', BPMF::Z, BPMF::EI); - ASSIGNKEY2(ktcm, vec, 'w', BPMF::C, BPMF::E); - ASSIGNKEY1(ktcm, vec, 's', BPMF::S); - ASSIGNKEY1(ktcm, vec, 'e', BPMF::I); - ASSIGNKEY1(ktcm, vec, 'x', BPMF::U); - ASSIGNKEY1(ktcm, vec, 'u', BPMF::UE); - ASSIGNKEY1(ktcm, vec, 'a', BPMF::A); - ASSIGNKEY1(ktcm, vec, 'o', BPMF::O); - ASSIGNKEY1(ktcm, vec, 'r', BPMF::ER); - ASSIGNKEY1(ktcm, vec, 'i', BPMF::AI); - ASSIGNKEY1(ktcm, vec, 'z', BPMF::AO); - - return new BopomofoKeyboardLayout(ktcm, "ETen26"); -} - -static BopomofoKeyboardLayout *CreateFakeSeigyouLayout() -{ - std::vector vec; - BopomofoKeyToComponentMap ktcm; - - ASSIGNKEY1(ktcm, vec, '1', BPMF::Tone5); - ASSIGNKEY1(ktcm, vec, '2', BPMF::B); - ASSIGNKEY1(ktcm, vec, '3', BPMF::D); - ASSIGNKEY1(ktcm, vec, '4', BPMF::I); - ASSIGNKEY1(ktcm, vec, '5', BPMF::U); - ASSIGNKEY1(ktcm, vec, '6', BPMF::ZH); - ASSIGNKEY1(ktcm, vec, '7', BPMF::UE); - ASSIGNKEY1(ktcm, vec, '8', BPMF::A); - ASSIGNKEY1(ktcm, vec, '9', BPMF::AI); - ASSIGNKEY1(ktcm, vec, '0', BPMF::AN); - ASSIGNKEY1(ktcm, vec, '-', BPMF::ERR); - ASSIGNKEY1(ktcm, vec, ';', BPMF::ANG); - ASSIGNKEY1(ktcm, vec, ',', BPMF::E); - ASSIGNKEY1(ktcm, vec, '.', BPMF::OU); - ASSIGNKEY1(ktcm, vec, '/', BPMF::ENG); - ASSIGNKEY1(ktcm, vec, 'a', BPMF::Tone3); - ASSIGNKEY1(ktcm, vec, 'b', BPMF::X); - ASSIGNKEY1(ktcm, vec, 'c', BPMF::L); - ASSIGNKEY1(ktcm, vec, 'd', BPMF::N); - ASSIGNKEY1(ktcm, vec, 'e', BPMF::T); - ASSIGNKEY1(ktcm, vec, 'f', BPMF::K); - ASSIGNKEY1(ktcm, vec, 'g', BPMF::Q); - ASSIGNKEY1(ktcm, vec, 'h', BPMF::SH); - ASSIGNKEY1(ktcm, vec, 'i', BPMF::O); - ASSIGNKEY1(ktcm, vec, 'j', BPMF::C); - ASSIGNKEY1(ktcm, vec, 'k', BPMF::ER); - ASSIGNKEY1(ktcm, vec, 'l', BPMF::AO); - ASSIGNKEY1(ktcm, vec, 'm', BPMF::S); - ASSIGNKEY1(ktcm, vec, 'n', BPMF::R); - ASSIGNKEY1(ktcm, vec, 'o', BPMF::EI); - ASSIGNKEY1(ktcm, vec, 'p', BPMF::EN); - ASSIGNKEY1(ktcm, vec, 'q', BPMF::Tone2); - ASSIGNKEY1(ktcm, vec, 'r', BPMF::G); - ASSIGNKEY1(ktcm, vec, 's', BPMF::M); - ASSIGNKEY1(ktcm, vec, 't', BPMF::J); - ASSIGNKEY1(ktcm, vec, 'u', BPMF::Z); - ASSIGNKEY1(ktcm, vec, 'v', BPMF::H); - ASSIGNKEY1(ktcm, vec, 'w', BPMF::P); - ASSIGNKEY1(ktcm, vec, 'x', BPMF::F); - ASSIGNKEY1(ktcm, vec, 'y', BPMF::CH); - ASSIGNKEY1(ktcm, vec, 'z', BPMF::Tone4); - - return new BopomofoKeyboardLayout(ktcm, "FakeSeigyou"); -} - -static BopomofoKeyboardLayout *CreateHanyuPinyinLayout() -{ - BopomofoKeyToComponentMap ktcm; - return new BopomofoKeyboardLayout(ktcm, "HanyuPinyin"); -} - -const BopomofoKeyboardLayout *BopomofoKeyboardLayout::StandardLayout() -{ - static BopomofoKeyboardLayout *layout = CreateStandardLayout(); - return layout; -} - -const BopomofoKeyboardLayout *BopomofoKeyboardLayout::ETenLayout() -{ - static BopomofoKeyboardLayout *layout = CreateETenLayout(); - return layout; -} - -const BopomofoKeyboardLayout *BopomofoKeyboardLayout::HsuLayout() -{ - static BopomofoKeyboardLayout *layout = CreateHsuLayout(); - return layout; -} - -const BopomofoKeyboardLayout *BopomofoKeyboardLayout::ETen26Layout() -{ - static BopomofoKeyboardLayout *layout = CreateETen26Layout(); - return layout; -} - -const BopomofoKeyboardLayout *BopomofoKeyboardLayout::IBMLayout() -{ - static BopomofoKeyboardLayout *layout = CreateIBMLayout(); - return layout; -} - -const BopomofoKeyboardLayout *BopomofoKeyboardLayout::MiTACLayout() -{ - static BopomofoKeyboardLayout *layout = CreateMiTACLayout(); - return layout; -} - -const BopomofoKeyboardLayout *BopomofoKeyboardLayout::FakeSeigyouLayout() -{ - static BopomofoKeyboardLayout *layout = CreateFakeSeigyouLayout(); - return layout; -} - -const BopomofoKeyboardLayout *BopomofoKeyboardLayout::HanyuPinyinLayout() -{ - static BopomofoKeyboardLayout *layout = CreateHanyuPinyinLayout(); - return layout; -} - -} // namespace Mandarin diff --git a/Source/3rdParty/OVMandarin/Mandarin.h b/Source/3rdParty/OVMandarin/Mandarin.h deleted file mode 100644 index 50ae8718..00000000 --- a/Source/3rdParty/OVMandarin/Mandarin.h +++ /dev/null @@ -1,587 +0,0 @@ -// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). -// All possible vChewing-specific modifications are of: -// (c) 2021 and onwards The vChewing Project (MIT-NTL License). -/* -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: - -1. The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -2. 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 above. - -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. -*/ - -#ifndef MANDARIN_H_ -#define MANDARIN_H_ - -#include -#include -#include -#include - -namespace Mandarin -{ - -class BopomofoSyllable -{ - public: - typedef uint16_t Component; - - explicit BopomofoSyllable(Component syllable = 0) : syllable_(syllable) - { - } - - BopomofoSyllable(const BopomofoSyllable &) = default; - BopomofoSyllable(BopomofoSyllable &&another) = default; - BopomofoSyllable &operator=(const BopomofoSyllable &) = default; - BopomofoSyllable &operator=(BopomofoSyllable &&) = default; - - // takes the ASCII-form, "v"-tolerant, TW-style Hanyu Pinyin (fong, pong, bong - // acceptable) - static const BopomofoSyllable FromHanyuPinyin(const std::string &str); - - // TO DO: Support accented vowels - const std::string HanyuPinyinString(bool includesTone, bool useVForUUmlaut) const; - - static const BopomofoSyllable FromComposedString(const std::string &str); - const std::string composedString() const; - - void clear() - { - syllable_ = 0; - } - - bool isEmpty() const - { - return !syllable_; - } - - bool hasConsonant() const - { - return !!(syllable_ & ConsonantMask); - } - - bool hasMiddleVowel() const - { - return !!(syllable_ & MiddleVowelMask); - } - bool hasVowel() const - { - return !!(syllable_ & VowelMask); - } - - bool hasToneMarker() const - { - return !!(syllable_ & ToneMarkerMask); - } - - Component consonantComponent() const - { - return syllable_ & ConsonantMask; - } - - Component middleVowelComponent() const - { - return syllable_ & MiddleVowelMask; - } - - Component vowelComponent() const - { - return syllable_ & VowelMask; - } - - Component toneMarkerComponent() const - { - return syllable_ & ToneMarkerMask; - } - - bool operator==(const BopomofoSyllable &another) const - { - return syllable_ == another.syllable_; - } - - bool operator!=(const BopomofoSyllable &another) const - { - return syllable_ != another.syllable_; - } - - bool isOverlappingWith(const BopomofoSyllable &another) const - { -#define IOW_SAND(mask) ((syllable_ & mask) && (another.syllable_ & mask)) - return IOW_SAND(ConsonantMask) || IOW_SAND(MiddleVowelMask) || IOW_SAND(VowelMask) || IOW_SAND(ToneMarkerMask); -#undef IOW_SAND - } - - // consonants J, Q, X all require the existence of vowel I or UE - bool belongsToJQXClass() const - { - Component consonant = syllable_ & ConsonantMask; - return (consonant == J || consonant == Q || consonant == X); - } - - // zi, ci, si, chi, chi, shi, ri - bool belongsToZCSRClass() const - { - Component consonant = syllable_ & ConsonantMask; - return (consonant >= ZH && consonant <= S); - } - - Component maskType() const - { - Component mask = 0; - mask |= (syllable_ & ConsonantMask) ? ConsonantMask : 0; - mask |= (syllable_ & MiddleVowelMask) ? MiddleVowelMask : 0; - mask |= (syllable_ & VowelMask) ? VowelMask : 0; - mask |= (syllable_ & ToneMarkerMask) ? ToneMarkerMask : 0; - return mask; - } - - const BopomofoSyllable operator+(const BopomofoSyllable &another) const - { - Component newSyllable = syllable_; -#define OP_SOVER(mask) \ - if (another.syllable_ & mask) \ - { \ - newSyllable = (newSyllable & ~mask) | (another.syllable_ & mask); \ - } - OP_SOVER(ConsonantMask); - OP_SOVER(MiddleVowelMask); - OP_SOVER(VowelMask); - OP_SOVER(ToneMarkerMask); -#undef OP_SOVER - return BopomofoSyllable(newSyllable); - } - - BopomofoSyllable &operator+=(const BopomofoSyllable &another) - { -#define OPE_SOVER(mask) \ - if (another.syllable_ & mask) \ - { \ - syllable_ = (syllable_ & ~mask) | (another.syllable_ & mask); \ - } - OPE_SOVER(ConsonantMask); - OPE_SOVER(MiddleVowelMask); - OPE_SOVER(VowelMask); - OPE_SOVER(ToneMarkerMask); -#undef OPE_SOVER - return *this; - } - - friend std::ostream &operator<<(std::ostream &stream, const BopomofoSyllable &syllable); - - static constexpr Component ConsonantMask = 0x001f, // 0000 0000 0001 1111, 21 consonants - MiddleVowelMask = 0x0060, // 0000 0000 0110 0000, 3 middle vowels - VowelMask = 0x0780, // 0000 0111 1000 0000, 13 vowels - ToneMarkerMask = 0x3800, // 0011 1000 0000 0000, 5 tones (tone1 = 0x00) - B = 0x0001, P = 0x0002, M = 0x0003, F = 0x0004, D = 0x0005, T = 0x0006, N = 0x0007, L = 0x0008, G = 0x0009, - K = 0x000a, H = 0x000b, J = 0x000c, Q = 0x000d, X = 0x000e, ZH = 0x000f, CH = 0x0010, - SH = 0x0011, R = 0x0012, Z = 0x0013, C = 0x0014, S = 0x0015, I = 0x0020, U = 0x0040, - UE = 0x0060, // ue = u umlaut (we use the German convention here as an - // ersatz to the /ju:/ sound) - A = 0x0080, O = 0x0100, ER = 0x0180, E = 0x0200, AI = 0x0280, EI = 0x0300, AO = 0x0380, OU = 0x0400, - AN = 0x0480, EN = 0x0500, ANG = 0x0580, ENG = 0x0600, ERR = 0x0680, Tone1 = 0x0000, - Tone2 = 0x0800, Tone3 = 0x1000, Tone4 = 0x1800, Tone5 = 0x2000; - - protected: - Component syllable_; -}; - -inline std::ostream &operator<<(std::ostream &stream, const BopomofoSyllable &syllable) -{ - stream << syllable.composedString(); - return stream; -} - -typedef BopomofoSyllable BPMF; - -typedef std::map> BopomofoKeyToComponentMap; -typedef std::map BopomofoComponentToKeyMap; - -extern "C" class BopomofoKeyboardLayout -{ - public: - static const BopomofoKeyboardLayout *StandardLayout(); - static const BopomofoKeyboardLayout *ETenLayout(); - static const BopomofoKeyboardLayout *HsuLayout(); - static const BopomofoKeyboardLayout *ETen26Layout(); - static const BopomofoKeyboardLayout *IBMLayout(); - static const BopomofoKeyboardLayout *MiTACLayout(); - static const BopomofoKeyboardLayout *FakeSeigyouLayout(); - static const BopomofoKeyboardLayout *HanyuPinyinLayout(); - - BopomofoKeyboardLayout(const BopomofoKeyToComponentMap &ktcm, const std::string &name) - : m_keyToComponent(ktcm), m_name(name) - { - for (BopomofoKeyToComponentMap::const_iterator miter = m_keyToComponent.begin(); - miter != m_keyToComponent.end(); ++miter) - for (std::vector::const_iterator viter = (*miter).second.begin(); - viter != (*miter).second.end(); ++viter) - m_componentToKey[*viter] = (*miter).first; - } - - const std::string name() const - { - return m_name; - } - - char componentToKey(BPMF::Component component) const - { - BopomofoComponentToKeyMap::const_iterator iter = m_componentToKey.find(component); - return (iter == m_componentToKey.end()) ? 0 : (*iter).second; - } - - const std::vector keyToComponents(char key) const - { - BopomofoKeyToComponentMap::const_iterator iter = m_keyToComponent.find(key); - return (iter == m_keyToComponent.end()) ? std::vector() : (*iter).second; - } - - const std::string keySequenceFromSyllable(BPMF syllable) const - { - std::string sequence; - - BPMF::Component c; - char k; -#define STKS_COMBINE(component) \ - if ((c = component)) \ - { \ - if ((k = componentToKey(c))) \ - sequence += std::string(1, k); \ - } - STKS_COMBINE(syllable.consonantComponent()); - STKS_COMBINE(syllable.middleVowelComponent()); - STKS_COMBINE(syllable.vowelComponent()); - STKS_COMBINE(syllable.toneMarkerComponent()); -#undef STKS_COMBINE - return sequence; - } - - const BPMF syllableFromKeySequence(const std::string &sequence) const - { - BPMF syllable; - - for (std::string::const_iterator iter = sequence.begin(); iter != sequence.end(); ++iter) - { - bool beforeSeqHasIorUE = sequenceContainsIorUE(sequence.begin(), iter); - bool aheadSeqHasIorUE = sequenceContainsIorUE(iter + 1, sequence.end()); - - std::vector components = keyToComponents(*iter); - - if (!components.size()) - continue; - - if (components.size() == 1) - { - syllable += BPMF(components[0]); - continue; - } - - BPMF head = BPMF(components[0]); - BPMF follow = BPMF(components[1]); - BPMF ending = components.size() > 2 ? BPMF(components[2]) : follow; - - // apply the I/UE + E rule - if (head.vowelComponent() == BPMF::E && follow.vowelComponent() != BPMF::E) - { - syllable += beforeSeqHasIorUE ? head : follow; - continue; - } - - if (head.vowelComponent() != BPMF::E && follow.vowelComponent() == BPMF::E) - { - syllable += beforeSeqHasIorUE ? follow : head; - continue; - } - - // apply the J/Q/X + I/UE rule, only two components are allowed in the - // components vector here - if (head.belongsToJQXClass() && !follow.belongsToJQXClass()) - { - if (!syllable.isEmpty()) - { - if (ending != follow) - syllable += ending; - } - else - { - syllable += aheadSeqHasIorUE ? head : follow; - } - - continue; - } - - if (!head.belongsToJQXClass() && follow.belongsToJQXClass()) - { - if (!syllable.isEmpty()) - { - if (ending != follow) - syllable += ending; - } - else - { - syllable += aheadSeqHasIorUE ? follow : head; - } - - continue; - } - - // the nasty issue of only one char in the buffer - if (iter == sequence.begin() && iter + 1 == sequence.end()) - { - if (head.hasVowel() || follow.hasToneMarker() || head.belongsToZCSRClass()) - { - syllable += head; - } - else - { - if (follow.hasVowel() || ending.hasToneMarker()) - { - syllable += follow; - } - else - { - syllable += ending; - } - } - - continue; - } - - if (!(syllable.maskType() & head.maskType()) && !endAheadOrAheadHasToneMarkKey(iter + 1, sequence.end())) - { - syllable += head; - } - else - { - if (endAheadOrAheadHasToneMarkKey(iter + 1, sequence.end()) && head.belongsToZCSRClass() && - syllable.isEmpty()) - { - syllable += head; - } - else if (syllable.maskType() < follow.maskType()) - { - syllable += follow; - } - else - { - syllable += ending; - } - } - } - - // heuristics for Hsu keyboard layout - if (this == HsuLayout()) - { - // fix the left out L to ERR when it has sound, and GI, GUE -> JI, JUE - if (syllable.vowelComponent() == BPMF::ENG && !syllable.hasConsonant() && !syllable.hasMiddleVowel()) - { - syllable += BPMF(BPMF::ERR); - } - else if (syllable.consonantComponent() == BPMF::G && - (syllable.middleVowelComponent() == BPMF::I || syllable.middleVowelComponent() == BPMF::UE)) - { - syllable += BPMF(BPMF::J); - } - } - - return syllable; - } - - protected: - bool endAheadOrAheadHasToneMarkKey(std::string::const_iterator ahead, std::string::const_iterator end) const - { - if (ahead == end) - return true; - - char tone1 = componentToKey(BPMF::Tone1); - char tone2 = componentToKey(BPMF::Tone2); - char tone3 = componentToKey(BPMF::Tone3); - char tone4 = componentToKey(BPMF::Tone4); - char tone5 = componentToKey(BPMF::Tone5); - - if (tone1) - if (*ahead == tone1) - return true; - - if (*ahead == tone2 || *ahead == tone3 || *ahead == tone4 || *ahead == tone5) - return true; - - return false; - } - - bool sequenceContainsIorUE(std::string::const_iterator start, std::string::const_iterator end) const - { - char iChar = componentToKey(BPMF::I); - char ueChar = componentToKey(BPMF::UE); - - for (; start != end; ++start) - if (*start == iChar || *start == ueChar) - return true; - return false; - } - - std::string m_name; - BopomofoKeyToComponentMap m_keyToComponent; - BopomofoComponentToKeyMap m_componentToKey; -}; - -extern "C" class BopomofoReadingBuffer -{ - public: - explicit BopomofoReadingBuffer(const BopomofoKeyboardLayout *layout) : layout_(layout), pinyin_mode_(false) - { - if (layout == BopomofoKeyboardLayout::HanyuPinyinLayout()) - { - pinyin_mode_ = true; - pinyin_sequence_ = ""; - } - } - - void setKeyboardLayout(const BopomofoKeyboardLayout *layout) - { - layout_ = layout; - - if (layout == BopomofoKeyboardLayout::HanyuPinyinLayout()) - { - pinyin_mode_ = true; - pinyin_sequence_ = ""; - } - } - - bool isValidKey(char k) const - { - if (!pinyin_mode_) - { - return layout_ ? (layout_->keyToComponents(k)).size() > 0 : false; - } - - char lk = tolower(k); - if (lk >= 'a' && lk <= 'z') - { - // if a tone marker is already in place - if (pinyin_sequence_.length()) - { - char lastc = pinyin_sequence_[pinyin_sequence_.length() - 1]; - if (lastc >= '2' && lastc <= '5') - { - return false; - } - return true; - } - return true; - } - - if (pinyin_sequence_.length() && (lk >= '2' && lk <= '5')) - { - return true; - } - - return false; - } - - bool combineKey(char k) - { - if (!isValidKey(k)) - return false; - - if (pinyin_mode_) - { - pinyin_sequence_ += std::string(1, tolower(k)); - syllable_ = BPMF::FromHanyuPinyin(pinyin_sequence_); - return true; - } - - std::string sequence = layout_->keySequenceFromSyllable(syllable_) + std::string(1, k); - syllable_ = layout_->syllableFromKeySequence(sequence); - return true; - } - - void clear() - { - pinyin_sequence_.clear(); - syllable_.clear(); - } - - void backspace() - { - if (!layout_) - return; - - if (pinyin_mode_) - { - if (pinyin_sequence_.length()) - { - pinyin_sequence_ = pinyin_sequence_.substr(0, pinyin_sequence_.length() - 1); - } - - syllable_ = BPMF::FromHanyuPinyin(pinyin_sequence_); - return; - } - - std::string sequence = layout_->keySequenceFromSyllable(syllable_); - if (sequence.length()) - { - sequence = sequence.substr(0, sequence.length() - 1); - syllable_ = layout_->syllableFromKeySequence(sequence); - } - } - - bool isEmpty() const - { - return syllable_.isEmpty(); - } - - const std::string composedString() const - { - if (pinyin_mode_) - { - return pinyin_sequence_; - } - - return syllable_.composedString(); - } - - const BPMF syllable() const - { - return syllable_; - } - - const std::string standardLayoutQueryString() const - { - return BopomofoKeyboardLayout::StandardLayout()->keySequenceFromSyllable(syllable_); - } - - bool hasToneMarker() const - { - return syllable_.hasToneMarker(); - } - - bool hasToneMarkerOnly() const - { - return syllable_.hasToneMarker() && - !(syllable_.hasConsonant() || syllable_.hasMiddleVowel() || syllable_.hasVowel()); - } - - protected: - const BopomofoKeyboardLayout *layout_; - BPMF syllable_; - - bool pinyin_mode_; - std::string pinyin_sequence_; -}; -} // namespace Mandarin - -#endif // MANDARIN_H_ diff --git a/Source/Data b/Source/Data index f49547bf..5abc6821 160000 --- a/Source/Data +++ b/Source/Data @@ -1 +1 @@ -Subproject commit f49547bff120f4a800d1930384a428890cf13f9d +Subproject commit 5abc68212bba31114197bdfee08dd615d89878bd diff --git a/Source/Headers/vChewing-Bridging-Header.h b/Source/Headers/vChewing-Bridging-Header.h index fd5078af..fa441994 100644 --- a/Source/Headers/vChewing-Bridging-Header.h +++ b/Source/Headers/vChewing-Bridging-Header.h @@ -31,4 +31,3 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @import Foundation; #import "CTools.h" -#import "Composer.hh" diff --git a/Source/Modules/ControllerModules/KeyHandler_Core.swift b/Source/Modules/ControllerModules/KeyHandler_Core.swift index cc8567fe..9c790668 100644 --- a/Source/Modules/ControllerModules/KeyHandler_Core.swift +++ b/Source/Modules/ControllerModules/KeyHandler_Core.swift @@ -48,6 +48,7 @@ protocol KeyHandlerDelegate: NSObjectProtocol { class KeyHandler: NSObject { let kEpsilon: Double = 0.000001 + var _composer: Tekkon.Composer = .init() var _inputMode: String = "" var _languageModel: vChewing.LMInstantiator = .init() var _userOverrideModel: vChewing.LMUserOverride = .init() @@ -73,12 +74,12 @@ class KeyHandler: NSObject { override init() { _builder = Megrez.BlockReadingBuilder(lm: _languageModel) super.init() - Composer.ensureParser() + ensureParser() setInputMode(ctlInputMethod.currentInputMode) } func clear() { - Composer.clearBuffer() + _composer.clear() _builder.clear() _walkedNodes.removeAll() } @@ -104,8 +105,8 @@ class KeyHandler: NSObject { // Create new grid builder. createNewBuilder() - if !Composer.isBufferEmpty() { - Composer.clearBuffer() + if !_composer.isEmpty { + _composer.clear() } } // 直接寫到衛星模組內,省得類型轉換 @@ -121,7 +122,7 @@ class KeyHandler: NSObject { let walker = Megrez.Walker(grid: _builder.grid()) // the reverse walk traces the grid from the end - let walked: [Megrez.NodeAnchor] = walker.reverseWalk(at: _builder.grid().width(), nodesLimit: 10) + let walked: [Megrez.NodeAnchor] = walker.reverseWalk(at: _builder.grid().width(), balanced: true) // then we use ".reversed()" to reverse the nodes so that we get the forward-walked nodes _walkedNodes.removeAll() @@ -258,7 +259,7 @@ class KeyHandler: NSObject { return highestScore + epsilon } - // MARK: - Extracted methods and functions. + // MARK: - Extracted methods and functions (Megrez). func isBuilderEmpty() -> Bool { _builder.grid().width() == 0 } @@ -321,4 +322,30 @@ class KeyHandler: NSObject { func getKeyLengthAtIndexZero() -> Int { _walkedNodes[0].node?.currentKeyValue().value.count ?? 0 } + + // MARK: - Extracted methods and functions (Tekkon). + + func ensureParser() { + switch mgrPrefs.mandarinParser { + case MandarinParser.ofStandard.rawValue: + _composer.ensureParser(arrange: .ofDachen) + case MandarinParser.ofEten.rawValue: + _composer.ensureParser(arrange: .ofEten) + case MandarinParser.ofHsu.rawValue: + _composer.ensureParser(arrange: .ofHsu) + case MandarinParser.ofEten26.rawValue: + _composer.ensureParser(arrange: .ofEten26) + case MandarinParser.ofIBM.rawValue: + _composer.ensureParser(arrange: .ofIBM) + case MandarinParser.ofMiTAC.rawValue: + _composer.ensureParser(arrange: .ofMiTAC) + case MandarinParser.ofFakeSeigyou.rawValue: + _composer.ensureParser(arrange: .ofFakeSeigyou) + default: + _composer.ensureParser(arrange: .ofDachen) + mgrPrefs.mandarinParser = MandarinParser.ofStandard.rawValue + } + _composer.clear() + } + } diff --git a/Source/Modules/ControllerModules/KeyHandler_HandleCandidate.swift b/Source/Modules/ControllerModules/KeyHandler_HandleCandidate.swift index f858bfef..f2aefffd 100644 --- a/Source/Modules/ControllerModules/KeyHandler_HandleCandidate.swift +++ b/Source/Modules/ControllerModules/KeyHandler_HandleCandidate.swift @@ -331,7 +331,7 @@ extension KeyHandler { let punctuation: String = arrPunctuations.joined(separator: "") var shouldAutoSelectCandidate: Bool = - Composer.chkKeyValidity(charCode) || ifLangModelHasUnigrams(forKey: customPunctuation) + _composer.inputValidityCheck(key: charCode) || ifLangModelHasUnigrams(forKey: customPunctuation) || ifLangModelHasUnigrams(forKey: punctuation) if !shouldAutoSelectCandidate, input.isUpperCaseASCIILetterKey { diff --git a/Source/Modules/ControllerModules/KeyHandler_HandleInput.swift b/Source/Modules/ControllerModules/KeyHandler_HandleInput.swift index 57153b4d..9928654d 100644 --- a/Source/Modules/ControllerModules/KeyHandler_HandleInput.swift +++ b/Source/Modules/ControllerModules/KeyHandler_HandleInput.swift @@ -147,34 +147,34 @@ extension KeyHandler { let skipPhoneticHandling = input.isReservedKey || input.isControlHold || input.isOptionHold // See if Phonetic reading is valid. - if !skipPhoneticHandling && Composer.chkKeyValidity(charCode) { - Composer.combineReadingKey(charCode) + if !skipPhoneticHandling && _composer.inputValidityCheck(key: charCode) { + _composer.receiveKey(fromCharCode: charCode) keyConsumedByReading = true // If we have a tone marker, we have to insert the reading to the // builder in other words, if we don't have a tone marker, we just // update the composing buffer. - let composeReading = Composer.hasToneMarker() + let composeReading = _composer.hasToneMarker() if !composeReading { stateCallback(buildInputtingState()) return true } } - var composeReading = Composer.hasToneMarker() || Composer.hasToneMarkerOnly() + var composeReading = _composer.hasToneMarker() // 這裡不需要做排他性判斷。 // See if we have composition if Enter/Space is hit and buffer is not empty. // We use "|=" conditioning so that the tone marker key is also taken into account. // However, Swift does not support "|=". - composeReading = composeReading || (!Composer.isBufferEmpty() && (input.isSpace || input.isEnter)) + composeReading = composeReading || (!_composer.isEmpty && (input.isSpace || input.isEnter)) if composeReading { - let reading = Composer.getSyllableComposition() + let reading = _composer.getRealComposition() // See whether we have a unigram for this... if !ifLangModelHasUnigrams(forKey: reading) { IME.prtDebugIntel("B49C0979:語彙庫內無「\(reading)」的匹配記錄。") errorCallback() - Composer.clearBuffer() + _composer.clear() stateCallback((getBuilderLength() == 0) ? InputState.EmptyIgnoringPreviousState() : buildInputtingState()) return true } @@ -189,7 +189,7 @@ extension KeyHandler { dealWithOverrideModelSuggestions() // ... then update the text. - Composer.clearBuffer() + _composer.clear() let inputting = buildInputtingState() inputting.poppedText = poppedText @@ -239,7 +239,7 @@ extension KeyHandler { // MARK: Calling candidate window using Space or Down or PageUp / PageDn. if let currentState = state as? InputState.NotEmpty { - if Composer.isBufferEmpty(), + if _composer.isEmpty, input.isExtraChooseCandidateKey || input.isExtraChooseCandidateKeyReverse || input.isSpace || input.isPageDown || input.isPageUp || input.isTab || (input.useVerticalMode && (input.isVerticalModeOnlyChooseCandidateKey)) @@ -354,7 +354,7 @@ extension KeyHandler { if input.isSymbolMenuPhysicalKey && !input.isShiftHold { if !input.isOptionHold { if ifLangModelHasUnigrams(forKey: "_punctuation_list") { - if Composer.isBufferEmpty() { + if _composer.isEmpty { insertReadingToBuilderAtCursor(reading: "_punctuation_list") let poppedText: String! = popOverflowComposingTextAndWalk() let inputting = buildInputtingState() @@ -443,7 +443,7 @@ extension KeyHandler { // "thinking" that the key is not actually consumed. // 砍掉這一段會導致「F1-F12 按鍵干擾組字區」的問題。 // 暫時只能先恢復這段,且補上偵錯彙報機制,方便今後排查故障。 - if (state is InputState.NotEmpty) || !Composer.isBufferEmpty() { + if (state is InputState.NotEmpty) || !_composer.isEmpty { IME.prtDebugIntel( "Blocked data: charCode: \(charCode), keyCode: \(input.keyCode)") IME.prtDebugIntel("A9BFF20E") diff --git a/Source/Modules/ControllerModules/KeyHandler_States.swift b/Source/Modules/ControllerModules/KeyHandler_States.swift index 4ab80928..454db395 100644 --- a/Source/Modules/ControllerModules/KeyHandler_States.swift +++ b/Source/Modules/ControllerModules/KeyHandler_States.swift @@ -87,7 +87,7 @@ extension KeyHandler { // The reading text is what the user is typing. let head = String((composingBuffer as NSString).substring(to: composedStringCursorIndex)) - let reading = Composer.getComposition() + let reading = _composer.getDisplayedComposition() let tail = String((composingBuffer as NSString).substring(from: composedStringCursorIndex)) let composedText = head + reading + tail let cursorIndex = composedStringCursorIndex + reading.count @@ -213,14 +213,14 @@ extension KeyHandler { return false } - if Composer.isBufferEmpty() { + if _composer.isEmpty { insertReadingToBuilderAtCursor(reading: customPunctuation) let poppedText = popOverflowComposingTextAndWalk() let inputting = buildInputtingState() inputting.poppedText = poppedText stateCallback(inputting) - if mgrPrefs.useSCPCTypingMode, Composer.isBufferEmpty() { + if mgrPrefs.useSCPCTypingMode, _composer.isEmpty { let candidateState = buildCandidate( state: inputting, useVerticalMode: useVerticalMode @@ -335,9 +335,9 @@ extension KeyHandler { return false } - if Composer.hasToneMarkerOnly() { - Composer.clearBuffer() - } else if Composer.isBufferEmpty() { + if _composer.hasToneMarker(withNothingElse: true) { + _composer.clear() + } else if _composer.isEmpty { if getBuilderCursorIndex() >= 0 { deleteBuilderReadingInFrontOfCursor() walk() @@ -348,10 +348,10 @@ extension KeyHandler { return true } } else { - Composer.doBackSpaceToBuffer() + _composer.doBackSpace() } - if Composer.isBufferEmpty(), getBuilderLength() == 0 { + if _composer.isEmpty, getBuilderLength() == 0 { stateCallback(InputState.EmptyIgnoringPreviousState()) } else { stateCallback(buildInputtingState()) @@ -370,7 +370,7 @@ extension KeyHandler { return false } - if Composer.isBufferEmpty() { + if _composer.isEmpty { if getBuilderCursorIndex() != getBuilderLength() { deleteBuilderReadingAfterCursor() walk() @@ -405,7 +405,7 @@ extension KeyHandler { if !(state is InputState.Inputting) { return false } - if !Composer.isBufferEmpty() { + if !_composer.isEmpty { IME.prtDebugIntel("9B6F908D") errorCallback() } @@ -424,7 +424,7 @@ extension KeyHandler { return false } - if !Composer.isBufferEmpty() { + if !_composer.isEmpty { IME.prtDebugIntel("ABC44080") errorCallback() stateCallback(state) @@ -454,7 +454,7 @@ extension KeyHandler { return false } - if !Composer.isBufferEmpty() { + if !_composer.isEmpty { IME.prtDebugIntel("9B69908D") errorCallback() stateCallback(state) @@ -493,8 +493,8 @@ extension KeyHandler { stateCallback(InputState.EmptyIgnoringPreviousState()) } else { // If reading is not empty, we cancel the reading. - if !Composer.isBufferEmpty() { - Composer.clearBuffer() + if !_composer.isEmpty { + _composer.clear() if getBuilderLength() == 0 { stateCallback(InputState.EmptyIgnoringPreviousState()) } else { @@ -515,7 +515,7 @@ extension KeyHandler { ) -> Bool { if !(state is InputState.Inputting) { return false } - if !Composer.isBufferEmpty() { + if !_composer.isEmpty { IME.prtDebugIntel("B3BA5257") errorCallback() stateCallback(state) @@ -566,7 +566,7 @@ extension KeyHandler { ) -> Bool { if !(state is InputState.Inputting) { return false } - if !Composer.isBufferEmpty() { + if !_composer.isEmpty { IME.prtDebugIntel("6ED95318") errorCallback() stateCallback(state) diff --git a/Source/Modules/ControllerModules/SyllableComposer.swift b/Source/Modules/ControllerModules/SyllableComposer.swift new file mode 100644 index 00000000..add9d9f3 --- /dev/null +++ b/Source/Modules/ControllerModules/SyllableComposer.swift @@ -0,0 +1,546 @@ +// (c) 2022 and onwards The vChewing Project (MIT-NTL 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 +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: + +1. The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +2. 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 above. + +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 Foundation + +/// The namespace for this package. +public struct Tekkon { + // MARK: - Static Constants and Basic Enums + + public enum PhoneType: Int { + case null = 0 // 假 + case consonant = 1 // 聲 + case semivowel = 2 // 韻 + case vowel = 3 // 介 + case intonation = 4 // 調 + } + + public enum MandarinParser: Int { + case ofDachen = 0 + case ofEten = 1 + case ofHsu = 2 + case ofEten26 = 3 + case ofIBM = 4 + case ofMiTAC = 5 + case ofFakeSeigyou = 6 + case ofSeigyou = 7 + case ofHanyuPinyin = 10 + + var name: String { + switch self { + case .ofDachen: + return "Dachen" + case .ofEten: + return "ETen" + case .ofHsu: + return "Hsu" + case .ofEten26: + return "ETen26" + case .ofIBM: + return "IBM" + case .ofMiTAC: + return "MiTAC" + case .ofFakeSeigyou: + return "FakeSeigyou" + case .ofSeigyou: + return "Seigyou" + case .ofHanyuPinyin: + return "HanyuPinyin" + } + } + } + + public static let allowedConsonants = [ + "ㄅ", "ㄆ", "ㄇ", "ㄈ", "ㄉ", "ㄊ", "ㄋ", "ㄌ", + "ㄍ", "ㄎ", "ㄏ", "ㄐ", "ㄑ", "ㄒ", + "ㄓ", "ㄔ", "ㄕ", "ㄖ", "ㄗ", "ㄘ", "ㄙ", + ] + + public static let allowedsemivowels = ["ㄧ", "ㄨ", "ㄩ"] + + public static let allowedVowels = [ + "ㄚ", "ㄛ", "ㄜ", "ㄝ", "ㄞ", "ㄟ", + "ㄠ", "ㄡ", "ㄢ", "ㄣ", "ㄤ", "ㄥ", "ㄦ", + ] + + public static let allowedIntonations = [" ", "ˊ", "ˇ", "ˋ", "˙"] + + public static var allowedPhonabets: [String] { + allowedConsonants + allowedsemivowels + allowedVowels + allowedIntonations + } + + // MARK: - Phonabet Structure + + @frozen public struct Phonabet: Equatable, Hashable, ExpressibleByStringLiteral { + public var type: PhoneType = .null + public var value: String = "" + public var isEmpty: Bool { + value.isEmpty + } + + public init(_ input: String = "") { + if !input.isEmpty { + if allowedPhonabets.contains(String(input.reversed()[0])) { + value = String(input.reversed()[0]) + if Tekkon.allowedConsonants.contains(value) { type = .consonant } + if Tekkon.allowedsemivowels.contains(value) { type = .semivowel } + if Tekkon.allowedVowels.contains(value) { type = .vowel } + if Tekkon.allowedIntonations.contains(value) { type = .intonation } + } + } + } + + public mutating func clear() { + value = "" + } + + // MARK: - Misc Definitions + + public static func == (lhs: Phonabet, rhs: Phonabet) -> Bool { + lhs.value == rhs.value + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(value) + hasher.combine(type) + } + + public init(stringLiteral value: String) { + self.init(value) + } + + public init(unicodeScalarLiteral value: String) { + self.init(stringLiteral: value) + } + + public init(extendedGraphemeClusterLiteral value: String) { + self.init(stringLiteral: value) + } + } + + // MARK: - Syllable Composer + + @frozen public struct Composer: Equatable, Hashable, ExpressibleByStringLiteral { + public var consonant: Phonabet = "" + public var semivowel: Phonabet = "" + public var vowel: Phonabet = "" + public var intonation: Phonabet = "" + public var parser: MandarinParser = .ofDachen + public var value: String { + consonant.value + semivowel.value + vowel.value + intonation.value.replacingOccurrences(of: " ", with: "") + } + + public var isEmpty: Bool { + intonation.isEmpty && vowel.isEmpty && semivowel.isEmpty && consonant.isEmpty + } + + public init(_ input: String = "", arrange parser: MandarinParser = .ofDachen) { + receiveKey(fromString: input) + ensureParser(arrange: parser) + } + + public mutating func clear() { + consonant.clear() + semivowel.clear() + vowel.clear() + intonation.clear() + } + + // MARK: - Public Functions + + /// 用於檢測「某個輸入字符訊號的合規性」的函數。 + /// Phonabet 是一個特殊的 String 類 Struct, + /// 只會接受正確的注音符號資料、且根據其類型自動回報其類型。 + /// 類型只有「聲、韻、介、調」這四類。 + public func inputValidityCheck(key inputKey: UniChar = 0) -> Bool { + if let scalar = UnicodeScalar(inputKey) { + let input = String(scalar) + switch parser { + case .ofDachen: + return Tekkon.mapQwertyDachen[input] != nil + case .ofEten: + return Tekkon.mapQwertyEtenTraditional[input] != nil + case .ofHsu: + return Tekkon.mapHsuStaticKeys[input] != nil + case .ofEten26: + return Tekkon.mapEten26StaticKeys[input] != nil + case .ofIBM: + return Tekkon.mapQwertyIBM[input] != nil + case .ofMiTAC: + return Tekkon.mapQwertyMiTAC[input] != nil + case .ofSeigyou: + return Tekkon.mapSeigyou[input] != nil + case .ofFakeSeigyou: + return Tekkon.mapFakeSeigyou[input] != nil + case .ofHanyuPinyin: + return Tekkon.mapArayuruPinyin.contains(input) + } + } + return false + } + + public mutating func receiveKey(fromString input: String = "") { + let translatedInput = translate(key: String(input)) + let thePhone: Phonabet = .init(translatedInput) + switch thePhone.type { + case .consonant: consonant = thePhone + case .semivowel: semivowel = thePhone + case .vowel: vowel = thePhone + case .intonation: intonation = thePhone + default: break + } + } + + public mutating func receiveKey(fromCharCode inputCharCode: UniChar = 0) { + if let scalar = UnicodeScalar(inputCharCode) { + let translatedInput = translate(key: String(scalar)) + let thePhone: Phonabet = .init(translatedInput) + switch thePhone.type { + case .consonant: consonant = thePhone + case .semivowel: semivowel = thePhone + case .vowel: vowel = thePhone + case .intonation: intonation = thePhone + default: break + } + } + } + + /// 本來這個函數是不需要的,但將來在做漢語拼音功能時、這裡得回傳別的東西。 + /// 也就是說,這個函數就是用來決定輸入法組字區內顯示的注音/拼音內容。 + public func getDisplayedComposition() -> String { + value + } + + /// 這是專門用來「生成用以進行詞庫檢索的 Key」的函數。 + public func getRealComposition() -> String { + value + } + + /// 專門用來響應使用者摁下 BackSpace 按鍵時的行為。 + public mutating func doBackSpace() { + if !intonation.isEmpty { + intonation.clear() + } else if !vowel.isEmpty { + vowel.clear() + } else if !semivowel.isEmpty { + semivowel.clear() + } else if !consonant.isEmpty { + consonant.clear() + } + } + + /// 用來檢測是否有調號 + public func hasToneMarker(withNothingElse: Bool = false) -> Bool { + if !withNothingElse { + return !intonation.isEmpty + } + return !intonation.isEmpty && vowel.isEmpty && semivowel.isEmpty && consonant.isEmpty + } + + /// 當接收按鍵輸入時的處理。本來 Phonabet 就會自動使輸入的無效數值被忽略掉。 + /// 然後再根據 Phonabet 初期化後自身的 type 屬性來決定「聲、韻、介、調」到底哪個該更新。 + public mutating func receiveCharCode(_ inputKey: UniChar = 0) { + // TODO: 在這裡補上鍵盤轉換工序 + if let scalar = UnicodeScalar(inputKey) { + let input = String(scalar) + receiveKey(fromString: input) + } + } + + // 設定該 Composer 處於何種鍵盤排列分析模式 + public mutating func ensureParser(arrange: MandarinParser = .ofDachen) { + parser = arrange + } + + // MARK: - Parser Processings + + mutating func translate(key: String = "") -> String { + switch parser { + case .ofDachen: + return Tekkon.mapQwertyDachen[key] ?? "" + case .ofEten: + return Tekkon.mapQwertyEtenTraditional[key] ?? "" + case .ofHsu: + return handleHsu(key: key) + case .ofEten26: + return handleEten26(key: key) + case .ofIBM: + return Tekkon.mapQwertyIBM[key] ?? "" + case .ofMiTAC: + return Tekkon.mapQwertyMiTAC[key] ?? "" + case .ofSeigyou: + return Tekkon.mapSeigyou[key] ?? "" + case .ofFakeSeigyou: + return Tekkon.mapFakeSeigyou[key] ?? "" + case .ofHanyuPinyin: break // TODO: 待辦 + } + return "" + } + + /// 倚天忘形注音排列比較麻煩,需要單獨處理。 + mutating func handleEten26(key: String = "") -> String { + var strReturn = "" + strReturn = Tekkon.mapEten26StaticKeys[key] ?? "" + let incomingPhonabet = Phonabet(strReturn) + + switch key { + case "d": if consonant.isEmpty { consonant = "ㄉ" } else { intonation = "˙" } + case "f": if consonant.isEmpty { consonant = "ㄈ" } else { intonation = "ˊ" } + case "h": if consonant.isEmpty { consonant = "ㄏ" } else { vowel = "ㄦ" } + case "j": if consonant.isEmpty { consonant = "ㄖ" } else { intonation = "ˇ" } + case "k": if consonant.isEmpty { consonant = "ㄎ" } else { intonation = "ˋ" } + case "l": if consonant.isEmpty { consonant = "ㄌ" } else { vowel = "ㄥ" } + case "m": if consonant.isEmpty { consonant = "ㄇ" } else { vowel = "ㄢ" } + case "n": if consonant.isEmpty { consonant = "ㄋ" } else { vowel = "ㄣ" } + case "p": if consonant.isEmpty { consonant = "ㄆ" } else { vowel = "ㄡ" } + case "q": if consonant.isEmpty { consonant = "ㄗ" } else { vowel = "ㄟ" } + case "t": if consonant.isEmpty { consonant = "ㄊ" } else { vowel = "ㄤ" } + case "w": if consonant.isEmpty { consonant = "ㄘ" } else { vowel = "ㄝ" } + default: break + } + + // 處理「一個按鍵對應兩個聲母」的情形。 + if !consonant.isEmpty, incomingPhonabet.type == .semivowel { + switch consonant { + case "ㄍ": + switch incomingPhonabet { + case "ㄧ": consonant = "ㄑ" // ㄑㄧ + case "ㄨ": consonant = "ㄍ" // ㄍㄨ + case "ㄩ": consonant = "ㄑ" // ㄑㄩ + default: break + } + case "ㄓ": + switch incomingPhonabet { + case "ㄧ": consonant = "ㄐ" // ㄐㄧ + case "ㄨ": consonant = "ㄓ" // ㄓㄨ + case "ㄩ": consonant = "ㄐ" // ㄐㄩ + default: break + } + case "ㄕ": + switch incomingPhonabet { + case "ㄧ": consonant = "ㄒ" // ㄒㄧ + case "ㄨ": consonant = "ㄕ" // ㄕㄨ + case "ㄩ": consonant = "ㄒ" // ㄒㄩ + default: break + } + default: break + } + } + + return strReturn + } + + /// 許氏鍵盤與倚天忘形一樣同樣也比較麻煩,需要單獨處理。 + mutating func handleHsu(key: String = "") -> String { + var strReturn = "" + strReturn = Tekkon.mapHsuStaticKeys[key] ?? "" + let incomingPhonabet = Phonabet(strReturn) + + switch key { + case "e": if semivowel.isEmpty { semivowel = "ㄧ" } else { vowel = "ㄝ" } + case "a": if consonant.isEmpty { consonant = "ㄘ" } else { vowel = "ㄟ" } + case "g": if consonant.isEmpty { consonant = "ㄍ" } else { vowel = "ㄜ" } + case "h": if consonant.isEmpty { consonant = "ㄏ" } else { vowel = "ㄛ" } + case "k": if consonant.isEmpty { consonant = "ㄎ" } else { vowel = "ㄤ" } + case "m": if consonant.isEmpty { consonant = "ㄇ" } else { vowel = "ㄢ" } + case "n": if consonant.isEmpty { consonant = "ㄋ" } else { vowel = "ㄣ" } + case "s": if consonant.isEmpty { consonant = "ㄙ" } else { intonation = "˙" } + case "d": if consonant.isEmpty { consonant = "ㄉ" } else { intonation = "ˊ" } + case "f": if consonant.isEmpty { consonant = "ㄈ" } else { intonation = "ˇ" } + case "l": if value.isEmpty { vowel = "ㄦ" } else if consonant.isEmpty { consonant = "ㄌ" } else { vowel = "ㄥ" } + case "j": if !consonant.isEmpty { intonation = "ˋ" } + default: break + } + + // 處理「一個按鍵對應兩個聲母」的情形。 + if !consonant.isEmpty, incomingPhonabet.type == .semivowel { + switch consonant { + case "ㄓ": + if intonation.isEmpty { + switch incomingPhonabet { + case "ㄧ": consonant = "ㄐ" // ㄐㄧ + case "ㄨ": consonant = "ㄓ" // ㄓㄨ + case "ㄩ": consonant = "ㄐ" // ㄐㄩ + default: break + } + } + case "ㄕ": + switch incomingPhonabet { + case "ㄧ": consonant = "ㄒ" // ㄒㄧ + case "ㄨ": consonant = "ㄕ" // ㄕㄨ + case "ㄩ": consonant = "ㄒ" // ㄒㄩ + default: break + } + default: break + } + } + + return strReturn + } + + // MARK: - Misc Definitions + + public static func == (lhs: Composer, rhs: Composer) -> Bool { + lhs.value == rhs.value + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(consonant) + hasher.combine(semivowel) + hasher.combine(vowel) + hasher.combine(intonation) + } + + public init(stringLiteral value: String) { + self.init(value) + } + + public init(unicodeScalarLiteral value: String) { + self.init(stringLiteral: value) + } + + public init(extendedGraphemeClusterLiteral value: String) { + self.init(stringLiteral: value) + } + } + + // MARK: - Phonabets (Enum) + + enum Phonabets: Phonabet { + case ofBO = "ㄅ" + case ofPO = "ㄆ" + case ofMO = "ㄇ" + case ofFO = "ㄈ" + case ofDE = "ㄉ" + case ofTE = "ㄊ" + case ofNE = "ㄋ" + case ofLE = "ㄌ" + case ofGE = "ㄍ" + case ofKE = "ㄎ" + case ofHE = "ㄏ" + case ofJI = "ㄐ" + case ofQI = "ㄑ" + case ofXI = "ㄒ" + case ofZH = "ㄓ" + case ofCH = "ㄔ" + case ofSH = "ㄕ" + case ofRI = "ㄖ" + case ofZI = "ㄗ" + case ofCI = "ㄘ" + case ofSI = "ㄙ" + case ofYI = "ㄧ" + case ofWU = "ㄨ" + case ofYU = "ㄩ" + case ofAA = "ㄚ" + case ofOO = "ㄛ" + case ofEE = "ㄜ" + case ofEA = "ㄝ" + case ofAI = "ㄞ" + case ofEI = "ㄟ" + case ofAO = "ㄠ" + case ofOU = "ㄡ" + case ofAN = "ㄢ" + case ofEN = "ㄣ" + case ofAG = "ㄤ" + case ofOG = "ㄥ" + case ofT1 = " " + case ofT2 = "ˊ" + case ofT3 = "ˇ" + case ofT4 = "ˋ" + case ofT5 = "˙" + } + + // MARK: - Maps for Keyboard-to-Phonabet parsers + + // 任何形式的拼音排列都會用到的陣列,用 Strings 反而省事一些。 + static let mapArayuruPinyin: String = "abcdefghijklmnopqrstuvwxyz12345 " + + /// 標準大千排列專用處理陣列。 + /// 威注音輸入法 macOS 版使用了 Ukelele 佈局來完成對諸如倚天傳統等其它注音鍵盤排列的支援。 + /// 如果要將鐵恨模組拿給別的平台的輸入法使用的話,恐怕需要針對這些注音鍵盤排列各自新增專用陣列才可以。 + static let mapQwertyDachen: [String: String] = [ + "0": "ㄢ", "1": "ㄅ", "2": "ㄉ", "3": "ˇ", "4": "ˋ", "5": "ㄓ", "6": "ˊ", "7": "˙", "8": "ㄚ", "9": "ㄞ", "-": "ㄦ", + ",": "ㄝ", ".": "ㄡ", "/": "ㄥ", ";": "ㄤ", "a": "ㄇ", "b": "ㄖ", "c": "ㄏ", "d": "ㄎ", "e": "ㄍ", "f": "ㄑ", "g": "ㄕ", + "h": "ㄘ", "i": "ㄛ", "j": "ㄨ", "k": "ㄜ", "l": "ㄠ", "m": "ㄩ", "n": "ㄙ", "o": "ㄟ", "p": "ㄣ", "q": "ㄆ", "r": "ㄐ", + "s": "ㄋ", "t": "ㄔ", "u": "ㄧ", "v": "ㄒ", "w": "ㄊ", "x": "ㄌ", "y": "ㄗ", "z": "ㄈ", " ": " ", + ] + + /// 許氏排列專用處理陣列,但未包含全部的映射內容。 + /// 在這裡將二十六個字母寫全,也只是為了方便做 validity check。 + /// 這裡提前對複音按鍵做處理,然後再用程式判斷介母類型、據此判斷是否需要做複音切換。 + static let mapHsuStaticKeys: [String: String] = [ + "a": "ㄘ", "b": "ㄅ", "c": "ㄕ", "d": "ㄉ", "e": "ㄧ", "f": "ㄈ", "g": "ㄍ", "h": "ㄏ", "i": "ㄞ", "j": "ㄓ", "k": "ㄎ", + "l": "ㄌ", "m": "ㄇ", "n": "ㄋ", "o": "ㄡ", "p": "ㄆ", "r": "ㄖ", "s": "ㄙ", "t": "ㄊ", "u": "ㄩ", "v": "ㄑ", "w": "ㄠ", + "x": "ㄨ", "y": "ㄚ", "z": "ㄗ", " ": " ", + ] + + /// 倚天忘形排列預處理專用陣列,但未包含全部的映射內容。 + /// 在這裡將二十六個字母寫全,也只是為了方便做 validity check。 + /// 這裡提前對ㄓ/ㄍ/ㄕ做處理,然後再用程式判斷介母類型、據此判斷是否需要換成ㄒ/ㄑ/ㄐ。 + static let mapEten26StaticKeys: [String: String] = [ + "a": "ㄚ", "b": "ㄅ", "c": "ㄕ", "d": "ㄉ", "e": "ㄧ", "f": "ㄈ", "g": "ㄓ", "h": "ㄏ", "i": "ㄞ", "j": "ㄖ", "k": "ㄎ", + "l": "ㄌ", "m": "ㄇ", "n": "ㄋ", "o": "ㄛ", "p": "ㄆ", "q": "ㄗ", "r": "ㄜ", "s": "ㄙ", "t": "ㄊ", "u": "ㄩ", "v": "ㄍ", + "w": "ㄘ", "x": "ㄨ", "y": "ㄔ", "z": "ㄠ", " ": " ", + ] + + /// 倚天傳統排列專用處理陣列。 + static let mapQwertyEtenTraditional: [String: String] = [ + "'": "ㄘ", ",": "ㄓ", "-": "ㄥ", ".": "ㄔ", "/": "ㄕ", "0": "ㄤ", "1": "˙", "2": "ˊ", "3": "ˇ", "4": "ˋ", "7": "ㄑ", + "8": "ㄢ", "9": "ㄣ", ";": "ㄗ", "=": "ㄦ", "a": "ㄚ", "b": "ㄅ", "c": "ㄒ", "d": "ㄉ", "e": "ㄧ", "f": "ㄈ", "g": "ㄐ", + "h": "ㄏ", "i": "ㄞ", "j": "ㄖ", "k": "ㄎ", "l": "ㄌ", "m": "ㄇ", "n": "ㄋ", "o": "ㄛ", "p": "ㄆ", "q": "ㄟ", "r": "ㄜ", + "s": "ㄙ", "t": "ㄊ", "u": "ㄩ", "v": "ㄍ", "w": "ㄝ", "x": "ㄨ", "y": "ㄡ", "z": "ㄠ", " ": " ", + ] + + /// IBM排列專用處理陣列。 + static let mapQwertyIBM: [String: String] = [ + ",": "ˇ", "-": "ㄏ", ".": "ˋ", "/": "˙", "0": "ㄎ", "1": "ㄅ", "2": "ㄆ", "3": "ㄇ", "4": "ㄈ", "5": "ㄉ", "6": "ㄊ", + "7": "ㄋ", "8": "ㄌ", "9": "ㄍ", ";": "ㄠ", "a": "ㄧ", "b": "ㄥ", "c": "ㄣ", "d": "ㄩ", "e": "ㄒ", "f": "ㄚ", "g": "ㄛ", + "h": "ㄜ", "i": "ㄗ", "j": "ㄝ", "k": "ㄞ", "l": "ㄟ", "m": "ˊ", "n": "ㄦ", "o": "ㄘ", "p": "ㄙ", "q": "ㄐ", "r": "ㄓ", + "s": "ㄨ", "t": "ㄔ", "u": "ㄖ", "v": "ㄤ", "w": "ㄑ", "x": "ㄢ", "y": "ㄕ", "z": "ㄡ", " ": " ", + ] + + /// 精業排列專用處理陣列。 + static let mapSeigyou: [String: String] = [ + "a": "ˇ", "b": "ㄒ", "c": "ㄌ", "d": "ㄋ", "e": "ㄊ", "f": "ㄎ", "g": "ㄑ", "h": "ㄕ", "i": "ㄛ", "j": "ㄘ", "k": "ㄜ", + "l": "ㄠ", "m": "ㄙ", "n": "ㄖ", "o": "ㄟ", "p": "ㄣ", "q": "ˊ", "r": "ㄍ", "s": "ㄇ", "t": "ㄐ", "u": "ㄗ", "v": "ㄏ", + "w": "ㄆ", "x": "ㄈ", "y": "ㄔ", "z": "ˋ", "1": "˙", "2": "ㄅ", "3": "ㄉ", "6": "ㄓ", "8": "ㄚ", "9": "ㄞ", "0": "ㄢ", + "-": "ㄧ", ";": "ㄤ", ",": "ㄝ", ".": "ㄡ", "/": "ㄥ", "'": "ㄩ", "[": "ㄨ", "=": "ㄦ", " ": " ", + ] + + /// 偽精業排列專用處理陣列。 + static let mapFakeSeigyou: [String: String] = [ + "a": "ˇ", "b": "ㄒ", "c": "ㄌ", "d": "ㄋ", "e": "ㄊ", "f": "ㄎ", "g": "ㄑ", "h": "ㄕ", "i": "ㄛ", "j": "ㄘ", "k": "ㄜ", + "l": "ㄠ", "m": "ㄙ", "n": "ㄖ", "o": "ㄟ", "p": "ㄣ", "q": "ˊ", "r": "ㄍ", "s": "ㄇ", "t": "ㄐ", "u": "ㄗ", "v": "ㄏ", + "w": "ㄆ", "x": "ㄈ", "y": "ㄔ", "z": "ˋ", "1": "˙", "2": "ㄅ", "3": "ㄉ", "6": "ㄓ", "8": "ㄚ", "9": "ㄞ", "0": "ㄢ", + "4": "ㄧ", ";": "ㄤ", ",": "ㄝ", ".": "ㄡ", "/": "ㄥ", "7": "ㄩ", "5": "ㄨ", "-": "ㄦ", " ": " ", + ] + + /// 神通排列專用處理陣列。 + static let mapQwertyMiTAC: [String: String] = [ + ",": "ㄓ", "-": "ㄦ", ".": "ㄔ", "/": "ㄕ", "0": "ㄥ", "1": "˙", "2": "ˊ", "3": "ˇ", "4": "ˋ", "5": "ㄞ", "6": "ㄠ", + "7": "ㄢ", "8": "ㄣ", "9": "ㄤ", ";": "ㄝ", "a": "ㄚ", "b": "ㄅ", "c": "ㄘ", "d": "ㄉ", "e": "ㄜ", "f": "ㄈ", "g": "ㄍ", + "h": "ㄏ", "i": "ㄟ", "j": "ㄐ", "k": "ㄎ", "l": "ㄌ", "m": "ㄇ", "n": "ㄋ", "o": "ㄛ", "p": "ㄆ", "q": "ㄑ", "r": "ㄖ", + "s": "ㄙ", "t": "ㄊ", "u": "ㄡ", "v": "ㄩ", "w": "ㄨ", "x": "ㄒ", "y": "ㄧ", "z": "ㄗ", " ": " ", + ] +} diff --git a/Source/Modules/IMEModules/ctlInputMethod.swift b/Source/Modules/IMEModules/ctlInputMethod.swift index a01c275e..08cb21e6 100644 --- a/Source/Modules/IMEModules/ctlInputMethod.swift +++ b/Source/Modules/IMEModules/ctlInputMethod.swift @@ -93,7 +93,8 @@ class ctlInputMethod: IMKInputController { currentClient = client keyHandler.clear() - Composer.ensureParser() + keyHandler.ensureParser() + if let bundleCheckID = (client as? IMKTextInput)?.bundleIdentifier() { if bundleCheckID != Bundle.main.bundleIdentifier { // Override the keyboard layout to the basic one. diff --git a/Source/Modules/IMEModules/mgrPrefs.swift b/Source/Modules/IMEModules/mgrPrefs.swift index 6f5dee5c..1a38a935 100644 --- a/Source/Modules/IMEModules/mgrPrefs.swift +++ b/Source/Modules/IMEModules/mgrPrefs.swift @@ -168,7 +168,7 @@ struct ComposingBufferSize { case ofStandard = 0 case ofEten = 1 case ofHsu = 2 - case ofEen26 = 3 + case ofEten26 = 3 case ofIBM = 4 case ofMiTAC = 5 case ofFakeSeigyou = 6 @@ -182,7 +182,7 @@ struct ComposingBufferSize { return "ETen" case .ofHsu: return "Hsu" - case .ofEen26: + case .ofEten26: return "ETen26" case .ofIBM: return "IBM" diff --git a/Source/Modules/LangModelRelated/OldFileReferences/ParselessLM.cpp b/Source/Modules/LangModelRelated/OldFileReferences/ParselessLM.cpp deleted file mode 100644 index 4f40bb8c..00000000 --- a/Source/Modules/LangModelRelated/OldFileReferences/ParselessLM.cpp +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). -// All possible vChewing-specific modifications are of: -// (c) 2021 and onwards The vChewing Project (MIT-NTL License). -/* -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: - -1. The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -2. 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 above. - -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. -*/ - -#include "ParselessLM.h" - -#include -#include -#include -#include - -#include - -vChewing::ParselessLM::~ParselessLM() -{ - close(); -} - -bool vChewing::ParselessLM::isLoaded() -{ - if (data_) - { - return true; - } - return false; -} - -bool vChewing::ParselessLM::open(const std::string_view &path) -{ - if (data_) - { - return false; - } - - fd_ = ::open(path.data(), O_RDONLY); - if (fd_ == -1) - { - return false; - } - - struct stat sb; - if (fstat(fd_, &sb) == -1) - { - ::close(fd_); - fd_ = -1; - return false; - } - - length_ = static_cast(sb.st_size); - - data_ = mmap(NULL, length_, PROT_READ, MAP_SHARED, fd_, 0); - if (data_ == nullptr) - { - ::close(fd_); - fd_ = -1; - length_ = 0; - return false; - } - - db_ = std::unique_ptr(new ParselessPhraseDB(static_cast(data_), length_)); - return true; -} - -void vChewing::ParselessLM::close() -{ - if (data_ != nullptr) - { - munmap(data_, length_); - ::close(fd_); - fd_ = -1; - length_ = 0; - data_ = nullptr; - } -} - -const std::vector vChewing::ParselessLM::bigramsForKeys(const std::string &preceedingKey, - const std::string &key) -{ - return std::vector(); -} - -const std::vector vChewing::ParselessLM::unigramsForKey(const std::string &key) -{ - if (db_ == nullptr) - { - return std::vector(); - } - - std::vector results; - for (const auto &row : db_->findRows(key + " ")) - { - Gramambular::Unigram unigram; - - // Move ahead until we encounter the first space. This is the key. - auto it = row.begin(); - while (it != row.end() && *it != ' ') - { - ++it; - } - - unigram.keyValue.key = std::string(row.begin(), it); - - // Read past the space. - if (it != row.end()) - { - ++it; - } - - if (it != row.end()) - { - // Now it is the start of the value portion. - auto value_begin = it; - - // Move ahead until we encounter the second space. This is the - // value. - while (it != row.end() && *it != ' ') - { - ++it; - } - unigram.keyValue.value = std::string(value_begin, it); - } - - // Read past the space. The remainder, if it exists, is the score. - if (it != row.end()) - { - ++it; - } - - if (it != row.end()) - { - unigram.score = std::stod(std::string(it, row.end())); - } - results.push_back(unigram); - } - return results; -} - -bool vChewing::ParselessLM::hasUnigramsForKey(const std::string &key) -{ - if (db_ == nullptr) - { - return false; - } - - return db_->findFirstMatchingLine(key + " ") != nullptr; -} diff --git a/Source/Modules/LangModelRelated/OldFileReferences/ParselessLM.h b/Source/Modules/LangModelRelated/OldFileReferences/ParselessLM.h deleted file mode 100644 index 698bcecc..00000000 --- a/Source/Modules/LangModelRelated/OldFileReferences/ParselessLM.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). -// All possible vChewing-specific modifications are of: -// (c) 2021 and onwards The vChewing Project (MIT-NTL License). -/* -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: - -1. The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -2. 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 above. - -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. -*/ - -#ifndef SOURCE_ENGINE_PARSELESSLM_H_ -#define SOURCE_ENGINE_PARSELESSLM_H_ - -#include -#include -#include - -#include "LanguageModel.h" -#include "ParselessPhraseDB.h" - -namespace vChewing -{ - -class ParselessLM : public Gramambular::LanguageModel -{ - public: - ~ParselessLM() override; - - bool isLoaded(); - bool open(const std::string_view &path); - void close(); - - const std::vector bigramsForKeys(const std::string &preceedingKey, - const std::string &key) override; - const std::vector unigramsForKey(const std::string &key) override; - bool hasUnigramsForKey(const std::string &key) override; - - private: - int fd_ = -1; - void *data_ = nullptr; - size_t length_ = 0; - std::unique_ptr db_; -}; - -}; // namespace vChewing - -#endif // SOURCE_ENGINE_PARSELESSLM_H_ diff --git a/Source/Modules/LangModelRelated/OldFileReferences/ParselessPhraseDB.cpp b/Source/Modules/LangModelRelated/OldFileReferences/ParselessPhraseDB.cpp deleted file mode 100644 index a0097e69..00000000 --- a/Source/Modules/LangModelRelated/OldFileReferences/ParselessPhraseDB.cpp +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). -// All possible vChewing-specific modifications are of: -// (c) 2021 and onwards The vChewing Project (MIT-NTL License). -/* -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: - -1. The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -2. 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 above. - -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. -*/ - -#include "ParselessPhraseDB.h" - -#include -#include - -namespace vChewing -{ - -ParselessPhraseDB::ParselessPhraseDB(const char *buf, size_t length) : begin_(buf), end_(buf + length) -{ -} - -std::vector ParselessPhraseDB::findRows(const std::string_view &key) -{ - std::vector rows; - - const char *ptr = findFirstMatchingLine(key); - if (ptr == nullptr) - { - return rows; - } - - while (ptr + key.length() <= end_ && memcmp(ptr, key.data(), key.length()) == 0) - { - const char *eol = ptr; - - while (eol != end_ && *eol != '\n') - { - ++eol; - } - - rows.emplace_back(ptr, eol - ptr); - if (eol == end_) - { - break; - } - - ptr = ++eol; - } - - return rows; -} - -// Implements a binary search that returns the pointer to the first matching -// row. In its core it's just a standard binary search, but we use backtracking -// to locate the line start. We also check the previous line to see if the -// current line is actually the first matching line: if the previous line is -// less to the key and the current line starts exactly with the key, then -// the current line is the first matching line. -const char *ParselessPhraseDB::findFirstMatchingLine(const std::string_view &key) -{ - if (key.empty()) - { - return begin_; - } - - const char *top = begin_; - const char *bottom = end_; - - while (top < bottom) - { - const char *mid = top + (bottom - top) / 2; - const char *ptr = mid; - - if (ptr != begin_) - { - --ptr; - } - - while (ptr != begin_ && *ptr != '\n') - { - --ptr; - } - - const char *prev = nullptr; - if (*ptr == '\n') - { - prev = ptr; - ++ptr; - } - - // ptr is now in the "current" line we're interested in. - if (ptr + key.length() > end_) - { - // not enough data to compare at this point, bail. - break; - } - - int current_cmp = memcmp(ptr, key.data(), key.length()); - - if (current_cmp > 0) - { - bottom = mid - 1; - continue; - } - - if (current_cmp < 0) - { - top = mid + 1; - continue; - } - - if (!prev) - { - return ptr; - } - - // Move the prev so that it reaches the previous line. - if (prev != begin_) - { - --prev; - } - while (prev != begin_ && *prev != '\n') - { - --prev; - } - if (*prev == '\n') - { - ++prev; - } - - int prev_cmp = memcmp(prev, key.data(), key.length()); - - // This is the first occurrence. - if (prev_cmp < 0 && current_cmp == 0) - { - return ptr; - } - - // This is not, which means ptr is "larger" than the keyData. - bottom = mid - 1; - } - - return nullptr; -} - -}; // namespace vChewing diff --git a/Source/Modules/LangModelRelated/OldFileReferences/ParselessPhraseDB.h b/Source/Modules/LangModelRelated/OldFileReferences/ParselessPhraseDB.h deleted file mode 100644 index 3ac28768..00000000 --- a/Source/Modules/LangModelRelated/OldFileReferences/ParselessPhraseDB.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). -// All possible vChewing-specific modifications are of: -// (c) 2021 and onwards The vChewing Project (MIT-NTL License). -/* -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: - -1. The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -2. 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 above. - -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. -*/ - -#ifndef SOURCE_ENGINE_PARSELESSPHRASEDB_H_ -#define SOURCE_ENGINE_PARSELESSPHRASEDB_H_ - -#include -#include -#include - -namespace vChewing -{ - -// Defines phrase database that consists of (key, value, score) rows that are -// pre-sorted by the byte value of the keys. It is way faster than FastLM -// because it does not need to parse anything. Instead, it relies on the fact -// that the database is already sorted, and binary search is used to find the -// rows. -class ParselessPhraseDB -{ - public: - ParselessPhraseDB(const char *buf, size_t length); - - // Find the rows that match the key. Note that prefix match is used. If you - // need exact match, the key will need to have a delimiter (usually a space) - // at the end. - std::vector findRows(const std::string_view &key); - - const char *findFirstMatchingLine(const std::string_view &key); - - private: - const char *begin_; - const char *end_; -}; - -}; // namespace vChewing - -#endif // SOURCE_ENGINE_PARSELESSPHRASEDB_H_ diff --git a/Source/Modules/LanguageParsers/Megrez/1_Walker.swift b/Source/Modules/LanguageParsers/Megrez/1_Walker.swift index 429d78b5..bf98aaea 100644 --- a/Source/Modules/LanguageParsers/Megrez/1_Walker.swift +++ b/Source/Modules/LanguageParsers/Megrez/1_Walker.swift @@ -31,9 +31,12 @@ extension Megrez { mutGrid = grid } - public func reverseWalk(at location: Int, score accumulatedScore: Double = 0.0, nodesLimit: Int = 0) - -> [NodeAnchor] - { + public func reverseWalk( + at location: Int, + score accumulatedScore: Double = 0.0, + nodesLimit: Int = 0, + balanced: Bool = false + ) -> [NodeAnchor] { if location == 0 || location > mutGrid.width() { return [] as [NodeAnchor] } @@ -41,8 +44,10 @@ extension Megrez { var paths: [[NodeAnchor]] = [] var nodes: [NodeAnchor] = mutGrid.nodesEndingAt(location: location) - nodes.sort { - $0.balancedScore > $1.balancedScore // 排序規則已經在 NodeAnchor 內定義了。 + if balanced { + nodes.sort { + $0.balancedScore > $1.balancedScore // 排序規則已經在 NodeAnchor 內定義了。 + } } // 只檢查前 X 個 NodeAnchor 是否有 node。 @@ -58,10 +63,13 @@ extension Megrez { continue } + n.accumulatedScore = accumulatedScore + nNode.score() // 利用 Spanning Length 來決定權重。 // 這樣一來,例:「再見」比「在」與「見」的權重更高。 - let weightedScore: Double = (Double(n.spanningLength) - 1) * 2 - n.accumulatedScore = accumulatedScore + nNode.score() + weightedScore + if balanced { + let weightedScore: Double = (Double(n.spanningLength) - 1) * 2 + n.accumulatedScore += weightedScore + } var path: [NodeAnchor] = reverseWalk( at: location - n.spanningLength, @@ -72,7 +80,7 @@ extension Megrez { paths.append(path) // 始終使用固定的候選字 - if nNode.score() >= 0 { + if balanced, nNode.score() >= 0 { break } } diff --git a/Source/UI/PrefUI/suiPrefPaneKeyboard.swift b/Source/UI/PrefUI/suiPrefPaneKeyboard.swift index af59371f..35809ec6 100644 --- a/Source/UI/PrefUI/suiPrefPaneKeyboard.swift +++ b/Source/UI/PrefUI/suiPrefPaneKeyboard.swift @@ -53,7 +53,7 @@ struct suiPrefPaneKeyboard: View { Text(LocalizedStringKey("Hsu")).tag(2) Text(LocalizedStringKey("MiTAC")).tag(5) Text(LocalizedStringKey("Fake Seigyou")).tag(6) - Text(LocalizedStringKey("Hanyu Pinyin with Numeral Intonation")).tag(10) + // Text(LocalizedStringKey("Hanyu Pinyin with Numeral Intonation")).tag(10) }.onChange(of: selMandarinParser) { value in mgrPrefs.mandarinParser = value } diff --git a/Source/WindowNIBs/Base.lproj/frmAboutWindow.xib b/Source/WindowNIBs/Base.lproj/frmAboutWindow.xib index 68677eea..78825465 100644 --- a/Source/WindowNIBs/Base.lproj/frmAboutWindow.xib +++ b/Source/WindowNIBs/Base.lproj/frmAboutWindow.xib @@ -1,6 +1,7 @@ + @@ -53,12 +54,9 @@ - - + + - McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al. -vChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc. -vChewing Phrase Database Maintained by Shiki Suen. @@ -67,7 +65,7 @@ vChewing Phrase Database Maintained by Shiki Suen. - + @@ -121,17 +119,17 @@ DQ - + - - + + - + - + @@ -151,7 +149,7 @@ DQ - + diff --git a/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib b/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib index 54548cc0..c0a57c04 100644 --- a/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib +++ b/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib @@ -759,7 +759,6 @@ - diff --git a/Source/WindowNIBs/en.lproj/frmAboutWindow.strings b/Source/WindowNIBs/en.lproj/frmAboutWindow.strings index 1d0d5e01..a05b24a3 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, 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."; +/* Class = "NSTextFieldCell"; title = "Tekkon Syllable Composition Engine by Shiki Suen.\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" = "Tekkon Syllable Composition Engine by Shiki Suen.\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 1ff90c89..4ae9cb84 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, 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 で再開発したものである)。"; +/* Class = "NSTextFieldCell"; title = "Tekkon Syllable Composition Engine by Shiki Suen.\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" = "鉄恨ボポモフォエンジン開発:Shiki Suen。\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 d9bf31a9..cc8903c3 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, 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 重写而得。"; +/* Class = "NSTextFieldCell"; title = "Tekkon Syllable Composition Engine by Shiki Suen.\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" = "铁恨注音并击输入处理引擎研发:Shiki Suen。\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 e4bd24be..58f38111 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, 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 重寫而得。"; +/* Class = "NSTextFieldCell"; title = "Tekkon Syllable Composition Engine by Shiki Suen.\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" = "鐵恨注音並擊輸入處理引擎研發:Shiki Suen。\n輸入法狀態管理引擎研發:Zonble Yang。\n威注音 macOS 程式研發:Shiki Suen, Isaac Xen, Hiraku Wang, 等。\n威注音詞庫維護:Shiki Suen。\n天權星語彙引擎:Shiki Suen,用 Swift 將 Lukhnos 的 C++ Gramambular 重寫而得。"; diff --git a/Update-Info.plist b/Update-Info.plist index 3b5600ae..8e23f3f1 100644 --- a/Update-Info.plist +++ b/Update-Info.plist @@ -3,9 +3,9 @@ CFBundleShortVersionString - 1.5.6 + 1.5.7 CFBundleVersion - 1956 + 1957 UpdateInfoEndpoint https://gitee.com/vchewing/vChewing-macOS/raw/main/Update-Info.plist UpdateInfoSite diff --git a/vChewing.pkgproj b/vChewing.pkgproj index 77218f6c..5b1183d0 100644 --- a/vChewing.pkgproj +++ b/vChewing.pkgproj @@ -726,7 +726,7 @@ USE_HFS+_COMPRESSION VERSION - 1.5.6 + 1.5.7 TYPE 0 diff --git a/vChewing.xcodeproj/project.pbxproj b/vChewing.xcodeproj/project.pbxproj index f8bb64b8..2dbab490 100644 --- a/vChewing.xcodeproj/project.pbxproj +++ b/vChewing.xcodeproj/project.pbxproj @@ -25,7 +25,6 @@ 5B38F5A2281E2E49007D5F5D /* 0_Megrez.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F1615FC0EB100ABF4B3 /* 0_Megrez.swift */; }; 5B38F5A3281E2E49007D5F5D /* 3_Span.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F1C15FC0EB100ABF4B3 /* 3_Span.swift */; }; 5B38F5A4281E2E49007D5F5D /* 5_LanguageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F1915FC0EB100ABF4B3 /* 5_LanguageModel.swift */; }; - 5B407153281F94E6009C24CB /* Composer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B407152281F94E6009C24CB /* Composer.mm */; }; 5B40730C281672610023DFFF /* lmAssociates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B407309281672610023DFFF /* lmAssociates.swift */; }; 5B40730D281672610023DFFF /* lmReplacements.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B40730A281672610023DFFF /* lmReplacements.swift */; }; 5B5E535227EF261400C6AA1E /* IME.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B5E535127EF261400C6AA1E /* IME.swift */; }; @@ -70,6 +69,7 @@ 5BA9FD4927FEF3C9002DE248 /* Section.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA9FD3C27FEF3C8002DE248 /* Section.swift */; }; 5BA9FD4A27FEF3C9002DE248 /* PreferencesTabViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA9FD3D27FEF3C8002DE248 /* PreferencesTabViewController.swift */; }; 5BA9FD8B28006B41002DE248 /* VDKComboBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA9FD8A28006B41002DE248 /* VDKComboBox.swift */; }; + 5BAA8FBE282CAF380066C406 /* SyllableComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BAA8FBD282CAF380066C406 /* SyllableComposer.swift */; }; 5BAD0CD527D701F6003D127F /* vChewingKeyLayout.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 5B30F11227BA568800484E24 /* vChewingKeyLayout.bundle */; }; 5BAEFAD028012565001F42C9 /* mgrLangModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BAEFACF28012565001F42C9 /* mgrLangModel.swift */; }; 5BB802DA27FABA8300CF1C19 /* ctlInputMethod_Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BB802D927FABA8300CF1C19 /* ctlInputMethod_Menu.swift */; }; @@ -98,7 +98,6 @@ 5BE78BD927B3775B005EA1BE /* ctlAboutWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BE78BD827B37750005EA1BE /* ctlAboutWindow.swift */; }; 5BE78BDD27B3776D005EA1BE /* frmAboutWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BE78BDA27B37764005EA1BE /* frmAboutWindow.xib */; }; 5BF8423127BAA942008E7E4C /* vChewingKanjiConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF8423027BAA942008E7E4C /* vChewingKanjiConverter.swift */; }; - 6A0D4F4515FC0EB100ABF4B3 /* Mandarin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F2015FC0EB100ABF4B3 /* Mandarin.cpp */; }; 6A187E2616004C5900466B2E /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6A187E2816004C5900466B2E /* MainMenu.xib */; }; 6A225A1F23679F2600F685C6 /* NotarizedArchives in Resources */ = {isa = PBXBuildFile; fileRef = 6A225A1E23679F2600F685C6 /* NotarizedArchives */; }; 6A2E40F6253A69DA00D1AE1D /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6A2E40F5253A69DA00D1AE1D /* Images.xcassets */; }; @@ -199,8 +198,6 @@ 5B2DB17127AF8771006D874E /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; name = Makefile; path = Data/Makefile; sourceTree = ""; }; 5B30F11227BA568800484E24 /* vChewingKeyLayout.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = vChewingKeyLayout.bundle; sourceTree = ""; }; 5B3133BE280B229700A4A505 /* KeyHandler_States.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = KeyHandler_States.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; - 5B407151281F94E6009C24CB /* Composer.hh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Composer.hh; sourceTree = ""; }; - 5B407152281F94E6009C24CB /* Composer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = Composer.mm; sourceTree = ""; }; 5B407309281672610023DFFF /* lmAssociates.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; lineEnding = 0; path = lmAssociates.swift; sourceTree = ""; usesTabs = 0; }; 5B40730A281672610023DFFF /* lmReplacements.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; lineEnding = 0; path = lmReplacements.swift; sourceTree = ""; usesTabs = 0; }; 5B5E535127EF261400C6AA1E /* IME.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = IME.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; @@ -246,6 +243,7 @@ 5BA9FD3C27FEF3C8002DE248 /* Section.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = Section.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; 5BA9FD3D27FEF3C8002DE248 /* PreferencesTabViewController.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = PreferencesTabViewController.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; 5BA9FD8A28006B41002DE248 /* VDKComboBox.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = VDKComboBox.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; + 5BAA8FBD282CAF380066C406 /* SyllableComposer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SyllableComposer.swift; sourceTree = ""; }; 5BAEFACF28012565001F42C9 /* mgrLangModel.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = mgrLangModel.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; 5BB802D927FABA8300CF1C19 /* ctlInputMethod_Menu.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = ctlInputMethod_Menu.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; 5BBBB75D27AED54C0023B93A /* Beep.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = Beep.m4a; sourceTree = ""; }; @@ -303,8 +301,6 @@ 6A0D4F1C15FC0EB100ABF4B3 /* 3_Span.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = 3_Span.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; 6A0D4F1D15FC0EB100ABF4B3 /* 6_Unigram.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = 6_Unigram.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; 6A0D4F1E15FC0EB100ABF4B3 /* 1_Walker.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = 1_Walker.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; - 6A0D4F2015FC0EB100ABF4B3 /* Mandarin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = Mandarin.cpp; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; - 6A0D4F2115FC0EB100ABF4B3 /* Mandarin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = Mandarin.h; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; 6A15B32421A51F2300B92CD3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 6A15B32521A51F2300B92CD3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 6A225A1E23679F2600F685C6 /* NotarizedArchives */ = {isa = PBXFileReference; lastKnownFileType = folder; path = NotarizedArchives; sourceTree = ""; }; @@ -315,10 +311,6 @@ 6ACA41EF15FC1D9000935EF6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; 6ACA41F215FC1D9000935EF6 /* Installer-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "Installer-Info.plist"; path = "Installer/Installer-Info.plist"; sourceTree = SOURCE_ROOT; }; 6ACA41F315FC1D9000935EF6 /* Installer-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "Installer-Prefix.pch"; path = "Installer/Installer-Prefix.pch"; sourceTree = SOURCE_ROOT; }; - 6ACC3D402793701600F1B140 /* ParselessPhraseDB.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = ParselessPhraseDB.cpp; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; - 6ACC3D412793701600F1B140 /* ParselessPhraseDB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = ParselessPhraseDB.h; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; - 6ACC3D422793701600F1B140 /* ParselessLM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = ParselessLM.cpp; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; - 6ACC3D432793701600F1B140 /* ParselessLM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = ParselessLM.h; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; D427A9BF25ED28CC005D43E0 /* vChewing-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "vChewing-Bridging-Header.h"; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; D427F76B278CA1BA004A2160 /* AppDelegate.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = AppDelegate.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; D456576D279E4F7B00DF6BC9 /* InputHandler.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = InputHandler.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; @@ -403,24 +395,12 @@ children = ( 5B949BD72816DC4400D87B5D /* LineReader */, 5B707CE627D9F43E0099EF99 /* OpenCCBridge */, - 5B62A30227AE733500A19448 /* OVMandarin */, 5BA9FCEA27FED652002DE248 /* SindreSorhus */, 5BA9FD8C28006BA7002DE248 /* VDKComboBox */, ); path = 3rdParty; sourceTree = ""; }; - 5B62A30227AE733500A19448 /* OVMandarin */ = { - isa = PBXGroup; - children = ( - 6A0D4F2015FC0EB100ABF4B3 /* Mandarin.cpp */, - 6A0D4F2115FC0EB100ABF4B3 /* Mandarin.h */, - 5B407151281F94E6009C24CB /* Composer.hh */, - 5B407152281F94E6009C24CB /* Composer.mm */, - ); - path = OVMandarin; - sourceTree = ""; - }; 5B62A31E27AE74E400A19448 /* SFX */ = { isa = PBXGroup; children = ( @@ -443,6 +423,7 @@ 5B61B0C9280BEFD4002E3CFA /* KeyHandler_Misc.swift */, 5B3133BE280B229700A4A505 /* KeyHandler_States.swift */, 5B62A33727AE79CD00A19448 /* NSStringUtils.swift */, + 5BAA8FBD282CAF380066C406 /* SyllableComposer.swift */, 5BF8423027BAA942008E7E4C /* vChewingKanjiConverter.swift */, ); path = ControllerModules; @@ -501,10 +482,6 @@ 5B62A32527AE758000A19448 /* OldFileReferences */ = { isa = PBXGroup; children = ( - 6ACC3D422793701600F1B140 /* ParselessLM.cpp */, - 6ACC3D432793701600F1B140 /* ParselessLM.h */, - 6ACC3D402793701600F1B140 /* ParselessPhraseDB.cpp */, - 6ACC3D412793701600F1B140 /* ParselessPhraseDB.h */, D47F7DD2278C1263002F9DD7 /* UserOverrideModel.cpp */, D47F7DD1278C1263002F9DD7 /* UserOverrideModel.h */, ); @@ -1111,7 +1088,6 @@ 5B62A33827AE79CD00A19448 /* NSStringUtils.swift in Sources */, 5BA9FD0F27FEDB6B002DE248 /* suiPrefPaneGeneral.swift in Sources */, 5BA9FD4927FEF3C9002DE248 /* Section.swift in Sources */, - 5B407153281F94E6009C24CB /* Composer.mm in Sources */, 5BA9FD3E27FEF3C8002DE248 /* Utilities.swift in Sources */, 5BA9FD1127FEDB6B002DE248 /* ctlPrefUI.swift in Sources */, 5B38F59C281E2E49007D5F5D /* 2_Grid.swift in Sources */, @@ -1120,12 +1096,12 @@ 5B62A33227AE792F00A19448 /* InputSourceHelper.swift in Sources */, 5B5E535227EF261400C6AA1E /* IME.swift in Sources */, 5B62A34927AE7CD900A19448 /* TooltipController.swift in Sources */, - 6A0D4F4515FC0EB100ABF4B3 /* Mandarin.cpp in Sources */, 5B61B0CA280BEFD4002E3CFA /* KeyHandler_Misc.swift in Sources */, 5B38F59A281E2E49007D5F5D /* 6_Unigram.swift in Sources */, 5B38F5A0281E2E49007D5F5D /* 1_Walker.swift in Sources */, 5B62A34827AE7CD900A19448 /* ctlCandidateVertical.swift in Sources */, 5BA9FD4027FEF3C8002DE248 /* Localization.swift in Sources */, + 5BAA8FBE282CAF380066C406 /* SyllableComposer.swift in Sources */, 5BA9FD1327FEDB6B002DE248 /* suiPrefPaneDictionary.swift in Sources */, 5BBBB77A27AEDC690023B93A /* clsSFX.swift in Sources */, 5BA9FD4727FEF3C9002DE248 /* PreferencesStyleController.swift in Sources */, @@ -1332,7 +1308,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1956; + CURRENT_PROJECT_VERSION = 1957; DEBUG_INFORMATION_FORMAT = dwarf; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; @@ -1355,7 +1331,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.11.5; - MARKETING_VERSION = 1.5.6; + MARKETING_VERSION = 1.5.7; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor; @@ -1388,7 +1364,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1956; + CURRENT_PROJECT_VERSION = 1957; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -1407,7 +1383,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.11.5; - MARKETING_VERSION = 1.5.6; + MARKETING_VERSION = 1.5.7; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor; @@ -1522,7 +1498,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1956; + CURRENT_PROJECT_VERSION = 1957; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = ""; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -1557,7 +1533,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.11.5; - MARKETING_VERSION = 1.5.6; + MARKETING_VERSION = 1.5.7; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1589,7 +1565,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1956; + CURRENT_PROJECT_VERSION = 1957; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = ""; @@ -1619,7 +1595,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.11.5; - MARKETING_VERSION = 1.5.6; + MARKETING_VERSION = 1.5.7; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1702,7 +1678,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1956; + CURRENT_PROJECT_VERSION = 1957; DEVELOPMENT_TEAM = ""; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; @@ -1727,7 +1703,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.11.5; - MARKETING_VERSION = 1.5.6; + MARKETING_VERSION = 1.5.7; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1754,7 +1730,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1956; + CURRENT_PROJECT_VERSION = 1957; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = ""; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -1774,7 +1750,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.11.5; - MARKETING_VERSION = 1.5.6; + MARKETING_VERSION = 1.5.7; PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "";