]> git.pld-linux.org Git - packages/vim.git/blob - 7.0.232
- updated to 1.15
[packages/vim.git] / 7.0.232
1 To: vim-dev@vim.org
2 Subject: patch 7.0.232 (extra)
3 Fcc: outbox
4 From: Bram Moolenaar <Bram@moolenaar.net>
5 Mime-Version: 1.0
6 Content-Type: text/plain; charset=ISO-8859-1
7 Content-Transfer-Encoding: 8bit
8 ------------
9
10 Patch 7.0.232 (extra)
11 Problem:    Mac: doesn't support GUI tab page labels.
12 Solution:   Add GUI tab page labels. (Nicolas Weber)
13 Files:      src/feature.h, src/gui.c, src/gui.h, src/gui_mac.c,
14             src/proto/gui_mac.pro
15
16
17 *** ../vim-7.0.231/src/feature.h        Wed Nov  1 18:10:36 2006
18 --- src/feature.h       Thu Mar 15 19:02:15 2007
19 ***************
20 *** 756,761 ****
21 --- 756,762 ----
22   #if defined(FEAT_WINDOWS) && defined(FEAT_NORMAL) \
23       && (defined(FEAT_GUI_GTK) \
24         || (defined(FEAT_GUI_MOTIF) && defined(HAVE_XM_NOTEBOOK_H)) \
25 +       || defined(FEAT_GUI_MAC) \
26         || (defined(FEAT_GUI_MSWIN) && (!defined(_MSC_VER) || _MSC_VER > 1020)))
27   # define FEAT_GUI_TABLINE
28   #endif
29 *** ../vim-7.0.231/src/gui.c    Tue Oct 10 17:36:50 2006
30 --- src/gui.c   Thu Mar 15 19:02:15 2007
31 ***************
32 *** 1159,1165 ****
33   #endif
34   
35   # if defined(FEAT_GUI_TABLINE) && (defined(FEAT_GUI_MSWIN) \
36 !       || defined(FEAT_GUI_MOTIF))
37       if (gui_has_tabline())
38         text_area_y += gui.tabline_height;
39   #endif
40 --- 1159,1165 ----
41   #endif
42   
43   # if defined(FEAT_GUI_TABLINE) && (defined(FEAT_GUI_MSWIN) \
44 !       || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_MAC))
45       if (gui_has_tabline())
46         text_area_y += gui.tabline_height;
47   #endif
48 *** ../vim-7.0.231/src/gui.h    Thu Apr 27 01:52:33 2006
49 --- src/gui.h   Thu Mar 15 19:02:15 2007
50 ***************
51 *** 421,427 ****
52   #endif        /* FEAT_GUI_GTK */
53   
54   #if defined(FEAT_GUI_TABLINE) \
55 !       && (defined(FEAT_GUI_W32) || defined(FEAT_GUI_MOTIF))
56       int               tabline_height;
57   #endif
58   
59 --- 425,432 ----
60   #endif        /* FEAT_GUI_GTK */
61   
62   #if defined(FEAT_GUI_TABLINE) \
63 !       && (defined(FEAT_GUI_W32) || defined(FEAT_GUI_MOTIF) \
64 !                  || defined(FEAT_GUI_MAC))
65       int               tabline_height;
66   #endif
67   
68 *** ../vim-7.0.231/src/gui_mac.c        Thu Mar  8 20:39:02 2007
69 --- src/gui_mac.c       Fri Mar 16 11:26:05 2007
70 ***************
71 *** 4,10 ****
72    *                            GUI/Motif support by Robert Webb
73    *                            Macintosh port by Dany St-Amant
74    *                                          and Axel Kielhorn
75 !  *                            Port to MPW by Bernhard Pr\9fmmer
76    *                            Initial Carbon port by Ammon Skidmore
77    *
78    * Do ":help uganda"  in Vim to read copying and usage conditions.
79 --- 4,10 ----
80    *                            GUI/Motif support by Robert Webb
81    *                            Macintosh port by Dany St-Amant
82    *                                          and Axel Kielhorn
83 !  *                            Port to MPW by Bernhard Pruemmer
84    *                            Initial Carbon port by Ammon Skidmore
85    *
86    * Do ":help uganda"  in Vim to read copying and usage conditions.
87 ***************
88 *** 260,265 ****
89 --- 260,270 ----
90   OSErr HandleUnusedParms(const AppleEvent *theAEvent);
91   #endif
92   
93 + #ifdef FEAT_GUI_TABLINE
94 + static void initialise_tabline(void);
95 + static WindowRef drawer = NULL; // TODO: put into gui.h
96 + #endif
97
98   /*
99    * ------------------------------------------------------------
100    * Conversion Utility
101 ***************
102 *** 2357,2362 ****
103 --- 2323,2335 ----
104   
105       thePart = FindWindow(theEvent->where, &whichWindow);
106   
107 + #ifdef FEAT_GUI_TABLINE
108 +     /* prevent that the vim window size changes if it's activated by a
109 +        click into the tab pane */
110 +     if (whichWindow == drawer)
111 +         return;
112 + #endif
113
114       switch (thePart)
115       {
116         case (inDesk):
117 ***************
118 *** 3097,3102 ****
119 --- 3070,3082 ----
120   #endif
121   */
122   
123 + #ifdef FEAT_GUI_TABLINE
124 +     /*
125 +      * Create the tabline
126 +      */
127 +     initialise_tabline();
128 + #endif
129
130       /* TODO: Load bitmap if using TOOLBAR */
131       return OK;
132   }
133 ***************
134 *** 5895,5901 ****
135       theCPB.dirInfo.ioFDirIndex = 0;
136       theCPB.dirInfo.ioNamePtr   = file.name;
137       theCPB.dirInfo.ioVRefNum   = file.vRefNum;
138 !   /*theCPB.hFileInfo.ioDirID   = 0;*/
139       theCPB.dirInfo.ioDrDirID   = file.parID;
140   
141       /* As ioFDirIndex = 0, get the info of ioNamePtr,
142 --- 5875,5881 ----
143       theCPB.dirInfo.ioFDirIndex = 0;
144       theCPB.dirInfo.ioNamePtr   = file.name;
145       theCPB.dirInfo.ioVRefNum   = file.vRefNum;
146 !     /*theCPB.hFileInfo.ioDirID   = 0;*/
147       theCPB.dirInfo.ioDrDirID   = file.parID;
148   
149       /* As ioFDirIndex = 0, get the info of ioNamePtr,
150 ***************
151 *** 6093,6096 ****
152 --- 6073,6479 ----
153       return (script != smRoman
154             && script == GetScriptManagerVariable(smSysScript)) ? 1 : 0;
155   }
156
157   #endif /* defined(USE_IM_CONTROL) || defined(PROTO) */
158
159
160
161
162 + #if defined(FEAT_GUI_TABLINE) || defined(PROTO)
163 + // drawer implementation
164 + static MenuRef contextMenu = NULL;
165 + enum
166 + {
167 +     kTabContextMenuId = 42,
168 + };
169
170 + // the caller has to CFRelease() the returned string
171 +     static CFStringRef
172 + getTabLabel(tabpage_T *page)
173 + {
174 +     get_tabline_label(page, FALSE);
175 + #ifdef MACOS_CONVERT
176 +     return mac_enc_to_cfstring(NameBuff, STRLEN(NameBuff));
177 + #else
178 +     // TODO: check internal encoding?
179 +     return CFStringCreateWithCString(kCFAllocatorDefault, (char *)NameBuff,
180 +                                                  kCFStringEncodingMacRoman);
181 + #endif
182 + }
183
184
185 + #define DRAWER_SIZE 150
186 + #define DRAWER_INSET 16
187
188 + static ControlRef dataBrowser = NULL;
189
190 + // when the tabline is hidden, vim doesn't call update_tabline(). When
191 + // the tabline is shown again, show_tabline() is called before upate_tabline(),
192 + // and because of this, the tab labels and vims internal tabs are out of sync
193 + // for a very short time. to prevent inconsistent state, we store the labels
194 + // of the tabs, not pointers to the tabs (which are invalid for a short time).
195 + static CFStringRef *tabLabels = NULL;
196 + static int tabLabelsSize = 0;
197
198 + enum
199 + {
200 +     kTabsColumn = 'Tabs'
201 + };
202
203 +     static int
204 + getTabCount(void)
205 + {
206 +     tabpage_T *tp;
207 +     int               numTabs = 0;
208
209 +     for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
210 +         ++numTabs;
211 +     return numTabs;
212 + }
213
214 + // data browser item display callback
215 +     static OSStatus
216 + dbItemDataCallback(ControlRef browser,
217 +       DataBrowserItemID itemID,
218 +         DataBrowserPropertyID property /* column id */,
219 +         DataBrowserItemDataRef itemData,
220 +       Boolean changeValue)
221 + {
222 +     OSStatus status = noErr;
223
224 +     // assert(property == kTabsColumn); // why is this violated??
225
226 +     // changeValue is true if we have a modifieable list and data was changed.
227 +     // In our case, it's always false.
228 +     // (that is: if (changeValue) updateInternalData(); else return
229 +     // internalData();
230 +     if (!changeValue)
231 +     {
232 +       CFStringRef str;
233
234 +       assert(itemID - 1 >= 0 && itemID - 1 < tabLabelsSize);
235 +       str = tabLabels[itemID - 1];
236 +       status = SetDataBrowserItemDataText(itemData, str);
237 +     }
238 +     else
239 +       status = errDataBrowserPropertyNotSupported;
240
241 +     return status;
242 + }
243
244 + // data browser action callback
245 +     static void
246 + dbItemNotificationCallback(ControlRef browser,
247 +       DataBrowserItemID item,
248 +       DataBrowserItemNotification message)
249 + {
250 +     switch (message)
251 +     {
252 +       case kDataBrowserItemSelected:
253 +           send_tabline_event(item);
254 +           break;
255 +     }
256 + }
257
258 + // callbacks needed for contextual menu:
259 +     static void
260 + dbGetContextualMenuCallback(ControlRef browser,
261 +       MenuRef *menu,
262 +         UInt32 *helpType,
263 +       CFStringRef *helpItemString,
264 +         AEDesc *selection)
265 + {
266 +     // on mac os 9: kCMHelpItemNoHelp, but it's not the same
267 +     *helpType = kCMHelpItemRemoveHelp; // OS X only ;-)
268 +     *helpItemString = NULL;
269
270 +     *menu = contextMenu;
271 + }
272
273 +     static void
274 + dbSelectContextualMenuCallback(ControlRef browser,
275 +       MenuRef menu,
276 +       UInt32 selectionType,
277 +       SInt16 menuID,
278 +       MenuItemIndex menuItem)
279 + {
280 +     if (selectionType == kCMMenuItemSelected)
281 +     {
282 +       MenuCommand command;
283 +       GetMenuItemCommandID(menu, menuItem, &command);
284
285 +       // get tab that was selected when the context menu appeared
286 +       // (there is always one tab selected). TODO: check if the context menu
287 +       // isn't opened on an item but on empty space (has to be possible some
288 +       // way, the finder does it too ;-) )
289 +       Handle items = NewHandle(0);
290 +       if (items != NULL)
291 +       {
292 +           int numItems;
293
294 +           GetDataBrowserItems(browser, kDataBrowserNoItem, false,
295 +                                          kDataBrowserItemIsSelected, items);
296 +           numItems = GetHandleSize(items) / sizeof(DataBrowserItemID);
297 +           if (numItems > 0)
298 +           {
299 +               int idx;
300 +               DataBrowserItemID *itemsPtr;
301
302 +               HLock(items);
303 +               itemsPtr = (DataBrowserItemID *)*items;
304 +               idx = itemsPtr[0];
305 +               HUnlock(items);
306 +               send_tabline_menu_event(idx, command);
307 +           }
308 +           DisposeHandle(items);
309 +       }
310 +     }
311 + }
312
313 + // focus callback of the data browser to always leave focus in vim
314 +     static OSStatus
315 + dbFocusCallback(EventHandlerCallRef handler, EventRef event, void *data)
316 + {
317 +     assert(GetEventClass(event) == kEventClassControl
318 +           && GetEventKind(event) == kEventControlSetFocusPart);
319
320 +     return paramErr;
321 + }
322
323
324 + // drawer callback to resize data browser to drawer size
325 +     static OSStatus
326 + drawerCallback(EventHandlerCallRef handler, EventRef event, void *data)
327 + {
328 +     switch (GetEventKind(event))
329 +     {
330 +       case kEventWindowBoundsChanged: // move or resize
331 +           {
332 +               UInt32 attribs;
333 +               GetEventParameter(event, kEventParamAttributes, typeUInt32,
334 +                                      NULL, sizeof(attribs), NULL, &attribs);
335 +               if (attribs & kWindowBoundsChangeSizeChanged) // resize
336 +               {
337 +                   Rect r;
338 +                   GetWindowBounds(drawer, kWindowContentRgn, &r);
339 +                   SetRect(&r, 0, 0, r.right - r.left, r.bottom - r.top);
340 +                   SetControlBounds(dataBrowser, &r);
341 +                   SetDataBrowserTableViewNamedColumnWidth(dataBrowser,
342 +                                                       kTabsColumn, r.right);
343 +               }
344 +           }
345 +           break;
346 +     }
347
348 +     return eventNotHandledErr;
349 + }
350
351 + // Load DataBrowserChangeAttributes() dynamically on tiger (and better).
352 + // This way the code works on 10.2 and 10.3 as well (it doesn't have the
353 + // blue highlights in the list view on these systems, though. Oh well.)
354
355
356 + #import <mach-o/dyld.h>
357
358 + enum { kMyDataBrowserAttributeListViewAlternatingRowColors = (1 << 1) };
359
360 +     static OSStatus
361 + myDataBrowserChangeAttributes(ControlRef inDataBrowser,
362 +       OptionBits inAttributesToSet,
363 +       OptionBits inAttributesToClear)
364 + {
365 +     long osVersion;
366 +     char *symbolName;
367 +     NSSymbol symbol = NULL;
368 +     OSStatus (*dataBrowserChangeAttributes)(ControlRef inDataBrowser,
369 +             OptionBits   inAttributesToSet, OptionBits inAttributesToClear);
370
371 +     Gestalt(gestaltSystemVersion, &osVersion);
372 +     if (osVersion < 0x1040) // only supported for 10.4 (and up)
373 +       return noErr;
374
375 +     // C name mangling...
376 +     symbolName = "_DataBrowserChangeAttributes";
377 +     if (!NSIsSymbolNameDefined(symbolName)
378 +           || (symbol = NSLookupAndBindSymbol(symbolName)) == NULL)
379 +       return noErr;
380
381 +     dataBrowserChangeAttributes = NSAddressOfSymbol(symbol);
382 +     if (dataBrowserChangeAttributes == NULL)
383 +       return noErr; // well...
384 +     return dataBrowserChangeAttributes(inDataBrowser,
385 +                                     inAttributesToSet, inAttributesToClear);
386 + }
387
388 +     static void
389 + initialise_tabline(void)
390 + {
391 +     Rect drawerRect = { 0, 0, 0, DRAWER_SIZE };
392 +     DataBrowserCallbacks dbCallbacks;
393 +     EventTypeSpec focusEvent = {kEventClassControl, kEventControlSetFocusPart};
394 +     EventTypeSpec resizeEvent = {kEventClassWindow, kEventWindowBoundsChanged};
395 +     DataBrowserListViewColumnDesc colDesc;
396
397 +     // drawers have to have compositing enabled
398 +     CreateNewWindow(kDrawerWindowClass,
399 +           kWindowStandardHandlerAttribute
400 +                   | kWindowCompositingAttribute
401 +                   | kWindowResizableAttribute
402 +                   | kWindowLiveResizeAttribute,
403 +           &drawerRect, &drawer);
404
405 +     SetThemeWindowBackground(drawer, kThemeBrushDrawerBackground, true);
406 +     SetDrawerParent(drawer, gui.VimWindow);
407 +     SetDrawerOffsets(drawer, kWindowOffsetUnchanged, DRAWER_INSET);
408
409
410 +     // create list view embedded in drawer
411 +     CreateDataBrowserControl(drawer, &drawerRect, kDataBrowserListView,
412 +                                                               &dataBrowser);
413
414 +     dbCallbacks.version = kDataBrowserLatestCallbacks;
415 +     InitDataBrowserCallbacks(&dbCallbacks);
416 +     dbCallbacks.u.v1.itemDataCallback =
417 +                               NewDataBrowserItemDataUPP(dbItemDataCallback);
418 +     dbCallbacks.u.v1.itemNotificationCallback =
419 +               NewDataBrowserItemNotificationUPP(dbItemNotificationCallback);
420 +     dbCallbacks.u.v1.getContextualMenuCallback =
421 +             NewDataBrowserGetContextualMenuUPP(dbGetContextualMenuCallback);
422 +     dbCallbacks.u.v1.selectContextualMenuCallback =
423 +       NewDataBrowserSelectContextualMenuUPP(dbSelectContextualMenuCallback);
424
425 +     SetDataBrowserCallbacks(dataBrowser, &dbCallbacks);
426
427 +     SetDataBrowserListViewHeaderBtnHeight(dataBrowser, 0); // no header
428 +     SetDataBrowserHasScrollBars(dataBrowser, false, true); // only vertical
429 +     SetDataBrowserSelectionFlags(dataBrowser,
430 +             kDataBrowserSelectOnlyOne | kDataBrowserNeverEmptySelectionSet);
431 +     SetDataBrowserTableViewHiliteStyle(dataBrowser,
432 +                                            kDataBrowserTableViewFillHilite);
433 +     Boolean b = false;
434 +     SetControlData(dataBrowser, kControlEntireControl,
435 +                 kControlDataBrowserIncludesFrameAndFocusTag, sizeof(b), &b);
436
437 +     // enable blue background in data browser (this is only in 10.4 and vim
438 +     // has to support older osx versions as well, so we have to load this
439 +     // function dynamically)
440 +     myDataBrowserChangeAttributes(dataBrowser,
441 +                     kMyDataBrowserAttributeListViewAlternatingRowColors, 0);
442
443 +     // install callback that keeps focus in vim and away from the data browser
444 +     InstallControlEventHandler(dataBrowser, dbFocusCallback, 1, &focusEvent,
445 +                                                                 NULL, NULL);
446
447 +     // install callback that keeps data browser at the size of the drawer
448 +     InstallWindowEventHandler(drawer, drawerCallback, 1, &resizeEvent,
449 +                                                                 NULL, NULL);
450
451 +     // add "tabs" column to data browser
452 +     colDesc.propertyDesc.propertyID = kTabsColumn;
453 +     colDesc.propertyDesc.propertyType = kDataBrowserTextType;
454
455 +     // add if items can be selected (?): kDataBrowserListViewSelectionColumn
456 +     colDesc.propertyDesc.propertyFlags = kDataBrowserDefaultPropertyFlags;
457
458 +     colDesc.headerBtnDesc.version = kDataBrowserListViewLatestHeaderDesc;
459 +     colDesc.headerBtnDesc.minimumWidth = 100;
460 +     colDesc.headerBtnDesc.maximumWidth = 150;
461 +     colDesc.headerBtnDesc.titleOffset = 0;
462 +     colDesc.headerBtnDesc.titleString = CFSTR("Tabs");
463 +     colDesc.headerBtnDesc.initialOrder = kDataBrowserOrderIncreasing;
464 +     colDesc.headerBtnDesc.btnFontStyle.flags = 0; // use default font
465 +     colDesc.headerBtnDesc.btnContentInfo.contentType = kControlContentTextOnly;
466
467 +     AddDataBrowserListViewColumn(dataBrowser, &colDesc, 0);
468
469 +     // create tabline popup menu required by vim docs (see :he tabline-menu)
470 +     CreateNewMenu(kTabContextMenuId, 0, &contextMenu);
471 +     AppendMenuItemTextWithCFString(contextMenu, CFSTR("Close"), 0,
472 +                                                   TABLINE_MENU_CLOSE, NULL);
473 +     AppendMenuItemTextWithCFString(contextMenu, CFSTR("New Tab"), 0,
474 +                                                     TABLINE_MENU_NEW, NULL);
475 +     AppendMenuItemTextWithCFString(contextMenu, CFSTR("Open Tab..."), 0,
476 +                                                    TABLINE_MENU_OPEN, NULL);
477 + }
478
479
480 + /*
481 +  * Show or hide the tabline.
482 +  */
483 +     void
484 + gui_mch_show_tabline(int showit)
485 + {
486 +     if (showit == 0)
487 +         CloseDrawer(drawer, true);
488 +     else
489 +         OpenDrawer(drawer, kWindowEdgeRight, true);
490 + }
491
492 + /*
493 +  * Return TRUE when tabline is displayed.
494 +  */
495 +     int
496 + gui_mch_showing_tabline(void)
497 + {
498 +     WindowDrawerState state = GetDrawerState(drawer);
499
500 +     return state == kWindowDrawerOpen || state == kWindowDrawerOpening;
501 + }
502
503 + /*
504 +  * Update the labels of the tabline.
505 +  */
506 +     void
507 + gui_mch_update_tabline(void)
508 + {
509 +     tabpage_T *tp;
510 +     int               numTabs = getTabCount();
511 +     int               nr = 1;
512 +     int               curtabidx = 1;
513
514 +     // adjust data browser
515 +     if (tabLabels != NULL)
516 +     {
517 +         int i;
518
519 +         for (i = 0; i < tabLabelsSize; ++i)
520 +             CFRelease(tabLabels[i]);
521 +         free(tabLabels);
522 +     }
523 +     tabLabels = (CFStringRef *)malloc(numTabs * sizeof(CFStringRef));
524 +     tabLabelsSize = numTabs;
525
526 +     for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, ++nr)
527 +     {
528 +       if (tp == curtab)
529 +           curtabidx = nr;
530 +         tabLabels[nr-1] = getTabLabel(tp);
531 +     }
532
533 +     RemoveDataBrowserItems(dataBrowser, kDataBrowserNoItem, 0, NULL,
534 +                                                 kDataBrowserItemNoProperty);
535 +     // data browser uses ids 1, 2, 3, ... numTabs per default, so we
536 +     // can pass NULL for the id array
537 +     AddDataBrowserItems(dataBrowser, kDataBrowserNoItem, numTabs, NULL,
538 +                                                 kDataBrowserItemNoProperty);
539
540 +     DataBrowserItemID item = curtabidx;
541 +     SetDataBrowserSelectedItems(dataBrowser, 1, &item, kDataBrowserItemsAssign);
542 + }
543
544 + /*
545 +  * Set the current tab to "nr".  First tab is 1.
546 +  */
547 +     void
548 + gui_mch_set_curtab(nr)
549 +     int               nr;
550 + {
551 +     DataBrowserItemID item = nr;
552 +     SetDataBrowserSelectedItems(dataBrowser, 1, &item, kDataBrowserItemsAssign);
553
554 +     // TODO: call something like this?: (or restore scroll position, or...)
555 +     RevealDataBrowserItem(dataBrowser, item, kTabsColumn,
556 +                                                     kDataBrowserRevealOnly);
557 + }
558
559 + #endif // FEAT_GUI_TABLINE
560 *** ../vim-7.0.231/src/proto/gui_mac.pro        Tue Mar 28 23:01:02 2006
561 --- src/proto/gui_mac.pro       Thu Mar 15 20:23:42 2007
562 ***************
563 *** 84,89 ****
564 --- 84,93 ----
565   int gui_mch_dialog __ARGS((int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield));
566   char_u *gui_mch_browse __ARGS((int saving, char_u *title, char_u *dflt, char_u *ext, char_u *initdir, char_u *filter));
567   void gui_mch_set_foreground __ARGS((void));
568 + void gui_mch_show_tabline __ARGS((int showit));
569 + int gui_mch_showing_tabline __ARGS((void));
570 + void gui_mch_update_tabline __ARGS((void));
571 + void gui_mch_set_curtab __ARGS((int nr));
572   
573   char_u *C2Pascal_save __ARGS((char_u *Cstring));
574   char_u *C2Pascal_save_and_remove_backslash __ARGS((char_u *Cstring));
575 *** ../vim-7.0.231/src/version.c        Thu Apr 26 17:23:28 2007
576 --- src/version.c       Thu Apr 26 18:17:42 2007
577 ***************
578 *** 668,669 ****
579 --- 668,671 ----
580   {   /* Add new patch number below this line */
581 + /**/
582 +     232,
583   /**/
584
585 -- 
586 hundred-and-one symptoms of being an internet addict:
587 24. You realize there is not a sound in the house and you have no idea where
588     your children are.
589
590  /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net   \\\
591 ///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
592 \\\        download, build and distribute -- http://www.A-A-P.org        ///
593  \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///
This page took 0.064937 seconds and 3 git commands to generate.