mirror of
https://github.com/macvim-dev/macvim.git
synced 2026-06-11 15:37:29 +02:00
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:
committed by
Bjorn Winckler
parent
0b018a5836
commit
52bb6e960f
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user