Improve IM support for 10.5

When using "set noimd" remember which input source was used in normal
mode separately from the input source used in insert mode.  This way it
is possible to e.g. use a US layout in normal mode and a non-US layout
in insert mode.

The input source used in normal mode must be ASCII capable or it won't
be remembered -- any input source used in insert mode is remembered.

On 10.4 the IM code is unchanged because 10.4 does not support the Text
Input Source Services.
This commit is contained in:
Bjorn Winckler
2009-07-25 00:25:32 +02:00
parent cbe2f307b1
commit 107a1cf7cc
7 changed files with 129 additions and 8 deletions
+1
View File
@@ -69,6 +69,7 @@ enum { MMMaxCellsPerChar = 2 };
- (void)setMouseShape:(int)shape;
- (void)setAntialias:(BOOL)state;
- (void)setImControl:(BOOL)enable;
- (void)activateIm:(BOOL)enable;
- (BOOL)convertPoint:(NSPoint)point toRow:(int *)row column:(int *)column;
- (NSPoint)pointForRow:(int)row column:(int)col;
- (NSRect)rectForRow:(int)row column:(int)col numRows:(int)nr
+5
View File
@@ -329,6 +329,11 @@ defaultLineHeightForFont(NSFont *font)
[helper setImControl:enable];
}
- (void)activateIm:(BOOL)enable
{
[helper activateIm:enable];
}
- (void)keyDown:(NSEvent *)event
{
[helper keyDown:event];
+1
View File
@@ -33,6 +33,7 @@
- (void)setMouseShape:(int)shape;
- (void)setAntialias:(BOOL)antialias;
- (void)setImControl:(BOOL)enable;
- (void)activateIm:(BOOL)enable;
//
// MMTextStorage methods
+5
View File
@@ -312,6 +312,11 @@
[helper setImControl:enable];
}
- (void)activateIm:(BOOL)enable
{
[helper activateIm:enable];
}
- (NSFont *)font
{
return [(MMTextStorage*)[self textStorage] font];
+10
View File
@@ -10,6 +10,11 @@
#import <Cocoa/Cocoa.h>
#if (MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4)
// Need Carbon for TIS...() functions
#import <Carbon/Carbon.h>
#endif
enum {
// These values are chosen so that the min text view size is not too small
@@ -43,6 +48,10 @@ enum {
int preEditColumn;
BOOL imControl;
BOOL imState;
#if (MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4)
TISInputSourceRef lastImSource;
TISInputSourceRef lastAsciiImSource;
#endif
}
- (void)setTextView:(id)view;
@@ -85,5 +94,6 @@ enum {
- (void)setMarkedRange:(NSRange)range;
- (NSRect)firstRectForCharacterRange:(NSRange)range;
- (void)setImControl:(BOOL)enable;
- (void)activateIm:(BOOL)enable;
@end
+105 -4
View File
@@ -57,6 +57,17 @@ static float MMDragAreaSize = 73.0f;
[markedText release]; markedText = nil;
[markedTextAttributes release]; markedTextAttributes = nil;
#if (MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4)
if (lastAsciiImSource) {
CFRelease(lastAsciiImSource);
lastAsciiImSource = NULL;
}
if (lastImSource) {
CFRelease(lastImSource);
lastImSource = NULL;
}
#endif
[super dealloc];
}
@@ -93,9 +104,6 @@ static float MMDragAreaSize = 73.0f;
// returns from this method without releasing and resetting this reference!
currentEvent = [event retain];
if (imControl)
[self checkImState];
if ([self hasMarkedText]) {
// HACK! Need to redisplay manually otherwise the marked text may not
// be correctly displayed (e.g. it is still visible after pressing Esc
@@ -145,6 +153,11 @@ static float MMDragAreaSize = 73.0f;
if (string)
[self doKeyDown:string];
// NOTE: Check IM state _after_ key has been interpreted or we'll pick up
// the old IM state when it has been switched via a keyboard shortcut.
if (imControl)
[self checkImState];
[currentEvent release];
currentEvent = nil;
}
@@ -698,8 +711,88 @@ static float MMDragAreaSize = 73.0f;
{
// This flag corresponds to the (negation of the) 'imd' option. When
// enabled changes to the input method are detected and forwarded to the
// backend.
// backend. On 10.5 and later we do not forward changes to the input
// method, instead we let Vim be in complete control.
#if (MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4)
// The TIS symbols are weakly linked.
if (NULL != TISCopyCurrentKeyboardInputSource) {
// We get here when compiled on 10.5 and running on 10.5 (or later).
// Save current input source for use when IM is on and get an ASCII
// source for use when IM is off.
if (lastAsciiImSource) CFRelease(lastAsciiImSource);
lastAsciiImSource = TISCopyCurrentASCIICapableKeyboardInputSource();
if (lastImSource) CFRelease(lastImSource);
lastImSource = TISCopyCurrentKeyboardInputSource();
}
#endif
// The imControl flag is only used on 10.4 -- on 10.5 we wait for Vim to
// call activateIm: and never explicitly check if the input source changes.
imControl = enable;
ASLogInfo(@"IM control %sabled", enable ? "en" : "dis");
}
- (void)activateIm:(BOOL)enable
{
ASLogDebug(@"Activate IM=%d", enable);
#if (MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4)
// The TIS symbols are weakly linked.
if (NULL != TISCopyCurrentKeyboardInputSource) {
// We get here when compiled for 10.5 and running on 10.5 (or later)
TISInputSourceRef ref = NULL;
if (enable) {
// Enable IM: switch back to input source used when IM was last on.
if (lastImSource)
ref = lastImSource;
// Remember current input source if it is ASCII capable so we can
// switch back to it when IM is once more disabled.
TISInputSourceRef curRef = TISCopyCurrentKeyboardInputSource();
if (curRef) {
CFBooleanRef boolRef = (CFBooleanRef)TISGetInputSourceProperty(
curRef, kTISPropertyInputSourceIsASCIICapable);
BOOL curIsAscii = boolRef ? CFBooleanGetValue(boolRef) : NO;
if (curIsAscii) {
if (lastAsciiImSource) CFRelease(lastAsciiImSource);
lastAsciiImSource = curRef;
} else {
CFRelease(curRef);
}
}
} else {
// Disable IM: switch back to ASCII input source that was used when
// IM was last off.
if (lastAsciiImSource)
ref = lastAsciiImSource;
// Remember current input source so we can switch back to it when
// IM is once more enabled.
if (lastImSource) CFRelease(lastImSource);
lastImSource = TISCopyCurrentKeyboardInputSource();
}
if (ref) {
ASLogDebug(@"Change input source: %@",
TISGetInputSourceProperty(ref, kTISPropertyInputSourceID));
TISSelectInputSource(ref);
}
return;
}
// We get here when compiled on 10.5 but running on 10.4 -- fall through
// and use old IM code...
#endif
#if (MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4)
// NOTE: The IM code is delegated to the frontend since calling it in
// the backend caused weird bugs (second dock icon appearing etc.).
KeyScript(enable ? smKeySysScript : smKeyRoman);
#endif
}
@end // MMTextViewHelper
@@ -801,6 +894,13 @@ static float MMDragAreaSize = 73.0f;
- (void)checkImState
{
#if (MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4)
#if (MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4)
if (NULL != TISCopyCurrentKeyboardInputSource)
return; // Compiled for 10.4 -- 10.5, running on 10.5
#endif
// Compiled for 10.4 or higher, running on 10.4
// 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.)
@@ -815,6 +915,7 @@ static float MMDragAreaSize = 73.0f;
int msgid = state ? ActivatedImMsgID : DeactivatedImMsgID;
[[self vimController] sendMessage:msgid data:nil];
}
#endif
}
- (void)hideMouseCursor
+2 -4
View File
@@ -807,11 +807,9 @@ static BOOL isUnsafeMessage(int msgid);
flags:[[dict objectForKey:@"flags"] intValue]];
}
} else if (ActivateKeyScriptMsgID == msgid) {
// NOTE: The IM code is delegated to the frontend since calling it in
// the backend caused weird bugs (second dock icon appearing etc.).
KeyScript(smKeySysScript);
[[[windowController vimView] textView] activateIm:YES];
} else if (DeactivateKeyScriptMsgID == msgid) {
KeyScript(smKeyRoman);
[[[windowController vimView] textView] activateIm:NO];
} else if (EnableImControlMsgID == msgid) {
[[[windowController vimView] textView] setImControl:YES];
} else if (DisableImControlMsgID == msgid) {