From 320cf2e3b409fcd20a4c056f485cce7995e89dc5 Mon Sep 17 00:00:00 2001 From: Bjorn Winckler Date: Tue, 13 Nov 2007 19:15:11 +0100 Subject: [PATCH] Add IM control support When the default system keyboard script is non-roman the input manager is automatically switched to a roman keyboard script when going to normal mode. See 'imd', 'imc', 'imi' for some relevant options. MacVim uses an over-the-spot style of IM support. --- src/MacVim/MMBackend.h | 1 + src/MacVim/MMBackend.m | 8 ++++++++ src/MacVim/MMTextView.h | 3 +++ src/MacVim/MMTextView.m | 33 +++++++++++++++++---------------- src/MacVim/MMVimController.m | 3 +++ src/MacVim/MacVim.h | 1 + src/MacVim/MacVim.m | 1 + src/MacVim/gui_macvim.m | 41 +++++++++++++++++++++++++++++++++++++++++ src/Makefile | 2 +- src/vim.h | 3 ++- 10 files changed, 78 insertions(+), 18 deletions(-) diff --git a/src/MacVim/MMBackend.h b/src/MacVim/MMBackend.h index 2f8cc74c..02b959e1 100644 --- a/src/MacVim/MMBackend.h +++ b/src/MacVim/MMBackend.h @@ -106,6 +106,7 @@ - (void)stopBlink; - (void)adjustLinespace:(int)linespace; - (void)activate; +- (void)setPreEditRow:(int)row column:(int)col; - (int)lookupColorWithKey:(NSString *)key; - (BOOL)hasSpecialKeyWithValue:(NSString *)value; diff --git a/src/MacVim/MMBackend.m b/src/MacVim/MMBackend.m index 9dcf64ed..ee21c66b 100644 --- a/src/MacVim/MMBackend.m +++ b/src/MacVim/MMBackend.m @@ -946,6 +946,14 @@ enum { [self queueMessage:ActivateMsgID data:nil]; } +- (void)setPreEditRow:(int)row column:(int)col +{ + NSMutableData *data = [NSMutableData data]; + [data appendBytes:&row length:sizeof(int)]; + [data appendBytes:&col length:sizeof(int)]; + [self queueMessage:SetPreEditPositionMsgID data:data]; +} + - (int)lookupColorWithKey:(NSString *)key { if (!(key && [key length] > 0)) diff --git a/src/MacVim/MMTextView.h b/src/MacVim/MMTextView.h index 69ea8ba0..528d4f0b 100644 --- a/src/MacVim/MMTextView.h +++ b/src/MacVim/MMTextView.h @@ -26,10 +26,13 @@ int insertionPointShape; int insertionPointFraction; NSTextField *markedTextField; + int preEditRow; + int preEditColumn; } - (NSEvent *)lastMouseDownEvent; - (void)setShouldDrawInsertionPoint:(BOOL)on; +- (void)setPreEditRow:(int)row column:(int)col; - (void)drawInsertionPointAtRow:(int)row column:(int)col shape:(int)shape fraction:(int)percent color:(NSColor *)color; - (void)hideMarkedTextField; diff --git a/src/MacVim/MMTextView.m b/src/MacVim/MMTextView.m index d7e7ba27..1495dd1b 100644 --- a/src/MacVim/MMTextView.m +++ b/src/MacVim/MMTextView.m @@ -79,6 +79,12 @@ static NSString *MMKeypadEnterString = @"KA"; shouldDrawInsertionPoint = on; } +- (void)setPreEditRow:(int)row column:(int)col +{ + preEditRow = row; + preEditColumn = col; +} + - (void)drawInsertionPointAtRow:(int)row column:(int)col shape:(int)shape fraction:(int)percent color:(NSColor *)color { @@ -396,7 +402,7 @@ static NSString *MMKeypadEnterString = @"KA"; // Convert coordinates (row,col) -> view -> window base -> screen NSPoint origin; - if (![self convertRow:insertionPointRow+1 column:insertionPointColumn + if (![self convertRow:preEditRow+1 column:preEditColumn toPoint:&origin]) return; origin = [self convertPoint:origin toView:nil]; @@ -427,26 +433,21 @@ static NSString *MMKeypadEnterString = @"KA"; // HACK! Since we always return marked text to have location NSNotFound, // this method will be called with 'range.location == NSNotFound' whenever - // the input manager tries to position a popup window near the insertion - // point. For this reason we compute where the insertion point is and - // return a rect which contains it. + // the input manager tries to position a popup window at the pre-edit + // point. The pre-edit point itself is set by the IM routines in Vim + // (MacVim is notified via the SetPreEditPositionMsgID). if (!(ts && lm && tc) || NSNotFound != range.location) return [super firstRectForCharacterRange:range]; - unsigned charIdx = [ts characterIndexForRow:insertionPointRow - column:insertionPointColumn]; - NSRange glyphRange = - [lm glyphRangeForCharacterRange:NSMakeRange(charIdx,1) - actualCharacterRange:NULL]; - NSRect ipRect = [lm boundingRectForGlyphRange:glyphRange - inTextContainer:tc]; - ipRect.origin.x += [self textContainerOrigin].x; - ipRect.origin.y += [self textContainerOrigin].y + [ts cellSize].height; + NSRect rect = [ts boundingRectForCharacterAtRow:preEditRow + column:preEditColumn]; + rect.origin.x += [self textContainerOrigin].x; + rect.origin.y += [self textContainerOrigin].y + [ts cellSize].height; - ipRect.origin = [self convertPoint:ipRect.origin toView:nil]; - ipRect.origin = [[self window] convertBaseToScreen:ipRect.origin]; + rect.origin = [self convertPoint:rect.origin toView:nil]; + rect.origin = [[self window] convertBaseToScreen:rect.origin]; - return ipRect; + return rect; } - (void)scrollWheel:(NSEvent *)event diff --git a/src/MacVim/MMVimController.m b/src/MacVim/MMVimController.m index b2aa95b4..d436af5f 100644 --- a/src/MacVim/MMVimController.m +++ b/src/MacVim/MMVimController.m @@ -814,6 +814,9 @@ static NSTimeInterval MMResendInterval = 0.5; [[windowController window] setDocumentEdited:NO]; } else if (BuffersModifiedMsgID == msgid) { [[windowController window] setDocumentEdited:YES]; + } else if (SetPreEditPositionMsgID == msgid) { + const int *dim = (const int*)[data bytes]; + [[windowController textView] setPreEditRow:dim[0] column:dim[1]]; } else { NSLog(@"WARNING: Unknown message received (msgid=%d)", msgid); } diff --git a/src/MacVim/MacVim.h b/src/MacVim/MacVim.h index 49031ca9..b07b3333 100644 --- a/src/MacVim/MacVim.h +++ b/src/MacVim/MacVim.h @@ -155,6 +155,7 @@ enum { BuffersNotModifiedMsgID, BuffersModifiedMsgID, AddInputMsgID, + SetPreEditPositionMsgID, }; diff --git a/src/MacVim/MacVim.m b/src/MacVim/MacVim.m index e3e6a9f4..b9a5df8c 100644 --- a/src/MacVim/MacVim.m +++ b/src/MacVim/MacVim.m @@ -68,6 +68,7 @@ char *MessageStrings[] = "BuffersNotModifiedMsgID", "BuffersModifiedMsgID", "AddInputMsgID", + "SetPreEditPositionMsgID", }; diff --git a/src/MacVim/gui_macvim.m b/src/MacVim/gui_macvim.m index 58ecde86..839b8383 100644 --- a/src/MacVim/gui_macvim.m +++ b/src/MacVim/gui_macvim.m @@ -1104,6 +1104,47 @@ mch_set_mouse_shape(int shape) +// -- Input Method ---------------------------------------------------------- + +#if defined(USE_IM_CONTROL) + + void +im_set_position(int row, int col) +{ + // The pre-edit area is a popup window which is displayed by MMTextView. + [[MMBackend sharedInstance] setPreEditRow:row column:col]; +} + + + void +im_set_active(int active) +{ + // Set roman or the system script if 'active' is TRUE or FALSE, + // respectively. + SInt32 systemScript = GetScriptManagerVariable(smSysScript); + + if (!p_imdisable && smRoman != systemScript) + KeyScript(active ? smKeySysScript : smKeyRoman); +} + + + int +im_get_status(void) +{ + // IM is active whenever the current script is the system script and the + // system script isn't roman. (Hence IM can only be active when using + // non-roman scripts.) + SInt32 currentScript = GetScriptManagerVariable(smKeyScript); + SInt32 systemScript = GetScriptManagerVariable(smSysScript); + + return currentScript != smRoman && currentScript == systemScript; +} + +#endif // defined(USE_IM_CONTROL) + + + + // -- Unsorted -------------------------------------------------------------- diff --git a/src/Makefile b/src/Makefile index d7b3852d..7516978c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1233,7 +1233,7 @@ MACVIMGUI_OBJ = objects/gui.o objects/pty.o objects/gui_macvim.o \ MACVIMGUI_DEFS = -DFEAT_GUI_MACVIM -Wall -Wno-unknown-pragmas -pipe MACVIMGUI_IPATH = -I. -Iproto MACVIMGUI_LIBS_DIR = -MACVIMGUI_LIBS1 = -framework Cocoa +MACVIMGUI_LIBS1 = -framework Cocoa -framework Carbon MACVIMGUI_LIBS2 = MACVIMGUI_INSTALL = install_normal MACVIMGUI_TARGETS = diff --git a/src/vim.h b/src/vim.h index 9b25537c..328439a6 100644 --- a/src/vim.h +++ b/src/vim.h @@ -463,7 +463,8 @@ typedef unsigned long u8char_T; /* long should be 32 bits or more */ * Check input method control. */ #if defined(FEAT_XIM) || \ - (defined(FEAT_GUI) && (defined(FEAT_MBYTE_IME) || defined(GLOBAL_IME))) + (defined(FEAT_GUI) && (defined(FEAT_MBYTE_IME) || defined(GLOBAL_IME))) \ + || defined(FEAT_GUI_MACVIM) # define USE_IM_CONTROL #endif -- 2.11.4.GIT