diff --git a/Source/Modules/ControllerModules/KeyHandler.mm b/Source/Modules/ControllerModules/KeyHandler.mm index fe523f9a..9797a6fa 100644 --- a/Source/Modules/ControllerModules/KeyHandler.mm +++ b/Source/Modules/ControllerModules/KeyHandler.mm @@ -97,21 +97,26 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; { NSString *newInputMode; vChewingLM *newLanguageModel; + UserOverrideModel *newUserOverrideModel; if ([value isKindOfClass:[NSString class]] && [value isEqual:imeModeCHS]) { newInputMode = imeModeCHS; newLanguageModel = [mgrLangModel lmCHS]; - newLanguageModel->setPhraseReplacementEnabled(false); + newUserOverrideModel = [mgrLangModel userOverrideModelCHS]; } else { newInputMode = imeModeCHT; newLanguageModel = [mgrLangModel lmCHT]; - newLanguageModel->setPhraseReplacementEnabled(Preferences.phraseReplacementEnabled); + newUserOverrideModel = [mgrLangModel userOverrideModelCHT]; } + // Symchronize the Preference Setting "setPhraseReplacementEnabled" to the new LM. + newLanguageModel->setPhraseReplacementEnabled(Preferences.phraseReplacementEnabled); + // Only apply the changes if the value is changed if (![_inputMode isEqualToString:newInputMode]) { _inputMode = newInputMode; _languageModel = newLanguageModel; + _userOverrideModel = newUserOverrideModel; if (_builder) { delete _builder; @@ -146,7 +151,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; // create the lattice builder _languageModel = [mgrLangModel lmCHT]; _languageModel->setPhraseReplacementEnabled(Preferences.phraseReplacementEnabled); - _userOverrideModel = [mgrLangModel userOverrideModel]; + _userOverrideModel = [mgrLangModel userOverrideModelCHT]; _builder = new BlockReadingBuilder(_languageModel); @@ -190,7 +195,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; size_t cursorIndex = [self _actualCandidateCursorIndex]; string stringValue = [value UTF8String]; _builder->grid().fixNodeSelectedCandidate(cursorIndex, stringValue); - if (_inputMode != imeModeCHS) { + if (!Preferences.useSCPCTypingMode) { // 不要針對逐字選字模式啟用臨時半衰記憶模型。 _userOverrideModel->observe(_walkedNodes, cursorIndex, stringValue, [[NSDate date] timeIntervalSince1970]); } [self _walk]; diff --git a/Source/Modules/IMEModules/ctlInputMethod.swift b/Source/Modules/IMEModules/ctlInputMethod.swift index 13cc180a..6fcbf635 100644 --- a/Source/Modules/IMEModules/ctlInputMethod.swift +++ b/Source/Modules/IMEModules/ctlInputMethod.swift @@ -224,8 +224,7 @@ class ctlInputMethod: IMKInputController { } @objc func togglePhraseReplacement(_ sender: Any?) { - let enabled = Preferences.togglePhraseReplacementEnabled() - mgrLangModel.phraseReplacementEnabled = enabled + mgrLangModel.setPhraseReplacementEnabled(Preferences.togglePhraseReplacementEnabled()) } @objc func selfTerminate(_ sender: Any?) { @@ -253,15 +252,15 @@ class ctlInputMethod: IMKInputController { } @objc func openUserPhrases(_ sender: Any?) { - open(userFileAt: mgrLangModel.userPhrasesDataPathCHT) + open(userFileAt: mgrLangModel.userPhrasesDataPath(keyHandler.inputMode)) } @objc func openExcludedPhrases(_ sender: Any?) { - open(userFileAt: mgrLangModel.excludedPhrasesDataPathCHT) + open(userFileAt: mgrLangModel.excludedPhrasesDataPath(keyHandler.inputMode)) } @objc func openPhraseReplacement(_ sender: Any?) { - open(userFileAt: mgrLangModel.phraseReplacementDataPathCHT) + open(userFileAt: mgrLangModel.phraseReplacementDataPath(keyHandler.inputMode)) } @objc func reloadUserPhrases(_ sender: Any?) { @@ -554,7 +553,7 @@ extension ctlInputMethod: KeyHandlerDelegate { if !state.validToWrite { return false } - mgrLangModel.writeUserPhrase(state.userPhrase) + mgrLangModel.writeUserPhrase(state.userPhrase, inputMode: keyHandler.inputMode) return true } } diff --git a/Source/Modules/LangModelRelated/mgrLangModel.h b/Source/Modules/LangModelRelated/mgrLangModel.h index e918eb84..df19d4cf 100644 --- a/Source/Modules/LangModelRelated/mgrLangModel.h +++ b/Source/Modules/LangModelRelated/mgrLangModel.h @@ -31,16 +31,16 @@ NS_ASSUME_NONNULL_BEGIN + (BOOL)checkIfUserLanguageModelFilesExist; + (BOOL)checkIfUserPhraseExist:(NSString *)userPhrase key:(NSString *)key NS_SWIFT_NAME(checkIfExist(userPhrase:key:)); -+ (BOOL)writeUserPhrase:(NSString *)userPhrase; ++ (BOOL)writeUserPhrase:(NSString *)userPhrase inputMode:(InputMode)mode; ++ (void)setPhraseReplacementEnabled:(BOOL)phraseReplacementEnabled; ++ (BOOL)cnsEnabled:(InputMode)mode; ++ (void)setCNSEnabled:(BOOL)cnsEnabled inputMode:(InputMode)mode; ++ (NSString *)userPhrasesDataPath:(InputMode)mode; ++ (NSString *)excludedPhrasesDataPath:(InputMode)mode; ++ (NSString *)phraseReplacementDataPath:(InputMode)mode; @property (class, readonly, nonatomic) NSString *dataFolderPath; -@property (class, readonly, nonatomic) NSString *userPhrasesDataPathCHT; -@property (class, readonly, nonatomic) NSString *userPhrasesDataPathCHS; -@property (class, readonly, nonatomic) NSString *excludedPhrasesDataPathCHT; -@property (class, readonly, nonatomic) NSString *excludedPhrasesDataPathCHS; -@property (class, readonly, nonatomic) NSString *phraseReplacementDataPathCHT; -@property (class, readonly, nonatomic) NSString *phraseReplacementDataPathCHS; -@property (class, assign, nonatomic) BOOL phraseReplacementEnabled; +@property (class, readonly, nonatomic) NSString *cnsDataPath; @end diff --git a/Source/Modules/LangModelRelated/mgrLangModel.mm b/Source/Modules/LangModelRelated/mgrLangModel.mm index 01745a6c..5a75fbc7 100644 --- a/Source/Modules/LangModelRelated/mgrLangModel.mm +++ b/Source/Modules/LangModelRelated/mgrLangModel.mm @@ -29,7 +29,8 @@ static const double kObservedOverrideHalflife = 5400.0; static vChewingLM gLangModelCHT; static vChewingLM gLangModelCHS; -static UserOverrideModel gUserOverrideModel(kUserOverrideModelCapacity, kObservedOverrideHalflife); +static UserOverrideModel gUserOverrideModelCHT(kUserOverrideModelCapacity, kObservedOverrideHalflife); +static UserOverrideModel gUserOverrideModelCHS(kUserOverrideModelCapacity, kObservedOverrideHalflife); static NSString *const kUserDataTemplateName = @"template-data"; static NSString *const kExcludedPhrasesvChewingTemplateName = @"template-exclude-phrases"; @@ -71,6 +72,9 @@ static void LTLoadAssociatedPhrases(vChewingLM &lm) if (!gLangModelCHT.isDataModelLoaded()) { LTLoadLanguageModelFile(@"data-cht", gLangModelCHT); } + if (!gLangModelCHT.isAssociatedPhrasesLoaded()) { + LTLoadAssociatedPhrases(gLangModelCHT); + } } if ([mode isEqualToString:imeModeCHS]) { @@ -85,13 +89,14 @@ static void LTLoadAssociatedPhrases(vChewingLM &lm) + (void)loadUserPhrases { - gLangModelCHT.loadUserPhrases([[self userPhrasesDataPathCHT] UTF8String], [[self excludedPhrasesDataPathCHT] UTF8String]); - gLangModelCHS.loadUserPhrases([[self userPhrasesDataPathCHS] UTF8String], [[self excludedPhrasesDataPathCHS] UTF8String]); + gLangModelCHT.loadUserPhrases([[self userPhrasesDataPath:imeModeCHT] UTF8String], [[self excludedPhrasesDataPath:imeModeCHT] UTF8String]); + gLangModelCHS.loadUserPhrases([[self userPhrasesDataPath:imeModeCHS] UTF8String], [[self excludedPhrasesDataPath:imeModeCHS] UTF8String]); } + (void)loadUserPhraseReplacement { - gLangModelCHT.loadPhraseReplacementMap([[self phraseReplacementDataPathCHT] UTF8String]); + gLangModelCHT.loadPhraseReplacementMap([[self phraseReplacementDataPath:imeModeCHT] UTF8String]); + gLangModelCHS.loadPhraseReplacementMap([[self phraseReplacementDataPath:imeModeCHS] UTF8String]); } + (void)setupDataModelValueConverter @@ -171,13 +176,22 @@ static void LTLoadAssociatedPhrases(vChewingLM &lm) if (![self checkIfUserDataFolderExists]) { return NO; } - if (![self ensureFileExists:[self userPhrasesDataPathCHT] populateWithTemplate:kUserDataTemplateName extension:kTemplateExtension]) { + if (![self ensureFileExists:[self userPhrasesDataPath:imeModeCHS] populateWithTemplate:kUserDataTemplateName extension:kTemplateExtension]) { return NO; } - if (![self ensureFileExists:[self excludedPhrasesDataPathCHT] populateWithTemplate:kExcludedPhrasesvChewingTemplateName extension:kTemplateExtension]) { + if (![self ensureFileExists:[self userPhrasesDataPath:imeModeCHT] populateWithTemplate:kUserDataTemplateName extension:kTemplateExtension]) { return NO; } - if (![self ensureFileExists:[self phraseReplacementDataPathCHT] populateWithTemplate:kPhraseReplacementTemplateName extension:kTemplateExtension]) { + if (![self ensureFileExists:[self excludedPhrasesDataPath:imeModeCHS] populateWithTemplate:kExcludedPhrasesvChewingTemplateName extension:kTemplateExtension]) { + return NO; + } + if (![self ensureFileExists:[self excludedPhrasesDataPath:imeModeCHT] populateWithTemplate:kExcludedPhrasesvChewingTemplateName extension:kTemplateExtension]) { + return NO; + } + if (![self ensureFileExists:[self phraseReplacementDataPath:imeModeCHS] populateWithTemplate:kPhraseReplacementTemplateName extension:kTemplateExtension]) { + return NO; + } + if (![self ensureFileExists:[self phraseReplacementDataPath:imeModeCHT] populateWithTemplate:kPhraseReplacementTemplateName extension:kTemplateExtension]) { return NO; } return YES; @@ -196,14 +210,14 @@ static void LTLoadAssociatedPhrases(vChewingLM &lm) return NO; } -+ (BOOL)writeUserPhrase:(NSString *)userPhrase ++ (BOOL)writeUserPhrase:(NSString *)userPhrase inputMode:(InputMode)mode; { if (![self checkIfUserLanguageModelFilesExist]) { return NO; } BOOL addLineBreakAtFront = NO; - NSString *path = [self userPhrasesDataPathCHT]; + NSString *path = [self userPhrasesDataPath:mode]; if ([[NSFileManager defaultManager] fileExistsAtPath:path]) { NSError *error = nil; @@ -253,34 +267,22 @@ static void LTLoadAssociatedPhrases(vChewingLM &lm) return userDictPath; } -+ (NSString *)userPhrasesDataPathCHT ++ (NSString *)userPhrasesDataPath:(InputMode)mode; { - return [[self dataFolderPath] stringByAppendingPathComponent:@"userdata-cht.txt"]; + NSString *fileName = [mode isEqualToString:imeModeCHT] ? @"userdata-cht.txt" : @"userdata-chs.txt"; + return [[self dataFolderPath] stringByAppendingPathComponent:fileName]; } -+ (NSString *)userPhrasesDataPathCHS ++ (NSString *)excludedPhrasesDataPath:(InputMode)mode; { - return [[self dataFolderPath] stringByAppendingPathComponent:@"userdata-chs.txt"]; + NSString *fileName = [mode isEqualToString:imeModeCHT] ? @"exclude-phrases-cht.txt" : @"exclude-phrases-chs.txt"; + return [[self dataFolderPath] stringByAppendingPathComponent:fileName]; } -+ (NSString *)excludedPhrasesDataPathCHT ++ (NSString *)phraseReplacementDataPath:(InputMode)mode; { - return [[self dataFolderPath] stringByAppendingPathComponent:@"exclude-phrases-cht.txt"]; -} - -+ (NSString *)excludedPhrasesDataPathCHS -{ - return [[self dataFolderPath] stringByAppendingPathComponent:@"exclude-phrases-chs.txt"]; -} - -+ (NSString *)phraseReplacementDataPathCHT -{ - return [[self dataFolderPath] stringByAppendingPathComponent:@"phrases-replacement-cht.txt"]; -} - -+ (NSString *)phraseReplacementDataPathCHS -{ - return [[self dataFolderPath] stringByAppendingPathComponent:@"phrases-replacement-chs.txt"]; + NSString *fileName = [mode isEqualToString:imeModeCHT] ? @"phrases-replacement-cht.txt" : @"phrases-replacement-chs.txt"; + return [[self dataFolderPath] stringByAppendingPathComponent:fileName]; } + (vChewingLM *)lmCHT @@ -293,19 +295,20 @@ static void LTLoadAssociatedPhrases(vChewingLM &lm) return &gLangModelCHS; } -+ (vChewing::UserOverrideModel *)userOverrideModel ++ (vChewing::UserOverrideModel *)userOverrideModelCHT { - return &gUserOverrideModel; + return &gUserOverrideModelCHT; } -+ (BOOL)phraseReplacementEnabled ++ (vChewing::UserOverrideModel *)userOverrideModelCHS { - return gLangModelCHT.phraseReplacementEnabled(); + return &gUserOverrideModelCHS; } + (void)setPhraseReplacementEnabled:(BOOL)phraseReplacementEnabled { gLangModelCHT.setPhraseReplacementEnabled(phraseReplacementEnabled); + gLangModelCHS.setPhraseReplacementEnabled(phraseReplacementEnabled); } @end diff --git a/Source/Modules/LangModelRelated/mgrLangModel_Privates.h b/Source/Modules/LangModelRelated/mgrLangModel_Privates.h index 103e0fd3..49cd0de8 100644 --- a/Source/Modules/LangModelRelated/mgrLangModel_Privates.h +++ b/Source/Modules/LangModelRelated/mgrLangModel_Privates.h @@ -26,7 +26,8 @@ NS_ASSUME_NONNULL_BEGIN @interface mgrLangModel () @property (class, readonly, nonatomic) vChewing::vChewingLM *lmCHT; @property (class, readonly, nonatomic) vChewing::vChewingLM *lmCHS; -@property (class, readonly, nonatomic) vChewing::UserOverrideModel *userOverrideModel; +@property (class, readonly, nonatomic) vChewing::UserOverrideModel *userOverrideModelCHS; +@property (class, readonly, nonatomic) vChewing::UserOverrideModel *userOverrideModelCHT; @end NS_ASSUME_NONNULL_END