Skip to content
Browse files

Extract the candidate handler; handle subtleties of vertical text mode.

Now both Left and Right can be used as choose-candidate key. Also the
candidate window now doesn't obscure the vertical text being typed by
moving to the right to the vertical text. Because of this, Left key
feels strange. Adding Right key should give a better mental model.
  • Loading branch information...
1 parent 42aa3ad commit a1bc443b2b5a5363982fd9204c93a881ffcc120b @lukhnos lukhnos committed May 6, 2012
Showing with 175 additions and 152 deletions.
  1. +175 −152 Source/InputMethodController.mm
View
327 Source/InputMethodController.mm
@@ -118,6 +118,9 @@ - (NSString *)neighborTrigramString;
- (void)_performDeferredSaveUserCandidatesDictionary;
- (void)saveUserCandidatesDictionary;
- (void)_showCandidateWindowUsingVerticalMode:(BOOL)useVerticalMode client:(id)client;
+
+- (void)beep;
+- (BOOL)handleCandidateEventWithInputText:(NSString *)inputText charCode:(UniChar)charCode keyCode:(NSUInteger)keyCode;
@end
// sort helper
@@ -457,29 +460,160 @@ - (void)beep
NSBeep();
}
+- (BOOL)handleCandidateEventWithInputText:(NSString *)inputText charCode:(UniChar)charCode keyCode:(NSUInteger)keyCode
+{
+ if (charCode == 27) {
+ gCurrentCandidateController.visible = NO;
+ [_candidates removeAllObjects];
+ return YES;
+ }
+ else if (charCode == 13 || keyCode == 127) {
+ [self candidateController:gCurrentCandidateController didSelectCandidateAtIndex:gCurrentCandidateController.selectedCandidateIndex];
+ return YES;
+ }
+ else if (charCode == 32 || keyCode == kPageDownKeyCode) {
+ BOOL updated = [gCurrentCandidateController showNextPage];
+ if (!updated) {
+ [self beep];
+ }
+ return YES;
+ }
+ else if (keyCode == kPageUpKeyCode) {
+ BOOL updated = [gCurrentCandidateController showPreviousPage];
+ if (!updated) {
+ [self beep];
+ }
+ return YES;
+ }
+ else if (keyCode == kLeftKeyCode) {
+ if ([gCurrentCandidateController isKindOfClass:[VTHorizontalCandidateController class]]) {
+ BOOL updated = [gCurrentCandidateController highlightPreviousCandidate];
+ if (!updated) {
+ [self beep];
+ }
+ return YES;
+ }
+ else {
+ [self beep];
+ return YES;
+ }
+ }
+ else if (keyCode == kRightKeyCode) {
+ if ([gCurrentCandidateController isKindOfClass:[VTHorizontalCandidateController class]]) {
+ BOOL updated = [gCurrentCandidateController highlightNextCandidate];
+ if (!updated) {
+ [self beep];
+ }
+ return YES;
+ }
+ else {
+ [self beep];
+ return YES;
+ }
+ }
+ else if (keyCode == kUpKeyCode) {
+ if ([gCurrentCandidateController isKindOfClass:[VTHorizontalCandidateController class]]) {
+ BOOL updated = [gCurrentCandidateController showPreviousPage];
+ if (!updated) {
+ [self beep];
+ }
+ return YES;
+ }
+ else {
+ BOOL updated = [gCurrentCandidateController highlightPreviousCandidate];
+ if (!updated) {
+ [self beep];
+ }
+ return YES;
+ }
+ }
+ else if (keyCode == kDownKeyCode) {
+ if ([gCurrentCandidateController isKindOfClass:[VTHorizontalCandidateController class]]) {
+ BOOL updated = [gCurrentCandidateController showNextPage];
+ if (!updated) {
+ [self beep];
+ }
+ return YES;
+ }
+ else {
+ BOOL updated = [gCurrentCandidateController highlightNextCandidate];
+ if (!updated) {
+ [self beep];
+ }
+ return YES;
+ }
+ }
+ else if (keyCode == kHomeKeyCode) {
+ if (gCurrentCandidateController.selectedCandidateIndex == 0) {
+ [self beep];
+
+ }
+ else {
+ gCurrentCandidateController.selectedCandidateIndex = 0;
+ }
+
+ return YES;
+ }
+ else if (keyCode == kEndKeyCode && [_candidates count] > 0) {
+ if (gCurrentCandidateController.selectedCandidateIndex == [_candidates count] - 1) {
+ [self beep];
+ }
+ else {
+ gCurrentCandidateController.selectedCandidateIndex = [_candidates count] - 1;
+ }
+
+ return YES;
+ }
+ else {
+
+ NSInteger index = NSNotFound;
+ for (NSUInteger j = 0, c = [gCurrentCandidateController.keyLabels count]; j < c; j++) {
+ if ([inputText compare:[gCurrentCandidateController.keyLabels objectAtIndex:j] options:NSCaseInsensitiveSearch] == NSOrderedSame) {
+ index = j;
+ break;
+ }
+ }
+
+ [gCurrentCandidateController.keyLabels indexOfObject:inputText];
+ if (index != NSNotFound) {
+ NSUInteger candidateIndex = [gCurrentCandidateController candidateIndexAtKeyLabelIndex:index];
+ if (candidateIndex != NSUIntegerMax) {
+ [self candidateController:gCurrentCandidateController didSelectCandidateAtIndex:candidateIndex];
+ return YES;
+ }
+ }
+
+ [self beep];
+ return YES;
+ }
+}
+
- (BOOL)inputText:(NSString*)inputText key:(NSInteger)keyCode modifiers:(NSUInteger)flags client:(id)client
{
NSRect textFrame = NSZeroRect;
NSDictionary *attributes = nil;
+
+ bool composeReading = false;
BOOL useVerticalMode = NO;
+
@try {
attributes = [client attributesForCharacterIndex:0 lineHeightRectangle:&textFrame];
useVerticalMode = [attributes objectForKey:@"IMKTextOrientation"] && [[attributes objectForKey:@"IMKTextOrientation"] integerValue] == 0;
}
@catch (NSException *e) {
- // An exception may raise while using Twitter.app's search filed.
+ // exception may raise while using Twitter.app's search filed.
}
NSInteger cursorForwardKey = useVerticalMode ? kDownKeyCode : kRightKeyCode;
NSInteger cursorBackwardKey = useVerticalMode ? kUpKeyCode : kLeftKeyCode;
NSInteger extraChooseCandidateKey = useVerticalMode ? kLeftKeyCode : kDownKeyCode;
NSInteger absorbedArrowKey = useVerticalMode ? kRightKeyCode : kUpKeyCode;
+ NSInteger verticalModeOnlyChooseCandidateKey = useVerticalMode ? absorbedArrowKey : 0;
// get the unicode character code
UniChar charCode = [inputText length] ? [inputText characterAtIndex:0] : 0;
- if ([[client bundleIdentifier] isEqualToString:@"com.apple.Terminal"] && [NSStringFromClass([client class]) isEqualToString:@"IPMDServerClientWrapper"])
- {
+ if ([[client bundleIdentifier] isEqualToString:@"com.apple.Terminal"] && [NSStringFromClass([client class]) isEqualToString:@"IPMDServerClientWrapper"]) {
// special handling for com.apple.Terminal
_currentDeferredClient = client;
}
@@ -494,160 +628,43 @@ - (BOOL)inputText:(NSString*)inputText key:(NSInteger)keyCode modifiers:(NSUInte
return NO;
}
- bool composeReading = false;
- // caps lock processing : if caps is locked, temporarily disabled bopomofo.
-
- if (charCode == 8 || charCode == 13 ||
- keyCode == absorbedArrowKey || keyCode == extraChooseCandidateKey ||
- keyCode == cursorForwardKey || keyCode == cursorBackwardKey) {
- // Do nothing if backspace is pressed
- } else if (flags & NSAlphaShiftKeyMask){
- // Now process all possible combination, we hope.
- if ([_composingBuffer length]) [self commitComposition:client];
- // First commit everything in the buffer.
- if (flags & NSShiftKeyMask) return NO;
- // when shift is pressed, don't do further processing, since it outputs
- // capital letter anyway.
+ // Caps Lock processing : if Caps Lock is on, temporarily disable bopomofo.
+ if (charCode == 8 || charCode == 13 || keyCode == absorbedArrowKey || keyCode == extraChooseCandidateKey || keyCode == cursorForwardKey || keyCode == cursorBackwardKey) {
+ // do nothing if backspace is pressed -- we ignore the key
+ }
+ else if (flags & NSAlphaShiftKeyMask) {
+ // process all possible combination, we hope.
+ if ([_composingBuffer length]) {
+ [self commitComposition:client];
+ }
+
+ // first commit everything in the buffer.
+ if (flags & NSShiftKeyMask) {
+ return NO;
+ }
+
+ // when shift is pressed, don't do further processing, since it outputs capital letter anyway.
NSString *popedText = [inputText lowercaseString];
[client insertText:popedText replacementRange:NSMakeRange(NSNotFound, NSNotFound)];
return YES;
}
+
if (flags & NSNumericPadKeyMask) {
if (keyCode != kLeftKeyCode && keyCode != kRightKeyCode && keyCode != kDownKeyCode && keyCode != kUpKeyCode && charCode != 32 && isprint(charCode)) {
- if ([_composingBuffer length]) [self commitComposition:client];
+ if ([_composingBuffer length]) {
+ [self commitComposition:client];
+ }
+
NSString *popedText = [inputText lowercaseString];
[client insertText:popedText replacementRange:NSMakeRange(NSNotFound, NSNotFound)];
return YES;
}
}
+ // if we have candidate, it means we need to pass the event to the candidate handler
if ([_candidates count]) {
- if (charCode == 27) {
- gCurrentCandidateController.visible = NO;
- [_candidates removeAllObjects];
- return YES;
- }
- else if (charCode == 13 || keyCode == 127) {
- [self candidateController:gCurrentCandidateController didSelectCandidateAtIndex:gCurrentCandidateController.selectedCandidateIndex];
- return YES;
- }
- else if (charCode == 32 || keyCode == kPageDownKeyCode) {
- BOOL updated = [gCurrentCandidateController showNextPage];
- if (!updated) {
- [self beep];
- }
- return YES;
- }
- else if (keyCode == kPageUpKeyCode) {
- BOOL updated = [gCurrentCandidateController showPreviousPage];
- if (!updated) {
- [self beep];
- }
- return YES;
- }
- else if (keyCode == kLeftKeyCode) {
- if ([gCurrentCandidateController isKindOfClass:[VTHorizontalCandidateController class]]) {
- BOOL updated = [gCurrentCandidateController highlightPreviousCandidate];
- if (!updated) {
- [self beep];
- }
- return YES;
- }
- else {
- [self beep];
- return YES;
- }
- }
- else if (keyCode == kRightKeyCode) {
- if ([gCurrentCandidateController isKindOfClass:[VTHorizontalCandidateController class]]) {
- BOOL updated = [gCurrentCandidateController highlightNextCandidate];
- if (!updated) {
- [self beep];
- }
- return YES;
- }
- else {
- [self beep];
- return YES;
- }
- }
- else if (keyCode == kUpKeyCode) {
- if ([gCurrentCandidateController isKindOfClass:[VTHorizontalCandidateController class]]) {
- BOOL updated = [gCurrentCandidateController showPreviousPage];
- if (!updated) {
- [self beep];
- }
- return YES;
- }
- else {
- BOOL updated = [gCurrentCandidateController highlightPreviousCandidate];
- if (!updated) {
- [self beep];
- }
- return YES;
- }
- }
- else if (keyCode == kDownKeyCode) {
- if ([gCurrentCandidateController isKindOfClass:[VTHorizontalCandidateController class]]) {
- BOOL updated = [gCurrentCandidateController showNextPage];
- if (!updated) {
- [self beep];
- }
- return YES;
- }
- else {
- BOOL updated = [gCurrentCandidateController highlightNextCandidate];
- if (!updated) {
- [self beep];
- }
- return YES;
- }
- }
- else if (keyCode == kHomeKeyCode) {
- if (gCurrentCandidateController.selectedCandidateIndex == 0) {
- [self beep];
-
- }
- else {
- gCurrentCandidateController.selectedCandidateIndex = 0;
- }
-
- return YES;
- }
- else if (keyCode == kEndKeyCode && [_candidates count] > 0) {
- if (gCurrentCandidateController.selectedCandidateIndex == [_candidates count] - 1) {
- [self beep];
- }
- else {
- gCurrentCandidateController.selectedCandidateIndex = [_candidates count] - 1;
- }
-
- return YES;
- }
- else {
-
- NSInteger index = NSNotFound;
- for (NSUInteger j = 0, c = [gCurrentCandidateController.keyLabels count]; j < c; j++) {
- if ([inputText compare:[gCurrentCandidateController.keyLabels objectAtIndex:j] options:NSCaseInsensitiveSearch] == NSOrderedSame) {
- index = j;
- break;
- }
- }
-
- [gCurrentCandidateController.keyLabels indexOfObject:inputText];
- if (index != NSNotFound) {
- NSUInteger candidateIndex = [gCurrentCandidateController candidateIndexAtKeyLabelIndex:index];
- if (candidateIndex != NSUIntegerMax) {
- [self candidateController:gCurrentCandidateController didSelectCandidateAtIndex:candidateIndex];
- return YES;
- }
- }
-
- [self beep];
- return YES;
- }
-
+ return [self handleCandidateEventWithInputText:inputText charCode:charCode keyCode:keyCode];
}
@@ -704,7 +721,7 @@ - (BOOL)inputText:(NSString*)inputText key:(NSInteger)keyCode modifiers:(NSUInte
}
// keyCode 125 = Down, charCode 32 = Space
- if (_bpmfReadingBuffer->isEmpty() && [_composingBuffer length] > 0 && (keyCode == extraChooseCandidateKey || charCode == 32)) {
+ if (_bpmfReadingBuffer->isEmpty() && [_composingBuffer length] > 0 && (keyCode == extraChooseCandidateKey || charCode == 32 || (useVerticalMode && (keyCode == verticalModeOnlyChooseCandidateKey)))) {
if (charCode == 32) {
// if the spacebar is NOT set to be a selection key
if (![[NSUserDefaults standardUserDefaults] boolForKey:kChooseCandidateUsingSpaceKey]) {
@@ -728,25 +745,24 @@ - (BOOL)inputText:(NSString*)inputText key:(NSInteger)keyCode modifiers:(NSUInte
// Esc
if (charCode == 27) {
+ // if reading is not empty, we cancel the reading; Apple's built-in Zhuyin (and the erstwhile Hanin) has a default option that Esc "cancels" the current composed character and revert it to Bopomofo reading, in odds with the expectation of users from other platforms
+
if (_bpmfReadingBuffer->isEmpty()) {
+ // no nee to beep since the event is deliberately triggered by user
+
if (![_composingBuffer length]) {
return NO;
}
-
- //[self beep];
- //如果要按 ESC 的時候都已經知道要取消些啥,不必beep
}
else {
_bpmfReadingBuffer->clear();
}
[self updateClientComposingBuffer:client];
return YES;
- //可能的行為包括 1. 取消組字, 把字吃掉 2. 取消 candidate 選擇, 恢復原來的
- //3. 取消組字,現出注音
}
- // The Right key, note we use keyCode here
+ // handle cursor backward
if (keyCode == cursorBackwardKey) {
if (!_bpmfReadingBuffer->isEmpty()) {
[self beep];
@@ -768,7 +784,7 @@ - (BOOL)inputText:(NSString*)inputText key:(NSInteger)keyCode modifiers:(NSUInte
return YES;
}
- // The Left key, note we use keyCode here
+ // handle cursor forward
if (keyCode == cursorForwardKey) {
if (!_bpmfReadingBuffer->isEmpty()) {
[self beep];
@@ -831,6 +847,7 @@ - (BOOL)inputText:(NSString*)inputText key:(NSInteger)keyCode modifiers:(NSUInte
return YES;
}
+ // punctuation list
if ((char)charCode == '`') {
if (gLanguageModel.hasUnigramsForKey(string("_punctuation_list"))) {
if (_bpmfReadingBuffer->isEmpty()) {
@@ -1110,7 +1127,13 @@ - (void)_showCandidateWindowUsingVerticalMode:(BOOL)useVerticalMode client:(id)c
NSLog(@"%@", exception);
}
- [gCurrentCandidateController setWindowTopLeftPoint:NSMakePoint(lineHeightRect.origin.x, lineHeightRect.origin.y - 4.0) bottomOutOfScreenAdjustmentHeight:lineHeightRect.size.height + 4.0];
+ if (useVerticalMode) {
+ [gCurrentCandidateController setWindowTopLeftPoint:NSMakePoint(lineHeightRect.origin.x + lineHeightRect.size.width + 4.0, lineHeightRect.origin.y - 4.0) bottomOutOfScreenAdjustmentHeight:lineHeightRect.size.height + 4.0];
+ }
+ else {
+ [gCurrentCandidateController setWindowTopLeftPoint:NSMakePoint(lineHeightRect.origin.x, lineHeightRect.origin.y - 4.0) bottomOutOfScreenAdjustmentHeight:lineHeightRect.size.height + 4.0];
+ }
+
gCurrentCandidateController.visible = YES;
}

0 comments on commit a1bc443

Please sign in to comment.
Something went wrong with that request. Please try again.