- Fixed bug where tab bar controller never removed itself as an observer - Shutdown changed; when connection dies, cleanup is called where all delegates, notifications etc. are reset. - Views are now initialized in the designated initializer of MMWindowController instead of in the nib. For some reason some object in the nib got deallocated more than once and this caused EXC_BAD_ACCESS errors. Hopefully this bug is now fixed. - Put @try/@catch clause around processInput:data: DO call since this can throw an exception if the underlying port is dead. - GUI status line is no longer used. - Added description methods to MMWindowController and MMVimController.

git-svn-id: http://macvim.googlecode.com/svn/trunk@144 96c4425d-ca35-0410-94e5-3396d5c13a8f
This commit is contained in:
Bjorn Winckler
2007-08-16 08:56:10 +00:00
parent c9ce3ae679
commit 9973a221fa
6 changed files with 247 additions and 106 deletions
+2
View File
@@ -220,6 +220,8 @@
- (void)removeVimController:(id)controller
{
[[controller windowController] close];
[vimControllers removeObject:controller];
if (![vimControllers count]) {
+3
View File
@@ -57,6 +57,8 @@ static int specialKeyToNSKey(int key);
- (void)dealloc
{
//NSLog(@"%@ %s", [self className], _cmd);
[[NSNotificationCenter defaultCenter] removeObserver:self];
[queue release];
@@ -295,6 +297,7 @@ static int specialKeyToNSKey(int key);
// By invalidating the NSConnection the MMWindowController immediately
// finds out that the connection is down and as a result
// [MMWindowController connectionDidDie:] is invoked.
//NSLog(@"%@ %s", [self className], _cmd);
[[NSNotificationCenter defaultCenter] removeObserver:self];
[connection invalidate];
}
+2 -1
View File
@@ -18,6 +18,7 @@
@interface MMVimController : NSObject <MMFrontendProtocol>
{
BOOL isInitialized;
MMWindowController *windowController;
id backendProxy;
BOOL inProcessCommandQueue;
@@ -32,7 +33,7 @@
- (id)initWithBackend:(id)backend;
- (id)backendProxy;
- (MMWindowController *)windowController;
- (void)windowWillClose:(NSNotification *)notification;
- (void)cleanup;
- (void)sendMessage:(int)msgid data:(NSData *)data wait:(BOOL)wait;
@end
+72 -14
View File
@@ -93,6 +93,23 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag)
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(connectionDidDie:)
name:NSConnectionDidDieNotification object:connection];
NSWindow *win = [windowController window];
#if 0
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(windowWillClose:)
name:NSWindowWillCloseNotification
object:win];
#endif
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(windowDidBecomeMain:)
name:NSWindowDidBecomeMainNotification
object:win];
isInitialized = YES;
}
return self;
@@ -101,17 +118,16 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag)
- (void)dealloc
{
//NSLog(@"%@ %s", [self className], _cmd);
isInitialized = NO;
[[NSNotificationCenter defaultCenter] removeObserver:self];
[backendProxy release]; backendProxy = nil;
[sendQueue release]; sendQueue = nil;
[backendProxy release];
[sendQueue release];
[toolbarItemDict release];
[toolbar release];
[popupMenuItems release];
[mainMenuItems release];
[windowController release];
[toolbarItemDict release]; toolbarItemDict = nil;
[toolbar release]; toolbar = nil;
[popupMenuItems release]; popupMenuItems = nil;
[mainMenuItems release]; mainMenuItems = nil;
[windowController release]; windowController = nil;
[super dealloc];
}
@@ -123,6 +139,8 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag)
- (void)sendMessage:(int)msgid data:(NSData *)data wait:(BOOL)wait
{
if (!isInitialized) return;
if (inProcessCommandQueue) {
//NSLog(@"In process command queue; delaying message send.");
[sendQueue addObject:[NSNumber numberWithInt:msgid]];
@@ -134,7 +152,13 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag)
}
if (wait) {
[backendProxy processInput:msgid data:data];
@try {
[backendProxy processInput:msgid data:data];
}
@catch (NSException *e) {
NSLog(@"%@ %s Exception caught during DO call: %@",
[self className], _cmd, e);
}
} else {
// Do not wait for the message to be sent, i.e. drop the message if it
// can't be delivered immediately.
@@ -161,10 +185,23 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag)
return backendProxy;
}
- (void)cleanup
{
//NSLog(@"%@ %s", [self className], _cmd);
if (!isInitialized) return;
isInitialized = NO;
[toolbar setDelegate:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self];
[windowController cleanup];
}
- (oneway void)showSavePanelForDirectory:(in bycopy NSString *)dir
title:(in bycopy NSString *)title
saving:(int)saving
{
if (!isInitialized) return;
[windowController setStatusText:title];
if (saving) {
@@ -186,6 +223,8 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag)
- (oneway void)processCommandQueue:(in NSArray *)queue
{
if (!isInitialized) return;
unsigned i, count = [queue count];
if (count % 2) {
NSLog(@"WARNING: Uneven number of components (%d) in flush queue "
@@ -239,17 +278,24 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag)
}
}
#if 0
- (void)windowWillClose:(NSNotification *)notification
{
NSLog(@"%@ %s%@", [self className], _cmd, notification);
//[self cleanup];
// NOTE! This causes the call to removeVimController: to be delayed.
[[NSApp delegate]
performSelectorOnMainThread:@selector(removeVimController:)
withObject:self waitUntilDone:NO];
}
#endif
- (void)windowDidBecomeMain:(NSNotification *)notification
{
[self updateMainMenu];
if (isInitialized)
[self updateMainMenu];
}
- (NSToolbarItem *)toolbar:(NSToolbar *)theToolbar
@@ -839,6 +885,7 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag)
- (void)updateMainMenu
{
#if 1
NSMenu *mainMenu = [NSApp mainMenu];
// Stop NSApp from updating the Window menu.
@@ -873,6 +920,7 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag)
[NSApp setWindowsMenu:windowMenu];
}
#endif
shouldUpdateMainMenu = NO;
}
@@ -964,9 +1012,14 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag)
- (void)connectionDidDie:(NSNotification *)notification
{
//NSLog(@"A MMVimController lost its connection to the backend; "
// "closing the controller.");
[windowController close];
//NSLog(@"%@ %s%@", [self className], _cmd, notification);
[self cleanup];
// NOTE! This causes the call to removeVimController: to be delayed.
[[NSApp delegate]
performSelectorOnMainThread:@selector(removeVimController:)
withObject:self waitUntilDone:NO];
}
- (BOOL)executeActionWithName:(NSString *)name
@@ -1004,6 +1057,11 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag)
return NO;
}
- (NSString *)description
{
return [NSString stringWithFormat:@"%@ : isInitialized=%d inProcessCommandQueue=%d mainMenuItems=%@ popupMenuItems=%@ toolbar=%@", [self className], isInitialized, inProcessCommandQueue, mainMenuItems, popupMenuItems, toolbar];
}
@end // MMVimController (Private)
+5
View File
@@ -10,6 +10,10 @@
#import <Cocoa/Cocoa.h>
#define MM_USE_EMPTY_WINDOW 1
@class PSMTabBarControl;
@class MMTextView;
@class MMTextStorage;
@@ -40,6 +44,7 @@
- (MMTextStorage *)textStorage;
- (NSString *)windowAutosaveKey;
- (void)setWindowAutosaveKey:(NSString *)key;
- (void)cleanup;
- (void)openWindow;
- (void)updateTabsWithData:(NSData *)data;
- (void)selectTabWithIndex:(int)idx;
+163 -91
View File
@@ -98,7 +98,12 @@ NSMutableArray *buildMenuAddress(NSMenu *menu)
- (id)initWithVimController:(MMVimController *)controller
{
if ((self = [super initWithWindowNibName:@"VimWindow"])) {
#if MM_USE_EMPTY_WINDOW
if ((self = [super initWithWindowNibName:@"EmptyWindow"]))
#else
if ((self = [super initWithWindowNibName:@"VimWindow"]))
#endif
{
vimController = controller;
scrollbars = [[NSMutableArray alloc] init];
@@ -130,7 +135,8 @@ NSMutableArray *buildMenuAddress(NSMenu *menu)
[textStorage addLayoutManager:lm];
[lm addTextContainer:tc];
textView = [[MMTextView alloc] initWithFrame:NSZeroRect
NSView *contentView = [[self window] contentView];
textView = [[MMTextView alloc] initWithFrame:[contentView frame]
textContainer:tc];
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
@@ -138,10 +144,57 @@ NSMutableArray *buildMenuAddress(NSMenu *menu)
int top = [ud integerForKey:MMTextInsetTopKey];
[textView setTextContainerInset:NSMakeSize(left, top)];
[contentView addSubview:textView];
// The text storage retains the layout manager which in turn retains
// the text container.
[tc release];
[lm release];
#if MM_USE_EMPTY_WINDOW
// Create the tabline separator (which may be visible when the tabline
// is hidden).
NSRect tabSepRect = [contentView frame];
tabSepRect.origin.y = NSMaxY(tabSepRect)-1;
tabSepRect.size.height = 1;
tablineSeparator = [[NSBox alloc] initWithFrame:tabSepRect];
// Create the tab view (which is never visible, but the tab bar control
// needs it to function).
tabView = [[NSTabView alloc] initWithFrame:NSZeroRect];
// Create the tab bar control (which is responsible for actually
// drawing the tabline and tabs).
NSRect tabFrame = [contentView frame];
tabFrame.origin.y = NSMaxY(tabFrame) - 22;
tabFrame.size.height = 22;
tabBarControl = [[PSMTabBarControl alloc] initWithFrame:tabFrame];
[tabView setDelegate:tabBarControl];
[tabBarControl setTabView:tabView];
[tabBarControl setDelegate:self];
[tabBarControl setHidden:YES];
[tabBarControl setAutoresizingMask:NSViewWidthSizable|NSViewMinYMargin];
[tabBarControl setCellMinWidth:[ud integerForKey:MMTabMinWidthKey]];
[tabBarControl setCellMaxWidth:[ud integerForKey:MMTabMaxWidthKey]];
[tabBarControl setCellOptimumWidth:
[ud integerForKey:MMTabOptimumWidthKey]];
[tabBarControl setAllowsDragBetweenWindows:NO];
[tablineSeparator setBoxType:NSBoxSeparator];
[tablineSeparator setHidden:NO];
[tablineSeparator setAutoresizingMask:NSViewWidthSizable
| NSViewMinYMargin];
[contentView setAutoresizesSubviews:YES];
[contentView addSubview:tabBarControl];
[contentView addSubview:tablineSeparator];
[[self window] setDelegate:self];
[[self window] setInitialFirstResponder:textView];
#endif
}
return self;
@@ -151,29 +204,33 @@ NSMutableArray *buildMenuAddress(NSMenu *menu)
{
//NSLog(@"%@ %s", [self className], _cmd);
// TODO: release tabBarControl and tabView?
#if MM_USE_EMPTY_WINDOW
[tabBarControl release]; tabBarControl = nil;
[tabView release]; tabView = nil;
[tablineSeparator release]; tablineSeparator = nil;
#endif
[windowAutosaveKey release]; windowAutosaveKey = nil;
[scrollbars release]; scrollbars = nil;
[textView release]; textView = nil;
[textStorage release]; textStorage = nil;
vimController = nil;
[tabBarControl setDelegate:nil];
[[self window] setDelegate:nil];
[tabView removeAllTabViewItems];
[scrollbars release];
[textView release];
[textStorage release];
//[tabBarControl release]; tabBarControl = nil;
//[tabView release]; tabView = nil;
[super dealloc];
}
- (NSString *)description
{
return [NSString stringWithFormat:@"%@ : setupDone=%d windowAutosaveKey=%@ vimController=%@", [self className], setupDone, windowAutosaveKey, vimController];
}
#if !MM_USE_EMPTY_WINDOW
- (void)windowDidLoad
{
NSWindow *win = [self window];
// Called after window nib file is loaded.
[tablineSeparator setHidden:NO];
[tablineSeparator setHidden:([[self window] toolbar] == nil)];
[tabBarControl setHidden:YES];
// NOTE: Size to fit looks good, but not many tabs will fit and there are
@@ -186,29 +243,15 @@ NSMutableArray *buildMenuAddress(NSMenu *menu)
[tabBarControl setCellOptimumWidth:[ud integerForKey:MMTabOptimumWidthKey]];
[tabBarControl setAllowsDragBetweenWindows:NO];
[tabBarControl setShowAddTabButton:YES];
[[tabBarControl addTabButton] setTarget:self];
[[tabBarControl addTabButton] setAction:@selector(addNewTab:)];
//[tabBarControl setShowAddTabButton:YES];
//[[tabBarControl addTabButton] setTarget:self];
//[[tabBarControl addTabButton] setAction:@selector(addNewTab:)];
// HACK! remove any tabs present in the nib
[tabView removeAllTabViewItems];
// HACK! These observers used to be set in the designated init of
// MMVimController, but this occasionally caused exceptions from within the
// AppKit to be raised. The problem seemed related to the fact that the
// window got loaded 'too early'; adding the observers here seems to
// alleviate this problem.
[[NSNotificationCenter defaultCenter]
addObserver:vimController
selector:@selector(windowWillClose:)
name:NSWindowWillCloseNotification
object:win];
[[NSNotificationCenter defaultCenter]
addObserver:vimController
selector:@selector(windowDidBecomeMain:)
name:NSWindowDidBecomeMainNotification
object:win];
[tabView setHidden:YES];
}
#endif
- (MMVimController *)vimController
{
@@ -236,6 +279,44 @@ NSMutableArray *buildMenuAddress(NSMenu *menu)
windowAutosaveKey = [key copy];
}
- (void)cleanup
{
//NSLog(@"%@ %s", [self className], _cmd);
setupDone = NO;
vimController = nil;
// NOTE! There is a bug in PSMTabBarControl in that it retains the delegate
// (which is the MMWindowController) so reset the delegate here, otherwise
// the MMWindowController never gets released resulting in a pretty serious
// memory leak.
[tabView setDelegate:nil];
[tabBarControl setDelegate:nil];
[tabBarControl setTabView:nil];
[[self window] setDelegate:nil];
// NOTE! There is another bug in PSMTabBarControl where the control is not
// removed as an observer, so remove it here (else lots of evil nasty bugs
// will come and gnaw at your feet while you are sleeping).
[[NSNotificationCenter defaultCenter] removeObserver:tabBarControl];
#if MM_USE_EMPTY_WINDOW
[tabBarControl removeFromSuperviewWithoutNeedingDisplay];
[tablineSeparator removeFromSuperviewWithoutNeedingDisplay];
#endif
[textView removeFromSuperviewWithoutNeedingDisplay];
unsigned i, count = [scrollbars count];
for (i = 0; i < count; ++i) {
MMScroller *sb = [scrollbars objectAtIndex:i];
[sb removeFromSuperviewWithoutNeedingDisplay];
}
[tabView removeAllTabViewItems];
[[self window] orderOut:self];
}
- (void)openWindow
{
[[NSApp delegate] windowControllerWillOpen:self];
@@ -245,15 +326,17 @@ NSMutableArray *buildMenuAddress(NSMenu *menu)
// NOTE! This flag is set once the entire text system is set up.
setupDone = YES;
[self updateResizeIncrements];
[self resizeWindowToFit:self];
[[self window] makeKeyAndOrderFront:self];
#if !MM_USE_EMPTY_WINDOW
BOOL statusOff = [[NSUserDefaults standardUserDefaults]
boolForKey:MMStatuslineOffKey];
[statusTextField setHidden:statusOff];
[statusSeparator setHidden:statusOff];
[self flashStatusText:@"Welcome to MacVim!"];
#endif
[self updateResizeIncrements];
[self resizeWindowToFit:self];
[[self window] makeKeyAndOrderFront:self];
}
- (void)updateTabsWithData:(NSData *)data
@@ -339,14 +422,17 @@ NSMutableArray *buildMenuAddress(NSMenu *menu)
- (void)setStatusText:(NSString *)text
{
#if !MM_USE_EMPTY_WINDOW
if (text)
[statusTextField setStringValue:text];
else
[statusTextField setStringValue:@""];
#endif
}
- (void)flashStatusText:(NSString *)text
{
#if !MM_USE_EMPTY_WINDOW
if ([[NSUserDefaults standardUserDefaults] boolForKey:MMStatuslineOffKey])
return;
@@ -362,6 +448,7 @@ NSMutableArray *buildMenuAddress(NSMenu *menu)
selector:@selector(statusTimerFired:)
userInfo:nil
repeats:NO] retain];
#endif
}
- (void)createScrollbarWithIdentifier:(long)ident type:(int)type
@@ -517,15 +604,15 @@ NSMutableArray *buildMenuAddress(NSMenu *menu)
- (IBAction)addNewTab:(id)sender
{
// NOTE! This can get called a lot if the user holds down the key
// equivalent for this action, which causes the ports to fill up. If we
// wait for the message to be sent then the app might become unresponsive.
[vimController sendMessage:AddNewTabMsgID data:nil wait:NO];
// NOTE! This can get called a lot if the user holds down the key
// equivalent for this action, which causes the ports to fill up. If we
// wait for the message to be sent then the app might become unresponsive.
[vimController sendMessage:AddNewTabMsgID data:nil wait:NO];
}
- (IBAction)toggleToolbar:(id)sender
{
[vimController sendMessage:ToggleToolbarMsgID data:nil wait:NO];
[vimController sendMessage:ToggleToolbarMsgID data:nil wait:NO];
}
@@ -536,14 +623,16 @@ NSMutableArray *buildMenuAddress(NSMenu *menu)
- (void)tabView:(NSTabView *)theTabView didSelectTabViewItem:
(NSTabViewItem *)tabViewItem
{
// HACK! There seem to be a bug in NSTextView which results in the first
// responder not being set to the view of the tab item so it is done
// manually here.
[[self window] makeFirstResponder:[tabViewItem view]];
#if !MM_USE_EMPTY_WINDOW
// HACK! There seem to be a bug in NSTabView which results in the first
// responder not being set to the view of the tab item so it is done
// manually here.
//[[self window] makeFirstResponder:[tabViewItem view]];
#endif
// HACK! The selection message should not be propagated to the VimTask if
// the VimTask selected the tab (e.g. as opposed the user clicking the
// tab). The delegate method has no way of knowing who initiated the
// HACK! The selection message should not be propagated to the VimTask if
// the VimTask selected the tab (e.g. as opposed the user clicking the
// tab). The delegate method has no way of knowing who initiated the
// selection so a flag is set when the VimTask initiated the selection.
if (!vimTaskSelectedTab) {
// Propagate the selection message to the VimTask.
@@ -590,17 +679,6 @@ NSMutableArray *buildMenuAddress(NSMenu *menu)
return NO;
}
- (void)windowWillClose:(NSNotification *)notification
{
//NSLog(@"%@ %s", [self className], _cmd);
// NOTE! There is a bug in PSMTabBarControl in that it retains the delegate
// (which is the MMWindowController) so reset the delegate here, otherwise
// the MMWindowController never gets released resulting in a pretty serious
// memory leak.
[tabBarControl setDelegate:nil];
}
- (void)windowDidMove:(NSNotification *)notification
{
if (setupDone && windowAutosaveKey) {
@@ -846,11 +924,6 @@ NSMutableArray *buildMenuAddress(NSMenu *menu)
// will automatically select the first tab added to a tab view.
NSTabViewItem *tvi = [[NSTabViewItem alloc] initWithIdentifier:nil];
[tvi setView:textView];
// BUG! This call seems to have no effect; see comment in
// tabView:didSelectTabViewItem:.
//[tvi setInitialFirstResponder:textView];
// NOTE: If this is the first tab it will be automatically selected.
vimTaskSelectedTab = YES;
@@ -939,8 +1012,7 @@ NSMutableArray *buildMenuAddress(NSMenu *menu)
{
if (!setupDone) return;
NSRect tabViewFrame = [tabView frame];
NSView *contentView = [[self window] contentView];
NSRect textViewFrame = [textView frame];
BOOL lsbVisible = [self leftScrollbarVisible];
BOOL statusVisible = ![[NSUserDefaults standardUserDefaults]
boolForKey:MMStatuslineOffKey];
@@ -994,28 +1066,28 @@ NSMutableArray *buildMenuAddress(NSMenu *menu)
// text view all the way to the right, otherwise it looks ugly when
// the user drags the window to resize.
if (i == leftmostSbIdx) {
float w = NSMaxX(tabViewFrame) - NSMaxX(rect);
float w = NSMaxX(textViewFrame) - NSMaxX(rect);
if (w > 0)
rect.size.width += w;
}
// Make sure scrollbar rect is bounded by the tab view frame.
if (rect.origin.x < tabViewFrame.origin.x)
rect.origin.x = tabViewFrame.origin.x;
else if (rect.origin.x > NSMaxX(tabViewFrame))
rect.origin.x = NSMaxX(tabViewFrame);
if (NSMaxX(rect) > NSMaxX(tabViewFrame))
rect.size.width -= NSMaxX(rect) - NSMaxX(tabViewFrame);
// Make sure scrollbar rect is bounded by the text view frame.
if (rect.origin.x < textViewFrame.origin.x)
rect.origin.x = textViewFrame.origin.x;
else if (rect.origin.x > NSMaxX(textViewFrame))
rect.origin.x = NSMaxX(textViewFrame);
if (NSMaxX(rect) > NSMaxX(textViewFrame))
rect.size.width -= NSMaxX(rect) - NSMaxX(textViewFrame);
if (rect.size.width < 0)
rect.size.width = 0;
} else {
rect = [textStorage rectForRowsInRange:[scroller range]];
// Adjust for the fact that text layout is flipped.
rect.origin.y = NSMaxY(tabViewFrame) - rect.origin.y
rect.origin.y = NSMaxY(textViewFrame) - rect.origin.y
- rect.size.height;
rect.size.width = [NSScroller scrollerWidth];
if ([scroller type] == MMScrollerTypeRight)
rect.origin.x = NSMaxX(tabViewFrame);
rect.origin.x = NSMaxX(textViewFrame);
// HACK! Make sure the lowest vertical scrollbar covers the text
// view all the way to the bottom. This is done because Vim only
@@ -1025,9 +1097,9 @@ NSMutableArray *buildMenuAddress(NSMenu *menu)
// TODO! Find a nicer way to do this.
if (i == lowestLeftSbIdx || i == lowestRightSbIdx) {
float h = rect.origin.y + rect.size.height
- tabViewFrame.origin.y;
- textViewFrame.origin.y;
if (rect.size.height < h) {
rect.origin.y = tabViewFrame.origin.y;
rect.origin.y = textViewFrame.origin.y;
rect.size.height = h;
}
}
@@ -1039,14 +1111,14 @@ NSMutableArray *buildMenuAddress(NSMenu *menu)
rect.origin.y = [NSScroller scrollerWidth];
}
// Make sure scrollbar rect is bounded by the tab view frame.
if (rect.origin.y < tabViewFrame.origin.y) {
rect.size.height -= tabViewFrame.origin.y - rect.origin.y;
rect.origin.y = tabViewFrame.origin.y;
} else if (rect.origin.y > NSMaxY(tabViewFrame))
rect.origin.y = NSMaxY(tabViewFrame);
if (NSMaxY(rect) > NSMaxY(tabViewFrame))
rect.size.height -= NSMaxY(rect) - NSMaxY(tabViewFrame);
// Make sure scrollbar rect is bounded by the text view frame.
if (rect.origin.y < textViewFrame.origin.y) {
rect.size.height -= textViewFrame.origin.y - rect.origin.y;
rect.origin.y = textViewFrame.origin.y;
} else if (rect.origin.y > NSMaxY(textViewFrame))
rect.origin.y = NSMaxY(textViewFrame);
if (NSMaxY(rect) > NSMaxY(textViewFrame))
rect.size.height -= NSMaxY(rect) - NSMaxY(textViewFrame);
if (rect.size.height < 0)
rect.size.height = 0;
}
@@ -1057,7 +1129,7 @@ NSMutableArray *buildMenuAddress(NSMenu *menu)
[scroller setFrame:rect];
// Clear behind the old scroller frame, or parts of the old
// scroller might still be visible after setFrame:.
[contentView setNeedsDisplayInRect:oldRect];
[[[self window] contentView] setNeedsDisplayInRect:oldRect];
[scroller setNeedsDisplay:YES];
}
}
@@ -1108,7 +1180,7 @@ NSMutableArray *buildMenuAddress(NSMenu *menu)
wait:![textView inLiveResize]];
}
[tabView setFrame:textViewRect];
[textView setFrame:textViewRect];
[self placeScrollbars];
}