Skip to content

Commit

Permalink
inline placeholder
Browse files Browse the repository at this point in the history
  • Loading branch information
groverlynn committed Aug 18, 2023
1 parent c5f4970 commit 49a60c5
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 45 deletions.
126 changes: 81 additions & 45 deletions SquirrelInputController.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@
@interface SquirrelInputController(Private)
-(void)createSession;
-(void)destroySession;
-(void)rimeConsumeCommittedText;
-(BOOL)rimeConsumeCommittedText;
-(void)rimeUpdate;
-(void)updateAppOptions;
@end

const int N_KEY_ROLL_OVER = 50;

@implementation SquirrelInputController {
id _currentClient;
NSString *_preeditString;
NSMutableAttributedString *_preeditString;
NSAttributedString *_originalString;
NSString *_composedString;
NSRange _selRange;
NSUInteger _caretPos;
NSArray *_candidates;
Expand All @@ -29,6 +30,9 @@ @implementation SquirrelInputController {
NSString *_schemaId;
BOOL _inlinePreedit;
BOOL _inlineCandidate;
// app-specific bug fix
BOOL _inlinePlaceHolder;
BOOL _panellessCommitFix;
// for chord-typing
int _chordKeyCodes[N_KEY_ROLL_OVER];
int _chordModifiers[N_KEY_ROLL_OVER];
Expand All @@ -49,9 +53,6 @@ - (BOOL)handleEvent:(NSEvent*)event client:(id)sender
// Key processing will not continue in that case. In other words the
// system will not deliver a key down event to the application.
// Returning NO means the original key down will be passed on to the client.

_currentClient = sender;

NSUInteger modifiers = event.modifierFlags;

BOOL handled = NO;
Expand All @@ -64,7 +65,7 @@ - (BOOL)handleEvent:(NSEvent*)event client:(id)sender
}
}

NSString* app = [_currentClient bundleIdentifier];
NSString* app = [sender bundleIdentifier];

if (![_currentApp isEqualToString:app]) {
_currentApp = [app copy];
Expand Down Expand Up @@ -319,14 +320,15 @@ -(void)activateServer:(id)sender
if (keyboardLayout) {
[sender overrideKeyboardWithKeyboardNamed:keyboardLayout];
}
_preeditString = @"";
_preeditString = nil;
_originalString = nil;
_composedString = nil;
}

-(instancetype)initWithServer:(IMKServer*)server delegate:(id)delegate client:(id)inputClient
{
//NSLog(@"initWithServer:delegate:client:");
if (self = [super initWithServer:server delegate:delegate client:inputClient]) {
_currentClient = inputClient;
[self createSession];
}
return self;
Expand All @@ -335,7 +337,6 @@ -(instancetype)initWithServer:(IMKServer*)server delegate:(id)delegate client:(i
-(void)deactivateServer:(id)sender
{
//NSLog(@"deactivateServer:");
[NSApp.squirrelAppDelegate.panel hide];
[self commitComposition:sender];
}

Expand All @@ -353,13 +354,9 @@ -(void)deactivateServer:(id)sender
-(void)commitComposition:(id)sender
{
//NSLog(@"commitComposition:");
// commit raw input
if (_session) {
const char* raw_input = rime_get_api()->get_input(_session);
if (raw_input) {
[self commitString: @(raw_input)];
rime_get_api()->clear_composition(_session);
}
[self commitString:[self composedString:sender]];
rime_get_api()->clear_composition(_session);
}
}

Expand Down Expand Up @@ -402,54 +399,85 @@ -(NSArray*)candidates:(id)sender
return _candidates;
}

-(void)dealloc
- (void)hidePalettes
{
[NSApp.squirrelAppDelegate.panel hide];
}

- (void)dealloc
{
[self destroySession];
}

-(void)commitString:(NSString*)string
- (NSRange)selectionRange
{
return NSMakeRange(_caretPos, 0);
}

- (NSRange)replacementRange
{
return self.client.selectedRange;
}

- (void)commitString:(id)string
{
//NSLog(@"commitString:");
[_currentClient insertText:string
replacementRange:NSMakeRange(NSNotFound, 0)];
[self.client insertText:string
replacementRange:self.replacementRange];
[self hidePalettes];

_preeditString = @"";
_composedString = nil;
_originalString = nil;
_preeditString = nil;
}

[NSApp.squirrelAppDelegate.panel hide];
- (void)cancelComposition
{
[self commitString:[self originalString:self.client]];
rime_get_api()->clear_composition(_session);
}

- (void)updateComposition
{
[self.client setMarkedText:_preeditString
selectionRange:self.selectionRange
replacementRange:self.replacementRange];
}

-(void)showPreeditString:(NSString*)preedit
selRange:(NSRange)range
caretPos:(NSUInteger)pos
{
//NSLog(@"showPreeditString: '%@'", preedit);

if ([_preeditString isEqualToString:preedit] &&
_caretPos == pos && _selRange.location == range.location && _selRange.length == range.length)
if ([preedit isEqualToString:_preeditString.string] &&
NSEqualRanges(range, _selRange) && pos == _caretPos) {
if (_inlinePlaceHolder) {
[self updateComposition];
}
return;

_preeditString = preedit;
}
_selRange = range;
_caretPos = pos;

//NSLog(@"selRange.location = %ld, selRange.length = %ld; caretPos = %ld",
// range.location, range.length, pos);
NSDictionary* attrs;
NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] initWithString:preedit];
NSDictionary *attrs;
_preeditString = [[NSMutableAttributedString alloc] initWithString:preedit];
if (range.location > 0) {
NSRange convertedRange = NSMakeRange(0, range.location);
attrs = [self markForStyle:kTSMHiliteConvertedText atRange:convertedRange];
[attrString setAttributes:attrs range:convertedRange];
[_preeditString addAttributes:attrs range:convertedRange];
}
{
NSRange remainingRange = NSMakeRange(range.location, preedit.length - range.location);
attrs = [self markForStyle:kTSMHiliteSelectedRawText atRange:remainingRange];
[attrString setAttributes:attrs range:remainingRange];
if (range.location < pos) {
attrs = [self markForStyle:kTSMHiliteSelectedConvertedText atRange:range];
[_preeditString addAttributes:attrs range:range];
}
[_currentClient setMarkedText:attrString
selectionRange:NSMakeRange(pos, 0)
replacementRange:NSMakeRange(NSNotFound, 0)];

if (MIN(NSMaxRange(range), pos) < preedit.length) {
NSRange rawRange = NSMakeRange(MIN(NSMaxRange(range), pos), preedit.length - MIN(NSMaxRange(range), pos));
attrs = [self markForStyle:kTSMHiliteSelectedRawText atRange:rawRange];
[_preeditString addAttributes:attrs range:rawRange];
}
[self updateComposition];
}

-(void)showPanelWithPreedit:(NSString*)preedit
Expand All @@ -463,7 +491,7 @@ -(void)showPanelWithPreedit:(NSString*)preedit
//NSLog(@"showPanelWithPreedit:...:");
_candidates = candidates;
NSRect inputPos;
[_currentClient attributesForCharacterIndex:0 lineHeightRectangle:&inputPos];
[self.client attributesForCharacterIndex:0 lineHeightRectangle:&inputPos];
SquirrelPanel* panel = NSApp.squirrelAppDelegate.panel;
panel.position = inputPos;
panel.inputController = self;
Expand All @@ -485,7 +513,7 @@ @implementation SquirrelInputController(Private)

-(void)createSession
{
NSString* app = [_currentClient bundleIdentifier];
NSString* app = [self.client bundleIdentifier];
NSLog(@"createSession: %@", app);
_currentApp = [app copy];
_session = rime_get_api()->create_session();
Expand All @@ -508,6 +536,8 @@ -(void)updateAppOptions
NSLog(@"set app option: %@ = %d", key, value);
rime_get_api()->set_option(_session, key.UTF8String, value);
}
_panellessCommitFix = (appOptions[@"panelless_commit_fix"] ? : @(NO)).boolValue;
_inlinePlaceHolder = (appOptions[@"inline_placeholder"] ? : @(NO)).boolValue;
}
}

Expand All @@ -521,15 +551,19 @@ -(void)destroySession
[self clearChord];
}

-(void)rimeConsumeCommittedText
-(BOOL)rimeConsumeCommittedText
{
RIME_STRUCT(RimeCommit, commit);
if (rime_get_api()->get_commit(_session, &commit)) {
NSString *commitText = @(commit.text);
[self showPreeditString:@" " selRange:NSMakeRange(0, 0) caretPos:0];
if (_preeditString.length == 0 && _panellessCommitFix) {
[self showPreeditString:@" " selRange:NSMakeRange(0, 0) caretPos:0];
}
[self commitString:commitText];
rime_get_api()->free_commit(&commit);
return YES;
}
return NO;
}

NSString *substr(const char *str, int length) {
Expand All @@ -542,7 +576,9 @@ -(void)rimeConsumeCommittedText
-(void)rimeUpdate
{
//NSLog(@"rimeUpdate");
[self rimeConsumeCommittedText];
if ([self rimeConsumeCommittedText]) {
return;
}

RIME_STRUCT(RimeStatus, status);
if (rime_get_api()->get_status(_session, &status)) {
Expand Down Expand Up @@ -592,11 +628,11 @@ -(void)rimeUpdate
if (_inlinePreedit) {
[self showPreeditString:preeditText selRange:selRange caretPos:caretPos];
} else {
NSRange empty = {0, 0};
// TRICKY: display a non-empty string to prevent iTerm2 from echoing each character in preedit.
// note this is a full-shape space U+3000; using half shape characters like "..." will result in
// an unstable baseline when composing Chinese characters.
[self showPreeditString:(preedit ? @" " : @"") selRange:empty caretPos:0];
[self showPreeditString:(preedit && _inlinePlaceHolder ? @" " : @"")
selRange:NSMakeRange(0, 0) caretPos:0];
}
}
// update candidates
Expand Down
7 changes: 7 additions & 0 deletions data/squirrel.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ app_options:
com.apple.Terminal:
ascii_mode: true
no_inline: true
inline_placeholder: true
com.googlecode.iterm2:
ascii_mode: true
no_inline: true
Expand All @@ -350,6 +351,7 @@ app_options:
vim_mode: true # 退出VIM插入模式自動切換輸入法狀態
com.apple.dt.Xcode:
ascii_mode: true
no_inline: true
com.barebones.textwrangler:
ascii_mode: true
com.macromates.TextMate.preview:
Expand All @@ -367,9 +369,14 @@ app_options:
no_inline: true
co.zeit.hyper:
ascii_mode: true
org.alacritty:
ascii_mode: true
vim_mode: true
panelless_commit_fix: true
com.google.Chrome:
# 規避 https://github.com/rime/squirrel/issues/435
inline: true
inline_placeholder: true
ru.keepcoder.Telegram:
# 規避 https://github.com/rime/squirrel/issues/475
inline: true

0 comments on commit 49a60c5

Please sign in to comment.