Pre Merge pull request !28 from ShikiSuen/upd/1.5.5

This commit is contained in:
ShikiSuen 2022-05-09 14:51:17 +00:00 committed by Gitee
commit 2e6cc99a24
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
39 changed files with 502 additions and 436 deletions

16
AUTHORS
View File

@ -1,11 +1,15 @@
$ Main contributors and volunteers of this repository (vChewing for macOS):
Shiki Suen // Main developer of vChewing for macOS.
Hiraku Wang // Technical assistant in Cocoa.
- Shiki Suen // Main developer of vChewing for macOS.
- Hiraku Wang // Technical reinforcement in Cocoa during the Object-Cpp dev period of this project.
- Isaac Xen // Technical reinforcement in Swift: SFX Module and StringView Ranges Extension.
$ Contributors and volunteeres of the upstream repo, having no responsibility in discussing anything in the current repo:
Mengjuei Hsieh // McBopomofo for macOS 1.x main developer and architect.
Zonble Yang // McBopomofo for macOS 2.x architect.
Lukhnos D Liu // Mandarin and Gramambular engine developer.
- Mengjuei Hsieh // McBopomofo for macOS 1.x main developer and architect.
- Zonble Yang // McBopomofo for macOS 2.x architect, especially state-based IME behavior management.
- Lukhnos D Liu // Developer of the Mandarin syllable input processor.
$ Special thanks to:
- All supporters from Cocoaheads Taipei and Mobile01 community.

View File

@ -356,7 +356,7 @@ func weightAndSort(_ arrStructUncalculated: [Entry], isCHS: Bool) -> [Entry] {
weight = -13
case 0: //
weight = log10(
fscale ** (Float(entry.valPhrase.count) / 3.0 - 1.0) * 0.5 / norm)
fscale ** (Float(entry.valPhrase.count) / 3.0 - 1.0) * 0.25 / norm)
default:
weight = log10(
fscale ** (Float(entry.valPhrase.count) / 3.0 - 1.0)

View File

@ -198,7 +198,7 @@
<textFieldCell key="cell" selectable="YES" id="VW8-s5-Wpn">
<font key="font" metaFont="cellTitle"/>
<string key="title">McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.
vChewing macOS Development: Shiki Suen, Hiraku Wang, etc.vChewing Phrase Database Maintained by Shiki Suen.</string>
vChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.vChewing Phrase Database Maintained by Shiki Suen.</string>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>

View File

@ -56,8 +56,8 @@
/* Class = "NSTextFieldCell"; title = "Derived from OpenVanilla McBopopmofo Project."; ObjectID = "QYf-Nf-hoi"; */
"QYf-Nf-hoi.title" = "Derived from OpenVanilla McBopopmofo Project.";
/* Class = "NSTextFieldCell"; title = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; ObjectID = "VW8-s5-Wpn"; */
"VW8-s5-Wpn.title" = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine.";
/* Class = "NSTextFieldCell"; title = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; ObjectID = "VW8-s5-Wpn"; */
"VW8-s5-Wpn.title" = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine.";
/* Class = "NSTextFieldCell"; title = "Placeholder for showing copyright information."; ObjectID = "eo3-TK-0rB"; */
// "eo3-TK-0rB.title" = "Placeholder for showing copyright information.";

View File

@ -56,8 +56,8 @@
/* Class = "NSTextFieldCell"; title = "Derived from OpenVanilla McBopopmofo Project."; ObjectID = "QYf-Nf-hoi"; */
"QYf-Nf-hoi.title" = "OpenVanilla 小麦注音プロジェクトから派生。";
/* Class = "NSTextFieldCell"; title = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; ObjectID = "VW8-s5-Wpn"; */
"VW8-s5-Wpn.title" = "ボポモフォエンジン開発Lukhnos Liu。\n入力状態管理システム開発Zonble Yang。\nmacOS 版威注音の開発Shiki Suen, Hiraku Wang, など。\n威注音語彙データの維持Shiki Suen。\nMegrez 辞書処理エンジンShiki SuenLukhnos の Gramambular C++ エンジンを Swift で再開発したものである)。";
/* Class = "NSTextFieldCell"; title = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; ObjectID = "VW8-s5-Wpn"; */
"VW8-s5-Wpn.title" = "ボポモフォエンジン開発Lukhnos Liu。\n入力状態管理システム開発Zonble Yang。\nmacOS 版威注音の開発Shiki Suen, Isaac Xen, Hiraku Wang, など。\n威注音語彙データの維持Shiki Suen。\nMegrez 辞書処理エンジンShiki SuenLukhnos の Gramambular C++ エンジンを Swift で再開発したものである)。";
/* Class = "NSTextFieldCell"; title = "Placeholder for showing copyright information."; ObjectID = "eo3-TK-0rB"; */
"eo3-TK-0rB.title" = "Placeholder for showing copyright information.";

View File

@ -56,9 +56,9 @@
/* Class = "NSTextFieldCell"; title = "Derived from OpenVanilla McBopopmofo Project."; ObjectID = "QYf-Nf-hoi"; */
"QYf-Nf-hoi.title" = "该专案由 OpenVanilla 小麦注音专案衍生而来。";
/* Class = "NSTextFieldCell"; title = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.
/* Class = "NSTextFieldCell"; title = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.
vChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "VW8-s5-Wpn"; */
"VW8-s5-Wpn.title" = "注音拼音输入处理引擎研发Lukhnos Liu。\n输入法状态管理引擎研发Zonble Yang。\n威注音 macOS 程式研发Shiki Suen, Hiraku Wang, 等。\n威注音词库维护Shiki Suen。\n天权星语汇引擎Shiki Suen用 Swift 将 Lukhnos 的 C++ Gramambular 重写而得。";
"VW8-s5-Wpn.title" = "注音拼音输入处理引擎研发Lukhnos Liu。\n输入法状态管理引擎研发Zonble Yang。\n威注音 macOS 程式研发Shiki Suen, Isaac Xen, Hiraku Wang, 等。\n威注音词库维护Shiki Suen。\n天权星语汇引擎Shiki Suen用 Swift 将 Lukhnos 的 C++ Gramambular 重写而得。";
/* Class = "NSTextFieldCell"; title = "Placeholder for showing copyright information."; ObjectID = "eo3-TK-0rB"; */
// "eo3-TK-0rB.title" = "Placeholder for showing copyright information.";

View File

@ -56,9 +56,9 @@
/* Class = "NSTextFieldCell"; title = "Derived from OpenVanilla McBopopmofo Project."; ObjectID = "QYf-Nf-hoi"; */
"QYf-Nf-hoi.title" = "該專案由 OpenVanilla 小麥注音專案衍生而來。";
/* Class = "NSTextFieldCell"; title = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.
/* Class = "NSTextFieldCell"; title = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.
vChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "VW8-s5-Wpn"; */
"VW8-s5-Wpn.title" = "注音拼音輸入處理引擎研發Lukhnos Liu。\n輸入法狀態管理引擎研發Zonble Yang。\n威注音 macOS 程式研發Shiki Suen, Hiraku Wang, 等。\n威注音詞庫維護Shiki Suen。\n天權星語彙引擎Shiki Suen用 Swift 將 Lukhnos 的 C++ Gramambular 重寫而得。";
"VW8-s5-Wpn.title" = "注音拼音輸入處理引擎研發Lukhnos Liu。\n輸入法狀態管理引擎研發Zonble Yang。\n威注音 macOS 程式研發Shiki Suen, Isaac Xen, Hiraku Wang, 等。\n威注音詞庫維護Shiki Suen。\n天權星語彙引擎Shiki Suen用 Swift 將 Lukhnos 的 C++ Gramambular 重寫而得。";
/* Class = "NSTextFieldCell"; title = "Placeholder for showing copyright information."; ObjectID = "eo3-TK-0rB"; */
// "eo3-TK-0rB.title" = "Placeholder for showing copyright information.";

View File

@ -5,7 +5,7 @@ vChewing macOS: MIT-NTL License 麻理(去商标)授权合约
© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project.
注音拼音输入处理引擎研发Lukhnos Liu。
输入法状态管理引擎研发Zonble Yang。
威注音 macOS 程式研发Shiki Suen, Hiraku Wang, 等。
威注音 macOS 程式研发Shiki Suen, Isaac Xen, Hiraku Wang, 等。
威注音词库维护Shiki Suen。
天权星语汇引擎Shiki Suen用 Swift 将 Lukhnos 的 C++ Gramambular 重写而得。

View File

@ -5,7 +5,7 @@ vChewing macOS: MIT-NTL License 麻理(去商標)授權合約
© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project.
注音拼音輸入處理引擎研發Lukhnos Liu。
輸入法狀態管理引擎研發Zonble Yang。
威注音 macOS 程式研發Shiki Suen, Hiraku Wang, 等。
威注音 macOS 程式研發Shiki Suen, Isaac Xen, Hiraku Wang, 等。
威注音詞庫維護Shiki Suen。
天權星語彙引擎Shiki Suen用 Swift 將 Lukhnos 的 C++ Gramambular 重寫而得。

View File

@ -4,7 +4,7 @@ vChewing macOS: MIT商標不許可ライセンス (MIT-NTL License)
ボポモフォエンジン開発Lukhnos Liu。
入力状態管理システム開発Zonble Yang。
macOS 版威注音の開発Shiki Suen, Hiraku Wang, など。
macOS 版威注音の開発Shiki Suen, Isaac Xen, Hiraku Wang, など。
威注音語彙データの維持Shiki Suen。
Megrez 辞書処理エンジンShiki SuenLukhnos の Gramambular C++ エンジンを Swift で再開発したものである)。

View File

@ -5,7 +5,7 @@ vChewing macOS: MIT-NTL License
© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project.
Mandarin Syllable Composer Engine by Lukhnos Liu.
Input State Management Architecture by Zonble Yang.
vChewing macOS Development: Shiki Suen, Hiraku Wang, etc.
vChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.
vChewing Phrase Database Maintained by Shiki Suen.
Megrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine.

View File

@ -33,7 +33,8 @@ NS_ASSUME_NONNULL_BEGIN
+ (BOOL)isBufferEmpty;
+ (void)clearBuffer;
+ (void)combineReadingKey:(UniChar)charCode;
+ (BOOL)checkWhetherToneMarkerConfirms;
+ (BOOL)hasToneMarker;
+ (BOOL)hasToneMarkerOnly;
+ (NSString *)getSyllableComposition;
+ (void)doBackSpaceToBuffer;
+ (NSString *)getComposition;

View File

@ -52,11 +52,16 @@ static Mandarin::BopomofoReadingBuffer *PhoneticBuffer;
PhoneticBuffer->combineKey((char)charCode);
}
+ (BOOL)checkWhetherToneMarkerConfirms
+ (BOOL)hasToneMarker
{
return PhoneticBuffer->hasToneMarker();
}
+ (BOOL)hasToneMarkerOnly
{
return PhoneticBuffer->hasToneMarkerOnly();
}
+ (NSString *)getSyllableComposition
{
return [NSString stringWithUTF8String:PhoneticBuffer->syllable().composedString().c_str()];

View File

@ -569,6 +569,12 @@ extern "C" class BopomofoReadingBuffer
return syllable_.hasToneMarker();
}
bool hasToneMarkerOnly() const
{
return syllable_.hasToneMarker() &&
!(syllable_.hasConsonant() || syllable_.hasMiddleVowel() || syllable_.hasVowel());
}
protected:
const BopomofoKeyboardLayout *layout_;
BPMF syllable_;

@ -1 +1 @@
Subproject commit 4065cb727373ab12a3401eb3526e4a6208671e59
Subproject commit 4f922087d6c20964a59f7838e05ae82beef493d1

View File

@ -61,16 +61,16 @@ enum KeyCode: UInt16 {
case kF8 = 100
case kF9 = 101
case kF11 = 103
case kF13 = 105
case kF13 = 105 // PrtSc
case kF16 = 106
case kF14 = 107
case kF10 = 109
case kF12 = 111
case kF15 = 113
case kHelp = 114
case kHelp = 114 // Insert
case kHome = 115
case kPageUp = 116
case kWindowDelete = 117 // Renamed from "kForwardDelete" to avoid nomenclatural confusions.
case kWindowsDelete = 117 // Renamed from "kForwardDelete" to avoid nomenclatural confusions.
case kF4 = 118
case kEnd = 119
case kF2 = 120
@ -82,6 +82,33 @@ enum KeyCode: UInt16 {
case kUpArrow = 126
}
enum KeyCodeBlackListed: UInt16 {
case kF17 = 64
case kVolumeUp = 72
case kVolumeDown = 73
case kMute = 74
case kF18 = 79
case kF19 = 80
case kF20 = 90
case kF5 = 96
case kF6 = 97
case kF7 = 98
case kF3 = 99
case kF8 = 100
case kF9 = 101
case kF11 = 103
case kF13 = 105 // PrtSc
case kF16 = 106
case kF14 = 107
case kF10 = 109
case kF12 = 111
case kF15 = 113
case kHelp = 114 // Insert
case kF4 = 118
case kF2 = 120
case kF1 = 122
}
// CharCodes: https://theasciicode.com.ar/ascii-control-characters/horizontal-tab-ascii-code-9.html
enum CharCode: UInt /* 16 */ {
case yajuusenpai = 114_514_191_191_810_893
@ -172,6 +199,26 @@ class InputHandler: NSObject {
"<\(super.description) inputText:\(String(describing: inputText)), inputTextIgnoringModifiers:\(String(describing: inputTextIgnoringModifiers)) charCode:\(charCode), keyCode:\(keyCode), flags:\(flags), cursorForwardKey:\(cursorForwardKey), cursorBackwardKey:\(cursorBackwardKey), extraChooseCandidateKey:\(extraChooseCandidateKey), extraChooseCandidateKeyReverse:\(extraChooseCandidateKeyReverse), absorbedArrowKey:\(absorbedArrowKey), verticalModeOnlyChooseCandidateKey:\(verticalModeOnlyChooseCandidateKey), emacsKey:\(emacsKey), useVerticalMode:\(useVerticalMode)>"
}
// ANSI charCode Swift KeyHandler
var isInvalidInput: Bool {
switch charCode {
case 0x20...0xFF: // ANSI charCode
return false
default:
if isReservedKey, !isKeyCodeBlacklisted {
return false
}
return true
}
}
var isKeyCodeBlacklisted: Bool {
guard let code = KeyCodeBlackListed(rawValue: keyCode) else {
return false
}
return code.rawValue != KeyCode.kNone.rawValue
}
var isShiftHold: Bool {
flags.contains([.shift])
}
@ -269,7 +316,7 @@ class InputHandler: NSObject {
}
var isDelete: Bool {
KeyCode(rawValue: keyCode) == KeyCode.kWindowDelete
KeyCode(rawValue: keyCode) == KeyCode.kWindowsDelete
}
var isCursorBackward: Bool {

View File

@ -115,12 +115,12 @@ class KeyHandler: NSObject {
// MARK: - Functions dealing with Megrez.
func walk() {
// Retrieve the most likely trellis, i.e. a Maximum Likelihood Estimation
// Retrieve the most likely grid, i.e. a Maximum Likelihood Estimation
// of the best possible Mandarin characters given the input syllables,
// using the Viterbi algorithm implemented in the Gramambular library
// using the Viterbi algorithm implemented in the Megrez library
let walker = Megrez.Walker(grid: _builder.grid())
// the reverse walk traces the trellis from the end
// the reverse walk traces the grid from the end
let walked: [Megrez.NodeAnchor] = walker.reverseWalk(at: _builder.grid().width())
// then we use ".reversed()" to reverse the nodes so that we get the forward-walked nodes

View File

@ -46,6 +46,14 @@ extension KeyHandler {
return false
}
// Megrez
if input.isInvalidInput {
IME.prtDebugIntel("550BCF7B: KeyHandler just refused an invalid input.")
errorCallback()
stateCallback(state)
return true
}
// Ignore the input if the composing buffer is empty with no reading
// and there is some function key combination.
let isFunctionKey: Bool =
@ -56,7 +64,7 @@ extension KeyHandler {
// MARK: Caps Lock processing.
// If Caps Lock is ON, temporarily disable bopomofo.
// If Caps Lock is ON, temporarily disable phonetic reading.
// Note: Alphanumerical mode processing.
if input.isBackSpace || input.isEnter || input.isAbsorbedArrowKey || input.isExtraChooseCandidateKey
|| input.isExtraChooseCandidateKeyReverse || input.isCursorForward || input.isCursorBackward
@ -135,23 +143,26 @@ extension KeyHandler {
// MARK: Handle BPMF Keys.
var composeReading = false
var keyConsumedByReading = false
let skipPhoneticHandling = input.isReservedKey || input.isControlHold || input.isOptionHold
// See if Phonetic reading is valid.
if !skipPhoneticHandling && Composer.chkKeyValidity(charCode) {
Composer.combineReadingKey(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.
composeReading = Composer.checkWhetherToneMarkerConfirms()
let composeReading = Composer.hasToneMarker()
if !composeReading {
stateCallback(buildInputtingState())
return true
}
}
var composeReading = Composer.hasToneMarker() || Composer.hasToneMarkerOnly()
// 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 "|=".
@ -159,17 +170,19 @@ extension KeyHandler {
if composeReading {
let reading = Composer.getSyllableComposition()
// See whether we have a unigram for this...
if !ifLangModelHasUnigrams(forKey: reading) {
IME.prtDebugIntel("B49C0979語彙庫內無「\(reading)」的匹配記錄。")
errorCallback()
stateCallback(buildInputtingState())
Composer.clearBuffer()
stateCallback((getBuilderLength() == 0) ? InputState.EmptyIgnoringPreviousState() : buildInputtingState())
return true
}
// ... and insert it into the lattice grid...
// ... and insert it into the grid...
insertReadingToBuilderAtCursor(reading: reading)
// ... then walk the lattice grid...
// ... then walk the grid...
let poppedText = popOverflowComposingTextAndWalk()
// ... get and tweak override model suggestion if possible...
@ -210,6 +223,16 @@ extension KeyHandler {
stateCallback(choosingCandidates)
}
}
return true // Telling the client that the key is consumed.
}
// The only possibility for this to be true is that the Phonetic reading
// already has a tone marker but the last key is *not* a tone marker key. An
// example is the sequence "6u" with the Standard layout, which produces "ˊ"
// but does not compose. Only sequences such as "ˊ", "ˊˊ", "ˊˇ", or "ˊ "
// would compose.
if keyConsumedByReading {
stateCallback(buildInputtingState())
return true
}
@ -318,7 +341,9 @@ extension KeyHandler {
if input.isEnter {
return (input.isCommandHold && input.isControlHold)
? handleCtrlCommandEnter(state: state, stateCallback: stateCallback, errorCallback: errorCallback)
? (input.isOptionHold
? handleCtrlOptionCommandEnter(state: state, stateCallback: stateCallback, errorCallback: errorCallback)
: handleCtrlCommandEnter(state: state, stateCallback: stateCallback, errorCallback: errorCallback))
: handleEnter(state: state, stateCallback: stateCallback, errorCallback: errorCallback)
}

View File

@ -268,7 +268,7 @@ extension KeyHandler {
return true
}
// MARK: - CMD+Enter
// MARK: - CMD+Enter
func handleCtrlCommandEnter(
state: InputState,
@ -292,6 +292,38 @@ extension KeyHandler {
return true
}
// MARK: - CMD+Alt+Enter Ruby
func handleCtrlOptionCommandEnter(
state: InputState,
stateCallback: @escaping (InputState) -> Void,
errorCallback _: @escaping () -> Void
) -> Bool {
if !(state is InputState.Inputting) {
return false
}
var composed = ""
for theAnchor in _walkedNodes {
if let node = theAnchor.node {
let key = node.currentKeyValue().key.replacingOccurrences(of: "-", with: " ")
let value = node.currentKeyValue().value
if key.contains("_") { //
composed += value
} else {
composed += "<ruby>\(value)<rp>(</rp><rt>\(key)</rt><rp>)</rp></ruby>"
}
}
}
clear()
stateCallback(InputState.Committing(poppedText: composed))
stateCallback(InputState.Empty())
return true
}
// MARK: - Backspace (macOS Delete)
func handleBackspace(
@ -303,7 +335,9 @@ extension KeyHandler {
return false
}
if Composer.isBufferEmpty() {
if Composer.hasToneMarkerOnly() {
Composer.clearBuffer()
} else if Composer.isBufferEmpty() {
if getBuilderCursorIndex() >= 0 {
deleteBuilderReadingInFrontOfCursor()
walk()
@ -462,7 +496,7 @@ extension KeyHandler {
if !Composer.isBufferEmpty() {
Composer.clearBuffer()
if getBuilderLength() == 0 {
stateCallback(InputState.Empty())
stateCallback(InputState.EmptyIgnoringPreviousState())
} else {
stateCallback(buildInputtingState())
}

View File

@ -51,7 +51,7 @@ public class IME: NSObject {
static func prtDebugIntel(_ strPrint: String) {
if mgrPrefs.isDebugModeEnabled {
NSLog("vChewingErrorCallback: %@", strPrint)
NSLog("vChewingDebug: %@", strPrint)
}
}
@ -64,14 +64,12 @@ public class IME: NSObject {
// MARK: - Initializing Language Models.
static func initLangModels(userOnly: Bool) {
DispatchQueue.global(qos: .userInitiated).async {
// mgrLangModel loadUserPhrases dataFolderPath
//
//
mgrLangModel.loadUserAssociatedPhrases()
mgrLangModel.loadUserPhraseReplacement()
mgrLangModel.loadUserPhrases()
}
// mgrLangModel loadUserPhrases dataFolderPath
//
//
mgrLangModel.loadUserAssociatesData()
mgrLangModel.loadUserPhraseReplacement()
mgrLangModel.loadUserPhrasesData()
if !userOnly {
// mgrLangModel.loadDataModels()
}

View File

@ -407,10 +407,19 @@ extension ctlInputMethod {
candidates.sort {
$0.count > $1.count
}
// If there is a candidate which is too long, we use the vertical
// candidate list window automatically.
if candidates.first?.count ?? 0 > 8 {
// return true //
if let candidateFirst = candidates.first {
// If there is a candidate which is too long, we use the vertical
// candidate list window automatically.
if candidateFirst.count > 8 {
// return true //
}
}
// 使
// for
for candidate in candidates {
if ["顏文字", "颜文字"].contains(candidate), mgrPrefs.symbolInputEnabled {
return true
}
}
return false
}()

View File

@ -135,7 +135,7 @@ extension ctlInputMethod {
if optionKeyPressed || !mgrPrefs.shouldAutoReloadUserDataFiles {
menu.addItem(
withTitle: NSLocalizedString("Reload User Phrases", comment: ""),
action: #selector(reloadUserPhrases(_:)), keyEquivalent: ""
action: #selector(reloadUserPhrasesData(_:)), keyEquivalent: ""
)
}
@ -346,7 +346,7 @@ extension ctlInputMethod {
}
}
@objc func reloadUserPhrases(_: Any?) {
@objc func reloadUserPhrasesData(_: Any?) {
IME.initLangModels(userOnly: true)
}

View File

@ -31,8 +31,12 @@ import Foundation
//
// LMInstantiator 100MB
private var lmCNS = vChewing.LMLite(consolidate: false)
private var lmSymbols = vChewing.LMCore(reverse: true, consolidate: false, defaultScore: -13.0, forceDefaultScore: true)
private var lmCNS = vChewing.LMCoreEX(
reverse: true, consolidate: false, defaultScore: -11.0, forceDefaultScore: false
)
private var lmSymbols = vChewing.LMCoreEX(
reverse: true, consolidate: false, defaultScore: -13.0, forceDefaultScore: false
)
extension vChewing {
/// LMInstantiator is a facade for managing a set of models including
@ -62,26 +66,35 @@ extension vChewing {
public var isCNSEnabled = false
public var isSymbolEnabled = false
///
/// LMCore key [Unigram]
///
/// ----------------------
/// LMCoreEX key [Unigram]
///
///
/// 使 LMLite
/// LMLite
/// LMLite LMCore
/// LMReplacements LMAssociates 使
/// LMCoreEX Unigram
/// LMCoreEX 滿
/// LMReplacements LMAssociates 使
//
/// Reverse
/// Reverse
var lmCore = LMCore(reverse: false, consolidate: false, defaultScore: -9.5, forceDefaultScore: false)
var lmMisc = LMCore(reverse: true, consolidate: false, defaultScore: -1, forceDefaultScore: false)
var lmCore = LMCoreEX(
reverse: false, consolidate: false, defaultScore: -9.9, forceDefaultScore: false
)
var lmMisc = LMCoreEX(
reverse: true, consolidate: false, defaultScore: -1.0, forceDefaultScore: false
)
// 使
// 使使
var lmUserPhrases = LMLite(consolidate: true)
var lmFiltered = LMLite(consolidate: true)
var lmUserSymbols = LMLite(consolidate: true)
var lmUserPhrases = LMCoreEX(
reverse: true, consolidate: true, defaultScore: 0, forceDefaultScore: true
)
var lmFiltered = LMCoreEX(
reverse: true, consolidate: true, defaultScore: 0, forceDefaultScore: true
)
var lmUserSymbols = LMCoreEX(
reverse: true, consolidate: true, defaultScore: -12.0, forceDefaultScore: true
)
var lmReplacements = LMReplacments()
var lmAssociates = LMAssociates()
@ -90,7 +103,7 @@ extension vChewing {
// 調
public func isDataModelLoaded() -> Bool { lmCore.isLoaded() }
public func isLanguageModelLoaded() -> Bool { lmCore.isLoaded() }
public func loadLanguageModel(path: String) {
if FileManager.default.isReadableFile(atPath: path) {
lmCore.open(path)
@ -130,7 +143,7 @@ extension vChewing {
}
}
public func loadUserPhrases(path: String, filterPath: String) {
public func loadUserPhrasesData(path: String, filterPath: String) {
if FileManager.default.isReadableFile(atPath: path) {
lmUserPhrases.close()
lmUserPhrases.open(path)
@ -157,7 +170,7 @@ extension vChewing {
}
}
public func loadUserAssociatedPhrases(path: String) {
public func loadUserAssociatesData(path: String) {
if FileManager.default.isReadableFile(atPath: path) {
lmAssociates.close()
lmAssociates.open(path)
@ -167,7 +180,7 @@ extension vChewing {
}
}
public func loadPhraseReplacementMap(path: String) {
public func loadReplacementsData(path: String) {
if FileManager.default.isReadableFile(atPath: path) {
lmReplacements.close()
lmReplacements.open(path)
@ -201,7 +214,7 @@ extension vChewing {
// reversed 使
//
// rawUserUnigrams
rawAllUnigrams += lmUserPhrases.unigramsFor(key: key, score: 0.0).reversed()
rawAllUnigrams += lmUserPhrases.unigramsFor(key: key).reversed()
if lmUserPhrases.unigramsFor(key: key).isEmpty {
IME.prtDebugIntel("Not found in UserPhrasesUnigram(\(lmUserPhrases.count)): \(key)")
}
@ -211,11 +224,11 @@ extension vChewing {
rawAllUnigrams += lmCore.unigramsFor(key: key)
if isCNSEnabled {
rawAllUnigrams += lmCNS.unigramsFor(key: key, score: -11)
rawAllUnigrams += lmCNS.unigramsFor(key: key)
}
if isSymbolEnabled {
rawAllUnigrams += lmUserSymbols.unigramsFor(key: key, score: -12.0)
rawAllUnigrams += lmUserSymbols.unigramsFor(key: key)
if lmUserSymbols.unigramsFor(key: key).isEmpty {
IME.prtDebugIntel("Not found in UserSymbolUnigram(\(lmUserSymbols.count)): \(key)")
}
@ -232,15 +245,6 @@ extension vChewing {
filteredPairs.insert(unigram.keyValue)
}
var debugOutput = "\n"
for neta in rawAllUnigrams {
debugOutput += "RAW: \(neta.keyValue.key) \(neta.keyValue.value) \(neta.score)\n"
}
if debugOutput == "\n" {
debugOutput = "RAW: No match found in all unigrams."
}
IME.prtDebugIntel(debugOutput)
return filterAndTransform(
unigrams: rawAllUnigrams,
filter: filteredPairs, inserted: &insertedPairs

View File

@ -1,6 +1,5 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// Refactored from the ObjCpp-version of this class by:
// (c) 2011 and onwards The OpenVanilla Project (MIT License).
// StringView Ranges extension by (c) 2022 and onwards Isaac Xen (MIT License).
/*
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
@ -28,18 +27,19 @@ import Foundation
extension vChewing {
@frozen public struct LMAssociates {
var keyValueMap: [String: [Megrez.KeyValuePair]] = [:]
var rangeMap: [String: [Range<String.Index>]] = [:]
var strData: String = ""
public var count: Int {
keyValueMap.count
rangeMap.count
}
public init() {
keyValueMap = [:]
rangeMap = [:]
}
public func isLoaded() -> Bool {
!keyValueMap.isEmpty
!rangeMap.isEmpty
}
@discardableResult public mutating func open(_ path: String) -> Bool {
@ -50,53 +50,40 @@ extension vChewing {
LMConsolidator.fixEOF(path: path)
LMConsolidator.consolidate(path: path, pragma: true)
var arrData: [String] = []
do {
arrData = try String(contentsOfFile: path, encoding: .utf8).components(separatedBy: "\n")
strData = try String(contentsOfFile: path, encoding: .utf8).replacingOccurrences(of: "\t", with: " ")
strData.ranges(splitBy: "\n").forEach {
let neta = strData[$0].components(separatedBy: " ")
if neta.count >= 2 {
let theKey = neta[0]
if !neta[0].isEmpty, !neta[1].isEmpty, theKey.first != "#" {
let theValue = $0
rangeMap[theKey, default: []].append(theValue)
}
}
}
} catch {
IME.prtDebugIntel("\(error)")
IME.prtDebugIntel("↑ Exception happened when reading Associated Phrases data.")
IME.prtDebugIntel("↑ Exception happened when reading data at: \(path).")
return false
}
for (lineID, lineContent) in arrData.enumerated() {
if !lineContent.hasPrefix("#") {
let lineContent = lineContent.replacingOccurrences(of: "\t", with: " ")
if lineContent.components(separatedBy: " ").count < 2 {
if lineContent != "", lineContent != " " {
IME.prtDebugIntel("Line #\(lineID + 1) Wrecked: \(lineContent)")
}
continue
}
var currentKV = Megrez.KeyValuePair()
for (unitID, unitContent) in lineContent.components(separatedBy: " ").enumerated() {
switch unitID {
case 0:
currentKV.key = unitContent
case 1:
currentKV.value = unitContent
default: break
}
}
keyValueMap[currentKV.key, default: []].append(currentKV)
}
}
return true
}
public mutating func close() {
if isLoaded() {
keyValueMap.removeAll()
rangeMap.removeAll()
}
}
public func dump() {
var strDump = ""
for entry in keyValueMap {
let rows: [Megrez.KeyValuePair] = entry.value
for row in rows {
let addline = row.key + " " + row.value + "\n"
for entry in rangeMap {
let netaRanges: [Range<String.Index>] = entry.value
for netaRange in netaRanges {
let neta = strData[netaRange]
let addline = neta + "\n"
strDump += addline
}
}
@ -104,17 +91,33 @@ extension vChewing {
}
public func valuesFor(key: String) -> [String]? {
var v: [String] = []
if let matched = keyValueMap[key] {
for entry in matched as [Megrez.KeyValuePair] {
v.append(entry.value)
var pairs: [String] = []
if let arrRangeRecords: [Range<String.Index>] = rangeMap[key] {
for netaRange in arrRangeRecords {
let neta = strData[netaRange].components(separatedBy: " ")
let theValue: String = neta[1]
pairs.append(theValue)
}
}
return v
return pairs
}
public func hasValuesFor(key: String) -> Bool {
keyValueMap[key] != nil
rangeMap[key] != nil
}
}
}
// MARK: - StringView Ranges Extension (by Isaac Xen)
extension String {
fileprivate func ranges(splitBy separator: Element) -> [Range<String.Index>] {
var startIndex = startIndex
return split(separator: separator).reduce(into: []) { ranges, substring in
_ = range(of: substring, range: startIndex..<endIndex).map { range in
ranges.append(range)
startIndex = range.upperBound
}
}
}
}

View File

@ -1,4 +1,5 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// StringView Ranges extension by (c) 2022 and onwards Isaac Xen (MIT License).
/*
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
@ -22,27 +23,31 @@ 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.
*/
// 使 Swift String
/// LMCore LMCoreEX range
/// range strData
/// C++ ParselessLM Swift
/// For
import Foundation
extension vChewing {
@frozen public struct LMCore {
var keyValueScoreMap: [String: [Megrez.Unigram]] = [:]
@frozen public struct LMCoreEX {
var rangeMap: [String: [Range<String.Index>]] = [:]
var strData: String = ""
var shouldReverse: Bool = false
var allowConsolidation: Bool = false
var defaultScore: Double = 0
var shouldForceDefaultScore: Bool = false
public var count: Int {
keyValueScoreMap.count
rangeMap.count
}
public init(
reverse: Bool = false, consolidate: Bool = false, defaultScore scoreDefault: Double = 0,
forceDefaultScore: Bool = false
) {
keyValueScoreMap = [:]
rangeMap = [:]
allowConsolidation = consolidate
shouldReverse = reverse
defaultScore = scoreDefault
@ -50,7 +55,7 @@ extension vChewing {
}
public func isLoaded() -> Bool {
!keyValueScoreMap.isEmpty
!rangeMap.isEmpty
}
@discardableResult public mutating func open(_ path: String) -> Bool {
@ -63,64 +68,30 @@ extension vChewing {
LMConsolidator.consolidate(path: path, pragma: true)
}
var arrData: [String] = []
do {
arrData = try String(contentsOfFile: path, encoding: .utf8).components(separatedBy: "\n")
strData = try String(contentsOfFile: path, encoding: .utf8).replacingOccurrences(of: "\t", with: " ")
strData.ranges(splitBy: "\n").forEach {
let neta = strData[$0].components(separatedBy: " ")
if neta.count >= 2 {
let theKey = shouldReverse ? neta[1] : neta[0]
if !neta[0].isEmpty, !neta[1].isEmpty, theKey.first != "#" {
let theValue = $0
rangeMap[theKey, default: []].append(theValue)
}
}
}
} catch {
IME.prtDebugIntel("\(error)")
IME.prtDebugIntel("↑ Exception happened when reading Associated Phrases data.")
IME.prtDebugIntel("↑ Exception happened when reading data at: \(path).")
return false
}
for (lineID, lineContent) in arrData.enumerated() {
if !lineContent.hasPrefix("#") {
let lineContent = lineContent.replacingOccurrences(of: "\t", with: " ")
if lineContent.components(separatedBy: " ").count < 2 {
if lineContent != "", lineContent != " " {
IME.prtDebugIntel("Line #\(lineID + 1) Wrecked: \(lineContent)")
}
continue
}
var currentUnigram = Megrez.Unigram(keyValue: Megrez.KeyValuePair(), score: defaultScore)
var columnOne = ""
var columnTwo = ""
for (unitID, unitContent) in lineContent.components(separatedBy: " ").enumerated() {
switch unitID {
case 0:
columnOne = unitContent
case 1:
columnTwo = unitContent
case 2:
if !shouldForceDefaultScore {
if let unitContentConverted = Double(unitContent) {
currentUnigram.score = unitContentConverted
} else {
IME.prtDebugIntel("Line #\(lineID) Score Data Wrecked: \(lineContent)")
}
}
default: break
}
}
//
if columnOne.contains("_punctuation_") {
currentUnigram.score -= (Double(lineID) * 0.000001)
}
let kvPair =
shouldReverse
? Megrez.KeyValuePair(key: columnTwo, value: columnOne)
: Megrez.KeyValuePair(key: columnOne, value: columnTwo)
currentUnigram.keyValue = kvPair
let key = shouldReverse ? columnTwo : columnOne
keyValueScoreMap[key, default: []].append(currentUnigram)
}
}
return true
}
public mutating func close() {
if isLoaded() {
keyValueScoreMap.removeAll()
rangeMap.removeAll()
}
}
@ -128,10 +99,11 @@ extension vChewing {
public func dump() {
var strDump = ""
for entry in keyValueScoreMap {
let rows: [Megrez.Unigram] = entry.value
for row in rows {
let addline = row.keyValue.key + " " + row.keyValue.value + " " + String(row.score) + "\n"
for entry in rangeMap {
let netaRanges: [Range<String.Index>] = entry.value
for netaRange in netaRanges {
let neta = strData[netaRange]
let addline = neta + "\n"
strDump += addline
}
}
@ -145,11 +117,41 @@ extension vChewing {
}
public func unigramsFor(key: String) -> [Megrez.Unigram] {
keyValueScoreMap[key] ?? [Megrez.Unigram]()
var grams: [Megrez.Unigram] = []
if let arrRangeRecords: [Range<String.Index>] = rangeMap[key] {
for netaRange in arrRangeRecords {
let neta = strData[netaRange].components(separatedBy: " ")
let theValue: String = shouldReverse ? neta[0] : neta[1]
let kvPair = Megrez.KeyValuePair(key: key, value: theValue)
var theScore = defaultScore
if neta.count >= 3, !shouldForceDefaultScore {
theScore = .init(neta[2]) ?? defaultScore
}
if theScore > 0 {
theScore *= -1 //
}
grams.append(Megrez.Unigram(keyValue: kvPair, score: theScore))
}
}
return grams
}
public func hasUnigramsFor(key: String) -> Bool {
keyValueScoreMap[key] != nil
rangeMap[key] != nil
}
}
}
// MARK: - StringView Ranges Extension (by Isaac Xen)
extension String {
fileprivate func ranges(splitBy separator: Element) -> [Range<String.Index>] {
var startIndex = startIndex
return split(separator: separator).reduce(into: []) { ranges, substring in
_ = range(of: substring, range: startIndex..<endIndex).map { range in
ranges.append(range)
startIndex = range.upperBound
}
}
}
}

View File

@ -1,124 +0,0 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// Refactored from the ObjCpp-version of this class by:
// (c) 2011 and onwards The OpenVanilla Project (MIT License).
/*
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
extension vChewing {
@frozen public struct LMLite {
var keyValueMap: [String: [Megrez.KeyValuePair]] = [:]
var allowConsolidation = false
public var count: Int {
keyValueMap.count
}
public init(consolidate: Bool = false) {
keyValueMap = [:]
allowConsolidation = consolidate
}
public func isLoaded() -> Bool {
!keyValueMap.isEmpty
}
@discardableResult public mutating func open(_ path: String) -> Bool {
if isLoaded() {
return false
}
if allowConsolidation {
LMConsolidator.fixEOF(path: path)
LMConsolidator.consolidate(path: path, pragma: true)
}
var arrData: [String] = []
do {
arrData = try String(contentsOfFile: path, encoding: .utf8).components(separatedBy: "\n")
} catch {
IME.prtDebugIntel("\(error)")
IME.prtDebugIntel("↑ Exception happened when reading Associated Phrases data.")
return false
}
for (lineID, lineContent) in arrData.enumerated() {
if !lineContent.hasPrefix("#") {
let lineContent = lineContent.replacingOccurrences(of: "\t", with: " ")
if lineContent.components(separatedBy: " ").count < 2 {
if lineContent != "", lineContent != " " {
IME.prtDebugIntel("Line #\(lineID + 1) Wrecked: \(lineContent)")
}
continue
}
var currentKV = Megrez.KeyValuePair()
for (unitID, unitContent) in lineContent.components(separatedBy: " ").enumerated() {
switch unitID {
case 0:
currentKV.value = unitContent
case 1:
currentKV.key = unitContent
default: break
}
}
keyValueMap[currentKV.key, default: []].append(currentKV)
}
}
return true
}
public mutating func close() {
if isLoaded() {
keyValueMap.removeAll()
}
}
public func dump() {
var strDump = ""
for entry in keyValueMap {
let rows: [Megrez.KeyValuePair] = entry.value
for row in rows {
let addline = row.key + " " + row.value + "\n"
strDump += addline
}
}
IME.prtDebugIntel(strDump)
}
public func unigramsFor(key: String, score givenScore: Double = 0.0) -> [Megrez.Unigram] {
var v: [Megrez.Unigram] = []
if let matched = keyValueMap[key] {
for entry in matched as [Megrez.KeyValuePair] {
v.append(Megrez.Unigram(keyValue: entry, score: givenScore))
}
}
return v
}
public func hasUnigramsFor(key: String) -> Bool {
keyValueMap[key] != nil
}
}
}

View File

@ -1,6 +1,5 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// Refactored from the ObjCpp-version of this class by:
// (c) 2011 and onwards The OpenVanilla Project (MIT License).
// StringView Ranges extension by (c) 2022 and onwards Isaac Xen (MIT License).
/*
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
@ -28,18 +27,19 @@ import Foundation
extension vChewing {
@frozen public struct LMReplacments {
var keyValueMap: [String: String] = [:]
var rangeMap: [String: Range<String.Index>] = [:]
var strData: String = ""
public var count: Int {
keyValueMap.count
rangeMap.count
}
public init() {
keyValueMap = [:]
rangeMap = [:]
}
public func isLoaded() -> Bool {
!keyValueMap.isEmpty
!rangeMap.isEmpty
}
@discardableResult public mutating func open(_ path: String) -> Bool {
@ -50,58 +50,68 @@ extension vChewing {
LMConsolidator.fixEOF(path: path)
LMConsolidator.consolidate(path: path, pragma: true)
var arrData: [String] = []
do {
arrData = try String(contentsOfFile: path, encoding: .utf8).components(separatedBy: "\n")
strData = try String(contentsOfFile: path, encoding: .utf8).replacingOccurrences(of: "\t", with: " ")
strData.ranges(splitBy: "\n").forEach {
let neta = strData[$0].components(separatedBy: " ")
if neta.count >= 2 {
let theKey = neta[0]
if !neta[0].isEmpty, !neta[1].isEmpty, theKey.first != "#" {
let theValue = $0
rangeMap[theKey] = theValue
}
}
}
} catch {
IME.prtDebugIntel("\(error)")
IME.prtDebugIntel("↑ Exception happened when reading Associated Phrases data.")
IME.prtDebugIntel("↑ Exception happened when reading data at: \(path).")
return false
}
for (lineID, lineContent) in arrData.enumerated() {
if !lineContent.hasPrefix("#") {
let lineContent = lineContent.replacingOccurrences(of: "\t", with: " ")
if lineContent.components(separatedBy: " ").count < 2 {
if lineContent != "", lineContent != " " {
IME.prtDebugIntel("Line #\(lineID + 1) Wrecked: \(lineContent)")
}
continue
}
var currentKV = Megrez.KeyValuePair()
for (unitID, unitContent) in lineContent.components(separatedBy: " ").enumerated() {
switch unitID {
case 0:
currentKV.key = unitContent
case 1:
currentKV.value = unitContent
default: break
}
}
keyValueMap[currentKV.key] = currentKV.value
}
}
return true
}
public mutating func close() {
if isLoaded() {
keyValueMap.removeAll()
rangeMap.removeAll()
}
}
public func dump() {
var strDump = ""
for entry in keyValueMap {
strDump += entry.key + " " + entry.value + "\n"
for entry in rangeMap {
strDump += strData[entry.value] + "\n"
}
IME.prtDebugIntel(strDump)
}
public func valuesFor(key: String) -> String {
keyValueMap[key] ?? ""
guard let range = rangeMap[key] else {
return ""
}
let arrNeta = strData[range].components(separatedBy: " ")
guard arrNeta.count >= 2 else {
return ""
}
return String(arrNeta[1])
}
public func hasValuesFor(key: String) -> Bool {
rangeMap[key] != nil
}
}
}
// MARK: - StringView Ranges Extension (by Isaac Xen)
extension String {
fileprivate func ranges(splitBy separator: Element) -> [Range<String.Index>] {
var startIndex = startIndex
return split(separator: separator).reduce(into: []) { ranges, substring in
_ = range(of: substring, range: startIndex..<endIndex).map { range in
ranges.append(range)
startIndex = range.upperBound
}
}
}
}

View File

@ -51,27 +51,25 @@ class mgrLangModel: NSObject {
}
public static func loadDataModels() {
DispatchQueue.global(qos: .userInitiated).async {
if !gLangModelCHT.isCNSDataLoaded() {
gLangModelCHT.loadCNSData(path: getBundleDataPath("char-kanji-cns"))
}
if !gLangModelCHT.isMiscDataLoaded() {
gLangModelCHT.loadMiscData(path: getBundleDataPath("data-zhuyinwen"))
}
if !gLangModelCHT.isSymbolDataLoaded() {
gLangModelCHT.loadSymbolData(path: getBundleDataPath("data-symbols"))
}
if !gLangModelCHS.isCNSDataLoaded() {
gLangModelCHS.loadCNSData(path: getBundleDataPath("char-kanji-cns"))
}
if !gLangModelCHS.isMiscDataLoaded() {
gLangModelCHS.loadMiscData(path: getBundleDataPath("data-zhuyinwen"))
}
if !gLangModelCHS.isSymbolDataLoaded() {
gLangModelCHS.loadSymbolData(path: getBundleDataPath("data-symbols"))
}
if !gLangModelCHT.isCNSDataLoaded() {
gLangModelCHT.loadCNSData(path: getBundleDataPath("char-kanji-cns"))
}
if !gLangModelCHT.isDataModelLoaded() {
if !gLangModelCHT.isMiscDataLoaded() {
gLangModelCHT.loadMiscData(path: getBundleDataPath("data-zhuyinwen"))
}
if !gLangModelCHT.isSymbolDataLoaded() {
gLangModelCHT.loadSymbolData(path: getBundleDataPath("data-symbols"))
}
if !gLangModelCHS.isCNSDataLoaded() {
gLangModelCHS.loadCNSData(path: getBundleDataPath("char-kanji-cns"))
}
if !gLangModelCHS.isMiscDataLoaded() {
gLangModelCHS.loadMiscData(path: getBundleDataPath("data-zhuyinwen"))
}
if !gLangModelCHS.isSymbolDataLoaded() {
gLangModelCHS.loadSymbolData(path: getBundleDataPath("data-symbols"))
}
if !gLangModelCHT.isLanguageModelLoaded() {
NotifierController.notify(
message: String(
format: "%@", NSLocalizedString("Loading CHT Core Dict...", comment: "")
@ -84,7 +82,7 @@ class mgrLangModel: NSObject {
)
)
}
if !gLangModelCHS.isDataModelLoaded() {
if !gLangModelCHS.isLanguageModelLoaded() {
NotifierController.notify(
message: String(
format: "%@", NSLocalizedString("Loading CHS Core Dict...", comment: "")
@ -101,18 +99,16 @@ class mgrLangModel: NSObject {
public static func loadDataModel(_ mode: InputMode) {
if mode == InputMode.imeModeCHS {
DispatchQueue.global(qos: .userInitiated).async {
if !gLangModelCHS.isMiscDataLoaded() {
gLangModelCHS.loadMiscData(path: getBundleDataPath("data-zhuyinwen"))
}
if !gLangModelCHS.isSymbolDataLoaded() {
gLangModelCHS.loadSymbolData(path: getBundleDataPath("data-symbols"))
}
if !gLangModelCHS.isCNSDataLoaded() {
gLangModelCHS.loadCNSData(path: getBundleDataPath("char-kanji-cns"))
}
if !gLangModelCHS.isMiscDataLoaded() {
gLangModelCHS.loadMiscData(path: getBundleDataPath("data-zhuyinwen"))
}
if !gLangModelCHS.isDataModelLoaded() {
if !gLangModelCHS.isSymbolDataLoaded() {
gLangModelCHS.loadSymbolData(path: getBundleDataPath("data-symbols"))
}
if !gLangModelCHS.isCNSDataLoaded() {
gLangModelCHS.loadCNSData(path: getBundleDataPath("char-kanji-cns"))
}
if !gLangModelCHS.isLanguageModelLoaded() {
NotifierController.notify(
message: String(
format: "%@", NSLocalizedString("Loading CHS Core Dict...", comment: "")
@ -126,18 +122,16 @@ class mgrLangModel: NSObject {
)
}
} else if mode == InputMode.imeModeCHT {
DispatchQueue.global(qos: .userInitiated).async {
if !gLangModelCHT.isMiscDataLoaded() {
gLangModelCHT.loadMiscData(path: getBundleDataPath("data-zhuyinwen"))
}
if !gLangModelCHT.isSymbolDataLoaded() {
gLangModelCHT.loadSymbolData(path: getBundleDataPath("data-symbols"))
}
if !gLangModelCHT.isCNSDataLoaded() {
gLangModelCHT.loadCNSData(path: getBundleDataPath("char-kanji-cns"))
}
if !gLangModelCHT.isMiscDataLoaded() {
gLangModelCHT.loadMiscData(path: getBundleDataPath("data-zhuyinwen"))
}
if !gLangModelCHT.isDataModelLoaded() {
if !gLangModelCHT.isSymbolDataLoaded() {
gLangModelCHT.loadSymbolData(path: getBundleDataPath("data-symbols"))
}
if !gLangModelCHT.isCNSDataLoaded() {
gLangModelCHT.loadCNSData(path: getBundleDataPath("char-kanji-cns"))
}
if !gLangModelCHT.isLanguageModelLoaded() {
NotifierController.notify(
message: String(
format: "%@", NSLocalizedString("Loading CHT Core Dict...", comment: "")
@ -153,12 +147,12 @@ class mgrLangModel: NSObject {
}
}
public static func loadUserPhrases() {
gLangModelCHT.loadUserPhrases(
public static func loadUserPhrasesData() {
gLangModelCHT.loadUserPhrasesData(
path: userPhrasesDataPath(InputMode.imeModeCHT),
filterPath: excludedPhrasesDataPath(InputMode.imeModeCHT)
)
gLangModelCHS.loadUserPhrases(
gLangModelCHS.loadUserPhrasesData(
path: userPhrasesDataPath(InputMode.imeModeCHS),
filterPath: excludedPhrasesDataPath(InputMode.imeModeCHS)
)
@ -166,20 +160,20 @@ class mgrLangModel: NSObject {
gLangModelCHS.loadUserSymbolData(path: userSymbolDataPath(InputMode.imeModeCHS))
}
public static func loadUserAssociatedPhrases() {
gLangModelCHT.loadUserAssociatedPhrases(
public static func loadUserAssociatesData() {
gLangModelCHT.loadUserAssociatesData(
path: mgrLangModel.userAssociatedPhrasesDataPath(InputMode.imeModeCHT)
)
gLangModelCHS.loadUserAssociatedPhrases(
gLangModelCHS.loadUserAssociatesData(
path: mgrLangModel.userAssociatedPhrasesDataPath(InputMode.imeModeCHS)
)
}
public static func loadUserPhraseReplacement() {
gLangModelCHT.loadPhraseReplacementMap(
gLangModelCHT.loadReplacementsData(
path: mgrLangModel.phraseReplacementDataPath(InputMode.imeModeCHT)
)
gLangModelCHS.loadPhraseReplacementMap(
gLangModelCHS.loadReplacementsData(
path: mgrLangModel.phraseReplacementDataPath(InputMode.imeModeCHS)
)
}
@ -430,7 +424,7 @@ class mgrLangModel: NSObject {
// We use FSEventStream to monitor possible changes of the user phrase folder, hence the
// lack of the needs of manually load data here unless FSEventStream is disabled by user.
if !mgrPrefs.shouldAutoReloadUserDataFiles {
loadUserPhrases()
loadUserPhrasesData()
}
return true
}

View File

@ -116,6 +116,7 @@ struct suiPrefPaneDictionary: View {
Toggle(LocalizedStringKey("Enable CNS11643 Support (2022-01-27)"), isOn: $selEnableCNS11643)
.onChange(of: selEnableCNS11643) { value in
mgrPrefs.cns11643Enabled = value
mgrLangModel.setCNSEnabled(value)
}
Toggle(
LocalizedStringKey("Enable symbol input support (incl. certain emoji symbols)"),
@ -123,6 +124,7 @@ struct suiPrefPaneDictionary: View {
)
.onChange(of: selEnableSymbolInputSupport) { value in
mgrPrefs.symbolInputEnabled = value
mgrLangModel.setSymbolEnabled(value)
}
}
}

View File

@ -1,8 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="20037" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="19529" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="20037"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="19529"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@ -58,7 +57,7 @@
<textFieldCell key="cell" selectable="YES" id="lblCredits">
<font key="font" metaFont="cellTitle"/>
<string key="title">McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.
vChewing macOS Development: Shiki Suen, Hiraku Wang, etc.
vChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.
vChewing Phrase Database Maintained by Shiki Suen.</string>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
@ -125,7 +124,7 @@ DQ
<rect key="frame" x="91" y="143" width="427" height="183"/>
<clipView key="contentView" drawsBackground="NO" id="35U-hd-B9v">
<rect key="frame" x="1" y="1" width="425" height="181"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textView editable="NO" importsGraphics="NO" richText="NO" verticallyResizable="YES" smartInsertDelete="YES" id="cEu-uC-XnV" userLabel="appEULAContent">
<rect key="frame" x="0.0" y="0.0" width="425" height="181"/>

View File

@ -23,5 +23,5 @@
/* Class = "NSTextFieldCell"; title = "© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project."; ObjectID = "lblCopyright"; */
// "lblCopyright.title" = "© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project.";
/* Class = "NSTextFieldCell"; title = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; ObjectID = "lblCredits"; */
"lblCredits.title" = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine.";
/* Class = "NSTextFieldCell"; title = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; ObjectID = "lblCredits"; */
"lblCredits.title" = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine.";

View File

@ -23,5 +23,5 @@
/* Class = "NSTextFieldCell"; title = "© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project."; ObjectID = "lblCopyright"; */
// "lblCopyright.title" = "© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project.";
/* Class = "NSTextFieldCell"; title = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; ObjectID = "lblCredits"; */
"lblCredits.title" = "ボポモフォエンジン開発Lukhnos Liu。\n入力状態管理システム開発Zonble Yang。\nmacOS 版威注音の開発Shiki Suen, Hiraku Wang, など。\n威注音語彙データの維持Shiki Suen。\nMegrez 辞書処理エンジンShiki SuenLukhnos の Gramambular C++ エンジンを Swift で再開発したものである)。";
/* Class = "NSTextFieldCell"; title = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; ObjectID = "lblCredits"; */
"lblCredits.title" = "ボポモフォエンジン開発Lukhnos Liu。\n入力状態管理システム開発Zonble Yang。\nmacOS 版威注音の開発Shiki Suen, Isaac Xen, Hiraku Wang, など。\n威注音語彙データの維持Shiki Suen。\nMegrez 辞書処理エンジンShiki SuenLukhnos の Gramambular C++ エンジンを Swift で再開発したものである)。";

View File

@ -23,5 +23,5 @@
/* Class = "NSTextFieldCell"; title = "© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project."; ObjectID = "lblCopyright"; */
// "lblCopyright.title" = "© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project.";
/* Class = "NSTextFieldCell"; title = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; ObjectID = "lblCredits"; */
"lblCredits.title" = "注音拼音输入处理引擎研发Lukhnos Liu。\n输入法状态管理引擎研发Zonble Yang。\n威注音 macOS 程式研发Shiki Suen, Hiraku Wang, 等。\n威注音词库维护Shiki Suen。\n天权星语汇引擎Shiki Suen用 Swift 将 Lukhnos 的 C++ Gramambular 重写而得。";
/* Class = "NSTextFieldCell"; title = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; ObjectID = "lblCredits"; */
"lblCredits.title" = "注音拼音输入处理引擎研发Lukhnos Liu。\n输入法状态管理引擎研发Zonble Yang。\n威注音 macOS 程式研发Shiki Suen, Isaac Xen, Hiraku Wang, 等。\n威注音词库维护Shiki Suen。\n天权星语汇引擎Shiki Suen用 Swift 将 Lukhnos 的 C++ Gramambular 重写而得。";

View File

@ -23,5 +23,5 @@
/* Class = "NSTextFieldCell"; title = "© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project."; ObjectID = "lblCopyright"; */
// "lblCopyright.title" = "© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project.";
/* Class = "NSTextFieldCell"; title = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; ObjectID = "lblCredits"; */
"lblCredits.title" = "注音拼音輸入處理引擎研發Lukhnos Liu。\n輸入法狀態管理引擎研發Zonble Yang。\n威注音 macOS 程式研發Shiki Suen, Hiraku Wang, 等。\n威注音詞庫維護Shiki Suen。\n天權星語彙引擎Shiki Suen用 Swift 將 Lukhnos 的 C++ Gramambular 重寫而得。";
/* Class = "NSTextFieldCell"; title = "Mandarin Syllable Composer Engine by Lukhnos Liu.\nInput State Management Architecture by Zonble Yang.\nvChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.\nMegrez is a rewritten unigram engine by Shiki Suen using Swift, replacing Lukhnos' C++ Gramambular engine."; ObjectID = "lblCredits"; */
"lblCredits.title" = "注音拼音輸入處理引擎研發Lukhnos Liu。\n輸入法狀態管理引擎研發Zonble Yang。\n威注音 macOS 程式研發Shiki Suen, Isaac Xen, Hiraku Wang, 等。\n威注音詞庫維護Shiki Suen。\n天權星語彙引擎Shiki Suen用 Swift 將 Lukhnos 的 C++ Gramambular 重寫而得。";

View File

@ -3,9 +3,9 @@
<plist version="1.0">
<dict>
<key>CFBundleShortVersionString</key>
<string>1.5.4</string>
<string>1.5.5</string>
<key>CFBundleVersion</key>
<string>1954</string>
<string>1955</string>
<key>UpdateInfoEndpoint</key>
<string>https://gitee.com/vchewing/vChewing-macOS/raw/main/Update-Info.plist</string>
<key>UpdateInfoSite</key>

View File

@ -726,7 +726,7 @@
<key>USE_HFS+_COMPRESSION</key>
<false/>
<key>VERSION</key>
<string>1.5.4</string>
<string>1.5.5</string>
</dict>
<key>TYPE</key>
<integer>0</integer>

View File

@ -7,7 +7,6 @@
objects = {
/* Begin PBXBuildFile section */
5B00A230282011980058E5DB /* lmLite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B00A22F282011980058E5DB /* lmLite.swift */; };
5B0AF8B527B2C8290096FE54 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B0AF8B427B2C8290096FE54 /* StringExtension.swift */; };
5B11328927B94CFB00E58451 /* AppleKeyboardConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B11328827B94CFB00E58451 /* AppleKeyboardConverter.swift */; };
5B27AD6A27CB1F9B000ED75B /* data-symbols.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5B27AD6827CB1F9B000ED75B /* data-symbols.txt */; };
@ -48,10 +47,10 @@
5B782EC4280C243C007276DE /* KeyHandler_HandleCandidate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B782EC3280C243C007276DE /* KeyHandler_HandleCandidate.swift */; };
5B7BC4B027AFFBE800F66C24 /* frmPrefWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5B7BC4AE27AFFBE800F66C24 /* frmPrefWindow.xib */; };
5B7F225D2808501000DDD3CB /* KeyHandler_HandleInput.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B7F225C2808501000DDD3CB /* KeyHandler_HandleInput.swift */; };
5B887F302826AEA400B6651E /* lmCoreEX.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B887F2F2826AEA400B6651E /* lmCoreEX.swift */; };
5B949BD92816DC5400D87B5D /* LineReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B949BD82816DC5400D87B5D /* LineReader.swift */; };
5B949BDB2816DDBC00D87B5D /* LMConsolidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B949BDA2816DDBC00D87B5D /* LMConsolidator.swift */; };
5BA0DF312817857D009E73BB /* lmUserOverride.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA0DF2E2817857D009E73BB /* lmUserOverride.swift */; };
5BA0DF322817857D009E73BB /* lmCore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA0DF2F2817857D009E73BB /* lmCore.swift */; };
5BA9FD0F27FEDB6B002DE248 /* suiPrefPaneGeneral.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA9FD0A27FEDB6B002DE248 /* suiPrefPaneGeneral.swift */; };
5BA9FD1027FEDB6B002DE248 /* suiPrefPaneKeyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA9FD0B27FEDB6B002DE248 /* suiPrefPaneKeyboard.swift */; };
5BA9FD1127FEDB6B002DE248 /* ctlPrefUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BA9FD0C27FEDB6B002DE248 /* ctlPrefUI.swift */; };
@ -161,7 +160,6 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
5B00A22F282011980058E5DB /* lmLite.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = lmLite.swift; sourceTree = "<group>"; usesTabs = 0; };
5B04305327B529D800CB65BC /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
5B04305427B529D800CB65BC /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
5B04305527B529D800CB65BC /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/MainMenu.strings"; sourceTree = "<group>"; };
@ -225,10 +223,10 @@
5B7BC4AF27AFFBE800F66C24 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/frmPrefWindow.xib; sourceTree = "<group>"; };
5B7BC4B227AFFC0B00F66C24 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/frmPrefWindow.strings; sourceTree = "<group>"; };
5B7F225C2808501000DDD3CB /* KeyHandler_HandleInput.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = KeyHandler_HandleInput.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
5B887F2F2826AEA400B6651E /* lmCoreEX.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = lmCoreEX.swift; sourceTree = "<group>"; usesTabs = 0; };
5B949BD82816DC5400D87B5D /* LineReader.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; lineEnding = 0; path = LineReader.swift; sourceTree = "<group>"; usesTabs = 0; };
5B949BDA2816DDBC00D87B5D /* LMConsolidator.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; lineEnding = 0; path = LMConsolidator.swift; sourceTree = "<group>"; usesTabs = 0; };
5BA0DF2E2817857D009E73BB /* lmUserOverride.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; lineEnding = 0; path = lmUserOverride.swift; sourceTree = "<group>"; usesTabs = 0; };
5BA0DF2F2817857D009E73BB /* lmCore.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; lineEnding = 0; path = lmCore.swift; sourceTree = "<group>"; usesTabs = 0; };
5BA9FD0A27FEDB6B002DE248 /* suiPrefPaneGeneral.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = suiPrefPaneGeneral.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
5BA9FD0B27FEDB6B002DE248 /* suiPrefPaneKeyboard.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = suiPrefPaneKeyboard.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
5BA9FD0C27FEDB6B002DE248 /* ctlPrefUI.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = ctlPrefUI.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
@ -393,8 +391,7 @@
isa = PBXGroup;
children = (
5B407309281672610023DFFF /* lmAssociates.swift */,
5BA0DF2F2817857D009E73BB /* lmCore.swift */,
5B00A22F282011980058E5DB /* lmLite.swift */,
5B887F2F2826AEA400B6651E /* lmCoreEX.swift */,
5B40730A281672610023DFFF /* lmReplacements.swift */,
5BA0DF2E2817857D009E73BB /* lmUserOverride.swift */,
);
@ -1077,7 +1074,6 @@
5B707CE827D9F4590099EF99 /* OpenCCBridge.swift in Sources */,
D427F76C278CA2B0004A2160 /* AppDelegate.swift in Sources */,
5BA9FD4527FEF3C9002DE248 /* ToolbarItemStyleViewController.swift in Sources */,
5BA0DF322817857D009E73BB /* lmCore.swift in Sources */,
5BA9FD4127FEF3C8002DE248 /* PreferencesStyle.swift in Sources */,
5B7F225D2808501000DDD3CB /* KeyHandler_HandleInput.swift in Sources */,
5BA9FD1227FEDB6B002DE248 /* suiPrefPaneExperience.swift in Sources */,
@ -1088,6 +1084,7 @@
5BA9FD4827FEF3C9002DE248 /* PreferencesWindowController.swift in Sources */,
5BD0113B28180D6100609769 /* LMInstantiator.swift in Sources */,
D4E569DC27A34D0E00AC2CEF /* CTools.m in Sources */,
5B887F302826AEA400B6651E /* lmCoreEX.swift in Sources */,
5BA9FD4627FEF3C9002DE248 /* Container.swift in Sources */,
D47F7DD0278C0897002F9DD7 /* ctlNonModalAlertWindow.swift in Sources */,
5B38F5A2281E2E49007D5F5D /* 0_Megrez.swift in Sources */,
@ -1130,7 +1127,6 @@
5B62A34827AE7CD900A19448 /* ctlCandidateVertical.swift in Sources */,
5BA9FD4027FEF3C8002DE248 /* Localization.swift in Sources */,
5BA9FD1327FEDB6B002DE248 /* suiPrefPaneDictionary.swift in Sources */,
5B00A230282011980058E5DB /* lmLite.swift in Sources */,
5BBBB77A27AEDC690023B93A /* clsSFX.swift in Sources */,
5BA9FD4727FEF3C9002DE248 /* PreferencesStyleController.swift in Sources */,
5BF8423127BAA942008E7E4C /* vChewingKanjiConverter.swift in Sources */,
@ -1336,7 +1332,7 @@
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1954;
CURRENT_PROJECT_VERSION = 1955;
DEBUG_INFORMATION_FORMAT = dwarf;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
@ -1359,7 +1355,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.11.5;
MARKETING_VERSION = 1.5.4;
MARKETING_VERSION = 1.5.5;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor;
@ -1392,7 +1388,7 @@
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1954;
CURRENT_PROJECT_VERSION = 1955;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu11;
@ -1411,7 +1407,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.11.5;
MARKETING_VERSION = 1.5.4;
MARKETING_VERSION = 1.5.5;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor;
@ -1526,7 +1522,7 @@
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1954;
CURRENT_PROJECT_VERSION = 1955;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
@ -1561,7 +1557,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.11.5;
MARKETING_VERSION = 1.5.4;
MARKETING_VERSION = 1.5.5;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -1593,7 +1589,7 @@
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1954;
CURRENT_PROJECT_VERSION = 1955;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = "";
@ -1623,7 +1619,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.11.5;
MARKETING_VERSION = 1.5.4;
MARKETING_VERSION = 1.5.5;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@ -1706,7 +1702,7 @@
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1954;
CURRENT_PROJECT_VERSION = 1955;
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
@ -1731,7 +1727,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.11.5;
MARKETING_VERSION = 1.5.4;
MARKETING_VERSION = 1.5.5;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
@ -1758,7 +1754,7 @@
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1954;
CURRENT_PROJECT_VERSION = 1955;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
@ -1778,7 +1774,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.11.5;
MARKETING_VERSION = 1.5.4;
MARKETING_VERSION = 1.5.5;
PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
</Workspace>

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1320"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<PathRunnable
runnableDebuggingMode = "0"
BundleIdentifier = "org.atelierInmu.inputmethod.vChewing"
FilePath = "~/Library/Input Methods/vChewing.app">
</PathRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>