mirror of
https://github.com/macvim-dev/macvim.git
synced 2026-06-02 11:19:22 +02:00
Compare commits
51 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bf70f82498 | |||
| 89d9e60b8a | |||
| 0ea7546c7c | |||
| 321fdf61aa | |||
| 2fa74c01aa | |||
| c4222c6ebb | |||
| 1f538dc364 | |||
| 9471224d0b | |||
| 1d83527039 | |||
| 7752431b82 | |||
| 2ac28f887e | |||
| 9c517cb4e9 | |||
| 3915c6afc6 | |||
| a4569d06ac | |||
| cb120a21cf | |||
| 7070fd3f76 | |||
| 9f1b770ee6 | |||
| ebf10927c7 | |||
| e18186c461 | |||
| af279d2477 | |||
| 8c442b7b28 | |||
| 4c6ed9759c | |||
| d98e291038 | |||
| 092e0cc894 | |||
| b904b019b8 | |||
| c0159b8fdf | |||
| 11ec93a03a | |||
| c2f8b396de | |||
| fa15736b2b | |||
| d1a9e08f94 | |||
| 9d2727c56f | |||
| ce9c112020 | |||
| 0e2ddfca38 | |||
| 1f7de911ba | |||
| f6ab5cbc03 | |||
| 44d7e60b06 | |||
| 0e37f590ab | |||
| a0f684e003 | |||
| f54c3100e9 | |||
| a588fc3e33 | |||
| 039f611554 | |||
| 3a4682c9dd | |||
| fdc64858c5 | |||
| 45a9151fc6 | |||
| b9241163d8 | |||
| defa7bd098 | |||
| 6bfab82aca | |||
| 64959e3177 | |||
| 2eee45eb39 | |||
| 8d051eef4e | |||
| 7f449520a5 |
+22
-10
@@ -1,6 +1,6 @@
|
||||
" Vim autoload file for editing compressed files.
|
||||
" Maintainer: Bram Moolenaar <Bram@vim.org>
|
||||
" Last Change: 2007 May 10
|
||||
" Last Change: 2008 May 29
|
||||
|
||||
" These functions are used by the gzip plugin.
|
||||
|
||||
@@ -73,8 +73,15 @@ fun gzip#read(cmd)
|
||||
let empty = line("'[") == 1 && line("']") == line("$")
|
||||
let tmp = tempname()
|
||||
let tmpe = tmp . "." . expand("<afile>:e")
|
||||
if exists('*fnameescape')
|
||||
let tmp_esc = fnameescape(tmp)
|
||||
let tmpe_esc = fnameescape(tmpe)
|
||||
else
|
||||
let tmp_esc = escape(tmp, ' ')
|
||||
let tmpe_esc = escape(tmpe, ' ')
|
||||
endif
|
||||
" write the just read lines to a temp file "'[,']w tmp.gz"
|
||||
execute "silent '[,']w " . escape(tmpe, ' ')
|
||||
execute "silent '[,']w " . tmpe_esc
|
||||
" uncompress the temp file: call system("gzip -dn tmp.gz")
|
||||
call system(a:cmd . " " . s:escape(tmpe))
|
||||
if !filereadable(tmp)
|
||||
@@ -95,12 +102,12 @@ fun gzip#read(cmd)
|
||||
setlocal nobin
|
||||
if exists(":lockmarks")
|
||||
if empty
|
||||
execute "silent lockmarks " . l . "r ++edit " . tmp
|
||||
execute "silent lockmarks " . l . "r ++edit " . tmp_esc
|
||||
else
|
||||
execute "silent lockmarks " . l . "r " . tmp
|
||||
execute "silent lockmarks " . l . "r " . tmp_esc
|
||||
endif
|
||||
else
|
||||
execute "silent " . l . "r " . tmp
|
||||
execute "silent " . l . "r " . tmp_esc
|
||||
endif
|
||||
|
||||
" if buffer became empty, delete trailing blank line
|
||||
@@ -110,8 +117,8 @@ fun gzip#read(cmd)
|
||||
endif
|
||||
" delete the temp file and the used buffers
|
||||
call delete(tmp)
|
||||
silent! exe "bwipe " . tmp
|
||||
silent! exe "bwipe " . tmpe
|
||||
silent! exe "bwipe " . tmp_esc
|
||||
silent! exe "bwipe " . tmpe_esc
|
||||
endif
|
||||
|
||||
" Restore saved option values.
|
||||
@@ -124,10 +131,15 @@ fun gzip#read(cmd)
|
||||
|
||||
" When uncompressed the whole buffer, do autocommands
|
||||
if ok && empty
|
||||
if &verbose >= 8
|
||||
execute "doau BufReadPost " . expand("%:r")
|
||||
if exists('*fnameescape')
|
||||
let fname = fnameescape(expand("%:r"))
|
||||
else
|
||||
execute "silent! doau BufReadPost " . expand("%:r")
|
||||
let fname = escape(expand("%:r"), " \t\n*?[{`$\\%#'\"|!<")
|
||||
endif
|
||||
if &verbose >= 8
|
||||
execute "doau BufReadPost " . fname
|
||||
else
|
||||
execute "silent! doau BufReadPost " . fname
|
||||
endif
|
||||
endif
|
||||
endfun
|
||||
|
||||
+15
-1
@@ -1,4 +1,4 @@
|
||||
*eval.txt* For Vim version 7.1. Last change: 2008 Feb 20
|
||||
*eval.txt* For Vim version 7.1. Last change: 2008 May 28
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -1609,6 +1609,7 @@ finddir( {name}[, {path}[, {count}]])
|
||||
String find directory {name} in {path}
|
||||
findfile( {name}[, {path}[, {count}]])
|
||||
String find file {name} in {path}
|
||||
fnameescape( {fname}) String escape special characters in {fname}
|
||||
fnamemodify( {fname}, {mods}) String modify file name
|
||||
foldclosed( {lnum}) Number first line of fold at {lnum} if closed
|
||||
foldclosedend( {lnum}) Number last line of fold at {lnum} if closed
|
||||
@@ -2620,6 +2621,19 @@ findfile({name}[, {path}[, {count}]]) *findfile()*
|
||||
< Searches from the directory of the current file upwards until
|
||||
it finds the file "tags.vim".
|
||||
|
||||
fnameescape({string}) *fnameescape()*
|
||||
Escape {string} for use as file name command argument. All
|
||||
characters that have a special meaning, such as '%' and '|'
|
||||
are escaped with a backslash.
|
||||
For most systems the characters escaped are "". For systems
|
||||
where a backslash appears in a filename, it depends on the
|
||||
value of 'isfname'.
|
||||
Example: >
|
||||
:let fname = 'some str%nge|name'
|
||||
:exe "edit " . fnameescape(fname)
|
||||
< results in executing: >
|
||||
edit some\ str\%nge\|name
|
||||
|
||||
fnamemodify({fname}, {mods}) *fnamemodify()*
|
||||
Modify file name {fname} according to {mods}. {mods} is a
|
||||
string of characters like it is used for file names on the
|
||||
|
||||
+14
-3
@@ -389,6 +389,12 @@ equivalent Cmd-n, which opens a new window when selected: >
|
||||
3. Create a mapping in normal mode which closes the current tab/window: >
|
||||
:map <C-w> :maca performClose:<CR>
|
||||
>
|
||||
|
||||
The standard Vim menus are modified in "$VIM/gvimrc". Take a look at that
|
||||
file for more examples on how to set up menus. Note: When no window is open a
|
||||
minimal default menu is used. The default menu is set up in MainMenu.nib
|
||||
which resides in "Resources/English.lproj/" folder inside the app bundle.
|
||||
|
||||
*Actions.plist*
|
||||
Some action messages would not be suitable to call from within Vim, so there
|
||||
is a dictionary called "Actions.plist" (in the Resources folder of the
|
||||
@@ -403,18 +409,23 @@ Here is a random assortment of actions from Actions.plist which might be
|
||||
useful.
|
||||
|
||||
Action Description ~
|
||||
fileOpen: Show "File Open" dialog
|
||||
findNext: Search forward using the "Find Pasteboard"
|
||||
findPrevious: Search backward using the "Find Pasteboard"
|
||||
fontSizeDown: Decrease font size
|
||||
fontSizeUp: Increase font size
|
||||
hide: Hide MacVim
|
||||
miniaturizeAll: Minimize all windows to the dock
|
||||
newWindow: Open a new (empty) window
|
||||
orderFrontCharacterPalette: Show the the "Special Characters" dialog
|
||||
orderFrontFontPanel: Show the Font panel
|
||||
orderFrontPreferencePanel: Show the Preferences panel
|
||||
performClose: Close tab/window
|
||||
performMiniaturize: Minimize window to the dock
|
||||
performZoom: Zoom window (same as clicking the green blob)
|
||||
selectNextWindow: Select next window (similar to <D-`>)
|
||||
selectPreviousWindow: Select previous window (similar to <S-D-`>)
|
||||
terminate: Quit MacVim
|
||||
zoomAll: Zoom all windows
|
||||
_cycleWindows: Select next window (similar to <D-`>)
|
||||
_cycleWindowsBackwards: Select previous window (similar to <D-S-`>)
|
||||
|
||||
==============================================================================
|
||||
6. Toolbar *macvim-toolbar*
|
||||
|
||||
@@ -16,20 +16,23 @@ set cpo&vim
|
||||
augroup filetypedetect
|
||||
|
||||
" Ignored extensions
|
||||
if exists("*fnameescape")
|
||||
au BufNewFile,BufRead ?\+.orig,?\+.bak,?\+.old,?\+.new,?\+.rpmsave,?\+.rpmnew
|
||||
\ exe "doau filetypedetect BufRead " . expand("<afile>:r")
|
||||
\ exe "doau filetypedetect BufRead " . fnameescape(expand("<afile>:r"))
|
||||
au BufNewFile,BufRead *~
|
||||
\ let s:name = expand("<afile>") |
|
||||
\ let s:short = substitute(s:name, '\~$', '', '') |
|
||||
\ if s:name != s:short && s:short != "" |
|
||||
\ exe "doau filetypedetect BufRead " . s:short |
|
||||
\ exe "doau filetypedetect BufRead " . fnameescape(s:short) |
|
||||
\ endif |
|
||||
\ unlet s:name |
|
||||
\ unlet s:short
|
||||
\ unlet s:name s:short
|
||||
au BufNewFile,BufRead ?\+.in
|
||||
\ if expand("<afile>:t") != "configure.in" |
|
||||
\ exe "doau filetypedetect BufRead " . expand("<afile>:r") |
|
||||
\ exe "doau filetypedetect BufRead " . fnameescape(expand("<afile>:r")) |
|
||||
\ endif
|
||||
elseif &verbose > 0
|
||||
echomsg "Warning: some filetypes will not be recognized because this version of Vim does not have fnameescape()"
|
||||
endif
|
||||
|
||||
" Pattern used to match file names which should not be inspected.
|
||||
" Currently finds compressed files.
|
||||
@@ -187,7 +190,7 @@ func! s:FTasmsyntax()
|
||||
let head = " ".getline(1)." ".getline(2)." ".getline(3)." ".getline(4).
|
||||
\" ".getline(5)." "
|
||||
if head =~ '\sasmsyntax=\S\+\s'
|
||||
let b:asmsyntax = substitute(head, '.*\sasmsyntax=\(\S\+\)\s.*','\1', "")
|
||||
let b:asmsyntax = substitute(head, '.*\sasmsyntax=\([a-zA-Z0-9]\+\)\s.*','\1', "")
|
||||
elseif ((head =~? '\.title') || (head =~? '\.ident') || (head =~? '\.macro') || (head =~? '\.subtitle') || (head =~? '\.library'))
|
||||
let b:asmsyntax = "vmasm"
|
||||
endif
|
||||
|
||||
+3
-2
@@ -783,8 +783,9 @@ func! s:BMMunge(fname, bnum)
|
||||
return name
|
||||
endfunc
|
||||
|
||||
" When just starting Vim, load the buffer menu later
|
||||
if has("vim_starting")
|
||||
" When just starting Vim, load the buffer menu later. Don't do this for MacVim
|
||||
" because it makes the menu flicker each time a new editor window is opened.
|
||||
if has("vim_starting") && !has("gui_macvim")
|
||||
augroup LoadBufferMenu
|
||||
au! VimEnter * if !exists("no_buffers_menu") | call <SID>BMShow() | endif
|
||||
au VimEnter * au! LoadBufferMenu
|
||||
|
||||
+6
-2
@@ -1,7 +1,7 @@
|
||||
" These commands create the option window.
|
||||
"
|
||||
" Maintainer: Bram Moolenaar <Bram@vim.org>
|
||||
" Last Change: 2006 Oct 10
|
||||
" Last Change: 2008 May 12
|
||||
|
||||
" If there already is an option window, jump to that one.
|
||||
if bufwinnr("option-window") > 0
|
||||
@@ -147,7 +147,7 @@ endwhile
|
||||
|
||||
" Open the window
|
||||
new option-window
|
||||
setlocal ts=15 tw=0
|
||||
setlocal ts=15 tw=0 noro
|
||||
|
||||
" Insert help and a "set" command for each option.
|
||||
call append(0, '" Each "set" line shows the current value of an option (on the left).')
|
||||
@@ -350,6 +350,10 @@ call append("$", "lines\tnumber of lines in the display")
|
||||
call append("$", " \tset lines=" . &lines)
|
||||
call append("$", "lazyredraw\tdon't redraw while executing macros")
|
||||
call <SID>BinOptionG("lz", &lz)
|
||||
if has("reltime")
|
||||
call append("$", "redrawtime\ttimeout for 'hlsearch' and :match highlighting in msec")
|
||||
call append("$", " \tset rdt=" . &rdt)
|
||||
endif
|
||||
call append("$", "writedelay\tdelay in msec for each char written to the display")
|
||||
call append("$", "\t(for debugging)")
|
||||
call append("$", " \tset wd=" . &wd)
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>_cycleWindows:</key>
|
||||
<string></string>
|
||||
<key>_cycleWindowsBackwards:</key>
|
||||
<string></string>
|
||||
<key>addNewTab:</key>
|
||||
<string></string>
|
||||
<key>arrangeInFront:</key>
|
||||
@@ -56,6 +60,8 @@
|
||||
<string></string>
|
||||
<key>selectPreviousWindow:</key>
|
||||
<string></string>
|
||||
<key>showVimHelp:</key>
|
||||
<string></string>
|
||||
<key>terminate:</key>
|
||||
<string></string>
|
||||
<key>undo:</key>
|
||||
@@ -64,5 +70,7 @@
|
||||
<string></string>
|
||||
<key>unhideAllApplications:</key>
|
||||
<string></string>
|
||||
<key>zoomAll:</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
+20
@@ -15,12 +15,20 @@
|
||||
<string>id</string>
|
||||
<key>newWindow</key>
|
||||
<string>id</string>
|
||||
<key>openWebsite</key>
|
||||
<string>id</string>
|
||||
<key>orderFrontPreferencePanel</key>
|
||||
<string>id</string>
|
||||
<key>selectNextWindow</key>
|
||||
<string>id</string>
|
||||
<key>selectPreviousWindow</key>
|
||||
<string>id</string>
|
||||
<key>showHelp</key>
|
||||
<string>id</string>
|
||||
<key>showVimHelp</key>
|
||||
<string>id</string>
|
||||
<key>zoomAll</key>
|
||||
<string>id</string>
|
||||
</dict>
|
||||
<key>CLASS</key>
|
||||
<string>MMAppController</string>
|
||||
@@ -29,9 +37,21 @@
|
||||
<key>SUPERCLASS</key>
|
||||
<string>NSObject</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CLASS</key>
|
||||
<string>NSMenu</string>
|
||||
<key>LANGUAGE</key>
|
||||
<string>ObjC</string>
|
||||
<key>SUPERCLASS</key>
|
||||
<string>NSObject</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>ACTIONS</key>
|
||||
<dict>
|
||||
<key>_cycleWindows</key>
|
||||
<string>id</string>
|
||||
<key>_cycleWindowsBackwards</key>
|
||||
<string>id</string>
|
||||
<key>addNewTab</key>
|
||||
<string>id</string>
|
||||
</dict>
|
||||
|
||||
+2
-2
@@ -10,10 +10,10 @@
|
||||
<integer>5</integer>
|
||||
<key>IBOpenObjects</key>
|
||||
<array>
|
||||
<integer>57</integer>
|
||||
<integer>310</integer>
|
||||
</array>
|
||||
<key>IBSystem Version</key>
|
||||
<string>9B18</string>
|
||||
<string>9D34</string>
|
||||
<key>targetFramework</key>
|
||||
<string>IBCocoaFramework</string>
|
||||
</dict>
|
||||
|
||||
Binary file not shown.
+30
-1
@@ -4,6 +4,35 @@
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<!--
|
||||
Both UTExportedTypeDeclarations (for Spotlight and QuickLook) and
|
||||
CFBundleDocumentTypes seem to be required, even though they contain
|
||||
more or less the same information:
|
||||
http://lists.apple.com/archives/Spotlight-dev/2007/Jul/msg00019.html
|
||||
-->
|
||||
<key>UTExportedTypeDeclarations</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UTTypeConformsTo</key>
|
||||
<array>
|
||||
<string>public.text</string>
|
||||
<string>public.plain-text</string>
|
||||
</array>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>vim script file</string>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>org.vim.vim</string>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>com.apple.ostype</key>
|
||||
<string>TEXT</string>
|
||||
<key>public.filename-extension</key>
|
||||
<array>
|
||||
<string>vim</string>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
@@ -545,7 +574,7 @@
|
||||
<key>CFBundleSignature</key>
|
||||
<string>VIMM</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>28</string>
|
||||
<string>29</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
|
||||
@@ -21,19 +21,24 @@
|
||||
NSString *openSelectionString;
|
||||
ATSFontContainerRef fontContainerRef;
|
||||
NSMutableDictionary *pidArguments;
|
||||
|
||||
NSMenu *defaultMainMenu;
|
||||
NSMenuItem *appMenuItemTemplate;
|
||||
NSMenuItem *recentFilesMenuItem;
|
||||
}
|
||||
|
||||
+ (MMAppController *)sharedInstance;
|
||||
- (NSMenu *)defaultMainMenu;
|
||||
- (NSMenuItem *)appMenuItemTemplate;
|
||||
- (void)removeVimController:(id)controller;
|
||||
- (void)windowControllerWillOpen:(MMWindowController *)windowController;
|
||||
- (void)setMainMenu:(NSMenu *)mainMenu;
|
||||
- (IBAction)newWindow:(id)sender;
|
||||
- (IBAction)fileOpen:(id)sender;
|
||||
- (IBAction)selectNextWindow:(id)sender;
|
||||
- (IBAction)selectPreviousWindow:(id)sender;
|
||||
- (IBAction)fontSizeUp:(id)sender;
|
||||
- (IBAction)fontSizeDown:(id)sender;
|
||||
- (IBAction)orderFrontPreferencePanel:(id)sender;
|
||||
- (IBAction)openWebsite:(id)sender;
|
||||
- (IBAction)showVimHelp:(id)sender;
|
||||
- (IBAction)zoomAll:(id)sender;
|
||||
|
||||
@end
|
||||
|
||||
+283
-93
@@ -13,7 +13,7 @@
|
||||
* MMAppController is the delegate of NSApp and as such handles file open
|
||||
* requests, application termination, etc. It sets up a named NSConnection on
|
||||
* which it listens to incoming connections from Vim processes. It also
|
||||
* coordinates all MMVimControllers.
|
||||
* coordinates all MMVimControllers and takes care of the main menu.
|
||||
*
|
||||
* A new Vim process is started by calling launchVimProcessWithArguments:.
|
||||
* When the Vim process is initialized it notifies the app controller by
|
||||
@@ -24,6 +24,17 @@
|
||||
* A Vim process started from the command line connects directly by sending the
|
||||
* connectBackend:pid: message (launchVimProcessWithArguments: is never called
|
||||
* in this case).
|
||||
*
|
||||
* The main menu is handled as follows. Each Vim controller keeps its own main
|
||||
* menu. All menus except the "MacVim" menu are controlled by the Vim process.
|
||||
* The app controller also keeps a reference to the "default main menu" which
|
||||
* is set up in MainMenu.nib. When no editor window is open the default main
|
||||
* menu is used. When a new editor window becomes main its main menu becomes
|
||||
* the new main menu, this is done in -[MMAppController setMainMenu:].
|
||||
* NOTE: Certain heuristics are used to find the "MacVim", "Windows", "File",
|
||||
* and "Services" menu. If MainMenu.nib changes these heuristics may have to
|
||||
* change as well. For specifics see the find... methods defined in the NSMenu
|
||||
* category "MMExtras".
|
||||
*/
|
||||
|
||||
#import "MMAppController.h"
|
||||
@@ -43,6 +54,10 @@ static NSTimeInterval MMReplyTimeout = 5;
|
||||
|
||||
static NSString *MMWebsiteString = @"http://code.google.com/p/macvim/";
|
||||
|
||||
// When terminating, notify Vim processes then sleep for these many
|
||||
// microseconds.
|
||||
static useconds_t MMTerminationSleepPeriod = 10000;
|
||||
|
||||
|
||||
#pragma options align=mac68k
|
||||
typedef struct
|
||||
@@ -86,15 +101,24 @@ static int executeInLoginShell(NSString *path, NSArray *args);
|
||||
- (void)passArguments:(NSDictionary *)args toVimController:(MMVimController*)vc;
|
||||
@end
|
||||
|
||||
@interface NSMenu (MMExtras)
|
||||
- (void)recurseSetAutoenablesItems:(BOOL)on;
|
||||
@end
|
||||
|
||||
@interface NSNumber (MMExtras)
|
||||
- (int)tag;
|
||||
@end
|
||||
|
||||
|
||||
@interface NSMenu (MMExtras)
|
||||
- (int)indexOfItemWithAction:(SEL)action;
|
||||
- (NSMenuItem *)itemWithAction:(SEL)action;
|
||||
- (NSMenu *)findMenuContainingItemWithAction:(SEL)action;
|
||||
- (NSMenu *)findWindowsMenu;
|
||||
- (NSMenu *)findApplicationMenu;
|
||||
- (NSMenu *)findServicesMenu;
|
||||
- (NSMenu *)findFileMenu;
|
||||
@end
|
||||
|
||||
|
||||
|
||||
|
||||
@implementation MMAppController
|
||||
|
||||
@@ -180,35 +204,51 @@ static int executeInLoginShell(NSString *path, NSArray *args);
|
||||
[vimControllers release]; vimControllers = nil;
|
||||
[openSelectionString release]; openSelectionString = nil;
|
||||
[recentFilesMenuItem release]; recentFilesMenuItem = nil;
|
||||
[defaultMainMenu release]; defaultMainMenu = nil;
|
||||
[appMenuItemTemplate release]; appMenuItemTemplate = nil;
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)applicationWillFinishLaunching:(NSNotification *)notification
|
||||
{
|
||||
// Create the "Open Recent" menu. See
|
||||
// http://lapcatsoftware.com/blog/2007/07/10/working-without-a-nib-part-5-open-recent-menu/
|
||||
// and http://www.cocoabuilder.com/archive/message/cocoa/2007/8/15/187793
|
||||
// Remember the default menu so that it can be restored if the user closes
|
||||
// all editor windows.
|
||||
defaultMainMenu = [[NSApp mainMenu] retain];
|
||||
|
||||
// Store a copy of the default app menu so we can use this as a template
|
||||
// for all other menus. We make a copy here because the "Services" menu
|
||||
// will not yet have been populated at this time. If we don't we get
|
||||
// problems trying to set key equivalents later on because they might clash
|
||||
// with items on the "Services" menu.
|
||||
appMenuItemTemplate = [defaultMainMenu itemAtIndex:0];
|
||||
appMenuItemTemplate = [appMenuItemTemplate copy];
|
||||
|
||||
// Set up the "Open Recent" menu. See
|
||||
// http://lapcatsoftware.com/blog/2007/07/10/
|
||||
// working-without-a-nib-part-5-open-recent-menu/
|
||||
// and
|
||||
// http://www.cocoabuilder.com/archive/message/cocoa/2007/8/15/187793
|
||||
// for more information.
|
||||
//
|
||||
// The menu needs to be created and be added to a toplevel menu in
|
||||
// applicationWillFinishLaunching at the latest, otherwise it doesn't work.
|
||||
//
|
||||
// The menu itself is created in MainMenu.nib but we still seem to have to
|
||||
// hack around a bit to get it to work. (This has to be done in
|
||||
// applicationWillFinishLaunching at the latest, otherwise it doesn't
|
||||
// work.)
|
||||
NSMenu *fileMenu = [defaultMainMenu findFileMenu];
|
||||
if (fileMenu) {
|
||||
int idx = [fileMenu indexOfItemWithAction:@selector(fileOpen:)];
|
||||
if (idx >= 0 && idx+1 < [fileMenu numberOfItems])
|
||||
|
||||
recentFilesMenuItem = [[NSMenuItem alloc] initWithTitle:@"Open Recent"
|
||||
action:nil keyEquivalent:@""];
|
||||
recentFilesMenuItem = [fileMenu itemWithTitle:@"Open Recent"];
|
||||
[[recentFilesMenuItem submenu] performSelector:@selector(_setMenuName:)
|
||||
withObject:@"NSRecentDocumentsMenu"];
|
||||
|
||||
NSMenu *recentFilesMenu = [[NSMenu alloc] initWithTitle:@"Open Recent"];
|
||||
[recentFilesMenu performSelector:@selector(_setMenuName:)
|
||||
withObject:@"NSRecentDocumentsMenu"];
|
||||
|
||||
[recentFilesMenu addItemWithTitle:@"Clear Menu"
|
||||
action:@selector(clearRecentDocuments:)
|
||||
keyEquivalent:@""];
|
||||
[recentFilesMenuItem setSubmenu:recentFilesMenu];
|
||||
[recentFilesMenu release]; // the menu is retained by recentFilesMenuItem
|
||||
[recentFilesMenuItem setTag:-1]; // must not be 0
|
||||
|
||||
[[[[NSApp mainMenu] itemWithTitle:@"File"] submenu] addItem:recentFilesMenuItem];
|
||||
// Note: The "Recent Files" menu must be moved around since there is no
|
||||
// -[NSApp setRecentFilesMenu:] method. We keep a reference to it to
|
||||
// facilitate this move (see setMainMenu: below).
|
||||
[recentFilesMenuItem retain];
|
||||
}
|
||||
|
||||
#if MM_HANDLE_XCODE_MOD_EVENT
|
||||
[[NSAppleEventManager sharedAppleEventManager]
|
||||
@@ -383,11 +423,16 @@ static int executeInLoginShell(NSString *path, NSArray *args);
|
||||
if (modifiedBuffers) {
|
||||
NSAlert *alert = [[NSAlert alloc] init];
|
||||
[alert setAlertStyle:NSWarningAlertStyle];
|
||||
[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?"];
|
||||
[alert addButtonWithTitle:NSLocalizedString(@"Quit",
|
||||
@"Dialog button")];
|
||||
[alert addButtonWithTitle:NSLocalizedString(@"Cancel",
|
||||
@"Dialog button")];
|
||||
[alert setMessageText:NSLocalizedString(@"Quit without saving?",
|
||||
@"Quit dialog with changed buffers, title")];
|
||||
[alert setInformativeText:NSLocalizedString(
|
||||
@"There are modified buffers, "
|
||||
"if you quit now all changes will be lost. Quit anyway?",
|
||||
@"Quit dialog with changed buffers, text")];
|
||||
|
||||
if ([alert runModal] != NSAlertFirstButtonReturn)
|
||||
reply = NSTerminateCancel;
|
||||
@@ -414,24 +459,35 @@ static int executeInLoginShell(NSString *path, NSArray *args);
|
||||
if (numWindows > 1 || numTabs > 1) {
|
||||
NSAlert *alert = [[NSAlert alloc] init];
|
||||
[alert setAlertStyle:NSWarningAlertStyle];
|
||||
[alert addButtonWithTitle:@"Quit"];
|
||||
[alert addButtonWithTitle:@"Cancel"];
|
||||
[alert setMessageText:@"Are you sure you want to quit MacVim?"];
|
||||
[alert addButtonWithTitle:NSLocalizedString(@"Quit",
|
||||
@"Dialog button")];
|
||||
[alert addButtonWithTitle:NSLocalizedString(@"Cancel",
|
||||
@"Dialog button")];
|
||||
[alert setMessageText:NSLocalizedString(
|
||||
@"Are you sure you want to quit MacVim?",
|
||||
@"Quit dialog with no changed buffers, title")];
|
||||
|
||||
NSString *info = nil;
|
||||
if (numWindows > 1) {
|
||||
if (numTabs > numWindows)
|
||||
info = [NSString stringWithFormat:@"There are %d windows "
|
||||
"open in MacVim, with a total of %d tabs. Do you want "
|
||||
"to quit anyway?", numWindows, numTabs];
|
||||
info = [NSString stringWithFormat:NSLocalizedString(
|
||||
@"There are %d windows open in MacVim, with a "
|
||||
"total of %d tabs. Do you want to quit anyway?",
|
||||
@"Quit dialog with no changed buffers, text"),
|
||||
numWindows, numTabs];
|
||||
else
|
||||
info = [NSString stringWithFormat:@"There are %d windows "
|
||||
"open in MacVim. Do you want to quit anyway?",
|
||||
info = [NSString stringWithFormat:NSLocalizedString(
|
||||
@"There are %d windows open in MacVim. "
|
||||
"Do you want to quit anyway?",
|
||||
@"Quit dialog with no changed buffers, text"),
|
||||
numWindows];
|
||||
|
||||
} else {
|
||||
info = [NSString stringWithFormat:@"There are %d tabs open "
|
||||
"in MacVim. Do you want to quit anyway?", numTabs];
|
||||
info = [NSString stringWithFormat:NSLocalizedString(
|
||||
@"There are %d tabs open in MacVim. "
|
||||
"Do you want to quit anyway?",
|
||||
@"Quit dialog with no changed buffers, text"),
|
||||
numTabs];
|
||||
}
|
||||
|
||||
[alert setInformativeText:info];
|
||||
@@ -451,6 +507,11 @@ static int executeInLoginShell(NSString *path, NSArray *args);
|
||||
id vc;
|
||||
while ((vc = [e nextObject]))
|
||||
[vc sendMessage:TerminateNowMsgID data:nil];
|
||||
|
||||
// Give Vim processes a chance to terminate before MacVim. If they
|
||||
// haven't terminated by the time applicationWillTerminate: is sent,
|
||||
// they may be forced to quit (see below).
|
||||
usleep(MMTerminationSleepPeriod);
|
||||
}
|
||||
|
||||
return reply;
|
||||
@@ -487,6 +548,24 @@ static int executeInLoginShell(NSString *path, NSArray *args);
|
||||
[NSApp setDelegate:nil];
|
||||
}
|
||||
|
||||
+ (MMAppController *)sharedInstance
|
||||
{
|
||||
// Note: The app controller is a singleton which is instantiated in
|
||||
// MainMenu.nib where it is also connected as the delegate of NSApp.
|
||||
id delegate = [NSApp delegate];
|
||||
return [delegate isKindOfClass:self] ? (MMAppController*)delegate : nil;
|
||||
}
|
||||
|
||||
- (NSMenu *)defaultMainMenu
|
||||
{
|
||||
return defaultMainMenu;
|
||||
}
|
||||
|
||||
- (NSMenuItem *)appMenuItemTemplate
|
||||
{
|
||||
return appMenuItemTemplate;
|
||||
}
|
||||
|
||||
- (void)removeVimController:(id)controller
|
||||
{
|
||||
//NSLog(@"%s%@", _cmd, controller);
|
||||
@@ -496,16 +575,9 @@ static int executeInLoginShell(NSString *path, NSArray *args);
|
||||
[vimControllers removeObject:controller];
|
||||
|
||||
if (![vimControllers count]) {
|
||||
// Turn on autoenabling of menus (because no Vim is open to handle it),
|
||||
// but do not touch the MacVim menu. Note that the menus must be
|
||||
// enabled first otherwise autoenabling does not work.
|
||||
NSMenu *mainMenu = [NSApp mainMenu];
|
||||
int i, count = [mainMenu numberOfItems];
|
||||
for (i = 1; i < count; ++i) {
|
||||
NSMenuItem *item = [mainMenu itemAtIndex:i];
|
||||
[item setEnabled:YES];
|
||||
[[item submenu] recurseSetAutoenablesItems:YES];
|
||||
}
|
||||
// The last editor window just closed so restore the main menu back to
|
||||
// its default state (which is defined in MainMenu.nib).
|
||||
[self setMainMenu:defaultMainMenu];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -548,6 +620,69 @@ static int executeInLoginShell(NSString *path, NSArray *args);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setMainMenu:(NSMenu *)mainMenu
|
||||
{
|
||||
if ([NSApp mainMenu] == mainMenu) return;
|
||||
|
||||
// If the new menu has a "Recent Files" dummy item, then swap the real item
|
||||
// for the dummy. We are forced to do this since Cocoa initializes the
|
||||
// "Recent Files" menu and there is no way to simply point Cocoa to a new
|
||||
// item each time the menus are swapped.
|
||||
NSMenu *fileMenu = [mainMenu findFileMenu];
|
||||
if (recentFilesMenuItem && fileMenu) {
|
||||
int dummyIdx =
|
||||
[fileMenu indexOfItemWithAction:@selector(recentFilesDummy:)];
|
||||
if (dummyIdx >= 0) {
|
||||
NSMenuItem *dummyItem = [[fileMenu itemAtIndex:dummyIdx] retain];
|
||||
[fileMenu removeItemAtIndex:dummyIdx];
|
||||
|
||||
NSMenu *recentFilesParentMenu = [recentFilesMenuItem menu];
|
||||
int idx = [recentFilesParentMenu indexOfItem:recentFilesMenuItem];
|
||||
if (idx >= 0) {
|
||||
[[recentFilesMenuItem retain] autorelease];
|
||||
[recentFilesParentMenu removeItemAtIndex:idx];
|
||||
[recentFilesParentMenu insertItem:dummyItem atIndex:idx];
|
||||
}
|
||||
|
||||
[fileMenu insertItem:recentFilesMenuItem atIndex:dummyIdx];
|
||||
[dummyItem release];
|
||||
}
|
||||
}
|
||||
|
||||
// Now set the new menu. Notice that we keep one menu for each editor
|
||||
// window since each editor can have its own set of menus. When swapping
|
||||
// menus we have to tell Cocoa where the new "MacVim", "Windows", and
|
||||
// "Services" menu are.
|
||||
[NSApp setMainMenu:mainMenu];
|
||||
|
||||
// Setting the "MacVim" (or "Application") menu ensures that it is typeset
|
||||
// in boldface. (The setAppleMenu: method used to be public but is now
|
||||
// private so this will have to be considered a bit of a hack!)
|
||||
NSMenu *appMenu = [mainMenu findApplicationMenu];
|
||||
[NSApp performSelector:@selector(setAppleMenu:) withObject:appMenu];
|
||||
|
||||
NSMenu *servicesMenu = [mainMenu findServicesMenu];
|
||||
[NSApp setServicesMenu:servicesMenu];
|
||||
|
||||
NSMenu *windowsMenu = [mainMenu findWindowsMenu];
|
||||
if (windowsMenu) {
|
||||
// Cocoa isn't clever enough to get rid of items it has added to the
|
||||
// "Windows" menu so we have to do it ourselves otherwise there will be
|
||||
// multiple menu items for each window in the "Windows" menu.
|
||||
// This code assumes that the only items Cocoa add are ones which
|
||||
// send off the action makeKeyAndOrderFront:. (Cocoa will not add
|
||||
// another separator item if the last item on the "Windows" menu
|
||||
// already is a separator, so we needen't worry about separators.)
|
||||
int i, count = [windowsMenu numberOfItems];
|
||||
for (i = count-1; i >= 0; --i) {
|
||||
NSMenuItem *item = [windowsMenu itemAtIndex:i];
|
||||
if ([item action] == @selector(makeKeyAndOrderFront:))
|
||||
[windowsMenu removeItem:item];
|
||||
}
|
||||
}
|
||||
[NSApp setWindowsMenu:windowsMenu];
|
||||
}
|
||||
|
||||
- (IBAction)newWindow:(id)sender
|
||||
{
|
||||
[self launchVimProcessWithArguments:nil];
|
||||
@@ -613,18 +748,6 @@ static int executeInLoginShell(NSString *path, NSArray *args);
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)fontSizeUp:(id)sender
|
||||
{
|
||||
[[NSFontManager sharedFontManager] modifyFont:
|
||||
[NSNumber numberWithInt:NSSizeUpFontAction]];
|
||||
}
|
||||
|
||||
- (IBAction)fontSizeDown:(id)sender
|
||||
{
|
||||
[[NSFontManager sharedFontManager] modifyFont:
|
||||
[NSNumber numberWithInt:NSSizeDownFontAction]];
|
||||
}
|
||||
|
||||
- (IBAction)orderFrontPreferencePanel:(id)sender
|
||||
{
|
||||
[[MMPreferenceController sharedPrefsWindowController] showWindow:self];
|
||||
@@ -636,6 +759,18 @@ static int executeInLoginShell(NSString *path, NSArray *args);
|
||||
[NSURL URLWithString:MMWebsiteString]];
|
||||
}
|
||||
|
||||
- (IBAction)showVimHelp:(id)sender
|
||||
{
|
||||
// Open a new window with the help window maximized.
|
||||
[self launchVimProcessWithArguments:[NSArray arrayWithObjects:
|
||||
@"-c", @":h gui_mac", @"-c", @":res", nil]];
|
||||
}
|
||||
|
||||
- (IBAction)zoomAll:(id)sender
|
||||
{
|
||||
[NSApp makeWindowsPerform:@selector(performZoom:) inOrder:YES];
|
||||
}
|
||||
|
||||
- (byref id <MMFrontendProtocol>)
|
||||
connectBackend:(byref in id <MMBackendProtocol>)backend
|
||||
pid:(int)pid
|
||||
@@ -649,7 +784,7 @@ static int executeInLoginShell(NSString *path, NSArray *args);
|
||||
setProtocolForProxy:@protocol(MMBackendProtocol)];
|
||||
|
||||
vc = [[[MMVimController alloc]
|
||||
initWithBackend:backend pid:pid recentFiles:recentFilesMenuItem]
|
||||
initWithBackend:backend pid:pid]
|
||||
autorelease];
|
||||
|
||||
if (![vimControllers count]) {
|
||||
@@ -870,18 +1005,23 @@ static int executeInLoginShell(NSString *path, NSArray *args);
|
||||
|
||||
if (firstMissingFile) {
|
||||
NSAlert *alert = [[NSAlert alloc] init];
|
||||
[alert addButtonWithTitle:@"OK"];
|
||||
[alert addButtonWithTitle:NSLocalizedString(@"OK",
|
||||
@"Dialog button")];
|
||||
|
||||
NSString *text;
|
||||
if ([files count] >= count-1) {
|
||||
[alert setMessageText:@"File not found"];
|
||||
text = [NSString stringWithFormat:@"Could not open file with "
|
||||
"name %@.", firstMissingFile];
|
||||
[alert setMessageText:NSLocalizedString(@"File not found",
|
||||
@"File not found dialog, title")];
|
||||
text = [NSString stringWithFormat:NSLocalizedString(
|
||||
@"Could not open file with name %@.",
|
||||
@"File not found dialog, text"), firstMissingFile];
|
||||
} else {
|
||||
[alert setMessageText:@"Multiple files not found"];
|
||||
text = [NSString stringWithFormat:@"Could not open file with "
|
||||
"name %@, and %d other files.", firstMissingFile,
|
||||
count-[files count]-1];
|
||||
[alert setMessageText:NSLocalizedString(@"Multiple files not found",
|
||||
@"File not found dialog, title")];
|
||||
text = [NSString stringWithFormat:NSLocalizedString(
|
||||
@"Could not open file with name %@, and %d other files.",
|
||||
@"File not found dialog, text"),
|
||||
firstMissingFile, count-[files count]-1];
|
||||
}
|
||||
|
||||
[alert setInformativeText:text];
|
||||
@@ -1013,6 +1153,8 @@ static int executeInLoginShell(NSString *path, NSArray *args);
|
||||
// TODO: This is a moronic test...should query the Vim process if there
|
||||
// are any open buffers or something like that instead.
|
||||
NSString *title = [[[vc windowController] window] title];
|
||||
|
||||
// TODO: this will not work in a localized MacVim
|
||||
if ([title hasPrefix:@"[No Name] - VIM"]) {
|
||||
//NSLog(@"found untitled window");
|
||||
return vc;
|
||||
@@ -1119,28 +1261,6 @@ static int executeInLoginShell(NSString *path, NSArray *args);
|
||||
|
||||
|
||||
|
||||
@implementation NSMenu (MMExtras)
|
||||
|
||||
- (void)recurseSetAutoenablesItems:(BOOL)on
|
||||
{
|
||||
[self setAutoenablesItems:on];
|
||||
|
||||
int i, count = [self numberOfItems];
|
||||
for (i = 0; i < count; ++i) {
|
||||
NSMenuItem *item = [self itemAtIndex:i];
|
||||
[item setEnabled:YES];
|
||||
NSMenu *submenu = [item submenu];
|
||||
if (submenu) {
|
||||
[submenu recurseSetAutoenablesItems:on];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end // NSMenu (MMExtras)
|
||||
|
||||
|
||||
|
||||
|
||||
@implementation NSNumber (MMExtras)
|
||||
- (int)tag
|
||||
{
|
||||
@@ -1151,6 +1271,77 @@ static int executeInLoginShell(NSString *path, NSArray *args);
|
||||
|
||||
|
||||
|
||||
@implementation NSMenu (MMExtras)
|
||||
|
||||
- (int)indexOfItemWithAction:(SEL)action
|
||||
{
|
||||
int i, count = [self numberOfItems];
|
||||
for (i = 0; i < count; ++i) {
|
||||
NSMenuItem *item = [self itemAtIndex:i];
|
||||
if ([item action] == action)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
- (NSMenuItem *)itemWithAction:(SEL)action
|
||||
{
|
||||
int idx = [self indexOfItemWithAction:action];
|
||||
return idx >= 0 ? [self itemAtIndex:idx] : nil;
|
||||
}
|
||||
|
||||
- (NSMenu *)findMenuContainingItemWithAction:(SEL)action
|
||||
{
|
||||
// NOTE: We only look for the action in the submenus of 'self'
|
||||
int i, count = [self numberOfItems];
|
||||
for (i = 0; i < count; ++i) {
|
||||
NSMenu *menu = [[self itemAtIndex:i] submenu];
|
||||
NSMenuItem *item = [menu itemWithAction:action];
|
||||
if (item) return menu;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSMenu *)findWindowsMenu
|
||||
{
|
||||
return [self findMenuContainingItemWithAction:
|
||||
@selector(performMiniaturize:)];
|
||||
}
|
||||
|
||||
- (NSMenu *)findApplicationMenu
|
||||
{
|
||||
// TODO: Just return [self itemAtIndex:0]?
|
||||
return [self findMenuContainingItemWithAction:@selector(terminate:)];
|
||||
}
|
||||
|
||||
- (NSMenu *)findServicesMenu
|
||||
{
|
||||
// NOTE! Our heuristic for finding the "Services" menu is to look for the
|
||||
// second item before the "Hide MacVim" menu item on the "MacVim" menu.
|
||||
// (The item before "Hide MacVim" should be a separator, but this is not
|
||||
// important as long as the item before that is the "Services" menu.)
|
||||
|
||||
NSMenu *appMenu = [self findApplicationMenu];
|
||||
if (!appMenu) return nil;
|
||||
|
||||
int idx = [appMenu indexOfItemWithAction: @selector(hide:)];
|
||||
if (idx-2 < 0) return nil; // idx == -1, if selector not found
|
||||
|
||||
return [[appMenu itemAtIndex:idx-2] submenu];
|
||||
}
|
||||
|
||||
- (NSMenu *)findFileMenu
|
||||
{
|
||||
return [self findMenuContainingItemWithAction:@selector(performClose:)];
|
||||
}
|
||||
|
||||
@end // NSMenu (MMExtras)
|
||||
|
||||
|
||||
|
||||
|
||||
static int
|
||||
executeInLoginShell(NSString *path, NSArray *args)
|
||||
{
|
||||
@@ -1244,4 +1435,3 @@ executeInLoginShell(NSString *path, NSArray *args)
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,6 @@ enum { MMMaxCellsPerChar = 2 };
|
||||
//
|
||||
// MMTextView methods
|
||||
//
|
||||
- (NSEvent *)lastMouseDownEvent;
|
||||
- (void)setShouldDrawInsertionPoint:(BOOL)on;
|
||||
- (void)setPreEditRow:(int)row column:(int)col;
|
||||
- (void)hideMarkedTextField;
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#import "MMAtsuiTextView.h"
|
||||
#import "MMVimController.h"
|
||||
#import "MMWindowController.h"
|
||||
#import "MMAppController.h"
|
||||
#import "MacVim.h"
|
||||
|
||||
|
||||
@@ -66,6 +67,7 @@ enum {
|
||||
- (void)updateAtsuStyles;
|
||||
- (void)dispatchKeyEvent:(NSEvent *)event;
|
||||
- (void)sendKeyDown:(const char *)chars length:(int)len modifiers:(int)flags;
|
||||
- (void)hideMouseCursor;
|
||||
- (MMWindowController *)windowController;
|
||||
- (MMVimController *)vimController;
|
||||
@end
|
||||
@@ -247,11 +249,6 @@ enum {
|
||||
|
||||
|
||||
|
||||
- (NSEvent *)lastMouseDownEvent
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)setShouldDrawInsertionPoint:(BOOL)on
|
||||
{
|
||||
}
|
||||
@@ -337,8 +334,7 @@ enum {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Support 'mousehide' (check p_mh)
|
||||
[NSCursor setHiddenUntilMouseMoves:YES];
|
||||
[self hideMouseCursor];
|
||||
|
||||
// NOTE: 'string' is either an NSString or an NSAttributedString. Since we
|
||||
// do not support attributes, simply pass the corresponding NSString in the
|
||||
@@ -416,13 +412,13 @@ enum {
|
||||
if ([[NSApp mainMenu] performKeyEquivalent:event])
|
||||
return YES;
|
||||
|
||||
// HACK! KeyCode 50 represent the key which switches between windows
|
||||
// within an application (like Cmd+Tab is used to switch between
|
||||
// applications). Return NO here, else the window switching does not work.
|
||||
//
|
||||
// Will this hack work for all languages / keyboard layouts?
|
||||
if ([event keyCode] == 50)
|
||||
return NO;
|
||||
// HACK! Give the default main menu a chance to handle the key down event.
|
||||
// This is to ensure that the standard mappings (which are in the default
|
||||
// main menu) are always available, also when the default Vim menus are
|
||||
// used (these do not set any key equivalents!).
|
||||
if ([[[MMAppController sharedInstance] defaultMainMenu]
|
||||
performKeyEquivalent:event])
|
||||
return YES;
|
||||
|
||||
// HACK! On Leopard Ctrl-key events end up here instead of keyDown:.
|
||||
if (flags & NSControlKeyMask) {
|
||||
@@ -905,14 +901,23 @@ enum {
|
||||
[data appendBytes:&len length:sizeof(int)];
|
||||
[data appendBytes:chars length:len];
|
||||
|
||||
// TODO: Support 'mousehide' (check p_mh)
|
||||
[NSCursor setHiddenUntilMouseMoves:YES];
|
||||
[self hideMouseCursor];
|
||||
|
||||
//NSLog(@"%s len=%d chars=0x%x", _cmd, len, chars[0]);
|
||||
[[self vimController] sendMessage:KeyDownMsgID data:data];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)hideMouseCursor
|
||||
{
|
||||
// Check 'mousehide' option
|
||||
id mh = [[[self vimController] vimState] objectForKey:@"p_mh"];
|
||||
if (mh && ![mh boolValue])
|
||||
[NSCursor setHiddenUntilMouseMoves:NO];
|
||||
else
|
||||
[NSCursor setHiddenUntilMouseMoves:YES];
|
||||
}
|
||||
|
||||
- (MMWindowController *)windowController
|
||||
{
|
||||
id windowController = [[self window] windowController];
|
||||
@@ -1116,6 +1121,10 @@ enum {
|
||||
} else if (MMInsertionPointVertical == shape) {
|
||||
int frac = (cellSize.width * percent + 99)/100;
|
||||
rect.size.width = frac;
|
||||
} else if (MMInsertionPointVerticalRight == shape) {
|
||||
int frac = (cellSize.width * percent + 99)/100;
|
||||
rect.origin.x += rect.size.width - frac;
|
||||
rect.size.width = frac;
|
||||
}
|
||||
|
||||
[color set];
|
||||
|
||||
+1
-10
@@ -57,6 +57,7 @@
|
||||
- (NSConnection *)connection;
|
||||
- (NSDictionary *)actionDict;
|
||||
|
||||
- (void)queueMessage:(int)msgid properties:(NSDictionary *)props;
|
||||
- (BOOL)checkin;
|
||||
- (BOOL)openVimWindow;
|
||||
- (void)clearAll;
|
||||
@@ -84,16 +85,6 @@
|
||||
saving:(int)saving;
|
||||
- (int)presentDialogWithType:(int)type title:(char *)title message:(char *)msg
|
||||
buttons:(char *)btns textField:(char *)txtfield;
|
||||
- (void)addMenuWithTag:(int)tag parent:(int)parentTag name:(char *)name
|
||||
atIndex:(int)index;
|
||||
- (void)addMenuItemWithTag:(int)tag parent:(int)parentTag name:(char *)name
|
||||
tip:(char *)tip icon:(char *)icon
|
||||
keyEquivalent:(int)key modifiers:(int)mods
|
||||
action:(char *)action isAlternate:(int)isAlt
|
||||
atIndex:(int)index;
|
||||
- (void)removeMenuItemWithTag:(int)tag;
|
||||
- (void)enableMenuItemWithTag:(int)tag state:(int)enabled;
|
||||
- (void)showPopupMenuWithName:(char *)name atMouseLocation:(BOOL)mouse;
|
||||
- (void)showToolbar:(int)enable flags:(int)flags;
|
||||
- (void)createScrollbarWithIdentifier:(long)ident type:(int)type;
|
||||
- (void)destroyScrollbarWithIdentifier:(long)ident;
|
||||
|
||||
+18
-185
@@ -51,10 +51,12 @@ static unsigned MMServerMax = 1000;
|
||||
|
||||
// TODO: Move to separate file.
|
||||
static int eventModifierFlagsToVimModMask(int modifierFlags);
|
||||
static int vimModMaskToEventModifierFlags(int mods);
|
||||
static int eventModifierFlagsToVimMouseModMask(int modifierFlags);
|
||||
static int eventButtonNumberToVimMouseButton(int buttonNumber);
|
||||
static int specialKeyToNSKey(int key);
|
||||
|
||||
// In gui_macvim.m
|
||||
vimmenu_T *menu_for_descriptor(NSArray *desc);
|
||||
|
||||
|
||||
enum {
|
||||
MMBlinkStateNone = 0,
|
||||
@@ -76,6 +78,7 @@ static NSString *MMSymlinkWarningString =
|
||||
|
||||
|
||||
|
||||
|
||||
@interface MMBackend (Private)
|
||||
- (void)queueVimStateMessage;
|
||||
- (void)processInputQueue;
|
||||
@@ -226,6 +229,11 @@ static NSString *MMSymlinkWarningString =
|
||||
return actionDict;
|
||||
}
|
||||
|
||||
- (void)queueMessage:(int)msgid properties:(NSDictionary *)props
|
||||
{
|
||||
[self queueMessage:msgid data:[props dictionaryAsData]];
|
||||
}
|
||||
|
||||
- (BOOL)checkin
|
||||
{
|
||||
if (![self connection]) {
|
||||
@@ -740,100 +748,6 @@ static NSString *MMSymlinkWarningString =
|
||||
return retval;
|
||||
}
|
||||
|
||||
- (void)addMenuWithTag:(int)tag parent:(int)parentTag name:(char *)name
|
||||
atIndex:(int)index
|
||||
{
|
||||
//NSLog(@"addMenuWithTag:%d parent:%d name:%s atIndex:%d", tag, parentTag,
|
||||
// name, index);
|
||||
|
||||
int namelen = name ? strlen(name) : 0;
|
||||
NSMutableData *data = [NSMutableData data];
|
||||
|
||||
[data appendBytes:&tag length:sizeof(int)];
|
||||
[data appendBytes:&parentTag length:sizeof(int)];
|
||||
[data appendBytes:&namelen length:sizeof(int)];
|
||||
if (namelen > 0) [data appendBytes:name length:namelen];
|
||||
[data appendBytes:&index length:sizeof(int)];
|
||||
|
||||
[self queueMessage:AddMenuMsgID data:data];
|
||||
}
|
||||
|
||||
- (void)addMenuItemWithTag:(int)tag parent:(int)parentTag name:(char *)name
|
||||
tip:(char *)tip icon:(char *)icon
|
||||
keyEquivalent:(int)key modifiers:(int)mods
|
||||
action:(char *)action isAlternate:(int)isAlt
|
||||
atIndex:(int)index
|
||||
{
|
||||
//NSLog(@"addMenuItemWithTag:%d parent:%d name:%s tip:%s atIndex:%d", tag,
|
||||
// parentTag, name, tip, index);
|
||||
|
||||
int namelen = name ? strlen(name) : 0;
|
||||
int tiplen = tip ? strlen(tip) : 0;
|
||||
int iconlen = icon ? strlen(icon) : 0;
|
||||
int eventFlags = vimModMaskToEventModifierFlags(mods);
|
||||
int actionlen = action ? strlen(action) : 0;
|
||||
NSMutableData *data = [NSMutableData data];
|
||||
|
||||
key = specialKeyToNSKey(key);
|
||||
|
||||
[data appendBytes:&tag length:sizeof(int)];
|
||||
[data appendBytes:&parentTag length:sizeof(int)];
|
||||
[data appendBytes:&namelen length:sizeof(int)];
|
||||
if (namelen > 0) [data appendBytes:name length:namelen];
|
||||
[data appendBytes:&tiplen length:sizeof(int)];
|
||||
if (tiplen > 0) [data appendBytes:tip length:tiplen];
|
||||
[data appendBytes:&iconlen length:sizeof(int)];
|
||||
if (iconlen > 0) [data appendBytes:icon length:iconlen];
|
||||
[data appendBytes:&actionlen length:sizeof(int)];
|
||||
if (actionlen > 0) [data appendBytes:action length:actionlen];
|
||||
[data appendBytes:&index length:sizeof(int)];
|
||||
[data appendBytes:&key length:sizeof(int)];
|
||||
[data appendBytes:&eventFlags length:sizeof(int)];
|
||||
[data appendBytes:&isAlt length:sizeof(int)];
|
||||
|
||||
[self queueMessage:AddMenuItemMsgID data:data];
|
||||
}
|
||||
|
||||
- (void)removeMenuItemWithTag:(int)tag
|
||||
{
|
||||
NSMutableData *data = [NSMutableData data];
|
||||
[data appendBytes:&tag length:sizeof(int)];
|
||||
|
||||
[self queueMessage:RemoveMenuItemMsgID data:data];
|
||||
}
|
||||
|
||||
- (void)enableMenuItemWithTag:(int)tag state:(int)enabled
|
||||
{
|
||||
NSMutableData *data = [NSMutableData data];
|
||||
|
||||
[data appendBytes:&tag length:sizeof(int)];
|
||||
[data appendBytes:&enabled length:sizeof(int)];
|
||||
|
||||
[self queueMessage:EnableMenuItemMsgID data:data];
|
||||
}
|
||||
|
||||
- (void)showPopupMenuWithName:(char *)name atMouseLocation:(BOOL)mouse
|
||||
{
|
||||
int len = strlen(name);
|
||||
int row = -1, col = -1;
|
||||
|
||||
if (len <= 0) return;
|
||||
|
||||
if (!mouse && curwin) {
|
||||
row = curwin->w_wrow;
|
||||
col = curwin->w_wcol;
|
||||
}
|
||||
|
||||
NSMutableData *data = [NSMutableData data];
|
||||
|
||||
[data appendBytes:&row length:sizeof(int)];
|
||||
[data appendBytes:&col length:sizeof(int)];
|
||||
[data appendBytes:&len length:sizeof(int)];
|
||||
[data appendBytes:name length:len];
|
||||
|
||||
[self queueMessage:ShowPopupMenuMsgID data:data];
|
||||
}
|
||||
|
||||
- (void)showToolbar:(int)enable flags:(int)flags
|
||||
{
|
||||
NSMutableData *data = [NSMutableData data];
|
||||
@@ -1569,8 +1483,10 @@ static NSString *MMSymlinkWarningString =
|
||||
// flushed (e.g. storing the currently selected text would be a bad idea).
|
||||
// We take this approach of "pushing" the state to MacVim to avoid having
|
||||
// to make synchronous calls from MacVim to Vim in order to get state.
|
||||
|
||||
NSDictionary *vimState = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[[NSFileManager defaultManager] currentDirectoryPath], @"pwd",
|
||||
[NSNumber numberWithInt:p_mh], @"p_mh",
|
||||
nil];
|
||||
|
||||
[self queueMessage:SetVimStateMsgID data:[vimState dictionaryAsData]];
|
||||
@@ -1651,14 +1567,12 @@ static NSString *MMSymlinkWarningString =
|
||||
//NSLog(@"[VimTask] Resizing shell to %dx%d.", cols, rows);
|
||||
gui_resize_shell(cols, rows);
|
||||
} else if (ExecuteMenuMsgID == msgid) {
|
||||
if (!data) return;
|
||||
const void *bytes = [data bytes];
|
||||
int tag = *((int*)bytes); bytes += sizeof(int);
|
||||
|
||||
vimmenu_T *menu = (vimmenu_T*)tag;
|
||||
// TODO! Make sure 'menu' is a valid menu pointer!
|
||||
if (menu) {
|
||||
gui_menu_cb(menu);
|
||||
NSDictionary *attrs = [NSDictionary dictionaryWithData:data];
|
||||
if (attrs) {
|
||||
NSArray *desc = [attrs objectForKey:@"descriptor"];
|
||||
vimmenu_T *menu = menu_for_descriptor(desc);
|
||||
if (menu)
|
||||
gui_menu_cb(menu);
|
||||
}
|
||||
} else if (ToggleToolbarMsgID == msgid) {
|
||||
[self handleToggleToolbar];
|
||||
@@ -2467,22 +2381,6 @@ static int eventModifierFlagsToVimModMask(int modifierFlags)
|
||||
return modMask;
|
||||
}
|
||||
|
||||
static int vimModMaskToEventModifierFlags(int mods)
|
||||
{
|
||||
int flags = 0;
|
||||
|
||||
if (mods & MOD_MASK_SHIFT)
|
||||
flags |= NSShiftKeyMask;
|
||||
if (mods & MOD_MASK_CTRL)
|
||||
flags |= NSControlKeyMask;
|
||||
if (mods & MOD_MASK_ALT)
|
||||
flags |= NSAlternateKeyMask;
|
||||
if (mods & MOD_MASK_CMD)
|
||||
flags |= NSCommandKeyMask;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static int eventModifierFlagsToVimMouseModMask(int modifierFlags)
|
||||
{
|
||||
int modMask = 0;
|
||||
@@ -2504,68 +2402,3 @@ static int eventButtonNumberToVimMouseButton(int buttonNumber)
|
||||
return (buttonNumber >= 0 && buttonNumber < 3)
|
||||
? mouseButton[buttonNumber] : -1;
|
||||
}
|
||||
|
||||
static int specialKeyToNSKey(int key)
|
||||
{
|
||||
if (!IS_SPECIAL(key))
|
||||
return key;
|
||||
|
||||
static struct {
|
||||
int special;
|
||||
int nskey;
|
||||
} sp2ns[] = {
|
||||
{ K_UP, NSUpArrowFunctionKey },
|
||||
{ K_DOWN, NSDownArrowFunctionKey },
|
||||
{ K_LEFT, NSLeftArrowFunctionKey },
|
||||
{ K_RIGHT, NSRightArrowFunctionKey },
|
||||
{ K_F1, NSF1FunctionKey },
|
||||
{ K_F2, NSF2FunctionKey },
|
||||
{ K_F3, NSF3FunctionKey },
|
||||
{ K_F4, NSF4FunctionKey },
|
||||
{ K_F5, NSF5FunctionKey },
|
||||
{ K_F6, NSF6FunctionKey },
|
||||
{ K_F7, NSF7FunctionKey },
|
||||
{ K_F8, NSF8FunctionKey },
|
||||
{ K_F9, NSF9FunctionKey },
|
||||
{ K_F10, NSF10FunctionKey },
|
||||
{ K_F11, NSF11FunctionKey },
|
||||
{ K_F12, NSF12FunctionKey },
|
||||
{ K_F13, NSF13FunctionKey },
|
||||
{ K_F14, NSF14FunctionKey },
|
||||
{ K_F15, NSF15FunctionKey },
|
||||
{ K_F16, NSF16FunctionKey },
|
||||
{ K_F17, NSF17FunctionKey },
|
||||
{ K_F18, NSF18FunctionKey },
|
||||
{ K_F19, NSF19FunctionKey },
|
||||
{ K_F20, NSF20FunctionKey },
|
||||
{ K_F21, NSF21FunctionKey },
|
||||
{ K_F22, NSF22FunctionKey },
|
||||
{ K_F23, NSF23FunctionKey },
|
||||
{ K_F24, NSF24FunctionKey },
|
||||
{ K_F25, NSF25FunctionKey },
|
||||
{ K_F26, NSF26FunctionKey },
|
||||
{ K_F27, NSF27FunctionKey },
|
||||
{ K_F28, NSF28FunctionKey },
|
||||
{ K_F29, NSF29FunctionKey },
|
||||
{ K_F30, NSF30FunctionKey },
|
||||
{ K_F31, NSF31FunctionKey },
|
||||
{ K_F32, NSF32FunctionKey },
|
||||
{ K_F33, NSF33FunctionKey },
|
||||
{ K_F34, NSF34FunctionKey },
|
||||
{ K_F35, NSF35FunctionKey },
|
||||
{ K_DEL, NSBackspaceCharacter },
|
||||
{ K_BS, NSDeleteCharacter },
|
||||
{ K_HOME, NSHomeFunctionKey },
|
||||
{ K_END, NSEndFunctionKey },
|
||||
{ K_PAGEUP, NSPageUpFunctionKey },
|
||||
{ K_PAGEDOWN, NSPageDownFunctionKey }
|
||||
};
|
||||
|
||||
int i;
|
||||
for (i = 0; i < sizeof(sp2ns)/sizeof(sp2ns[0]); ++i) {
|
||||
if (sp2ns[i].special == key)
|
||||
return sp2ns[i].nskey;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ static int numFullscreenWindows = 0;
|
||||
int fuRows = currRows, fuColumns = currColumns;
|
||||
|
||||
int maxRows, maxColumns;
|
||||
NSSize size = [[self screen] frame].size;
|
||||
NSSize size = [[self screen] visibleFrame].size;
|
||||
[view constrainRows:&maxRows columns:&maxColumns toSize:size];
|
||||
|
||||
// Store current pre-fu vim size
|
||||
@@ -298,6 +298,15 @@ static int numFullscreenWindows = 0;
|
||||
[super performClose:sender];
|
||||
}
|
||||
|
||||
- (BOOL)validateMenuItem:(NSMenuItem *)item
|
||||
{
|
||||
if ([item action] == @selector(vimMenuItemAction:)
|
||||
|| [item action] == @selector(performClose:))
|
||||
return [item tag];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end // MMFullscreenWindow
|
||||
|
||||
|
||||
|
||||
@@ -258,6 +258,16 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
|
||||
|| col+cells > maxColumns || !string || !(fg && bg && sp))
|
||||
return;
|
||||
|
||||
BOOL hasControlChars = [string rangeOfCharacterFromSet:
|
||||
[NSCharacterSet controlCharacterSet]].location != NSNotFound;
|
||||
if (hasControlChars) {
|
||||
// HACK! If a string for some reason contains control characters, then
|
||||
// draw blanks instead (otherwise charRangeForRow::: fails).
|
||||
NSRange subRange = { 0, cells };
|
||||
flags &= ~DRAW_WIDE;
|
||||
string = [[emptyRowString string] substringWithRange:subRange];
|
||||
}
|
||||
|
||||
// Find range of characters in text storage to replace.
|
||||
int acol = col;
|
||||
int acells = cells;
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
@interface MMTextView : NSTextView {
|
||||
BOOL shouldDrawInsertionPoint;
|
||||
NSEvent *lastMouseDownEvent;
|
||||
NSTrackingRectTag trackingRectTag;
|
||||
BOOL isDragging;
|
||||
BOOL isAutoscrolling;
|
||||
@@ -34,7 +33,6 @@
|
||||
|
||||
- (id)initWithFrame:(NSRect)frame;
|
||||
|
||||
- (NSEvent *)lastMouseDownEvent;
|
||||
- (void)setShouldDrawInsertionPoint:(BOOL)on;
|
||||
- (void)setPreEditRow:(int)row column:(int)col;
|
||||
- (void)drawInsertionPointAtRow:(int)row column:(int)col shape:(int)shape
|
||||
|
||||
+38
-20
@@ -22,6 +22,7 @@
|
||||
#import "MMWindowController.h"
|
||||
#import "MMVimController.h"
|
||||
#import "MMTypesetter.h"
|
||||
#import "MMAppController.h"
|
||||
#import "MacVim.h"
|
||||
|
||||
|
||||
@@ -56,6 +57,7 @@ enum {
|
||||
- (void)startDragTimerWithInterval:(NSTimeInterval)t;
|
||||
- (void)dragTimerFired:(NSTimer *)timer;
|
||||
- (void)sendKeyDown:(const char *)chars length:(int)len modifiers:(int)flags;
|
||||
- (void)hideMouseCursor;
|
||||
@end
|
||||
|
||||
|
||||
@@ -128,15 +130,9 @@ enum {
|
||||
markedTextField = nil;
|
||||
}
|
||||
|
||||
[lastMouseDownEvent release]; lastMouseDownEvent = nil;
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSEvent *)lastMouseDownEvent
|
||||
{
|
||||
return lastMouseDownEvent;
|
||||
}
|
||||
|
||||
- (BOOL)shouldDrawInsertionPoint
|
||||
{
|
||||
// NOTE: The insertion point is drawn manually in drawRect:. It would be
|
||||
@@ -469,7 +465,11 @@ enum {
|
||||
ipRect.origin.y += ipRect.size.height - frac;
|
||||
ipRect.size.height = frac;
|
||||
} else if (MMInsertionPointVertical == insertionPointShape) {
|
||||
int frac = ([ts cellSize].width* insertionPointFraction + 99)/100;
|
||||
int frac = ([ts cellSize].width * insertionPointFraction + 99)/100;
|
||||
ipRect.size.width = frac;
|
||||
} else if (MMInsertionPointVerticalRight == insertionPointShape) {
|
||||
int frac = ([ts cellSize].width * insertionPointFraction + 99)/100;
|
||||
ipRect.origin.x += ipRect.size.width - frac;
|
||||
ipRect.size.width = frac;
|
||||
}
|
||||
|
||||
@@ -567,8 +567,7 @@ enum {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Support 'mousehide' (check p_mh)
|
||||
[NSCursor setHiddenUntilMouseMoves:YES];
|
||||
[self hideMouseCursor];
|
||||
|
||||
// NOTE: 'string' is either an NSString or an NSAttributedString. Since we
|
||||
// do not support attributes, simply pass the corresponding NSString in the
|
||||
@@ -647,13 +646,13 @@ enum {
|
||||
if ([[NSApp mainMenu] performKeyEquivalent:event])
|
||||
return YES;
|
||||
|
||||
// HACK! KeyCode 50 represent the key which switches between windows
|
||||
// within an application (like Cmd+Tab is used to switch between
|
||||
// applications). Return NO here, else the window switching does not work.
|
||||
//
|
||||
// Will this hack work for all languages / keyboard layouts?
|
||||
if ([event keyCode] == 50)
|
||||
return NO;
|
||||
// HACK! Give the default main menu a chance to handle the key down event.
|
||||
// This is to ensure that the standard mappings (which are in the default
|
||||
// main menu) are always available, also when the default Vim menus are
|
||||
// used (these do not set any key equivalents!).
|
||||
if ([[[MMAppController sharedInstance] defaultMainMenu]
|
||||
performKeyEquivalent:event])
|
||||
return YES;
|
||||
|
||||
// HACK! On Leopard Ctrl-key events end up here instead of keyDown:.
|
||||
if (flags & NSControlKeyMask) {
|
||||
@@ -824,8 +823,6 @@ enum {
|
||||
if (![self convertPoint:pt toRow:&row column:&col])
|
||||
return;
|
||||
|
||||
lastMouseDownEvent = [event copy];
|
||||
|
||||
int button = [event buttonNumber];
|
||||
int flags = [event modifierFlags];
|
||||
int count = [event clickCount];
|
||||
@@ -1156,6 +1153,18 @@ enum {
|
||||
[[self windowController] vimMenuItemAction:sender];
|
||||
}
|
||||
|
||||
- (BOOL)validateMenuItem:(NSMenuItem *)item
|
||||
{
|
||||
if ([item action] == @selector(cut:)
|
||||
|| [item action] == @selector(copy:)
|
||||
|| [item action] == @selector(paste:)
|
||||
|| [item action] == @selector(undo:)
|
||||
|| [item action] == @selector(redo:)
|
||||
|| [item action] == @selector(selectAll:))
|
||||
return [item tag];
|
||||
|
||||
return YES;
|
||||
}
|
||||
@end // MMTextView
|
||||
|
||||
|
||||
@@ -1368,12 +1377,21 @@ enum {
|
||||
[data appendBytes:&len length:sizeof(int)];
|
||||
[data appendBytes:chars length:len];
|
||||
|
||||
// TODO: Support 'mousehide' (check p_mh)
|
||||
[NSCursor setHiddenUntilMouseMoves:YES];
|
||||
[self hideMouseCursor];
|
||||
|
||||
//NSLog(@"%s len=%d chars=0x%x", _cmd, len, chars[0]);
|
||||
[[self vimController] sendMessage:KeyDownMsgID data:data];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)hideMouseCursor
|
||||
{
|
||||
// Check 'mousehide' option
|
||||
id mh = [[[self vimController] vimState] objectForKey:@"p_mh"];
|
||||
if (mh && ![mh boolValue])
|
||||
[NSCursor setHiddenUntilMouseMoves:NO];
|
||||
else
|
||||
[NSCursor setHiddenUntilMouseMoves:YES];
|
||||
}
|
||||
|
||||
@end // MMTextView (Private)
|
||||
|
||||
@@ -27,9 +27,8 @@
|
||||
id backendProxy;
|
||||
BOOL inProcessCommandQueue;
|
||||
NSMutableArray *sendQueue;
|
||||
NSMutableArray *mainMenuItems;
|
||||
NSMenu *mainMenu;
|
||||
NSMutableArray *popupMenuItems;
|
||||
BOOL shouldUpdateMainMenu;
|
||||
NSToolbar *toolbar;
|
||||
NSMutableDictionary *toolbarItemDict;
|
||||
int pid;
|
||||
@@ -39,20 +38,17 @@
|
||||
int resendMsgid;
|
||||
NSData *resendData;
|
||||
#endif
|
||||
NSMenu *lastMenuSearched;
|
||||
NSMenuItem *recentFilesMenuItem;
|
||||
NSMenuItem *recentFilesDummy;
|
||||
NSDictionary *vimState;
|
||||
}
|
||||
|
||||
- (id)initWithBackend:(id)backend pid:(int)processIdentifier
|
||||
recentFiles:(NSMenuItem*)menu;
|
||||
- (id)initWithBackend:(id)backend pid:(int)processIdentifier;
|
||||
- (id)backendProxy;
|
||||
- (int)pid;
|
||||
- (void)setServerName:(NSString *)name;
|
||||
- (NSString *)serverName;
|
||||
- (MMWindowController *)windowController;
|
||||
- (NSDictionary *)vimState;
|
||||
- (NSMenu *)mainMenu;
|
||||
- (void)cleanup;
|
||||
- (void)dropFiles:(NSArray *)filenames forceOpen:(BOOL)force;
|
||||
- (void)dropString:(NSString *)string;
|
||||
@@ -63,5 +59,4 @@
|
||||
timeout:(NSTimeInterval)timeout;
|
||||
- (void)addVimInput:(NSString *)string;
|
||||
- (NSString *)evaluateVimExpression:(NSString *)expr;
|
||||
- (void)updateMainMenu;
|
||||
@end
|
||||
|
||||
+362
-370
@@ -61,28 +61,39 @@ static NSTimeInterval MMResendInterval = 0.5;
|
||||
- (void)savePanelDidEnd:(NSSavePanel *)panel code:(int)code
|
||||
context:(void *)context;
|
||||
- (void)alertDidEnd:(MMAlert *)alert code:(int)code context:(void *)context;
|
||||
- (NSMenuItem *)recurseMenuItemForTag:(int)tag rootMenu:(NSMenu *)root;
|
||||
- (NSMenuItem *)menuItemForTag:(int)tag;
|
||||
- (NSMenu *)menuForTag:(int)tag;
|
||||
- (NSMenuItem *)menuItemForDescriptor:(NSArray *)desc;
|
||||
- (NSMenu *)parentMenuForDescriptor:(NSArray *)desc;
|
||||
- (NSMenu *)topLevelMenuForTitle:(NSString *)title;
|
||||
- (void)addMenuWithTag:(int)tag parent:(int)parentTag title:(NSString *)title
|
||||
atIndex:(int)idx;
|
||||
- (void)addMenuItemWithTag:(int)tag parent:(NSMenu *)parent
|
||||
title:(NSString *)title tip:(NSString *)tip
|
||||
keyEquivalent:(int)key modifiers:(int)mask
|
||||
action:(NSString *)action isAlternate:(int)isAlt
|
||||
atIndex:(int)idx;
|
||||
- (NSToolbarItem *)toolbarItemForTag:(int)tag index:(int *)index;
|
||||
- (void)addToolbarItemToDictionaryWithTag:(int)tag label:(NSString *)title
|
||||
- (void)addMenuWithDescriptor:(NSArray *)desc atIndex:(int)index;
|
||||
- (void)addMenuItemWithDescriptor:(NSArray *)desc
|
||||
atIndex:(int)index
|
||||
tip:(NSString *)tip
|
||||
icon:(NSString *)icon
|
||||
keyEquivalent:(NSString *)keyEquivalent
|
||||
modifierMask:(int)modifierMask
|
||||
action:(NSString *)action
|
||||
isAlternate:(BOOL)isAlternate;
|
||||
- (void)removeMenuItemWithDescriptor:(NSArray *)desc;
|
||||
- (void)enableMenuItemWithDescriptor:(NSArray *)desc state:(BOOL)on;
|
||||
- (void)addToolbarItemToDictionaryWithLabel:(NSString *)title
|
||||
toolTip:(NSString *)tip icon:(NSString *)icon;
|
||||
- (void)addToolbarItemWithTag:(int)tag label:(NSString *)label
|
||||
- (void)addToolbarItemWithLabel:(NSString *)label
|
||||
tip:(NSString *)tip icon:(NSString *)icon
|
||||
atIndex:(int)idx;
|
||||
- (void)popupMenuWithDescriptor:(NSArray *)desc
|
||||
atRow:(NSNumber *)row
|
||||
column:(NSNumber *)col;
|
||||
- (void)connectionDidDie:(NSNotification *)notification;
|
||||
#if MM_RESEND_LAST_FAILURE
|
||||
- (void)resendTimerFired:(NSTimer *)timer;
|
||||
#endif
|
||||
- (void)replaceMenuItem:(NSMenuItem*)old with:(NSMenuItem*)new;
|
||||
@end
|
||||
|
||||
|
||||
@interface NSToolbar (MMExtras)
|
||||
- (int)indexOfItemWithItemIdentifier:(NSString *)identifier;
|
||||
- (NSToolbarItem *)itemAtIndex:(int)idx;
|
||||
- (NSToolbarItem *)itemWithItemIdentifier:(NSString *)identifier;
|
||||
@end
|
||||
|
||||
|
||||
@@ -91,17 +102,12 @@ static NSTimeInterval MMResendInterval = 0.5;
|
||||
@implementation MMVimController
|
||||
|
||||
- (id)initWithBackend:(id)backend pid:(int)processIdentifier
|
||||
recentFiles:(NSMenuItem*)menu;
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
|
||||
recentFilesMenuItem = [menu retain];
|
||||
|
||||
windowController =
|
||||
[[MMWindowController alloc] initWithVimController:self];
|
||||
backendProxy = [backend retain];
|
||||
sendQueue = [NSMutableArray new];
|
||||
mainMenuItems = [[NSMutableArray alloc] init];
|
||||
popupMenuItems = [[NSMutableArray alloc] init];
|
||||
toolbarItemDict = [[NSMutableDictionary alloc] init];
|
||||
pid = processIdentifier;
|
||||
@@ -116,6 +122,25 @@ static NSTimeInterval MMResendInterval = 0.5;
|
||||
selector:@selector(connectionDidDie:)
|
||||
name:NSConnectionDidDieNotification object:connection];
|
||||
|
||||
// Set up a main menu with only a "MacVim" menu (copied from a template
|
||||
// which itself is set up in MainMenu.nib). The main menu is populated
|
||||
// by Vim later on.
|
||||
mainMenu = [[NSMenu alloc] initWithTitle:@"MainMenu"];
|
||||
NSMenuItem *appMenuItem = [[MMAppController sharedInstance]
|
||||
appMenuItemTemplate];
|
||||
appMenuItem = [[appMenuItem copy] autorelease];
|
||||
|
||||
// Note: If the title of the application menu is anything but what
|
||||
// CFBundleName says then the application menu will not be typeset in
|
||||
// boldface for some reason. (It should already be set when we copy
|
||||
// from the default main menu, but this is not the case for some
|
||||
// reason.)
|
||||
NSString *appName = [[NSBundle mainBundle]
|
||||
objectForInfoDictionaryKey:@"CFBundleName"];
|
||||
[appMenuItem setTitle:appName];
|
||||
|
||||
[mainMenu addItem:appMenuItem];
|
||||
|
||||
isInitialized = YES;
|
||||
}
|
||||
|
||||
@@ -138,11 +163,10 @@ static NSTimeInterval MMResendInterval = 0.5;
|
||||
[toolbarItemDict release]; toolbarItemDict = nil;
|
||||
[toolbar release]; toolbar = nil;
|
||||
[popupMenuItems release]; popupMenuItems = nil;
|
||||
[mainMenuItems release]; mainMenuItems = nil;
|
||||
[windowController release]; windowController = nil;
|
||||
|
||||
[recentFilesMenuItem release]; recentFilesMenuItem = nil;
|
||||
[recentFilesDummy release]; recentFilesDummy = nil;
|
||||
[vimState release]; vimState = nil;
|
||||
[mainMenu release]; mainMenu = nil;
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
@@ -157,6 +181,11 @@ static NSTimeInterval MMResendInterval = 0.5;
|
||||
return vimState;
|
||||
}
|
||||
|
||||
- (NSMenu *)mainMenu
|
||||
{
|
||||
return mainMenu;
|
||||
}
|
||||
|
||||
- (void)setServerName:(NSString *)name
|
||||
{
|
||||
if (name != serverName) {
|
||||
@@ -497,33 +526,33 @@ static NSTimeInterval MMResendInterval = 0.5;
|
||||
{
|
||||
if (!isInitialized) return;
|
||||
|
||||
unsigned i, count = [queue count];
|
||||
if (count % 2) {
|
||||
NSLog(@"WARNING: Uneven number of components (%d) in flush queue "
|
||||
"message; ignoring this message.", count);
|
||||
return;
|
||||
@try {
|
||||
unsigned i, count = [queue count];
|
||||
if (count % 2) {
|
||||
NSLog(@"WARNING: Uneven number of components (%d) in flush queue "
|
||||
"message; ignoring this message.", count);
|
||||
return;
|
||||
}
|
||||
|
||||
inProcessCommandQueue = YES;
|
||||
|
||||
//NSLog(@"======== %s BEGIN ========", _cmd);
|
||||
for (i = 0; i < count; i += 2) {
|
||||
NSData *value = [queue objectAtIndex:i];
|
||||
NSData *data = [queue objectAtIndex:i+1];
|
||||
|
||||
int msgid = *((int*)[value bytes]);
|
||||
//NSLog(@"%s%s", _cmd, MessageStrings[msgid]);
|
||||
|
||||
[self handleMessage:msgid data:data];
|
||||
}
|
||||
//NSLog(@"======== %s END ========", _cmd);
|
||||
}
|
||||
|
||||
inProcessCommandQueue = YES;
|
||||
|
||||
//NSLog(@"======== %s BEGIN ========", _cmd);
|
||||
for (i = 0; i < count; i += 2) {
|
||||
NSData *value = [queue objectAtIndex:i];
|
||||
NSData *data = [queue objectAtIndex:i+1];
|
||||
|
||||
int msgid = *((int*)[value bytes]);
|
||||
//NSLog(@"%s%s", _cmd, MessageStrings[msgid]);
|
||||
|
||||
[self handleMessage:msgid data:data];
|
||||
}
|
||||
//NSLog(@"======== %s END ========", _cmd);
|
||||
|
||||
if (shouldUpdateMainMenu) {
|
||||
[self updateMainMenu];
|
||||
@catch (NSException *e) {
|
||||
NSLog(@"Exception caught whilst processing command queue: %@", e);
|
||||
}
|
||||
|
||||
[windowController processCommandQueueDidFinish];
|
||||
|
||||
inProcessCommandQueue = NO;
|
||||
|
||||
if ([sendQueue count] > 0) {
|
||||
@@ -561,53 +590,6 @@ static NSTimeInterval MMResendInterval = 0.5;
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)updateMainMenu
|
||||
{
|
||||
NSMenu *mainMenu = [NSApp mainMenu];
|
||||
|
||||
// Stop NSApp from updating the Window menu.
|
||||
[NSApp setWindowsMenu:nil];
|
||||
|
||||
// Remove all menus from main menu (except the MacVim menu).
|
||||
int i, count = [mainMenu numberOfItems];
|
||||
for (i = count-1; i > 0; --i) {
|
||||
[mainMenu removeItemAtIndex:i];
|
||||
}
|
||||
|
||||
// Add menus from 'mainMenuItems' to main menu.
|
||||
count = [mainMenuItems count];
|
||||
for (i = 0; i < count; ++i) {
|
||||
[mainMenu addItem:[mainMenuItems objectAtIndex:i]];
|
||||
}
|
||||
|
||||
// Set the new Window menu.
|
||||
// TODO! Need to look for 'Window' in all localized languages.
|
||||
NSMenu *windowMenu = [[mainMenu itemWithTitle:@"Window"] submenu];
|
||||
if (windowMenu) {
|
||||
// Remove all AppKit owned menu items (tag == 0); they will be added
|
||||
// again when setWindowsMenu: is called.
|
||||
count = [windowMenu numberOfItems];
|
||||
for (i = count-1; i >= 0; --i) {
|
||||
NSMenuItem *item = [windowMenu itemAtIndex:i];
|
||||
if (![item tag]) {
|
||||
[windowMenu removeItem:item];
|
||||
}
|
||||
}
|
||||
|
||||
[NSApp setWindowsMenu:windowMenu];
|
||||
}
|
||||
|
||||
// Replace real Recent Files menu in the old menu with the dummy, then
|
||||
// remove dummy from new menu and put Recent Files menu there
|
||||
NSMenuItem *oldItem = (NSMenuItem*)[recentFilesMenuItem representedObject];
|
||||
if (oldItem)
|
||||
[self replaceMenuItem:recentFilesMenuItem with:oldItem];
|
||||
[recentFilesMenuItem setRepresentedObject:recentFilesDummy];
|
||||
[self replaceMenuItem:recentFilesDummy with:recentFilesMenuItem];
|
||||
|
||||
shouldUpdateMainMenu = NO;
|
||||
}
|
||||
|
||||
@end // MMVimController
|
||||
|
||||
|
||||
@@ -654,127 +636,26 @@ static NSTimeInterval MMResendInterval = 0.5;
|
||||
|
||||
[string release];
|
||||
} else if (AddMenuMsgID == msgid) {
|
||||
NSString *title = nil;
|
||||
const void *bytes = [data bytes];
|
||||
int tag = *((int*)bytes); bytes += sizeof(int);
|
||||
int parentTag = *((int*)bytes); bytes += sizeof(int);
|
||||
int len = *((int*)bytes); bytes += sizeof(int);
|
||||
if (len > 0) {
|
||||
title = [[NSString alloc] initWithBytes:(void*)bytes length:len
|
||||
encoding:NSUTF8StringEncoding];
|
||||
bytes += len;
|
||||
}
|
||||
int idx = *((int*)bytes); bytes += sizeof(int);
|
||||
|
||||
if (MenuToolbarType == parentTag) {
|
||||
if (!toolbar) {
|
||||
// NOTE! Each toolbar must have a unique identifier, else each
|
||||
// window will have the same toolbar.
|
||||
NSString *ident = [NSString stringWithFormat:@"%d.%d",
|
||||
(int)self, tag];
|
||||
toolbar = [[NSToolbar alloc] initWithIdentifier:ident];
|
||||
|
||||
[toolbar setShowsBaselineSeparator:NO];
|
||||
[toolbar setDelegate:self];
|
||||
[toolbar setDisplayMode:NSToolbarDisplayModeIconOnly];
|
||||
[toolbar setSizeMode:NSToolbarSizeModeSmall];
|
||||
|
||||
[windowController setToolbar:toolbar];
|
||||
}
|
||||
} else if (title) {
|
||||
[self addMenuWithTag:tag parent:parentTag title:title atIndex:idx];
|
||||
}
|
||||
|
||||
[title release];
|
||||
NSDictionary *attrs = [NSDictionary dictionaryWithData:data];
|
||||
[self addMenuWithDescriptor:[attrs objectForKey:@"descriptor"]
|
||||
atIndex:[[attrs objectForKey:@"index"] intValue]];
|
||||
} else if (AddMenuItemMsgID == msgid) {
|
||||
NSString *title = nil, *tip = nil, *icon = nil, *action = nil;
|
||||
const void *bytes = [data bytes];
|
||||
int tag = *((int*)bytes); bytes += sizeof(int);
|
||||
int parentTag = *((int*)bytes); bytes += sizeof(int);
|
||||
int namelen = *((int*)bytes); bytes += sizeof(int);
|
||||
if (namelen > 0) {
|
||||
title = [[NSString alloc] initWithBytes:(void*)bytes length:namelen
|
||||
encoding:NSUTF8StringEncoding];
|
||||
bytes += namelen;
|
||||
}
|
||||
int tiplen = *((int*)bytes); bytes += sizeof(int);
|
||||
if (tiplen > 0) {
|
||||
tip = [[NSString alloc] initWithBytes:(void*)bytes length:tiplen
|
||||
encoding:NSUTF8StringEncoding];
|
||||
bytes += tiplen;
|
||||
}
|
||||
int iconlen = *((int*)bytes); bytes += sizeof(int);
|
||||
if (iconlen > 0) {
|
||||
icon = [[NSString alloc] initWithBytes:(void*)bytes length:iconlen
|
||||
encoding:NSUTF8StringEncoding];
|
||||
bytes += iconlen;
|
||||
}
|
||||
int actionlen = *((int*)bytes); bytes += sizeof(int);
|
||||
if (actionlen > 0) {
|
||||
action = [[NSString alloc] initWithBytes:(void*)bytes
|
||||
length:actionlen
|
||||
encoding:NSUTF8StringEncoding];
|
||||
bytes += actionlen;
|
||||
}
|
||||
int idx = *((int*)bytes); bytes += sizeof(int);
|
||||
if (idx < 0) idx = 0;
|
||||
int key = *((int*)bytes); bytes += sizeof(int);
|
||||
int mask = *((int*)bytes); bytes += sizeof(int);
|
||||
int isalt = *((int*)bytes); bytes += sizeof(int);
|
||||
|
||||
NSString *ident = [NSString stringWithFormat:@"%d.%d",
|
||||
(int)self, parentTag];
|
||||
if (toolbar && [[toolbar identifier] isEqual:ident]) {
|
||||
[self addToolbarItemWithTag:tag label:title tip:tip icon:icon
|
||||
atIndex:idx];
|
||||
} else {
|
||||
NSMenu *parent = [self menuForTag:parentTag];
|
||||
[self addMenuItemWithTag:tag parent:parent title:title tip:tip
|
||||
keyEquivalent:key modifiers:mask action:action
|
||||
isAlternate:isalt atIndex:idx];
|
||||
}
|
||||
|
||||
[title release];
|
||||
[tip release];
|
||||
[icon release];
|
||||
[action release];
|
||||
NSDictionary *attrs = [NSDictionary dictionaryWithData:data];
|
||||
[self addMenuItemWithDescriptor:[attrs objectForKey:@"descriptor"]
|
||||
atIndex:[[attrs objectForKey:@"index"] intValue]
|
||||
tip:[attrs objectForKey:@"tip"]
|
||||
icon:[attrs objectForKey:@"icon"]
|
||||
keyEquivalent:[attrs objectForKey:@"keyEquivalent"]
|
||||
modifierMask:[[attrs objectForKey:@"modifierMask"] intValue]
|
||||
action:[attrs objectForKey:@"action"]
|
||||
isAlternate:[[attrs objectForKey:@"isAlternate"] boolValue]];
|
||||
} else if (RemoveMenuItemMsgID == msgid) {
|
||||
const void *bytes = [data bytes];
|
||||
int tag = *((int*)bytes); bytes += sizeof(int);
|
||||
|
||||
id item;
|
||||
int idx;
|
||||
if ((item = [self toolbarItemForTag:tag index:&idx])) {
|
||||
[toolbar removeItemAtIndex:idx];
|
||||
} else if ((item = [self menuItemForTag:tag])) {
|
||||
[item retain];
|
||||
|
||||
if ([item menu] == [NSApp mainMenu] || ![item menu]) {
|
||||
// NOTE: To be on the safe side we try to remove the item from
|
||||
// both arrays (it is ok to call removeObject: even if an array
|
||||
// does not contain the object to remove).
|
||||
[mainMenuItems removeObject:item];
|
||||
[popupMenuItems removeObject:item];
|
||||
}
|
||||
|
||||
if ([item menu])
|
||||
[[item menu] removeItem:item];
|
||||
|
||||
[item release];
|
||||
}
|
||||
|
||||
// Reset cached menu, just to be on the safe side.
|
||||
lastMenuSearched = nil;
|
||||
NSDictionary *attrs = [NSDictionary dictionaryWithData:data];
|
||||
[self removeMenuItemWithDescriptor:[attrs objectForKey:@"descriptor"]];
|
||||
} else if (EnableMenuItemMsgID == msgid) {
|
||||
const void *bytes = [data bytes];
|
||||
int tag = *((int*)bytes); bytes += sizeof(int);
|
||||
int state = *((int*)bytes); bytes += sizeof(int);
|
||||
|
||||
id item = [self toolbarItemForTag:tag index:NULL];
|
||||
if (!item)
|
||||
item = [self menuItemForTag:tag];
|
||||
|
||||
[item setEnabled:state];
|
||||
NSDictionary *attrs = [NSDictionary dictionaryWithData:data];
|
||||
[self enableMenuItemWithDescriptor:[attrs objectForKey:@"descriptor"]
|
||||
state:[[attrs objectForKey:@"enable"] boolValue]];
|
||||
} else if (ShowToolbarMsgID == msgid) {
|
||||
const void *bytes = [data bytes];
|
||||
int enable = *((int*)bytes); bytes += sizeof(int);
|
||||
@@ -873,23 +754,10 @@ static NSTimeInterval MMResendInterval = 0.5;
|
||||
|
||||
[actionName release];
|
||||
} else if (ShowPopupMenuMsgID == msgid) {
|
||||
const void *bytes = [data bytes];
|
||||
int row = *((int*)bytes); bytes += sizeof(int);
|
||||
int col = *((int*)bytes); bytes += sizeof(int);
|
||||
int len = *((int*)bytes); bytes += sizeof(int);
|
||||
NSString *title = [[NSString alloc]
|
||||
initWithBytes:(void*)bytes length:len
|
||||
encoding:NSUTF8StringEncoding];
|
||||
|
||||
NSMenu *menu = [self topLevelMenuForTitle:title];
|
||||
if (menu) {
|
||||
[windowController popupMenu:menu atRow:row column:col];
|
||||
} else {
|
||||
NSLog(@"WARNING: Cannot popup menu with title %@; no such menu.",
|
||||
title);
|
||||
}
|
||||
|
||||
[title release];
|
||||
NSDictionary *attrs = [NSDictionary dictionaryWithData:data];
|
||||
[self popupMenuWithDescriptor:[attrs objectForKey:@"descriptor"]
|
||||
atRow:[attrs objectForKey:@"row"]
|
||||
column:[attrs objectForKey:@"column"]];
|
||||
} else if (SetMouseShapeMsgID == msgid) {
|
||||
const void *bytes = [data bytes];
|
||||
int shape = *((int*)bytes); bytes += sizeof(int);
|
||||
@@ -980,74 +848,61 @@ static NSTimeInterval MMResendInterval = 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSMenuItem *)recurseMenuItemForTag:(int)tag rootMenu:(NSMenu *)root
|
||||
- (NSMenuItem *)menuItemForDescriptor:(NSArray *)desc
|
||||
{
|
||||
if (root) {
|
||||
NSMenuItem *item = [root itemWithTag:tag];
|
||||
if (item) {
|
||||
lastMenuSearched = root;
|
||||
return item;
|
||||
}
|
||||
if (!(desc && [desc count] > 0)) return nil;
|
||||
|
||||
NSArray *items = [root itemArray];
|
||||
unsigned i, count = [items count];
|
||||
for (i = 0; i < count; ++i) {
|
||||
item = [items objectAtIndex:i];
|
||||
if ([item hasSubmenu]) {
|
||||
item = [self recurseMenuItemForTag:tag
|
||||
rootMenu:[item submenu]];
|
||||
if (item) {
|
||||
lastMenuSearched = [item submenu];
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
NSString *rootName = [desc objectAtIndex:0];
|
||||
NSArray *rootItems = [rootName hasPrefix:@"PopUp"] ? popupMenuItems
|
||||
: [mainMenu itemArray];
|
||||
|
||||
NSMenuItem *item = nil;
|
||||
int i, count = [rootItems count];
|
||||
for (i = 0; i < count; ++i) {
|
||||
item = [rootItems objectAtIndex:i];
|
||||
if ([[item title] isEqual:rootName])
|
||||
break;
|
||||
}
|
||||
|
||||
return nil;
|
||||
if (i == count) return nil;
|
||||
|
||||
count = [desc count];
|
||||
for (i = 1; i < count; ++i) {
|
||||
item = [[item submenu] itemWithTitle:[desc objectAtIndex:i]];
|
||||
if (!item) return nil;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
- (NSMenuItem *)menuItemForTag:(int)tag
|
||||
- (NSMenu *)parentMenuForDescriptor:(NSArray *)desc
|
||||
{
|
||||
// First search the same menu that was search last time this method was
|
||||
// called. Since this method is often called for each menu item in a
|
||||
// menu this can significantly improve search times.
|
||||
if (lastMenuSearched) {
|
||||
NSMenuItem *item = [self recurseMenuItemForTag:tag
|
||||
rootMenu:lastMenuSearched];
|
||||
if (item) return item;
|
||||
}
|
||||
if (!(desc && [desc count] > 0)) return nil;
|
||||
|
||||
// Search the main menu.
|
||||
int i, count = [mainMenuItems count];
|
||||
NSString *rootName = [desc objectAtIndex:0];
|
||||
NSArray *rootItems = [rootName hasPrefix:@"PopUp"] ? popupMenuItems
|
||||
: [mainMenu itemArray];
|
||||
|
||||
NSMenu *menu = nil;
|
||||
int i, count = [rootItems count];
|
||||
for (i = 0; i < count; ++i) {
|
||||
NSMenuItem *item = [mainMenuItems objectAtIndex:i];
|
||||
if ([item tag] == tag) return item;
|
||||
item = [self recurseMenuItemForTag:tag rootMenu:[item submenu]];
|
||||
if (item) {
|
||||
lastMenuSearched = [item submenu];
|
||||
return item;
|
||||
NSMenuItem *item = [rootItems objectAtIndex:i];
|
||||
if ([[item title] isEqual:rootName]) {
|
||||
menu = [item submenu];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Search the popup menus.
|
||||
count = [popupMenuItems count];
|
||||
for (i = 0; i < count; ++i) {
|
||||
NSMenuItem *item = [popupMenuItems objectAtIndex:i];
|
||||
if ([item tag] == tag) return item;
|
||||
item = [self recurseMenuItemForTag:tag rootMenu:[item submenu]];
|
||||
if (item) {
|
||||
lastMenuSearched = [item submenu];
|
||||
return item;
|
||||
}
|
||||
if (!menu) return nil;
|
||||
|
||||
count = [desc count] - 1;
|
||||
for (i = 1; i < count; ++i) {
|
||||
NSMenuItem *item = [menu itemWithTitle:[desc objectAtIndex:i]];
|
||||
menu = [item submenu];
|
||||
if (!menu) return nil;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSMenu *)menuForTag:(int)tag
|
||||
{
|
||||
return [[self menuItemForTag:tag] submenu];
|
||||
return menu;
|
||||
}
|
||||
|
||||
- (NSMenu *)topLevelMenuForTitle:(NSString *)title
|
||||
@@ -1061,9 +916,9 @@ static NSTimeInterval MMResendInterval = 0.5;
|
||||
return [item submenu];
|
||||
}
|
||||
|
||||
count = [mainMenuItems count];
|
||||
count = [mainMenu numberOfItems];
|
||||
for (i = 0; i < count; ++i) {
|
||||
NSMenuItem *item = [mainMenuItems objectAtIndex:i];
|
||||
NSMenuItem *item = [mainMenu itemAtIndex:i];
|
||||
if ([title isEqual:[item title]])
|
||||
return [item submenu];
|
||||
}
|
||||
@@ -1071,113 +926,191 @@ static NSTimeInterval MMResendInterval = 0.5;
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)addMenuWithTag:(int)tag parent:(int)parentTag title:(NSString *)title
|
||||
atIndex:(int)idx
|
||||
- (void)addMenuWithDescriptor:(NSArray *)desc atIndex:(int)idx
|
||||
{
|
||||
NSMenu *parent = [self menuForTag:parentTag];
|
||||
if (!(desc && [desc count] > 0 && idx >= 0)) return;
|
||||
|
||||
NSString *rootName = [desc objectAtIndex:0];
|
||||
if ([rootName isEqual:@"ToolBar"]) {
|
||||
// The toolbar only has one menu, we take this as a hint to create a
|
||||
// toolbar, then we return.
|
||||
if (!toolbar) {
|
||||
// NOTE! Each toolbar must have a unique identifier, else each
|
||||
// window will have the same toolbar.
|
||||
NSString *ident = [NSString stringWithFormat:@"%d", (int)self];
|
||||
toolbar = [[NSToolbar alloc] initWithIdentifier:ident];
|
||||
|
||||
[toolbar setShowsBaselineSeparator:NO];
|
||||
[toolbar setDelegate:self];
|
||||
[toolbar setDisplayMode:NSToolbarDisplayModeIconOnly];
|
||||
[toolbar setSizeMode:NSToolbarSizeModeSmall];
|
||||
|
||||
[windowController setToolbar:toolbar];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// This is either a main menu item or a popup menu item.
|
||||
NSString *title = [desc lastObject];
|
||||
NSMenuItem *item = [[NSMenuItem alloc] init];
|
||||
NSMenu *menu = [[NSMenu alloc] initWithTitle:title];
|
||||
|
||||
[menu setAutoenablesItems:NO];
|
||||
[item setTag:tag];
|
||||
[item setTitle:title];
|
||||
[item setSubmenu:menu];
|
||||
|
||||
if (parent) {
|
||||
NSMenu *parent = [self parentMenuForDescriptor:desc];
|
||||
if (!parent && [rootName hasPrefix:@"PopUp"]) {
|
||||
if ([popupMenuItems count] <= idx) {
|
||||
[popupMenuItems addObject:item];
|
||||
} else {
|
||||
[popupMenuItems insertObject:item atIndex:idx];
|
||||
}
|
||||
} else {
|
||||
// If descriptor has no parent and its not a popup (or toolbar) menu,
|
||||
// then it must belong to main menu.
|
||||
if (!parent) parent = mainMenu;
|
||||
|
||||
if ([parent numberOfItems] <= idx) {
|
||||
[parent addItem:item];
|
||||
} else {
|
||||
[parent insertItem:item atIndex:idx];
|
||||
}
|
||||
} else {
|
||||
NSMutableArray *items = (MenuPopupType == parentTag)
|
||||
? popupMenuItems : mainMenuItems;
|
||||
if ([items count] <= idx) {
|
||||
[items addObject:item];
|
||||
} else {
|
||||
[items insertObject:item atIndex:idx];
|
||||
}
|
||||
|
||||
shouldUpdateMainMenu = (MenuPopupType != parentTag);
|
||||
}
|
||||
|
||||
[item release];
|
||||
[menu release];
|
||||
}
|
||||
|
||||
- (void)addMenuItemWithTag:(int)tag parent:(NSMenu *)parent
|
||||
title:(NSString *)title tip:(NSString *)tip
|
||||
keyEquivalent:(int)key modifiers:(int)mask
|
||||
action:(NSString *)action isAlternate:(int)isAlt
|
||||
atIndex:(int)idx
|
||||
- (void)addMenuItemWithDescriptor:(NSArray *)desc
|
||||
atIndex:(int)idx
|
||||
tip:(NSString *)tip
|
||||
icon:(NSString *)icon
|
||||
keyEquivalent:(NSString *)keyEquivalent
|
||||
modifierMask:(int)modifierMask
|
||||
action:(NSString *)action
|
||||
isAlternate:(BOOL)isAlternate
|
||||
{
|
||||
if (parent) {
|
||||
NSMenuItem *item = nil;
|
||||
if (!title || ([title hasPrefix:@"-"] && [title hasSuffix:@"-"])) {
|
||||
item = [NSMenuItem separatorItem];
|
||||
} else {
|
||||
item = [[[NSMenuItem alloc] init] autorelease];
|
||||
[item setTitle:title];
|
||||
if (!(desc && [desc count] > 1 && idx >= 0)) return;
|
||||
|
||||
if ([action isEqualToString:@"recentFilesDummy:"]) {
|
||||
// Remove the recent files menu item from its current menu
|
||||
// and put it in the current file menu. See -[MMAppController
|
||||
// applicationWillFinishLaunching for more information.
|
||||
//[[recentFilesMenuItem menu] removeItem:recentFilesMenuItem];
|
||||
//item = recentFilesMenuItem;
|
||||
recentFilesDummy = [item retain];
|
||||
NSString *title = [desc lastObject];
|
||||
NSString *rootName = [desc objectAtIndex:0];
|
||||
|
||||
} else {
|
||||
// TODO: Check that 'action' is a valid action (nothing will
|
||||
// happen if it isn't, but it would be nice with a warning).
|
||||
if (action) [item setAction:NSSelectorFromString(action)];
|
||||
else [item setAction:@selector(vimMenuItemAction:)];
|
||||
if (tip) [item setToolTip:tip];
|
||||
if ([rootName isEqual:@"ToolBar"]) {
|
||||
if (toolbar && [desc count] == 2)
|
||||
[self addToolbarItemWithLabel:title tip:tip icon:icon atIndex:idx];
|
||||
return;
|
||||
}
|
||||
|
||||
if (key != 0) {
|
||||
NSString *keyString =
|
||||
[NSString stringWithFormat:@"%C", key];
|
||||
[item setKeyEquivalent:keyString];
|
||||
[item setKeyEquivalentModifierMask:mask];
|
||||
}
|
||||
NSMenu *parent = [self parentMenuForDescriptor:desc];
|
||||
if (!parent) {
|
||||
NSLog(@"WARNING: Menu item '%@' has no parent",
|
||||
[desc componentsJoinedByString:@"->"]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isAlt) [item setAlternate:YES];
|
||||
NSMenuItem *item = nil;
|
||||
if (0 == [title length]
|
||||
|| ([title hasPrefix:@"-"] && [title hasSuffix:@"-"])) {
|
||||
item = [NSMenuItem separatorItem];
|
||||
[item setTitle:title];
|
||||
} else {
|
||||
item = [[[NSMenuItem alloc] init] autorelease];
|
||||
[item setTitle:title];
|
||||
|
||||
// Note: It is possible to set the action to a message that "doesn't
|
||||
// exist" without problems. We take advantage of this when adding
|
||||
// "dummy items" e.g. when dealing with the "Recent Files" menu (in
|
||||
// which case a recentFilesDummy: action is set, although it is never
|
||||
// used).
|
||||
if ([action length] > 0)
|
||||
[item setAction:NSSelectorFromString(action)];
|
||||
else
|
||||
[item setAction:@selector(vimMenuItemAction:)];
|
||||
if ([tip length] > 0) [item setToolTip:tip];
|
||||
if ([keyEquivalent length] > 0) {
|
||||
[item setKeyEquivalent:keyEquivalent];
|
||||
[item setKeyEquivalentModifierMask:modifierMask];
|
||||
}
|
||||
[item setAlternate:isAlternate];
|
||||
|
||||
// The tag is used to indicate whether Vim thinks a menu item should be
|
||||
// enabled or disabled. By default Vim thinks menu items are enabled.
|
||||
[item setTag:1];
|
||||
}
|
||||
|
||||
if ([parent numberOfItems] <= idx) {
|
||||
[parent addItem:item];
|
||||
} else {
|
||||
[parent insertItem:item atIndex:idx];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)removeMenuItemWithDescriptor:(NSArray *)desc
|
||||
{
|
||||
if (!(desc && [desc count] > 0)) return;
|
||||
|
||||
NSString *title = [desc lastObject];
|
||||
NSString *rootName = [desc objectAtIndex:0];
|
||||
if ([rootName isEqual:@"ToolBar"]) {
|
||||
if (toolbar) {
|
||||
if ([desc count] == 1) {
|
||||
[windowController setToolbar:nil];
|
||||
[toolbar release]; toolbar = nil;
|
||||
} else if ([desc count] == 2) {
|
||||
int idx = [toolbar indexOfItemWithItemIdentifier:title];
|
||||
if (idx != NSNotFound)
|
||||
[toolbar removeItemAtIndex:idx];
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE! The tag is used to idenfity which menu items were
|
||||
// added by Vim (tag != 0) and which were added by the AppKit
|
||||
// (tag == 0).
|
||||
[item setTag:tag];
|
||||
NSMenuItem *item = [self menuItemForDescriptor:desc];
|
||||
if (!item) {
|
||||
NSLog(@"Failed to remove menu item, descriptor not found: %@",
|
||||
[desc componentsJoinedByString:@"->"]);
|
||||
return;
|
||||
}
|
||||
|
||||
if ([parent numberOfItems] <= idx) {
|
||||
[parent addItem:item];
|
||||
} else {
|
||||
[parent insertItem:item atIndex:idx];
|
||||
[item retain];
|
||||
|
||||
if ([item menu] == [NSApp mainMenu] || ![item menu]) {
|
||||
// NOTE: To be on the safe side we try to remove the item from
|
||||
// both arrays (it is ok to call removeObject: even if an array
|
||||
// does not contain the object to remove).
|
||||
[popupMenuItems removeObject:item];
|
||||
}
|
||||
|
||||
if ([item menu])
|
||||
[[item menu] removeItem:item];
|
||||
|
||||
[item release];
|
||||
}
|
||||
|
||||
- (void)enableMenuItemWithDescriptor:(NSArray *)desc state:(BOOL)on
|
||||
{
|
||||
if (!(desc && [desc count] > 0)) return;
|
||||
|
||||
/*NSLog(@"%sable item %@", on ? "En" : "Dis",
|
||||
[desc componentsJoinedByString:@"->"]);*/
|
||||
|
||||
NSString *rootName = [desc objectAtIndex:0];
|
||||
if ([rootName isEqual:@"ToolBar"]) {
|
||||
if (toolbar && [desc count] == 2) {
|
||||
NSString *title = [desc lastObject];
|
||||
[[toolbar itemWithItemIdentifier:title] setEnabled:on];
|
||||
}
|
||||
} else {
|
||||
NSLog(@"WARNING: Menu item '%@' (tag=%d) has no parent.", title, tag);
|
||||
// Use tag to set whether item is enabled or disabled instead of
|
||||
// calling setEnabled:. This way the menus can autoenable themselves
|
||||
// but at the same time Vim can set if a menu is enabled whenever it
|
||||
// wants to.
|
||||
[[self menuItemForDescriptor:desc] setTag:on];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSToolbarItem *)toolbarItemForTag:(int)tag index:(int *)index
|
||||
{
|
||||
if (!toolbar) return nil;
|
||||
|
||||
NSArray *items = [toolbar items];
|
||||
int i, count = [items count];
|
||||
for (i = 0; i < count; ++i) {
|
||||
NSToolbarItem *item = [items objectAtIndex:i];
|
||||
if ([item tag] == tag) {
|
||||
if (index) *index = i;
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)addToolbarItemToDictionaryWithTag:(int)tag label:(NSString *)title
|
||||
- (void)addToolbarItemToDictionaryWithLabel:(NSString *)title
|
||||
toolTip:(NSString *)tip icon:(NSString *)icon
|
||||
{
|
||||
// If the item corresponds to a separator then do nothing, since it is
|
||||
@@ -1188,7 +1121,6 @@ static NSTimeInterval MMResendInterval = 0.5;
|
||||
return;
|
||||
|
||||
NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier:title];
|
||||
[item setTag:tag];
|
||||
[item setLabel:title];
|
||||
[item setToolTip:tip];
|
||||
[item setAction:@selector(vimMenuItemAction:)];
|
||||
@@ -1211,7 +1143,7 @@ static NSTimeInterval MMResendInterval = 0.5;
|
||||
[item release];
|
||||
}
|
||||
|
||||
- (void)addToolbarItemWithTag:(int)tag label:(NSString *)label tip:(NSString
|
||||
- (void)addToolbarItemWithLabel:(NSString *)label tip:(NSString
|
||||
*)tip icon:(NSString *)icon atIndex:(int)idx
|
||||
{
|
||||
if (!toolbar) return;
|
||||
@@ -1232,8 +1164,7 @@ static NSTimeInterval MMResendInterval = 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
[self addToolbarItemToDictionaryWithTag:tag label:label toolTip:tip
|
||||
icon:icon];
|
||||
[self addToolbarItemToDictionaryWithLabel:label toolTip:tip icon:icon];
|
||||
|
||||
int maxIdx = [[toolbar items] count];
|
||||
if (maxIdx < idx) idx = maxIdx;
|
||||
@@ -1241,6 +1172,39 @@ static NSTimeInterval MMResendInterval = 0.5;
|
||||
[toolbar insertItemWithItemIdentifier:label atIndex:idx];
|
||||
}
|
||||
|
||||
- (void)popupMenuWithDescriptor:(NSArray *)desc
|
||||
atRow:(NSNumber *)row
|
||||
column:(NSNumber *)col
|
||||
{
|
||||
NSMenu *menu = [[self menuItemForDescriptor:desc] submenu];
|
||||
if (!menu) return;
|
||||
|
||||
id textView = [[windowController vimView] textView];
|
||||
NSPoint pt;
|
||||
if (row && col) {
|
||||
// TODO: Let textView convert (row,col) to NSPoint.
|
||||
int r = [row intValue];
|
||||
int c = [col intValue];
|
||||
NSSize cellSize = [textView cellSize];
|
||||
pt = NSMakePoint((c+1)*cellSize.width, (r+1)*cellSize.height);
|
||||
pt = [textView convertPoint:pt toView:nil];
|
||||
} else {
|
||||
pt = [[windowController window] mouseLocationOutsideOfEventStream];
|
||||
}
|
||||
|
||||
NSEvent *event = [NSEvent mouseEventWithType:NSRightMouseDown
|
||||
location:pt
|
||||
modifierFlags:0
|
||||
timestamp:0
|
||||
windowNumber:[[windowController window] windowNumber]
|
||||
context:nil
|
||||
eventNumber:0
|
||||
clickCount:0
|
||||
pressure:1.0];
|
||||
|
||||
[NSMenu popUpContextMenu:menu withEvent:event forView:textView];
|
||||
}
|
||||
|
||||
- (void)connectionDidDie:(NSNotification *)notification
|
||||
{
|
||||
//NSLog(@"%@ %s%@", [self className], _cmd, notification);
|
||||
@@ -1248,14 +1212,14 @@ static NSTimeInterval MMResendInterval = 0.5;
|
||||
[self cleanup];
|
||||
|
||||
// NOTE! This causes the call to removeVimController: to be delayed.
|
||||
[[NSApp delegate]
|
||||
[[MMAppController sharedInstance]
|
||||
performSelectorOnMainThread:@selector(removeVimController:)
|
||||
withObject:self waitUntilDone:NO];
|
||||
}
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"%@ : isInitialized=%d inProcessCommandQueue=%d mainMenuItems=%@ popupMenuItems=%@ toolbar=%@", [self className], isInitialized, inProcessCommandQueue, mainMenuItems, popupMenuItems, toolbar];
|
||||
return [NSString stringWithFormat:@"%@ : isInitialized=%d inProcessCommandQueue=%d mainMenu=%@ popupMenuItems=%@ toolbar=%@", [self className], isInitialized, inProcessCommandQueue, mainMenu, popupMenuItems, toolbar];
|
||||
}
|
||||
|
||||
#if MM_RESEND_LAST_FAILURE
|
||||
@@ -1278,15 +1242,43 @@ static NSTimeInterval MMResendInterval = 0.5;
|
||||
}
|
||||
#endif
|
||||
|
||||
- (void)replaceMenuItem:(NSMenuItem*)old with:(NSMenuItem*)new
|
||||
@end // MMVimController (Private)
|
||||
|
||||
|
||||
|
||||
|
||||
@implementation NSToolbar (MMExtras)
|
||||
|
||||
- (int)indexOfItemWithItemIdentifier:(NSString *)identifier
|
||||
{
|
||||
NSMenu *menu = [old menu];
|
||||
int index = [menu indexOfItem:old];
|
||||
[menu removeItemAtIndex:index];
|
||||
[menu insertItem:new atIndex:index];
|
||||
NSArray *items = [self items];
|
||||
int i, count = [items count];
|
||||
for (i = 0; i < count; ++i) {
|
||||
id item = [items objectAtIndex:i];
|
||||
if ([[item itemIdentifier] isEqual:identifier])
|
||||
return i;
|
||||
}
|
||||
|
||||
return NSNotFound;
|
||||
}
|
||||
|
||||
@end // MMVimController (Private)
|
||||
- (NSToolbarItem *)itemAtIndex:(int)idx
|
||||
{
|
||||
NSArray *items = [self items];
|
||||
if (idx < 0 || idx >= [items count])
|
||||
return nil;
|
||||
|
||||
return [items objectAtIndex:idx];
|
||||
}
|
||||
|
||||
- (NSToolbarItem *)itemWithItemIdentifier:(NSString *)identifier
|
||||
{
|
||||
int idx = [self indexOfItemWithItemIdentifier:identifier];
|
||||
return idx != NSNotFound ? [self itemAtIndex:idx] : nil;
|
||||
}
|
||||
|
||||
@end // NSToolbar (MMExtras)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -129,4 +129,13 @@
|
||||
[super performClose:sender];
|
||||
}
|
||||
|
||||
- (BOOL)validateMenuItem:(NSMenuItem *)item
|
||||
{
|
||||
if ([item action] == @selector(vimMenuItemAction:)
|
||||
|| [item action] == @selector(performClose:))
|
||||
return [item tag];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end // MMWindow
|
||||
|
||||
@@ -51,7 +51,6 @@
|
||||
- (void)setFont:(NSFont *)font;
|
||||
- (void)setWideFont:(NSFont *)font;
|
||||
- (void)processCommandQueueDidFinish;
|
||||
- (void)popupMenu:(NSMenu *)menu atRow:(int)row column:(int)col;
|
||||
- (void)showTabBar:(BOOL)on;
|
||||
- (void)showToolbar:(BOOL)on size:(int)size mode:(int)mode;
|
||||
- (void)setMouseShape:(int)shape;
|
||||
@@ -69,5 +68,7 @@
|
||||
- (IBAction)findNext:(id)sender;
|
||||
- (IBAction)findPrevious:(id)sender;
|
||||
- (IBAction)vimMenuItemAction:(id)sender;
|
||||
- (IBAction)fontSizeUp:(id)sender;
|
||||
- (IBAction)fontSizeDown:(id)sender;
|
||||
|
||||
@end
|
||||
|
||||
@@ -263,7 +263,7 @@
|
||||
|
||||
- (void)openWindow
|
||||
{
|
||||
[[NSApp delegate] windowControllerWillOpen:self];
|
||||
[[MMAppController sharedInstance] windowControllerWillOpen:self];
|
||||
|
||||
[self addNewTabViewItem];
|
||||
|
||||
@@ -411,33 +411,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)popupMenu:(NSMenu *)menu atRow:(int)row column:(int)col
|
||||
{
|
||||
if (!setupDone) return;
|
||||
|
||||
NSEvent *event;
|
||||
if (row >= 0 && col >= 0) {
|
||||
// TODO: Let textView convert (row,col) to NSPoint.
|
||||
NSSize cellSize = [[vimView textView] cellSize];
|
||||
NSPoint pt = { (col+1)*cellSize.width, (row+1)*cellSize.height };
|
||||
pt = [[vimView textView] convertPoint:pt toView:nil];
|
||||
|
||||
event = [NSEvent mouseEventWithType:NSRightMouseDown
|
||||
location:pt
|
||||
modifierFlags:0
|
||||
timestamp:0
|
||||
windowNumber:[[self window] windowNumber]
|
||||
context:nil
|
||||
eventNumber:0
|
||||
clickCount:0
|
||||
pressure:1.0];
|
||||
} else {
|
||||
event = [[vimView textView] lastMouseDownEvent];
|
||||
}
|
||||
|
||||
[NSMenu popUpContextMenu:menu withEvent:event forView:[vimView textView]];
|
||||
}
|
||||
|
||||
- (void)showTabBar:(BOOL)on
|
||||
{
|
||||
[[vimView tabBarControl] setHidden:!on];
|
||||
@@ -614,20 +587,54 @@
|
||||
|
||||
- (IBAction)vimMenuItemAction:(id)sender
|
||||
{
|
||||
int tag = [sender tag];
|
||||
if (![sender isKindOfClass:[NSMenuItem class]]) return;
|
||||
|
||||
NSMutableData *data = [NSMutableData data];
|
||||
[data appendBytes:&tag length:sizeof(int)];
|
||||
// TODO: Make into category on NSMenuItem which returns descriptor.
|
||||
NSMenuItem *item = (NSMenuItem*)sender;
|
||||
NSMutableArray *desc = [NSMutableArray arrayWithObject:[item title]];
|
||||
|
||||
[vimController sendMessage:ExecuteMenuMsgID data:data];
|
||||
NSMenu *menu = [item menu];
|
||||
while (menu) {
|
||||
[desc insertObject:[menu title] atIndex:0];
|
||||
menu = [menu supermenu];
|
||||
}
|
||||
|
||||
// The "MainMenu" item is part of the Cocoa menu and should not be part of
|
||||
// the descriptor.
|
||||
if ([[desc objectAtIndex:0] isEqual:@"MainMenu"])
|
||||
[desc removeObjectAtIndex:0];
|
||||
|
||||
NSDictionary *attrs = [NSDictionary dictionaryWithObject:desc
|
||||
forKey:@"descriptor"];
|
||||
[vimController sendMessage:ExecuteMenuMsgID data:[attrs dictionaryAsData]];
|
||||
}
|
||||
|
||||
- (IBAction)fontSizeUp:(id)sender
|
||||
{
|
||||
[[NSFontManager sharedFontManager] modifyFont:
|
||||
[NSNumber numberWithInt:NSSizeUpFontAction]];
|
||||
}
|
||||
|
||||
- (IBAction)fontSizeDown:(id)sender
|
||||
{
|
||||
[[NSFontManager sharedFontManager] modifyFont:
|
||||
[NSNumber numberWithInt:NSSizeDownFontAction]];
|
||||
}
|
||||
|
||||
- (BOOL)validateMenuItem:(NSMenuItem *)item
|
||||
{
|
||||
if ([item action] == @selector(vimMenuItemAction:)
|
||||
|| [item action] == @selector(performClose:))
|
||||
return [item tag];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
// -- NSWindow delegate ------------------------------------------------------
|
||||
|
||||
- (void)windowDidBecomeMain:(NSNotification *)notification
|
||||
{
|
||||
[vimController updateMainMenu];
|
||||
[[MMAppController sharedInstance] setMainMenu:[vimController mainMenu]];
|
||||
[vimController sendMessage:GotFocusMsgID data:nil];
|
||||
|
||||
if ([vimView textView]) {
|
||||
|
||||
@@ -183,6 +183,7 @@ enum {
|
||||
MMInsertionPointHorizontal,
|
||||
MMInsertionPointVertical,
|
||||
MMInsertionPointHollow,
|
||||
MMInsertionPointVerticalRight,
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -698,7 +698,7 @@
|
||||
i386,
|
||||
);
|
||||
COPY_PHASE_STRIP = YES;
|
||||
CURRENT_PROJECT_VERSION = 28;
|
||||
CURRENT_PROJECT_VERSION = 29;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
|
||||
@@ -739,7 +739,7 @@
|
||||
buildSettings = {
|
||||
ARCHS = "$(NATIVE_ARCH)";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 28;
|
||||
CURRENT_PROJECT_VERSION = 29;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
|
||||
@@ -770,7 +770,7 @@
|
||||
buildSettings = {
|
||||
ARCHS = "$(NATIVE_ARCH)";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
CURRENT_PROJECT_VERSION = 28;
|
||||
CURRENT_PROJECT_VERSION = 29;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
|
||||
|
||||
+221
-84
@@ -32,6 +32,15 @@ static float MMMaxFontSize = 100.0f;
|
||||
|
||||
|
||||
static NSFont *gui_macvim_font_with_name(char_u *name);
|
||||
static int specialKeyToNSKey(int key);
|
||||
static int vimModMaskToEventModifierFlags(int mods);
|
||||
|
||||
NSArray *descriptor_for_menu(vimmenu_T *menu);
|
||||
vimmenu_T *menu_for_descriptor(NSArray *desc);
|
||||
|
||||
@interface NSString (VimStrings)
|
||||
+ (id)stringWithVimString:(char_u *)s;
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@@ -607,34 +616,61 @@ clip_mch_set_selection(VimClipboard *cbd)
|
||||
|
||||
|
||||
/*
|
||||
* Add a sub menu to the menu bar.
|
||||
* A menu descriptor represents the "address" of a menu as an array of strings.
|
||||
* E.g. the menu "File->Close" has descriptor { "File", "Close" }.
|
||||
*/
|
||||
NSArray *
|
||||
descriptor_for_menu(vimmenu_T *menu)
|
||||
{
|
||||
if (!menu) return nil;
|
||||
|
||||
NSMutableArray *desc = [NSMutableArray array];
|
||||
while (menu) {
|
||||
NSString *name = [NSString stringWithVimString:menu->dname];
|
||||
[desc insertObject:name atIndex:0];
|
||||
menu = menu->parent;
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
vimmenu_T *
|
||||
menu_for_descriptor(NSArray *desc)
|
||||
{
|
||||
if (!(desc && [desc count] > 0)) return NULL;
|
||||
|
||||
vimmenu_T *menu = root_menu;
|
||||
int i, count = [desc count];
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
NSString *component = [desc objectAtIndex:i];
|
||||
while (menu) {
|
||||
NSString *name = [NSString stringWithVimString:menu->dname];
|
||||
if ([component isEqual:name]) {
|
||||
if (i+1 == count)
|
||||
return menu; // Matched all components, so return menu
|
||||
menu = menu->children;
|
||||
break;
|
||||
}
|
||||
menu = menu->next;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a submenu to the menu bar, toolbar, or a popup menu.
|
||||
*/
|
||||
void
|
||||
gui_mch_add_menu(vimmenu_T *menu, int idx)
|
||||
{
|
||||
// HACK! If menu has no parent, then we set the parent tag to the type of
|
||||
// menu it is. This will not mix up tag and type because pointers can not
|
||||
// take values close to zero (and the tag is simply the value of the
|
||||
// pointer).
|
||||
int parent = (int)menu->parent;
|
||||
if (!parent) {
|
||||
parent = menu_is_popup(menu->name) ? MenuPopupType :
|
||||
menu_is_toolbar(menu->name) ? MenuToolbarType :
|
||||
MenuMenubarType;
|
||||
}
|
||||
|
||||
char_u *dname = menu->dname;
|
||||
#ifdef FEAT_MBYTE
|
||||
dname = CONVERT_TO_UTF8(dname);
|
||||
#endif
|
||||
|
||||
[[MMBackend sharedInstance]
|
||||
addMenuWithTag:(int)menu parent:parent name:(char*)dname
|
||||
atIndex:idx];
|
||||
|
||||
#ifdef FEAT_MBYTE
|
||||
CONVERT_TO_UTF8_FREE(dname);
|
||||
#endif
|
||||
NSArray *desc = descriptor_for_menu(menu);
|
||||
[[MMBackend sharedInstance] queueMessage:AddMenuMsgID properties:
|
||||
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
desc, @"descriptor",
|
||||
[NSNumber numberWithInt:idx], @"index",
|
||||
nil]];
|
||||
}
|
||||
|
||||
|
||||
@@ -649,40 +685,25 @@ gui_mch_add_menu_item(vimmenu_T *menu, int idx)
|
||||
char_u *icon = menu->iconfile ? menu->iconfile :
|
||||
menu->iconidx >= 0 ? menu->dname :
|
||||
NULL;
|
||||
//char *name = menu_is_separator(menu->name) ? NULL : (char*)menu->dname;
|
||||
char_u *name = menu->dname;
|
||||
char_u *tip = menu->strings[MENU_INDEX_TIP]
|
||||
? menu->strings[MENU_INDEX_TIP] : menu->actext;
|
||||
char_u *map_str = menu->strings[MENU_INDEX_NORMAL];
|
||||
char_u *mac_action = menu->mac_action;
|
||||
NSArray *desc = descriptor_for_menu(menu);
|
||||
NSString *keyEquivalent = menu->mac_key
|
||||
? [NSString stringWithFormat:@"%C", specialKeyToNSKey(menu->mac_key)]
|
||||
: [NSString string];
|
||||
int modifierMask = vimModMaskToEventModifierFlags(menu->mac_mods);
|
||||
|
||||
#ifdef FEAT_MBYTE
|
||||
icon = CONVERT_TO_UTF8(icon);
|
||||
name = CONVERT_TO_UTF8(name);
|
||||
tip = CONVERT_TO_UTF8(tip);
|
||||
map_str = CONVERT_TO_UTF8(map_str);
|
||||
mac_action = CONVERT_TO_UTF8(mac_action);
|
||||
#endif
|
||||
|
||||
[[MMBackend sharedInstance]
|
||||
addMenuItemWithTag:(int)menu
|
||||
parent:(int)menu->parent
|
||||
name:(char*)name
|
||||
tip:(char*)tip
|
||||
icon:(char*)icon
|
||||
keyEquivalent:menu->mac_key
|
||||
modifiers:menu->mac_mods
|
||||
action:(char*)mac_action
|
||||
isAlternate:menu->mac_alternate
|
||||
atIndex:idx];
|
||||
|
||||
#ifdef FEAT_MBYTE
|
||||
CONVERT_TO_UTF8_FREE(icon);
|
||||
CONVERT_TO_UTF8_FREE(name);
|
||||
CONVERT_TO_UTF8_FREE(tip);
|
||||
CONVERT_TO_UTF8_FREE(map_str);
|
||||
CONVERT_TO_UTF8_FREE(mac_action);
|
||||
#endif
|
||||
[[MMBackend sharedInstance] queueMessage:AddMenuItemMsgID properties:
|
||||
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
desc, @"descriptor",
|
||||
[NSNumber numberWithInt:idx], @"index",
|
||||
[NSString stringWithVimString:tip], @"tip",
|
||||
[NSString stringWithVimString:icon], @"icon",
|
||||
keyEquivalent, @"keyEquivalent",
|
||||
[NSNumber numberWithInt:modifierMask], @"modifierMask",
|
||||
[NSString stringWithVimString:menu->mac_action], @"action",
|
||||
[NSNumber numberWithBool:menu->mac_alternate], @"isAlternate",
|
||||
nil]];
|
||||
}
|
||||
|
||||
|
||||
@@ -692,7 +713,9 @@ gui_mch_add_menu_item(vimmenu_T *menu, int idx)
|
||||
void
|
||||
gui_mch_destroy_menu(vimmenu_T *menu)
|
||||
{
|
||||
[[MMBackend sharedInstance] removeMenuItemWithTag:(int)menu];
|
||||
NSArray *desc = descriptor_for_menu(menu);
|
||||
[[MMBackend sharedInstance] queueMessage:RemoveMenuItemMsgID properties:
|
||||
[NSDictionary dictionaryWithObject:desc forKey:@"descriptor"]];
|
||||
}
|
||||
|
||||
|
||||
@@ -705,12 +728,17 @@ gui_mch_menu_grey(vimmenu_T *menu, int grey)
|
||||
/* Only update menu if the 'grey' state has changed to avoid having to pass
|
||||
* lots of unnecessary data to MacVim. (Skipping this test makes MacVim
|
||||
* pause noticably on mode changes. */
|
||||
if (menu->was_grey != grey)
|
||||
{
|
||||
menu->was_grey = grey;
|
||||
[[MMBackend sharedInstance]
|
||||
enableMenuItemWithTag:(int)menu state:!grey];
|
||||
}
|
||||
NSArray *desc = descriptor_for_menu(menu);
|
||||
if (menu->was_grey == grey)
|
||||
return;
|
||||
|
||||
menu->was_grey = grey;
|
||||
|
||||
[[MMBackend sharedInstance] queueMessage:EnableMenuItemMsgID properties:
|
||||
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
desc, @"descriptor",
|
||||
[NSNumber numberWithInt:!grey], @"enable",
|
||||
nil]];
|
||||
}
|
||||
|
||||
|
||||
@@ -732,18 +760,9 @@ gui_mch_menu_hidden(vimmenu_T *menu, int hidden)
|
||||
void
|
||||
gui_mch_show_popupmenu(vimmenu_T *menu)
|
||||
{
|
||||
char_u *name = menu->name;
|
||||
#ifdef FEAT_MBYTE
|
||||
name = CONVERT_TO_UTF8(name);
|
||||
#endif
|
||||
|
||||
[[MMBackend sharedInstance] showPopupMenuWithName:(char*)name
|
||||
atMouseLocation:YES];
|
||||
|
||||
#ifdef FEAT_MBYTE
|
||||
CONVERT_TO_UTF8_FREE(name);
|
||||
#endif
|
||||
|
||||
NSArray *desc = descriptor_for_menu(menu);
|
||||
[[MMBackend sharedInstance] queueMessage:ShowPopupMenuMsgID properties:
|
||||
[NSDictionary dictionaryWithObject:desc forKey:@"descriptor"]];
|
||||
}
|
||||
|
||||
|
||||
@@ -753,16 +772,19 @@ gui_mch_show_popupmenu(vimmenu_T *menu)
|
||||
void
|
||||
gui_make_popup(char_u *path_name, int mouse_pos)
|
||||
{
|
||||
#ifdef FEAT_MBYTE
|
||||
path_name = CONVERT_TO_UTF8(path_name);
|
||||
#endif
|
||||
vimmenu_T *menu = gui_find_menu(path_name);
|
||||
if (!(menu && menu->children)) return;
|
||||
|
||||
[[MMBackend sharedInstance] showPopupMenuWithName:(char*)path_name
|
||||
atMouseLocation:mouse_pos];
|
||||
NSArray *desc = descriptor_for_menu(menu);
|
||||
NSDictionary *p = (mouse_pos || NULL == curwin)
|
||||
? [NSDictionary dictionaryWithObject:desc forKey:@"descriptor"]
|
||||
: [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
desc, @"descriptor",
|
||||
[NSNumber numberWithInt:curwin->w_wrow], @"row",
|
||||
[NSNumber numberWithInt:curwin->w_wcol], @"column",
|
||||
nil];
|
||||
|
||||
#ifdef FEAT_MBYTE
|
||||
CONVERT_TO_UTF8_FREE(path_name);
|
||||
#endif
|
||||
[[MMBackend sharedInstance] queueMessage:ShowPopupMenuMsgID properties:p];
|
||||
}
|
||||
|
||||
|
||||
@@ -1051,11 +1073,24 @@ gui_mch_draw_part_cursor(int w, int h, guicolor_T color)
|
||||
// font dimensions. Thus these parameters are useless. Instead we look at
|
||||
// the shape_table to determine the shape and size of the cursor (just like
|
||||
// gui_update_cursor() does).
|
||||
|
||||
#ifdef FEAT_RIGHTLEFT
|
||||
// If 'rl' is set the insert mode cursor must be drawn on the right-hand
|
||||
// side of a text cell.
|
||||
int rl = curwin ? curwin->w_p_rl : FALSE;
|
||||
#else
|
||||
int rl = FALSE;
|
||||
#endif
|
||||
int idx = get_shape_idx(FALSE);
|
||||
int shape = MMInsertionPointBlock;
|
||||
switch (shape_table[idx].shape) {
|
||||
case SHAPE_HOR: shape = MMInsertionPointHorizontal; break;
|
||||
case SHAPE_VER: shape = MMInsertionPointVertical; break;
|
||||
case SHAPE_HOR:
|
||||
shape = MMInsertionPointHorizontal;
|
||||
break;
|
||||
case SHAPE_VER:
|
||||
shape = rl ? MMInsertionPointVerticalRight
|
||||
: MMInsertionPointVertical;
|
||||
break;
|
||||
}
|
||||
|
||||
return [[MMBackend sharedInstance]
|
||||
@@ -1886,3 +1921,105 @@ is_valid_macaction(char_u *action)
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
static int specialKeyToNSKey(int key)
|
||||
{
|
||||
if (!IS_SPECIAL(key))
|
||||
return key;
|
||||
|
||||
static struct {
|
||||
int special;
|
||||
int nskey;
|
||||
} sp2ns[] = {
|
||||
{ K_UP, NSUpArrowFunctionKey },
|
||||
{ K_DOWN, NSDownArrowFunctionKey },
|
||||
{ K_LEFT, NSLeftArrowFunctionKey },
|
||||
{ K_RIGHT, NSRightArrowFunctionKey },
|
||||
{ K_F1, NSF1FunctionKey },
|
||||
{ K_F2, NSF2FunctionKey },
|
||||
{ K_F3, NSF3FunctionKey },
|
||||
{ K_F4, NSF4FunctionKey },
|
||||
{ K_F5, NSF5FunctionKey },
|
||||
{ K_F6, NSF6FunctionKey },
|
||||
{ K_F7, NSF7FunctionKey },
|
||||
{ K_F8, NSF8FunctionKey },
|
||||
{ K_F9, NSF9FunctionKey },
|
||||
{ K_F10, NSF10FunctionKey },
|
||||
{ K_F11, NSF11FunctionKey },
|
||||
{ K_F12, NSF12FunctionKey },
|
||||
{ K_F13, NSF13FunctionKey },
|
||||
{ K_F14, NSF14FunctionKey },
|
||||
{ K_F15, NSF15FunctionKey },
|
||||
{ K_F16, NSF16FunctionKey },
|
||||
{ K_F17, NSF17FunctionKey },
|
||||
{ K_F18, NSF18FunctionKey },
|
||||
{ K_F19, NSF19FunctionKey },
|
||||
{ K_F20, NSF20FunctionKey },
|
||||
{ K_F21, NSF21FunctionKey },
|
||||
{ K_F22, NSF22FunctionKey },
|
||||
{ K_F23, NSF23FunctionKey },
|
||||
{ K_F24, NSF24FunctionKey },
|
||||
{ K_F25, NSF25FunctionKey },
|
||||
{ K_F26, NSF26FunctionKey },
|
||||
{ K_F27, NSF27FunctionKey },
|
||||
{ K_F28, NSF28FunctionKey },
|
||||
{ K_F29, NSF29FunctionKey },
|
||||
{ K_F30, NSF30FunctionKey },
|
||||
{ K_F31, NSF31FunctionKey },
|
||||
{ K_F32, NSF32FunctionKey },
|
||||
{ K_F33, NSF33FunctionKey },
|
||||
{ K_F34, NSF34FunctionKey },
|
||||
{ K_F35, NSF35FunctionKey },
|
||||
{ K_DEL, NSBackspaceCharacter },
|
||||
{ K_BS, NSDeleteCharacter },
|
||||
{ K_HOME, NSHomeFunctionKey },
|
||||
{ K_END, NSEndFunctionKey },
|
||||
{ K_PAGEUP, NSPageUpFunctionKey },
|
||||
{ K_PAGEDOWN, NSPageDownFunctionKey }
|
||||
};
|
||||
|
||||
int i;
|
||||
for (i = 0; i < sizeof(sp2ns)/sizeof(sp2ns[0]); ++i) {
|
||||
if (sp2ns[i].special == key)
|
||||
return sp2ns[i].nskey;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vimModMaskToEventModifierFlags(int mods)
|
||||
{
|
||||
int flags = 0;
|
||||
|
||||
if (mods & MOD_MASK_SHIFT)
|
||||
flags |= NSShiftKeyMask;
|
||||
if (mods & MOD_MASK_CTRL)
|
||||
flags |= NSControlKeyMask;
|
||||
if (mods & MOD_MASK_ALT)
|
||||
flags |= NSAlternateKeyMask;
|
||||
if (mods & MOD_MASK_CMD)
|
||||
flags |= NSCommandKeyMask;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@implementation NSString (VimStrings)
|
||||
+ (id)stringWithVimString:(char_u *)s
|
||||
{
|
||||
if (s) {
|
||||
#ifdef FEAT_MBYTE
|
||||
s = CONVERT_TO_UTF8(s);
|
||||
#endif
|
||||
NSString *string = [NSString stringWithUTF8String:(char*)s];
|
||||
#ifdef FEAT_MBYTE
|
||||
CONVERT_TO_UTF8_FREE(s);
|
||||
#endif
|
||||
return string;
|
||||
}
|
||||
|
||||
return [NSString string];
|
||||
}
|
||||
@end
|
||||
|
||||
+10
-2
@@ -79,8 +79,12 @@ an 20.470 Edit.Special\ Characters\.\.\. <Nop>
|
||||
aunmenu Window
|
||||
|
||||
an <silent> 9900.300 Window.Minimize <Nop>
|
||||
an <silent> 9900.301 Window.Minimize\ All <Nop>
|
||||
an <silent> 9900.310 Window.Zoom <Nop>
|
||||
an <silent> 9900.311 Window.Zoom\ All <Nop>
|
||||
an <silent> 9900.320 Window.Toggle\ Full\ Screen\ Mode :set invfullscreen<CR>
|
||||
an <silent> 9900.325 Window.Cycle\ Through\ Windows <Nop>
|
||||
an <silent> 9900.326 Window.Cycle\ Backwards\ Through\ Windows <Nop>
|
||||
an 9900.330 Window.-SEP1- <Nop>
|
||||
" TODO! Grey out if no tabs are visible.
|
||||
an <silent> 9900.340 Window.Previous\ Tab :tabprevious<CR>
|
||||
@@ -235,9 +239,13 @@ macm Tools.Previous\ Error key=<D-C-Left>
|
||||
macm Tools.Older\ List key=<D-C-Up>
|
||||
macm Tools.Newer\ List key=<D-C-Down>
|
||||
|
||||
macm Window.Minimize key=<D-m> action=performMiniaturize:
|
||||
macm Window.Zoom key=<D-C-z> action=performZoom:
|
||||
macm Window.Minimize key=<D-m> action=performMiniaturize:
|
||||
macm Window.Minimize\ All key=<D-M-m> action=miniaturizeAll: alt=YES
|
||||
macm Window.Zoom key=<D-C-z> action=performZoom:
|
||||
macm Window.Zoom\ All key=<D-M-C-z> action=zoomAll: alt=YES
|
||||
macm Window.Toggle\ Full\ Screen\ Mode key=<D-F>
|
||||
macm Window.Cycle\ Through\ Windows key=<D-`> action=_cycleWindows:
|
||||
macm Window.Cycle\ Backwards\ Through\ Windows key=<D-S-`> action=_cycleWindowsBackwards: alt=YES
|
||||
macm Window.Previous\ Tab key=<D-{>
|
||||
macm Window.Next\ Tab key=<D-}>
|
||||
macm Window.Bring\ All\ To\ Front action=arrangeInFront:
|
||||
|
||||
@@ -40,6 +40,42 @@
|
||||
Sparkle supports updates in zip, tar, tbz, tgz, or dmg format.
|
||||
-->
|
||||
|
||||
<item>
|
||||
<title>Snapshot 29 released</title>
|
||||
<description><![CDATA[
|
||||
<h1>MacVim snapshot 29 released</h1>
|
||||
<p> Changes since snapshot 28:
|
||||
<ul>
|
||||
<li> copy&paste and other "Edit" menu items now work as expected with dialogs
|
||||
(such as open/save). </li>
|
||||
<li> some menus (such as the "Window" menu) has got some new items </li>
|
||||
<li> general menu improvements when no editor window is open </li>
|
||||
<li> window-cycling key Cmd-` is no longer hard-coded and can be changed with
|
||||
:macmenu command </li>
|
||||
<li> ability to access some OS X default Cmd-keys even if menus are
|
||||
completely altered (e.g. when starting with "-u NONE") </li>
|
||||
<li> QuickLook works with .vim files (patch by Nico Weber) </li>
|
||||
<li> insert mode cursor honors the 'rightleft' option </li>
|
||||
<li> no more "freezes" during :shell </li>
|
||||
<li> no beeping on Cmd-q </li>
|
||||
<li> Cmd-w works in full-screen again </li>
|
||||
<li> window dimensions properly restored when leaving full-screen when
|
||||
"maxvert" is in 'fuoptions' </li>
|
||||
<li> support for 'mousehide' option </li>
|
||||
<li> latest vim patches and runtime files </li>
|
||||
</ul>
|
||||
</p>
|
||||
]]></description>
|
||||
<pubDate>Sun, 7 Jun 2008 12:57 CET</pubDate>
|
||||
<enclosure type="application/octet-stream"
|
||||
url="http://macvim.googlecode.com/files/MacVim-snapshot-29.tbz"
|
||||
length="8137324"
|
||||
sparkle:version="29"
|
||||
sparkle:shortVersionString="7.1"
|
||||
/>
|
||||
</item>
|
||||
|
||||
|
||||
<item>
|
||||
<title>Snapshot 28 released</title>
|
||||
<description><![CDATA[
|
||||
|
||||
+8
-3
@@ -780,6 +780,8 @@ LINT_OPTIONS = -beprxzF
|
||||
# 1) make config
|
||||
# 2) edit auto/config.mk, add -n32 to LDFLAGS
|
||||
# 3) make
|
||||
#
|
||||
#Alternatively: use -o32 instead of -n32.
|
||||
###
|
||||
|
||||
### (C) On SCO Unix v3.2.5 (and probably other versions) the termcap library,
|
||||
@@ -1074,7 +1076,7 @@ PRINTSOURCE = ../runtime/print
|
||||
# default vi editor, it will create a link from vi to Vim when doing
|
||||
# "make install". An existing file will be overwritten!
|
||||
# When not using it, some make programs can't handle an undefined $(LINKIT).
|
||||
#LINKIT = -ln -f -s $(BINDIR)/$(VIMTARGET) /usr/bin/vi
|
||||
#LINKIT = ln -f -s $(DEST_BIN)/$(VIMTARGET) $(DESTDIR)/usr/bin/vi
|
||||
LINKIT = @echo >/dev/null
|
||||
|
||||
###
|
||||
@@ -1306,6 +1308,9 @@ LINT_EXTRA = -DUSE_SNIFF -DHANGUL_INPUT -D"__attribute__(x)="
|
||||
|
||||
DEPEND_CFLAGS = -DPROTO -DDEPEND -DFEAT_GUI $(LINT_CFLAGS)
|
||||
|
||||
# If you have problems with flags that cproto doesn't support, and you are
|
||||
# using GNU make, you can try using the other line to filter out arguments.
|
||||
#PFLAGS = $(PROTO_FLAGS) -DPROTO $(filter -D% -I%, $(LINT_CFLAGS))
|
||||
PFLAGS = $(PROTO_FLAGS) -DPROTO $(LINT_CFLAGS)
|
||||
|
||||
ALL_LIB_DIRS = $(GUI_LIBS_DIR) $(X_LIBS_DIR)
|
||||
@@ -2190,7 +2195,7 @@ SHADOWDIR = shadow
|
||||
|
||||
shadow: runtime pixmaps
|
||||
mkdir $(SHADOWDIR)
|
||||
cd $(SHADOWDIR); ln -s ../*.[ch] ../*.in ../*.sh ../*.xs ../*.xbm ../toolcheck ../proto ../vimtutor ../gvimtutor ../mkinstalldirs .
|
||||
cd $(SHADOWDIR); ln -s ../*.[ch] ../*.in ../*.sh ../*.xs ../*.xbm ../toolcheck ../proto ../po ../vimtutor ../gvimtutor ../mkinstalldirs .
|
||||
mkdir $(SHADOWDIR)/auto
|
||||
cd $(SHADOWDIR)/auto; ln -s ../../auto/configure .
|
||||
cd $(SHADOWDIR); rm -f auto/link.sed
|
||||
@@ -2209,7 +2214,7 @@ shadow: runtime pixmaps
|
||||
cd $(SHADOWDIR)/testdir; ln -s ../../testdir/Makefile \
|
||||
../../testdir/vimrc.unix \
|
||||
../../testdir/*.in \
|
||||
../../testdir/unix.vim \
|
||||
../../testdir/*.vim \
|
||||
../../testdir/*.ok .
|
||||
|
||||
# Link needed for doing "make install" in a shadow directory.
|
||||
|
||||
+127
-79
@@ -507,6 +507,7 @@ static void f_filewritable __ARGS((typval_T *argvars, typval_T *rettv));
|
||||
static void f_filter __ARGS((typval_T *argvars, typval_T *rettv));
|
||||
static void f_finddir __ARGS((typval_T *argvars, typval_T *rettv));
|
||||
static void f_findfile __ARGS((typval_T *argvars, typval_T *rettv));
|
||||
static void f_fnameescape __ARGS((typval_T *argvars, typval_T *rettv));
|
||||
static void f_fnamemodify __ARGS((typval_T *argvars, typval_T *rettv));
|
||||
static void f_foldclosed __ARGS((typval_T *argvars, typval_T *rettv));
|
||||
static void f_foldclosedend __ARGS((typval_T *argvars, typval_T *rettv));
|
||||
@@ -7107,6 +7108,7 @@ static struct fst
|
||||
{"filter", 2, 2, f_filter},
|
||||
{"finddir", 1, 3, f_finddir},
|
||||
{"findfile", 1, 3, f_findfile},
|
||||
{"fnameescape", 1, 1, f_fnameescape},
|
||||
{"fnamemodify", 2, 2, f_fnamemodify},
|
||||
{"foldclosed", 1, 1, f_foldclosed},
|
||||
{"foldclosedend", 1, 1, f_foldclosedend},
|
||||
@@ -9464,6 +9466,19 @@ f_findfile(argvars, rettv)
|
||||
findfilendir(argvars, rettv, FINDFILE_FILE);
|
||||
}
|
||||
|
||||
/*
|
||||
* "fnameescape({string})" function
|
||||
*/
|
||||
static void
|
||||
f_fnameescape(argvars, rettv)
|
||||
typval_T *argvars;
|
||||
typval_T *rettv;
|
||||
{
|
||||
rettv->vval.v_string = vim_strsave_fnameescape(
|
||||
get_tv_string(&argvars[0]), FALSE);
|
||||
rettv->v_type = VAR_STRING;
|
||||
}
|
||||
|
||||
/*
|
||||
* "fnamemodify({fname}, {mods})" function
|
||||
*/
|
||||
@@ -21073,8 +21088,12 @@ static int shortpath_for_invalid_fname __ARGS((char_u **fname, char_u **bufp, in
|
||||
static int shortpath_for_partial __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
|
||||
|
||||
/*
|
||||
* Get the short pathname of a file.
|
||||
* Returns 1 on success. *fnamelen is 0 for nonexistent path.
|
||||
* Get the short path (8.3) for the filename in "fnamep".
|
||||
* Only works for a valid file name.
|
||||
* When the path gets longer "fnamep" is changed and the allocated buffer
|
||||
* is put in "bufp".
|
||||
* *fnamelen is the length of "fnamep" and set to 0 for a nonexistent path.
|
||||
* Returns OK on success, FAIL on failure.
|
||||
*/
|
||||
static int
|
||||
get_short_pathname(fnamep, bufp, fnamelen)
|
||||
@@ -21082,36 +21101,44 @@ get_short_pathname(fnamep, bufp, fnamelen)
|
||||
char_u **bufp;
|
||||
int *fnamelen;
|
||||
{
|
||||
int l,len;
|
||||
int l, len;
|
||||
char_u *newbuf;
|
||||
|
||||
len = *fnamelen;
|
||||
|
||||
l = GetShortPathName(*fnamep, *fnamep, len);
|
||||
if (l > len - 1)
|
||||
{
|
||||
/* If that doesn't work (not enough space), then save the string
|
||||
* and try again with a new buffer big enough
|
||||
*/
|
||||
* and try again with a new buffer big enough. */
|
||||
newbuf = vim_strnsave(*fnamep, l);
|
||||
if (newbuf == NULL)
|
||||
return 0;
|
||||
return FAIL;
|
||||
|
||||
vim_free(*bufp);
|
||||
*fnamep = *bufp = newbuf;
|
||||
|
||||
l = GetShortPathName(*fnamep,*fnamep,l+1);
|
||||
|
||||
/* Really should always succeed, as the buffer is big enough */
|
||||
/* Really should always succeed, as the buffer is big enough. */
|
||||
l = GetShortPathName(*fnamep, *fnamep, l+1);
|
||||
}
|
||||
|
||||
*fnamelen = l;
|
||||
return 1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a short path name. Returns the length of the buffer it needs.
|
||||
* Doesn't copy over the end of the buffer passed in.
|
||||
* Get the short path (8.3) for the filename in "fname". The converted
|
||||
* path is returned in "bufp".
|
||||
*
|
||||
* Some of the directories specified in "fname" may not exist. This function
|
||||
* will shorten the existing directories at the beginning of the path and then
|
||||
* append the remaining non-existing path.
|
||||
*
|
||||
* fname - Pointer to the filename to shorten. On return, contains the
|
||||
* pointer to the shortened pathname
|
||||
* bufp - Pointer to an allocated buffer for the filename.
|
||||
* fnamelen - Length of the filename pointed to by fname
|
||||
*
|
||||
* Returns OK on success (or nothing done) and FAIL on failure (out of memory).
|
||||
*/
|
||||
static int
|
||||
shortpath_for_invalid_fname(fname, bufp, fnamelen)
|
||||
@@ -21119,85 +21146,106 @@ shortpath_for_invalid_fname(fname, bufp, fnamelen)
|
||||
char_u **bufp;
|
||||
int *fnamelen;
|
||||
{
|
||||
char_u *s, *p, *pbuf2, *pbuf3;
|
||||
char_u *short_fname, *save_fname, *pbuf_unused;
|
||||
char_u *endp, *save_endp;
|
||||
char_u ch;
|
||||
int len, len2, plen, slen;
|
||||
int old_len, len;
|
||||
int new_len, sfx_len;
|
||||
int retval = OK;
|
||||
|
||||
/* Make a copy */
|
||||
len2 = *fnamelen;
|
||||
pbuf2 = vim_strnsave(*fname, len2);
|
||||
pbuf3 = NULL;
|
||||
old_len = *fnamelen;
|
||||
save_fname = vim_strnsave(*fname, old_len);
|
||||
pbuf_unused = NULL;
|
||||
short_fname = NULL;
|
||||
|
||||
s = pbuf2 + len2 - 1; /* Find the end */
|
||||
slen = 1;
|
||||
plen = len2;
|
||||
endp = save_fname + old_len - 1; /* Find the end of the copy */
|
||||
save_endp = endp;
|
||||
|
||||
if (after_pathsep(pbuf2, s + 1))
|
||||
/*
|
||||
* Try shortening the supplied path till it succeeds by removing one
|
||||
* directory at a time from the tail of the path.
|
||||
*/
|
||||
len = 0;
|
||||
for (;;)
|
||||
{
|
||||
--s;
|
||||
++slen;
|
||||
--plen;
|
||||
/* go back one path-separator */
|
||||
while (endp > save_fname && !after_pathsep(save_fname, endp + 1))
|
||||
--endp;
|
||||
if (endp <= save_fname)
|
||||
break; /* processed the complete path */
|
||||
|
||||
/*
|
||||
* Replace the path separator with a NUL and try to shorten the
|
||||
* resulting path.
|
||||
*/
|
||||
ch = *endp;
|
||||
*endp = 0;
|
||||
short_fname = save_fname;
|
||||
len = STRLEN(short_fname) + 1;
|
||||
if (get_short_pathname(&short_fname, &pbuf_unused, &len) == FAIL)
|
||||
{
|
||||
retval = FAIL;
|
||||
goto theend;
|
||||
}
|
||||
*endp = ch; /* preserve the string */
|
||||
|
||||
if (len > 0)
|
||||
break; /* successfully shortened the path */
|
||||
|
||||
/* failed to shorten the path. Skip the path separator */
|
||||
--endp;
|
||||
}
|
||||
|
||||
do
|
||||
if (len > 0)
|
||||
{
|
||||
/* Go back one path-separator */
|
||||
while (s > pbuf2 && !after_pathsep(pbuf2, s + 1))
|
||||
{
|
||||
--s;
|
||||
++slen;
|
||||
--plen;
|
||||
}
|
||||
if (s <= pbuf2)
|
||||
break;
|
||||
/*
|
||||
* Succeeded in shortening the path. Now concatenate the shortened
|
||||
* path with the remaining path at the tail.
|
||||
*/
|
||||
|
||||
/* Remember the character that is about to be splatted */
|
||||
ch = *s;
|
||||
*s = 0; /* get_short_pathname requires a null-terminated string */
|
||||
/* Compute the length of the new path. */
|
||||
sfx_len = (int)(save_endp - endp) + 1;
|
||||
new_len = len + sfx_len;
|
||||
|
||||
/* Try it in situ */
|
||||
p = pbuf2;
|
||||
if (!get_short_pathname(&p, &pbuf3, &plen))
|
||||
{
|
||||
vim_free(pbuf2);
|
||||
return -1;
|
||||
}
|
||||
*s = ch; /* Preserve the string */
|
||||
} while (plen == 0);
|
||||
|
||||
if (plen > 0)
|
||||
{
|
||||
/* Remember the length of the new string. */
|
||||
*fnamelen = len = plen + slen;
|
||||
*fnamelen = new_len;
|
||||
vim_free(*bufp);
|
||||
if (len > len2)
|
||||
if (new_len > old_len)
|
||||
{
|
||||
/* If there's not enough space in the currently allocated string,
|
||||
* then copy it to a buffer big enough.
|
||||
*/
|
||||
*fname= *bufp = vim_strnsave(p, len);
|
||||
/* There is not enough space in the currently allocated string,
|
||||
* copy it to a buffer big enough. */
|
||||
*fname = *bufp = vim_strnsave(short_fname, new_len);
|
||||
if (*fname == NULL)
|
||||
return -1;
|
||||
{
|
||||
retval = FAIL;
|
||||
goto theend;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Transfer pbuf2 to being the main buffer (it's big enough) */
|
||||
*fname = *bufp = pbuf2;
|
||||
if (p != pbuf2)
|
||||
strncpy(*fname, p, plen);
|
||||
pbuf2 = NULL;
|
||||
/* Transfer short_fname to the main buffer (it's big enough),
|
||||
* unless get_short_pathname() did its work in-place. */
|
||||
*fname = *bufp = save_fname;
|
||||
if (short_fname != save_fname)
|
||||
vim_strncpy(save_fname, short_fname, len);
|
||||
save_fname = NULL;
|
||||
}
|
||||
/* Concat the next bit */
|
||||
strncpy(*fname + plen, s, slen);
|
||||
(*fname)[len] = '\0';
|
||||
|
||||
/* concat the not-shortened part of the path */
|
||||
vim_strncpy(*fname + len, endp, sfx_len);
|
||||
(*fname)[new_len] = NUL;
|
||||
}
|
||||
vim_free(pbuf3);
|
||||
vim_free(pbuf2);
|
||||
return 0;
|
||||
|
||||
theend:
|
||||
vim_free(pbuf_unused);
|
||||
vim_free(save_fname);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a pathname for a partial path.
|
||||
* Returns OK for success, FAIL for failure.
|
||||
*/
|
||||
static int
|
||||
shortpath_for_partial(fnamep, bufp, fnamelen)
|
||||
@@ -21227,8 +21275,8 @@ shortpath_for_partial(fnamep, bufp, fnamelen)
|
||||
|
||||
len = tflen = (int)STRLEN(tfname);
|
||||
|
||||
if (!get_short_pathname(&tfname, &pbuf, &len))
|
||||
return -1;
|
||||
if (get_short_pathname(&tfname, &pbuf, &len) == FAIL)
|
||||
return FAIL;
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
@@ -21237,8 +21285,8 @@ shortpath_for_partial(fnamep, bufp, fnamelen)
|
||||
* there's not a lot of point in guessing what it might be.
|
||||
*/
|
||||
len = tflen;
|
||||
if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == -1)
|
||||
return -1;
|
||||
if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == FAIL)
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
/* Count the paths backward to find the beginning of the desired string. */
|
||||
@@ -21262,7 +21310,7 @@ shortpath_for_partial(fnamep, bufp, fnamelen)
|
||||
if (p >= tfname)
|
||||
*p = '~';
|
||||
else
|
||||
return -1;
|
||||
return FAIL;
|
||||
}
|
||||
else
|
||||
++p;
|
||||
@@ -21273,7 +21321,7 @@ shortpath_for_partial(fnamep, bufp, fnamelen)
|
||||
*bufp = pbuf;
|
||||
*fnamep = p;
|
||||
|
||||
return 0;
|
||||
return OK;
|
||||
}
|
||||
#endif /* WIN3264 */
|
||||
|
||||
@@ -21281,7 +21329,7 @@ shortpath_for_partial(fnamep, bufp, fnamelen)
|
||||
* Adjust a filename, according to a string of modifiers.
|
||||
* *fnamep must be NUL terminated when called. When returning, the length is
|
||||
* determined by *fnamelen.
|
||||
* Returns valid flags.
|
||||
* Returns VALID_ flags or -1 for failure.
|
||||
* When there is an error, *fnamep is set to NULL.
|
||||
*/
|
||||
int
|
||||
@@ -21493,7 +21541,7 @@ repeat:
|
||||
*/
|
||||
if (!has_fullname && !vim_isAbsName(*fnamep))
|
||||
{
|
||||
if (shortpath_for_partial(fnamep, bufp, fnamelen) == -1)
|
||||
if (shortpath_for_partial(fnamep, bufp, fnamelen) == FAIL)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
@@ -21503,7 +21551,7 @@ repeat:
|
||||
/* Simple case, already have the full-name
|
||||
* Nearly always shorter, so try first time. */
|
||||
l = *fnamelen;
|
||||
if (!get_short_pathname(fnamep, bufp, &l))
|
||||
if (get_short_pathname(fnamep, bufp, &l) == FAIL)
|
||||
return -1;
|
||||
|
||||
if (l == 0)
|
||||
@@ -21511,7 +21559,7 @@ repeat:
|
||||
/* Couldn't find the filename.. search the paths.
|
||||
*/
|
||||
l = *fnamelen;
|
||||
if (shortpath_for_invalid_fname(fnamep, bufp, &l ) == -1)
|
||||
if (shortpath_for_invalid_fname(fnamep, bufp, &l) == FAIL)
|
||||
return -1;
|
||||
}
|
||||
*fnamelen = l;
|
||||
|
||||
+28
-13
@@ -3657,20 +3657,9 @@ ExpandEscape(xp, str, numfiles, files, options)
|
||||
}
|
||||
}
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
{
|
||||
char_u buf[20];
|
||||
int j = 0;
|
||||
|
||||
/* Don't escape '[' and '{' if they are in 'isfname'. */
|
||||
for (p = PATH_ESC_CHARS; *p != NUL; ++p)
|
||||
if ((*p != '[' && *p != '{') || !vim_isfilec(*p))
|
||||
buf[j++] = *p;
|
||||
buf[j] = NUL;
|
||||
p = vim_strsave_escaped(files[i], buf);
|
||||
}
|
||||
p = vim_strsave_fnameescape(files[i], FALSE);
|
||||
#else
|
||||
p = vim_strsave_escaped(files[i],
|
||||
xp->xp_shell ? SHELL_ESC_CHARS : PATH_ESC_CHARS);
|
||||
p = vim_strsave_fnameescape(files[i], xp->xp_shell);
|
||||
#endif
|
||||
if (p != NULL)
|
||||
{
|
||||
@@ -3709,6 +3698,32 @@ ExpandEscape(xp, str, numfiles, files, options)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Escape special characters in "fname" for when used as a file name argument
|
||||
* after a Vim command, or, when "shell" is non-zero, a shell command.
|
||||
* Returns the result in allocated memory.
|
||||
*/
|
||||
char_u *
|
||||
vim_strsave_fnameescape(fname, shell)
|
||||
char_u *fname;
|
||||
int shell;
|
||||
{
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
char_u buf[20];
|
||||
int j = 0;
|
||||
char_u *p;
|
||||
|
||||
/* Don't escape '[' and '{' if they are in 'isfname'. */
|
||||
for (p = PATH_ESC_CHARS; *p != NUL; ++p)
|
||||
if ((*p != '[' && *p != '{') || !vim_isfilec(*p))
|
||||
buf[j++] = *p;
|
||||
buf[j] = NUL;
|
||||
return vim_strsave_escaped(fname, buf);
|
||||
#else
|
||||
return vim_strsave_escaped(fname, shell ? SHELL_ESC_CHARS : PATH_ESC_CHARS);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Put a backslash before the file name in "pp", which is in allocated memory.
|
||||
*/
|
||||
|
||||
+80
-44
@@ -1288,12 +1288,49 @@ retry:
|
||||
#ifdef FEAT_MBYTE
|
||||
else if (conv_restlen > 0)
|
||||
{
|
||||
/* Reached end-of-file but some trailing bytes could
|
||||
* not be converted. Truncated file? */
|
||||
if (conv_error == 0)
|
||||
conv_error = linecnt;
|
||||
if (bad_char_behavior != BAD_DROP)
|
||||
/*
|
||||
* Reached end-of-file but some trailing bytes could
|
||||
* not be converted. Truncated file?
|
||||
*/
|
||||
|
||||
/* When we did a conversion report an error. */
|
||||
if (fio_flags != 0
|
||||
# ifdef USE_ICONV
|
||||
|| iconv_fd != (iconv_t)-1
|
||||
# endif
|
||||
)
|
||||
{
|
||||
if (conv_error == 0)
|
||||
conv_error = curbuf->b_ml.ml_line_count
|
||||
- linecnt + 1;
|
||||
}
|
||||
/* Remember the first linenr with an illegal byte */
|
||||
else if (illegal_byte == 0)
|
||||
illegal_byte = curbuf->b_ml.ml_line_count
|
||||
- linecnt + 1;
|
||||
if (bad_char_behavior == BAD_DROP)
|
||||
{
|
||||
*(ptr - conv_restlen) = NUL;
|
||||
conv_restlen = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Replace the trailing bytes with the replacement
|
||||
* character if we were converting; if we weren't,
|
||||
* leave the UTF8 checking code to do it, as it
|
||||
* works slightly differently. */
|
||||
if (bad_char_behavior != BAD_KEEP && (fio_flags != 0
|
||||
# ifdef USE_ICONV
|
||||
|| iconv_fd != (iconv_t)-1
|
||||
# endif
|
||||
))
|
||||
{
|
||||
while (conv_restlen > 0)
|
||||
{
|
||||
*(--ptr) = bad_char_behavior;
|
||||
--conv_restlen;
|
||||
}
|
||||
}
|
||||
fio_flags = 0; /* don't convert this */
|
||||
# ifdef USE_ICONV
|
||||
if (iconv_fd != (iconv_t)-1)
|
||||
@@ -1302,20 +1339,6 @@ retry:
|
||||
iconv_fd = (iconv_t)-1;
|
||||
}
|
||||
# endif
|
||||
if (bad_char_behavior == BAD_KEEP)
|
||||
{
|
||||
/* Keep the trailing bytes as-is. */
|
||||
size = conv_restlen;
|
||||
ptr -= conv_restlen;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Replace the trailing bytes with the
|
||||
* replacement character. */
|
||||
size = 1;
|
||||
*--ptr = bad_char_behavior;
|
||||
}
|
||||
conv_restlen = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1397,6 +1420,11 @@ retry:
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
/* Include not converted bytes. */
|
||||
ptr -= conv_restlen;
|
||||
size += conv_restlen;
|
||||
conv_restlen = 0;
|
||||
#endif
|
||||
/*
|
||||
* Break here for a read error or end-of-file.
|
||||
@@ -1406,11 +1434,6 @@ retry:
|
||||
|
||||
#ifdef FEAT_MBYTE
|
||||
|
||||
/* Include not converted bytes. */
|
||||
ptr -= conv_restlen;
|
||||
size += conv_restlen;
|
||||
conv_restlen = 0;
|
||||
|
||||
# ifdef USE_ICONV
|
||||
if (iconv_fd != (iconv_t)-1)
|
||||
{
|
||||
@@ -1872,12 +1895,12 @@ retry:
|
||||
size = (long)((ptr + real_size) - dest);
|
||||
ptr = dest;
|
||||
}
|
||||
else if (enc_utf8 && conv_error == 0 && !curbuf->b_p_bin)
|
||||
else if (enc_utf8 && !curbuf->b_p_bin)
|
||||
{
|
||||
/* Reading UTF-8: Check if the bytes are valid UTF-8.
|
||||
* Need to start before "ptr" when part of the character was
|
||||
* read in the previous read() call. */
|
||||
for (p = ptr - utf_head_off(buffer, ptr); ; ++p)
|
||||
int incomplete_tail = FALSE;
|
||||
|
||||
/* Reading UTF-8: Check if the bytes are valid UTF-8. */
|
||||
for (p = ptr; ; ++p)
|
||||
{
|
||||
int todo = (int)((ptr + size) - p);
|
||||
int l;
|
||||
@@ -1891,43 +1914,56 @@ retry:
|
||||
* read() will get the next bytes, we'll check it
|
||||
* then. */
|
||||
l = utf_ptr2len_len(p, todo);
|
||||
if (l > todo)
|
||||
if (l > todo && !incomplete_tail)
|
||||
{
|
||||
/* Incomplete byte sequence, the next read()
|
||||
* should get them and check the bytes. */
|
||||
p += todo;
|
||||
break;
|
||||
/* Avoid retrying with a different encoding when
|
||||
* a truncated file is more likely, or attempting
|
||||
* to read the rest of an incomplete sequence when
|
||||
* we have already done so. */
|
||||
if (p > ptr || filesize > 0)
|
||||
incomplete_tail = TRUE;
|
||||
/* Incomplete byte sequence, move it to conv_rest[]
|
||||
* and try to read the rest of it, unless we've
|
||||
* already done so. */
|
||||
if (p > ptr)
|
||||
{
|
||||
conv_restlen = todo;
|
||||
mch_memmove(conv_rest, p, conv_restlen);
|
||||
size -= conv_restlen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (l == 1)
|
||||
if (l == 1 || l > todo)
|
||||
{
|
||||
/* Illegal byte. If we can try another encoding
|
||||
* do that. */
|
||||
if (can_retry)
|
||||
* do that, unless at EOF where a truncated
|
||||
* file is more likely than a conversion error. */
|
||||
if (can_retry && !incomplete_tail)
|
||||
break;
|
||||
|
||||
/* Remember the first linenr with an illegal byte */
|
||||
if (illegal_byte == 0)
|
||||
illegal_byte = readfile_linenr(linecnt, ptr, p);
|
||||
# ifdef USE_ICONV
|
||||
/* When we did a conversion report an error. */
|
||||
if (iconv_fd != (iconv_t)-1 && conv_error == 0)
|
||||
conv_error = readfile_linenr(linecnt, ptr, p);
|
||||
# endif
|
||||
/* Remember the first linenr with an illegal byte */
|
||||
if (conv_error == 0 && illegal_byte == 0)
|
||||
illegal_byte = readfile_linenr(linecnt, ptr, p);
|
||||
|
||||
/* Drop, keep or replace the bad byte. */
|
||||
if (bad_char_behavior == BAD_DROP)
|
||||
{
|
||||
mch_memmove(p, p+1, todo - 1);
|
||||
mch_memmove(p, p + 1, todo - 1);
|
||||
--p;
|
||||
--size;
|
||||
}
|
||||
else if (bad_char_behavior != BAD_KEEP)
|
||||
*p = bad_char_behavior;
|
||||
}
|
||||
p += l - 1;
|
||||
else
|
||||
p += l - 1;
|
||||
}
|
||||
}
|
||||
if (p < ptr + size)
|
||||
if (p < ptr + size && !incomplete_tail)
|
||||
{
|
||||
/* Detected a UTF-8 error. */
|
||||
rewind_retry:
|
||||
|
||||
+115
-87
@@ -38,6 +38,8 @@
|
||||
# undef HAVE_STDARG_H /* Python's config.h defines it as well. */
|
||||
#endif
|
||||
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
|
||||
#include <Python.h>
|
||||
#if defined(MACOS) && !defined(MACOS_X_UNIX)
|
||||
# include "macglue.h"
|
||||
@@ -55,6 +57,22 @@ struct PyMethodDef { int a; };
|
||||
# define PySequenceMethods int
|
||||
#endif
|
||||
|
||||
#if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02050000
|
||||
# define PyInt Py_ssize_t
|
||||
# define PyInquiry lenfunc
|
||||
# define PyIntArgFunc ssizeargfunc
|
||||
# define PyIntIntArgFunc ssizessizeargfunc
|
||||
# define PyIntObjArgProc ssizeobjargproc
|
||||
# define PyIntIntObjArgProc ssizessizeobjargproc
|
||||
#else
|
||||
# define PyInt int
|
||||
# define PyInquiry inquiry
|
||||
# define PyIntArgFunc intargfunc
|
||||
# define PyIntIntArgFunc intintargfunc
|
||||
# define PyIntObjArgProc intobjargproc
|
||||
# define PyIntIntObjArgProc intintobjargproc
|
||||
#endif
|
||||
|
||||
/* Parser flags */
|
||||
#define single_input 256
|
||||
#define file_input 257
|
||||
@@ -150,11 +168,11 @@ static void (*dll_PyGILState_Release)(PyGILState_STATE);
|
||||
static long(*dll_PyInt_AsLong)(PyObject *);
|
||||
static PyObject*(*dll_PyInt_FromLong)(long);
|
||||
static PyTypeObject* dll_PyInt_Type;
|
||||
static PyObject*(*dll_PyList_GetItem)(PyObject *, int);
|
||||
static PyObject*(*dll_PyList_GetItem)(PyObject *, PyInt);
|
||||
static PyObject*(*dll_PyList_Append)(PyObject *, PyObject *);
|
||||
static PyObject*(*dll_PyList_New)(int size);
|
||||
static int(*dll_PyList_SetItem)(PyObject *, int, PyObject *);
|
||||
static int(*dll_PyList_Size)(PyObject *);
|
||||
static PyObject*(*dll_PyList_New)(PyInt size);
|
||||
static int(*dll_PyList_SetItem)(PyObject *, PyInt, PyObject *);
|
||||
static PyInt(*dll_PyList_Size)(PyObject *);
|
||||
static PyTypeObject* dll_PyList_Type;
|
||||
static PyObject*(*dll_PyImport_ImportModule)(const char *);
|
||||
static PyObject*(*dll_PyDict_New)(void);
|
||||
@@ -163,8 +181,8 @@ static PyObject*(*dll_PyModule_GetDict)(PyObject *);
|
||||
static int(*dll_PyRun_SimpleString)(char *);
|
||||
static char*(*dll_PyString_AsString)(PyObject *);
|
||||
static PyObject*(*dll_PyString_FromString)(const char *);
|
||||
static PyObject*(*dll_PyString_FromStringAndSize)(const char *, int);
|
||||
static int(*dll_PyString_Size)(PyObject *);
|
||||
static PyObject*(*dll_PyString_FromStringAndSize)(const char *, PyInt);
|
||||
static PyInt(*dll_PyString_Size)(PyObject *);
|
||||
static PyTypeObject* dll_PyString_Type;
|
||||
static int(*dll_PySys_SetObject)(char *, PyObject *);
|
||||
static int(*dll_PySys_SetArgv)(int, char **);
|
||||
@@ -367,10 +385,10 @@ static int PythonMod_Init(void);
|
||||
* ----------------------------------------------
|
||||
*/
|
||||
static PyObject *GetBufferLine(buf_T *, int);
|
||||
static PyObject *GetBufferLineList(buf_T *, int, int);
|
||||
static PyObject *GetBufferLineList(buf_T *, PyInt, PyInt);
|
||||
|
||||
static int SetBufferLine(buf_T *, int, PyObject *, int *);
|
||||
static int SetBufferLineList(buf_T *, int, int, PyObject *, int *);
|
||||
static int SetBufferLineList(buf_T *, PyInt, PyInt, PyObject *, int *);
|
||||
static int InsertBufferLines(buf_T *, int, PyObject *, int *);
|
||||
|
||||
static PyObject *LineToString(const char *);
|
||||
@@ -773,8 +791,8 @@ OutputWrite(PyObject *self, PyObject *args)
|
||||
static PyObject *
|
||||
OutputWritelines(PyObject *self, PyObject *args)
|
||||
{
|
||||
int n;
|
||||
int i;
|
||||
PyInt n;
|
||||
PyInt i;
|
||||
PyObject *list;
|
||||
int error = ((OutputObject *)(self))->error;
|
||||
|
||||
@@ -986,11 +1004,11 @@ static void BufferDestructor(PyObject *);
|
||||
static PyObject *BufferGetattr(PyObject *, char *);
|
||||
static PyObject *BufferRepr(PyObject *);
|
||||
|
||||
static int BufferLength(PyObject *);
|
||||
static PyObject *BufferItem(PyObject *, int);
|
||||
static PyObject *BufferSlice(PyObject *, int, int);
|
||||
static int BufferAssItem(PyObject *, int, PyObject *);
|
||||
static int BufferAssSlice(PyObject *, int, int, PyObject *);
|
||||
static PyInt BufferLength(PyObject *);
|
||||
static PyObject *BufferItem(PyObject *, PyInt);
|
||||
static PyObject *BufferSlice(PyObject *, PyInt, PyInt);
|
||||
static PyInt BufferAssItem(PyObject *, PyInt, PyObject *);
|
||||
static PyInt BufferAssSlice(PyObject *, PyInt, PyInt, PyObject *);
|
||||
|
||||
static PyObject *BufferAppend(PyObject *, PyObject *);
|
||||
static PyObject *BufferMark(PyObject *, PyObject *);
|
||||
@@ -1017,11 +1035,11 @@ static void RangeDestructor(PyObject *);
|
||||
static PyObject *RangeGetattr(PyObject *, char *);
|
||||
static PyObject *RangeRepr(PyObject *);
|
||||
|
||||
static int RangeLength(PyObject *);
|
||||
static PyObject *RangeItem(PyObject *, int);
|
||||
static PyObject *RangeSlice(PyObject *, int, int);
|
||||
static int RangeAssItem(PyObject *, int, PyObject *);
|
||||
static int RangeAssSlice(PyObject *, int, int, PyObject *);
|
||||
static PyInt RangeLength(PyObject *);
|
||||
static PyObject *RangeItem(PyObject *, PyInt);
|
||||
static PyObject *RangeSlice(PyObject *, PyInt, PyInt);
|
||||
static PyInt RangeAssItem(PyObject *, PyInt, PyObject *);
|
||||
static PyInt RangeAssSlice(PyObject *, PyInt, PyInt, PyObject *);
|
||||
|
||||
static PyObject *RangeAppend(PyObject *, PyObject *);
|
||||
|
||||
@@ -1029,15 +1047,15 @@ static PyObject *RangeAppend(PyObject *, PyObject *);
|
||||
* -------------------------------------------
|
||||
*/
|
||||
|
||||
static int WinListLength(PyObject *);
|
||||
static PyObject *WinListItem(PyObject *, int);
|
||||
static PyInt WinListLength(PyObject *);
|
||||
static PyObject *WinListItem(PyObject *, PyInt);
|
||||
|
||||
/* Buffer list type - Implementation functions
|
||||
* -------------------------------------------
|
||||
*/
|
||||
|
||||
static int BufListLength(PyObject *);
|
||||
static PyObject *BufListItem(PyObject *, int);
|
||||
static PyInt BufListLength(PyObject *);
|
||||
static PyObject *BufListItem(PyObject *, PyInt);
|
||||
|
||||
/* Current objects type - Implementation functions
|
||||
* -----------------------------------------------
|
||||
@@ -1130,6 +1148,16 @@ VimToPython(typval_T *our_tv, int depth, PyObject *lookupDict)
|
||||
result = Py_BuildValue("s", buf);
|
||||
PyDict_SetItemString(lookupDict, ptrBuf, result);
|
||||
}
|
||||
#ifdef FEAT_FLOAT
|
||||
else if (our_tv->v_type == VAR_FLOAT)
|
||||
{
|
||||
char buf[NUMBUFLEN];
|
||||
|
||||
sprintf(buf, "%f", our_tv->vval.v_float);
|
||||
result = Py_BuildValue("s", buf);
|
||||
PyDict_SetItemString(lookupDict, ptrBuf, result);
|
||||
}
|
||||
#endif
|
||||
else if (our_tv->v_type == VAR_LIST)
|
||||
{
|
||||
list_T *list = our_tv->vval.v_list;
|
||||
@@ -1245,7 +1273,7 @@ CheckBuffer(BufferObject *this)
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
RBItem(BufferObject *self, int n, int start, int end)
|
||||
RBItem(BufferObject *self, PyInt n, int start, int end)
|
||||
{
|
||||
if (CheckBuffer(self))
|
||||
return NULL;
|
||||
@@ -1260,9 +1288,9 @@ RBItem(BufferObject *self, int n, int start, int end)
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
RBSlice(BufferObject *self, int lo, int hi, int start, int end)
|
||||
RBSlice(BufferObject *self, PyInt lo, PyInt hi, int start, int end)
|
||||
{
|
||||
int size;
|
||||
PyInt size;
|
||||
|
||||
if (CheckBuffer(self))
|
||||
return NULL;
|
||||
@@ -1283,8 +1311,8 @@ RBSlice(BufferObject *self, int lo, int hi, int start, int end)
|
||||
return GetBufferLineList(self->buf, lo+start, hi+start);
|
||||
}
|
||||
|
||||
static int
|
||||
RBAssItem(BufferObject *self, int n, PyObject *val, int start, int end, int *new_end)
|
||||
static PyInt
|
||||
RBAssItem(BufferObject *self, PyInt n, PyObject *val, int start, int end, int *new_end)
|
||||
{
|
||||
int len_change;
|
||||
|
||||
@@ -1306,8 +1334,8 @@ RBAssItem(BufferObject *self, int n, PyObject *val, int start, int end, int *new
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
RBAssSlice(BufferObject *self, int lo, int hi, PyObject *val, int start, int end, int *new_end)
|
||||
static PyInt
|
||||
RBAssSlice(BufferObject *self, PyInt lo, PyInt hi, PyObject *val, int start, int end, int *new_end)
|
||||
{
|
||||
int size;
|
||||
int len_change;
|
||||
@@ -1384,13 +1412,13 @@ static struct PyMethodDef BufferMethods[] = {
|
||||
};
|
||||
|
||||
static PySequenceMethods BufferAsSeq = {
|
||||
(inquiry) BufferLength, /* sq_length, len(x) */
|
||||
(PyInquiry) BufferLength, /* sq_length, len(x) */
|
||||
(binaryfunc) 0, /* BufferConcat, */ /* sq_concat, x+y */
|
||||
(intargfunc) 0, /* BufferRepeat, */ /* sq_repeat, x*n */
|
||||
(intargfunc) BufferItem, /* sq_item, x[i] */
|
||||
(intintargfunc) BufferSlice, /* sq_slice, x[i:j] */
|
||||
(intobjargproc) BufferAssItem, /* sq_ass_item, x[i]=v */
|
||||
(intintobjargproc) BufferAssSlice, /* sq_ass_slice, x[i:j]=v */
|
||||
(PyIntArgFunc) 0, /* BufferRepeat, */ /* sq_repeat, x*n */
|
||||
(PyIntArgFunc) BufferItem, /* sq_item, x[i] */
|
||||
(PyIntIntArgFunc) BufferSlice, /* sq_slice, x[i:j] */
|
||||
(PyIntObjArgProc) BufferAssItem, /* sq_ass_item, x[i]=v */
|
||||
(PyIntIntObjArgProc) BufferAssSlice, /* sq_ass_slice, x[i:j]=v */
|
||||
};
|
||||
|
||||
static PyTypeObject BufferType = {
|
||||
@@ -1516,7 +1544,7 @@ BufferRepr(PyObject *self)
|
||||
|
||||
/******************/
|
||||
|
||||
static int
|
||||
static PyInt
|
||||
BufferLength(PyObject *self)
|
||||
{
|
||||
/* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
|
||||
@@ -1527,29 +1555,29 @@ BufferLength(PyObject *self)
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
BufferItem(PyObject *self, int n)
|
||||
BufferItem(PyObject *self, PyInt n)
|
||||
{
|
||||
return RBItem((BufferObject *)(self), n, 1,
|
||||
(int)((BufferObject *)(self))->buf->b_ml.ml_line_count);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
BufferSlice(PyObject *self, int lo, int hi)
|
||||
BufferSlice(PyObject *self, PyInt lo, PyInt hi)
|
||||
{
|
||||
return RBSlice((BufferObject *)(self), lo, hi, 1,
|
||||
(int)((BufferObject *)(self))->buf->b_ml.ml_line_count);
|
||||
}
|
||||
|
||||
static int
|
||||
BufferAssItem(PyObject *self, int n, PyObject *val)
|
||||
static PyInt
|
||||
BufferAssItem(PyObject *self, PyInt n, PyObject *val)
|
||||
{
|
||||
return RBAssItem((BufferObject *)(self), n, val, 1,
|
||||
(int)((BufferObject *)(self))->buf->b_ml.ml_line_count,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
BufferAssSlice(PyObject *self, int lo, int hi, PyObject *val)
|
||||
static PyInt
|
||||
BufferAssSlice(PyObject *self, PyInt lo, PyInt hi, PyObject *val)
|
||||
{
|
||||
return RBAssSlice((BufferObject *)(self), lo, hi, val, 1,
|
||||
(int)((BufferObject *)(self))->buf->b_ml.ml_line_count,
|
||||
@@ -1627,13 +1655,13 @@ static struct PyMethodDef RangeMethods[] = {
|
||||
};
|
||||
|
||||
static PySequenceMethods RangeAsSeq = {
|
||||
(inquiry) RangeLength, /* sq_length, len(x) */
|
||||
(PyInquiry) RangeLength, /* sq_length, len(x) */
|
||||
(binaryfunc) 0, /* RangeConcat, */ /* sq_concat, x+y */
|
||||
(intargfunc) 0, /* RangeRepeat, */ /* sq_repeat, x*n */
|
||||
(intargfunc) RangeItem, /* sq_item, x[i] */
|
||||
(intintargfunc) RangeSlice, /* sq_slice, x[i:j] */
|
||||
(intobjargproc) RangeAssItem, /* sq_ass_item, x[i]=v */
|
||||
(intintobjargproc) RangeAssSlice, /* sq_ass_slice, x[i:j]=v */
|
||||
(PyIntArgFunc) 0, /* RangeRepeat, */ /* sq_repeat, x*n */
|
||||
(PyIntArgFunc) RangeItem, /* sq_item, x[i] */
|
||||
(PyIntIntArgFunc) RangeSlice, /* sq_slice, x[i:j] */
|
||||
(PyIntObjArgProc) RangeAssItem, /* sq_ass_item, x[i]=v */
|
||||
(PyIntIntObjArgProc) RangeAssSlice, /* sq_ass_slice, x[i:j]=v */
|
||||
};
|
||||
|
||||
static PyTypeObject RangeType = {
|
||||
@@ -1738,7 +1766,7 @@ RangeRepr(PyObject *self)
|
||||
|
||||
/****************/
|
||||
|
||||
static int
|
||||
static PyInt
|
||||
RangeLength(PyObject *self)
|
||||
{
|
||||
/* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
|
||||
@@ -1749,7 +1777,7 @@ RangeLength(PyObject *self)
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
RangeItem(PyObject *self, int n)
|
||||
RangeItem(PyObject *self, PyInt n)
|
||||
{
|
||||
return RBItem(((RangeObject *)(self))->buf, n,
|
||||
((RangeObject *)(self))->start,
|
||||
@@ -1757,15 +1785,15 @@ RangeItem(PyObject *self, int n)
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
RangeSlice(PyObject *self, int lo, int hi)
|
||||
RangeSlice(PyObject *self, PyInt lo, PyInt hi)
|
||||
{
|
||||
return RBSlice(((RangeObject *)(self))->buf, lo, hi,
|
||||
((RangeObject *)(self))->start,
|
||||
((RangeObject *)(self))->end);
|
||||
}
|
||||
|
||||
static int
|
||||
RangeAssItem(PyObject *self, int n, PyObject *val)
|
||||
static PyInt
|
||||
RangeAssItem(PyObject *self, PyInt n, PyObject *val)
|
||||
{
|
||||
return RBAssItem(((RangeObject *)(self))->buf, n, val,
|
||||
((RangeObject *)(self))->start,
|
||||
@@ -1773,8 +1801,8 @@ RangeAssItem(PyObject *self, int n, PyObject *val)
|
||||
&((RangeObject *)(self))->end);
|
||||
}
|
||||
|
||||
static int
|
||||
RangeAssSlice(PyObject *self, int lo, int hi, PyObject *val)
|
||||
static PyInt
|
||||
RangeAssSlice(PyObject *self, PyInt lo, PyInt hi, PyObject *val)
|
||||
{
|
||||
return RBAssSlice(((RangeObject *)(self))->buf, lo, hi, val,
|
||||
((RangeObject *)(self))->start,
|
||||
@@ -1801,13 +1829,13 @@ typedef struct
|
||||
BufListObject;
|
||||
|
||||
static PySequenceMethods BufListAsSeq = {
|
||||
(inquiry) BufListLength, /* sq_length, len(x) */
|
||||
(PyInquiry) BufListLength, /* sq_length, len(x) */
|
||||
(binaryfunc) 0, /* sq_concat, x+y */
|
||||
(intargfunc) 0, /* sq_repeat, x*n */
|
||||
(intargfunc) BufListItem, /* sq_item, x[i] */
|
||||
(intintargfunc) 0, /* sq_slice, x[i:j] */
|
||||
(intobjargproc) 0, /* sq_ass_item, x[i]=v */
|
||||
(intintobjargproc) 0, /* sq_ass_slice, x[i:j]=v */
|
||||
(PyIntArgFunc) 0, /* sq_repeat, x*n */
|
||||
(PyIntArgFunc) BufListItem, /* sq_item, x[i] */
|
||||
(PyIntIntArgFunc) 0, /* sq_slice, x[i:j] */
|
||||
(PyIntObjArgProc) 0, /* sq_ass_item, x[i]=v */
|
||||
(PyIntIntObjArgProc) 0, /* sq_ass_slice, x[i:j]=v */
|
||||
};
|
||||
|
||||
static PyTypeObject BufListType = {
|
||||
@@ -1837,7 +1865,7 @@ static PyTypeObject BufListType = {
|
||||
*/
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
static PyInt
|
||||
BufListLength(PyObject *self)
|
||||
{
|
||||
buf_T *b = firstbuf;
|
||||
@@ -1854,7 +1882,7 @@ BufListLength(PyObject *self)
|
||||
|
||||
/*ARGSUSED*/
|
||||
static PyObject *
|
||||
BufListItem(PyObject *self, int n)
|
||||
BufListItem(PyObject *self, PyInt n)
|
||||
{
|
||||
buf_T *b;
|
||||
|
||||
@@ -2119,13 +2147,13 @@ typedef struct
|
||||
WinListObject;
|
||||
|
||||
static PySequenceMethods WinListAsSeq = {
|
||||
(inquiry) WinListLength, /* sq_length, len(x) */
|
||||
(PyInquiry) WinListLength, /* sq_length, len(x) */
|
||||
(binaryfunc) 0, /* sq_concat, x+y */
|
||||
(intargfunc) 0, /* sq_repeat, x*n */
|
||||
(intargfunc) WinListItem, /* sq_item, x[i] */
|
||||
(intintargfunc) 0, /* sq_slice, x[i:j] */
|
||||
(intobjargproc) 0, /* sq_ass_item, x[i]=v */
|
||||
(intintobjargproc) 0, /* sq_ass_slice, x[i:j]=v */
|
||||
(PyIntArgFunc) 0, /* sq_repeat, x*n */
|
||||
(PyIntArgFunc) WinListItem, /* sq_item, x[i] */
|
||||
(PyIntIntArgFunc) 0, /* sq_slice, x[i:j] */
|
||||
(PyIntObjArgProc) 0, /* sq_ass_item, x[i]=v */
|
||||
(PyIntIntObjArgProc) 0, /* sq_ass_slice, x[i:j]=v */
|
||||
};
|
||||
|
||||
static PyTypeObject WinListType = {
|
||||
@@ -2154,7 +2182,7 @@ static PyTypeObject WinListType = {
|
||||
/* Window list object - Implementation
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
static PyInt
|
||||
WinListLength(PyObject *self)
|
||||
{
|
||||
win_T *w = firstwin;
|
||||
@@ -2171,7 +2199,7 @@ WinListLength(PyObject *self)
|
||||
|
||||
/*ARGSUSED*/
|
||||
static PyObject *
|
||||
WinListItem(PyObject *self, int n)
|
||||
WinListItem(PyObject *self, PyInt n)
|
||||
{
|
||||
win_T *w;
|
||||
|
||||
@@ -2351,10 +2379,10 @@ GetBufferLine(buf_T *buf, int n)
|
||||
* including, hi. The list is returned as a Python list of string objects.
|
||||
*/
|
||||
static PyObject *
|
||||
GetBufferLineList(buf_T *buf, int lo, int hi)
|
||||
GetBufferLineList(buf_T *buf, PyInt lo, PyInt hi)
|
||||
{
|
||||
int i;
|
||||
int n = hi - lo;
|
||||
PyInt i;
|
||||
PyInt n = hi - lo;
|
||||
PyObject *list = PyList_New(n);
|
||||
|
||||
if (list == NULL)
|
||||
@@ -2517,7 +2545,7 @@ SetBufferLine(buf_T *buf, int n, PyObject *line, int *len_change)
|
||||
* is set to the change in the buffer length.
|
||||
*/
|
||||
static int
|
||||
SetBufferLineList(buf_T *buf, int lo, int hi, PyObject *list, int *len_change)
|
||||
SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, int *len_change)
|
||||
{
|
||||
/* First of all, we check the thpe of the supplied Python object.
|
||||
* There are three cases:
|
||||
@@ -2527,8 +2555,8 @@ SetBufferLineList(buf_T *buf, int lo, int hi, PyObject *list, int *len_change)
|
||||
*/
|
||||
if (list == Py_None || list == NULL)
|
||||
{
|
||||
int i;
|
||||
int n = hi - lo;
|
||||
PyInt i;
|
||||
PyInt n = hi - lo;
|
||||
buf_T *savebuf = curbuf;
|
||||
|
||||
PyErr_Clear();
|
||||
@@ -2564,9 +2592,9 @@ SetBufferLineList(buf_T *buf, int lo, int hi, PyObject *list, int *len_change)
|
||||
}
|
||||
else if (PyList_Check(list))
|
||||
{
|
||||
int i;
|
||||
int new_len = PyList_Size(list);
|
||||
int old_len = hi - lo;
|
||||
PyInt i;
|
||||
PyInt new_len = PyList_Size(list);
|
||||
PyInt old_len = hi - lo;
|
||||
int extra = 0; /* lines added to text, can be negative */
|
||||
char **array;
|
||||
buf_T *savebuf;
|
||||
@@ -2745,8 +2773,8 @@ InsertBufferLines(buf_T *buf, int n, PyObject *lines, int *len_change)
|
||||
}
|
||||
else if (PyList_Check(lines))
|
||||
{
|
||||
int i;
|
||||
int size = PyList_Size(lines);
|
||||
PyInt i;
|
||||
PyInt size = PyList_Size(lines);
|
||||
char **array;
|
||||
buf_T *savebuf;
|
||||
|
||||
@@ -2831,7 +2859,7 @@ InsertBufferLines(buf_T *buf, int n, PyObject *lines, int *len_change)
|
||||
LineToString(const char *str)
|
||||
{
|
||||
PyObject *result;
|
||||
int len = strlen(str);
|
||||
PyInt len = strlen(str);
|
||||
char *p;
|
||||
|
||||
/* Allocate an Python string object, with uninitialised contents. We
|
||||
@@ -2871,8 +2899,8 @@ StringToLine(PyObject *obj)
|
||||
{
|
||||
const char *str;
|
||||
char *save;
|
||||
int len;
|
||||
int i;
|
||||
PyInt len;
|
||||
PyInt i;
|
||||
char *p;
|
||||
|
||||
if (obj == NULL || !PyString_Check(obj))
|
||||
|
||||
+9
-6
@@ -1973,8 +1973,10 @@ utf_class(c)
|
||||
{0x205f, 0x205f, 0},
|
||||
{0x2060, 0x27ff, 1}, /* punctuation and symbols */
|
||||
{0x2070, 0x207f, 0x2070}, /* superscript */
|
||||
{0x2080, 0x208f, 0x2080}, /* subscript */
|
||||
{0x2983, 0x2998, 1},
|
||||
{0x2080, 0x2094, 0x2080}, /* subscript */
|
||||
{0x20a0, 0x27ff, 1}, /* all kinds of symbols */
|
||||
{0x2800, 0x28ff, 0x2800}, /* braille */
|
||||
{0x2900, 0x2998, 1}, /* arrows, brackets, etc. */
|
||||
{0x29d8, 0x29db, 1},
|
||||
{0x29fc, 0x29fd, 1},
|
||||
{0x3000, 0x3000, 0}, /* ideographic space */
|
||||
@@ -5518,13 +5520,13 @@ preedit_callback_setup(GdkIC *ic)
|
||||
preedit_caret_cb.callback = (XIMProc)preedit_caret_cbproc;
|
||||
preedit_done_cb.callback = (XIMProc)preedit_done_cbproc;
|
||||
preedit_attr
|
||||
= XVaCreateNestedList (0,
|
||||
= XVaCreateNestedList(0,
|
||||
XNPreeditStartCallback, &preedit_start_cb,
|
||||
XNPreeditDrawCallback, &preedit_draw_cb,
|
||||
XNPreeditCaretCallback, &preedit_caret_cb,
|
||||
XNPreeditDoneCallback, &preedit_done_cb,
|
||||
0);
|
||||
XSetICValues (xxic, XNPreeditAttributes, preedit_attr, 0);
|
||||
NULL);
|
||||
XSetICValues(xxic, XNPreeditAttributes, preedit_attr, NULL);
|
||||
XFree(preedit_attr);
|
||||
}
|
||||
|
||||
@@ -5534,7 +5536,8 @@ reset_state_setup(GdkIC *ic)
|
||||
{
|
||||
#ifdef USE_X11R6_XIM
|
||||
/* don't change the input context when we call reset */
|
||||
XSetICValues(((GdkICPrivate*)ic)->xic, XNResetState, XIMPreserveState, 0);
|
||||
XSetICValues(((GdkICPrivate *)ic)->xic, XNResetState, XIMPreserveState,
|
||||
NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ char_u *ExpandOne __ARGS((expand_T *xp, char_u *str, char_u *orig, int options,
|
||||
void ExpandInit __ARGS((expand_T *xp));
|
||||
void ExpandCleanup __ARGS((expand_T *xp));
|
||||
void ExpandEscape __ARGS((expand_T *xp, char_u *str, int numfiles, char_u **files, int options));
|
||||
char_u *vim_strsave_fnameescape __ARGS((char_u *fname, int shell));
|
||||
void tilde_replace __ARGS((char_u *orig_pat, int num_files, char_u **files));
|
||||
char_u *sm_gettail __ARGS((char_u *s));
|
||||
char_u *addstar __ARGS((char_u *fname, int len, int context));
|
||||
|
||||
@@ -9357,6 +9357,11 @@ showruler(always)
|
||||
)
|
||||
maketitle();
|
||||
#endif
|
||||
#ifdef FEAT_WINDOWS
|
||||
/* Redraw the tab pages line if needed. */
|
||||
if (redraw_tabline)
|
||||
draw_tabline();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef FEAT_CMDL_INFO
|
||||
|
||||
@@ -681,6 +681,32 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
311,
|
||||
/**/
|
||||
310,
|
||||
/**/
|
||||
309,
|
||||
/**/
|
||||
308,
|
||||
/**/
|
||||
307,
|
||||
/**/
|
||||
306,
|
||||
/**/
|
||||
305,
|
||||
/**/
|
||||
304,
|
||||
/**/
|
||||
303,
|
||||
/**/
|
||||
302,
|
||||
/**/
|
||||
301,
|
||||
/**/
|
||||
300,
|
||||
/**/
|
||||
299,
|
||||
/**/
|
||||
298,
|
||||
/**/
|
||||
|
||||
@@ -337,10 +337,10 @@
|
||||
# endif
|
||||
#endif
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
# define PATH_ESC_CHARS ((char_u *)" \t*?[{`%#")
|
||||
# define PATH_ESC_CHARS ((char_u *)" \t\n*?[{`%#'\"|!<")
|
||||
#else
|
||||
# define PATH_ESC_CHARS ((char_u *)" \t*?[{`$\\%#'\"|")
|
||||
# define SHELL_ESC_CHARS ((char_u *)" \t*?[{`$\\%#'\"|<>();&!")
|
||||
# define PATH_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<")
|
||||
# define SHELL_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<>();&")
|
||||
#endif
|
||||
|
||||
#define NUMBUFLEN 30 /* length of a buffer to store a number in ASCII */
|
||||
|
||||
Reference in New Issue
Block a user