KeyHandler // Miscellaneous function refactorings.
- syncWithPreferences -> ensurePhoneticParser - (BOOL)checkWhetherToneMarkerConfirmsPhoneticReadingBuffer; - (BOOL)chkKeyValidity:(UniChar)value; - (BOOL)isPhoneticReadingBufferEmpty; - (NSString *)getCompositionFromPhoneticReadingBuffer; - (NSString *)getSyllableCompositionFromPhoneticReadingBuffer; - (void)clearPhoneticReadingBuffer; - (void)combinePhoneticReadingBufferKey:(UniChar)charCode; - (void)doBackSpaceToPhoneticReadingBuffer; - (void)removeBuilderAndReset:(BOOL)shouldReset; - (void)createNewBuilder; - (void)setInputModesToLM:(BOOL)isCHS; - (void)syncBaseLMPrefs; - (void)ensurePhoneticParser;
This commit is contained in:
parent
950b4ff941
commit
27438d48aa
|
@ -53,7 +53,7 @@ extern InputMode imeModeNULL;
|
||||||
errorCallback:(void (^)(void))errorCallback
|
errorCallback:(void (^)(void))errorCallback
|
||||||
NS_SWIFT_NAME(handle(input:state:stateCallback:errorCallback:));
|
NS_SWIFT_NAME(handle(input:state:stateCallback:errorCallback:));
|
||||||
|
|
||||||
- (void)syncWithPreferences;
|
- (void)ensurePhoneticParser;
|
||||||
- (void)fixNodeWithValue:(NSString *)value NS_SWIFT_NAME(fixNode(value:));
|
- (void)fixNodeWithValue:(NSString *)value NS_SWIFT_NAME(fixNode(value:));
|
||||||
- (void)clear;
|
- (void)clear;
|
||||||
|
|
||||||
|
@ -62,6 +62,7 @@ extern InputMode imeModeNULL;
|
||||||
|
|
||||||
@property(strong, nonatomic) InputMode inputMode;
|
@property(strong, nonatomic) InputMode inputMode;
|
||||||
@property(weak, nonatomic) id<KeyHandlerDelegate> delegate;
|
@property(weak, nonatomic) id<KeyHandlerDelegate> delegate;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_END
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
|
@ -37,6 +37,11 @@ InputMode imeModeCHS = ctlInputMethod.kIMEModeCHS;
|
||||||
InputMode imeModeCHT = ctlInputMethod.kIMEModeCHT;
|
InputMode imeModeCHT = ctlInputMethod.kIMEModeCHT;
|
||||||
InputMode imeModeNULL = ctlInputMethod.kIMEModeNULL;
|
InputMode imeModeNULL = ctlInputMethod.kIMEModeNULL;
|
||||||
|
|
||||||
|
typedef vChewing::LMInstantiator BaseLM;
|
||||||
|
typedef vChewing::UserOverrideModel UserOverrideLM;
|
||||||
|
typedef Gramambular::BlockReadingBuilder BlockBuilder;
|
||||||
|
typedef Mandarin::BopomofoReadingBuffer PhoneticBuffer;
|
||||||
|
|
||||||
static const double kEpsilon = 0.000001;
|
static const double kEpsilon = 0.000001;
|
||||||
|
|
||||||
static double FindHighestScore(const std::vector<Gramambular::NodeAnchor> &nodes, double epsilon)
|
static double FindHighestScore(const std::vector<Gramambular::NodeAnchor> &nodes, double epsilon)
|
||||||
|
@ -69,16 +74,16 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
@implementation KeyHandler
|
@implementation KeyHandler
|
||||||
{
|
{
|
||||||
// the reading buffer that takes user input
|
// the reading buffer that takes user input
|
||||||
Mandarin::BopomofoReadingBuffer *_bpmfReadingBuffer;
|
PhoneticBuffer *_bpmfReadingBuffer;
|
||||||
|
|
||||||
// language model
|
// language model
|
||||||
vChewing::LMInstantiator *_languageModel;
|
BaseLM *_languageModel;
|
||||||
|
|
||||||
// user override model
|
// user override model
|
||||||
vChewing::UserOverrideModel *_userOverrideModel;
|
UserOverrideLM *_userOverrideModel;
|
||||||
|
|
||||||
// the grid (lattice) builder for the unigrams (and bigrams)
|
// the grid (lattice) builder for the unigrams (and bigrams)
|
||||||
Gramambular::BlockReadingBuilder *_builder;
|
BlockBuilder *_builder;
|
||||||
|
|
||||||
// latest walked path (trellis) using the Viterbi algorithm
|
// latest walked path (trellis) using the Viterbi algorithm
|
||||||
std::vector<Gramambular::NodeAnchor> _walkedNodes;
|
std::vector<Gramambular::NodeAnchor> _walkedNodes;
|
||||||
|
@ -101,40 +106,28 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
|
|
||||||
- (void)setInputMode:(NSString *)value
|
- (void)setInputMode:(NSString *)value
|
||||||
{
|
{
|
||||||
NSString *newInputMode;
|
// 下面這句的「isKindOfClass」是做類型檢查,
|
||||||
vChewing::LMInstantiator *newLanguageModel;
|
// 為了應對出現輸入法 plist 被改壞掉這樣的極端情況。
|
||||||
vChewing::UserOverrideModel *newUserOverrideModel;
|
|
||||||
|
|
||||||
BOOL isCHS = [value isKindOfClass:[NSString class]] && [value isEqual:imeModeCHS];
|
BOOL isCHS = [value isKindOfClass:[NSString class]] && [value isEqual:imeModeCHS];
|
||||||
|
|
||||||
newInputMode = isCHS ? imeModeCHS : imeModeCHT;
|
// 緊接著將新的簡繁輸入模式提報給 ctlInputMethod:
|
||||||
newLanguageModel = isCHS ? [mgrLangModel lmCHS] : [mgrLangModel lmCHT];
|
ctlInputMethod.currentInputMode = isCHS ? imeModeCHS : imeModeCHT;
|
||||||
newUserOverrideModel = isCHS ? [mgrLangModel userOverrideModelCHS] : [mgrLangModel userOverrideModelCHT];
|
|
||||||
|
|
||||||
// Report the current Input Mode to ctlInputMethod:
|
// 拿當前的 _inputMode 與 ctlInputMethod 的提報結果對比,不同的話則套用新設定:
|
||||||
ctlInputMethod.currentInputMode = newInputMode;
|
if (![_inputMode isEqualToString:ctlInputMethod.currentInputMode])
|
||||||
|
|
||||||
// Synchronize the sub-languageModel state settings to the new LM.
|
|
||||||
newLanguageModel->setPhraseReplacementEnabled(mgrPrefs.phraseReplacementEnabled);
|
|
||||||
newLanguageModel->setSymbolEnabled(mgrPrefs.symbolInputEnabled);
|
|
||||||
newLanguageModel->setCNSEnabled(mgrPrefs.cns11643Enabled);
|
|
||||||
|
|
||||||
// Only apply the changes if the value is changed
|
|
||||||
if (![_inputMode isEqualToString:newInputMode])
|
|
||||||
{
|
{
|
||||||
_inputMode = newInputMode;
|
_inputMode = ctlInputMethod.currentInputMode;
|
||||||
_languageModel = newLanguageModel;
|
|
||||||
_userOverrideModel = newUserOverrideModel;
|
|
||||||
|
|
||||||
if (_builder)
|
// Reinitiate language models if necessary
|
||||||
{
|
[self setInputModesToLM:isCHS];
|
||||||
delete _builder;
|
|
||||||
_builder = new Gramambular::BlockReadingBuilder(_languageModel);
|
|
||||||
_builder->setJoinSeparator("-");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_bpmfReadingBuffer->isEmpty())
|
// Synchronize the sub-languageModel state settings to the new LM.
|
||||||
_bpmfReadingBuffer->clear();
|
[self syncBaseLMPrefs];
|
||||||
|
|
||||||
|
[self removeBuilderAndReset:YES];
|
||||||
|
|
||||||
|
if (![self isPhoneticReadingBufferEmpty])
|
||||||
|
[self clearPhoneticReadingBuffer];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +136,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
if (_bpmfReadingBuffer)
|
if (_bpmfReadingBuffer)
|
||||||
delete _bpmfReadingBuffer;
|
delete _bpmfReadingBuffer;
|
||||||
if (_builder)
|
if (_builder)
|
||||||
delete _builder;
|
[self removeBuilderAndReset:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)init
|
- (instancetype)init
|
||||||
|
@ -151,58 +144,13 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_bpmfReadingBuffer = new Mandarin::BopomofoReadingBuffer(Mandarin::BopomofoKeyboardLayout::StandardLayout());
|
[self ensurePhoneticParser];
|
||||||
|
[self setInputMode:ctlInputMethod.currentInputMode];
|
||||||
// create the lattice builder
|
|
||||||
_languageModel = [mgrLangModel lmCHT];
|
|
||||||
_languageModel->setPhraseReplacementEnabled(mgrPrefs.phraseReplacementEnabled);
|
|
||||||
_languageModel->setCNSEnabled(mgrPrefs.cns11643Enabled);
|
|
||||||
_languageModel->setSymbolEnabled(mgrPrefs.symbolInputEnabled);
|
|
||||||
_userOverrideModel = [mgrLangModel userOverrideModelCHT];
|
|
||||||
|
|
||||||
_builder = new Gramambular::BlockReadingBuilder(_languageModel);
|
|
||||||
|
|
||||||
// each Mandarin syllable is separated by a hyphen
|
|
||||||
_builder->setJoinSeparator("-");
|
|
||||||
_inputMode = imeModeCHT;
|
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)syncWithPreferences
|
// NON-SWIFTIFIABLE
|
||||||
{
|
|
||||||
switch (mgrPrefs.mandarinParser)
|
|
||||||
{
|
|
||||||
case MandarinParserOfStandard:
|
|
||||||
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::StandardLayout());
|
|
||||||
break;
|
|
||||||
case MandarinParserOfEten:
|
|
||||||
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::ETenLayout());
|
|
||||||
break;
|
|
||||||
case MandarinParserOfHsu:
|
|
||||||
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::HsuLayout());
|
|
||||||
break;
|
|
||||||
case MandarinParserOfEen26:
|
|
||||||
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::ETen26Layout());
|
|
||||||
break;
|
|
||||||
case MandarinParserOfIBM:
|
|
||||||
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::IBMLayout());
|
|
||||||
break;
|
|
||||||
case MandarinParserOfMiTAC:
|
|
||||||
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::MiTACLayout());
|
|
||||||
break;
|
|
||||||
case MandarinParserOfFakeSeigyou:
|
|
||||||
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::FakeSeigyouLayout());
|
|
||||||
break;
|
|
||||||
case MandarinParserOfHanyuPinyin:
|
|
||||||
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::HanyuPinyinLayout());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::StandardLayout());
|
|
||||||
mgrPrefs.mandarinParser = MandarinParserOfStandard;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)fixNodeWithValue:(NSString *)value
|
- (void)fixNodeWithValue:(NSString *)value
|
||||||
{
|
{
|
||||||
size_t cursorIndex = [self _actualCandidateCursorIndex];
|
size_t cursorIndex = [self _actualCandidateCursorIndex];
|
||||||
|
@ -242,9 +190,10 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NON-SWIFTIFIABLE
|
||||||
- (void)clear
|
- (void)clear
|
||||||
{
|
{
|
||||||
_bpmfReadingBuffer->clear();
|
[self clearPhoneticReadingBuffer];
|
||||||
_builder->clear();
|
_builder->clear();
|
||||||
_walkedNodes.clear();
|
_walkedNodes.clear();
|
||||||
}
|
}
|
||||||
|
@ -360,14 +309,14 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
// MARK: Handle BPMF Keys
|
// MARK: Handle BPMF Keys
|
||||||
|
|
||||||
// see if it's valid BPMF reading
|
// see if it's valid BPMF reading
|
||||||
if (!skipBpmfHandling && _bpmfReadingBuffer->isValidKey((char)charCode))
|
if (!skipBpmfHandling && [self chkKeyValidity:charCode])
|
||||||
{
|
{
|
||||||
_bpmfReadingBuffer->combineKey((char)charCode);
|
[self combinePhoneticReadingBufferKey:charCode];
|
||||||
|
|
||||||
// if we have a tone marker, we have to insert the reading to the
|
// 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
|
// builder in other words, if we don't have a tone marker, we just
|
||||||
// update the composing buffer
|
// update the composing buffer
|
||||||
composeReading = _bpmfReadingBuffer->hasToneMarker();
|
composeReading = [self checkWhetherToneMarkerConfirmsPhoneticReadingBuffer];
|
||||||
if (!composeReading)
|
if (!composeReading)
|
||||||
{
|
{
|
||||||
InputStateInputting *inputting = (InputStateInputting *)[self buildInputtingState];
|
InputStateInputting *inputting = (InputStateInputting *)[self buildInputtingState];
|
||||||
|
@ -378,11 +327,11 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
|
|
||||||
// see if we have composition if Enter/Space is hit and buffer is not empty
|
// see if we have composition if Enter/Space is hit and buffer is not empty
|
||||||
// we use "OR" conditioning so that the tone marker key is also taken into account
|
// we use "OR" conditioning so that the tone marker key is also taken into account
|
||||||
composeReading |= (!_bpmfReadingBuffer->isEmpty() && ([input isSpace] || [input isEnter]));
|
composeReading |= (![self isPhoneticReadingBufferEmpty] && ([input isSpace] || [input isEnter]));
|
||||||
if (composeReading)
|
if (composeReading)
|
||||||
{
|
{
|
||||||
// combine the reading
|
// combine the reading
|
||||||
std::string reading = _bpmfReadingBuffer->syllable().composedString();
|
std::string reading = [[self getSyllableCompositionFromPhoneticReadingBuffer] UTF8String];
|
||||||
|
|
||||||
// see if we have an unigram for this
|
// see if we have an unigram for this
|
||||||
if (!_languageModel->hasUnigramsForKey(reading))
|
if (!_languageModel->hasUnigramsForKey(reading))
|
||||||
|
@ -416,7 +365,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
}
|
}
|
||||||
|
|
||||||
// then update the text
|
// then update the text
|
||||||
_bpmfReadingBuffer->clear();
|
[self clearPhoneticReadingBuffer];
|
||||||
|
|
||||||
InputStateInputting *inputting = (InputStateInputting *)[self buildInputtingState];
|
InputStateInputting *inputting = (InputStateInputting *)[self buildInputtingState];
|
||||||
inputting.poppedText = poppedText;
|
inputting.poppedText = poppedText;
|
||||||
|
@ -461,7 +410,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Calling candidate window using Space or Down or PageUp / PageDn.
|
// MARK: Calling candidate window using Space or Down or PageUp / PageDn.
|
||||||
if (_bpmfReadingBuffer->isEmpty() && [state isKindOfClass:[InputStateNotEmpty class]] &&
|
if ([self isPhoneticReadingBufferEmpty] && [state isKindOfClass:[InputStateNotEmpty class]] &&
|
||||||
([input isExtraChooseCandidateKey] || [input isExtraChooseCandidateKeyReverse] || [input isSpace] ||
|
([input isExtraChooseCandidateKey] || [input isExtraChooseCandidateKeyReverse] || [input isSpace] ||
|
||||||
[input isPageDown] || [input isPageUp] || [input isTab] ||
|
[input isPageDown] || [input isPageUp] || [input isTab] ||
|
||||||
(input.useVerticalMode && ([input isVerticalModeOnlyChooseCandidateKey]))))
|
(input.useVerticalMode && ([input isVerticalModeOnlyChooseCandidateKey]))))
|
||||||
|
@ -561,7 +510,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
{
|
{
|
||||||
if (_languageModel->hasUnigramsForKey("_punctuation_list"))
|
if (_languageModel->hasUnigramsForKey("_punctuation_list"))
|
||||||
{
|
{
|
||||||
if (_bpmfReadingBuffer->isEmpty())
|
if ([self isPhoneticReadingBufferEmpty])
|
||||||
{
|
{
|
||||||
_builder->insertReadingAtCursor(string("_punctuation_list"));
|
_builder->insertReadingAtCursor(string("_punctuation_list"));
|
||||||
NSString *poppedText = [self _popOverflowComposingTextAndWalk];
|
NSString *poppedText = [self _popOverflowComposingTextAndWalk];
|
||||||
|
@ -643,7 +592,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
// still nothing, then we update the composing buffer (some app has strange behavior if we don't do this, "thinking"
|
// still nothing, then we update the composing buffer (some app has strange behavior if we don't do this, "thinking"
|
||||||
// the key is not actually consumed) 砍掉這一段會導致「F1-F12
|
// the key is not actually consumed) 砍掉這一段會導致「F1-F12
|
||||||
// 按鍵干擾組字區」的問題。暫時只能先恢復這段,且補上偵錯彙報機制,方便今後排查故障。
|
// 按鍵干擾組字區」的問題。暫時只能先恢復這段,且補上偵錯彙報機制,方便今後排查故障。
|
||||||
if ([state isKindOfClass:[InputStateNotEmpty class]] || !_bpmfReadingBuffer->isEmpty())
|
if ([state isKindOfClass:[InputStateNotEmpty class]] || ![self isPhoneticReadingBufferEmpty])
|
||||||
{
|
{
|
||||||
[IME prtDebugIntel:[NSString
|
[IME prtDebugIntel:[NSString
|
||||||
stringWithFormat:@"Blocked data: charCode: %c, keyCode: %c", charCode, input.keyCode]];
|
stringWithFormat:@"Blocked data: charCode: %c, keyCode: %c", charCode, input.keyCode]];
|
||||||
|
@ -681,9 +630,9 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
// Bopomofo reading, in odds with the expectation of users from
|
// Bopomofo reading, in odds with the expectation of users from
|
||||||
// other platforms
|
// other platforms
|
||||||
|
|
||||||
if (!_bpmfReadingBuffer->isEmpty())
|
if (![self isPhoneticReadingBufferEmpty])
|
||||||
{
|
{
|
||||||
_bpmfReadingBuffer->clear();
|
[self clearPhoneticReadingBuffer];
|
||||||
if (!_builder->length())
|
if (!_builder->length())
|
||||||
{
|
{
|
||||||
InputStateEmpty *empty = [[InputStateEmpty alloc] init];
|
InputStateEmpty *empty = [[InputStateEmpty alloc] init];
|
||||||
|
@ -707,7 +656,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
if (![state isKindOfClass:[InputStateInputting class]])
|
if (![state isKindOfClass:[InputStateInputting class]])
|
||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
if (!_bpmfReadingBuffer->isEmpty())
|
if (![self isPhoneticReadingBufferEmpty])
|
||||||
{
|
{
|
||||||
[IME prtDebugIntel:@"6ED95318"];
|
[IME prtDebugIntel:@"6ED95318"];
|
||||||
errorCallback();
|
errorCallback();
|
||||||
|
@ -764,7 +713,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
if (![state isKindOfClass:[InputStateInputting class]])
|
if (![state isKindOfClass:[InputStateInputting class]])
|
||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
if (!_bpmfReadingBuffer->isEmpty())
|
if (![self isPhoneticReadingBufferEmpty])
|
||||||
{
|
{
|
||||||
[IME prtDebugIntel:@"B3BA5257"];
|
[IME prtDebugIntel:@"B3BA5257"];
|
||||||
errorCallback();
|
errorCallback();
|
||||||
|
@ -820,7 +769,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
if (![state isKindOfClass:[InputStateInputting class]])
|
if (![state isKindOfClass:[InputStateInputting class]])
|
||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
if (!_bpmfReadingBuffer->isEmpty())
|
if (![self isPhoneticReadingBufferEmpty])
|
||||||
{
|
{
|
||||||
[IME prtDebugIntel:@"ABC44080"];
|
[IME prtDebugIntel:@"ABC44080"];
|
||||||
errorCallback();
|
errorCallback();
|
||||||
|
@ -851,7 +800,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
if (![state isKindOfClass:[InputStateInputting class]])
|
if (![state isKindOfClass:[InputStateInputting class]])
|
||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
if (!_bpmfReadingBuffer->isEmpty())
|
if (![self isPhoneticReadingBufferEmpty])
|
||||||
{
|
{
|
||||||
[IME prtDebugIntel:@"9B69908D"];
|
[IME prtDebugIntel:@"9B69908D"];
|
||||||
errorCallback();
|
errorCallback();
|
||||||
|
@ -882,7 +831,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
if (![state isKindOfClass:[InputStateInputting class]])
|
if (![state isKindOfClass:[InputStateInputting class]])
|
||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
if (!_bpmfReadingBuffer->isEmpty())
|
if (![self isPhoneticReadingBufferEmpty])
|
||||||
{
|
{
|
||||||
[IME prtDebugIntel:@"9B6F908D"];
|
[IME prtDebugIntel:@"9B6F908D"];
|
||||||
errorCallback();
|
errorCallback();
|
||||||
|
@ -898,7 +847,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
if (![state isKindOfClass:[InputStateInputting class]])
|
if (![state isKindOfClass:[InputStateInputting class]])
|
||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
if (_bpmfReadingBuffer->isEmpty())
|
if ([self isPhoneticReadingBufferEmpty])
|
||||||
{
|
{
|
||||||
if (_builder->cursorIndex())
|
if (_builder->cursorIndex())
|
||||||
{
|
{
|
||||||
|
@ -914,9 +863,9 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
_bpmfReadingBuffer->backspace();
|
[self doBackSpaceToPhoneticReadingBuffer];
|
||||||
|
|
||||||
if (_bpmfReadingBuffer->isEmpty() && !_builder->length())
|
if ([self isPhoneticReadingBufferEmpty] && !_builder->length())
|
||||||
{
|
{
|
||||||
InputStateEmptyIgnoringPreviousState *empty = [[InputStateEmptyIgnoringPreviousState alloc] init];
|
InputStateEmptyIgnoringPreviousState *empty = [[InputStateEmptyIgnoringPreviousState alloc] init];
|
||||||
stateCallback(empty);
|
stateCallback(empty);
|
||||||
|
@ -936,7 +885,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
if (![state isKindOfClass:[InputStateInputting class]])
|
if (![state isKindOfClass:[InputStateInputting class]])
|
||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
if (_bpmfReadingBuffer->isEmpty())
|
if ([self isPhoneticReadingBufferEmpty])
|
||||||
{
|
{
|
||||||
if (_builder->cursorIndex() != _builder->length())
|
if (_builder->cursorIndex() != _builder->length())
|
||||||
{
|
{
|
||||||
|
@ -1018,7 +967,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
NSString *poppedText;
|
NSString *poppedText;
|
||||||
if (_bpmfReadingBuffer->isEmpty())
|
if ([self isPhoneticReadingBufferEmpty])
|
||||||
{
|
{
|
||||||
_builder->insertReadingAtCursor(customPunctuation);
|
_builder->insertReadingAtCursor(customPunctuation);
|
||||||
poppedText = [self _popOverflowComposingTextAndWalk];
|
poppedText = [self _popOverflowComposingTextAndWalk];
|
||||||
|
@ -1035,7 +984,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
inputting.poppedText = poppedText;
|
inputting.poppedText = poppedText;
|
||||||
stateCallback(inputting);
|
stateCallback(inputting);
|
||||||
|
|
||||||
if (mgrPrefs.useSCPCTypingMode && _bpmfReadingBuffer->isEmpty())
|
if (mgrPrefs.useSCPCTypingMode && [self isPhoneticReadingBufferEmpty])
|
||||||
{
|
{
|
||||||
InputStateChoosingCandidate *candidateState = [self _buildCandidateState:inputting
|
InputStateChoosingCandidate *candidateState = [self _buildCandidateState:inputting
|
||||||
useVerticalMode:useVerticalMode];
|
useVerticalMode:useVerticalMode];
|
||||||
|
@ -1454,7 +1403,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
std::string customPunctuation = punctuationNamePrefix + parser + std::string(1, (char)charCode);
|
std::string customPunctuation = punctuationNamePrefix + parser + std::string(1, (char)charCode);
|
||||||
std::string punctuation = punctuationNamePrefix + std::string(1, (char)charCode);
|
std::string punctuation = punctuationNamePrefix + std::string(1, (char)charCode);
|
||||||
|
|
||||||
BOOL shouldAutoSelectCandidate = _bpmfReadingBuffer->isValidKey((char)charCode) ||
|
BOOL shouldAutoSelectCandidate = [self chkKeyValidity:charCode] ||
|
||||||
_languageModel->hasUnigramsForKey(customPunctuation) ||
|
_languageModel->hasUnigramsForKey(customPunctuation) ||
|
||||||
_languageModel->hasUnigramsForKey(punctuation);
|
_languageModel->hasUnigramsForKey(punctuation);
|
||||||
|
|
||||||
|
@ -1585,7 +1534,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
// and insert the reading text (the Mandarin syllable) in between them;
|
// and insert the reading text (the Mandarin syllable) in between them;
|
||||||
// the reading text is what the user is typing
|
// the reading text is what the user is typing
|
||||||
NSString *head = [composingBuffer substringToIndex:composedStringCursorIndex];
|
NSString *head = [composingBuffer substringToIndex:composedStringCursorIndex];
|
||||||
NSString *reading = [NSString stringWithUTF8String:_bpmfReadingBuffer->composedString().c_str()];
|
NSString *reading = [self getCompositionFromPhoneticReadingBuffer];
|
||||||
NSString *tail = [composingBuffer substringFromIndex:composedStringCursorIndex];
|
NSString *tail = [composingBuffer substringFromIndex:composedStringCursorIndex];
|
||||||
NSString *composedText = [head stringByAppendingString:[reading stringByAppendingString:tail]];
|
NSString *composedText = [head stringByAppendingString:[reading stringByAppendingString:tail]];
|
||||||
NSInteger cursorIndex = composedStringCursorIndex + [reading length];
|
NSInteger cursorIndex = composedStringCursorIndex + [reading length];
|
||||||
|
@ -1627,10 +1576,10 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
// in an ideal world, we can as well let the user type forever,
|
// in an ideal world, we can as well let the user type forever,
|
||||||
// but because the Viterbi algorithm has a complexity of O(N^2),
|
// but because the Viterbi algorithm has a complexity of O(N^2),
|
||||||
// the walk will become slower as the number of nodes increase,
|
// the walk will become slower as the number of nodes increase,
|
||||||
// therefore we need to "pop out" overflown text -- they usually
|
// therefore we need to auto-commit overflown texts which usually
|
||||||
// lose their influence over the whole MLE anyway -- so that when
|
// lose their influence over the whole MLE anyway -- so that when
|
||||||
// the user type along, the already composed text at front will
|
// the user type along, the already composed text in the rear side
|
||||||
// be popped out
|
// of the buffer will be committed (i.e. "popped out").
|
||||||
|
|
||||||
NSString *poppedText = @"";
|
NSString *poppedText = @"";
|
||||||
NSInteger composingBufferSize = mgrPrefs.composingBufferSize;
|
NSInteger composingBufferSize = mgrPrefs.composingBufferSize;
|
||||||
|
@ -1677,6 +1626,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NON-SWIFTIFIABLE
|
||||||
- (size_t)_actualCandidateCursorIndex
|
- (size_t)_actualCandidateCursorIndex
|
||||||
{
|
{
|
||||||
size_t cursorIndex = _builder->cursorIndex();
|
size_t cursorIndex = _builder->cursorIndex();
|
||||||
|
@ -1687,6 +1637,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
return cursorIndex;
|
return cursorIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NON-SWIFTIFIABLE
|
||||||
- (NSArray *)_currentReadings
|
- (NSArray *)_currentReadings
|
||||||
{
|
{
|
||||||
NSMutableArray *readingsArray = [[NSMutableArray alloc] init];
|
NSMutableArray *readingsArray = [[NSMutableArray alloc] init];
|
||||||
|
@ -1696,6 +1647,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
return readingsArray;
|
return readingsArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NON-SWIFTIFIABLE
|
||||||
- (nullable InputState *)buildAssociatePhraseStateWithKey:(NSString *)key useVerticalMode:(BOOL)useVerticalMode
|
- (nullable InputState *)buildAssociatePhraseStateWithKey:(NSString *)key useVerticalMode:(BOOL)useVerticalMode
|
||||||
{
|
{
|
||||||
std::string cppKey = std::string(key.UTF8String);
|
std::string cppKey = std::string(key.UTF8String);
|
||||||
|
@ -1715,4 +1667,126 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - 必須用 ObjCpp 處理的部分: Mandarin
|
||||||
|
|
||||||
|
- (BOOL)chkKeyValidity:(UniChar)charCode
|
||||||
|
{
|
||||||
|
return _bpmfReadingBuffer->isValidKey((char)charCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isPhoneticReadingBufferEmpty
|
||||||
|
{
|
||||||
|
return _bpmfReadingBuffer->isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)clearPhoneticReadingBuffer
|
||||||
|
{
|
||||||
|
_bpmfReadingBuffer->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)combinePhoneticReadingBufferKey:(UniChar)charCode
|
||||||
|
{
|
||||||
|
_bpmfReadingBuffer->combineKey((char)charCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)checkWhetherToneMarkerConfirmsPhoneticReadingBuffer
|
||||||
|
{
|
||||||
|
return _bpmfReadingBuffer->hasToneMarker();
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)getSyllableCompositionFromPhoneticReadingBuffer
|
||||||
|
{
|
||||||
|
return [NSString stringWithUTF8String:_bpmfReadingBuffer->syllable().composedString().c_str()];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)doBackSpaceToPhoneticReadingBuffer
|
||||||
|
{
|
||||||
|
_bpmfReadingBuffer->backspace();
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)getCompositionFromPhoneticReadingBuffer
|
||||||
|
{
|
||||||
|
return [NSString stringWithUTF8String:_bpmfReadingBuffer->composedString().c_str()];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)ensurePhoneticParser
|
||||||
|
{
|
||||||
|
if (_bpmfReadingBuffer)
|
||||||
|
{
|
||||||
|
switch (mgrPrefs.mandarinParser)
|
||||||
|
{
|
||||||
|
case MandarinParserOfStandard:
|
||||||
|
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::StandardLayout());
|
||||||
|
break;
|
||||||
|
case MandarinParserOfEten:
|
||||||
|
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::ETenLayout());
|
||||||
|
break;
|
||||||
|
case MandarinParserOfHsu:
|
||||||
|
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::HsuLayout());
|
||||||
|
break;
|
||||||
|
case MandarinParserOfEen26:
|
||||||
|
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::ETen26Layout());
|
||||||
|
break;
|
||||||
|
case MandarinParserOfIBM:
|
||||||
|
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::IBMLayout());
|
||||||
|
break;
|
||||||
|
case MandarinParserOfMiTAC:
|
||||||
|
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::MiTACLayout());
|
||||||
|
break;
|
||||||
|
case MandarinParserOfFakeSeigyou:
|
||||||
|
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::FakeSeigyouLayout());
|
||||||
|
break;
|
||||||
|
case MandarinParserOfHanyuPinyin:
|
||||||
|
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::HanyuPinyinLayout());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_bpmfReadingBuffer->setKeyboardLayout(Mandarin::BopomofoKeyboardLayout::StandardLayout());
|
||||||
|
mgrPrefs.mandarinParser = MandarinParserOfStandard;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_bpmfReadingBuffer = new Mandarin::BopomofoReadingBuffer(Mandarin::BopomofoKeyboardLayout::StandardLayout());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - 必須用 ObjCpp 處理的部分: Gramambular 等
|
||||||
|
|
||||||
|
- (void)removeBuilderAndReset:(BOOL)shouldReset
|
||||||
|
{
|
||||||
|
if (_builder)
|
||||||
|
{
|
||||||
|
delete _builder;
|
||||||
|
if (shouldReset)
|
||||||
|
[self createNewBuilder];
|
||||||
|
}
|
||||||
|
else if (shouldReset)
|
||||||
|
[self createNewBuilder];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)createNewBuilder
|
||||||
|
{
|
||||||
|
_builder = new Gramambular::BlockReadingBuilder(_languageModel);
|
||||||
|
// Each Mandarin syllable is separated by a hyphen.
|
||||||
|
_builder->setJoinSeparator("-");
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setInputModesToLM:(BOOL)isCHS
|
||||||
|
{
|
||||||
|
_languageModel = isCHS ? [mgrLangModel lmCHS] : [mgrLangModel lmCHT];
|
||||||
|
_userOverrideModel = isCHS ? [mgrLangModel userOverrideModelCHS] : [mgrLangModel userOverrideModelCHT];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)syncBaseLMPrefs
|
||||||
|
{
|
||||||
|
if (_languageModel)
|
||||||
|
{
|
||||||
|
_languageModel->setPhraseReplacementEnabled(mgrPrefs.phraseReplacementEnabled);
|
||||||
|
_languageModel->setSymbolEnabled(mgrPrefs.symbolInputEnabled);
|
||||||
|
_languageModel->setCNSEnabled(mgrPrefs.cns11643Enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - 威注音認為有必要單獨拿出來處理的部分。
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -95,7 +95,7 @@ class ctlInputMethod: IMKInputController {
|
||||||
currentClient = client
|
currentClient = client
|
||||||
|
|
||||||
keyHandler.clear()
|
keyHandler.clear()
|
||||||
keyHandler.syncWithPreferences()
|
keyHandler.ensurePhoneticParser()
|
||||||
if let bundleCheckID = (client as? IMKTextInput)?.bundleIdentifier() {
|
if let bundleCheckID = (client as? IMKTextInput)?.bundleIdentifier() {
|
||||||
if bundleCheckID != Bundle.main.bundleIdentifier {
|
if bundleCheckID != Bundle.main.bundleIdentifier {
|
||||||
// Override the keyboard layout to the basic one.
|
// Override the keyboard layout to the basic one.
|
||||||
|
|
|
@ -324,7 +324,7 @@
|
||||||
D4E33D8927A838CF006DB1CF /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = "<group>"; };
|
D4E33D8927A838CF006DB1CF /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
D4E33D8E27A838F0006DB1CF /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
D4E33D8E27A838F0006DB1CF /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||||
D4E569DA27A34CC100AC2CEF /* KeyHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyHandler.h; sourceTree = "<group>"; };
|
D4E569DA27A34CC100AC2CEF /* KeyHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyHandler.h; sourceTree = "<group>"; };
|
||||||
D4E569DB27A34CC100AC2CEF /* KeyHandler.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = KeyHandler.mm; sourceTree = "<group>"; };
|
D4E569DB27A34CC100AC2CEF /* KeyHandler.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = KeyHandler.mm; sourceTree = "<group>"; usesTabs = 0; };
|
||||||
D4F0BBDE279AF1AF0071253C /* ArchiveUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArchiveUtil.swift; sourceTree = "<group>"; };
|
D4F0BBDE279AF1AF0071253C /* ArchiveUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArchiveUtil.swift; sourceTree = "<group>"; };
|
||||||
D4F0BBE0279AF8B30071253C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
D4F0BBE0279AF8B30071253C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
D4F0BBE2279B08900071253C /* Chronosphere.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Chronosphere.h; sourceTree = "<group>"; };
|
D4F0BBE2279B08900071253C /* Chronosphere.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Chronosphere.h; sourceTree = "<group>"; };
|
||||||
|
|
Loading…
Reference in New Issue