1 /* vi:set ts=8 sts=4 sw=4 ft=objc:
3 * VIM - Vi IMproved by Bram Moolenaar
4 * MacVim GUI port by Bjorn Winckler
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.
13 * Handles resizing of windows, acts as an mediator between MMVimView and
16 * Resizing in windowed mode:
18 * In windowed mode resizing can occur either due to the window frame changing
19 * size (e.g. when the user drags to resize), or due to Vim changing the number
20 * of (rows,columns). The former case is dealt with by letting the vim view
21 * fill the entire content view when the window has resized. In the latter
22 * case we ensure that vim view fits on the screen.
24 * The vim view notifies Vim if the number of (rows,columns) does not match the
25 * current number whenver the view size is about to change. Upon receiving a
26 * dimension change message, Vim notifies the window controller and the window
27 * resizes. However, the window is never resized programmatically during a
28 * live resize (in order to avoid jittering).
30 * The window size is constrained to not become too small during live resize,
31 * and it is also constrained to always fit an integer number of
34 * In windowed mode we have to manually draw a tabline separator (due to bugs
35 * in the way Cocoa deals with the toolbar separator) when certain conditions
36 * are met. The rules for this are as follows:
38 * Tabline visible & Toolbar visible => Separator visible
39 * =====================================================================
40 * NO & NO => YES, if the window is textured
47 * Resizing in full-screen mode:
49 * The window never resizes since it fills the screen, however the vim view may
50 * change size, e.g. when the user types ":set lines=60", or when a scrollbar
53 * It is ensured that the vim view never becomes larger than the screen size
54 * and that it always stays in the center of the screen.
58 #import "MMWindowController.h"
59 #import "MMAppController.h"
60 #import "MMAtsuiTextView.h"
61 #import "MMFullscreenWindow.h"
62 #import "MMTextView.h"
63 #import "MMTypesetter.h"
64 #import "MMVimController.h"
69 #import <PSMTabBarControl.h>
73 @interface MMWindowController (Private)
74 - (NSSize)contentSize;
75 - (void)resizeWindowToFitContentSize:(NSSize)contentSize;
76 - (NSSize)constrainContentSizeToScreenSize:(NSSize)contentSize;
77 - (void)updateResizeConstraints;
78 - (NSTabViewItem *)addNewTabViewItem;
79 - (IBAction)vimMenuItemAction:(id)sender;
80 - (BOOL)askBackendForStarRegister:(NSPasteboard *)pb;
81 - (void)hideTablineSeparator:(BOOL)hide;
82 - (void)doFindNext:(BOOL)next;
86 @interface NSWindow (NSWindowPrivate)
87 // Note: This hack allows us to set content shadowing separately from
88 // the window shadow. This is apparently what webkit and terminal do.
89 - (void)_setContentHasShadow:(BOOL)shadow; // new Tiger private method
91 // This is a private api that makes textured windows not have rounded corners.
92 // We want this on Leopard.
93 - (void)setBottomCornerRounded:(BOOL)rounded;
97 @interface NSWindow (NSLeopardOnly)
98 // Note: These functions are Leopard-only, use -[NSObject respondsToSelector:]
99 // before calling them to make sure everything works on Tiger too.
101 #ifndef CGFLOAT_DEFINED
102 // On Leopard, CGFloat is float on 32bit and double on 64bit. On Tiger,
103 // we can't use this anyways, so it's just here to keep the compiler happy.
104 // However, when we're compiling for Tiger and running on Leopard, we
105 // might need the correct typedef, so this piece is copied from ATSTypes.h
107 typedef double CGFloat;
109 typedef float CGFloat;
112 - (void)setAutorecalculatesContentBorderThickness:(BOOL)b forEdge:(NSRectEdge)e;
113 - (void)setContentBorderThickness:(CGFloat)b forEdge:(NSRectEdge)e;
119 @implementation MMWindowController
121 - (id)initWithVimController:(MMVimController *)controller
123 #ifndef NSAppKitVersionNumber10_4 // needed for non-10.5 sdk
124 # define NSAppKitVersionNumber10_4 824
126 unsigned styleMask = NSTitledWindowMask | NSClosableWindowMask
127 | NSMiniaturizableWindowMask | NSResizableWindowMask
128 | NSUnifiedTitleAndToolbarWindowMask;
130 // Use textured background on Leopard or later (skip the 'if' on Tiger for
131 // polished metal window).
132 if ([[NSUserDefaults standardUserDefaults] boolForKey:MMTexturedWindowKey]
133 || (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_4))
134 styleMask |= NSTexturedBackgroundWindowMask;
136 // NOTE: The content rect is only used the very first time MacVim is
137 // started (or rather, when ~/Library/Preferences/org.vim.MacVim.plist does
138 // not exist). The chosen values will put the window somewhere near the
139 // top and in the middle of a 1024x768 screen.
140 MMWindow *win = [[MMWindow alloc]
141 initWithContentRect:NSMakeRect(242,364,480,360)
143 backing:NSBackingStoreBuffered
147 self = [super initWithWindow:win];
148 if (!self) return nil;
150 vimController = controller;
151 decoratedWindow = [win retain];
153 // Window cascading is handled by MMAppController.
154 [self setShouldCascadeWindows:NO];
156 // NOTE: Autoresizing is enabled for the content view, but only used
157 // for the tabline separator. The vim view must be resized manually
158 // because of full-screen considerations, and because its size depends
159 // on whether the tabline separator is visible or not.
160 NSView *contentView = [win contentView];
161 [contentView setAutoresizesSubviews:YES];
163 vimView = [[MMVimView alloc] initWithFrame:[contentView frame]
164 vimController:vimController];
165 [vimView setAutoresizingMask:NSViewNotSizable];
166 [contentView addSubview:vimView];
168 [win setDelegate:self];
169 [win setInitialFirstResponder:[vimView textView]];
171 if ([win styleMask] & NSTexturedBackgroundWindowMask) {
172 // On Leopard, we want to have a textured window to have nice
173 // looking tabs. But the textured window look implies rounded
174 // corners, which looks really weird -- disable them. This is a
175 // private api, though.
176 if ([win respondsToSelector:@selector(setBottomCornerRounded:)])
177 [win setBottomCornerRounded:NO];
179 // When the tab bar is toggled, it changes color for the fraction
180 // of a second, probably because vim sends us events in a strange
181 // order, confusing appkit's content border heuristic for a short
182 // while. This can be worked around with these two methods. There
183 // might be a better way, but it's good enough.
184 if ([win respondsToSelector:@selector(
185 setAutorecalculatesContentBorderThickness:forEdge:)])
186 [win setAutorecalculatesContentBorderThickness:NO
188 if ([win respondsToSelector:
189 @selector(setContentBorderThickness:forEdge:)])
190 [win setContentBorderThickness:0 forEdge:NSMaxYEdge];
193 // Make us safe on pre-tiger OSX
194 if ([win respondsToSelector:@selector(_setContentHasShadow:)])
195 [win _setContentHasShadow:NO];
202 //NSLog(@"%@ %s", [self className], _cmd);
204 [decoratedWindow release]; decoratedWindow = nil;
205 [windowAutosaveKey release]; windowAutosaveKey = nil;
206 [vimView release]; vimView = nil;
211 - (NSString *)description
214 @"%@ : setupDone=%d windowAutosaveKey=%@ vimController=%@";
215 return [NSString stringWithFormat:format,
216 [self className], setupDone, windowAutosaveKey, vimController];
219 - (MMVimController *)vimController
221 return vimController;
224 - (MMVimView *)vimView
229 - (NSString *)windowAutosaveKey
231 return windowAutosaveKey;
234 - (void)setWindowAutosaveKey:(NSString *)key
236 [windowAutosaveKey autorelease];
237 windowAutosaveKey = [key copy];
242 //NSLog(@"%@ %s", [self className], _cmd);
244 if (fullscreenEnabled) {
245 // If we are closed while still in fullscreen, end fullscreen mode,
246 // release ourselves (because this won't happen in MMWindowController)
247 // and perform close operation on the original window.
248 [self leaveFullscreen];
254 [vimView removeFromSuperviewWithoutNeedingDisplay];
257 // It is feasible (though unlikely) that the user quits before the window
258 // controller is released, make sure the edit flag is cleared so no warning
259 // dialog is displayed.
260 [decoratedWindow setDocumentEdited:NO];
262 [[self window] orderOut:self];
267 [[NSApp delegate] windowControllerWillOpen:self];
269 [self addNewTabViewItem];
273 [self updateResizeConstraints];
274 [self resizeWindowToFitContentSize:[vimView desiredSize]];
275 [[self window] makeKeyAndOrderFront:self];
278 - (void)updateTabsWithData:(NSData *)data
280 [vimView updateTabsWithData:data];
283 - (void)selectTabWithIndex:(int)idx
285 [vimView selectTabWithIndex:idx];
288 - (void)setTextDimensionsWithRows:(int)rows columns:(int)cols live:(BOOL)live
290 //NSLog(@"setTextDimensionsWithRows:%d columns:%d live:%s", rows, cols,
291 // live ? "YES" : "NO");
293 // NOTE: This is the only place where the (rows,columns) of the vim view
294 // are modified. Setting these values have no immediate effect, the actual
295 // resizing of the view is done in processCommandQueueDidFinish.
297 // The 'live' flag indicates that this resize originated from a live
298 // resize; it may very well happen that the view is no longer in live
299 // resize when this message is received. We refrain from changing the view
300 // size when this flag is set, otherwise the window might jitter when the
301 // user drags to resize the window.
303 [vimView setDesiredRows:rows columns:cols];
305 if (setupDone && !live)
306 shouldResizeVimView = YES;
309 - (void)setTitle:(NSString *)title
312 [decoratedWindow setTitle:title];
313 [fullscreenWindow setTitle:title];
317 - (void)setToolbar:(NSToolbar *)toolbar
319 // The full-screen window has no toolbar.
320 [decoratedWindow setToolbar:toolbar];
322 // HACK! Redirect the pill button so that we can ask Vim to hide the
324 NSButton *pillButton = [decoratedWindow
325 standardWindowButton:NSWindowToolbarButton];
327 [pillButton setAction:@selector(toggleToolbar:)];
328 [pillButton setTarget:self];
332 - (void)createScrollbarWithIdentifier:(long)ident type:(int)type
334 [vimView createScrollbarWithIdentifier:ident type:type];
337 - (BOOL)destroyScrollbarWithIdentifier:(long)ident
339 BOOL scrollbarHidden = [vimView destroyScrollbarWithIdentifier:ident];
340 shouldResizeVimView = shouldResizeVimView || scrollbarHidden;
342 return scrollbarHidden;
345 - (BOOL)showScrollbarWithIdentifier:(long)ident state:(BOOL)visible
347 BOOL scrollbarToggled = [vimView showScrollbarWithIdentifier:ident
349 shouldResizeVimView = shouldResizeVimView || scrollbarToggled;
351 return scrollbarToggled;
354 - (void)setScrollbarPosition:(int)pos length:(int)len identifier:(long)ident
356 [vimView setScrollbarPosition:pos length:len identifier:ident];
359 - (void)setScrollbarThumbValue:(float)val proportion:(float)prop
360 identifier:(long)ident
362 [vimView setScrollbarThumbValue:val proportion:prop identifier:ident];
365 - (void)setDefaultColorsBackground:(NSColor *)back foreground:(NSColor *)fore
367 // NOTE: This is called when the transparency changes so set the opacity
368 // flag on the window here (should be faster if the window is opaque).
369 BOOL isOpaque = [back alphaComponent] == 1.0f;
370 [[self window] setOpaque:isOpaque];
372 [vimView setDefaultColorsBackground:back foreground:fore];
375 - (void)setFont:(NSFont *)font
377 [[NSFontManager sharedFontManager] setSelectedFont:font isMultiple:NO];
378 [[vimView textView] setFont:font];
379 [self updateResizeConstraints];
382 - (void)setWideFont:(NSFont *)font
384 [[vimView textView] setWideFont:font];
387 - (void)processCommandQueueDidFinish
389 // NOTE: Resizing is delayed until after all commands have been processed
390 // since it often happens that more than one command will cause a resize.
391 // If we were to immediately resize then the vim view size would jitter
392 // (e.g. hiding/showing scrollbars often happens several time in one
395 if (shouldResizeVimView) {
396 shouldResizeVimView = NO;
398 NSSize contentSize = [vimView desiredSize];
399 contentSize = [self constrainContentSizeToScreenSize:contentSize];
400 contentSize = [vimView constrainRows:NULL columns:NULL
402 [vimView setFrameSize:contentSize];
404 if (fullscreenEnabled) {
405 [[fullscreenWindow contentView] setNeedsDisplay:YES];
406 [fullscreenWindow centerView];
408 [self resizeWindowToFitContentSize:contentSize];
413 - (void)popupMenu:(NSMenu *)menu atRow:(int)row column:(int)col
415 if (!setupDone) return;
418 if (row >= 0 && col >= 0) {
419 // TODO: Let textView convert (row,col) to NSPoint.
420 NSSize cellSize = [[vimView textView] cellSize];
421 NSPoint pt = { (col+1)*cellSize.width, (row+1)*cellSize.height };
422 pt = [[vimView textView] convertPoint:pt toView:nil];
424 event = [NSEvent mouseEventWithType:NSRightMouseDown
428 windowNumber:[[self window] windowNumber]
434 event = [[vimView textView] lastMouseDownEvent];
437 [NSMenu popUpContextMenu:menu withEvent:event forView:[vimView textView]];
440 - (void)showTabBar:(BOOL)on
442 [[vimView tabBarControl] setHidden:!on];
444 // Showing the tabline may result in the tabline separator being hidden or
445 // shown; this does not apply to full-screen mode.
447 NSToolbar *toolbar = [decoratedWindow toolbar];
448 if (([decoratedWindow styleMask] & NSTexturedBackgroundWindowMask)
450 [self hideTablineSeparator:![toolbar isVisible]];
452 [self hideTablineSeparator:NO];
455 if (([decoratedWindow styleMask] & NSTexturedBackgroundWindowMask)
457 [self hideTablineSeparator:on];
459 [self hideTablineSeparator:YES];
464 - (void)showToolbar:(BOOL)on size:(int)size mode:(int)mode
466 NSToolbar *toolbar = [decoratedWindow toolbar];
467 if (!toolbar) return;
469 [toolbar setSizeMode:size];
470 [toolbar setDisplayMode:mode];
471 [toolbar setVisible:on];
473 if (([decoratedWindow styleMask] & NSTexturedBackgroundWindowMask) == 0) {
475 [self hideTablineSeparator:YES];
477 [self hideTablineSeparator:![[vimView tabBarControl] isHidden]];
480 // Textured windows don't have a line below there title bar, so we
481 // need the separator in this case as well. In fact, the only case
482 // where we don't need the separator is when the tab bar control
483 // is visible (because it brings its own separator).
484 [self hideTablineSeparator:![[vimView tabBarControl] isHidden]];
488 - (void)setMouseShape:(int)shape
490 // This switch should match mshape_names[] in misc2.c.
492 // TODO: Add missing cursor shapes.
494 case 2: [[NSCursor IBeamCursor] set]; break;
495 case 3: case 4: [[NSCursor resizeUpDownCursor] set]; break;
496 case 5: case 6: [[NSCursor resizeLeftRightCursor] set]; break;
497 case 9: [[NSCursor crosshairCursor] set]; break;
498 case 10: [[NSCursor pointingHandCursor] set]; break;
499 case 11: [[NSCursor openHandCursor] set]; break;
501 [[NSCursor arrowCursor] set]; break;
504 // Shape 1 indicates that the mouse cursor should be hidden.
506 [NSCursor setHiddenUntilMouseMoves:YES];
509 - (void)adjustLinespace:(int)linespace
511 if (vimView && [vimView textView]) {
512 [[vimView textView] setLinespace:(float)linespace];
513 shouldResizeVimView = YES;
517 - (void)liveResizeWillStart
519 // Save the original title, if we haven't already.
520 if (lastSetTitle == nil) {
521 lastSetTitle = [[decoratedWindow title] retain];
525 - (void)liveResizeDidEnd
527 if (!setupDone) return;
529 // NOTE: During live resize messages from MacVim to Vim are often dropped
530 // (because too many messages are sent at once). This may lead to
531 // inconsistent states between Vim and MacVim; to avoid this we send a
532 // synchronous resize message to Vim now (this is not fool-proof, but it
533 // does seem to work quite well).
536 NSSize textViewSize = [[vimView textView] frame].size;
537 [[vimView textView] constrainRows:&constrained[0] columns:&constrained[1]
538 toSize:textViewSize];
540 //NSLog(@"End of live resize, notify Vim that text dimensions are %dx%d",
541 // constrained[1], constrained[0]);
543 NSData *data = [NSData dataWithBytes:constrained length:2*sizeof(int)];
544 BOOL sendOk = [vimController sendMessageNow:SetTextDimensionsMsgID
549 // Sending of synchronous message failed. Force the window size to
550 // match the last dimensions received from Vim, otherwise we end up
551 // with inconsistent states.
552 [self resizeWindowToFitContentSize:[vimView desiredSize]];
555 // If we saved the original title while resizing, restore it.
556 if (lastSetTitle != nil) {
557 [decoratedWindow setTitle:lastSetTitle];
558 [lastSetTitle release];
563 - (void)enterFullscreen
565 if (fullscreenEnabled) return;
567 fullscreenWindow = [[MMFullscreenWindow alloc]
568 initWithWindow:decoratedWindow view:vimView];
569 [fullscreenWindow enterFullscreen];
570 [fullscreenWindow setDelegate:self];
571 fullscreenEnabled = YES;
573 // The resize handle disappears so the vim view needs to update the
575 shouldResizeVimView = YES;
578 - (void)leaveFullscreen
580 if (!fullscreenEnabled) return;
582 fullscreenEnabled = NO;
583 [fullscreenWindow leaveFullscreen];
584 [fullscreenWindow release];
585 fullscreenWindow = nil;
587 // The vim view may be too large to fit the screen, so update it.
588 shouldResizeVimView = YES;
591 - (void)setBuffersModified:(BOOL)mod
593 // NOTE: We only set the document edited flag on the decorated window since
594 // the full-screen window has no close button anyway. (It also saves us
595 // from keeping track of the flag in two different places.)
596 [decoratedWindow setDocumentEdited:mod];
600 - (IBAction)addNewTab:(id)sender
602 [vimView addNewTab:sender];
605 - (IBAction)toggleToolbar:(id)sender
607 [vimController sendMessage:ToggleToolbarMsgID data:nil];
610 - (IBAction)performClose:(id)sender
612 // NOTE: File->Close is bound to this action message instead binding it
613 // directly to the below vim input so that File->Close also works for
614 // auxiliary windows such as the About dialog. (If we were to bind the
615 // below, then <D-w> will not close e.g. the About dialog.)
616 [vimController addVimInput:@"<C-\\><C-N>:conf q<CR>"];
619 - (IBAction)findNext:(id)sender
621 [self doFindNext:YES];
624 - (IBAction)findPrevious:(id)sender
626 [self doFindNext:NO];
630 // -- NSWindow delegate ------------------------------------------------------
632 - (void)windowDidBecomeMain:(NSNotification *)notification
634 [vimController updateMainMenu];
635 [vimController sendMessage:GotFocusMsgID data:nil];
637 if ([vimView textView]) {
638 NSFontManager *fm = [NSFontManager sharedFontManager];
639 [fm setSelectedFont:[[vimView textView] font] isMultiple:NO];
643 - (void)windowDidResignMain:(NSNotification *)notification
645 [vimController sendMessage:LostFocusMsgID data:nil];
647 if ([vimView textView])
648 [[vimView textView] hideMarkedTextField];
651 - (BOOL)windowShouldClose:(id)sender
653 // Don't close the window now; Instead let Vim decide whether to close the
655 [vimController sendMessage:VimShouldCloseMsgID data:nil];
659 - (void)windowDidMove:(NSNotification *)notification
661 if (setupDone && windowAutosaveKey) {
662 NSRect frame = [decoratedWindow frame];
663 NSPoint topLeft = { frame.origin.x, NSMaxY(frame) };
664 NSString *topLeftString = NSStringFromPoint(topLeft);
666 [[NSUserDefaults standardUserDefaults]
667 setObject:topLeftString forKey:windowAutosaveKey];
671 - (void)windowDidResize:(id)sender
673 if (!setupDone || fullscreenEnabled) return;
675 // NOTE: Since we have no control over when the window may resize (Cocoa
676 // may resize automatically) we simply set the view to fill the entire
677 // window. The vim view takes care of notifying Vim if the number of
678 // (rows,columns) changed.
679 [vimView setFrameSize:[self contentSize]];
682 - (NSRect)windowWillUseStandardFrame:(NSWindow *)win
683 defaultFrame:(NSRect)frame
685 // Keep old width and horizontal position unless user clicked while the
686 // Command key is held down, or if the MMZoomBoth user default is set.
688 NSEvent *event = [NSApp currentEvent];
689 BOOL cmdLeftClick = [event type] == NSLeftMouseUp
690 && [event modifierFlags] & NSCommandKeyMask;
691 BOOL zoomBoth = [[NSUserDefaults standardUserDefaults]
692 boolForKey:MMZoomBothKey];
693 if (zoomBoth || cmdLeftClick)
696 NSRect currentFrame = [win frame];
697 frame.size.width = currentFrame.size.width;
698 frame.origin.x = currentFrame.origin.x;
706 // -- Services menu delegate -------------------------------------------------
708 - (id)validRequestorForSendType:(NSString *)sendType
709 returnType:(NSString *)returnType
711 if ([sendType isEqual:NSStringPboardType]
712 && [self askBackendForStarRegister:nil])
715 return [super validRequestorForSendType:sendType returnType:returnType];
718 - (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard
719 types:(NSArray *)types
721 if (![types containsObject:NSStringPboardType])
724 return [self askBackendForStarRegister:pboard];
727 @end // MMWindowController
731 @implementation MMWindowController (Private)
733 - (NSSize)contentSize
735 // NOTE: Never query the content view directly for its size since it may
736 // not return the same size as contentRectForFrameRect: (e.g. when in
737 // windowed mode and the tabline separator is visible)!
738 NSWindow *win = [self window];
739 return [win contentRectForFrameRect:[win frame]].size;
742 - (void)resizeWindowToFitContentSize:(NSSize)contentSize
744 NSRect frame = [decoratedWindow frame];
745 NSRect contentRect = [decoratedWindow contentRectForFrameRect:frame];
747 // Keep top-left corner of the window fixed when resizing.
748 contentRect.origin.y -= contentSize.height - contentRect.size.height;
749 contentRect.size = contentSize;
751 frame = [decoratedWindow frameRectForContentRect:contentRect];
752 [decoratedWindow setFrame:frame display:YES];
755 - (NSSize)constrainContentSizeToScreenSize:(NSSize)contentSize
757 NSWindow *win = [self window];
758 NSRect rect = [win contentRectForFrameRect:[[win screen] visibleFrame]];
760 if (contentSize.height > rect.size.height)
761 contentSize.height = rect.size.height;
762 if (contentSize.width > rect.size.width)
763 contentSize.width = rect.size.width;
768 - (void)updateResizeConstraints
770 if (!setupDone) return;
772 // Set the resize increments to exactly match the font size; this way the
773 // window will always hold an integer number of (rows,columns).
774 NSSize cellSize = [[vimView textView] cellSize];
775 [decoratedWindow setContentResizeIncrements:cellSize];
777 NSSize minSize = [vimView minSize];
778 [decoratedWindow setContentMinSize:minSize];
781 - (NSTabViewItem *)addNewTabViewItem
783 return [vimView addNewTabViewItem];
786 - (IBAction)vimMenuItemAction:(id)sender
788 int tag = [sender tag];
790 NSMutableData *data = [NSMutableData data];
791 [data appendBytes:&tag length:sizeof(int)];
793 [vimController sendMessage:ExecuteMenuMsgID data:data];
796 - (BOOL)askBackendForStarRegister:(NSPasteboard *)pb
798 // TODO: Can this be done with evaluateExpression: instead?
800 id backendProxy = [vimController backendProxy];
804 reply = [backendProxy starRegisterToPasteboard:pb];
806 @catch (NSException *e) {
807 NSLog(@"WARNING: Caught exception in %s: \"%@\"", _cmd, e);
814 - (void)hideTablineSeparator:(BOOL)hide
816 // The full-screen window has no tabline separator so we operate on
817 // decoratedWindow instead of [self window].
818 if ([decoratedWindow hideTablineSeparator:hide]) {
819 // The tabline separator was toggled so the content view must change
821 [self updateResizeConstraints];
822 shouldResizeVimView = YES;
826 - (void)doFindNext:(BOOL)next
828 NSString *query = nil;
831 // Use current query if the search field is selected.
832 id searchField = [[self searchFieldItem] view];
833 if (searchField && [[searchField stringValue] length] > 0 &&
834 [decoratedWindow firstResponder] == [searchField currentEditor])
835 query = [searchField stringValue];
839 // Use find pasteboard for next query.
840 NSPasteboard *pb = [NSPasteboard pasteboardWithName:NSFindPboard];
841 NSArray *types = [NSArray arrayWithObject:NSStringPboardType];
842 if ([pb availableTypeFromArray:types])
843 query = [pb stringForType:NSStringPboardType];
846 NSString *input = nil;
848 // NOTE: The '/' register holds the last search string. By setting it
849 // (using the '@/' syntax) we fool Vim into thinking that it has
850 // already searched for that string and then we can simply use 'n' or
851 // 'N' to find the next/previous match.
852 input = [NSString stringWithFormat:@"<C-\\><C-N>:let @/='%@'<CR>%c",
853 query, next ? 'n' : 'N'];
855 input = next ? @"<C-\\><C-N>n" : @"<C-\\><C-N>N";
858 [vimController addVimInput:input];
861 @end // MMWindowController (Private)