- Escape '%' with backslash in drop files - Code cleanup

git-svn-id: http://macvim.googlecode.com/svn/trunk@309 96c4425d-ca35-0410-94e5-3396d5c13a8f
This commit is contained in:
Bjorn Winckler
2007-10-12 17:42:42 +00:00
parent 390e648dd4
commit 2df36264dc
4 changed files with 364 additions and 254 deletions
+306 -253
View File
@@ -57,6 +57,7 @@ enum {
@interface MMBackend (Private)
- (void)handleMessage:(int)msgid data:(NSData *)data;
+ (NSDictionary *)specialKeys;
- (void)handleInsertText:(NSData *)data;
- (void)handleKeyDown:(NSString *)key modifiers:(int)mods;
- (void)queueMessage:(int)msgid data:(NSData *)data;
- (void)connectionDidDie:(NSNotification *)notification;
@@ -64,6 +65,16 @@ enum {
- (void)focusChange:(BOOL)on;
- (void)processInputBegin;
- (void)processInputEnd;
- (void)handleToggleToolbar;
- (void)handleScrollbarEvent:(NSData *)data;
- (void)handleSetFont:(NSData *)data;
- (void)handleDropFiles:(NSData *)data;
- (void)handleDropString:(NSData *)data;
@end
@interface MMBackend (ClientServer)
- (NSString *)connectionNameFromServerName:(NSString *)name;
- (NSConnection *)connectionForServerName:(NSString *)name;
- (NSConnection *)connectionForServerPort:(int)port;
@@ -1403,37 +1414,7 @@ enum {
- (void)handleMessage:(int)msgid data:(NSData *)data
{
if (InsertTextMsgID == msgid) {
if (!data) return;
NSString *key = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
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(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.
static char_u extra[2] = { KS_EXTRA, KE_CSI };
add_to_input_buf(extra, 2);
}
}
#if MM_ENABLE_CONV
if (conv_str)
vim_free(conv_str);
#endif
[key release];
[self handleInsertText:data];
} else if (KeyDownMsgID == msgid || CmdKeyMsgID == msgid) {
if (!data) return;
const void *bytes = [data bytes];
@@ -1545,233 +1526,17 @@ enum {
gui_menu_cb(menu);
}
} else if (ToggleToolbarMsgID == msgid) {
char_u go[sizeof(GO_ALL)+2];
char_u *p;
int len;
STRCPY(go, p_go);
p = vim_strchr(go, GO_TOOLBAR);
len = STRLEN(go);
if (p != NULL) {
char_u *end = go + len;
while (p < end) {
p[0] = p[1];
++p;
}
} else {
go[len] = GO_TOOLBAR;
go[len+1] = NUL;
}
set_option_value((char_u*)"guioptions", 0, go, 0);
// Force screen redraw (does it have to be this complicated?).
redraw_all_later(CLEAR);
update_screen(NOT_VALID);
setcursor();
out_flush();
gui_update_cursor(FALSE, FALSE);
gui_mch_flush();
[self handleToggleToolbar];
} else if (ScrollbarEventMsgID == msgid) {
if (!data) return;
const void *bytes = [data bytes];
long ident = *((long*)bytes); bytes += sizeof(long);
int hitPart = *((int*)bytes); bytes += sizeof(int);
float fval = *((float*)bytes); bytes += sizeof(float);
scrollbar_T *sb = gui_find_scrollbar(ident);
if (sb) {
scrollbar_T *sb_info = sb->wp ? &sb->wp->w_scrollbars[0] : sb;
long value = sb_info->value;
long size = sb_info->size;
long max = sb_info->max;
BOOL isStillDragging = NO;
BOOL updateKnob = YES;
switch (hitPart) {
case NSScrollerDecrementPage:
value -= (size > 2 ? size - 2 : 1);
break;
case NSScrollerIncrementPage:
value += (size > 2 ? size - 2 : 1);
break;
case NSScrollerDecrementLine:
--value;
break;
case NSScrollerIncrementLine:
++value;
break;
case NSScrollerKnob:
isStillDragging = YES;
// fall through ...
case NSScrollerKnobSlot:
value = (long)(fval * (max - size + 1));
// fall through ...
default:
updateKnob = NO;
break;
}
//NSLog(@"value %d -> %d", sb_info->value, value);
gui_drag_scrollbar(sb, value, isStillDragging);
if (updateKnob) {
// Dragging the knob or option+clicking automatically updates
// the knob position (on the actual NSScroller), so we only
// need to set the knob position in the other cases.
if (sb->wp) {
// Update both the left&right vertical scrollbars.
long identLeft = sb->wp->w_scrollbars[SBAR_LEFT].ident;
long identRight = sb->wp->w_scrollbars[SBAR_RIGHT].ident;
[self setScrollbarThumbValue:value size:size max:max
identifier:identLeft];
[self setScrollbarThumbValue:value size:size max:max
identifier:identRight];
} else {
// Update the horizontal scrollbar.
[self setScrollbarThumbValue:value size:size max:max
identifier:ident];
}
}
}
[self handleScrollbarEvent:data];
} else if (SetFontMsgID == msgid) {
if (!data) return;
const void *bytes = [data bytes];
float pointSize = *((float*)bytes); bytes += sizeof(float);
//unsigned len = *((unsigned*)bytes); bytes += sizeof(unsigned);
bytes += sizeof(unsigned); // len not used
NSMutableString *name = [NSMutableString stringWithUTF8String:bytes];
[name appendString:[NSString stringWithFormat:@":h%.2f", pointSize]];
char_u *s = (char_u*)[name UTF8String];
#if MM_ENABLE_CONV
s = CONVERT_FROM_UTF8(s);
#endif
set_option_value((char_u*)"guifont", 0, s, 0);
#if MM_ENABLE_CONV
CONVERT_FROM_UTF8_FREE(s);
#endif
// Force screen redraw (does it have to be this complicated?).
redraw_all_later(CLEAR);
update_screen(NOT_VALID);
setcursor();
out_flush();
gui_update_cursor(FALSE, FALSE);
gui_mch_flush();
[self handleSetFont:data];
} else if (VimShouldCloseMsgID == msgid) {
gui_shell_closed();
} else if (DropFilesMsgID == msgid) {
#ifdef FEAT_DND
const void *bytes = [data bytes];
const void *end = [data bytes] + [data length];
int n = *((int*)bytes); bytes += sizeof(int);
if (State & CMDLINE) {
// HACK! If Vim is in command line mode then the files names
// should be added to the command line, instead of opening the
// files in tabs. This is taken care of by gui_handle_drop().
char_u **fnames = (char_u **)alloc(n * sizeof(char_u *));
if (fnames) {
int i = 0;
while (bytes < end && i < n) {
int len = *((int*)bytes); bytes += sizeof(int);
char_u *s = (char_u*)bytes;
#if MM_ENABLE_CONV
s = CONVERT_FROM_UTF8(s);
#endif
fnames[i++] = vim_strsave(s);
#if MM_ENABLE_CONV
CONVERT_FROM_UTF8_FREE(s);
#endif
bytes += len;
}
// NOTE! This function will free 'fnames'.
// HACK! It is assumed that the 'x' and 'y' arguments are
// unused when in command line mode.
gui_handle_drop(0, 0, 0, fnames, i < n ? i : n);
}
} else {
// HACK! I'm not sure how to get Vim to open a list of files in
// tabs, so instead I create a ':tab drop' command with all the
// files to open and execute it.
NSMutableString *cmd = (n > 1)
? [NSMutableString stringWithString:@":tab drop"]
: [NSMutableString stringWithString:@":drop"];
int i;
for (i = 0; i < n && bytes < end; ++i) {
int len = *((int*)bytes); bytes += sizeof(int);
NSMutableString *file =
[NSMutableString stringWithUTF8String:bytes];
[file replaceOccurrencesOfString:@" "
withString:@"\\ "
options:0
range:NSMakeRange(0,[file length])];
bytes += len;
[cmd appendString:@" "];
[cmd appendString:file];
}
// By going to the last tabpage we ensure that the new tabs will
// appear last (if this call is left out, the taborder becomes
// messy).
goto_tabpage(9999);
char_u *s = (char_u*)[cmd UTF8String];
#if MM_ENABLE_CONV
s = CONVERT_FROM_UTF8(s);
#endif
do_cmdline_cmd(s);
#if MM_ENABLE_CONV
CONVERT_FROM_UTF8_FREE(s);
#endif
// Force screen redraw (does it have to be this complicated?).
// (This code was taken from the end of gui_handle_drop().)
update_screen(NOT_VALID);
setcursor();
out_flush();
gui_update_cursor(FALSE, FALSE);
gui_mch_flush();
}
#endif // FEAT_DND
[self handleDropFiles:data];
} else if (DropStringMsgID == msgid) {
#ifdef FEAT_DND
char_u dropkey[3] = { CSI, KS_EXTRA, (char_u)KE_DROP };
const void *bytes = [data bytes];
int len = *((int*)bytes); bytes += sizeof(int);
NSMutableString *string = [NSMutableString stringWithUTF8String:bytes];
// Replace unrecognized end-of-line sequences with \x0a (line feed).
NSRange range = { 0, [string length] };
unsigned n = [string replaceOccurrencesOfString:@"\x0d\x0a"
withString:@"\x0a" options:0
range:range];
if (0 == n) {
n = [string replaceOccurrencesOfString:@"\x0d" withString:@"\x0a"
options:0 range:range];
}
len = [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
char_u *s = (char_u*)[string UTF8String];
#if MM_ENABLE_CONV
if (input_conv.vc_type != CONV_NONE)
s = string_convert(&input_conv, s, &len);
#endif
dnd_yank_drag_data(s, len);
#if MM_ENABLE_CONV
if (input_conv.vc_type != CONV_NONE)
vim_free(s);
#endif
add_to_input_buf(dropkey, sizeof(dropkey));
#endif // FEAT_DND
[self handleDropString:data];
} else if (GotFocusMsgID == msgid) {
if (!gui.in_focus)
[self focusChange:YES];
@@ -1807,6 +1572,42 @@ enum {
return specialKeys;
}
- (void)handleInsertText:(NSData *)data
{
if (!data) return;
NSString *key = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
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(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.
static char_u extra[2] = { KS_EXTRA, KE_CSI };
add_to_input_buf(extra, 2);
}
}
#if MM_ENABLE_CONV
if (conv_str)
vim_free(conv_str);
#endif
[key release];
}
- (void)handleKeyDown:(NSString *)key modifiers:(int)mods
{
char_u special[3];
@@ -2017,6 +1818,258 @@ enum {
inProcessInput = NO;
}
- (void)handleToggleToolbar
{
// If 'go' contains 'T', then remove it, else add it.
char_u go[sizeof(GO_ALL)+2];
char_u *p;
int len;
STRCPY(go, p_go);
p = vim_strchr(go, GO_TOOLBAR);
len = STRLEN(go);
if (p != NULL) {
char_u *end = go + len;
while (p < end) {
p[0] = p[1];
++p;
}
} else {
go[len] = GO_TOOLBAR;
go[len+1] = NUL;
}
set_option_value((char_u*)"guioptions", 0, go, 0);
// Force screen redraw (does it have to be this complicated?).
redraw_all_later(CLEAR);
update_screen(NOT_VALID);
setcursor();
out_flush();
gui_update_cursor(FALSE, FALSE);
gui_mch_flush();
}
- (void)handleScrollbarEvent:(NSData *)data
{
if (!data) return;
const void *bytes = [data bytes];
long ident = *((long*)bytes); bytes += sizeof(long);
int hitPart = *((int*)bytes); bytes += sizeof(int);
float fval = *((float*)bytes); bytes += sizeof(float);
scrollbar_T *sb = gui_find_scrollbar(ident);
if (sb) {
scrollbar_T *sb_info = sb->wp ? &sb->wp->w_scrollbars[0] : sb;
long value = sb_info->value;
long size = sb_info->size;
long max = sb_info->max;
BOOL isStillDragging = NO;
BOOL updateKnob = YES;
switch (hitPart) {
case NSScrollerDecrementPage:
value -= (size > 2 ? size - 2 : 1);
break;
case NSScrollerIncrementPage:
value += (size > 2 ? size - 2 : 1);
break;
case NSScrollerDecrementLine:
--value;
break;
case NSScrollerIncrementLine:
++value;
break;
case NSScrollerKnob:
isStillDragging = YES;
// fall through ...
case NSScrollerKnobSlot:
value = (long)(fval * (max - size + 1));
// fall through ...
default:
updateKnob = NO;
break;
}
//NSLog(@"value %d -> %d", sb_info->value, value);
gui_drag_scrollbar(sb, value, isStillDragging);
if (updateKnob) {
// Dragging the knob or option+clicking automatically updates
// the knob position (on the actual NSScroller), so we only
// need to set the knob position in the other cases.
if (sb->wp) {
// Update both the left&right vertical scrollbars.
long identLeft = sb->wp->w_scrollbars[SBAR_LEFT].ident;
long identRight = sb->wp->w_scrollbars[SBAR_RIGHT].ident;
[self setScrollbarThumbValue:value size:size max:max
identifier:identLeft];
[self setScrollbarThumbValue:value size:size max:max
identifier:identRight];
} else {
// Update the horizontal scrollbar.
[self setScrollbarThumbValue:value size:size max:max
identifier:ident];
}
}
}
}
- (void)handleSetFont:(NSData *)data
{
if (!data) return;
const void *bytes = [data bytes];
float pointSize = *((float*)bytes); bytes += sizeof(float);
//unsigned len = *((unsigned*)bytes); bytes += sizeof(unsigned);
bytes += sizeof(unsigned); // len not used
NSMutableString *name = [NSMutableString stringWithUTF8String:bytes];
[name appendString:[NSString stringWithFormat:@":h%.2f", pointSize]];
char_u *s = (char_u*)[name UTF8String];
#if MM_ENABLE_CONV
s = CONVERT_FROM_UTF8(s);
#endif
set_option_value((char_u*)"guifont", 0, s, 0);
#if MM_ENABLE_CONV
CONVERT_FROM_UTF8_FREE(s);
#endif
// Force screen redraw (does it have to be this complicated?).
redraw_all_later(CLEAR);
update_screen(NOT_VALID);
setcursor();
out_flush();
gui_update_cursor(FALSE, FALSE);
gui_mch_flush();
}
- (void)handleDropFiles:(NSData *)data
{
if (!data) return;
#ifdef FEAT_DND
const void *bytes = [data bytes];
const void *end = [data bytes] + [data length];
int n = *((int*)bytes); bytes += sizeof(int);
if (State & CMDLINE) {
// HACK! If Vim is in command line mode then the files names
// should be added to the command line, instead of opening the
// files in tabs. This is taken care of by gui_handle_drop().
char_u **fnames = (char_u **)alloc(n * sizeof(char_u *));
if (fnames) {
int i = 0;
while (bytes < end && i < n) {
int len = *((int*)bytes); bytes += sizeof(int);
char_u *s = (char_u*)bytes;
#if MM_ENABLE_CONV
s = CONVERT_FROM_UTF8(s);
#endif
fnames[i++] = vim_strsave(s);
#if MM_ENABLE_CONV
CONVERT_FROM_UTF8_FREE(s);
#endif
bytes += len;
}
// NOTE! This function will free 'fnames'.
// HACK! It is assumed that the 'x' and 'y' arguments are
// unused when in command line mode.
gui_handle_drop(0, 0, 0, fnames, i < n ? i : n);
}
} else {
// HACK! I'm not sure how to get Vim to open a list of files in
// tabs, so instead I create a ':tab drop' command with all the
// files to open and execute it.
NSMutableString *cmd = (n > 1)
? [NSMutableString stringWithString:@":tab drop"]
: [NSMutableString stringWithString:@":drop"];
int i;
for (i = 0; i < n && bytes < end; ++i) {
int len = *((int*)bytes); bytes += sizeof(int);
NSString *file = [NSString stringWithUTF8String:bytes];
file = [file stringByEscapingInvalidFilenameCharacters];
bytes += len;
[cmd appendString:@" "];
[cmd appendString:file];
}
// By going to the last tabpage we ensure that the new tabs will
// appear last (if this call is left out, the taborder becomes
// messy).
goto_tabpage(9999);
char_u *s = (char_u*)[cmd UTF8String];
#if MM_ENABLE_CONV
s = CONVERT_FROM_UTF8(s);
#endif
do_cmdline_cmd(s);
#if MM_ENABLE_CONV
CONVERT_FROM_UTF8_FREE(s);
#endif
// Force screen redraw (does it have to be this complicated?).
// (This code was taken from the end of gui_handle_drop().)
update_screen(NOT_VALID);
setcursor();
out_flush();
gui_update_cursor(FALSE, FALSE);
gui_mch_flush();
}
#endif // FEAT_DND
}
- (void)handleDropString:(NSData *)data
{
if (!data) return;
#ifdef FEAT_DND
char_u dropkey[3] = { CSI, KS_EXTRA, (char_u)KE_DROP };
const void *bytes = [data bytes];
int len = *((int*)bytes); bytes += sizeof(int);
NSMutableString *string = [NSMutableString stringWithUTF8String:bytes];
// Replace unrecognized end-of-line sequences with \x0a (line feed).
NSRange range = { 0, [string length] };
unsigned n = [string replaceOccurrencesOfString:@"\x0d\x0a"
withString:@"\x0a" options:0
range:range];
if (0 == n) {
n = [string replaceOccurrencesOfString:@"\x0d" withString:@"\x0a"
options:0 range:range];
}
len = [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
char_u *s = (char_u*)[string UTF8String];
#if MM_ENABLE_CONV
if (input_conv.vc_type != CONV_NONE)
s = string_convert(&input_conv, s, &len);
#endif
dnd_yank_drag_data(s, len);
#if MM_ENABLE_CONV
if (input_conv.vc_type != CONV_NONE)
vim_free(s);
#endif
add_to_input_buf(dropkey, sizeof(dropkey));
#endif // FEAT_DND
}
@end // MMBackend (Private)
@implementation MMBackend (ClientServer)
- (NSString *)connectionNameFromServerName:(NSString *)name
{
NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
@@ -2158,7 +2211,7 @@ enum {
return nil;
}
@end // MMBackend (Private)
@end // MMBackend (ClientServer)
+1 -1
View File
@@ -199,7 +199,7 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag)
int len = [file lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
if (len > 0) {
++len; // append NUL as well
++len; // include NUL as well
[data appendBytes:&len length:sizeof(int)];
[data appendBytes:[file UTF8String] length:len];
}
+9
View File
@@ -215,4 +215,13 @@ extern NSString *MMOpenFilesInTabsKey;
ATSFontContainerRef loadFonts();
@interface NSString (MMExtras)
- (NSString *)stringByEscapingPercent;
- (NSString *)stringByEscapingSpace;
- (NSString *)stringByEscapingInvalidFilenameCharacters;
@end
// vim: set ft=objc:
+48
View File
@@ -117,3 +117,51 @@ loadFonts()
return fontContainerRef;
}
@implementation NSString (MMExtras)
- (NSString *)stringByEscapingPercent
{
NSMutableString *string = [self mutableCopy];
// Some '%' may already be escaped, so un-escape first...
[string replaceOccurrencesOfString:@"\\%"
withString:@"%"
options:NSLiteralSearch
range:NSMakeRange(0, [string length])];
// ...then escape all '%'
[string replaceOccurrencesOfString:@"%"
withString:@"\\%"
options:NSLiteralSearch
range:NSMakeRange(0, [string length])];
return [string autorelease];
}
- (NSString *)stringByEscapingSpace
{
NSMutableString *string = [self mutableCopy];
// Some space chars may already be escaped, so un-escape first...
[string replaceOccurrencesOfString:@"\\ "
withString:@" "
options:NSLiteralSearch
range:NSMakeRange(0, [string length])];
// ...then escape all space chars
[string replaceOccurrencesOfString:@" "
withString:@"\\ "
options:NSLiteralSearch
range:NSMakeRange(0, [string length])];
return [string autorelease];
}
- (NSString *)stringByEscapingInvalidFilenameCharacters
{
return [[self stringByEscapingSpace] stringByEscapingPercent];
}
@end // NSString (MMExtras)