Prepared for ATSUI renderer
[MacVim.git] / src / MacVim / MMAtsuiTextView.m
blobc5e5d9d6d63a040771d708eac6b18393830ad4ec
1 /* vi:set ts=8 sts=4 sw=4 ft=objc:
2  *
3  * VIM - Vi IMproved            by Bram Moolenaar
4  *                              MacVim GUI port by Bjorn Winckler
5  *
6  * Do ":help uganda"  in Vim to read copying and usage conditions.
7  * Do ":help credits" in Vim to see a list of people who contributed.
8  * See README.txt for an overview of the Vim source code.
9  */
11  * MMAtsuiTextView
12  *
13  * Dispatches keyboard and mouse input to the backend.  Handles drag-n-drop of
14  * files onto window.
15  */
17 #import "MMAtsuiTextView.h"
18 #import "MMVimController.h"
19 #import "MacVim.h"
23 static char MMKeypadEnter[2] = { 'K', 'A' };
24 static NSString *MMKeypadEnterString = @"KA";
28 @interface MMAtsuiTextView (Private)
29 - (void)dispatchKeyEvent:(NSEvent *)event;
30 - (void)sendKeyDown:(const char *)chars length:(int)len modifiers:(int)flags;
31 - (MMVimController *)vimController;
32 @end
34 @interface MMAtsuiTextView (Drawing)
35 - (void)beginDrawing;
36 - (void)endDrawing;
37 - (void)drawString:(UniChar *)string length:(UniCharCount)length
38              atRow:(int)row column:(int)col cells:(int)cells
39          withFlags:(int)flags foregroundColor:(NSColor *)fg
40    backgroundColor:(NSColor *)bg specialColor:(NSColor *)sp;
41 - (void)deleteLinesFromRow:(int)row lineCount:(int)count
42               scrollBottom:(int)bottom left:(int)left right:(int)right
43                      color:(NSColor *)color;
44 - (void)insertLinesAtRow:(int)row lineCount:(int)count
45             scrollBottom:(int)bottom left:(int)left right:(int)right
46                    color:(NSColor *)color;
47 - (void)clearBlockFromRow:(int)row1 column:(int)col1 toRow:(int)row2
48                    column:(int)col2 color:(NSColor *)color;
49 - (void)clearAll;
50 @end
53 @implementation MMAtsuiTextView
55 - (id)initWithFrame:(NSRect)frame
57     if ((self = [super initWithFrame:frame])) {
58         // NOTE!  It does not matter which font is set here, Vim will set its
59         // own font on startup anyway.  Just set some bogus values.
60         font = [[NSFont userFixedPitchFontOfSize:0] retain];
61         cellSize.width = cellSize.height = 1;
62     }
64     return self;
67 - (void)dealloc
69     [font release];  font = nil;
70     [defaultBackgroundColor release];  defaultBackgroundColor = nil;
71     [defaultForegroundColor release];  defaultForegroundColor = nil;
73     [super dealloc];
76 - (void)getMaxRows:(int*)rows columns:(int*)cols
78     if (rows) *rows = maxRows;
79     if (cols) *cols = maxColumns;
82 - (void)setMaxRows:(int)rows columns:(int)cols
84     // NOTE: Just remember the new values, the actual resizing is done lazily.
85     maxRows = rows;
86     maxColumns = cols;
89 - (void)setDefaultColorsBackground:(NSColor *)bgColor
90                         foreground:(NSColor *)fgColor
92     if (defaultBackgroundColor != bgColor) {
93         [defaultBackgroundColor release];
94         defaultBackgroundColor = bgColor ? [bgColor retain] : nil;
95     }
97     // NOTE: The default foreground color isn't actually used for anything, but
98     // other class instances might want to be able to access it so it is stored
99     // here.
100     if (defaultForegroundColor != fgColor) {
101         [defaultForegroundColor release];
102         defaultForegroundColor = fgColor ? [fgColor retain] : nil;
103     }
106 - (NSSize)size
108     return NSMakeSize(maxColumns*cellSize.width, maxRows*cellSize.height);
111 - (NSSize)fitToSize:(NSSize)size rows:(int *)rows columns:(int *)columns
113     NSSize curSize = [self size];
114     NSSize fitSize = curSize;
115     int fitRows = maxRows;
116     int fitCols = maxColumns;
118     if (size.height < curSize.height) {
119         // Remove lines until the height of the text storage fits inside
120         // 'size'.  However, always make sure there are at least 3 lines in the
121         // text storage.  (Why 3? It seem Vim never allows less than 3 lines.)
122         //
123         // TODO: No need to search since line height is fixed, just calculate
124         // the new height.
125         int rowCount = maxRows;
126         int rowsToRemove;
127         for (rowsToRemove = 0; rowsToRemove < maxRows-3; ++rowsToRemove) {
128             float height = cellSize.height*rowCount;
130             if (height <= size.height) {
131                 fitSize.height = height;
132                 break;
133             }
135             --rowCount;
136         }
138         fitRows -= rowsToRemove;
139     } else if (size.height > curSize.height) {
140         float fh = cellSize.height;
141         if (fh < 1.0f) fh = 1.0f;
143         fitRows = floor(size.height/fh);
144         fitSize.height = fh*fitRows;
145     }
147     if (size.width != curSize.width) {
148         float fw = cellSize.width;
149         if (fw < 1.0f) fw = 1.0f;
151         fitCols = floor(size.width/fw);
152         fitSize.width = fw*fitCols;
153     }
155     if (rows) *rows = fitRows;
156     if (columns) *columns = fitCols;
158     return fitSize;
161 - (NSRect)rectForRowsInRange:(NSRange)range
163     NSRect rect = { 0, 0, 0, 0 };
164     unsigned start = range.location > maxRows ? maxRows : range.location;
165     unsigned length = range.length;
167     if (start+length > maxRows)
168         length = maxRows - start;
170     rect.origin.y = cellSize.height * start;
171     rect.size.height = cellSize.height * length;
173     return rect;
176 - (NSRect)rectForColumnsInRange:(NSRange)range
178     NSRect rect = { 0, 0, 0, 0 };
179     unsigned start = range.location > maxColumns ? maxColumns : range.location;
180     unsigned length = range.length;
182     if (start+length > maxColumns)
183         length = maxColumns - start;
185     rect.origin.x = cellSize.width * start;
186     rect.size.width = cellSize.width * length;
188     return rect;
192 - (void)setFont:(NSFont *)newFont
194     if (newFont && font != newFont) {
195         [font release];
196         font = [newFont retain];
198         float em = [newFont widthOfString:@"m"];
199         float cellWidthMultiplier = [[NSUserDefaults standardUserDefaults]
200                 floatForKey:MMCellWidthMultiplierKey];
202         // NOTE! Even though NSFontFixedAdvanceAttribute is a float, it will
203         // only render at integer sizes.  Hence, we restrict the cell width to
204         // an integer here, otherwise the window width and the actual text
205         // width will not match.
206         cellSize.width = ceilf(em * cellWidthMultiplier);
207         cellSize.height = linespace + [newFont defaultLineHeightForFont];
208     }
211 - (void)setWideFont:(NSFont *)newFont
215 - (NSFont *)font
217     return font;
220 - (NSSize)cellSize
222     return cellSize;
225 - (void)setLinespace:(float)newLinespace
227     linespace = newLinespace;
229     // NOTE: The linespace is added to the cell height in order for a multiline
230     // selection not to have white (background color) gaps between lines.  Also
231     // this simplifies the code a lot because there is no need to check the
232     // linespace when calculating the size of the text view etc.  When the
233     // linespace is non-zero the baseline will be adjusted as well; check
234     // MMTypesetter.
235     cellSize.height = linespace + [font defaultLineHeightForFont];
241 - (NSEvent *)lastMouseDownEvent
243     return nil;
246 - (void)setShouldDrawInsertionPoint:(BOOL)on
250 - (void)setPreEditRow:(int)row column:(int)col
254 - (void)drawInsertionPointAtRow:(int)row column:(int)col shape:(int)shape
255                        fraction:(int)percent color:(NSColor *)color
259 - (void)hideMarkedTextField
266 - (void)keyDown:(NSEvent *)event
268     //NSLog(@"%s %@", _cmd, event);
269     // HACK! If control modifier is held, don't pass the event along to
270     // interpretKeyEvents: since some keys are bound to multiple commands which
271     // means doCommandBySelector: is called several times.
272     //
273     // TODO: Figure out a way to disable Cocoa key bindings entirely, without
274     // affecting input management.
275     if ([event modifierFlags] & NSControlKeyMask) {
276         NSString *unmod = [event charactersIgnoringModifiers];
277         if ([unmod length] == 1 && [unmod characterAtIndex:0] <= 0x7f
278                                 && [unmod characterAtIndex:0] >= 0x60) {
279             // HACK! Send Ctrl-letter keys (and C-@, C-[, C-\, C-], C-^, C-_)
280             // as normal text to be added to the Vim input buffer.  This must
281             // be done in order for the backend to be able to separate e.g.
282             // Ctrl-i and Ctrl-tab.
283             [self insertText:[event characters]];
284         } else {
285             [self dispatchKeyEvent:event];
286         }
287     } else {
288         [super keyDown:event];
289     }
292 - (void)insertText:(id)string
294     //NSLog(@"%s %@", _cmd, string);
295     // NOTE!  This method is called for normal key presses but also for
296     // Option-key presses --- even when Ctrl is held as well as Option.  When
297     // Ctrl is held, the AppKit translates the character to a Ctrl+key stroke,
298     // so 'string' need not be a printable character!  In this case it still
299     // works to pass 'string' on to Vim as a printable character (since
300     // modifiers are already included and should not be added to the input
301     // buffer using CSI, K_MODIFIER).
303     [self hideMarkedTextField];
305     NSEvent *event = [NSApp currentEvent];
307     // HACK!  In order to be able to bind to <S-Space>, <S-M-Tab>, etc. we have
308     // to watch for them here.
309     if ([event type] == NSKeyDown
310             && [[event charactersIgnoringModifiers] length] > 0
311             && [event modifierFlags]
312                 & (NSShiftKeyMask|NSControlKeyMask|NSAlternateKeyMask)) {
313         unichar c = [[event charactersIgnoringModifiers] characterAtIndex:0];
315         // <S-M-Tab> translates to 0x19 
316         if (' ' == c || 0x19 == c) {
317             [self dispatchKeyEvent:event];
318             return;
319         }
320     }
322     // TODO: Support 'mousehide' (check p_mh)
323     [NSCursor setHiddenUntilMouseMoves:YES];
325     // NOTE: 'string' is either an NSString or an NSAttributedString.  Since we
326     // do not support attributes, simply pass the corresponding NSString in the
327     // latter case.
328     if ([string isKindOfClass:[NSAttributedString class]])
329         string = [string string];
331     //NSLog(@"send InsertTextMsgID: %@", string);
333     [[self vimController] sendMessage:InsertTextMsgID
334                  data:[string dataUsingEncoding:NSUTF8StringEncoding]];
337 - (void)doCommandBySelector:(SEL)selector
339     //NSLog(@"%s %@", _cmd, NSStringFromSelector(selector));
340     // By ignoring the selector we effectively disable the key binding
341     // mechanism of Cocoa.  Hopefully this is what the user will expect
342     // (pressing Ctrl+P would otherwise result in moveUp: instead of previous
343     // match, etc.).
344     //
345     // We usually end up here if the user pressed Ctrl+key (but not
346     // Ctrl+Option+key).
348     NSEvent *event = [NSApp currentEvent];
350     if (selector == @selector(cancelOperation:)
351             || selector == @selector(insertNewline:)) {
352         // HACK! If there was marked text which got abandoned as a result of
353         // hitting escape or enter, then 'insertText:' is called with the
354         // abandoned text but '[event characters]' includes the abandoned text
355         // as well.  Since 'dispatchKeyEvent:' looks at '[event characters]' we
356         // must intercept these keys here or the abandonded text gets inserted
357         // twice.
358         NSString *key = [event charactersIgnoringModifiers];
359         const char *chars = [key UTF8String];
360         int len = [key lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
362         if (0x3 == chars[0]) {
363             // HACK! AppKit turns enter (not return) into Ctrl-C, so we need to
364             // handle it separately (else Ctrl-C doesn't work).
365             len = sizeof(MMKeypadEnter)/sizeof(MMKeypadEnter[0]);
366             chars = MMKeypadEnter;
367         }
369         [self sendKeyDown:chars length:len modifiers:[event modifierFlags]];
370     } else {
371         [self dispatchKeyEvent:event];
372     }
375 - (BOOL)performKeyEquivalent:(NSEvent *)event
377     //NSLog(@"%s %@", _cmd, event);
378     // Called for Cmd+key keystrokes, function keys, arrow keys, page
379     // up/down, home, end.
380     //
381     // NOTE: This message cannot be ignored since Cmd+letter keys never are
382     // passed to keyDown:.  It seems as if the main menu consumes Cmd-key
383     // strokes, unless the key is a function key.
385     // NOTE: If the event that triggered this method represents a function key
386     // down then we do nothing, otherwise the input method never gets the key
387     // stroke (some input methods use e.g. arrow keys).  The function key down
388     // event will still reach Vim though (via keyDown:).  The exceptions to
389     // this rule are: PageUp/PageDown (keycode 116/121).
390     int flags = [event modifierFlags];
391     if ([event type] != NSKeyDown || flags & NSFunctionKeyMask
392             && !(116 == [event keyCode] || 121 == [event keyCode]))
393         return NO;
395     // HACK!  Let the main menu try to handle any key down event, before
396     // passing it on to vim, otherwise key equivalents for menus will
397     // effectively be disabled.
398     if ([[NSApp mainMenu] performKeyEquivalent:event])
399         return YES;
401     // HACK!  KeyCode 50 represent the key which switches between windows
402     // within an application (like Cmd+Tab is used to switch between
403     // applications).  Return NO here, else the window switching does not work.
404     //
405     // Will this hack work for all languages / keyboard layouts?
406     if ([event keyCode] == 50)
407         return NO;
409     // HACK!  On Leopard Ctrl-key events end up here instead of keyDown:.
410     if (flags & NSControlKeyMask) {
411         [self keyDown:event];
412         return YES;
413     }
415     //NSLog(@"%s%@", _cmd, event);
417     NSString *chars = [event characters];
418     NSString *unmodchars = [event charactersIgnoringModifiers];
419     int len = [unmodchars lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
420     NSMutableData *data = [NSMutableData data];
422     if (len <= 0)
423         return NO;
425     // If 'chars' and 'unmodchars' differs when shift flag is present, then we
426     // can clear the shift flag as it is already included in 'unmodchars'.
427     // Failing to clear the shift flag means <D-Bar> turns into <S-D-Bar> (on
428     // an English keyboard).
429     if (flags & NSShiftKeyMask && ![chars isEqual:unmodchars])
430         flags &= ~NSShiftKeyMask;
432     if (0x3 == [unmodchars characterAtIndex:0]) {
433         // HACK! AppKit turns enter (not return) into Ctrl-C, so we need to
434         // handle it separately (else Cmd-enter turns into Ctrl-C).
435         unmodchars = MMKeypadEnterString;
436         len = [unmodchars lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
437     }
439     [data appendBytes:&flags length:sizeof(int)];
440     [data appendBytes:&len length:sizeof(int)];
441     [data appendBytes:[unmodchars UTF8String] length:len];
443     [[self vimController] sendMessage:CmdKeyMsgID data:data];
445     return YES;
448 - (NSPoint)textContainerOrigin
450     return NSZeroPoint;
453 - (void)setTextContainerInset:(NSSize)inset
457 - (void)setBackgroundColor:(NSColor *)color
464 - (BOOL)acceptsFirstResponder
466     return YES;
469 - (BOOL)isFlipped
471     return YES;
474 - (void)drawRect:(NSRect)rect
476     NSColor *color = defaultBackgroundColor ? defaultBackgroundColor
477                                             : [NSColor lightGrayColor];
478     [color set];
479     [NSBezierPath fillRect:rect];
485 #define MM_DEBUG_DRAWING 0
487 - (void)performBatchDrawWithData:(NSData *)data
489     const void *bytes = [data bytes];
490     const void *end = bytes + [data length];
492 #if MM_DEBUG_DRAWING
493     NSLog(@"====> BEGIN %s", _cmd);
494 #endif
495     [self beginDrawing];
497     // TODO: Sanity check input
499     while (bytes < end) {
500         int type = *((int*)bytes);  bytes += sizeof(int);
502         if (ClearAllDrawType == type) {
503 #if MM_DEBUG_DRAWING
504             NSLog(@"   Clear all");
505 #endif
506             [self clearAll];
507         } else if (ClearBlockDrawType == type) {
508             unsigned color = *((unsigned*)bytes);  bytes += sizeof(unsigned);
509             int row1 = *((int*)bytes);  bytes += sizeof(int);
510             int col1 = *((int*)bytes);  bytes += sizeof(int);
511             int row2 = *((int*)bytes);  bytes += sizeof(int);
512             int col2 = *((int*)bytes);  bytes += sizeof(int);
514 #if MM_DEBUG_DRAWING
515             NSLog(@"   Clear block (%d,%d) -> (%d,%d)", row1, col1,
516                     row2,col2);
517 #endif
518             [self clearBlockFromRow:row1 column:col1
519                     toRow:row2 column:col2
520                     color:[NSColor colorWithArgbInt:color]];
521         } else if (DeleteLinesDrawType == type) {
522             unsigned color = *((unsigned*)bytes);  bytes += sizeof(unsigned);
523             int row = *((int*)bytes);  bytes += sizeof(int);
524             int count = *((int*)bytes);  bytes += sizeof(int);
525             int bot = *((int*)bytes);  bytes += sizeof(int);
526             int left = *((int*)bytes);  bytes += sizeof(int);
527             int right = *((int*)bytes);  bytes += sizeof(int);
529 #if MM_DEBUG_DRAWING
530             NSLog(@"   Delete %d line(s) from %d", count, row);
531 #endif
532             [self deleteLinesFromRow:row lineCount:count
533                     scrollBottom:bot left:left right:right
534                            color:[NSColor colorWithArgbInt:color]];
535         } else if (DrawStringDrawType == type) {
536             int bg = *((int*)bytes);  bytes += sizeof(int);
537             int fg = *((int*)bytes);  bytes += sizeof(int);
538             int sp = *((int*)bytes);  bytes += sizeof(int);
539             int row = *((int*)bytes);  bytes += sizeof(int);
540             int col = *((int*)bytes);  bytes += sizeof(int);
541             int cells = *((int*)bytes);  bytes += sizeof(int);
542             int flags = *((int*)bytes);  bytes += sizeof(int);
543             int len = *((int*)bytes);  bytes += sizeof(int);
544             UniChar *string = (UniChar*)bytes;  bytes += len;
546 #if MM_DEBUG_DRAWING
547             NSLog(@"   Draw string at (%d,%d) length=%d flags=%d fg=0x%x "
548                     "bg=0x%x sp=0x%x", row, col, len, flags, fg, bg, sp);
549 #endif
550             [self drawString:string length:len atRow:row column:col
551                        cells:cells withFlags:flags
552                     foregroundColor:[NSColor colorWithRgbInt:fg]
553                     backgroundColor:[NSColor colorWithArgbInt:bg]
554                        specialColor:[NSColor colorWithRgbInt:sp]];
555         } else if (InsertLinesDrawType == type) {
556             unsigned color = *((unsigned*)bytes);  bytes += sizeof(unsigned);
557             int row = *((int*)bytes);  bytes += sizeof(int);
558             int count = *((int*)bytes);  bytes += sizeof(int);
559             int bot = *((int*)bytes);  bytes += sizeof(int);
560             int left = *((int*)bytes);  bytes += sizeof(int);
561             int right = *((int*)bytes);  bytes += sizeof(int);
563 #if MM_DEBUG_DRAWING
564             NSLog(@"   Insert %d line(s) at row %d", count, row);
565 #endif
566             [self insertLinesAtRow:row lineCount:count
567                              scrollBottom:bot left:left right:right
568                                     color:[NSColor colorWithArgbInt:color]];
569         } else if (DrawCursorDrawType == type) {
570             unsigned color = *((unsigned*)bytes);  bytes += sizeof(unsigned);
571             int row = *((int*)bytes);  bytes += sizeof(int);
572             int col = *((int*)bytes);  bytes += sizeof(int);
573             int shape = *((int*)bytes);  bytes += sizeof(int);
574             int percent = *((int*)bytes);  bytes += sizeof(int);
576 #if MM_DEBUG_DRAWING
577             NSLog(@"   Draw cursor at (%d,%d)", row, col);
578 #endif
579             [self drawInsertionPointAtRow:row column:col shape:shape
580                                      fraction:percent
581                                         color:[NSColor colorWithRgbInt:color]];
582         } else {
583             NSLog(@"WARNING: Unknown draw type (type=%d)", type);
584         }
585     }
587     [self endDrawing];
589     // NOTE: During resizing, Cocoa only sends draw messages before Vim's rows
590     // and columns are changed (due to ipc delays). Force a redraw here.
591     [self displayIfNeeded];
593 #if MM_DEBUG_DRAWING
594     NSLog(@"<==== END   %s", _cmd);
595 #endif
598 @end // MMAtsuiTextView
603 @implementation MMAtsuiTextView (Private)
605 - (void)dispatchKeyEvent:(NSEvent *)event
607     // Only handle the command if it came from a keyDown event
608     if ([event type] != NSKeyDown)
609         return;
611     NSString *chars = [event characters];
612     NSString *unmodchars = [event charactersIgnoringModifiers];
613     unichar c = [chars characterAtIndex:0];
614     unichar imc = [unmodchars characterAtIndex:0];
615     int len = 0;
616     const char *bytes = 0;
617     int mods = [event modifierFlags];
619     //NSLog(@"%s chars[0]=0x%x unmodchars[0]=0x%x (chars=%@ unmodchars=%@)",
620     //        _cmd, c, imc, chars, unmodchars);
622     if (' ' == imc && 0xa0 != c) {
623         // HACK!  The AppKit turns <C-Space> into <C-@> which is not standard
624         // Vim behaviour, so bypass this problem.  (0xa0 is <M-Space>, which
625         // should be passed on as is.)
626         len = [unmodchars lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
627         bytes = [unmodchars UTF8String];
628     } else if (imc == c && '2' == c) {
629         // HACK!  Translate Ctrl+2 to <C-@>.
630         static char ctrl_at = 0;
631         len = 1;  bytes = &ctrl_at;
632     } else if (imc == c && '6' == c) {
633         // HACK!  Translate Ctrl+6 to <C-^>.
634         static char ctrl_hat = 0x1e;
635         len = 1;  bytes = &ctrl_hat;
636     } else if (c == 0x19 && imc == 0x19) {
637         // HACK! AppKit turns back tab into Ctrl-Y, so we need to handle it
638         // separately (else Ctrl-Y doesn't work).
639         static char tab = 0x9;
640         len = 1;  bytes = &tab;  mods |= NSShiftKeyMask;
641     } else {
642         len = [chars lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
643         bytes = [chars UTF8String];
644     }
646     [self sendKeyDown:bytes length:len modifiers:mods];
649 - (void)sendKeyDown:(const char *)chars length:(int)len modifiers:(int)flags
651     if (chars && len > 0) {
652         NSMutableData *data = [NSMutableData data];
654         [data appendBytes:&flags length:sizeof(int)];
655         [data appendBytes:&len length:sizeof(int)];
656         [data appendBytes:chars length:len];
658         // TODO: Support 'mousehide' (check p_mh)
659         [NSCursor setHiddenUntilMouseMoves:YES];
661         //NSLog(@"%s len=%d chars=0x%x", _cmd, len, chars[0]);
662         [[self vimController] sendMessage:KeyDownMsgID data:data];
663     }
666 - (MMVimController *)vimController
668     id windowController = [[self window] windowController];
670     // TODO: Make sure 'windowController' is a MMWindowController before type
671     // casting.
672     return [(MMWindowController*)windowController vimController];
675 @end // MMAtsuiTextView (Private)
680 @implementation MMAtsuiTextView (Drawing)
682 - (void)beginDrawing
686 - (void)endDrawing
690 - (void)drawString:(UniChar *)string length:(UniCharCount)length
691              atRow:(int)row column:(int)col cells:(int)cells
692          withFlags:(int)flags foregroundColor:(NSColor *)fg
693    backgroundColor:(NSColor *)bg specialColor:(NSColor *)sp
695     // 'string' consists of 'length' utf-16 code pairs and should cover 'cells'
696     // display cells (a normal character takes up one display cell, a wide
697     // character takes up two)
700 - (void)deleteLinesFromRow:(int)row lineCount:(int)count
701               scrollBottom:(int)bottom left:(int)left right:(int)right
702                      color:(NSColor *)color
706 - (void)insertLinesAtRow:(int)row lineCount:(int)count
707             scrollBottom:(int)bottom left:(int)left right:(int)right
708                    color:(NSColor *)color
712 - (void)clearBlockFromRow:(int)row1 column:(int)col1 toRow:(int)row2
713                    column:(int)col2 color:(NSColor *)color
717 - (void)clearAll
721 @end // MMAtsuiTextView (Drawing)