From d530aa8ce15c8d147f31cf5d5048af87b5f35b4a Mon Sep 17 00:00:00 2001 From: Bjorn Winckler Date: Thu, 12 Jun 2008 22:22:16 +0200 Subject: [PATCH] Draw modeless selection --- src/MacVim/MMAtsuiTextView.m | 31 +++++++++++ src/MacVim/MMBackend.h | 2 + src/MacVim/MMBackend.m | 13 +++++ src/MacVim/MMTextView.h | 4 +- src/MacVim/MMTextView.m | 119 ++++++++++++++++++++++++++++++++++++------- src/MacVim/MacVim.h | 1 + src/MacVim/gui_macvim.m | 20 ++++---- src/proto/gui_macvim.pro | 2 +- src/ui.c | 4 ++ 9 files changed, 167 insertions(+), 29 deletions(-) diff --git a/src/MacVim/MMAtsuiTextView.m b/src/MacVim/MMAtsuiTextView.m index cbc51eec..b41874ae 100644 --- a/src/MacVim/MMAtsuiTextView.m +++ b/src/MacVim/MMAtsuiTextView.m @@ -96,6 +96,8 @@ enum { - (void)clearAll; - (void)drawInsertionPointAtRow:(int)row column:(int)col shape:(int)shape fraction:(int)percent color:(NSColor *)color; +- (void)drawInvertedRectAtRow:(int)row column:(int)col numRows:(int)nrows + numColumns:(int)ncols; @end @@ -599,6 +601,19 @@ enum { [self drawInsertionPointAtRow:row column:col shape:shape fraction:percent color:[NSColor colorWithRgbInt:color]]; + } else if (DrawInvertedRectDrawType == type) { + int row = *((int*)bytes); bytes += sizeof(int); + int col = *((int*)bytes); bytes += sizeof(int); + int nr = *((int*)bytes); bytes += sizeof(int); + int nc = *((int*)bytes); bytes += sizeof(int); + /*int invert = *((int*)bytes);*/ bytes += sizeof(int); + +#if MM_DEBUG_DRAWING + NSLog(@" Draw inverted rect: row=%d col=%d nrows=%d ncols=%d", + row, col, nr, nc); +#endif + [self drawInvertedRectAtRow:row column:col numRows:nr + numColumns:nc]; } else if (SetCursorPosDrawType == type) { // TODO: This is used for Voice Over support in MMTextView, // MMAtsuiTextView currently does not support Voice Over. @@ -1133,4 +1148,20 @@ enum { } } +- (void)drawInvertedRectAtRow:(int)row column:(int)col numRows:(int)nrows + numColumns:(int)ncols +{ + // TODO: THIS CODE HAS NOT BEEN TESTED! + CGContextRef cgctx = [[NSGraphicsContext currentContext] graphicsPort]; + CGContextSaveGState(cgctx); + CGContextSetBlendMode(cgctx, kCGBlendModeDifference); + CGContextSetRGBFillColor(cgctx, 1.0, 1.0, 1.0, 1.0); + + CGRect rect = { col * cellSize.width, row * cellSize.height, + ncols * cellSize.width, nrows * cellSize.height }; + CGContextFillRect(cgctx, rect); + + CGContextRestoreGState(cgctx); +} + @end // MMAtsuiTextView (Drawing) diff --git a/src/MacVim/MMBackend.h b/src/MacVim/MMBackend.h index b99af3eb..f518b25a 100644 --- a/src/MacVim/MMBackend.h +++ b/src/MacVim/MMBackend.h @@ -71,6 +71,8 @@ scrollBottom:(int)bottom left:(int)left right:(int)right; - (void)drawCursorAtRow:(int)row column:(int)col shape:(int)shape fraction:(int)percent color:(int)color; +- (void)drawInvertedRectAtRow:(int)row column:(int)col numRows:(int)nr + numColumns:(int)nc invert:(int)invert; - (void)update; - (void)flushQueue:(BOOL)force; - (BOOL)waitForInput:(int)milliseconds; diff --git a/src/MacVim/MMBackend.m b/src/MacVim/MMBackend.m index 2f75583e..91a8e098 100644 --- a/src/MacVim/MMBackend.m +++ b/src/MacVim/MMBackend.m @@ -429,6 +429,19 @@ static NSString *MMSymlinkWarningString = [drawData appendBytes:&percent length:sizeof(int)]; } +- (void)drawInvertedRectAtRow:(int)row column:(int)col numRows:(int)nr + numColumns:(int)nc invert:(int)invert +{ + int type = DrawInvertedRectDrawType; + [drawData appendBytes:&type length:sizeof(int)]; + + [drawData appendBytes:&row length:sizeof(int)]; + [drawData appendBytes:&col length:sizeof(int)]; + [drawData appendBytes:&nr length:sizeof(int)]; + [drawData appendBytes:&nc length:sizeof(int)]; + [drawData appendBytes:&invert length:sizeof(int)]; +} + - (void)update { // Tend to the run loop, returning immediately if there are no events diff --git a/src/MacVim/MMTextView.h b/src/MacVim/MMTextView.h index c8f04c29..264f6207 100644 --- a/src/MacVim/MMTextView.h +++ b/src/MacVim/MMTextView.h @@ -29,14 +29,14 @@ int preEditColumn; int mouseShape; BOOL antialias; + NSRect *invertRects; + int numInvertRects; } - (id)initWithFrame:(NSRect)frame; - (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; - (void)performBatchDrawWithData:(NSData *)data; - (void)setMouseShape:(int)shape; diff --git a/src/MacVim/MMTextView.m b/src/MacVim/MMTextView.m index 2da91483..2307d166 100644 --- a/src/MacVim/MMTextView.m +++ b/src/MacVim/MMTextView.m @@ -50,6 +50,8 @@ enum { - (void)setCursor; - (BOOL)convertPoint:(NSPoint)point toRow:(int *)row column:(int *)column; - (BOOL)convertRow:(int)row column:(int)column toPoint:(NSPoint *)point; +- (BOOL)convertRow:(int)row column:(int)column numRows:(int)nr + numColumns:(int)nc toRect:(NSRect *)rect; - (NSRect)trackingRect; - (void)dispatchKeyEvent:(NSEvent *)event; - (MMWindowController *)windowController; @@ -58,6 +60,10 @@ enum { - (void)dragTimerFired:(NSTimer *)timer; - (void)sendKeyDown:(const char *)chars length:(int)len modifiers:(int)flags; - (void)hideMouseCursor; +- (void)drawInsertionPointAtRow:(int)row column:(int)col shape:(int)shape + fraction:(int)percent color:(NSColor *)color; +- (void)drawInvertedRectAtRow:(int)row column:(int)col numRows:(int)nrows + numColumns:(int)ncols invert:(int)invert; @end @@ -130,6 +136,12 @@ enum { markedTextField = nil; } + if (invertRects) { + free(invertRects); + invertRects = NULL; + numInvertRects = 0; + } + [super dealloc]; } @@ -153,23 +165,6 @@ enum { preEditColumn = col; } -- (void)drawInsertionPointAtRow:(int)row column:(int)col shape:(int)shape - fraction:(int)percent color:(NSColor *)color -{ - //NSLog(@"drawInsertionPointAtRow:%d column:%d shape:%d color:%@", - // row, col, shape, color); - - // This only stores where to draw the insertion point, the actual drawing - // is done in drawRect:. - shouldDrawInsertionPoint = YES; - insertionPointRow = row; - insertionPointColumn = col; - insertionPointShape = shape; - insertionPointFraction = percent; - - [self setInsertionPointColor:color]; -} - - (void)hideMarkedTextField { if (markedTextField) { @@ -300,6 +295,19 @@ enum { [self drawInsertionPointAtRow:row column:col shape:shape fraction:percent color:[NSColor colorWithRgbInt:color]]; + } else if (DrawInvertedRectDrawType == type) { + int row = *((int*)bytes); bytes += sizeof(int); + int col = *((int*)bytes); bytes += sizeof(int); + int nr = *((int*)bytes); bytes += sizeof(int); + int nc = *((int*)bytes); bytes += sizeof(int); + int invert = *((int*)bytes); bytes += sizeof(int); + +#if MM_DEBUG_DRAWING + NSLog(@" Draw inverted rect: row=%d col=%d nrows=%d ncols=%d", + row, col, nr, nc); +#endif + [self drawInvertedRectAtRow:row column:col numRows:nr numColumns:nc + invert:invert]; } else if (SetCursorPosDrawType == type) { cursorRow = *((int*)bytes); bytes += sizeof(int); cursorCol = *((int*)bytes); bytes += sizeof(int); @@ -452,6 +460,24 @@ enum { [super drawRect:rect]; + if (invertRects) { + CGContextRef cgctx = (CGContextRef)[context graphicsPort]; + CGContextSaveGState(cgctx); + CGContextSetBlendMode(cgctx, kCGBlendModeDifference); + CGContextSetRGBFillColor(cgctx, 1.0, 1.0, 1.0, 1.0); + + int i; + CGRect *rect = (CGRect*)invertRects; + for (i = 0; i < numInvertRects; ++i) + CGContextFillRect(cgctx, rect[i]); + + CGContextRestoreGState(cgctx); + + free(invertRects); + invertRects = NULL; + numInvertRects = 0; + } + if (shouldDrawInsertionPoint) { MMTextStorage *ts = (MMTextStorage*)[self textStorage]; @@ -1242,6 +1268,23 @@ enum { return YES; } +- (BOOL)convertRow:(int)row column:(int)column numRows:(int)nr + numColumns:(int)nc toRect:(NSRect *)rect +{ + MMTextStorage *ts = (MMTextStorage*)[self textStorage]; + NSSize cellSize = [ts cellSize]; + if (!(rect && cellSize.width > 0 && cellSize.height > 0)) + return NO; + + rect->origin = [self textContainerOrigin]; + rect->origin.x += column * cellSize.width; + rect->origin.y += row * cellSize.height; + rect->size.width = cellSize.width * nc; + rect->size.height = cellSize.height * nr; + + return YES; +} + - (NSRect)trackingRect { NSRect rect = [self frame]; @@ -1392,4 +1435,46 @@ enum { [NSCursor setHiddenUntilMouseMoves:YES]; } +- (void)drawInsertionPointAtRow:(int)row column:(int)col shape:(int)shape + fraction:(int)percent color:(NSColor *)color +{ + //NSLog(@"drawInsertionPointAtRow:%d column:%d shape:%d color:%@", + // row, col, shape, color); + + // This only stores where to draw the insertion point, the actual drawing + // is done in drawRect:. + shouldDrawInsertionPoint = YES; + insertionPointRow = row; + insertionPointColumn = col; + insertionPointShape = shape; + insertionPointFraction = percent; + + [self setInsertionPointColor:color]; +} + +- (void)drawInvertedRectAtRow:(int)row column:(int)col numRows:(int)nrows + numColumns:(int)ncols invert:(int)invert +{ + if (invert) { + // The result should be inverted. + int n = numInvertRects++; + invertRects = reallocf(invertRects, + numInvertRects*sizeof(NSRect)); + if (NULL != invertRects) { + [self convertRow:row column:col numRows:nrows numColumns:ncols + toRect:&invertRects[n]]; + [self setNeedsDisplayInRect:invertRects[n]]; + } else { + n = numInvertRects = 0; + } + } else { + // The result should look normal; all we need to do is to mark + // the rect for redrawing and Cocoa will redraw the text. + NSRect rect; + [self convertRow:row column:col numRows:nrows numColumns:ncols + toRect:&rect]; + [self setNeedsDisplayInRect:rect]; + } +} + @end // MMTextView (Private) diff --git a/src/MacVim/MacVim.h b/src/MacVim/MacVim.h index 5c93c3f9..45f5bb82 100644 --- a/src/MacVim/MacVim.h +++ b/src/MacVim/MacVim.h @@ -176,6 +176,7 @@ enum { InsertLinesDrawType, DrawCursorDrawType, SetCursorPosDrawType, + DrawInvertedRectDrawType, }; enum { diff --git a/src/MacVim/gui_macvim.m b/src/MacVim/gui_macvim.m index 9e22970b..beb5e2e0 100644 --- a/src/MacVim/gui_macvim.m +++ b/src/MacVim/gui_macvim.m @@ -426,6 +426,17 @@ gui_mch_new_colors(void) foreground:gui.def_norm_pixel]; } +/* + * Invert a rectangle from row r, column c, for nr rows and nc columns. + */ + void +gui_mch_invert_rectangle(int r, int c, int nr, int nc, int invert) +{ + [[MMBackend sharedInstance] drawInvertedRectAtRow:r column:c numRows:nr + numColumns:nc invert:invert]; +} + + // -- Tabline --------------------------------------------------------------- @@ -1454,15 +1465,6 @@ gui_mch_iconify(void) } -/* - * Invert a rectangle from row r, column c, for nr rows and nc columns. - */ - void -gui_mch_invert_rectangle(int r, int c, int nr, int nc) -{ -} - - #if defined(FEAT_EVAL) || defined(PROTO) /* * Bring the Vim window to the foreground. diff --git a/src/proto/gui_macvim.pro b/src/proto/gui_macvim.pro index b7ecf6cb..fda7a2b6 100644 --- a/src/proto/gui_macvim.pro +++ b/src/proto/gui_macvim.pro @@ -124,7 +124,7 @@ gui_mch_haskey(char_u *name); void gui_mch_iconify(void); void -gui_mch_invert_rectangle(int r, int c, int nr, int nc); +gui_mch_invert_rectangle(int r, int c, int nr, int nc, int invert); void gui_mch_new_colors(void); void diff --git a/src/ui.c b/src/ui.c index 5e4f69f1..55080161 100644 --- a/src/ui.c +++ b/src/ui.c @@ -1126,7 +1126,11 @@ clip_invert_rectangle(row, col, height, width, invert) { #ifdef FEAT_GUI if (gui.in_use) +# ifdef FEAT_GUI_MACVIM + gui_mch_invert_rectangle(row, col, height, width, invert); +# else gui_mch_invert_rectangle(row, col, height, width); +#endif else #endif screen_draw_rectangle(row, col, height, width, invert); -- 2.11.4.GIT