10
10
#import < IOKit/hid/IOHIDLib.h>
11
11
#import < IOKit/hidsystem/IOHIDLib.h>
12
12
13
- const int N_KEY_ROLL_OVER = 50 ;
13
+ static const int N_KEY_ROLL_OVER = 50 ;
14
14
static NSString *const kFullWidthSpace = @" " ;
15
15
16
16
@implementation SquirrelInputController {
@@ -22,6 +22,7 @@ @implementation SquirrelInputController {
22
22
NSArray <NSString *> *_candidates;
23
23
NSEventModifierFlags _lastModifiers;
24
24
uint _lastEventCount;
25
+ NSUInteger _lastPageNum;
25
26
RimeSessionId _session;
26
27
NSString *_schemaId;
27
28
BOOL _inlinePreedit;
@@ -41,7 +42,8 @@ @implementation SquirrelInputController {
41
42
}
42
43
43
44
static SquirrelInputController *_currentController = nil ;
44
- static NSMapTable <SquirrelInputController *, NSDate *> *_controllerDeactivationTime = NSMapTable .weakToWeakObjectsMapTable;
45
+ static NSMapTable <SquirrelInputController *, NSDate *> *_controllerDeactivationTime =
46
+ NSMapTable .weakToWeakObjectsMapTable;
45
47
46
48
+ (void )setCurrentController : (SquirrelInputController *)controller {
47
49
_currentController = controller;
@@ -212,9 +214,9 @@ - (BOOL)mouseDownOnCharacterIndex:(NSUInteger)index
212
214
if (_inlineCandidate && !_inlinePreedit) {
213
215
return NO ;
214
216
}
215
- [self perform: kSELECT onIndex: kEnd ];
217
+ [self perform: kPROCESS onIndex: kEndKey ];
216
218
} else if (point.x < head.x || index <= 0 ) {
217
- [self perform: kSELECT onIndex: kHome ];
219
+ [self perform: kPROCESS onIndex: kHomeKey ];
218
220
} else {
219
221
[self moveCursor: _caretPos
220
222
toPosition: index
@@ -240,17 +242,30 @@ void set_CapsLock_LED_state(bool target_state) {
240
242
241
243
- (BOOL )processKey : (int )rime_keycode
242
244
modifiers : (int )rime_modifiers {
245
+ SquirrelPanel *panel = NSApp .squirrelAppDelegate .panel ;
243
246
// with linear candidate list, arrow keys may behave differently.
244
- Bool is_linear = (Bool)NSApp . squirrelAppDelegate . panel .linear ;
247
+ Bool is_linear = (Bool)panel.linear ;
245
248
if (is_linear != rime_get_api ()->get_option (_session, " _linear" )) {
246
249
rime_get_api ()->set_option (_session, " _linear" , is_linear);
247
250
}
248
251
// with vertical text, arrow keys may behave differently.
249
- Bool is_vertical = (Bool)NSApp . squirrelAppDelegate . panel .vertical ;
252
+ Bool is_vertical = (Bool)panel.vertical ;
250
253
if (is_vertical != rime_get_api ()->get_option (_session, " _vertical" )) {
251
254
rime_get_api ()->set_option (_session, " _vertical" , is_vertical);
252
255
}
253
256
257
+ if (panel.tabular && !rime_modifiers &&
258
+ (is_vertical ? rime_keycode == XK_Left || rime_keycode == XK_Right
259
+ : rime_keycode == XK_Up || rime_keycode == XK_Down)) {
260
+ NSUInteger newIndex = [panel candidateIndexOnDirection: (SquirrelIndex)rime_keycode];
261
+ if (newIndex != NSNotFound ) {
262
+ if (!panel.locked && !panel.expanded && rime_keycode == (is_vertical ? XK_Left : XK_Down)) {
263
+ panel.expanded = YES ;
264
+ }
265
+ return rime_get_api ()->highlight_candidate (_session, newIndex);
266
+ }
267
+ }
268
+
254
269
BOOL handled = (BOOL )rime_get_api ()->process_key (_session, rime_keycode, rime_modifiers);
255
270
// NSLog(@"rime_keycode: 0x%x, rime_modifiers: 0x%x, handled = %d", rime_keycode, rime_modifiers, handled);
256
271
@@ -337,24 +352,26 @@ - (void)perform:(SquirrelAction)action
337
352
onIndex : (SquirrelIndex)index {
338
353
// NSLog(@"perform action: %lu on index: %lu", action, index);
339
354
bool handled = false ;
340
- if (index >= ' !' && index <= ' ~' && (action == kSELECT || action == kHILITE )) {
341
- handled = rime_get_api ()->process_key (_session, (int )index , action == kHILITE ? kAltMask : 0 );
342
- } else if (index >= 0xff08 && index <= 0xffff && action == kSELECT ) {
343
- handled = rime_get_api ()->process_key (_session, (int )index , 0 );
344
- } else if (index >= 0 && index < 10 ) {
345
- switch (action) {
346
- case kDELETE :
347
- handled = rime_get_api ()->delete_candidate_on_current_page (_session, (size_t )index );
348
- break ;
349
- case kSELECT :
350
- handled = rime_get_api ()->select_candidate_on_current_page (_session, (size_t )index );
351
- break ;
352
- case kHILITE :
353
- handled = rime_get_api ()->highlight_candidate_on_current_page (_session, (size_t )index );
354
- break ;
355
- }
355
+ switch (action) {
356
+ case kPROCESS :
357
+ if (index >= 0xff08 && index <= 0xffff ) {
358
+ handled = rime_get_api ()->process_key (_session, (int )index , 0 );
359
+ } else if (index >= kExpandButton && index <= kLockButton ) {
360
+ handled = true ;
361
+ }
362
+ break ;
363
+ case kSELECT :
364
+ handled = rime_get_api ()->select_candidate (_session, index );
365
+ break ;
366
+ case kHIGHLIGHT :
367
+ handled = rime_get_api ()->highlight_candidate (_session, index );
368
+ break ;
369
+ case kDELETE :
370
+ handled = rime_get_api ()->delete_candidate (_session, index );
371
+ break ;
356
372
}
357
373
if (handled) {
374
+ _lastPageNum = NSNotFound ;
358
375
[self rimeUpdate ];
359
376
}
360
377
}
@@ -733,6 +750,7 @@ - (void)showPanelWithPreedit:(NSString *)preedit
733
750
lastPage : (BOOL )lastPage {
734
751
// NSLog(@"showPanelWithPreedit:...:");
735
752
_candidates = candidates;
753
+ _lastPageNum = pageNum;
736
754
SquirrelPanel *panel = NSApp .squirrelAppDelegate .panel ;
737
755
panel.IbeamRect = [self getIbeamRect ];
738
756
if (NSIsEmptyRect (panel.IbeamRect ) && panel.statusMessage .length > 0 ) {
@@ -819,6 +837,7 @@ - (void)rimeUpdate {
819
837
// NSLog(@"rimeUpdate");
820
838
BOOL didCommit = [self rimeConsumeCommittedText ];
821
839
840
+ SquirrelPanel *panel = NSApp .squirrelAppDelegate .panel ;
822
841
RIME_STRUCT (RimeStatus, status);
823
842
if (rime_get_api ()->get_status (_session, &status)) {
824
843
// enable schema specific ui style
@@ -830,11 +849,9 @@ - (void)rimeUpdate {
830
849
[NSApp .squirrelAppDelegate loadSchemaSpecificSettings: _schemaId
831
850
withRimeSession: _session];
832
851
// inline preedit
833
- _inlinePreedit = (NSApp .squirrelAppDelegate .panel .inlinePreedit &&
834
- !rime_get_api ()->get_option (_session, " no_inline" )) ||
852
+ _inlinePreedit = (panel.inlinePreedit && !rime_get_api ()->get_option (_session, " no_inline" )) ||
835
853
rime_get_api ()->get_option (_session, " inline" );
836
- _inlineCandidate = (NSApp .squirrelAppDelegate .panel .inlineCandidate &&
837
- !rime_get_api ()->get_option (_session, " no_inline" ));
854
+ _inlineCandidate = panel.inlineCandidate && !rime_get_api ()->get_option (_session, " no_inline" );
838
855
// if not inline, embed soft cursor in preedit string
839
856
rime_get_api ()->set_option (_session, " soft_cursor" , !_inlinePreedit);
840
857
} else {
@@ -846,9 +863,10 @@ - (void)rimeUpdate {
846
863
847
864
RIME_STRUCT (RimeContext, ctx);
848
865
if (rime_get_api ()->get_context (_session, &ctx)) {
849
- BOOL showingStatus = NSApp . squirrelAppDelegate . panel .statusMessage .length > 0 ;
866
+ BOOL showingStatus = panel.statusMessage .length > 0 ;
850
867
// update raw input
851
868
const char *raw_input = rime_get_api ()->get_input (_session);
869
+ BOOL didCompose = ![_originalString isEqualToString: raw_input ? @(raw_input) : @" " ];
852
870
_originalString = raw_input ? @(raw_input) : @" " ;
853
871
854
872
// update preedit text
@@ -873,7 +891,31 @@ - (void)rimeUpdate {
873
891
NSUInteger end = UTF8LengthToUTF16Length (preedit, ctx.composition .sel_end );
874
892
NSUInteger caretPos = UTF8LengthToUTF16Length (preedit, ctx.composition .cursor_pos );
875
893
NSUInteger length = UTF8LengthToUTF16Length (preedit, ctx.composition .length );
876
- NSUInteger numCandidate = (NSUInteger )ctx.menu .num_candidates ;
894
+ NSUInteger numCandidates = (NSUInteger )ctx.menu .num_candidates ;
895
+ NSUInteger pageNum = (NSUInteger )ctx.menu .page_no ;
896
+ NSUInteger pageSize = (NSUInteger )ctx.menu .page_size ;
897
+ NSUInteger highlightedIndex = numCandidates == 0 ? NSNotFound :
898
+ (NSUInteger )ctx.menu .highlighted_candidate_index ;
899
+ BOOL isLastPage = (BOOL )ctx.menu .is_last_page ;
900
+
901
+ // update discloser and active line status in gridded layout
902
+ if (panel.tabular && !showingStatus && numCandidates > 0 ) {
903
+ if (didCompose) {
904
+ panel.activePage = 0 ;
905
+ } else if (_lastPageNum != NSNotFound ) {
906
+ if (!panel.locked && panel.expanded && (pageNum | _lastPageNum | highlightedIndex) == 0 ) {
907
+ panel.expanded = NO ;
908
+ } else if (!panel.locked && !panel.expanded && pageNum > 0 && pageNum > _lastPageNum) {
909
+ panel.expanded = YES ;
910
+ }
911
+ if (panel.expanded && pageNum > _lastPageNum && panel.activePage < 4 ) {
912
+ panel.activePage = MIN (panel.activePage + pageNum - _lastPageNum, isLastPage ? 4UL : 3UL );
913
+ } else if (panel.expanded && pageNum < _lastPageNum && panel.activePage > 0 ) {
914
+ panel.activePage = MAX (panel.activePage + pageNum - _lastPageNum, pageNum == 0 ? 0UL : 1UL );
915
+ }
916
+ }
917
+ highlightedIndex += pageSize * panel.activePage ;
918
+ }
877
919
878
920
if (showingStatus) {
879
921
[self clearBuffer ];
@@ -909,7 +951,7 @@ - (void)rimeUpdate {
909
951
}
910
952
} else {
911
953
if (_inlinePreedit && !_showingSwitcherMenu) {
912
- if (_inlinePlaceholder && preeditText.length == 0 && numCandidate > 0 ) {
954
+ if (_inlinePlaceholder && preeditText.length == 0 && numCandidates > 0 ) {
913
955
[self showPlaceholder: kFullWidthSpace ];
914
956
} else if (!didCommit || preeditText.length > 0 ) {
915
957
[self showPreeditString: preeditText
@@ -925,20 +967,44 @@ - (void)rimeUpdate {
925
967
}
926
968
}
927
969
// update candidates
928
- NSMutableArray *candidates = [[NSMutableArray alloc ] initWithCapacity: numCandidate];
929
- NSMutableArray *comments = [[NSMutableArray alloc ] initWithCapacity: numCandidate];
930
- for (NSUInteger i = 0 ; i < numCandidate; ++i) {
970
+ NSMutableArray *candidates = numCandidates ? [[NSMutableArray alloc ] init ] : nil ;
971
+ NSMutableArray *comments = numCandidates ? [[NSMutableArray alloc ] init ] : nil ;
972
+ if (numCandidates > 0 && panel.expanded && panel.activePage > 0 ) {
973
+ NSUInteger index = pageSize * (pageNum - panel.activePage );
974
+ RimeCandidateListIterator iterator;
975
+ if (rime_get_api ()->candidate_list_from_index (_session, &iterator, (int )index )) {
976
+ NSUInteger endIndex = pageSize * pageNum;
977
+ while (index ++ < endIndex && rime_get_api ()->candidate_list_next (&iterator)) {
978
+ [candidates addObject: @(iterator.candidate.text)];
979
+ [comments addObject: @(iterator.candidate.comment ? : " " )];
980
+ }
981
+ rime_get_api ()->candidate_list_end (&iterator);
982
+ }
983
+ }
984
+ for (NSUInteger i = 0 ; i < numCandidates; ++i) {
931
985
[candidates addObject: @(ctx.menu.candidates[i].text)];
932
986
[comments addObject: @(ctx.menu.candidates[i].comment ? : " " )];
933
987
}
988
+ if (numCandidates > 0 && panel.expanded && panel.activePage < 5 ) {
989
+ NSUInteger index = pageSize * (pageNum + 1 );
990
+ RimeCandidateListIterator iterator;
991
+ if (rime_get_api ()->candidate_list_from_index (_session, &iterator, (int )index )) {
992
+ NSUInteger endIndex = pageSize * (pageNum + 5 - panel.activePage );
993
+ while (index ++ < endIndex && rime_get_api ()->candidate_list_next (&iterator)) {
994
+ [candidates addObject: @(iterator.candidate.text)];
995
+ [comments addObject: @(iterator.candidate.comment ? : " " )];
996
+ }
997
+ rime_get_api ()->candidate_list_end (&iterator);
998
+ }
999
+ }
934
1000
[self showPanelWithPreedit: _inlinePreedit && !_showingSwitcherMenu ? nil : preeditText
935
1001
selRange: NSMakeRange (start, end - start)
936
1002
caretPos: _showingSwitcherMenu ? NSNotFound : caretPos
937
1003
candidates: candidates
938
1004
comments: comments
939
- highlightedIndex: ( NSUInteger )ctx.menu.highlighted_candidate_index
940
- pageNum: ( NSUInteger )ctx.menu.page_no
941
- lastPage: ( BOOL )ctx.menu.is_last_page ];
1005
+ highlightedIndex: highlightedIndex
1006
+ pageNum: pageNum
1007
+ lastPage: isLastPage ];
942
1008
rime_get_api ()->free_context (&ctx);
943
1009
} else {
944
1010
[self hidePalettes ];
0 commit comments