Compare commits

...

51 Commits

Author SHA1 Message Date
Bjorn Winckler bf70f82498 Snapshot 29 2008-06-08 14:21:16 +02:00
Bjorn Winckler 89d9e60b8a Add 'rightleft' support to ATSUI renderer 2008-06-07 15:36:07 +02:00
Bjorn Winckler 0ea7546c7c Add 'mousehide' option support 2008-06-07 15:35:25 +02:00
Bjorn Winckler 321fdf61aa Ensure processCommandQueueDidFinish: gets called if exception is raised 2008-06-07 14:33:05 +02:00
Bjorn Winckler 2fa74c01aa Use -[NSScreen visibleFrame] to get full-screen max dimensions
This fixes a bug where the window dimensions were not restored after
leaving full-screen (with 'maxvert' fu-option set).
2008-06-07 14:30:52 +02:00
Bjorn Winckler c4222c6ebb Don't delay loading "Buffers" menu
This avoids a flickering menu each time a new editor window is opened.
2008-06-07 12:42:47 +02:00
Bjorn Winckler 1f538dc364 Set title for separator items to ensure valid descriptors 2008-06-06 23:32:26 +02:00
Bjorn Winckler 9471224d0b Give Vim processes some time to terminate before MacVim does
This should stop MacVim from beeping when Cmd-q is pressed.
2008-06-06 22:46:13 +02:00
Bjorn Winckler 1d83527039 Pass 'rl' option in "DrawCursor" message 2008-06-06 22:31:21 +02:00
Bjorn Winckler 7752431b82 Ensure "Services" menu is empty when creating new main menu
MMVimController uses a copy of the "MacVim" menu that is defined inside
MainMenu.nib instead of getting it from the default main menu.  This
ensures that the "Services" menu is initially empty for each new
MMVimController.  Without this the setKeyEquivalent: call would fail if
the key equivalent already was in a "Services" menu item (e.g. <D-F> and
<D-L> would fail).
2008-06-06 21:20:55 +02:00
Bjorn Winckler 2ac28f887e Edit->Font->Bigger/Smaller validates properly
Fixes bug where the above items were enabled even when all windows were
minimized.
2008-06-06 17:47:54 +02:00
Bjorn Winckler 9c517cb4e9 Don't draw control chars in MMTextStorage
It can happen that MMTextStorage is asked to draw characters from the
"Control Characters" set (e.g. when :shell is invoked).  This would
cause internal errors in MMTextStorage so when control chars are
detected, simply draw blanks instead.
2008-06-06 14:24:49 +02:00
Bjorn Winckler 3915c6afc6 Catch exceptions in processCommandQueue: 2008-06-06 14:22:49 +02:00
Bjorn Winckler a4569d06ac Do not set key equivalent when 'mac_key == 0' 2008-06-06 14:16:10 +02:00
Bjorn Winckler cb120a21cf Validate performClose: in MMWindow and MMFullscreenWindow
Failing to validate would cause the "Close" menu item to be disabled in
full-screen.
2008-06-05 23:13:40 +02:00
Bjorn Winckler 7070fd3f76 Update help on menus 2008-06-05 21:27:02 +02:00
Bjorn Winckler 9f1b770ee6 Add "Cycle Through Windows" to default "Windows" menu
This ensures that Cmd-` works for all windows.  Also changed its
alternate to read "Cycle Backwards Through Windows".  Note that the
default "Windows" menu does not contain the alternate since Interface
Builder turned Cmd-Shift-` into Cmd-~ which is no longer a valid
alternate.
2008-06-05 20:52:30 +02:00
Bjorn Winckler ebf10927c7 Ignore "Recent Files" when no "File" menu is found 2008-06-05 20:24:36 +02:00
Bjorn Winckler e18186c461 Pass key equivalents to default main menu after main menu
This is so that the key equivalents set up in the default main menu will
work even when the system gvimrc files hasn't been sourced.  This is
useful e.g. when "-u NONE -U NONE" is passed as arguments resulting in
the default Vim menus being used.
2008-06-05 20:19:32 +02:00
Bjorn Winckler af279d2477 Update MMAppController top level information 2008-06-04 21:53:05 +02:00
Bjorn Winckler 8c442b7b28 Merge upstream 2008-06-04 21:36:00 +02:00
vimboss 4c6ed9759c updated for version 7.1-311 2008-06-04 19:35:35 +00:00
Bjorn Winckler d98e291038 Set windows menu even if it is nil 2008-06-04 21:21:28 +02:00
Bjorn Winckler 092e0cc894 Add support for popup menus 2008-06-04 21:17:05 +02:00
vimboss b904b019b8 updated for version 7.1-310 2008-06-04 17:37:34 +00:00
Bjorn Winckler c0159b8fdf Default menu "MacVim Help" item opens help window maximized 2008-06-04 19:08:52 +02:00
Bjorn Winckler 11ec93a03a Add "Minimize All" and "Zoom All" items to "Windows" menu 2008-06-04 19:03:33 +02:00
Bjorn Winckler c2f8b396de Add "Cycle Through Windows" to Windows menu (remove <D-`> hack) 2008-06-04 18:45:45 +02:00
Bjorn Winckler fa15736b2b Hook up "MacVim Help" on default main menu 2008-06-04 18:25:08 +02:00
Bjorn Winckler d1a9e08f94 Add standard menus to default main menu 2008-06-04 18:17:23 +02:00
vimboss 9d2727c56f updated for version 7.1-309 2008-06-04 13:28:18 +00:00
vimboss ce9c112020 updated for version 7.1-308 2008-06-04 12:29:14 +00:00
vimboss 0e2ddfca38 updated for version 7.1-307 2008-06-04 11:35:26 +00:00
vimboss 1f7de911ba updated for version 7.1-306 2008-06-04 09:00:32 +00:00
Bjorn Winckler f6ab5cbc03 Use default menu when no window open, fix 'Recent Files' menu 2008-06-03 23:15:18 +02:00
Bjorn Winckler 44d7e60b06 Change heuristic for finding "Services" menu 2008-06-02 18:44:59 +02:00
Bjorn Winckler 0e37f590ab Use -[NSApp setMainMenu:] to update main menu 2008-06-01 21:28:18 +02:00
Bjorn Winckler a0f684e003 Add autoenabling for menus 2008-06-01 15:57:21 +02:00
Bjorn Winckler f54c3100e9 Menu removal functionality added 2008-06-01 14:30:00 +02:00
Bjorn Winckler a588fc3e33 Use menu descriptors instead of tags to locate menu items 2008-05-31 21:47:30 +02:00
vimboss 039f611554 updated for version 7.1-305 2008-05-29 20:41:57 +00:00
vimboss 3a4682c9dd updated for version 7.1-304 2008-05-29 19:47:13 +00:00
Nico Weber fdc64858c5 Wrap user-visible strings in NSLocalizedString() 2008-05-29 17:01:44 +02:00
vimboss 45a9151fc6 updated for version 7.1-303 2008-05-29 13:36:10 +00:00
vimboss b9241163d8 updated for version 7.1-302 2008-05-28 20:02:48 +00:00
Bjorn Winckler defa7bd098 Insert mode cursor respects 'rightleft' option
When 'rl' is enabled the insert mode cursor is drawn on the right-hand
side of a cell.
2008-05-28 21:16:27 +02:00
vimboss 6bfab82aca updated for version 7.1-301 2008-05-28 17:02:46 +00:00
vimboss 64959e3177 updated for version 7.1-300 2008-05-28 15:32:20 +00:00
vimboss 2eee45eb39 updated for version 7.1-299 2008-05-28 14:49:58 +00:00
Nico Weber 8d051eef4e Make QuickLook work with .vim files 2008-05-27 17:40:55 +02:00
Bjorn Winckler 7f449520a5 Patch a memory leak
The 'vimState' instance variable in MMVimController is now released on
dealloc.
2008-05-25 21:59:39 +02:00
41 changed files with 1611 additions and 1094 deletions
+22 -10
View File
@@ -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
View File
@@ -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
View File
@@ -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*
+9 -6
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+8
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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>
+8 -3
View File
@@ -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
View File
@@ -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;
}
-1
View File
@@ -54,7 +54,6 @@ enum { MMMaxCellsPerChar = 2 };
//
// MMTextView methods
//
- (NSEvent *)lastMouseDownEvent;
- (void)setShouldDrawInsertionPoint:(BOOL)on;
- (void)setPreEditRow:(int)row column:(int)col;
- (void)hideMarkedTextField;
+25 -16
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+10 -1
View File
@@ -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
+10
View File
@@ -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;
-2
View File
@@ -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
View File
@@ -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)
+3 -8
View File
@@ -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
View File
@@ -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)
+9
View File
@@ -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
+2 -1
View File
@@ -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
+40 -33
View File
@@ -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]) {
+1
View File
@@ -183,6 +183,7 @@ enum {
MMInsertionPointHorizontal,
MMInsertionPointVertical,
MMInsertionPointHollow,
MMInsertionPointVerticalRight,
};
+3 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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:
+36
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
}
+1
View File
@@ -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));
+5
View File
@@ -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
+26
View File
@@ -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,
/**/
+3 -3
View File
@@ -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 */