From aae3a695b997d7b9f3b06e130728e5edd74de8a7 Mon Sep 17 00:00:00 2001 From: Kaoru YOSHIDA Date: Mon, 30 Jun 2008 09:55:27 +0900 Subject: [PATCH] Inline IM Patch --- src/MacVim/MMTextStorage.h | 1 + src/MacVim/MMTextStorage.m | 5 ++ src/MacVim/MMTextView.h | 5 +- src/MacVim/MMTextView.m | 176 ++++++++++++++++++++++++---------------- src/MacVim/MMWindowController.m | 3 - 5 files changed, 114 insertions(+), 76 deletions(-) diff --git a/src/MacVim/MMTextStorage.h b/src/MacVim/MMTextStorage.h index 9cc03104..c75c27df 100644 --- a/src/MacVim/MMTextStorage.h +++ b/src/MacVim/MMTextStorage.h @@ -82,6 +82,7 @@ typedef struct { - (void)setFont:(NSFont *)newFont; - (void)setWideFont:(NSFont *)newFont; - (NSFont *)font; +- (NSFont *)fontWide; - (NSColor *)defaultBackgroundColor; - (NSColor *)defaultForegroundColor; - (NSSize)size; diff --git a/src/MacVim/MMTextStorage.m b/src/MacVim/MMTextStorage.m index 78b71f46..b0b61d5f 100644 --- a/src/MacVim/MMTextStorage.m +++ b/src/MacVim/MMTextStorage.m @@ -750,6 +750,11 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar"; return font; } +- (NSFont*)fontWide +{ + return fontWide; +} + - (NSColor *)defaultBackgroundColor { return defaultBackgroundColor; diff --git a/src/MacVim/MMTextView.h b/src/MacVim/MMTextView.h index 264f6207..1be75f1f 100644 --- a/src/MacVim/MMTextView.h +++ b/src/MacVim/MMTextView.h @@ -24,7 +24,9 @@ int insertionPointColumn; int insertionPointShape; int insertionPointFraction; - NSTextField *markedTextField; + NSRange imRange; + NSDictionary *markedTextAttributes; + NSMutableAttributedString *markedText; int preEditRow; int preEditColumn; int mouseShape; @@ -37,7 +39,6 @@ - (void)setShouldDrawInsertionPoint:(BOOL)on; - (void)setPreEditRow:(int)row column:(int)col; -- (void)hideMarkedTextField; - (void)performBatchDrawWithData:(NSData *)data; - (void)setMouseShape:(int)shape; - (void)setAntialias:(BOOL)antialias; diff --git a/src/MacVim/MMTextView.m b/src/MacVim/MMTextView.m index a3964d12..6cdb7a4d 100644 --- a/src/MacVim/MMTextView.m +++ b/src/MacVim/MMTextView.m @@ -130,10 +130,10 @@ enum { { //NSLog(@"MMTextView dealloc"); - if (markedTextField) { - [[markedTextField window] autorelease]; - [markedTextField release]; - markedTextField = nil; + if (markedText) { + imRange = NSMakeRange(0, 0); + [markedText release]; + markedText = nil; } if (invertRects) { @@ -165,16 +165,6 @@ enum { preEditColumn = col; } -- (void)hideMarkedTextField -{ - if (markedTextField) { - NSWindow *win = [markedTextField window]; - [win close]; - [markedTextField setStringValue:@""]; - } -} - - #define MM_DEBUG_DRAWING 0 - (void)performBatchDrawWithData:(NSData *)data @@ -478,6 +468,45 @@ enum { numInvertRects = 0; } + if ([self hasMarkedText]) { + shouldDrawInsertionPoint = YES; + MMTextStorage *ts = (MMTextStorage*)[self textStorage]; + NSSize size = [self textContainerInset]; + + int len = [markedText length]; + // The following implementation should be re-written with + // more efficient way... + + // Calculate how many wide-font characters can be inserted at + // a first line, and draw those characters. + int cols = ([ts actualColumns] - insertionPointColumn) / 2; + int done = 0; + int lend = cols > len ? len : cols; + NSAttributedString *aString = [markedText attributedSubstringFromRange:NSMakeRange(done, lend)]; + [aString drawAtPoint:NSMakePoint( + insertionPointColumn*[ts cellSize].width + size.width, + insertionPointRow*[ts cellSize].height + size.height)]; + + done = lend; + // Check whether there're charecters that aren't drawn at + // the first line. If everything is already done, the follow + // check fails. + if (done != len) { + int r; + // Calculate How many rows are needed to draw all the left + // characters. + int rows = (len - done) / ([ts actualColumns] / 2) + 1; + for (r = 1; r <= rows; r++) { + lend = len - done > [ts actualColumns] / 2 ? [ts actualColumns] / 2 : len - done; + aString = [markedText attributedSubstringFromRange:NSMakeRange(done, lend)]; + [aString drawAtPoint:NSMakePoint( + size.width, + (insertionPointRow + r)*[ts cellSize].height + size.height)]; + done += lend; + } + } + } + if (shouldDrawInsertionPoint) { MMTextStorage *ts = (MMTextStorage*)[self textStorage]; @@ -485,6 +514,14 @@ enum { column:insertionPointColumn]; ipRect.origin.x += [self textContainerOrigin].x; ipRect.origin.y += [self textContainerOrigin].y; + /* for markedText */ + if ([self hasMarkedText]) { + NSFont *theFont = [markedTextAttributes valueForKey:NSFontAttributeName]; + if (theFont == [ts font]) + ipRect.origin.x += [ts cellSize].width * (imRange.location + imRange.length); + else + ipRect.origin.x += [ts cellSize].width * 2 * (imRange.location + imRange.length); + } if (MMInsertionPointHorizontal == insertionPointShape) { int frac = ([ts cellSize].height * insertionPointFraction + 99)/100; @@ -514,6 +551,7 @@ enum { // NSStringFromRect(ipRect), insertionPointShape, // [self insertionPointColor]); } + #if 0 // this code invalidates the shadow, so we don't // get shifting ghost text on scroll and resize @@ -544,6 +582,16 @@ enum { // // TODO: Figure out a way to disable Cocoa key bindings entirely, without // affecting input management. + [NSCursor setHiddenUntilMouseMoves: YES]; + // When the Input Method is activated, some special key inputs + // should be treated as key inputs for Input Method. + if ([self hasMarkedText]) { + [self unmarkText]; + [super keyDown:event]; + [self setNeedsDisplay: YES]; + return; + } + int flags = [event modifierFlags]; if ((flags & NSControlKeyMask) || ((flags & NSAlternateKeyMask) && (flags & NSFunctionKeyMask))) { @@ -574,7 +622,9 @@ enum { // modifiers are already included and should not be added to the input // buffer using CSI, K_MODIFIER). - [self hideMarkedTextField]; + if([self hasMarkedText]) { + [self unmarkText]; + } NSEvent *event = [NSApp currentEvent]; @@ -724,82 +774,66 @@ enum { - (BOOL)hasMarkedText { //NSLog(@"%s", _cmd); - return markedTextField && [[markedTextField stringValue] length] > 0; + return markedText && [markedText length] > 0; } -- (NSRange)markedRange +- (void) setMarkedTextAttributes: (NSDictionary *) attr { - //NSLog(@"%s", _cmd); - unsigned len = [[markedTextField stringValue] length]; - return NSMakeRange(len > 0 ? 0 : NSNotFound, len); + [markedTextAttributes release]; + [attr retain]; + markedTextAttributes=attr; } + - (void)setMarkedText:(id)text selectedRange:(NSRange)range { //NSLog(@"setMarkedText:'%@' selectedRange:%@", text, // NSStringFromRange(range)); MMTextStorage *ts = (MMTextStorage*)[self textStorage]; - if (!ts) return; - - if (!markedTextField) { - // Create a text field and put it inside a floating panel. This field - // is used to display marked text. - NSSize cellSize = [ts cellSize]; - NSRect cellRect = { 0, 0, cellSize.width, cellSize.height }; - - markedTextField = [[NSTextField alloc] initWithFrame:cellRect]; - [markedTextField setEditable:NO]; - [markedTextField setSelectable:NO]; - [markedTextField setBezeled:NO]; - [markedTextField setBordered:YES]; - - // NOTE: The panel that holds the marked text field is allocated here - // and released in dealloc. No pointer to the panel is kept, instead - // [markedTextField window] is used to access the panel. - NSPanel *panel = [[NSPanel alloc] - initWithContentRect:cellRect - styleMask:NSBorderlessWindowMask|NSUtilityWindowMask - backing:NSBackingStoreBuffered - defer:YES]; - - //[panel setHidesOnDeactivate:NO]; - [panel setFloatingPanel:YES]; - [panel setBecomesKeyOnlyIfNeeded:YES]; - [panel setContentView:markedTextField]; - } + if (!ts) + return; + [self unmarkText]; if (text && [text length] > 0) { - [markedTextField setFont:[ts font]]; - if ([text isKindOfClass:[NSAttributedString class]]) - [markedTextField setAttributedStringValue:text]; - else - [markedTextField setStringValue:text]; - - [markedTextField sizeToFit]; - NSSize size = [markedTextField frame].size; - - // Convert coordinates (row,col) -> view -> window base -> screen - NSPoint origin; - if (![self convertRow:preEditRow+1 column:preEditColumn - toPoint:&origin]) - return; - origin = [self convertPoint:origin toView:nil]; - origin = [[self window] convertBaseToScreen:origin]; + if ([text isKindOfClass:[NSAttributedString class]]) { + [self setMarkedTextAttributes: + [NSDictionary dictionaryWithObjectsAndKeys: + [ts fontWide], NSFontAttributeName, + [ts defaultBackgroundColor], NSBackgroundColorAttributeName, + [ts defaultForegroundColor], NSForegroundColorAttributeName, + [NSNumber numberWithInt:1], NSUnderlineStyleAttributeName, + nil]]; + markedText=[[NSMutableAttributedString alloc] initWithString:[text string] + attributes:markedTextAttributes]; + } else { + [self setMarkedTextAttributes: + [NSDictionary dictionaryWithObjectsAndKeys: + [ts font], NSFontAttributeName, + [ts defaultBackgroundColor], NSBackgroundColorAttributeName, + [ts defaultForegroundColor], NSForegroundColorAttributeName, + [NSNumber numberWithInt:1], NSUnderlineStyleAttributeName, + nil]]; + markedText=[[NSMutableAttributedString alloc] initWithString:text + attributes:markedTextAttributes]; + } - NSWindow *win = [markedTextField window]; - [win setContentSize:size]; - [win setFrameOrigin:origin]; - [win orderFront:nil]; - } else { - [self hideMarkedTextField]; + imRange = range; + if (range.length) { + [markedText addAttribute:NSUnderlineStyleAttributeName + value:[NSNumber numberWithInt:2] + range:range]; + } + [self setNeedsDisplay: YES]; } } - (void)unmarkText { //NSLog(@"%s", _cmd); - [self hideMarkedTextField]; + imRange = NSMakeRange(0, 0); + [markedText release]; + markedText = nil; } - (NSRect)firstRectForCharacterRange:(NSRange)range diff --git a/src/MacVim/MMWindowController.m b/src/MacVim/MMWindowController.m index c7a86e79..7fb78684 100644 --- a/src/MacVim/MMWindowController.m +++ b/src/MacVim/MMWindowController.m @@ -668,9 +668,6 @@ - (void)windowDidResignMain:(NSNotification *)notification { [vimController sendMessage:LostFocusMsgID data:nil]; - - if ([vimView textView]) - [[vimView textView] hideMarkedTextField]; } - (BOOL)windowShouldClose:(id)sender -- 2.11.4.GIT