From 210a71b4cb401b158584b71f89b847cae0eafda4 Mon Sep 17 00:00:00 2001 From: Bjorn Winckler Date: Mon, 17 Jan 2011 17:54:40 +0100 Subject: [PATCH] Fix open from Xcode with selection range This is an initial attempt to fix a problem where double clicking a search result in Xcode would select an incorrect range of characters when the file opened in MacVim. It only works the file uses an 8 bit encoding. --- src/MacVim/MMAppController.m | 90 +++++++++++++++++++----------------- src/MacVim/MMBackend.m | 11 +++-- 2 files changed, 54 insertions(+), 47 deletions(-) diff --git a/src/MacVim/MMAppController.m b/src/MacVim/MMAppController.m index 2009c49099..b58f5e4766 100644 --- a/src/MacVim/MMAppController.m +++ b/src/MacVim/MMAppController.m @@ -903,6 +903,43 @@ fsEventCallback(ConstFSEventStreamRef streamRef, NSDictionary *openFilesDict = nil; filenames = [self filterOpenFiles:filenames openFilesDict:&openFilesDict]; + // The meaning of "layout" is defined by the WIN_* defines in main.c. + NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; + int layout = [ud integerForKey:MMOpenLayoutKey]; + BOOL splitVert = [ud boolForKey:MMVerticalSplitKey]; + BOOL openInCurrentWindow = [ud boolForKey:MMOpenInCurrentWindowKey]; + + if (splitVert && MMLayoutHorizontalSplit == layout) + layout = MMLayoutVerticalSplit; + if (layout < 0 || (layout > MMLayoutTabs && openInCurrentWindow)) + layout = MMLayoutTabs; + + if ([filenames count] == 0) { + // Raise the window containing the first file that was already open, + // and make sure that the tab containing that file is selected. Only + // do this when there are no more files to open, otherwise sometimes + // the window with 'firstFile' will be raised, other times it might be + // the window that will open with the files in the 'filenames' array. + // + // NOTE: Raise window before passing arguments, otherwise the selection + // will be lost when selectionRange is set. + firstFile = [firstFile stringByEscapingSpecialFilenameCharacters]; + + NSString *bufCmd = @"tab sb"; + switch (layout) { + case MMLayoutHorizontalSplit: bufCmd = @"sb"; break; + case MMLayoutVerticalSplit: bufCmd = @"vert sb"; break; + case MMLayoutArglist: bufCmd = @"b"; break; + } + + NSString *input = [NSString stringWithFormat:@"" + ":let oldswb=&swb|let &swb=\"useopen,usetab\"|" + "%@ %@|let &swb=oldswb|unl oldswb|" + "cal foreground()", bufCmd, firstFile]; + + [firstController addVimInput:input]; + } + // Pass arguments to vim controllers that had files open. id key; NSEnumerator *e = [openFilesDict keyEnumerator]; @@ -922,42 +959,6 @@ fsEventCallback(ConstFSEventStreamRef streamRef, firstController = vc; } - // The meaning of "layout" is defined by the WIN_* defines in main.c. - NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; - int layout = [ud integerForKey:MMOpenLayoutKey]; - BOOL splitVert = [ud boolForKey:MMVerticalSplitKey]; - BOOL openInCurrentWindow = [ud boolForKey:MMOpenInCurrentWindowKey]; - - if (splitVert && MMLayoutHorizontalSplit == layout) - layout = MMLayoutVerticalSplit; - if (layout < 0 || (layout > MMLayoutTabs && openInCurrentWindow)) - layout = MMLayoutTabs; - - if ([filenames count] == 0) { - // Raise the window containing the first file that was already open, - // and make sure that the tab containing that file is selected. Only - // do this when there are no more files to open, otherwise sometimes - // the window with 'firstFile' will be raised, other times it might be - // the window that will open with the files in the 'filenames' array. - firstFile = [firstFile stringByEscapingSpecialFilenameCharacters]; - - NSString *bufCmd = @"tab sb"; - switch (layout) { - case MMLayoutHorizontalSplit: bufCmd = @"sb"; break; - case MMLayoutVerticalSplit: bufCmd = @"vert sb"; break; - case MMLayoutArglist: bufCmd = @"b"; break; - } - - NSString *input = [NSString stringWithFormat:@"" - ":let oldswb=&swb|let &swb=\"useopen,usetab\"|" - "%@ %@|let &swb=oldswb|unl oldswb|" - "cal foreground()", bufCmd, firstFile]; - - [firstController addVimInput:input]; - - return YES; - } - // Add filenames to "Recent Files" menu, unless they are being edited // remotely (using ODB). if ([arguments objectForKey:@"remoteID"] == nil) { @@ -965,6 +966,9 @@ fsEventCallback(ConstFSEventStreamRef streamRef, noteNewRecentFilePaths:filenames]; } + if ([filenames count] == 0) + return YES; // No files left to open (all were already open) + // // b) Open any remaining files // @@ -1757,9 +1761,10 @@ fsEventCallback(ConstFSEventStreamRef streamRef, sr->unused2, sr->theDate); if (sr->lineNum < 0) { - // Should select a range of lines. + // Should select a range of characters. range.location = sr->startRange + 1; - range.length = sr->endRange - sr->startRange + 1; + range.length = sr->endRange > sr->startRange + ? sr->endRange - sr->startRange : 1; } else { // Should only move cursor to a line. range.location = sr->lineNum + 1; @@ -2338,11 +2343,12 @@ fsEventCallback(ConstFSEventStreamRef streamRef, NSRange r = NSRangeFromString(rangeString); [a addObject:@"-c"]; if (r.length > 0) { - // Select given range. - [a addObject:[NSString stringWithFormat:@"norm %dGV%dGz.0", - NSMaxRange(r), r.location]]; + // Select given range of characters. + // TODO: This only works for encodings where 1 byte == 1 character + [a addObject:[NSString stringWithFormat:@"norm %dgov%dgo", + r.location, NSMaxRange(r)-1]]; } else { - // Position cursor on start of range. + // Position cursor on line at start of range. [a addObject:[NSString stringWithFormat:@"norm %dGz.0", r.location]]; } diff --git a/src/MacVim/MMBackend.m b/src/MacVim/MMBackend.m index 2d389c14e5..d547d14fdf 100644 --- a/src/MacVim/MMBackend.m +++ b/src/MacVim/MMBackend.m @@ -2626,7 +2626,7 @@ static void netbeansReadCallback(CFSocketRef s, // filenames list of filenames // dontOpen don't open files specified in above argument // layout which layout to use to open files - // selectionRange range of lines to select + // selectionRange range of characters to select // searchText string to search for // cursorLine line to position the cursor on // cursorColumn column to position the cursor on @@ -2811,13 +2811,14 @@ static void netbeansReadCallback(CFSocketRef s, NSString *rangeString = [args objectForKey:@"selectionRange"]; if (rangeString) { // Build a command line string that will select the given range of - // lines. If range.length == 0, then position the cursor on the given - // line but do not select. + // characters. If range.length == 0, then position the cursor on the + // line at start of range but do not select. NSRange range = NSRangeFromString(rangeString); NSString *cmd; if (range.length > 0) { - cmd = [NSString stringWithFormat:@"%dGV%dGz.0", - NSMaxRange(range), range.location]; + // TODO: This only works for encodings where 1 byte == 1 character + cmd = [NSString stringWithFormat:@"%dgov%dgo", + range.location, NSMaxRange(range)-1]; } else { cmd = [NSString stringWithFormat:@"%dGz.0", range.location];