<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -162,7 +162,7 @@ add_custom_command(TARGET ${PROGNAME}
                    COMMAND mkdir -p ${VIM_BUNDLE_VIM_PATH}
                    COMMAND cmake -E remove -f ${PSMTBC_FRAMEWORK_PATH_IN_BUNDLE}
                    COMMAND cmake -E remove -f ${VIM_RUNTIME_PATH_IN_BUNDLE}
-                   COMMAND cmake -E create_symlink ${PSMTBC_FRAMEWORK} ${PSMTBC_FRAMEWORK_PATH_IN_BUNDLE}
-                   COMMAND cmake -E create_symlink ${VIM_RUNTIME_PATH} ${VIM_RUNTIME_PATH_IN_BUNDLE}
+                   COMMAND cmake -E copy_directory ${PSMTBC_FRAMEWORK} ${PSMTBC_FRAMEWORK_PATH_IN_BUNDLE}
+                   COMMAND cmake -E copy_directory ${VIM_RUNTIME_PATH} ${VIM_RUNTIME_PATH_IN_BUNDLE}
                    COMMENT &quot;Adding ${PSMTBC_FRAMEWORK} to ${VIM_BUNDLE_FRAMEWORK_PATH}&quot; VERBATIM)
 </diff>
      <filename>src/CMakeLists.txt</filename>
    </modified>
    <modified>
      <diff>@@ -85,6 +85,7 @@ static struct
 #define VIM_MAX_COL_LEN         1024
 #define VIM_MAX_FONT_NAME_LEN   256
 #define VIM_MAX_BUTTON_TITLE    256
+#define VIM_MAX_DRAW_OP_QUEUE   1024
 #define VIM_DEFAULT_FONT_SIZE   9
 #define VIM_DEFAULT_FONT_NAME   (char_u *) &quot;Monaco:h12&quot;
 #define VIM_MAX_CHAR_WIDTH      2
@@ -135,7 +136,7 @@ static struct
 - (void) beginDrawing;
 - (void) endDrawing;
 
-- (void) clearAll;
+- (NSImage *) contentImage;
 
 @end
 
@@ -176,7 +177,10 @@ static int VIMAlertTextFieldHeight = 22;
 
 @end
 
-@interface VimAppController: NSObject &lt;NSWindowDelegate&gt;
+@interface VimAppController: NSObject
+#if MAC_OS_X_VERSION_MAX_ALLOWED &gt;= 1060
+&lt;NSWindowDelegate&gt;
+#endif
 - (void) alertDidEnd:(VIMAlert *)alert returnCode:(int)returnCode contextInfo:(void *)contextInfo;
 - (void) panelDidEnd:(NSSavePanel *)panel code:(int)code context:(void *)context;
 - (void) initializeApplicationTimer:(NSTimer *)timer;
@@ -191,6 +195,55 @@ enum gui_mac_debug_level {
     MSG_ERROR = 3
 };
 
+enum gui_mac_drawing_type {
+    INVERT_RECT,
+    CLEAR_ALL,
+    CLEAR_BLOCK,
+    SCROLL_RECT,
+    DRAW_STRING,
+    DRAW_PART_CURSOR,
+};
+
+struct gui_mac_drawing_op {
+    uint8_t type;
+
+    guicolor_T back_pixel;
+
+    union {
+        struct {
+            int r;
+            int c;
+            int nr;
+            int nc;
+        } rect1;
+        struct {
+            int row1;
+            int col1;
+            int row2;
+            int col2;
+        } rect2;
+        struct {
+            NSRect rect;
+            int lines;
+        } scroll;
+        struct {
+            int row;
+            int col;
+            char_u *s;
+            int len;
+            int flags;
+            NSColor *fg_color;
+            NSColor *bg_color;
+            NSColor *sp_color;
+        } str;
+        struct {
+            int w;
+            int h;
+            guicolor_T color;
+        } cursor;
+    } u;
+};
+
 struct gui_mac_data {
     NSColor    *fg_color, *bg_color, *sp_color;
     
@@ -221,7 +274,10 @@ struct gui_mac_data {
     BOOL        showing_tabline;
     BOOL        selecting_tab;
     BOOL        window_opened;
-    
+
+    struct gui_mac_drawing_op ops[VIM_MAX_DRAW_OP_QUEUE];
+    uint32_t    queued_ops;
+
     CGSize      single_advances[VIM_MAX_COL_LEN];
     CGSize      double_advances[VIM_MAX_COL_LEN];
 
@@ -273,6 +329,14 @@ void      gui_mac_update();
 #define gui_mac_begin_tab_action()  (gui_mac.selecting_tab = YES)
 #define gui_mac_end_tab_action()    (gui_mac.selecting_tab = NO)
 
+void gui_mac_flush_queue();
+void gui_mac_clear_all(guicolor_T back_pixel);
+void gui_mac_invert_rectangle(int r, int c, int nr, int nc);
+void gui_mac_clear_block(int row1, int col1, int row2, int col2, guicolor_T back_pixel);
+void gui_mac_draw_string(int row, int col, char_u *s, int len, int flags,
+                         NSColor *fg_color, NSColor *bg_color, NSColor *sp_color);
+void gui_mac_draw_part_cursor(int w, int h, guicolor_T color);
+
 int  gui_mac_hex_digit(int c);
 void gui_mac_redraw();
 void gui_mac_scroll_rect(NSRect rect, int lines);
@@ -348,6 +412,7 @@ int gui_mch_init()
     gui_mac.showing_tabline = NO;
     gui_mac.selecting_tab  = NO;
     gui_mac.window_opened  = NO;
+    gui_mac.queued_ops     = 0;
 
     return OK;
 }
@@ -1447,6 +1512,70 @@ void gui_mch_set_sp_color(guicolor_T color)
 
 /* Drawing related {{{ */
 
+struct gui_mac_drawing_op *gui_mac_queue_op(uint8_t type)
+{
+    if (gui_mac.queued_ops &gt;= VIM_MAX_DRAW_OP_QUEUE - 1)
+        gui_mac_flush_queue();
+
+    struct gui_mac_drawing_op *op = &amp;gui_mac.ops[gui_mac.queued_ops++];
+
+    op-&gt;type = type;
+    op-&gt;back_pixel = gui.back_pixel;
+    return op;
+}
+
+void gui_mac_flush_queue()
+{
+    uint32_t i;
+
+    gui_mac_begin_drawing();
+
+    for (i = 0; i &lt; gui_mac.queued_ops; i++)
+    {
+        struct gui_mac_drawing_op *op = &amp;gui_mac.ops[i];
+
+        switch (op-&gt;type)
+        {
+        case INVERT_RECT:
+            gui_mac_invert_rectangle(op-&gt;u.rect1.r, op-&gt;u.rect1.c,
+                                     op-&gt;u.rect1.nr, op-&gt;u.rect1.nc);
+            break;
+
+        case CLEAR_ALL:
+            gui_mac_clear_all(op-&gt;back_pixel);
+            break;
+
+        case CLEAR_BLOCK:
+            gui_mac_clear_block(op-&gt;u.rect2.row1, op-&gt;u.rect2.col1,
+                                op-&gt;u.rect2.row2, op-&gt;u.rect2.col2,
+                                op-&gt;back_pixel);
+            break;
+
+        case SCROLL_RECT:
+            gui_mac_scroll_rect(op-&gt;u.scroll.rect, op-&gt;u.scroll.lines);
+            break;
+
+        case DRAW_STRING:
+            gui_mac_draw_string(op-&gt;u.str.row, op-&gt;u.str.col,
+                                op-&gt;u.str.s, op-&gt;u.str.len, op-&gt;u.str.flags,
+                                op-&gt;u.str.fg_color, op-&gt;u.str.bg_color,
+                                op-&gt;u.str.sp_color);
+            free(op-&gt;u.str.s);
+            [op-&gt;u.str.fg_color release];
+            [op-&gt;u.str.bg_color release];
+            [op-&gt;u.str.sp_color release];
+            break;
+
+        case DRAW_PART_CURSOR:
+            gui_mac_draw_part_cursor(op-&gt;u.cursor.w, op-&gt;u.cursor.h, op-&gt;u.cursor.color);
+            break;
+        }
+    }
+
+    gui_mac_end_drawing();
+    gui_mac.queued_ops = 0;
+}
+
 void gui_mch_flush()
 {
     // gui_mac_msg(MSG_DEBUG, @&quot;gui_mch_flush&quot;);
@@ -1457,20 +1586,24 @@ static inline CGRect CGRectFromNSRect(NSRect nsRect) { return *(CGRect*)&amp;nsRect;
 
 void gui_mch_invert_rectangle(int r, int c, int nr, int nc)
 {
-    NSRect rect;
-    
-    gui_mac_begin_drawing();
+    struct gui_mac_drawing_op *op = gui_mac_queue_op(INVERT_RECT);
 
-    rect = NSRectFromVim(r, c, r + nr, c + nc);
+    op-&gt;u.rect1.r = r;
+    op-&gt;u.rect1.c = c;
+    op-&gt;u.rect1.nr = nr;
+    op-&gt;u.rect1.nc = nc;
+}
+
+void gui_mac_invert_rectangle(int r, int c, int nr, int nc)
+{
+    NSRect rect = NSRectFromVim(r, c, r + nr, c + nc);
 
     CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
-    CGContextSaveGState (context);
+    CGContextSaveGState(context);
     CGContextSetBlendMode(context, kCGBlendModeDifference);
-    CGContextSetRGBFillColor (context, 1.0, 1.0, 1.0, 1.0);
-    CGContextFillRect (context, CGRectFromNSRect(rect));
-    CGContextRestoreGState (context);
-
-    gui_mac_end_drawing();;
+    CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
+    CGContextFillRect(context, CGRectFromNSRect(rect));
+    CGContextRestoreGState(context);
 }
 
 void gui_mch_flash(int msec)
@@ -1479,7 +1612,16 @@ void gui_mch_flash(int msec)
 
 void gui_mch_clear_all()
 {
-    [currentView clearAll];
+    gui_mac_queue_op(CLEAR_ALL);
+}
+
+void gui_mac_clear_all(guicolor_T back_pixel)
+{
+    gui_mch_set_bg_color(back_pixel);
+
+    [gui_mac.bg_color set];
+    NSRectFill([currentView bounds]);
+
 #if GUI_MAC_DELAY_OPEN
     if (! gui_mac.window_opened)
         gui_mac_open_window();
@@ -1488,36 +1630,39 @@ void gui_mch_clear_all()
 
 void gui_mch_clear_block(int row1, int col1, int row2, int col2)
 {
-    NSRect rect;
+    struct gui_mac_drawing_op *op = gui_mac_queue_op(CLEAR_BLOCK);
 
     // NSLog(@&quot;clearBlock: (%d, %d) - (%d, %d)&quot;, row1, col1, row2, col2);
+    op-&gt;u.rect2.row1 = row1;
+    op-&gt;u.rect2.col1 = col1;
+    op-&gt;u.rect2.row2 = row2;
+    op-&gt;u.rect2.col2 = col2;
+}
 
-    gui_mch_set_bg_color(gui.back_pixel);
+void gui_mac_clear_block(int row1, int col1, int row2, int col2, guicolor_T back_pixel)
+{
+    NSRect rect;
 
-    gui_mac_begin_drawing();
+    // NSLog(@&quot;clearBlock: (%d, %d) - (%d, %d)&quot;, row1, col1, row2, col2);
+    gui_mch_set_bg_color(back_pixel);
 
     rect = NSRectFromVim(row1, col1, row2, col2);
     // NSShowRect(&quot;clearBlock&quot;, rect);
 
     [gui_mac.bg_color set];
     NSRectFill(rect);
-
-    gui_mac_end_drawing();
 }
 
 void gui_mch_delete_lines(int row, int num_lines)
 {
-    NSRect src_rect;
-
-    // NSLog(@&quot;deleteLines: (%d, %d)&quot;, row, num_lines);
-    src_rect = NSRectFromVim(row + num_lines,            // row1
-                             gui.scroll_region_left,     // col1
-                             gui.scroll_region_bot,      // row2
-                             gui.scroll_region_right);   // col2
+    struct gui_mac_drawing_op *op = gui_mac_queue_op(SCROLL_RECT);
 
-    // NSShowRect(&quot;src_rect&quot;, src_rect);
-    // move src_dest up for numlines
-    gui_mac_scroll_rect(src_rect, -num_lines);
+    // move dest up for numlines
+    op-&gt;u.scroll.rect = NSRectFromVim(row + num_lines,            // row1
+                                      gui.scroll_region_left,     // col1
+                                      gui.scroll_region_bot,      // row2
+                                      gui.scroll_region_right);   // col2
+    op-&gt;u.scroll.lines = -num_lines;
 
     gui_clear_block(gui.scroll_region_bot - num_lines + 1,
                     gui.scroll_region_left,
@@ -1527,16 +1672,15 @@ void gui_mch_delete_lines(int row, int num_lines)
 
 void gui_mch_insert_lines(int row, int num_lines)
 {
-    NSRect src_rect;
+    struct gui_mac_drawing_op *op = gui_mac_queue_op(SCROLL_RECT);
 
+    // move rect down for num_lines
     // NSLog(@&quot;insertLines: (%d, %d)&quot;, row, num_lines);
-    src_rect = NSRectFromVim(row,                               // row1
-                             gui.scroll_region_left,            // col1
-                             gui.scroll_region_bot - num_lines, // row2
-                             gui.scroll_region_right);          // col2
-
-    // move src_dest down for num_lines
-    gui_mac_scroll_rect(src_rect, num_lines);
+    op-&gt;u.scroll.rect = NSRectFromVim(row,                               // row1
+                                      gui.scroll_region_left,            // col1
+                                      gui.scroll_region_bot - num_lines, // row2
+                                      gui.scroll_region_right);          // col2
+    op-&gt;u.scroll.lines = num_lines;
 
     /* Update gui.cursor_row if the cursor scrolled or copied over */
     if (gui.cursor_row &gt;= gui.row
@@ -1560,9 +1704,18 @@ void gui_mch_draw_hollow_cursor(guicolor_T color)
 
 void gui_mch_draw_part_cursor(int w, int h, guicolor_T color)
 {
+    struct gui_mac_drawing_op *op = gui_mac_queue_op(DRAW_PART_CURSOR);
+
+    op-&gt;u.cursor.w = w;
+    op-&gt;u.cursor.h = h;
+    op-&gt;u.cursor.color = color;
+}
+
+void gui_mac_draw_part_cursor(int w, int h, guicolor_T color)
+{
     NSRect rect;
     int    left;
-    
+
 #ifdef FEAT_RIGHTLEFT
     /* vertical line should be on the right of current point */
     if (CURSOR_BAR_RIGHT)
@@ -1573,13 +1726,11 @@ void gui_mch_draw_part_cursor(int w, int h, guicolor_T color)
 
     rect = NSMakeRect(left, FF_Y(gui.row + 1), w, h);
 
-    gui_mac_begin_drawing();
     [NSColorFromGuiColor(color, 1.0) set];
     // gui_mac_msg(MSG_DEBUG, @&quot;rect = %g %g %g %g&quot;,
     //            rect.origin.x, rect.origin.y,
     //            rect.size.width, rect.size.height);
     [NSBezierPath fillRect: rect];
-    gui_mac_end_drawing();
 }
 
 void print_draw_flags(int flags)
@@ -1605,7 +1756,27 @@ void gui_mac_draw_ct_line(CGContextRef context, CTLineRef line,
 
 void gui_mch_draw_string(int row, int col, char_u *s, int len, int flags)
 {
-    // gui_mac_msg(MSG_DEBUG, @&quot;gui_mch_draw_string: %d, %d, %d&quot;, row, col, len);
+    struct gui_mac_drawing_op *op = gui_mac_queue_op(DRAW_STRING);
+
+    op-&gt;u.str.row = row;
+    op-&gt;u.str.col = col;
+
+    op-&gt;u.str.s = alloc(len + 1);
+    STRNCPY(op-&gt;u.str.s, s, len);
+
+    op-&gt;u.str.len = len;
+    op-&gt;u.str.flags = flags;
+
+    op-&gt;u.str.fg_color = [gui_mac.fg_color copy];
+    op-&gt;u.str.bg_color = [gui_mac.bg_color copy];
+    op-&gt;u.str.sp_color = [gui_mac.sp_color copy];
+}
+
+void gui_mac_draw_string(int row, int col, char_u *s, int len, int flags,
+                         NSColor *fg_color, NSColor *bg_color, NSColor *sp_color)
+{
+    // gui_mac_msg(MSG_DEBUG, @&quot;gui_mac_draw_string: %d, %d, %d, %@, %@&quot;, row, col, len,
+    //            fg_color, bg_color);
     CTLineRef               line;
     CFStringRef             string;
     CFDictionaryRef         attributes;
@@ -1613,7 +1784,7 @@ void gui_mch_draw_string(int row, int col, char_u *s, int len, int flags)
     CTFontRef               font = (CTFontRef) gui_mac.current_font;
 
     CFStringRef keys[] = { kCTFontAttributeName, kCTForegroundColorAttributeName };
-    CFTypeRef values[] = { font,                 gui_mac.fg_color };
+    CFTypeRef values[] = { font,                 fg_color };
 
     // Create a CFString from the original UTF-8 string 's'
     string = CFStringCreateWithBytes(kCFAllocatorDefault,
@@ -1656,8 +1827,6 @@ void gui_mch_draw_string(int row, int col, char_u *s, int len, int flags)
         rect.size.width = gui.char_width * cell_len;
     }
 
-    gui_mac_begin_drawing();
-
     CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
     CGAffineTransform transform = CGAffineTransformIdentity;
 
@@ -1681,14 +1850,14 @@ void gui_mch_draw_string(int row, int col, char_u *s, int len, int flags)
 
     if (! (flags &amp; DRAW_TRANSP))
     {
-        [gui_mac.bg_color set];
+        [bg_color set];
         NSRectFill(rect);
     }
 
     CGContextSetRGBFillColor(context,
-                             [gui_mac.fg_color redComponent],
-                             [gui_mac.fg_color greenComponent],
-                             [gui_mac.fg_color blueComponent],
+                             [fg_color redComponent],
+                             [fg_color greenComponent],
+                             [fg_color blueComponent],
                              1.0);
 
     NSPoint textOrigin = NSMakePoint(rect.origin.x,
@@ -1699,7 +1868,7 @@ void gui_mch_draw_string(int row, int col, char_u *s, int len, int flags)
 
     if (flags &amp; DRAW_UNDERL)
     {
-        [gui_mac.sp_color set];
+        [sp_color set];
         NSRectFill(NSMakeRect(rect.origin.x,
                               rect.origin.y + VIM_UNDERLINE_OFFSET,
                               rect.size.width, VIM_UNDERLINE_HEIGHT));
@@ -1707,7 +1876,7 @@ void gui_mch_draw_string(int row, int col, char_u *s, int len, int flags)
 
     if (flags &amp; DRAW_UNDERC)
     {
-        [gui_mac.sp_color set];
+        [sp_color set];
 
         float line_end_x = rect.origin.x + rect.size.width;
         int i = 0;
@@ -1726,8 +1895,6 @@ void gui_mch_draw_string(int row, int col, char_u *s, int len, int flags)
         }    
     }
 
-    gui_mac_end_drawing();
-
     CFRelease(line);
 }
 
@@ -2732,6 +2899,11 @@ didDragTabViewItem: (NSTabViewItem *) tabViewItem
     return self;
 }
 
+- (NSImage *) contentImage
+{
+    return contentImage;
+}
+
 - (void) synchronizeContentImage
 {
     NSSize size = [self frame].size;
@@ -2743,6 +2915,8 @@ didDragTabViewItem: (NSTabViewItem *) tabViewItem
         [contentImage release];
         contentImage = [[NSImage alloc] initWithSize: size];
         gui_mac.main_height = size.height;
+
+        gui_mac_redraw();
     }
 }
 
@@ -2781,18 +2955,6 @@ didDragTabViewItem: (NSTabViewItem *) tabViewItem
     [contentImage unlockFocus];
 }
 
-- (void) clearAll
-{
-    gui_mch_set_bg_color(gui.back_pixel);
-
-    [contentImage lockFocus];
-
-    [gui_mac.bg_color set];
-    NSRectFill([self bounds]);
-
-    [contentImage unlockFocus];
-}
-
 - (NSAttributedString *) markedText
 {
     return markedText;
@@ -3339,13 +3501,24 @@ void gui_mac_scroll_rect(NSRect rect, int lines)
     NSPoint dest_point = rect.origin;
     dest_point.y -= lines * gui.char_height;
 
-    gui_mac_begin_drawing();
-    NSCopyBits(0, rect, dest_point);
+    // NSLog(@&quot;scrollRect: %@, %d&quot;, NSStringFromRect(rect), lines);
+
+    /* Set a barrier to flush previous drawing, otherwise the
+     * contentImage we used may not be updated */
     gui_mac_end_drawing();
+    gui_mac_begin_drawing();
+
+#if 1
+    [[currentView contentImage] compositeToPoint: dest_point
+                                        fromRect: rect
+                                       operation: NSCompositeCopy];
+#endif
+    // NSCopyBits(0, rect, dest_point);
 }
 
 void gui_mac_redraw()
 {
+    gui_mac_flush_queue();
     [currentView setNeedsDisplay: YES];
 }
 </diff>
      <filename>src/gui_mac.m</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>runtime/doc/tags</filename>
    </removed>
    <removed>
      <filename>src/auto/config.h</filename>
    </removed>
    <removed>
      <filename>src/auto/config.mk</filename>
    </removed>
    <removed>
      <filename>src/auto/configure</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>b8e77b25b95b1d25454307ad2c487abdd5f30f31</id>
    </parent>
  </parents>
  <author>
    <name>Jjgod Jiang</name>
    <email>gzjjgod@gmail.com</email>
  </author>
  <url>http://github.com/jjgod/vim-cocoa/commit/2c9a59f65572b34b87f641ce74711b7b53bb3014</url>
  <id>2c9a59f65572b34b87f641ce74711b7b53bb3014</id>
  <committed-date>2009-06-18T01:42:24-07:00</committed-date>
  <authored-date>2009-06-17T21:05:34-07:00</authored-date>
  <message>Use cached drawing instead of direct back drawing

Traditionally, vim-cocoa use a NSImage in VIMTextView as a back
buffer, everything operations called by upper-level vim (gui_mch_
{clear_all, clear_block, insert_lines, delete_lines, draw_string,
...}) will be instantly drawn on that NSImage, then VIMTextView
will simply copy that image on -drawRect:. Thus, a simple double
buffer drawing mechanism.

However, each time we draw on that NSImage, we will have to call
-lockFocus and -unlockFocus, which is a cheap operation prior to
Mac OS X 10.6. In Mac OS X 10.6, NSImage is changed substantially,
it's no longer backed by an off-screen view, the direct impact to
vim-cocoa is, NSImage -lockFocus/-unlockFocus became much more
expensive. That's why we need to cache all the drawing operations
in batch, and only call lockFocus/unlockFocus once we need to
flush the drawing queue.

That's basically what we did in this commit: use a drawing queue
to cache all the operations, wait until gui_mac_redraw() to flush
out all these operations in batch. We hope it can be a pretty
useful optimization for 10.6, and will increase the performance in
10.5 a little bit.</message>
  <tree>7a9e51cfd41a17084a8a1b48af6fae6f44b56c2d</tree>
  <committer>
    <name>Jjgod Jiang</name>
    <email>gzjjgod@gmail.com</email>
  </committer>
</commit>
