Inline IM Patch

This commit is contained in:
Kaoru Yoshida
2008-07-01 19:19:19 +02:00
committed by Bjorn Winckler
parent b24d62ac03
commit 33c4a57e05
5 changed files with 114 additions and 76 deletions
+1
View File
@@ -82,6 +82,7 @@ typedef struct {
- (void)setFont:(NSFont *)newFont;
- (void)setWideFont:(NSFont *)newFont;
- (NSFont *)font;
- (NSFont *)fontWide;
- (NSColor *)defaultBackgroundColor;
- (NSColor *)defaultForegroundColor;
- (NSSize)size;
+5
View File
@@ -750,6 +750,11 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
return font;
}
- (NSFont*)fontWide
{
return fontWide;
}
- (NSColor *)defaultBackgroundColor
{
return defaultBackgroundColor;
+3 -2
View File
@@ -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;
+105 -71
View File
@@ -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];
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];
}
[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];
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
-3
View File
@@ -668,9 +668,6 @@
- (void)windowDidResignMain:(NSNotification *)notification
{
[vimController sendMessage:LostFocusMsgID data:nil];
if ([vimView textView])
[[vimView textView] hideMarkedTextField];
}
- (BOOL)windowShouldClose:(id)sender