diff --git a/src/MacVim/MMAppController.m b/src/MacVim/MMAppController.m index 7cb7b887f4..8eadcf13c3 100644 --- a/src/MacVim/MMAppController.m +++ b/src/MacVim/MMAppController.m @@ -481,13 +481,11 @@ fsEventCallback(ConstFSEventStreamRef streamRef, int reply = NSTerminateNow; BOOL modifiedBuffers = NO; - // Go through windows, checking for modified buffers. (Each Vim process - // tells MacVim when any buffer has been modified and MacVim sets the - // 'documentEdited' flag of the window correspondingly.) - NSEnumerator *e = [[NSApp windows] objectEnumerator]; - id window; - while ((window = [e nextObject])) { - if ([window isDocumentEdited]) { + // Go through Vim controllers, checking for modified buffers. + NSEnumerator *e = [vimControllers objectEnumerator]; + id vc; + while ((vc = [e nextObject])) { + if ([vc hasModifiedBuffer]) { modifiedBuffers = YES; break; } @@ -519,7 +517,6 @@ fsEventCallback(ConstFSEventStreamRef streamRef, // Count the number of open tabs e = [vimControllers objectEnumerator]; - id vc; while ((vc = [e nextObject])) numTabs += [[vc objectForVimStateKey:@"numTabs"] intValue]; diff --git a/src/MacVim/MMBackend.m b/src/MacVim/MMBackend.m index 92d6899367..2d389c14e5 100644 --- a/src/MacVim/MMBackend.m +++ b/src/MacVim/MMBackend.m @@ -191,7 +191,7 @@ extern GuiFont gui_mch_retain_font(GuiFont font); - (void)startOdbEditWithArguments:(NSDictionary *)args; - (void)handleXcodeMod:(NSData *)data; - (void)handleOpenWithArguments:(NSDictionary *)args; -- (BOOL)checkForModifiedBuffers; +- (int)checkForModifiedBuffers; - (void)addInput:(NSString *)input; - (void)redrawScreen; - (void)handleFindReplace:(NSDictionary *)args; @@ -1182,12 +1182,10 @@ extern GuiFont gui_mch_retain_font(GuiFont font); - (void)updateModifiedFlag { - // Notify MacVim if _any_ buffer has changed from unmodified to modified or - // vice versa. - int msgid = [self checkForModifiedBuffers] - ? BuffersModifiedMsgID : BuffersNotModifiedMsgID; - - [self queueMessage:msgid data:nil]; + int state = [self checkForModifiedBuffers]; + NSMutableData *data = [NSMutableData data]; + [data appendBytes:&state length:sizeof(int)]; + [self queueMessage:SetBuffersModifiedMsgID data:data]; } - (oneway void)processInput:(int)msgid data:(in bycopy NSData *)data @@ -1818,6 +1816,8 @@ static void netbeansReadCallback(CFSocketRef s, nil]; // Put the state before all other messages. + // TODO: If called multiple times the oldest state will be used! Should + // remove any current Vim state messages from the queue first. int msgid = SetVimStateMsgID; [outputQueue insertObject:[vimState dictionaryAsData] atIndex:0]; [outputQueue insertObject:[NSData dataWithBytes:&msgid length:sizeof(int)] @@ -2836,16 +2836,22 @@ static void netbeansReadCallback(CFSocketRef s, } } -- (BOOL)checkForModifiedBuffers +- (int)checkForModifiedBuffers { + // Return 1 if current buffer is modified, -1 if other buffer is modified, + // otherwise return 0. + + if (curbuf && bufIsChanged(curbuf)) + return 1; + buf_T *buf; for (buf = firstbuf; buf != NULL; buf = buf->b_next) { if (bufIsChanged(buf)) { - return YES; + return -1; } } - return NO; + return 0; } - (void)addInput:(NSString *)input diff --git a/src/MacVim/MMVimController.h b/src/MacVim/MMVimController.h index b9fbaac0c5..7246e68460 100644 --- a/src/MacVim/MMVimController.h +++ b/src/MacVim/MMVimController.h @@ -34,6 +34,7 @@ NSDictionary *vimState; BOOL isPreloading; NSDate *creationDate; + BOOL hasModifiedBuffer; } - (id)initWithBackend:(id)backend pid:(int)processIdentifier; @@ -48,6 +49,7 @@ - (NSMenu *)mainMenu; - (BOOL)isPreloading; - (void)setIsPreloading:(BOOL)yn; +- (BOOL)hasModifiedBuffer; - (NSDate *)creationDate; - (void)cleanup; - (void)dropFiles:(NSArray *)filenames forceOpen:(BOOL)force; diff --git a/src/MacVim/MMVimController.m b/src/MacVim/MMVimController.m index d56745df6d..897843848a 100644 --- a/src/MacVim/MMVimController.m +++ b/src/MacVim/MMVimController.m @@ -220,6 +220,11 @@ static BOOL isUnsafeMessage(int msgid); isPreloading = yn; } +- (BOOL)hasModifiedBuffer +{ + return hasModifiedBuffer; +} + - (NSDate *)creationDate { return creationDate; @@ -765,10 +770,21 @@ static BOOL isUnsafeMessage(int msgid); [windowController enterFullscreen:fuoptions backgroundColor:back]; } else if (LeaveFullscreenMsgID == msgid) { [windowController leaveFullscreen]; - } else if (BuffersNotModifiedMsgID == msgid) { - [windowController setBuffersModified:NO]; - } else if (BuffersModifiedMsgID == msgid) { - [windowController setBuffersModified:YES]; + } else if (SetBuffersModifiedMsgID == msgid) { + const void *bytes = [data bytes]; + // state < 0 <-> some buffer modified + // state > 0 <-> current buffer modified + int state = *((int*)bytes); bytes += sizeof(int); + + // NOTE: The window controller tracks whether current buffer is + // modified or not (and greys out the proxy icon as well as putting a + // dot in the red "close button" if necessary). The Vim controller + // tracks whether any buffer has been modified (used to decide whether + // to show a warning or not when quitting). + // + // TODO: Make 'hasModifiedBuffer' part of the Vim state? + [windowController setBufferModified:(state > 0)]; + hasModifiedBuffer = (state != 0); } else if (SetPreEditPositionMsgID == msgid) { const int *dim = (const int*)[data bytes]; [[[windowController vimView] textView] setPreEditRow:dim[0] diff --git a/src/MacVim/MMWindowController.h b/src/MacVim/MMWindowController.h index 12084520c0..99884c4e40 100644 --- a/src/MacVim/MMWindowController.h +++ b/src/MacVim/MMWindowController.h @@ -79,7 +79,7 @@ - (void)leaveFullscreen; - (void)setFullscreenBackgroundColor:(NSColor *)back; -- (void)setBuffersModified:(BOOL)mod; +- (void)setBufferModified:(BOOL)mod; - (void)setTopLeft:(NSPoint)pt; - (BOOL)getDefaultTopLeft:(NSPoint*)pt; diff --git a/src/MacVim/MMWindowController.m b/src/MacVim/MMWindowController.m index a6e2ffea9a..f367145551 100644 --- a/src/MacVim/MMWindowController.m +++ b/src/MacVim/MMWindowController.m @@ -670,7 +670,7 @@ [fullscreenWindow setBackgroundColor:back]; } -- (void)setBuffersModified:(BOOL)mod +- (void)setBufferModified:(BOOL)mod { // NOTE: We only set the document edited flag on the decorated window since // the full-screen window has no close button anyway. (It also saves us diff --git a/src/MacVim/MacVim.h b/src/MacVim/MacVim.h index 26b5af775e..20ff1a6a9d 100644 --- a/src/MacVim/MacVim.h +++ b/src/MacVim/MacVim.h @@ -158,8 +158,7 @@ enum { SetServerNameMsgID, EnterFullscreenMsgID, LeaveFullscreenMsgID, - BuffersNotModifiedMsgID, - BuffersModifiedMsgID, + SetBuffersModifiedMsgID, AddInputMsgID, SetPreEditPositionMsgID, TerminateNowMsgID, diff --git a/src/MacVim/MacVim.m b/src/MacVim/MacVim.m index 2b10c8bfed..25f5776c6c 100644 --- a/src/MacVim/MacVim.m +++ b/src/MacVim/MacVim.m @@ -68,8 +68,7 @@ char *MessageStrings[] = "SetServerNameMsgID", "EnterFullscreenMsgID", "LeaveFullscreenMsgID", - "BuffersNotModifiedMsgID", - "BuffersModifiedMsgID", + "SetBuffersModifiedMsgID", "AddInputMsgID", "SetPreEditPositionMsgID", "TerminateNowMsgID",