mirror of
https://github.com/macvim-dev/macvim.git
synced 2026-06-11 15:37:29 +02:00
- Request/reply timeout set on root connection object - Check for unresponsive Vim processes in applicationShouldTerminate: and present alert if any are detectd - Send SIGINT to all Vim processes in applicationWillTerminate: - Started adding support for 'enc' (set MM_ENABLE_CONV in MacVim.h) - Cmd-. sends SIGINT to Vim - Use @try/@catch for starRegisterToPasteboard: calls - Removed starRegisterFromPasteboard: message
git-svn-id: http://macvim.googlecode.com/svn/trunk@163 96c4425d-ca35-0410-94e5-3396d5c13a8f
This commit is contained in:
+65
-7
@@ -14,6 +14,14 @@
|
||||
|
||||
|
||||
|
||||
// Default timeout intervals on all connections.
|
||||
static NSTimeInterval MMRequestTimeout = 5;
|
||||
static NSTimeInterval MMReplyTimeout = 5;
|
||||
|
||||
// Timeout used when the app should terminate.
|
||||
static NSTimeInterval MMTerminateTimeout = 3;
|
||||
|
||||
|
||||
|
||||
@interface MMAppController (MMServices)
|
||||
- (void)openSelection:(NSPasteboard *)pboard userData:(NSString *)userData
|
||||
@@ -73,6 +81,8 @@
|
||||
[[NSBundle mainBundle] bundleIdentifier]];
|
||||
//NSLog(@"Registering connection with name '%@'", name);
|
||||
if ([connection registerName:name]) {
|
||||
[connection setRequestTimeout:MMRequestTimeout];
|
||||
[connection setReplyTimeout:MMReplyTimeout];
|
||||
[connection setRootObject:self];
|
||||
|
||||
// NOTE: When the user is resizing the window the AppKit puts the
|
||||
@@ -188,24 +198,53 @@
|
||||
{
|
||||
int reply = NSTerminateNow;
|
||||
BOOL modifiedBuffers = NO;
|
||||
BOOL notResponding = NO;
|
||||
|
||||
// Go through vim controllers, checking for modified buffers. If a process
|
||||
// is not responding then note this as well.
|
||||
unsigned i, count = [vimControllers count];
|
||||
for (i = 0; i < count; ++i) {
|
||||
MMVimController *controller = [vimControllers objectAtIndex:i];
|
||||
id proxy = [controller backendProxy];
|
||||
if (proxy && [proxy checkForModifiedBuffers]) {
|
||||
modifiedBuffers = YES;
|
||||
break;
|
||||
NSConnection *connection = [proxy connectionForProxy];
|
||||
if (connection) {
|
||||
NSTimeInterval req = [connection requestTimeout];
|
||||
NSTimeInterval rep = [connection replyTimeout];
|
||||
[connection setRequestTimeout:MMTerminateTimeout];
|
||||
[connection setReplyTimeout:MMTerminateTimeout];
|
||||
|
||||
@try {
|
||||
if ([proxy checkForModifiedBuffers])
|
||||
modifiedBuffers = YES;
|
||||
}
|
||||
@catch (NSException *e) {
|
||||
NSLog(@"WARNING: Got exception while waiting for "
|
||||
"checkForModifiedBuffers: \"%@\"", e);
|
||||
notResponding = YES;
|
||||
}
|
||||
@finally {
|
||||
[connection setRequestTimeout:req];
|
||||
[connection setReplyTimeout:rep];
|
||||
if (modifiedBuffers || notResponding)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (modifiedBuffers) {
|
||||
if (modifiedBuffers || notResponding) {
|
||||
NSAlert *alert = [[NSAlert alloc] init];
|
||||
[alert addButtonWithTitle:@"Quit"];
|
||||
[alert addButtonWithTitle:@"Cancel"];
|
||||
[alert setMessageText:@"Quit without saving?"];
|
||||
[alert setInformativeText:@"There are modified buffers, "
|
||||
" if you quit now all changes will be lost. Quit anyway?"];
|
||||
if (modifiedBuffers) {
|
||||
[alert setMessageText:@"Quit without saving?"];
|
||||
[alert setInformativeText:@"There are modified buffers, "
|
||||
"if you quit now all changes will be lost. Quit anyway?"];
|
||||
} else {
|
||||
[alert setMessageText:@"Force Quit?"];
|
||||
[alert setInformativeText:@"At least one Vim process is not "
|
||||
"responding, if you quit now any changes you have made "
|
||||
"will be lost. Quit anyway?"];
|
||||
}
|
||||
[alert setAlertStyle:NSWarningAlertStyle];
|
||||
|
||||
if ([alert runModal] != NSAlertFirstButtonReturn) {
|
||||
@@ -220,6 +259,23 @@
|
||||
|
||||
- (void)applicationWillTerminate:(NSNotification *)aNotification
|
||||
{
|
||||
// Send a SIGINT to all running Vim processes, so that they are sure to
|
||||
// receive the connectionDidDie: notification (a process has to checking
|
||||
// the run-loop for this to happen).
|
||||
unsigned i, count = [vimControllers count];
|
||||
for (i = 0; i < count; ++i) {
|
||||
MMVimController *controller = [vimControllers objectAtIndex:i];
|
||||
int pid = [controller pid];
|
||||
if (pid > 0)
|
||||
kill(pid, SIGINT);
|
||||
|
||||
id proxy = [controller backendProxy];
|
||||
NSConnection *connection = [proxy connectionForProxy];
|
||||
if (connection) {
|
||||
[connection invalidate];
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE! Is this a correct way of releasing the MMAppController?
|
||||
[NSApp setDelegate:nil];
|
||||
[self autorelease];
|
||||
@@ -227,6 +283,8 @@
|
||||
|
||||
- (void)removeVimController:(id)controller
|
||||
{
|
||||
//NSLog(@"%s%@", _cmd, controller);
|
||||
|
||||
[[controller windowController] close];
|
||||
|
||||
[vimControllers removeObject:controller];
|
||||
|
||||
+16
-12
@@ -810,15 +810,6 @@ static int specialKeyToNSKey(int key);
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)starRegisterFromPasteboard:(byref NSPasteboard *)pboard
|
||||
{
|
||||
if (curbuf && !curbuf->b_p_ro) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end // MMBackend
|
||||
|
||||
|
||||
@@ -837,12 +828,21 @@ static int specialKeyToNSKey(int key);
|
||||
if (!data) return;
|
||||
NSString *key = [[NSString alloc] initWithData:data
|
||||
encoding:NSUTF8StringEncoding];
|
||||
char_u *chars = (char_u*)[key UTF8String];
|
||||
char_u *str = (char_u*)[key UTF8String];
|
||||
int i, len = [key lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
#if MM_ENABLE_CONV
|
||||
char_u *conv_str = NULL;
|
||||
if (input_conv.vc_type != CONV_NONE) {
|
||||
conv_str = string_convert(&input_conv, str, &len);
|
||||
if (conv_str)
|
||||
str = conv_str;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < len; ++i) {
|
||||
add_to_input_buf(chars+i, 1);
|
||||
if (CSI == chars[i]) {
|
||||
add_to_input_buf(str+i, 1);
|
||||
if (CSI == str[i]) {
|
||||
// NOTE: If the converted string contains the byte CSI, then it
|
||||
// must be followed by the bytes KS_EXTRA, KE_CSI or things
|
||||
// won't work.
|
||||
@@ -851,6 +851,10 @@ static int specialKeyToNSKey(int key);
|
||||
}
|
||||
}
|
||||
|
||||
#if MM_ENABLE_CONV
|
||||
if (conv_str)
|
||||
vim_free(conv_str);
|
||||
#endif
|
||||
[key release];
|
||||
} else if (KeyDownMsgID == msgid || CmdKeyMsgID == msgid) {
|
||||
if (!data) return;
|
||||
|
||||
+13
-5
@@ -118,16 +118,24 @@
|
||||
|
||||
//NSLog(@"%s%@", _cmd, event);
|
||||
|
||||
NSMutableData *data = [NSMutableData data];
|
||||
NSString *string = [event charactersIgnoringModifiers];
|
||||
int flags = [event modifierFlags];
|
||||
int len = [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
[data appendBytes:&flags length:sizeof(int)];
|
||||
[data appendBytes:&len length:sizeof(int)];
|
||||
[data appendBytes:[string UTF8String] length:len];
|
||||
if (len > 0 && [string characterAtIndex:0] == '.') {
|
||||
// HACK! Intercept Cmd-. and send SIGINT to Vim.
|
||||
int pid = [[self vimController] pid];
|
||||
if (pid > 0)
|
||||
kill(pid, SIGINT);
|
||||
} else {
|
||||
NSMutableData *data = [NSMutableData data];
|
||||
|
||||
[[self vimController] sendMessage:CmdKeyMsgID data:data wait:NO];
|
||||
[data appendBytes:&flags length:sizeof(int)];
|
||||
[data appendBytes:&len length:sizeof(int)];
|
||||
[data appendBytes:[string UTF8String] length:len];
|
||||
|
||||
[[self vimController] sendMessage:CmdKeyMsgID data:data wait:NO];
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
+17
-8
@@ -662,13 +662,13 @@ NSMutableArray *buildMenuAddress(NSMenu *menu)
|
||||
{
|
||||
id backendProxy = [vimController backendProxy];
|
||||
|
||||
if ((!sendType || [sendType isEqual:NSStringPboardType])
|
||||
&& (!returnType || [returnType isEqual:NSStringPboardType]))
|
||||
{
|
||||
if ((!sendType || [backendProxy starRegisterToPasteboard:nil]) &&
|
||||
(!returnType || [backendProxy starRegisterFromPasteboard:nil]))
|
||||
{
|
||||
return self;
|
||||
if (backendProxy && [sendType isEqual:NSStringPboardType]) {
|
||||
@try {
|
||||
if ([backendProxy starRegisterToPasteboard:nil])
|
||||
return self;
|
||||
}
|
||||
@catch (NSException *e) {
|
||||
NSLog(@"WARNING: Caught exception in %s: \"%@\"", _cmd, e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -682,7 +682,16 @@ NSMutableArray *buildMenuAddress(NSMenu *menu)
|
||||
return NO;
|
||||
|
||||
id backendProxy = [vimController backendProxy];
|
||||
return [backendProxy starRegisterToPasteboard:pboard];
|
||||
if (backendProxy) {
|
||||
@try {
|
||||
return [backendProxy starRegisterToPasteboard:pboard];
|
||||
}
|
||||
@catch (NSException *e) {
|
||||
NSLog(@"WARNING: Caught exception in %s: \"%@\"", _cmd, e);
|
||||
}
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end // MMWindowController
|
||||
|
||||
@@ -11,20 +11,29 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
|
||||
// Enable to use experimental 'enc' support.
|
||||
#define MM_ENABLE_CONV 0
|
||||
|
||||
|
||||
|
||||
//
|
||||
// This is the protocol MMBackend implements.
|
||||
//
|
||||
// Only processInput:data: is allowed to cause state changes in Vim; all other
|
||||
// messages should only read the Vim state.
|
||||
// messages should only read the Vim state. (Note that setDialogReturn: is an
|
||||
// exception to this rule; there really is no other way to deal with dialogs
|
||||
// since they work with callbacks, so we cannot wait for them to return.)
|
||||
//
|
||||
// Be careful with messages with return type other than 'oneway void' -- there
|
||||
// is a reply timeout set in MMAppController, if a message fails to get a
|
||||
// response within the given timeout an exception will be thrown. Use
|
||||
// @try/@catch/@finally to deal with timeouts.
|
||||
//
|
||||
@protocol MMBackendProtocol
|
||||
- (oneway void)processInput:(int)msgid data:(in NSData *)data;
|
||||
- (BOOL)checkForModifiedBuffers;
|
||||
- (oneway void)setDialogReturn:(in bycopy id)obj;
|
||||
- (BOOL)starRegisterToPasteboard:(byref NSPasteboard *)pboard;
|
||||
- (BOOL)starRegisterFromPasteboard:(byref NSPasteboard *)pboard;
|
||||
@end
|
||||
|
||||
|
||||
|
||||
+61
-16
@@ -305,6 +305,15 @@ gui_macvim_draw_string(int row, int col, char_u *s, int len, int flags)
|
||||
BOOL outPad = NO;
|
||||
MMBackend *backend = [MMBackend sharedInstance];
|
||||
static char ZeroWidthSpace[] = { 0xe2, 0x80, 0x8b };
|
||||
#if MM_ENABLE_CONV
|
||||
char_u *conv_str = NULL;
|
||||
|
||||
if (output_conv.vc_type != CONV_NONE) {
|
||||
char_u *conv_str = string_convert(&output_conv, s, &len);
|
||||
if (conv_str)
|
||||
s = conv_str;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < len; i += cl) {
|
||||
c = utf_ptr2char(s + i);
|
||||
@@ -375,6 +384,11 @@ gui_macvim_draw_string(int row, int col, char_u *s, int len, int flags)
|
||||
row:row column:endcol-1 flags:flags];
|
||||
}
|
||||
|
||||
#if MM_ENABLE_CONV
|
||||
if (conv_str)
|
||||
vim_free(conv_str);
|
||||
#endif
|
||||
|
||||
return endcol - col;
|
||||
#else
|
||||
// This will fail abysmally when wide or composing characters are used.
|
||||
@@ -475,9 +489,9 @@ clip_mch_own_selection(VimClipboard *cbd)
|
||||
clip_mch_request_selection(VimClipboard *cbd)
|
||||
{
|
||||
NSPasteboard *pb = [NSPasteboard generalPasteboard];
|
||||
NSString *type = [pb availableTypeFromArray:
|
||||
NSString *pbType = [pb availableTypeFromArray:
|
||||
[NSArray arrayWithObject:NSStringPboardType]];
|
||||
if (type) {
|
||||
if (pbType) {
|
||||
NSMutableString *string =
|
||||
[[pb stringForType:NSStringPboardType] mutableCopy];
|
||||
|
||||
@@ -496,9 +510,24 @@ clip_mch_request_selection(VimClipboard *cbd)
|
||||
int type = MCHAR;
|
||||
if (0 < n || NSNotFound != [string rangeOfString:@"\n"].location)
|
||||
type = MLINE;
|
||||
|
||||
const char *utf8chars = [string UTF8String];
|
||||
clip_yank_selection(type, (char_u*)utf8chars, strlen(utf8chars), cbd);
|
||||
|
||||
char_u *str = (char_u*)[string UTF8String];
|
||||
int len = [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
#if MM_ENABLE_CONV
|
||||
if (input_conv.vc_type != CONV_NONE) {
|
||||
NSLog(@"Converting from: '%@'", string);
|
||||
char_u *conv_str = string_convert(&input_conv, str, &len);
|
||||
if (conv_str) {
|
||||
NSLog(@" to: '%s'", conv_str);
|
||||
clip_yank_selection(type, conv_str, len, cbd);
|
||||
vim_free(conv_str);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
clip_yank_selection(type, str, len, cbd);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -515,19 +544,35 @@ clip_mch_set_selection(VimClipboard *cbd)
|
||||
cbd->owned = FALSE;
|
||||
|
||||
// Get the text to put on the pasteboard.
|
||||
long_u len = 0; char_u *str = 0;
|
||||
int type = clip_convert_selection(&str, &len, cbd);
|
||||
long_u llen = 0; char_u *str = 0;
|
||||
int type = clip_convert_selection(&str, &llen, cbd);
|
||||
if (type < 0)
|
||||
return;
|
||||
|
||||
NSString *string = [[NSString alloc] initWithBytes:str length:len
|
||||
encoding:NSUTF8StringEncoding];
|
||||
|
||||
NSPasteboard *pb = [NSPasteboard generalPasteboard];
|
||||
[pb declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
|
||||
[pb setString:string forType:NSStringPboardType];
|
||||
|
||||
[string release];
|
||||
|
||||
// TODO: Avoid overflow.
|
||||
int len = (int)llen;
|
||||
#if MM_ENABLE_CONV
|
||||
if (output_conv.vc_type != CONV_NONE) {
|
||||
char_u *conv_str = string_convert(&output_conv, str, &len);
|
||||
if (conv_str) {
|
||||
vim_free(str);
|
||||
str = conv_str;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (len > 0) {
|
||||
NSString *string = [[NSString alloc]
|
||||
initWithBytes:str length:len encoding:NSUTF8StringEncoding];
|
||||
|
||||
NSPasteboard *pb = [NSPasteboard generalPasteboard];
|
||||
[pb declareTypes:[NSArray arrayWithObject:NSStringPboardType]
|
||||
owner:nil];
|
||||
[pb setString:string forType:NSStringPboardType];
|
||||
|
||||
[string release];
|
||||
}
|
||||
|
||||
vim_free(str);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user