Add IM support to ATSUI renderer

More functionality now shared between ATSUI and Cocoa renderers.
(Some modifications by Bjorn Winckler.)
This commit is contained in:
Kaoru Yoshida
2008-09-24 21:19:24 +02:00
committed by Bjorn Winckler
parent 0b018a5836
commit 52bb6e960f
7 changed files with 502 additions and 194 deletions
+10 -4
View File
@@ -9,20 +9,21 @@
*/
#import <Cocoa/Cocoa.h>
#import "MMTextView.h"
enum { MMMaxCellsPerChar = 2 };
@class MMTextViewHelper;
@interface MMAtsuiTextView : NSView {
@interface MMAtsuiTextView : NSView <NSTextInput> {
// From MMTextStorage
int maxRows, maxColumns;
NSColor *defaultBackgroundColor;
NSColor *defaultForegroundColor;
NSSize cellSize;
NSFont *font;
NSFont *fontWide;
float linespace;
float ascender;
@@ -44,28 +45,33 @@ enum { MMMaxCellsPerChar = 2 };
// MMTextStorage methods
//
- (int)maxRows;
- (int)maxColumns;
- (void)getMaxRows:(int*)rows columns:(int*)cols;
- (void)setMaxRows:(int)rows columns:(int)cols;
- (void)setDefaultColorsBackground:(NSColor *)bgColor
foreground:(NSColor *)fgColor;
- (NSColor *)defaultBackgroundColor;
- (NSColor *)defaultForegroundColor;
- (NSRect)rectForRowsInRange:(NSRange)range;
- (NSRect)rectForColumnsInRange:(NSRange)range;
- (void)setFont:(NSFont *)newFont;
- (void)setWideFont:(NSFont *)newFont;
- (NSFont *)font;
- (NSFont *)fontWide;
- (NSSize)cellSize;
- (void)setLinespace:(float)newLinespace;
//
// MMTextView methods
//
- (void)setShouldDrawInsertionPoint:(BOOL)on;
- (void)setPreEditRow:(int)row column:(int)col;
- (void)hideMarkedTextField;
- (void)setMouseShape:(int)shape;
- (void)setAntialias:(BOOL)state;
- (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
numColumns:(int)nc;
//
// NSTextView methods
+179 -22
View File
@@ -87,7 +87,7 @@
column:(int)col2 color:(NSColor *)color;
- (void)clearAll;
- (void)drawInsertionPointAtRow:(int)row column:(int)col shape:(int)shape
fraction:(int)percent color:(NSColor *)color;
fraction:(int)percent;
- (void)drawInvertedRectAtRow:(int)row column:(int)col numRows:(int)nrows
numColumns:(int)ncols;
@end
@@ -139,6 +139,8 @@ defaultLineHeightForFont(NSFont *font)
- (void)dealloc
{
LOG_DEALLOC
[self disposeAtsuStyles];
[font release]; font = nil;
[defaultBackgroundColor release]; defaultBackgroundColor = nil;
@@ -155,6 +157,11 @@ defaultLineHeightForFont(NSFont *font)
return maxRows;
}
- (int)maxColumns
{
return maxColumns;
}
- (void)getMaxRows:(int*)rows columns:(int*)cols
{
if (rows) *rows = maxRows;
@@ -176,15 +183,22 @@ defaultLineHeightForFont(NSFont *font)
defaultBackgroundColor = bgColor ? [bgColor retain] : nil;
}
// NOTE: The default foreground color isn't actually used for anything, but
// other class instances might want to be able to access it so it is stored
// here.
if (defaultForegroundColor != fgColor) {
[defaultForegroundColor release];
defaultForegroundColor = fgColor ? [fgColor retain] : nil;
}
}
- (NSColor *)defaultBackgroundColor
{
return defaultBackgroundColor;
}
- (NSColor *)defaultForegroundColor
{
return defaultForegroundColor;
}
- (void)setTextContainerInset:(NSSize)size
{
insetSize = size;
@@ -247,6 +261,18 @@ defaultLineHeightForFont(NSFont *font)
- (void)setWideFont:(NSFont *)newFont
{
if (!newFont) {
if (font) [self setWideFont:font];
} else if (newFont != fontWide) {
float pointSize = [newFont pointSize];
NSFontDescriptor *desc = [newFont fontDescriptor];
NSDictionary *dictWide = [NSDictionary
dictionaryWithObject:[NSNumber numberWithFloat:2*cellSize.width]
forKey:NSFontFixedAdvanceAttribute];
desc = [desc fontDescriptorByAddingAttributes:dictWide];
fontWide = [NSFont fontWithDescriptor:desc size:pointSize];
[fontWide retain];
}
}
- (NSFont *)font
@@ -254,6 +280,11 @@ defaultLineHeightForFont(NSFont *font)
return font;
}
- (NSFont *)fontWide
{
return fontWide;
}
- (NSSize)cellSize
{
return cellSize;
@@ -274,17 +305,13 @@ defaultLineHeightForFont(NSFont *font)
- (void)setShouldDrawInsertionPoint:(BOOL)on
{
}
- (void)setPreEditRow:(int)row column:(int)col
{
}
- (void)hideMarkedTextField
{
[helper setPreEditRow:row column:col];
}
- (void)setMouseShape:(int)shape
@@ -297,9 +324,6 @@ defaultLineHeightForFont(NSFont *font)
antialias = state;
}
- (void)keyDown:(NSEvent *)event
{
[helper keyDown:event];
@@ -322,11 +346,32 @@ defaultLineHeightForFont(NSFont *font)
- (BOOL)hasMarkedText
{
return NO;
return [helper hasMarkedText];
}
- (NSRange)markedRange
{
return [helper markedRange];
}
- (NSDictionary *)markedTextAttributes
{
return [helper markedTextAttributes];
}
- (void)setMarkedTextAttributes:(NSDictionary *)attr
{
[helper setMarkedTextAttributes:attr];
}
- (void)setMarkedText:(id)text selectedRange:(NSRange)range
{
[helper setMarkedText:text selectedRange:range];
}
- (void)unmarkText
{
[helper unmarkText];
}
- (void)scrollWheel:(NSEvent *)event
@@ -462,6 +507,63 @@ defaultLineHeightForFont(NSFont *font)
NSPoint pt = { insetSize.width, insetSize.height };
[contentImage compositeToPoint:pt operation:NSCompositeCopy];
if ([self hasMarkedText]) {
int len = [[helper markedText] length];
int rows = 0;
int cols = maxColumns - [helper preEditColumn];
NSFont *theFont = [[self markedTextAttributes]
valueForKey:NSFontAttributeName];
if (theFont == [self fontWide])
cols = cols / 2;
int done = 0;
int lend = cols > len ? len : cols;
NSAttributedString *aString = [[helper markedText]
attributedSubstringFromRange:NSMakeRange(done, lend)];
NSPoint pt = [self pointForRow:[helper preEditRow]
column:[helper preEditColumn]];
[aString drawAtPoint:pt];
done = lend;
if (done != len) {
int r;
rows = (len - done) / (maxColumns / 2) + 1;
for (r = 1; r <= rows; r++) {
lend = len - done > maxColumns / 2
? maxColumns / 2 : len - done;
aString = [[helper markedText] attributedSubstringFromRange:
NSMakeRange(done, lend)];
NSPoint pt = [self pointForRow:[helper preEditRow]+r
column:0];
[aString drawAtPoint:pt];
done += lend;
}
}
rows = maxRows - 1 - [helper preEditRow];
cols = [helper preEditColumn];
if (theFont == fontWide) {
cols += ([helper imRange].location+[helper imRange].length) * 2;
if (cols >= maxColumns - 1) {
rows -= cols / maxColumns;
cols = cols % 2 ? cols % maxColumns + 1 :
cols % maxColumns;
}
} else {
cols += ([helper imRange].location+[helper imRange].length);
if (cols >= maxColumns) {
rows -= cols / maxColumns;
cols = cols % 2 ? cols % maxColumns + 1 :
cols % maxColumns;
}
}
// TODO: Could IM be in "right-left" mode? If so the insertion point
// will be on the wrong side.
[self drawInsertionPointAtRow:rows
column:cols
shape:MMInsertionPointVertical
fraction:25];
}
}
- (BOOL) wantsDefaultClipping
@@ -580,9 +682,9 @@ defaultLineHeightForFont(NSFont *font)
#if MM_DEBUG_DRAWING
NSLog(@" Draw cursor at (%d,%d)", row, col);
#endif
[helper setInsertionPointColor:[NSColor colorWithRgbInt:color]];
[self drawInsertionPointAtRow:row column:col shape:shape
fraction:percent
color:[NSColor colorWithRgbInt:color]];
fraction:percent];
} else if (DrawInvertedRectDrawType == type) {
int row = *((int*)bytes); bytes += sizeof(int);
int col = *((int*)bytes); bytes += sizeof(int);
@@ -742,12 +844,67 @@ defaultLineHeightForFont(NSFont *font)
if (row) *row = floor((point.y-origin.y-1) / cellSize.height);
if (column) *column = floor((point.x-origin.x-1) / cellSize.width);
//NSLog(@"convertPoint:%@ toRow:%d column:%d", NSStringFromPoint(point),
// *row, *column);
return YES;
}
- (NSPoint)pointForRow:(int)row column:(int)col
{
// Return the lower left coordinate of the cell at (row,column).
NSPoint pt;
pt.x = insetSize.width + col*cellSize.width;
pt.y = [self frame].size.height -
(insetSize.height + (1+row)*cellSize.height);
return pt;
}
- (NSRect)rectForRow:(int)row column:(int)col numRows:(int)nr
numColumns:(int)nc
{
// Return the rect for the block which covers the specified rows and
// columns. The lower-left corner is the origin of this rect.
NSRect rect;
rect.origin.x = insetSize.width + col*cellSize.width;
rect.origin.y = [self frame].size.height -
(insetSize.height + (nr+row)*cellSize.height);
rect.size.width = nc*cellSize.width;
rect.size.height = nr*cellSize.height;
return rect;
}
- (NSArray *)validAttributesForMarkedText
{
return nil;
}
- (NSAttributedString *)attributedSubstringFromRange:(NSRange)range
{
return nil;
}
- (NSUInteger)characterIndexForPoint:(NSPoint)point
{
return NSNotFound;
}
- (NSInteger)conversationIdentifier
{
return (NSInteger)self;
}
- (NSRange)selectedRange
{
return [helper imRange];
}
- (NSRect)firstRectForCharacterRange:(NSRange)range
{
return [helper firstRectForCharacterRange:range];
}
@end // MMAtsuiTextView
@@ -861,7 +1018,7 @@ defaultLineHeightForFont(NSFont *font)
- (NSRect)rectFromRow:(int)row1 column:(int)col1
toRow:(int)row2 column:(int)col2
{
NSPoint origin = [self originForRow: row1 column: col1];
NSPoint origin = [self originForRow:row1 column:col1];
return NSMakeRect(origin.x, origin.y,
(col2 + 1 - col1) * cellSize.width,
(row2 + 1 - row1) * cellSize.height);
@@ -879,7 +1036,7 @@ defaultLineHeightForFont(NSFont *font)
//NSLog(@"resizeContentImage");
[contentImage release];
contentImage = [[NSImage alloc] initWithSize:[self textAreaSize]];
[contentImage setFlipped: YES];
[contentImage setFlipped:YES];
imageSize = [self textAreaSize];
}
@@ -1057,7 +1214,7 @@ defaultLineHeightForFont(NSFont *font)
}
- (void)drawInsertionPointAtRow:(int)row column:(int)col shape:(int)shape
fraction:(int)percent color:(NSColor *)color
fraction:(int)percent
{
NSPoint origin = [self originForRow:row column:col];
NSRect rect = NSMakeRect(origin.x, origin.y,
@@ -1078,7 +1235,7 @@ defaultLineHeightForFont(NSFont *font)
rect.size.width = frac;
}
[color set];
[[helper insertionPointColor] set];
if (MMInsertionPointHollow == shape) {
NSFrameRect(rect);
} else {
+7 -7
View File
@@ -19,12 +19,6 @@
int insertionPointColumn;
int insertionPointShape;
int insertionPointFraction;
NSRange imRange;
NSRange markedRange;
NSDictionary *markedTextAttributes;
NSMutableAttributedString *markedText;
int preEditRow;
int preEditColumn;
BOOL antialias;
NSRect *invertRects;
int numInvertRects;
@@ -34,7 +28,6 @@
- (id)initWithFrame:(NSRect)frame;
- (void)setShouldDrawInsertionPoint:(BOOL)on;
- (void)setPreEditRow:(int)row column:(int)col;
- (void)performBatchDrawWithData:(NSData *)data;
- (void)setMouseShape:(int)shape;
@@ -45,16 +38,20 @@
//
- (NSFont *)font;
- (void)setFont:(NSFont *)newFont;
- (NSFont *)fontWide;
- (void)setWideFont:(NSFont *)newFont;
- (NSSize)cellSize;
- (void)setLinespace:(float)newLinespace;
- (int)maxRows;
- (int)maxColumns;
- (void)getMaxRows:(int*)rows columns:(int*)cols;
- (void)setMaxRows:(int)rows columns:(int)cols;
- (NSRect)rectForRowsInRange:(NSRange)range;
- (NSRect)rectForColumnsInRange:(NSRange)range;
- (void)setDefaultColorsBackground:(NSColor *)bgColor
foreground:(NSColor *)fgColor;
- (NSColor *)defaultBackgroundColor;
- (NSColor *)defaultForegroundColor;
- (NSSize)constrainRows:(int *)rows columns:(int *)cols toSize:(NSSize)size;
- (NSSize)desiredSize;
@@ -62,5 +59,8 @@
- (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
numColumns:(int)nc;
@end
+93 -161
View File
@@ -35,13 +35,11 @@
@interface MMTextView (Private)
- (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;
- (MMWindowController *)windowController;
- (MMVimController *)vimController;
- (void)setShouldDrawInsertionPoint:(BOOL)on;
- (void)drawInsertionPointAtRow:(int)row column:(int)col shape:(int)shape
fraction:(int)percent color:(NSColor *)color;
fraction:(int)percent;
- (void)drawInvertedRectAtRow:(int)row column:(int)col numRows:(int)nrows
numColumns:(int)ncols invert:(int)invert;
@end
@@ -103,8 +101,6 @@
helper = [[MMTextViewHelper alloc] init];
[helper setTextView:self];
imRange = NSMakeRange(0, 0);
markedRange = NSMakeRange(0, 0);
// NOTE: If the default changes to 'NO' then the intialization of
// p_antialias in option.c must change as well.
antialias = YES;
@@ -116,12 +112,6 @@
{
LOG_DEALLOC
if (markedText) {
imRange = NSMakeRange(0, 0);
[markedText release];
markedText = nil;
}
if (invertRects) {
free(invertRects);
invertRects = NULL;
@@ -143,15 +133,9 @@
return NO;
}
- (void)setShouldDrawInsertionPoint:(BOOL)on
{
shouldDrawInsertionPoint = on;
}
- (void)setPreEditRow:(int)row column:(int)col
{
preEditRow = row;
preEditColumn = col;
[helper setPreEditRow:row column:col];
}
#define MM_DEBUG_DRAWING 0
@@ -231,13 +215,8 @@
// NOTE: If this is a call to draw the (block) cursor, then cancel
// any previous request to draw the insertion point, or it might
// get drawn as well.
if (flags & DRAW_CURSOR) {
if (flags & DRAW_CURSOR)
[self setShouldDrawInsertionPoint:NO];
//NSColor *color = [NSColor colorWithRgbInt:bg];
//[self drawInsertionPointAtRow:row column:col
// shape:MMInsertionPointBlock
// color:color];
}
[textStorage drawString:string
atRow:row column:col cells:cells
@@ -271,9 +250,9 @@
#if MM_DEBUG_DRAWING
NSLog(@" Draw cursor at (%d,%d)", row, col);
#endif
[helper setInsertionPointColor:[NSColor colorWithRgbInt:color]];
[self drawInsertionPointAtRow:row column:col shape:shape
fraction:percent
color:[NSColor colorWithRgbInt:color]];
fraction:percent];
} else if (DrawInvertedRectDrawType == type) {
int row = *((int*)bytes); bytes += sizeof(int);
int col = *((int*)bytes); bytes += sizeof(int);
@@ -335,6 +314,11 @@
[(MMTextStorage*)[self textStorage] setFont:newFont];
}
- (NSFont *)fontWide
{
return [(MMTextStorage*)[self textStorage] fontWide];
}
- (void)setWideFont:(NSFont *)newFont
{
[(MMTextStorage*)[self textStorage] setWideFont:newFont];
@@ -356,6 +340,12 @@
return [ts maxRows];
}
- (int)maxColumns
{
MMTextStorage *ts = (MMTextStorage *)[self textStorage];
return [ts maxColumns];
}
- (void)getMaxRows:(int*)rows columns:(int*)cols
{
return [(MMTextStorage*)[self textStorage] getMaxRows:rows columns:cols];
@@ -384,6 +374,16 @@
setDefaultColorsBackground:bgColor foreground:fgColor];
}
- (NSColor *)defaultBackgroundColor
{
return [(MMTextStorage*)[self textStorage] defaultBackgroundColor];
}
- (NSColor *)defaultForegroundColor
{
return [(MMTextStorage*)[self textStorage] defaultForegroundColor];
}
- (NSSize)constrainRows:(int *)rows columns:(int *)cols toSize:(NSSize)size
{
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
@@ -449,6 +449,39 @@
return YES;
}
- (NSPoint)pointForRow:(int)row column:(int)col
{
// Return the upper-left coordinate for (row,column).
// NOTE: The coordinate system is flipped!
NSPoint pt = [self textContainerOrigin];
MMTextStorage *ts = (MMTextStorage*)[self textStorage];
NSSize cellSize = [ts cellSize];
pt.x += col * cellSize.width;
pt.y += row * cellSize.height;
return pt;
}
- (NSRect)rectForRow:(int)row column:(int)col numRows:(int)nr
numColumns:(int)nc
{
// Return the rect for the block which covers the specified rows and
// columns. The upper-left corner is the origin of this rect.
// NOTE: The coordinate system is flipped!
NSRect rect;
MMTextStorage *ts = (MMTextStorage*)[self textStorage];
NSSize cellSize = [ts cellSize];
rect.origin = [self textContainerOrigin];
rect.origin.x += col * cellSize.width;
rect.origin.y += row * cellSize.height;
rect.size.width = cellSize.width * nc;
rect.size.height = cellSize.height * nr;
return rect;
}
- (BOOL)isOpaque
{
return NO;
@@ -496,7 +529,7 @@
inset.height -= baseline;
int len = [markedText length];
int len = [[helper markedText] length];
// The following implementation should be re-written with
// more efficient way...
@@ -509,11 +542,11 @@
cols = cols / 2;
int done = 0;
int lend = cols > len ? len : cols;
NSAttributedString *aString = [markedText attributedSubstringFromRange:
NSMakeRange(done, lend)];
NSAttributedString *aString = [[helper markedText]
attributedSubstringFromRange:NSMakeRange(done, lend)];
[aString drawAtPoint:NSMakePoint(
preEditColumn*[ts cellSize].width + inset.width,
preEditRow*[ts cellSize].height + inset.height)];
[helper preEditColumn]*[ts cellSize].width + inset.width,
[helper preEditRow]*[ts cellSize].height + inset.height)];
done = lend;
// Check whether there're charecters that aren't drawn at
@@ -527,11 +560,11 @@
for (r = 1; r <= rows; r++) {
lend = len - done > [ts actualColumns] / 2
? [ts actualColumns] / 2 : len - done;
aString = [markedText attributedSubstringFromRange:
aString = [[helper markedText] attributedSubstringFromRange:
NSMakeRange(done, lend)];
[aString drawAtPoint:NSMakePoint(
inset.width,
(preEditRow + r)*[ts cellSize].height
([helper preEditRow] + r)*[ts cellSize].height
+ inset.height)];
done += lend;
}
@@ -541,8 +574,8 @@
if (shouldDrawInsertionPoint) {
MMTextStorage *ts = (MMTextStorage*)[self textStorage];
NSRect ipRect = [ts boundingRectForCharacterAtRow:preEditRow
column:preEditColumn];
NSRect ipRect = [ts boundingRectForCharacterAtRow:[helper preEditRow]
column:[helper preEditColumn]];
ipRect.origin.x += [self textContainerOrigin].x;
ipRect.origin.y += [self textContainerOrigin].y;
@@ -552,10 +585,12 @@
valueForKey:NSFontAttributeName];
if (theFont == [ts font])
ipRect.origin.x += [ts cellSize].width *
(imRange.location + imRange.length);
([helper imRange].location +
[helper imRange].length);
else
ipRect.origin.x += [ts cellSize].width * 2 *
(imRange.location + imRange.length);
([helper imRange].location +
[helper imRange].length);
}
if (MMInsertionPointHorizontal == insertionPointShape) {
@@ -571,7 +606,7 @@
ipRect.size.width = frac;
}
[[self insertionPointColor] set];
[[helper insertionPointColor] set];
if (MMInsertionPointHollow == insertionPointShape) {
NSFrameRect(ipRect);
} else {
@@ -584,7 +619,7 @@
//NSLog(@"%s draw insertion point %@ shape=%d color=%@", _cmd,
// NSStringFromRect(ipRect), insertionPointShape,
// [self insertionPointColor]);
// [helper insertionPointColor]);
}
#if 0
@@ -627,109 +662,37 @@
- (BOOL)hasMarkedText
{
//NSLog(@"%s", _cmd);
//return markedText && [markedText length] > 0;
return markedRange.length > 0 ? YES : NO;
return [helper hasMarkedText];
}
- (NSRange)markedRange
{
if ([self hasMarkedText]) {
return markedRange;
} else
return NSMakeRange(NSNotFound, 0);
return [helper markedRange];
}
- (NSDictionary *)markedTextAttributes
{
return markedTextAttributes;
return [helper markedTextAttributes];
}
- (void)setMarkedTextAttributes:(NSDictionary *)attr
{
if (attr != markedTextAttributes) {
[markedTextAttributes release];
markedTextAttributes = [attr retain];
}
[helper setMarkedTextAttributes:attr];
}
- (void)setMarkedText:(id)text selectedRange:(NSRange)range
{
//NSLog(@"setMarkedText:'%@' selectedRange:%@", text,
// NSStringFromRange(range));
MMTextStorage *ts = (MMTextStorage*)[self textStorage];
if (!ts)
return;
[self unmarkText];
if (text && [text length] > 0) {
if ([text isKindOfClass:[NSAttributedString class]]) {
[self setMarkedTextAttributes:
[NSDictionary dictionaryWithObjectsAndKeys:
[ts fontWide], NSFontAttributeName,
[ts defaultBackgroundColor], NSBackgroundColorAttributeName,
[ts defaultForegroundColor], NSForegroundColorAttributeName,
nil]];
markedText = [[NSMutableAttributedString alloc]
initWithString:[text string]
attributes:[self markedTextAttributes]];
} else {
[self setMarkedTextAttributes:
[NSDictionary dictionaryWithObjectsAndKeys:
[ts font], NSFontAttributeName,
[ts defaultBackgroundColor], NSBackgroundColorAttributeName,
[ts defaultForegroundColor], NSForegroundColorAttributeName,
nil]];
markedText = [[NSMutableAttributedString alloc]
initWithString:text
attributes:[self markedTextAttributes]];
}
markedRange = NSMakeRange(0, [markedText length]);
if (markedRange.length) {
[markedText addAttribute:NSUnderlineStyleAttributeName
value:[NSNumber numberWithInt:1]
range:markedRange];
}
imRange = range;
if (range.length) {
[markedText addAttribute:NSUnderlineStyleAttributeName
value:[NSNumber numberWithInt:2]
range:range];
}
}
[self setNeedsDisplay: YES];
[helper setMarkedText:text selectedRange:range];
}
- (void)unmarkText
{
//NSLog(@"%s", _cmd);
imRange = NSMakeRange(0, 0);
markedRange = NSMakeRange(NSNotFound, 0);
[markedText release];
markedText = nil;
[helper unmarkText];
}
- (NSRect)firstRectForCharacterRange:(NSRange)range
{
//NSLog(@"%s%@", _cmd, NSStringFromRange(range));
// HACK! This method is called when the input manager wants to pop up an
// auxiliary window. The position where this should be is controller by
// Vim by sending SetPreEditPositionMsgID so compute a position based on
// the pre-edit (row,column) pair.
MMTextStorage *ts = (MMTextStorage*)[self textStorage];
NSRect rect = [ts boundingRectForCharacterAtRow:preEditRow
column:preEditColumn];
rect.origin.x += [self textContainerOrigin].x;
rect.origin.y += [self textContainerOrigin].y + [ts cellSize].height;
rect.origin = [self convertPoint:rect.origin toView:nil];
rect.origin = [[self window] convertBaseToScreen:rect.origin];
return rect;
return [helper firstRectForCharacterRange:range];
}
- (void)scrollWheel:(NSEvent *)event
@@ -926,6 +889,7 @@
return YES;
}
@end // MMTextView
@@ -933,37 +897,6 @@
@implementation MMTextView (Private)
- (BOOL)convertRow:(int)row column:(int)column toPoint:(NSPoint *)point
{
MMTextStorage *ts = (MMTextStorage*)[self textStorage];
NSSize cellSize = [ts cellSize];
if (!(point && cellSize.width > 0 && cellSize.height > 0))
return NO;
*point = [self textContainerOrigin];
point->x += column * cellSize.width;
point->y += row * cellSize.height;
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;
}
- (MMWindowController *)windowController
{
id windowController = [[self window] windowController];
@@ -977,12 +910,14 @@
return [[self windowController] vimController];
}
- (void)drawInsertionPointAtRow:(int)row column:(int)col shape:(int)shape
fraction:(int)percent color:(NSColor *)color
- (void)setShouldDrawInsertionPoint:(BOOL)on
{
//NSLog(@"drawInsertionPointAtRow:%d column:%d shape:%d color:%@",
// row, col, shape, color);
shouldDrawInsertionPoint = on;
}
- (void)drawInsertionPointAtRow:(int)row column:(int)col shape:(int)shape
fraction:(int)percent
{
// This only stores where to draw the insertion point, the actual drawing
// is done in drawRect:.
shouldDrawInsertionPoint = YES;
@@ -990,8 +925,6 @@
insertionPointColumn = col;
insertionPointShape = shape;
insertionPointFraction = percent;
[self setInsertionPointColor:color];
}
- (void)drawInvertedRectAtRow:(int)row column:(int)col numRows:(int)nrows
@@ -1003,8 +936,8 @@
invertRects = reallocf(invertRects,
numInvertRects*sizeof(NSRect));
if (NULL != invertRects) {
[self convertRow:row column:col numRows:nrows numColumns:ncols
toRect:&invertRects[n]];
invertRects[n] = [self rectForRow:row column:col numRows:nrows
numColumns:ncols];
[self setNeedsDisplayInRect:invertRects[n]];
} else {
n = numInvertRects = 0;
@@ -1012,9 +945,8 @@
} 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];
NSRect rect = [self rectForRow:row column:col numRows:nrows
numColumns:ncols];
[self setNeedsDisplayInRect:rect];
}
}
+27
View File
@@ -30,9 +30,20 @@ enum {
BOOL isAutoscrolling;
int mouseShape;
NSTrackingRectTag trackingRectTag;
NSColor *insertionPointColor;
// Input Manager
NSRange imRange;
NSRange markedRange;
NSDictionary *markedTextAttributes;
NSMutableAttributedString *markedText;
int preEditRow;
int preEditColumn;
}
- (void)setTextView:(id)view;
- (void)setInsertionPointColor:(NSColor *)color;
- (NSColor *)insertionPointColor;
- (void)keyDown:(NSEvent *)event;
- (void)insertText:(id)string;
@@ -53,4 +64,20 @@ enum {
- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender;
- (void)setMouseShape:(int)shape;
// Input Manager
- (BOOL)hasMarkedText;
- (NSRange)markedRange;
- (NSDictionary *)markedTextAttributes;
- (void)setMarkedTextAttributes:(NSDictionary *)attr;
- (void)setMarkedText:(id)text selectedRange:(NSRange)range;
- (void)unmarkText;
- (NSMutableAttributedString *)markedText;
- (void)setPreEditRow:(int)row column:(int)col;
- (int)preEditRow;
- (int)preEditColumn;
- (void)setImRange:(NSRange)range;
- (NSRange)imRange;
- (void)setMarkedRange:(NSRange)range;
- (NSRect)firstRectForCharacterRange:(NSRange)range;
@end
+172
View File
@@ -49,12 +49,32 @@ static float MMDragAreaSize = 73.0f;
@implementation MMTextViewHelper
- (void)dealloc
{
[markedText release]; markedText = nil;
[super dealloc];
}
- (void)setTextView:(id)view
{
// Only keep a weak reference to owning text view.
textView = view;
}
- (void)setInsertionPointColor:(NSColor *)color
{
if (color != insertionPointColor) {
[insertionPointColor release];
insertionPointColor = [color retain];
}
}
- (NSColor *)insertionPointColor
{
return insertionPointColor;
}
- (void)keyDown:(NSEvent *)event
{
//NSLog(@"%s %@", _cmd, event);
@@ -515,6 +535,158 @@ static float MMDragAreaSize = 73.0f;
[self setCursor];
}
- (BOOL)hasMarkedText
{
return markedRange.length > 0 ? YES : NO;
}
- (NSRange)markedRange
{
if ([self hasMarkedText])
return markedRange;
else
return NSMakeRange(NSNotFound, 0);
}
- (NSDictionary *)markedTextAttributes
{
return markedTextAttributes;
}
- (void)setMarkedTextAttributes:(NSDictionary *)attr
{
if (attr != markedTextAttributes) {
[markedTextAttributes release];
markedTextAttributes = [attr retain];
}
}
- (void)setMarkedText:(id)text selectedRange:(NSRange)range
{
[self unmarkText];
if (!(text && [text length] > 0))
return;
// HACK! Determine if the marked text is wide or normal width. This seems
// to always use 'wide' when there are both wide and normal width
// characters.
NSString *string = text;
NSFont *theFont = [textView font];
if ([text isKindOfClass:[NSAttributedString class]]) {
theFont = [textView fontWide];
string = [text string];
}
// TODO: Use special colors for marked text.
[self setMarkedTextAttributes:
[NSDictionary dictionaryWithObjectsAndKeys:
theFont, NSFontAttributeName,
[textView defaultBackgroundColor], NSBackgroundColorAttributeName,
[textView defaultForegroundColor], NSForegroundColorAttributeName,
nil]];
markedText = [[NSMutableAttributedString alloc]
initWithString:string
attributes:[self markedTextAttributes]];
markedRange = NSMakeRange(0, [markedText length]);
if (markedRange.length) {
[markedText addAttribute:NSUnderlineStyleAttributeName
value:[NSNumber numberWithInt:1]
range:markedRange];
}
imRange = range;
if (range.length) {
[markedText addAttribute:NSUnderlineStyleAttributeName
value:[NSNumber numberWithInt:2]
range:range];
}
[textView setNeedsDisplay:YES];
}
- (void)unmarkText
{
imRange = NSMakeRange(0, 0);
markedRange = NSMakeRange(NSNotFound, 0);
[markedText release];
markedText = nil;
}
- (NSMutableAttributedString *)markedText
{
return markedText;
}
- (void)setPreEditRow:(int)row column:(int)col
{
preEditRow = row;
preEditColumn = col;
}
- (int)preEditRow
{
return preEditRow;
}
- (int)preEditColumn
{
return preEditColumn;
}
- (void)setImRange:(NSRange)range
{
imRange = range;
}
- (NSRange)imRange
{
return imRange;
}
- (void)setMarkedRange:(NSRange)range
{
markedRange = range;
}
- (NSRect)firstRectForCharacterRange:(NSRange)range
{
// This method is called when the input manager wants to pop up an
// auxiliary window. The position where this should be is controlled by
// Vim by sending SetPreEditPositionMsgID so compute a position based on
// the pre-edit (row,column) pair.
int col = preEditColumn;
int row = preEditRow + 1;
NSFont *theFont = [[textView markedTextAttributes]
valueForKey:NSFontAttributeName];
if (theFont == [textView fontWide]) {
col += imRange.location * 2;
if (col >= [textView maxColumns] - 1) {
row += (col / [textView maxColumns]);
col = col % 2 ? col % [textView maxColumns] + 1 :
col % [textView maxColumns];
}
} else {
col += imRange.location;
if (col >= [textView maxColumns]) {
row += (col / [textView maxColumns]);
col = col % [textView maxColumns];
}
}
NSRect rect = [textView rectForRow:row
column:col
numRows:1
numColumns:range.length];
rect.origin = [textView convertPoint:rect.origin toView:nil];
rect.origin = [[textView window] convertBaseToScreen:rect.origin];
return rect;
}
@end // MMTextViewHelper
+14
View File
@@ -257,3 +257,17 @@ ATSFontContainerRef loadFonts();
// MacVim Apple Event Constants
#define keyMMUntitledWindow 'MMuw'
#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
// NSInteger was introduced in 10.5
# if __LP64__ || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
# else
typedef int NSInteger;
typedef unsigned int NSUInteger;
# endif
#endif