Submitted By: Matt Burgess (matthew at linuxfromscratch dot org) Date: 2008-01-04 Initial Package Version: 7.1 Origin: Upstream Upstream Status: Applied Description: Contains patches 001-202 from upstream diff -Naur vim71.orig/runtime/doc/change.txt vim71/runtime/doc/change.txt --- vim71.orig/runtime/doc/change.txt 2007-05-12 10:18:46.000000000 +0000 +++ vim71/runtime/doc/change.txt 2008-01-04 18:34:59.000000000 +0000 @@ -1571,6 +1571,10 @@ in their original order, right before the sorted lines. + If {pattern} is empty (e.g. // is specified), the + last search pattern is used. This allows trying out + a pattern first. + Note that using ":sort" with ":global" doesn't sort the matching lines, it's quite useless. diff -Naur vim71.orig/runtime/doc/cmdline.txt vim71/runtime/doc/cmdline.txt --- vim71.orig/runtime/doc/cmdline.txt 2007-05-12 10:18:46.000000000 +0000 +++ vim71/runtime/doc/cmdline.txt 2008-01-04 18:35:01.000000000 +0000 @@ -1,4 +1,4 @@ -*cmdline.txt* For Vim version 7.1. Last change: 2006 Jul 18 +*cmdline.txt* For Vim version 7.1. Last change: 2008 Jan 04 VIM REFERENCE MANUAL by Bram Moolenaar @@ -316,7 +316,7 @@ command-line is shown. (Note: the shifted arrow keys do not work on all terminals) - *his* *:history* + *:his* *:history* :his[tory] Print the history of last entered commands. {not in Vi} {not available when compiled without the |+cmdline_hist| @@ -447,6 +447,11 @@ To completely ignore files with some extension use 'wildignore'. +To match only files that end at the end of the typed text append a "$". For +example, to match only files that end in ".c": > + :e *.c$ +This will not match a file ending in ".cpp". Without the "$" it does match. + The old value of an option can be obtained by hitting 'wildchar' just after the '='. For example, typing 'wildchar' after ":set dir=" will insert the current value of 'dir'. This overrules file name completion for the options diff -Naur vim71.orig/runtime/doc/eval.txt vim71/runtime/doc/eval.txt --- vim71.orig/runtime/doc/eval.txt 2007-05-12 10:18:46.000000000 +0000 +++ vim71/runtime/doc/eval.txt 2008-01-04 18:35:00.000000000 +0000 @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 7.1. Last change: 2007 May 11 +*eval.txt* For Vim version 7.1. Last change: 2007 Sep 25 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1557,6 +1557,7 @@ changenr() Number current change number char2nr( {expr}) Number ASCII value of first char in {expr} cindent( {lnum}) Number C indent for line {lnum} +clearmatches() None clear all matches col( {expr}) Number column nr of cursor or mark complete({startcol}, {matches}) String set Insert mode completion complete_add( {expr}) Number add completion match @@ -1602,7 +1603,7 @@ foldtextresult( {lnum}) String text for closed fold at {lnum} foreground( ) Number bring the Vim window to the foreground function( {name}) Funcref reference to function {name} -garbagecollect() none free memory, breaking cyclic references +garbagecollect( [at_exit]) none free memory, breaking cyclic references get( {list}, {idx} [, {def}]) any get item {idx} from {list} or {def} get( {dict}, {key} [, {def}]) any get item {key} from {dict} or {def} getbufline( {expr}, {lnum} [, {end}]) @@ -1622,6 +1623,7 @@ getline( {lnum}) String line {lnum} of current buffer getline( {lnum}, {end}) List lines {lnum} to {end} of current buffer getloclist({nr}) List list of location list items +getmatches() List list of current matches getpos( {expr}) List position of cursor, mark, etc. getqflist() List list of quickfix items getreg( [{regname} [, 1]]) String contents of register @@ -1676,7 +1678,10 @@ String check for mappings matching {name} match( {expr}, {pat}[, {start}[, {count}]]) Number position where {pat} matches in {expr} +matchadd( {group}, {pattern}[, {priority}[, {id}]]) + Number highlight {pattern} with {group} matcharg( {nr}) List arguments of |:match| +matchdelete( {id}) Number delete match identified by {id} matchend( {expr}, {pat}[, {start}[, {count}]]) Number position where {pat} ends in {expr} matchlist( {expr}, {pat}[, {start}[, {count}]]) @@ -1731,6 +1736,7 @@ setline( {lnum}, {line}) Number set line {lnum} to {line} setloclist( {nr}, {list}[, {action}]) Number modify location list using {list} +setmatches( {list}) Number restore a list of matches setpos( {expr}, {list}) none set the {expr} position to {list} setqflist( {list}[, {action}]) Number modify quickfix list using {list} setreg( {n}, {v}[, {opt}]) Number set register to value and type @@ -2012,6 +2018,10 @@ feature, -1 is returned. See |C-indenting|. +clearmatches() *clearmatches()* + Clears all matches previously defined by |matchadd()| and the + |:match| commands. + *col()* col({expr}) The result is a Number, which is the byte index of the column position given with {expr}. The accepted positions are: @@ -2020,6 +2030,10 @@ number of characters in the cursor line plus one) 'x position of mark x (if the mark is not set, 0 is returned) + Additionally {expr} can be [lnum, col]: a |List| with the line + and column number. Most useful when the column is "$", to get + the las column of a specific line. When "lnum" or "col" is + out of range then col() returns zero. To get the line number use |line()|. To get both use |getpos()|. For the screen column position use |virtcol()|. @@ -2659,7 +2673,7 @@ {name} can be a user defined function or an internal function. -garbagecollect() *garbagecollect()* +garbagecollect([at_exit]) *garbagecollect()* Cleanup unused |Lists| and |Dictionaries| that have circular references. There is hardly ever a need to invoke this function, as it is automatically done when Vim runs out of @@ -2669,6 +2683,9 @@ This is useful if you have deleted a very big |List| and/or |Dictionary| with circular references in a script that runs for a long time. + When the optional "at_exit" argument is one, garbage + collection will also be done when exiting Vim, if it wasn't + done before. This is useful when checking for memory leaks. get({list}, {idx} [, {default}]) *get()* Get item {idx} from |List| {list}. When this item is not @@ -2824,6 +2841,8 @@ given file {fname}. If {fname} is a directory, 0 is returned. If the file {fname} can't be found, -1 is returned. + If the size of {fname} is too big to fit in a Number then -2 + is returned. getfontname([{name}]) *getfontname()* Without an argument returns the name of the normal font being @@ -2912,6 +2931,28 @@ returned. For an invalid window number {nr}, an empty list is returned. Otherwise, same as getqflist(). +getmatches() *getmatches()* + Returns a |List| with all matches previously defined by + |matchadd()| and the |:match| commands. |getmatches()| is + useful in combination with |setmatches()|, as |setmatches()| + can restore a list of matches saved by |getmatches()|. + Example: > + :echo getmatches() +< [{'group': 'MyGroup1', 'pattern': 'TODO', + 'priority': 10, 'id': 1}, {'group': 'MyGroup2', + 'pattern': 'FIXME', 'priority': 10, 'id': 2}] > + :let m = getmatches() + :call clearmatches() + :echo getmatches() +< [] > + :call setmatches(m) + :echo getmatches() +< [{'group': 'MyGroup1', 'pattern': 'TODO', + 'priority': 10, 'id': 1}, {'group': 'MyGroup2', + 'pattern': 'FIXME', 'priority': 10, 'id': 2}] > + :unlet m +< + getqflist() *getqflist()* Returns a list with all the current quickfix errors. Each list item is a dictionary with these entries: @@ -3616,6 +3657,44 @@ the pattern. 'smartcase' is NOT used. The matching is always done like 'magic' is set and 'cpoptions' is empty. + *matchadd()* *E798* *E799* *E801* +matchadd({group}, {pattern}[, {priority}[, {id}]]) + Defines a pattern to be highlighted in the current window (a + "match"). It will be highlighted with {group}. Returns an + identification number (ID), which can be used to delete the + match using |matchdelete()|. + + The optional {priority} argument assigns a priority to the + match. A match with a high priority will have its + highlighting overrule that of a match with a lower priority. + A priority is specified as an integer (negative numbers are no + exception). If the {priority} argument is not specified, the + default priority is 10. The priority of 'hlsearch' is zero, + hence all matches with a priority greater than zero will + overrule it. Syntax highlighting (see 'syntax') is a separate + mechanism, and regardless of the chosen priority a match will + always overrule syntax highlighting. + + The optional {id} argument allows the request for a specific + match ID. If a specified ID is already taken, an error + message will appear and the match will not be added. An ID + is specified as a positive integer (zero excluded). IDs 1, 2 + and 3 are reserved for |:match|, |:2match| and |:3match|, + respectively. If the {id} argument is not specified, + |matchadd()| automatically chooses a free ID. + + The number of matches is not limited, as it is the case with + the |:match| commands. + + Example: > + :highlight MyGroup ctermbg=green guibg=green + :let m = matchadd("MyGroup", "TODO") +< Deletion of the pattern: > + :call matchdelete(m) + +< A list of matches defined by |matchadd()| and |:match| are + available from |getmatches()|. All matches can be deleted in + one operation by |clearmatches()|. matcharg({nr}) *matcharg()* Selects the {nr} match item, as set with a |:match|, @@ -3625,8 +3704,15 @@ The pattern used. When {nr} is not 1, 2 or 3 returns an empty |List|. When there is no match item set returns ['', '']. - This is usef to save and restore a |:match|. - + This is useful to save and restore a |:match|. + Highlighting matches using the |:match| commands are limited + to three matches. |matchadd()| does not have this limitation. + +matchdelete({id}) *matchdelete()* *E802* *E803* + Deletes a match with ID {id} previously defined by |matchadd()| + or one of the |:match| commands. Returns 0 if succesfull, + otherwise -1. See example for |matchadd()|. All matches can + be deleted in one operation by |clearmatches()|. matchend({expr}, {pat}[, {start}[, {count}]]) *matchend()* Same as match(), but return the index of first character after @@ -4379,7 +4465,13 @@ When {nr} is zero the current window is used. For a location list window, the displayed location list is modified. For an invalid window number {nr}, -1 is returned. - Otherwise, same as setqflist(). + Otherwise, same as |setqflist()|. + Also see |location-list|. + +setmatches({list}) *setmatches()* + Restores a list of matches saved by |getmatches()|. Returns 0 + if succesfull, otherwise -1. All current matches are cleared + before the list is restored. See example for |getmatches()|. *setpos()* setpos({expr}, {list}) @@ -5022,14 +5114,12 @@ position, the returned Number will be the column at the end of the . For example, for a in column 1, with 'ts' set to 8, it returns 8. - For the use of {expr} see |col()|. Additionally you can use - [lnum, col]: a |List| with the line and column number. When - "lnum" or "col" is out of range then virtcol() returns zero. - When 'virtualedit' is used it can be [lnum, col, off], where + For the byte position use |col()|. + For the use of {expr} see |col()|. + When 'virtualedit' is used {expr} can be [lnum, col, off], where "off" is the offset in screen columns from the start of the character. E.g., a position within a or after the last character. - For the byte position use |col()|. When Virtual editing is active in the current mode, a position beyond the end of the line can be returned. |'virtualedit'| The accepted positions are: diff -Naur vim71.orig/runtime/doc/gui_w32.txt vim71/runtime/doc/gui_w32.txt --- vim71.orig/runtime/doc/gui_w32.txt 2007-05-12 10:18:46.000000000 +0000 +++ vim71/runtime/doc/gui_w32.txt 2008-01-04 18:35:00.000000000 +0000 @@ -1,4 +1,4 @@ -*gui_w32.txt* For Vim version 7.1. Last change: 2007 May 03 +*gui_w32.txt* For Vim version 7.1. Last change: 2007 Aug 14 VIM REFERENCE MANUAL by Bram Moolenaar @@ -53,6 +53,16 @@ There is a specific version of gvim.exe that runs under the Win32s subsystem of Windows 3.1 or 3.11. See |win32s|. + +Using Vim as a plugin *gui-w32-windowid* + +When gvim starts up normally, it creates its own top level window. If you +pass Vim the command-line option |--windowid| with a decimal or hexadecimal +value, Vim will create a window that is a child of the window with the given +ID. This enables Vim to act as a plugin in another application. This really +is a programmer's interface, and is of no use without a supporting application +to spawn Vim correctly. + ============================================================================== 2. Vim as default editor *vim-default-editor* diff -Naur vim71.orig/runtime/doc/options.txt vim71/runtime/doc/options.txt --- vim71.orig/runtime/doc/options.txt 2007-05-12 10:18:47.000000000 +0000 +++ vim71/runtime/doc/options.txt 2008-01-04 18:34:59.000000000 +0000 @@ -1,4 +1,4 @@ -*options.txt* For Vim version 7.1. Last change: 2007 May 11 +*options.txt* For Vim version 7.1. Last change: 2007 Aug 10 VIM REFERENCE MANUAL by Bram Moolenaar @@ -2415,8 +2415,8 @@ When mixing vertically and horizontally split windows, a minimal size is computed and some windows may be larger if there is room. The 'eadirection' option tells in which direction the size is affected. - Changing the height of a window can be avoided by setting - 'winfixheight'. + Changing the height and width of a window can be avoided by setting + 'winfixheight' and 'winfixwidth', respectively. *'equalprg'* *'ep'* 'equalprg' 'ep' string (default "") diff -Naur vim71.orig/runtime/doc/pattern.txt vim71/runtime/doc/pattern.txt --- vim71.orig/runtime/doc/pattern.txt 2007-05-12 10:18:47.000000000 +0000 +++ vim71/runtime/doc/pattern.txt 2008-01-04 18:34:59.000000000 +0000 @@ -1212,7 +1212,10 @@ {group} must exist at the moment this command is executed. The {group} highlighting still applies when a character is - to be highlighted for 'hlsearch'. + to be highlighted for 'hlsearch', as the highlighting for + matches is given higher priority than that of 'hlsearch'. + Syntax highlighting (see 'syntax') is also overruled by + matches. Note that highlighting the last used search pattern with 'hlsearch' is used in all windows, while the pattern defined @@ -1226,8 +1229,15 @@ display you may get unexpected results. That is because Vim looks for a match in the line where redrawing starts. - Also see |matcharg()|, it returns the highlight group and - pattern of a previous :match command. + Also see |matcharg()|and |getmatches()|. The former returns + the highlight group and pattern of a previous |:match| + command. The latter returns a list with highlight groups and + patterns defined by both |matchadd()| and |:match|. + + Highlighting matches using |:match| are limited to three + matches (aside from |:match|, |:2match| and |:3match|are + available). |matchadd()| does not have this limitation and in + addition makes it possible to prioritize matches. Another example, which highlights all characters in virtual column 72 and more: > diff -Naur vim71.orig/runtime/doc/pi_paren.txt vim71/runtime/doc/pi_paren.txt --- vim71.orig/runtime/doc/pi_paren.txt 2007-05-12 10:18:47.000000000 +0000 +++ vim71/runtime/doc/pi_paren.txt 2008-01-04 18:34:59.000000000 +0000 @@ -12,8 +12,8 @@ You can avoid loading this plugin by setting the "loaded_matchparen" variable: > :let loaded_matchparen = 1 -The plugin installs CursorMoved autocommands to redefine the match -highlighting. +The plugin installs CursorMoved, CursorMovedI and WinEnter autocommands to +redefine the match highlighting. To disable the plugin after it was loaded use this command: > diff -Naur vim71.orig/runtime/doc/starting.txt vim71/runtime/doc/starting.txt --- vim71.orig/runtime/doc/starting.txt 2007-05-12 10:18:47.000000000 +0000 +++ vim71/runtime/doc/starting.txt 2008-01-04 18:35:00.000000000 +0000 @@ -1,4 +1,4 @@ -*starting.txt* For Vim version 7.1. Last change: 2007 May 12 +*starting.txt* For Vim version 7.1. Last change: 2007 Aug 14 VIM REFERENCE MANUAL by Bram Moolenaar @@ -548,6 +548,11 @@ that it runs inside another window. See |gui-gtk-socketid| for details. {not in Vi} +--windowid {id} *--windowid* + Win32 GUI Vim only. Make gvim try to use the window {id} as a + parent, so that it runs inside that window. See + |gui-w32-windowid| for details. {not in Vi} + --echo-wid *--echo-wid* GTK+ GUI Vim only. Make gvim echo the Window ID on stdout, which can be used to run gvim in a kpart widget. The format diff -Naur vim71.orig/runtime/doc/usr_41.txt vim71/runtime/doc/usr_41.txt --- vim71.orig/runtime/doc/usr_41.txt 2007-05-12 10:18:48.000000000 +0000 +++ vim71/runtime/doc/usr_41.txt 2008-01-04 18:34:59.000000000 +0000 @@ -763,13 +763,22 @@ foldtextresult() get the text displayed for a closed fold Syntax and highlighting: + clearmatches() clear all matches defined by |matchadd()| and + the |:match| commands + getmatches() get all matches defined by |matchadd()| and + the |:match| commands hlexists() check if a highlight group exists hlID() get ID of a highlight group synID() get syntax ID at a specific position synIDattr() get a specific attribute of a syntax ID synIDtrans() get translated syntax ID diff_hlID() get highlight ID for diff mode at a position + matchadd() define a pattern to highlight (a "match") matcharg() get info about |:match| arguments + matchdelete() delete a match defined by |matchadd()| or a + |:match| command + setmatches() restore a list of matches saved by + |getmatches()| Spelling: spellbadword() locate badly spelled word at or after cursor diff -Naur vim71.orig/runtime/doc/vi_diff.txt vim71/runtime/doc/vi_diff.txt --- vim71.orig/runtime/doc/vi_diff.txt 2007-05-12 10:18:49.000000000 +0000 +++ vim71/runtime/doc/vi_diff.txt 2008-01-04 18:35:00.000000000 +0000 @@ -1,4 +1,4 @@ -*vi_diff.txt* For Vim version 7.1. Last change: 2007 May 07 +*vi_diff.txt* For Vim version 7.1. Last change: 2007 Aug 14 VIM REFERENCE MANUAL by Bram Moolenaar @@ -827,6 +827,8 @@ --socketid {id} Vim: GTK window socket to run Vim in +--windowid {id} Vim: Win32 window ID to run Vim in + --version Vim: show version message and exit. -? Vile: print usage summary and exit. diff -Naur vim71.orig/runtime/doc/windows.txt vim71/runtime/doc/windows.txt --- vim71.orig/runtime/doc/windows.txt 2007-05-12 10:18:49.000000000 +0000 +++ vim71/runtime/doc/windows.txt 2008-01-04 18:34:59.000000000 +0000 @@ -132,7 +132,8 @@ the same file. Make new window N high (default is to use half the height of the current window). Reduces the current window height to create room (and others, if the 'equalalways' option - is set and 'eadirection' isn't "hor"). + is set, 'eadirection' isn't "hor", and one of them is higher + than the current or the new window). Note: CTRL-S does not work on all terminals and might block further input, use CTRL-Q to get going again. Also see |++opt| and |+cmd|. @@ -140,9 +141,13 @@ CTRL-W CTRL-V *CTRL-W_CTRL-V* CTRL-W v *CTRL-W_v* :[N]vs[plit] [++opt] [+cmd] [file] *:vs* *:vsplit* - Like |:split|, but split vertically. If 'equalalways' is set - and 'eadirection' isn't "ver" the windows will be spread out - horizontally, unless a width was specified. + Like |:split|, but split vertically. The windows will be + spread out horizontally if + 1. a width was not specified, + 2. 'equalalways' is set, + 3. 'eadirection' isn't "ver", and + 4. one of the other windows are wider than the current or new + window. Note: In other places CTRL-Q does the same as CTRL-V, but here it doesn't! diff -Naur vim71.orig/runtime/filetype.vim vim71/runtime/filetype.vim --- vim71.orig/runtime/filetype.vim 2007-05-10 15:14:37.000000000 +0000 +++ vim71/runtime/filetype.vim 2008-01-04 18:34:59.000000000 +0000 @@ -1,7 +1,7 @@ " Vim support file to detect file types " " Maintainer: Bram Moolenaar -" Last Change: 2007 May 10 +" Last Change: 2007 May 15 " Listen very carefully, I will say this only once if exists("did_load_filetypes") @@ -1286,7 +1286,7 @@ au BufNewFile,BufRead *.it,*.ih setf ppwiz " Oracle Pro*C/C++ -au BufNewFile,BufRead .pc setf proc +au BufNewFile,BufRead *.pc setf proc " Privoxy actions file au BufNewFile,BufRead *.action setf privoxy diff -Naur vim71.orig/runtime/menu.vim vim71/runtime/menu.vim --- vim71.orig/runtime/menu.vim 2007-01-09 13:31:40.000000000 +0000 +++ vim71/runtime/menu.vim 2008-01-04 18:35:00.000000000 +0000 @@ -2,7 +2,7 @@ " You can also use this as a start for your own set of menus. " " Maintainer: Bram Moolenaar -" Last Change: 2007 Jan 09 +" Last Change: 2007 Nov 19 " Note that ":an" (short for ":anoremenu") is often used to make a menu work " in all modes and avoid side effects from mappings defined by the user. @@ -658,7 +658,6 @@ let buf = 1 while buf <= bufnr('$') if bufexists(buf) && !isdirectory(bufname(buf)) && buflisted(buf) - \ && !getbufvar(buf, "&bufsecret") let s:bmenu_count = s:bmenu_count + 1 endif let buf = buf + 1 @@ -671,7 +670,6 @@ let buf = 1 while buf <= bufnr('$') if bufexists(buf) && !isdirectory(bufname(buf)) && buflisted(buf) - \ && !getbufvar(buf, "&bufsecret") call BMFilename(bufname(buf), buf) endif let buf = buf + 1 diff -Naur vim71.orig/runtime/plugin/matchparen.vim vim71/runtime/plugin/matchparen.vim --- vim71.orig/runtime/plugin/matchparen.vim 2006-10-12 20:05:05.000000000 +0000 +++ vim71/runtime/plugin/matchparen.vim 2008-01-04 18:34:59.000000000 +0000 @@ -1,6 +1,6 @@ " Vim plugin for showing matching parens " Maintainer: Bram Moolenaar -" Last Change: 2006 Oct 12 +" Last Change: 2007 Aug 8 " Exit quickly when: " - this plugin was already loaded (or disabled) @@ -13,7 +13,7 @@ augroup matchparen " Replace all matchparen autocommands - autocmd! CursorMoved,CursorMovedI * call s:Highlight_Matching_Pair() + autocmd! CursorMoved,CursorMovedI,WinEnter * call s:Highlight_Matching_Pair() augroup END " Skip the rest if it was already done. @@ -62,25 +62,37 @@ " Figure out the arguments for searchpairpos(). " Restrict the search to visible lines with "stopline". " And avoid searching very far (e.g., for closed folds and long lines) + " The "viewable" variables give a range in which we can scroll while keeping + " the cursor at the same position + " adjustedScrolloff accounts for very large numbers of scrolloff + let adjustedScrolloff = min([&scrolloff, (line('w$') - line('w0')) / 2]) + let bottom_viewable = min([line('$'), c_lnum + &lines - adjustedScrolloff - 2]) + let top_viewable = max([1, c_lnum-&lines+adjustedScrolloff + 2]) + " one of these stoplines will be adjusted below, but the current values are + " minimal boundaries within the current window + let stoplinebottom = line('w$') + let stoplinetop = line('w0') if i % 2 == 0 let s_flags = 'nW' let c2 = plist[i + 1] if has("byte_offset") && has("syntax_items") && &smc > 0 let stopbyte = min([line2byte("$"), line2byte(".") + col(".") + &smc * 2]) - let stopline = min([line('w$'), byte2line(stopbyte)]) + let stopline = min([bottom_viewable, byte2line(stopbyte)]) else - let stopline = min([line('w$'), c_lnum + 100]) + let stopline = min([bottom_viewable, c_lnum + 100]) endif + let stoplinebottom = stopline else let s_flags = 'nbW' let c2 = c let c = plist[i - 1] if has("byte_offset") && has("syntax_items") && &smc > 0 let stopbyte = max([1, line2byte(".") + col(".") - &smc * 2]) - let stopline = max([line('w0'), byte2line(stopbyte)]) + let stopline = max([top_viewable, byte2line(stopbyte)]) else - let stopline = max([line('w0'), c_lnum - 100]) + let stopline = max([top_viewable, c_lnum - 100]) endif + let stoplinetop = stopline endif if c == '[' let c = '\[' @@ -106,7 +118,7 @@ endif " If a match is found setup match highlighting. - if m_lnum > 0 && m_lnum >= line('w0') && m_lnum <= line('w$') + if m_lnum > 0 && m_lnum >= stoplinetop && m_lnum <= stoplinebottom exe '3match MatchParen /\(\%' . c_lnum . 'l\%' . (c_col - before) . \ 'c\)\|\(\%' . m_lnum . 'l\%' . m_col . 'c\)/' let w:paren_hl_on = 1 @@ -114,7 +126,8 @@ endfunction " Define commands that will disable and enable the plugin. -command! NoMatchParen 3match none | unlet! g:loaded_matchparen | au! matchparen -command! DoMatchParen runtime plugin/matchparen.vim | doau CursorMoved +command! NoMatchParen windo 3match none | unlet! g:loaded_matchparen | + \ au! matchparen +command! DoMatchParen runtime plugin/matchparen.vim | windo doau CursorMoved let &cpo = cpo_save diff -Naur vim71.orig/src/Makefile vim71/src/Makefile --- vim71.orig/src/Makefile 2007-05-12 11:57:13.000000000 +0000 +++ vim71/src/Makefile 2008-01-04 18:35:01.000000000 +0000 @@ -2559,8 +2559,11 @@ # -mkdir $(DESTDIR)$(prefix)/$(APPDIR)/bin srcdir=`pwd`; $(MAKE) -f Makefile installruntime \ VIMEXE=$$srcdir/$(VIMTARGET) \ - prefix=$(DESTDIR)$(prefix)/$(RESDIR)/vim \ - VIMRTLOC=$(DESTDIR)$(prefix)/$(RESDIR)/vim/runtime + prefix=$(DESTDIR)$(prefix)/$(RESDIR)$(VIMDIR) \ + exec_prefix=$(DESTDIR)$(prefix)/$(APPDIR)/Contents \ + BINDIR=$(DESTDIR)$(prefix)/$(APPDIR)/Contents/MacOS \ + VIMLOC=$(DESTDIR)$(prefix)/$(RESDIR)$(VIMDIR) \ + VIMRTLOC=$(DESTDIR)$(prefix)/$(RESDIR)$(VIMDIR)/runtime # Put the link back. ln -s `pwd`/../runtime $(RESDIR)/vim # Copy rgb.txt, Mac doesn't always have X11 diff -Naur vim71.orig/src/auto/configure vim71/src/auto/configure --- vim71.orig/src/auto/configure 2007-05-12 11:49:09.000000000 +0000 +++ vim71/src/auto/configure 2008-01-04 18:35:01.000000000 +0000 @@ -3843,7 +3843,9 @@ fi if test "X$vi_cv_path_mzscheme_pfx" != "X"; then - if test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a"; then + if test "x$MACOSX" = "xyes"; then + MZSCHEME_LIBS="-framework PLT_MzScheme" + elif test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a"; then MZSCHEME_LIBS="${vi_cv_path_mzscheme_pfx}/lib/libmzscheme.a ${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a" else MZSCHEME_LIBS="-L${vi_cv_path_mzscheme_pfx}/lib -lmzscheme -lmzgc" @@ -4443,7 +4445,7 @@ tclsh_name="$withval"; echo "$as_me:$LINENO: result: $tclsh_name" >&5 echo "${ECHO_T}$tclsh_name" >&6 else - tclsh_name="tclsh8.4"; echo "$as_me:$LINENO: result: no" >&5 + tclsh_name="tclsh8.5"; echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi; # Extract the first word of "$tclsh_name", so it can be a program name with args. @@ -4487,7 +4489,49 @@ - if test "X$vi_cv_path_tcl" = "X" -a $tclsh_name = "tclsh8.4"; then + if test "X$vi_cv_path_tcl" = "X" -a $tclsh_name = "tclsh8.5"; then + tclsh_name="tclsh8.4" + # Extract the first word of "$tclsh_name", so it can be a program name with args. +set dummy $tclsh_name; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_vi_cv_path_tcl+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $vi_cv_path_tcl in + [\\/]* | ?:[\\/]*) + ac_cv_path_vi_cv_path_tcl="$vi_cv_path_tcl" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_vi_cv_path_tcl="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +vi_cv_path_tcl=$ac_cv_path_vi_cv_path_tcl + +if test -n "$vi_cv_path_tcl"; then + echo "$as_me:$LINENO: result: $vi_cv_path_tcl" >&5 +echo "${ECHO_T}$vi_cv_path_tcl" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + fi + if test "X$vi_cv_path_tcl" = "X" -a $tclsh_name = "tclsh8.4"; then tclsh_name="tclsh8.2" # Extract the first word of "$tclsh_name", so it can be a program name with args. set dummy $tclsh_name; ac_word=$2 @@ -4647,6 +4691,7 @@ echo $ECHO_N "checking for location of tclConfig.sh script... $ECHO_C" >&6 if test "x$MACOSX" != "xyes"; then tclcnf=`echo $tclinc | sed s/include/lib/g` + tclcnf="$tclcnf `echo $tclinc | sed s/include/lib64/g`" else tclcnf="/System/Library/Frameworks/Tcl.framework" fi @@ -4666,6 +4711,7 @@ echo "$as_me:$LINENO: checking for Tcl library by myself" >&5 echo $ECHO_N "checking for Tcl library by myself... $ECHO_C" >&6 tcllib=`echo $tclinc | sed s/include/lib/g` + tcllib="$tcllib `echo $tclinc | sed s/include/lib64/g`" for ext in .so .a ; do for ver in "" $tclver ; do for try in $tcllib ; do @@ -10263,8 +10309,9 @@ + for ac_header in stdarg.h stdlib.h string.h sys/select.h sys/utsname.h \ - termcap.h fcntl.h sgtty.h sys/ioctl.h sys/time.h termio.h \ + termcap.h fcntl.h sgtty.h sys/ioctl.h sys/time.h sys/types.h termio.h \ iconv.h langinfo.h unistd.h stropts.h errno.h \ sys/resource.h sys/systeminfo.h locale.h \ sys/stream.h sys/ptem.h termios.h libc.h sys/statfs.h \ diff -Naur vim71.orig/src/buffer.c vim71/src/buffer.c --- vim71.orig/src/buffer.c 2007-05-10 15:25:59.000000000 +0000 +++ vim71/src/buffer.c 2008-01-04 18:35:00.000000000 +0000 @@ -171,6 +171,13 @@ /* Put the cursor on the first line. */ curwin->w_cursor.lnum = 1; curwin->w_cursor.col = 0; + + /* Set or reset 'modified' before executing autocommands, so that + * it can be changed there. */ + if (!readonlymode && !bufempty()) + changed(); + else if (retval != FAIL) + unchanged(curbuf, FALSE); #ifdef FEAT_AUTOCMD # ifdef FEAT_EVAL apply_autocmds_retval(EVENT_STDINREADPOST, NULL, NULL, FALSE, @@ -194,16 +201,16 @@ /* When reading stdin, the buffer contents always needs writing, so set * the changed flag. Unless in readonly mode: "ls | gview -". * When interrupted and 'cpoptions' contains 'i' set changed flag. */ - if ((read_stdin && !readonlymode && !bufempty()) + if ((got_int && vim_strchr(p_cpo, CPO_INTMOD) != NULL) #ifdef FEAT_AUTOCMD || modified_was_set /* ":set modified" used in autocmd */ # ifdef FEAT_EVAL || (aborting() && vim_strchr(p_cpo, CPO_INTMOD) != NULL) # endif #endif - || (got_int && vim_strchr(p_cpo, CPO_INTMOD) != NULL)) + ) changed(); - else if (retval != FAIL) + else if (retval != FAIL && !read_stdin) unchanged(curbuf, FALSE); save_file_ff(curbuf); /* keep this fileformat */ @@ -495,6 +502,7 @@ buf->b_start_eol = TRUE; #ifdef FEAT_MBYTE buf->b_p_bomb = FALSE; + buf->b_start_bomb = FALSE; #endif buf->b_ml.ml_mfp = NULL; buf->b_ml.ml_flags = ML_EMPTY; /* empty buffer */ @@ -4167,29 +4175,35 @@ * mess up the full path name, even though it starts with a '/'. * Also expand when there is ".." in the file name, try to remove it, * because "c:/src/../README" is equal to "c:/README". + * Similarly "c:/src//file" is equal to "c:/src/file". * For MS-Windows also expand names like "longna~1" to "longname". */ #ifdef UNIX return FullName_save(fname, TRUE); #else - if (!vim_isAbsName(fname) || strstr((char *)fname, "..") != NULL -#if defined(MSWIN) || defined(DJGPP) + if (!vim_isAbsName(fname) + || strstr((char *)fname, "..") != NULL + || strstr((char *)fname, "//") != NULL +# ifdef BACKSLASH_IN_FILENAME + || strstr((char *)fname, "\\\\") != NULL +# endif +# if defined(MSWIN) || defined(DJGPP) || vim_strchr(fname, '~') != NULL -#endif +# endif ) return FullName_save(fname, FALSE); fname = vim_strsave(fname); -#ifdef USE_FNAME_CASE -# ifdef USE_LONG_FNAME +# ifdef USE_FNAME_CASE +# ifdef USE_LONG_FNAME if (USE_LONG_FNAME) -# endif +# endif { if (fname != NULL) fname_case(fname, 0); /* set correct case for file name */ } -#endif +# endif return fname; #endif @@ -4253,12 +4267,12 @@ do_arg_all(count, forceit, keep_tabs) int count; int forceit; /* hide buffers in current windows */ - int keep_tabs; /* keep curren tabs, for ":tab drop file" */ + int keep_tabs; /* keep current tabs, for ":tab drop file" */ { int i; win_T *wp, *wpnext; char_u *opened; /* array of flags for which args are open */ - int opened_len; /* lenght of opened[] */ + int opened_len; /* length of opened[] */ int use_firstwin = FALSE; /* use first window for arglist */ int split_ret = OK; int p_ea_save; @@ -4853,7 +4867,7 @@ */ for (e = s; *e != ':' && *e != NUL; ++e) if (e[0] == '\\' && e[1] == ':') - STRCPY(e, e + 1); + mch_memmove(e, e + 1, STRLEN(e)); if (*e == NUL) end = TRUE; @@ -4938,10 +4952,7 @@ /* Expand "~/" in the file name at "line + 1" to a full path. * Then try shortening it by comparing with the current directory */ expand_env(xline, NameBuff, MAXPATHL); - mch_dirname(IObuff, IOSIZE); - sfname = shorten_fname(NameBuff, IObuff); - if (sfname == NULL) - sfname = NameBuff; + sfname = shorten_fname1(NameBuff); buf = buflist_new(NameBuff, sfname, (linenr_T)0, BLN_LISTED); if (buf != NULL) /* just in case... */ @@ -5507,11 +5518,11 @@ #ifdef FEAT_AUTOCMD if (!aucmd) /* Don't trigger BufDelete autocommands here. */ - ++autocmd_block; + block_autocmds(); #endif close_buffer(NULL, buf, DOBUF_WIPE); #ifdef FEAT_AUTOCMD if (!aucmd) - --autocmd_block; + unblock_autocmds(); #endif } diff -Naur vim71.orig/src/charset.c vim71/src/charset.c --- vim71.orig/src/charset.c 2007-03-24 20:10:37.000000000 +0000 +++ vim71/src/charset.c 2008-01-04 18:34:59.000000000 +0000 @@ -207,7 +207,10 @@ } while (c <= c2) { - if (!do_isalpha || isalpha(c) + /* Use the MB_ functions here, because isalpha() doesn't + * work properly when 'encoding' is "latin1" and the locale is + * "C". */ + if (!do_isalpha || MB_ISLOWER(c) || MB_ISUPPER(c) #ifdef FEAT_FKMAP || (p_altkeymap && (F_isalpha(c) || F_isdigit(c))) #endif @@ -929,6 +932,23 @@ } /* + * return TRUE if 'c' is a valid file-name character or a wildcard character + * Assume characters above 0x100 are valid (multi-byte). + * Explicitly interpret ']' as a wildcard character as mch_has_wildcard("]") + * returns false. + */ + int +vim_isfilec_or_wc(c) + int c; +{ + char_u buf[2]; + + buf[0] = (char_u)c; + buf[1] = NUL; + return vim_isfilec(c) || c == ']' || mch_has_wildcard(buf); +} + +/* * return TRUE if 'c' is a printable character * Assume characters above 0x100 are printable (multi-byte), except for * Unicode. @@ -1898,7 +1918,7 @@ { for ( ; *p; ++p) if (rem_backslash(p)) - STRCPY(p, p + 1); + mch_memmove(p, p + 1, STRLEN(p)); } /* diff -Naur vim71.orig/src/configure.in vim71/src/configure.in --- vim71.orig/src/configure.in 2007-05-12 09:19:27.000000000 +0000 +++ vim71/src/configure.in 2008-01-04 18:35:01.000000000 +0000 @@ -423,7 +423,9 @@ fi if test "X$vi_cv_path_mzscheme_pfx" != "X"; then - if test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a"; then + if test "x$MACOSX" = "xyes"; then + MZSCHEME_LIBS="-framework PLT_MzScheme" + elif test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a"; then MZSCHEME_LIBS="${vi_cv_path_mzscheme_pfx}/lib/libmzscheme.a ${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a" else MZSCHEME_LIBS="-L${vi_cv_path_mzscheme_pfx}/lib -lmzscheme -lmzgc" @@ -757,15 +759,19 @@ if test "$enable_tclinterp" = "yes"; then - dnl on FreeBSD tclsh is a silly script, look for tclsh8.[420] + dnl on FreeBSD tclsh is a silly script, look for tclsh8.[5420] AC_MSG_CHECKING(--with-tclsh argument) AC_ARG_WITH(tclsh, [ --with-tclsh=PATH which tclsh to use (default: tclsh8.0)], tclsh_name="$withval"; AC_MSG_RESULT($tclsh_name), - tclsh_name="tclsh8.4"; AC_MSG_RESULT(no)) + tclsh_name="tclsh8.5"; AC_MSG_RESULT(no)) AC_PATH_PROG(vi_cv_path_tcl, $tclsh_name) AC_SUBST(vi_cv_path_tcl) - dnl when no specific version specified, also try 8.2 and 8.0 + dnl when no specific version specified, also try 8.4, 8.2 and 8.0 + if test "X$vi_cv_path_tcl" = "X" -a $tclsh_name = "tclsh8.5"; then + tclsh_name="tclsh8.4" + AC_PATH_PROG(vi_cv_path_tcl, $tclsh_name) + fi if test "X$vi_cv_path_tcl" = "X" -a $tclsh_name = "tclsh8.4"; then tclsh_name="tclsh8.2" AC_PATH_PROG(vi_cv_path_tcl, $tclsh_name) @@ -808,6 +814,7 @@ AC_MSG_CHECKING(for location of tclConfig.sh script) if test "x$MACOSX" != "xyes"; then tclcnf=`echo $tclinc | sed s/include/lib/g` + tclcnf="$tclcnf `echo $tclinc | sed s/include/lib64/g`" else dnl For Mac OS X 10.3, use the OS-provided framework location tclcnf="/System/Library/Frameworks/Tcl.framework" @@ -828,6 +835,7 @@ AC_MSG_RESULT() AC_MSG_CHECKING(for Tcl library by myself) tcllib=`echo $tclinc | sed s/include/lib/g` + tcllib="$tcllib `echo $tclinc | sed s/include/lib64/g`" for ext in .so .a ; do for ver in "" $tclver ; do for try in $tcllib ; do @@ -2024,7 +2032,7 @@ fi AC_CHECK_HEADERS(stdarg.h stdlib.h string.h sys/select.h sys/utsname.h \ - termcap.h fcntl.h sgtty.h sys/ioctl.h sys/time.h termio.h \ + termcap.h fcntl.h sgtty.h sys/ioctl.h sys/time.h sys/types.h termio.h \ iconv.h langinfo.h unistd.h stropts.h errno.h \ sys/resource.h sys/systeminfo.h locale.h \ sys/stream.h sys/ptem.h termios.h libc.h sys/statfs.h \ diff -Naur vim71.orig/src/diff.c vim71/src/diff.c --- vim71.orig/src/diff.c 2007-02-16 00:18:41.000000000 +0000 +++ vim71/src/diff.c 2008-01-04 18:35:00.000000000 +0000 @@ -791,6 +791,9 @@ } mch_remove(tmp_orig); + /* force updating cursor position on screen */ + curwin->w_valid_cursor.lnum = 0; + diff_redraw(TRUE); theend: @@ -840,11 +843,11 @@ tmp_orig, tmp_new); append_redir(cmd, p_srr, tmp_diff); #ifdef FEAT_AUTOCMD - ++autocmd_block; /* Avoid ShellCmdPost stuff */ + block_autocmds(); /* Avoid ShellCmdPost stuff */ #endif (void)call_shell(cmd, SHELL_FILTER|SHELL_SILENT|SHELL_DOOUT); #ifdef FEAT_AUTOCMD - --autocmd_block; + unblock_autocmds(); #endif vim_free(cmd); } @@ -949,11 +952,11 @@ # endif eap->arg); #ifdef FEAT_AUTOCMD - ++autocmd_block; /* Avoid ShellCmdPost stuff */ + block_autocmds(); /* Avoid ShellCmdPost stuff */ #endif (void)call_shell(buf, SHELL_FILTER | SHELL_COOKED); #ifdef FEAT_AUTOCMD - --autocmd_block; + unblock_autocmds(); #endif } @@ -1310,7 +1313,7 @@ dp->df_count[idx_new] += -off; off = 0; } - for (i = idx_orig; i < idx_new + !notset; ++i) + for (i = idx_orig; i < idx_new; ++i) if (curtab->tp_diffbuf[i] != NULL) dp->df_count[i] = dpl->df_lnum[i] + dpl->df_count[i] - dp->df_lnum[i] + off; diff -Naur vim71.orig/src/digraph.c vim71/src/digraph.c --- vim71.orig/src/digraph.c 2006-05-02 18:24:04.000000000 +0000 +++ vim71/src/digraph.c 2008-01-04 18:35:01.000000000 +0000 @@ -1978,6 +1978,61 @@ {'f', 't', 0xfb05}, {'s', 't', 0xfb06}, # endif /* FEAT_MBYTE */ + + /* Vim 5.x compatible digraphs that don't conflict with the above */ + {'~', '!', 161}, /* ¡ */ + {'c', '|', 162}, /* ¢ */ + {'$', '$', 163}, /* £ */ + {'o', 'x', 164}, /* ¤ - currency symbol in ISO 8859-1 */ + {'Y', '-', 165}, /* ¥ */ + {'|', '|', 166}, /* ¦ */ + {'c', 'O', 169}, /* © */ + {'-', ',', 172}, /* ¬ */ + {'-', '=', 175}, /* ¯ */ + {'~', 'o', 176}, /* ° */ + {'2', '2', 178}, /* ² */ + {'3', '3', 179}, /* ³ */ + {'p', 'p', 182}, /* ¶ */ + {'~', '.', 183}, /* · */ + {'1', '1', 185}, /* ¹ */ + {'~', '?', 191}, /* ¿ */ + {'A', '`', 192}, /* À */ + {'A', '^', 194}, /* Â */ + {'A', '~', 195}, /* Ã */ + {'A', '"', 196}, /* Ä */ + {'A', '@', 197}, /* Å */ + {'E', '`', 200}, /* È */ + {'E', '^', 202}, /* Ê */ + {'E', '"', 203}, /* Ë */ + {'I', '`', 204}, /* Ì */ + {'I', '^', 206}, /* Î */ + {'I', '"', 207}, /* Ï */ + {'N', '~', 209}, /* Ñ */ + {'O', '`', 210}, /* Ò */ + {'O', '^', 212}, /* Ô */ + {'O', '~', 213}, /* Õ */ + {'/', '\\', 215}, /* × - multiplication symbol in ISO 8859-1 */ + {'U', '`', 217}, /* Ù */ + {'U', '^', 219}, /* Û */ + {'I', 'p', 222}, /* Þ */ + {'a', '`', 224}, /* à */ + {'a', '^', 226}, /* â */ + {'a', '~', 227}, /* ã */ + {'a', '"', 228}, /* ä */ + {'a', '@', 229}, /* å */ + {'e', '`', 232}, /* è */ + {'e', '^', 234}, /* ê */ + {'e', '"', 235}, /* ë */ + {'i', '`', 236}, /* ì */ + {'i', '^', 238}, /* î */ + {'n', '~', 241}, /* ñ */ + {'o', '`', 242}, /* ò */ + {'o', '^', 244}, /* ô */ + {'o', '~', 245}, /* õ */ + {'u', '`', 249}, /* ù */ + {'u', '^', 251}, /* û */ + {'y', '"', 255}, /* x XX */ + {NUL, NUL, NUL} }; @@ -2028,7 +2083,7 @@ ++no_mapping; ++allow_keys; - c = safe_vgetc(); + c = plain_vgetc(); --no_mapping; --allow_keys; if (c != ESC) /* ESC cancels CTRL-K */ @@ -2050,7 +2105,7 @@ #endif ++no_mapping; ++allow_keys; - cc = safe_vgetc(); + cc = plain_vgetc(); --no_mapping; --allow_keys; if (cc != ESC) /* ESC cancels CTRL-K */ @@ -2349,8 +2404,10 @@ if (*curbuf->b_p_keymap == NUL) { - /* Stop any active keymap and clear the table. */ + /* Stop any active keymap and clear the table. Also remove + * b:keymap_name, as no keymap is active now. */ keymap_unload(); + do_cmdline_cmd((char_u *)"unlet! b:keymap_name"); } else { @@ -2500,7 +2557,6 @@ ga_clear(&curbuf->b_kmap_ga); curbuf->b_kmap_state &= ~KEYMAP_LOADED; - do_cmdline_cmd((char_u *)"unlet! b:keymap_name"); #ifdef FEAT_WINDOWS status_redraw_curbuf(); #endif diff -Naur vim71.orig/src/edit.c vim71/src/edit.c --- vim71.orig/src/edit.c 2007-05-07 19:43:55.000000000 +0000 +++ vim71/src/edit.c 2008-01-04 18:35:01.000000000 +0000 @@ -129,6 +129,7 @@ static void ins_ctrl_x __ARGS((void)); static int has_compl_option __ARGS((int dict_opt)); +static int ins_compl_accept_char __ARGS((int c)); static int ins_compl_add __ARGS((char_u *str, int len, int icase, char_u *fname, char_u **cptext, int cdir, int flags, int adup)); static int ins_compl_equal __ARGS((compl_T *match, char_u *str, int len)); static void ins_compl_longest_match __ARGS((compl_T *match)); @@ -549,7 +550,7 @@ i = showmode(); if (!p_im && did_restart_edit == 0) - change_warning(i + 1); + change_warning(i == 0 ? 0 : i + 1); #ifdef CURSOR_SHAPE ui_cursor_shape(); /* may show different cursor shape */ @@ -754,8 +755,9 @@ continue; } - /* A printable, non-white character: Add to "compl_leader". */ - if (vim_isprintc(c) && !vim_iswhite(c)) + /* A non-white character that fits in with the current + * completion: Add to "compl_leader". */ + if (ins_compl_accept_char(c)) { ins_compl_addleader(c); continue; @@ -788,7 +790,7 @@ ins_redraw(FALSE); ++no_mapping; ++allow_keys; - c = safe_vgetc(); + c = plain_vgetc(); --no_mapping; --allow_keys; if (c != Ctrl_N && c != Ctrl_G && c != Ctrl_O) @@ -981,7 +983,7 @@ #ifdef FEAT_NETBEANS_INTG case K_F21: /* NetBeans command */ ++no_mapping; /* don't map the next key hits */ - i = safe_vgetc(); + i = plain_vgetc(); --no_mapping; netbeans_keycommand(i); break; @@ -2053,11 +2055,44 @@ } /* + * Return TRUE when character "c" is part of the item currently being + * completed. Used to decide whether to abandon complete mode when the menu + * is visible. + */ + static int +ins_compl_accept_char(c) + int c; +{ + if (ctrl_x_mode & CTRL_X_WANT_IDENT) + /* When expanding an identifier only accept identifier chars. */ + return vim_isIDc(c); + + switch (ctrl_x_mode) + { + case CTRL_X_FILES: + /* When expanding file name only accept file name chars. But not + * path separators, so that "proto/" expands files in + * "proto", not "proto/" as a whole */ + return vim_isfilec(c) && !vim_ispathsep(c); + + case CTRL_X_CMDLINE: + case CTRL_X_OMNI: + /* Command line and Omni completion can work with just about any + * printable character, but do stop at white space. */ + return vim_isprintc(c) && !vim_iswhite(c); + + case CTRL_X_WHOLE_LINE: + /* For while line completion a space can be part of the line. */ + return vim_isprintc(c); + } + return vim_iswordc(c); +} + +/* * This is like ins_compl_add(), but if 'ic' and 'inf' are set, then the * case of the originally typed text is used, and the case of the completed * text is inferred, ie this tries to work out what case you probably wanted * the rest of the word to be in -- webb - * TODO: make this work for multi-byte characters. */ int ins_compl_add_infercase(str, len, icase, fname, dir, flags) @@ -2068,54 +2103,147 @@ int dir; int flags; { + char_u *p; + int i, c; + int actual_len; /* Take multi-byte characters */ + int actual_compl_length; /* into account. */ + int *wca; /* Wide character array. */ int has_lower = FALSE; int was_letter = FALSE; - int idx; - if (p_ic && curbuf->b_p_inf && len < IOSIZE) + if (p_ic && curbuf->b_p_inf && len > 0) { - /* Infer case of completed part -- webb */ - /* Use IObuff, str would change text in buffer! */ - vim_strncpy(IObuff, str, len); + /* Infer case of completed part. */ - /* Rule 1: Were any chars converted to lower? */ - for (idx = 0; idx < compl_length; ++idx) + /* Find actual length of completion. */ +#ifdef FEAT_MBYTE + if (has_mbyte) { - if (islower(compl_orig_text[idx])) + p = str; + actual_len = 0; + while (*p != NUL) { - has_lower = TRUE; - if (isupper(IObuff[idx])) - { - /* Rule 1 is satisfied */ - for (idx = compl_length; idx < len; ++idx) - IObuff[idx] = TOLOWER_LOC(IObuff[idx]); - break; - } + mb_ptr_adv(p); + ++actual_len; } } + else +#endif + actual_len = len; - /* - * Rule 2: No lower case, 2nd consecutive letter converted to - * upper case. - */ - if (!has_lower) + /* Find actual length of original text. */ +#ifdef FEAT_MBYTE + if (has_mbyte) + { + p = compl_orig_text; + actual_compl_length = 0; + while (*p != NUL) + { + mb_ptr_adv(p); + ++actual_compl_length; + } + } + else +#endif + actual_compl_length = compl_length; + + /* Allocate wide character array for the completion and fill it. */ + wca = (int *)alloc(actual_len * sizeof(int)); + if (wca != NULL) { - for (idx = 0; idx < compl_length; ++idx) + p = str; + for (i = 0; i < actual_len; ++i) +#ifdef FEAT_MBYTE + if (has_mbyte) + wca[i] = mb_ptr2char_adv(&p); + else +#endif + wca[i] = *(p++); + + /* Rule 1: Were any chars converted to lower? */ + p = compl_orig_text; + for (i = 0; i < actual_compl_length; ++i) { - if (was_letter && isupper(compl_orig_text[idx]) - && islower(IObuff[idx])) +#ifdef FEAT_MBYTE + if (has_mbyte) + c = mb_ptr2char_adv(&p); + else +#endif + c = *(p++); + if (MB_ISLOWER(c)) { - /* Rule 2 is satisfied */ - for (idx = compl_length; idx < len; ++idx) - IObuff[idx] = TOUPPER_LOC(IObuff[idx]); - break; + has_lower = TRUE; + if (MB_ISUPPER(wca[i])) + { + /* Rule 1 is satisfied. */ + for (i = actual_compl_length; i < actual_len; ++i) + wca[i] = MB_TOLOWER(wca[i]); + break; + } } - was_letter = isalpha(compl_orig_text[idx]); } - } - /* Copy the original case of the part we typed */ - STRNCPY(IObuff, compl_orig_text, compl_length); + /* + * Rule 2: No lower case, 2nd consecutive letter converted to + * upper case. + */ + if (!has_lower) + { + p = compl_orig_text; + for (i = 0; i < actual_compl_length; ++i) + { +#ifdef FEAT_MBYTE + if (has_mbyte) + c = mb_ptr2char_adv(&p); + else +#endif + c = *(p++); + if (was_letter && MB_ISUPPER(c) && MB_ISLOWER(wca[i])) + { + /* Rule 2 is satisfied. */ + for (i = actual_compl_length; i < actual_len; ++i) + wca[i] = MB_TOUPPER(wca[i]); + break; + } + was_letter = MB_ISLOWER(c) || MB_ISUPPER(c); + } + } + + /* Copy the original case of the part we typed. */ + p = compl_orig_text; + for (i = 0; i < actual_compl_length; ++i) + { +#ifdef FEAT_MBYTE + if (has_mbyte) + c = mb_ptr2char_adv(&p); + else +#endif + c = *(p++); + if (MB_ISLOWER(c)) + wca[i] = MB_TOLOWER(wca[i]); + else if (MB_ISUPPER(c)) + wca[i] = MB_TOUPPER(wca[i]); + } + + /* + * Generate encoding specific output from wide character array. + * Multi-byte characters can occupy up to five bytes more than + * ASCII characters, and we also need one byte for NUL, so stay + * six bytes away from the edge of IObuff. + */ + p = IObuff; + i = 0; + while (i < actual_len && (p - IObuff + 6) < IOSIZE) +#ifdef FEAT_MBYTE + if (has_mbyte) + p += (*mb_char2bytes)(wca[i++], p); + else +#endif + *(p++) = wca[i++]; + *p = NUL; + + vim_free(wca); + } return ins_compl_add(IObuff, len, icase, fname, NULL, dir, flags, FALSE); @@ -2842,6 +2970,7 @@ /* * Add the other matches on the line */ + ptr = buf; while (!got_int) { /* Find start of the next word. Skip white @@ -2851,7 +2980,7 @@ break; wstart = ptr; - /* Find end of the word and add it. */ + /* Find end of the word. */ #ifdef FEAT_MBYTE if (has_mbyte) /* Japanese words may have characters in @@ -2868,9 +2997,12 @@ else #endif ptr = find_word_end(ptr); - add_r = ins_compl_add_infercase(wstart, - (int)(ptr - wstart), - p_ic, files[i], *dir, 0); + + /* Add the word. Skip the regexp match. */ + if (wstart != regmatch->startp[0]) + add_r = ins_compl_add_infercase(wstart, + (int)(ptr - wstart), + p_ic, files[i], *dir, 0); } } if (add_r == OK) @@ -3032,8 +3164,11 @@ p = line + curwin->w_cursor.col; mb_ptr_back(line, p); - /* Stop completion when the whole word was deleted. */ - if ((int)(p - line) - (int)compl_col <= 0) + /* Stop completion when the whole word was deleted. For Omni completion + * allow the word to be deleted, we won't match everything. */ + if ((int)(p - line) - (int)compl_col < 0 + || ((int)(p - line) - (int)compl_col == 0 + && (ctrl_x_mode & CTRL_X_OMNI) == 0)) return K_BS; /* Deleted more than what was used to find matches or didn't finish @@ -3250,8 +3385,8 @@ if (c != Ctrl_R && vim_is_ctrl_x_key(c)) edit_submode_extra = NULL; - /* Ignore end of Select mode mapping */ - if (c == K_SELECT) + /* Ignore end of Select mode mapping and mouse scroll buttons. */ + if (c == K_SELECT || c == K_MOUSEDOWN || c == K_MOUSEUP) return retval; /* Set "compl_get_longest" when finding the first matches. */ @@ -4495,14 +4630,13 @@ curs_col = curwin->w_cursor.col; compl_pending = 0; - /* if this same ctrl_x_mode has been interrupted use the text from + /* If this same ctrl_x_mode has been interrupted use the text from * "compl_startpos" to the cursor as a pattern to add a new word * instead of expand the one before the cursor, in word-wise if - * "compl_startpos" - * is not in the same line as the cursor then fix it (the line has - * been split because it was longer than 'tw'). if SOL is set then - * skip the previous pattern, a word at the beginning of the line has - * been inserted, we'll look for that -- Acevedo. */ + * "compl_startpos" is not in the same line as the cursor then fix it + * (the line has been split because it was longer than 'tw'). if SOL + * is set then skip the previous pattern, a word at the beginning of + * the line has been inserted, we'll look for that -- Acevedo. */ if ((compl_cont_status & CONT_INTRPT) == CONT_INTRPT && compl_cont_mode == ctrl_x_mode) { @@ -5128,10 +5262,7 @@ i = 0; for (;;) { - do - nc = safe_vgetc(); - while (nc == K_IGNORE || nc == K_VER_SCROLLBAR - || nc == K_HOR_SCROLLBAR); + nc = plain_vgetc(); #ifdef FEAT_CMDL_INFO if (!(State & CMDLINE) # ifdef FEAT_MBYTE @@ -6313,8 +6444,10 @@ { vim_free(last_insert); last_insert = NULL; +# ifdef FEAT_INS_EXPAND vim_free(compl_orig_text); compl_orig_text = NULL; +# endif } #endif @@ -6806,6 +6939,25 @@ ++replace_stack_nr; } +#if defined(FEAT_MBYTE) || defined(PROTO) +/* + * Push a character onto the replace stack. Handles a multi-byte character in + * reverse byte order, so that the first byte is popped off first. + * Return the number of bytes done (includes composing characters). + */ + int +replace_push_mb(p) + char_u *p; +{ + int l = (*mb_ptr2len)(p); + int j; + + for (j = l - 1; j >= 0; --j) + replace_push(p[j]); + return l; +} +#endif + #if 0 /* * call replace_push(c) with replace_offset set to the first NUL. @@ -7215,6 +7367,8 @@ p = ml_get_curline(); if (cin_iscase(p) || cin_isscopedecl(p) || cin_islabel(30)) return TRUE; + /* Need to get the line again after cin_islabel(). */ + p = ml_get_curline(); if (curwin->w_cursor.col > 2 && p[curwin->w_cursor.col - 1] == ':' && p[curwin->w_cursor.col - 2] == ':') @@ -7477,7 +7631,7 @@ * deleted when ESC is hit. */ ++no_mapping; - regname = safe_vgetc(); + regname = plain_vgetc(); #ifdef FEAT_LANGMAP LANGMAP_ADJUST(regname, TRUE); #endif @@ -7488,7 +7642,7 @@ #ifdef FEAT_CMDL_INFO add_to_showcmd_c(literally); #endif - regname = safe_vgetc(); + regname = plain_vgetc(); #ifdef FEAT_LANGMAP LANGMAP_ADJUST(regname, TRUE); #endif @@ -7579,7 +7733,7 @@ * deleted when ESC is hit. */ ++no_mapping; - c = safe_vgetc(); + c = plain_vgetc(); --no_mapping; switch (c) { @@ -7998,7 +8152,8 @@ /* * 0^D and ^^D: remove all indent. */ - if ((lastc == '0' || lastc == '^') && curwin->w_cursor.col) + if (c == Ctrl_D && (lastc == '0' || lastc == '^') + && curwin->w_cursor.col > 0) { --curwin->w_cursor.col; (void)del_char(FALSE); /* delete the '^' or '0' */ @@ -8053,6 +8208,29 @@ AppendCharToRedobuff(K_DEL); } +static void ins_bs_one __ARGS((colnr_T *vcolp)); + +/* + * Delete one character for ins_bs(). + */ + static void +ins_bs_one(vcolp) + colnr_T *vcolp; +{ + dec_cursor(); + getvcol(curwin, &curwin->w_cursor, vcolp, NULL, NULL); + if (State & REPLACE_FLAG) + { + /* Don't delete characters before the insert point when in + * Replace mode */ + if (curwin->w_cursor.lnum != Insstart.lnum + || curwin->w_cursor.col >= Insstart.col) + replace_do_bs(); + } + else + (void)del_char(FALSE); +} + /* * Handle Backspace, delete-word and delete-line in Insert mode. * Return TRUE when backspace was actually used. @@ -8282,9 +8460,7 @@ int ts; colnr_T vcol; colnr_T want_vcol; -#if 0 - int extra = 0; -#endif + colnr_T start_vcol; *inserted_space_p = FALSE; if (p_sta && in_indent) @@ -8295,6 +8471,7 @@ * 'showbreak' may get in the way, need to get the last column of * the previous character. */ getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL); + start_vcol = vcol; dec_cursor(); getvcol(curwin, &curwin->w_cursor, NULL, NULL, &want_vcol); inc_cursor(); @@ -8303,30 +8480,7 @@ /* delete characters until we are at or before want_vcol */ while (vcol > want_vcol && (cc = *(ml_get_cursor() - 1), vim_iswhite(cc))) - { - dec_cursor(); - getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL); - if (State & REPLACE_FLAG) - { - /* Don't delete characters before the insert point when in - * Replace mode */ - if (curwin->w_cursor.lnum != Insstart.lnum - || curwin->w_cursor.col >= Insstart.col) - { -#if 0 /* what was this for? It causes problems when sw != ts. */ - if (State == REPLACE && (int)vcol < want_vcol) - { - (void)del_char(FALSE); - extra = 2; /* don't pop too much */ - } - else -#endif - replace_do_bs(); - } - } - else - (void)del_char(FALSE); - } + ins_bs_one(&vcol); /* insert extra spaces until we are at want_vcol */ while (vcol < want_vcol) @@ -8343,22 +8497,16 @@ #endif { ins_str((char_u *)" "); - if ((State & REPLACE_FLAG) /* && extra <= 1 */) - { -#if 0 - if (extra) - replace_push_off(NUL); - else -#endif - replace_push(NUL); - } -#if 0 - if (extra == 2) - extra = 1; -#endif + if ((State & REPLACE_FLAG)) + replace_push(NUL); } getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL); } + + /* If we are now back where we started delete one character. Can + * happen when using 'sts' and 'linebreak'. */ + if (vcol >= start_vcol) + ins_bs_one(&vcol); } /* @@ -8518,15 +8666,16 @@ int up; { pos_T tpos; -# if defined(FEAT_GUI) && defined(FEAT_WINDOWS) - win_T *old_curwin; +# if defined(FEAT_WINDOWS) + win_T *old_curwin = curwin; +# endif +# ifdef FEAT_INS_EXPAND + int did_scroll = FALSE; # endif tpos = curwin->w_cursor; # if defined(FEAT_GUI) && defined(FEAT_WINDOWS) - old_curwin = curwin; - /* Currently the mouse coordinates are only known in the GUI. */ if (gui.in_use && mouse_row >= 0 && mouse_col >= 0) { @@ -8543,10 +8692,23 @@ # endif undisplay_dollar(); - if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) - scroll_redraw(up, (long)(curwin->w_botline - curwin->w_topline)); - else - scroll_redraw(up, 3L); +# ifdef FEAT_INS_EXPAND + /* Don't scroll the window in which completion is being done. */ + if (!pum_visible() +# if defined(FEAT_WINDOWS) + || curwin != old_curwin +# endif + ) +# endif + { + if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) + scroll_redraw(up, (long)(curwin->w_botline - curwin->w_topline)); + else + scroll_redraw(up, 3L); +# ifdef FEAT_INS_EXPAND + did_scroll = TRUE; +# endif + } # if defined(FEAT_GUI) && defined(FEAT_WINDOWS) curwin->w_redr_status = TRUE; @@ -8555,6 +8717,17 @@ curbuf = curwin->w_buffer; # endif +# ifdef FEAT_INS_EXPAND + /* The popup menu may overlay the window, need to redraw it. + * TODO: Would be more efficient to only redraw the windows that are + * overlapped by the popup menu. */ + if (pum_visible() && did_scroll) + { + redraw_all_later(NOT_VALID); + ins_compl_show_pum(); + } +# endif + if (!equalpos(curwin->w_cursor, tpos)) { start_arrow(&tpos); @@ -9257,7 +9430,7 @@ * mode message to be deleted when ESC is hit */ ++no_mapping; ++allow_keys; - c = safe_vgetc(); + c = plain_vgetc(); --no_mapping; --allow_keys; if (IS_SPECIAL(c) || mod_mask) /* special key */ @@ -9289,7 +9462,7 @@ } ++no_mapping; ++allow_keys; - cc = safe_vgetc(); + cc = plain_vgetc(); --no_mapping; --allow_keys; if (cc != ESC) diff -Naur vim71.orig/src/eval.c vim71/src/eval.c --- vim71.orig/src/eval.c 2007-05-07 19:47:32.000000000 +0000 +++ vim71/src/eval.c 2008-01-04 18:35:01.000000000 +0000 @@ -369,17 +369,17 @@ static int ex_let_vars __ARGS((char_u *arg, typval_T *tv, int copy, int semicolon, int var_count, char_u *nextchars)); static char_u *skip_var_list __ARGS((char_u *arg, int *var_count, int *semicolon)); static char_u *skip_var_one __ARGS((char_u *arg)); -static void list_hashtable_vars __ARGS((hashtab_T *ht, char_u *prefix, int empty)); -static void list_glob_vars __ARGS((void)); -static void list_buf_vars __ARGS((void)); -static void list_win_vars __ARGS((void)); +static void list_hashtable_vars __ARGS((hashtab_T *ht, char_u *prefix, int empty, int *first)); +static void list_glob_vars __ARGS((int *first)); +static void list_buf_vars __ARGS((int *first)); +static void list_win_vars __ARGS((int *first)); #ifdef FEAT_WINDOWS -static void list_tab_vars __ARGS((void)); +static void list_tab_vars __ARGS((int *first)); #endif -static void list_vim_vars __ARGS((void)); -static void list_script_vars __ARGS((void)); -static void list_func_vars __ARGS((void)); -static char_u *list_arg_vars __ARGS((exarg_T *eap, char_u *arg)); +static void list_vim_vars __ARGS((int *first)); +static void list_script_vars __ARGS((int *first)); +static void list_func_vars __ARGS((int *first)); +static char_u *list_arg_vars __ARGS((exarg_T *eap, char_u *arg, int *first)); static char_u *ex_let_one __ARGS((char_u *arg, typval_T *tv, int copy, char_u *endchars, char_u *op)); static int check_changedtick __ARGS((char_u *arg)); static char_u *get_lval __ARGS((char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int quiet, int fne_flags)); @@ -475,6 +475,7 @@ static void f_changenr __ARGS((typval_T *argvars, typval_T *rettv)); static void f_char2nr __ARGS((typval_T *argvars, typval_T *rettv)); static void f_cindent __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_clearmatches __ARGS((typval_T *argvars, typval_T *rettv)); static void f_col __ARGS((typval_T *argvars, typval_T *rettv)); #if defined(FEAT_INS_EXPAND) static void f_complete __ARGS((typval_T *argvars, typval_T *rettv)); @@ -529,6 +530,7 @@ static void f_getftime __ARGS((typval_T *argvars, typval_T *rettv)); static void f_getftype __ARGS((typval_T *argvars, typval_T *rettv)); static void f_getline __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_getmatches __ARGS((typval_T *argvars, typval_T *rettv)); static void f_getpos __ARGS((typval_T *argvars, typval_T *rettv)); static void f_getqflist __ARGS((typval_T *argvars, typval_T *rettv)); static void f_getreg __ARGS((typval_T *argvars, typval_T *rettv)); @@ -577,7 +579,9 @@ static void f_maparg __ARGS((typval_T *argvars, typval_T *rettv)); static void f_mapcheck __ARGS((typval_T *argvars, typval_T *rettv)); static void f_match __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_matchadd __ARGS((typval_T *argvars, typval_T *rettv)); static void f_matcharg __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_matchdelete __ARGS((typval_T *argvars, typval_T *rettv)); static void f_matchend __ARGS((typval_T *argvars, typval_T *rettv)); static void f_matchlist __ARGS((typval_T *argvars, typval_T *rettv)); static void f_matchstr __ARGS((typval_T *argvars, typval_T *rettv)); @@ -618,6 +622,7 @@ static void f_setcmdpos __ARGS((typval_T *argvars, typval_T *rettv)); static void f_setline __ARGS((typval_T *argvars, typval_T *rettv)); static void f_setloclist __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_setmatches __ARGS((typval_T *argvars, typval_T *rettv)); static void f_setpos __ARGS((typval_T *argvars, typval_T *rettv)); static void f_setqflist __ARGS((typval_T *argvars, typval_T *rettv)); static void f_setreg __ARGS((typval_T *argvars, typval_T *rettv)); @@ -672,7 +677,7 @@ static void f_writefile __ARGS((typval_T *argvars, typval_T *rettv)); static int list2fpos __ARGS((typval_T *arg, pos_T *posp, int *fnump)); -static pos_T *var2fpos __ARGS((typval_T *varp, int lnum, int *fnum)); +static pos_T *var2fpos __ARGS((typval_T *varp, int dollar_lnum, int *fnum)); static int get_env_len __ARGS((char_u **arg)); static int get_id_len __ARGS((char_u **arg)); static int get_name_len __ARGS((char_u **arg, char_u **alias, int evaluate, int verbose)); @@ -699,8 +704,8 @@ static hashtab_T *find_var_ht __ARGS((char_u *name, char_u **varname)); static void vars_clear_ext __ARGS((hashtab_T *ht, int free_val)); static void delete_var __ARGS((hashtab_T *ht, hashitem_T *hi)); -static void list_one_var __ARGS((dictitem_T *v, char_u *prefix)); -static void list_one_var_a __ARGS((char_u *prefix, char_u *name, int type, char_u *string)); +static void list_one_var __ARGS((dictitem_T *v, char_u *prefix, int *first)); +static void list_one_var_a __ARGS((char_u *prefix, char_u *name, int type, char_u *string, int *first)); static void set_var __ARGS((char_u *name, typval_T *varp, int copy)); static int var_check_ro __ARGS((int flags, char_u *name)); static int var_check_fixed __ARGS((int flags, char_u *name)); @@ -992,20 +997,20 @@ char_u *value; int value_len; { - size_t len; + int len; if (redir_lval == NULL) return; if (value_len == -1) - len = STRLEN(value); /* Append the entire string */ + len = (int)STRLEN(value); /* Append the entire string */ else - len = value_len; /* Append only "value_len" characters */ + len = value_len; /* Append only "value_len" characters */ - if (ga_grow(&redir_ga, (int)len) == OK) + if (ga_grow(&redir_ga, len) == OK) { mch_memmove((char *)redir_ga.ga_data + redir_ga.ga_len, value, len); - redir_ga.ga_len += (int)len; + redir_ga.ga_len += len; } else var_redir_stop(); @@ -1313,7 +1318,6 @@ { hashitem_T *hi; - clear_tv(&vimvars[idx].vv_tv); vimvars[idx].vv_tv = *save_tv; if (vimvars[idx].vv_type == VAR_UNKNOWN) { @@ -1357,7 +1361,6 @@ if (p_verbose == 0) --emsg_off; - vimvars[VV_VAL].vv_str = NULL; restore_vimvar(VV_VAL, &save_val); return list; @@ -1411,7 +1414,8 @@ } -#if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) || defined(PROTO) +#if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) \ + || defined(FEAT_COMPL_FUNC) || defined(PROTO) /* * Call some vimL function and return the result in "*rettv". * Uses argv[argc] for the function arguments. @@ -1484,6 +1488,7 @@ return ret; } +# if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) || defined(PROTO) /* * Call vimL function "func" and return the result as a string. * Returns NULL when calling the function fails. @@ -1506,8 +1511,9 @@ clear_tv(&rettv); return retval; } +# endif -#if defined(FEAT_COMPL_FUNC) || defined(PROTO) +# if defined(FEAT_COMPL_FUNC) || defined(PROTO) /* * Call vimL function "func" and return the result as a number. * Returns -1 when calling the function fails. @@ -1530,7 +1536,7 @@ clear_tv(&rettv); return retval; } -#endif +# endif /* * Call vimL function "func" and return the result as a list @@ -1556,9 +1562,9 @@ return rettv.vval.v_list; } - #endif + /* * Save the current function call pointer, and set it to NULL. * Used when executing autocommands and for ":source". @@ -1691,6 +1697,7 @@ int semicolon = 0; char_u op[2]; char_u *argend; + int first = TRUE; argend = skip_var_list(arg, &var_count, &semicolon); if (argend == NULL) @@ -1707,19 +1714,19 @@ EMSG(_(e_invarg)); else if (!ends_excmd(*arg)) /* ":let var1 var2" */ - arg = list_arg_vars(eap, arg); + arg = list_arg_vars(eap, arg, &first); else if (!eap->skip) { /* ":let" */ - list_glob_vars(); - list_buf_vars(); - list_win_vars(); + list_glob_vars(&first); + list_buf_vars(&first); + list_win_vars(&first); #ifdef FEAT_WINDOWS - list_tab_vars(); + list_tab_vars(&first); #endif - list_script_vars(); - list_func_vars(); - list_vim_vars(); + list_script_vars(&first); + list_func_vars(&first); + list_vim_vars(&first); } eap->nextcmd = check_nextcmd(arg); } @@ -1924,10 +1931,11 @@ * If "empty" is TRUE also list NULL strings as empty strings. */ static void -list_hashtable_vars(ht, prefix, empty) +list_hashtable_vars(ht, prefix, empty, first) hashtab_T *ht; char_u *prefix; int empty; + int *first; { hashitem_T *hi; dictitem_T *di; @@ -1942,7 +1950,7 @@ di = HI2DI(hi); if (empty || di->di_tv.v_type != VAR_STRING || di->di_tv.vval.v_string != NULL) - list_one_var(di, prefix); + list_one_var(di, prefix, first); } } } @@ -1951,32 +1959,38 @@ * List global variables. */ static void -list_glob_vars() +list_glob_vars(first) + int *first; { - list_hashtable_vars(&globvarht, (char_u *)"", TRUE); + list_hashtable_vars(&globvarht, (char_u *)"", TRUE, first); } /* * List buffer variables. */ static void -list_buf_vars() +list_buf_vars(first) + int *first; { char_u numbuf[NUMBUFLEN]; - list_hashtable_vars(&curbuf->b_vars.dv_hashtab, (char_u *)"b:", TRUE); + list_hashtable_vars(&curbuf->b_vars.dv_hashtab, (char_u *)"b:", + TRUE, first); sprintf((char *)numbuf, "%ld", (long)curbuf->b_changedtick); - list_one_var_a((char_u *)"b:", (char_u *)"changedtick", VAR_NUMBER, numbuf); + list_one_var_a((char_u *)"b:", (char_u *)"changedtick", VAR_NUMBER, + numbuf, first); } /* * List window variables. */ static void -list_win_vars() +list_win_vars(first) + int *first; { - list_hashtable_vars(&curwin->w_vars.dv_hashtab, (char_u *)"w:", TRUE); + list_hashtable_vars(&curwin->w_vars.dv_hashtab, + (char_u *)"w:", TRUE, first); } #ifdef FEAT_WINDOWS @@ -1984,9 +1998,11 @@ * List tab page variables. */ static void -list_tab_vars() +list_tab_vars(first) + int *first; { - list_hashtable_vars(&curtab->tp_vars.dv_hashtab, (char_u *)"t:", TRUE); + list_hashtable_vars(&curtab->tp_vars.dv_hashtab, + (char_u *)"t:", TRUE, first); } #endif @@ -1994,39 +2010,44 @@ * List Vim variables. */ static void -list_vim_vars() +list_vim_vars(first) + int *first; { - list_hashtable_vars(&vimvarht, (char_u *)"v:", FALSE); + list_hashtable_vars(&vimvarht, (char_u *)"v:", FALSE, first); } /* * List script-local variables, if there is a script. */ static void -list_script_vars() +list_script_vars(first) + int *first; { if (current_SID > 0 && current_SID <= ga_scripts.ga_len) - list_hashtable_vars(&SCRIPT_VARS(current_SID), (char_u *)"s:", FALSE); + list_hashtable_vars(&SCRIPT_VARS(current_SID), + (char_u *)"s:", FALSE, first); } /* * List function variables, if there is a function. */ static void -list_func_vars() +list_func_vars(first) + int *first; { if (current_funccal != NULL) list_hashtable_vars(¤t_funccal->l_vars.dv_hashtab, - (char_u *)"l:", FALSE); + (char_u *)"l:", FALSE, first); } /* * List variables in "arg". */ static char_u * -list_arg_vars(eap, arg) +list_arg_vars(eap, arg, first) exarg_T *eap; char_u *arg; + int *first; { int error = FALSE; int len; @@ -2083,15 +2104,15 @@ { switch (*name) { - case 'g': list_glob_vars(); break; - case 'b': list_buf_vars(); break; - case 'w': list_win_vars(); break; + case 'g': list_glob_vars(first); break; + case 'b': list_buf_vars(first); break; + case 'w': list_win_vars(first); break; #ifdef FEAT_WINDOWS - case 't': list_tab_vars(); break; + case 't': list_tab_vars(first); break; #endif - case 'v': list_vim_vars(); break; - case 's': list_script_vars(); break; - case 'l': list_func_vars(); break; + case 'v': list_vim_vars(first); break; + case 's': list_script_vars(first); break; + case 'l': list_func_vars(first); break; default: EMSG2(_("E738: Can't list variables for %s"), name); } @@ -2108,7 +2129,9 @@ *arg = NUL; list_one_var_a((char_u *)"", arg == arg_subsc ? name : name_start, - tv.v_type, s == NULL ? (char_u *)"" : s); + tv.v_type, + s == NULL ? (char_u *)"" : s, + first); *arg = c; vim_free(tf); } @@ -6105,6 +6128,7 @@ /* Only do this once. */ want_garbage_collect = FALSE; may_garbage_collect = FALSE; + garbage_collect_at_exit = FALSE; /* * 1. Go through all accessible variables and mark all lists and dicts @@ -6681,7 +6705,7 @@ dict_T *d = NULL; typval_T tvkey; typval_T tv; - char_u *key; + char_u *key = NULL; dictitem_T *item; char_u *start = skipwhite(*arg + 1); char_u buf[NUMBUFLEN]; @@ -6721,20 +6745,24 @@ clear_tv(&tvkey); goto failret; } - key = get_tv_string_buf_chk(&tvkey, buf); - if (key == NULL || *key == NUL) + if (evaluate) { - /* "key" is NULL when get_tv_string_buf_chk() gave an errmsg */ - if (key != NULL) - EMSG(_(e_emptykey)); - clear_tv(&tvkey); - goto failret; + key = get_tv_string_buf_chk(&tvkey, buf); + if (key == NULL || *key == NUL) + { + /* "key" is NULL when get_tv_string_buf_chk() gave an errmsg */ + if (key != NULL) + EMSG(_(e_emptykey)); + clear_tv(&tvkey); + goto failret; + } } *arg = skipwhite(*arg + 1); if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */ { - clear_tv(&tvkey); + if (evaluate) + clear_tv(&tvkey); goto failret; } if (evaluate) @@ -6794,7 +6822,7 @@ * "numbuf" is used for a number. * Does not put quotes around strings, as ":echo" displays values. * When "copyID" is not NULL replace recursive lists and dicts with "...". - * May return NULL; + * May return NULL. */ static char_u * echo_string(tv, tofree, numbuf, copyID) @@ -6879,7 +6907,7 @@ * If the memory is allocated "tofree" is set to it, otherwise NULL. * "numbuf" is used for a number. * Puts quotes around strings, so that they can be parsed back by eval(). - * May return NULL; + * May return NULL. */ static char_u * tv2string(tv, tofree, numbuf, copyID) @@ -7043,6 +7071,7 @@ {"changenr", 0, 0, f_changenr}, {"char2nr", 1, 1, f_char2nr}, {"cindent", 1, 1, f_cindent}, + {"clearmatches", 0, 0, f_clearmatches}, {"col", 1, 1, f_col}, #if defined(FEAT_INS_EXPAND) {"complete", 2, 2, f_complete}, @@ -7082,7 +7111,7 @@ {"foldtextresult", 1, 1, f_foldtextresult}, {"foreground", 0, 0, f_foreground}, {"function", 1, 1, f_function}, - {"garbagecollect", 0, 0, f_garbagecollect}, + {"garbagecollect", 0, 1, f_garbagecollect}, {"get", 2, 3, f_get}, {"getbufline", 2, 3, f_getbufline}, {"getbufvar", 2, 2, f_getbufvar}, @@ -7099,6 +7128,7 @@ {"getftype", 1, 1, f_getftype}, {"getline", 1, 2, f_getline}, {"getloclist", 1, 1, f_getqflist}, + {"getmatches", 0, 0, f_getmatches}, {"getpos", 1, 1, f_getpos}, {"getqflist", 0, 0, f_getqflist}, {"getreg", 0, 2, f_getreg}, @@ -7149,7 +7179,9 @@ {"maparg", 1, 3, f_maparg}, {"mapcheck", 1, 3, f_mapcheck}, {"match", 2, 4, f_match}, + {"matchadd", 2, 4, f_matchadd}, {"matcharg", 1, 1, f_matcharg}, + {"matchdelete", 1, 1, f_matchdelete}, {"matchend", 2, 4, f_matchend}, {"matchlist", 2, 4, f_matchlist}, {"matchstr", 2, 4, f_matchstr}, @@ -7190,6 +7222,7 @@ {"setcmdpos", 1, 1, f_setcmdpos}, {"setline", 2, 2, f_setline}, {"setloclist", 2, 3, f_setloclist}, + {"setmatches", 1, 1, f_setmatches}, {"setpos", 2, 2, f_setpos}, {"setqflist", 1, 2, f_setqflist}, {"setreg", 2, 3, f_setreg}, @@ -8240,6 +8273,20 @@ } /* + * "clearmatches()" function + */ +/*ARGSUSED*/ + static void +f_clearmatches(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ +#ifdef FEAT_SEARCH_EXTRA + clear_matches(curwin); +#endif +} + +/* * "col(string)" function */ static void @@ -8682,7 +8729,7 @@ static int fnum = 0; static int change_start = 0; static int change_end = 0; - static hlf_T hlID = 0; + static hlf_T hlID = (hlf_T)0; int filler_lines; int col; @@ -9339,15 +9386,16 @@ { typval_T rettv; char_u *s; + int retval = FAIL; copy_tv(tv, &vimvars[VV_VAL].vv_tv); s = expr; if (eval1(&s, &rettv, TRUE) == FAIL) - return FAIL; + goto theend; if (*s != NUL) /* check for trailing chars after expr */ { EMSG2(_(e_invexpr2), s); - return FAIL; + goto theend; } if (map) { @@ -9366,10 +9414,12 @@ /* On type error, nothing has been removed; return FAIL to stop the * loop. The error message was given by get_tv_number_chk(). */ if (error) - return FAIL; + goto theend; } + retval = OK; +theend: clear_tv(&vimvars[VV_VAL].vv_tv); - return OK; + return retval; } /* @@ -9670,6 +9720,9 @@ /* This is postponed until we are back at the toplevel, because we may be * using Lists and Dicts internally. E.g.: ":echo [garbagecollect()]". */ want_garbage_collect = TRUE; + + if (argvars[0].v_type != VAR_UNKNOWN && get_tv_number(&argvars[0]) == 1) + garbage_collect_at_exit = TRUE; } /* @@ -9868,18 +9921,24 @@ ++no_mapping; ++allow_keys; - if (argvars[0].v_type == VAR_UNKNOWN) - /* getchar(): blocking wait. */ - n = safe_vgetc(); - else if (get_tv_number_chk(&argvars[0], &error) == 1) - /* getchar(1): only check if char avail */ - n = vpeekc(); - else if (error || vpeekc() == NUL) - /* illegal argument or getchar(0) and no char avail: return zero */ - n = 0; - else - /* getchar(0) and char avail: return char */ - n = safe_vgetc(); + for (;;) + { + if (argvars[0].v_type == VAR_UNKNOWN) + /* getchar(): blocking wait. */ + n = safe_vgetc(); + else if (get_tv_number_chk(&argvars[0], &error) == 1) + /* getchar(1): only check if char avail */ + n = vpeekc(); + else if (error || vpeekc() == NUL) + /* illegal argument or getchar(0) and no char avail: return zero */ + n = 0; + else + /* getchar(0) and char avail: return char */ + n = safe_vgetc(); + if (n == K_IGNORE) + continue; + break; + } --no_mapping; --allow_keys; @@ -10136,7 +10195,13 @@ if (mch_isdir(fname)) rettv->vval.v_number = 0; else + { rettv->vval.v_number = (varnumber_T)st.st_size; + + /* non-perfect check for overflow */ + if ((off_t)rettv->vval.v_number != (off_t)st.st_size) + rettv->vval.v_number = -2; + } } else rettv->vval.v_number = -1; @@ -10269,6 +10334,39 @@ } /* + * "getmatches()" function + */ +/*ARGSUSED*/ + static void +f_getmatches(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ +#ifdef FEAT_SEARCH_EXTRA + dict_T *dict; + matchitem_T *cur = curwin->w_match_head; + + rettv->vval.v_number = 0; + + if (rettv_list_alloc(rettv) == OK) + { + while (cur != NULL) + { + dict = dict_alloc(); + if (dict == NULL) + return; + dict_add_nr_str(dict, "group", 0L, syn_id2name(cur->hlg_id)); + dict_add_nr_str(dict, "pattern", 0L, cur->pattern); + dict_add_nr_str(dict, "priority", (long)cur->priority, NULL); + dict_add_nr_str(dict, "id", (long)cur->id, NULL); + list_append_dict(rettv->vval.v_list, dict); + cur = cur->next; + } + } +#endif +} + +/* * "getpos(string)" function */ static void @@ -10290,7 +10388,8 @@ list_append_number(l, (varnumber_T)0); list_append_number(l, (fp != NULL) ? (varnumber_T)fp->lnum : (varnumber_T)0); - list_append_number(l, (fp != NULL) ? (varnumber_T)fp->col + 1 + list_append_number(l, (fp != NULL) + ? (varnumber_T)(fp->col == MAXCOL ? MAXCOL : fp->col + 1) : (varnumber_T)0); list_append_number(l, #ifdef FEAT_VIRTUALEDIT @@ -10785,6 +10884,9 @@ "gui_gtk2", # endif #endif +#ifdef FEAT_GUI_GNOME + "gui_gnome", +#endif #ifdef FEAT_GUI_MAC "gui_mac", #endif @@ -11471,14 +11573,12 @@ char_u *xp_arg = NULL; rettv->v_type = VAR_STRING; + rettv->vval.v_string = NULL; #ifdef NO_CONSOLE_INPUT /* While starting up, there is no place to enter text. */ if (no_console_input()) - { - rettv->vval.v_string = NULL; return; - } #endif cmd_silent = FALSE; /* Want to see the prompt. */ @@ -12439,6 +12539,44 @@ } /* + * "matchadd()" function + */ + static void +f_matchadd(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ +#ifdef FEAT_SEARCH_EXTRA + char_u buf[NUMBUFLEN]; + char_u *grp = get_tv_string_buf_chk(&argvars[0], buf); /* group */ + char_u *pat = get_tv_string_buf_chk(&argvars[1], buf); /* pattern */ + int prio = 10; /* default priority */ + int id = -1; + int error = FALSE; + + rettv->vval.v_number = -1; + + if (grp == NULL || pat == NULL) + return; + if (argvars[2].v_type != VAR_UNKNOWN) + { + prio = get_tv_number_chk(&argvars[2], &error); + if (argvars[3].v_type != VAR_UNKNOWN) + id = get_tv_number_chk(&argvars[3], &error); + } + if (error == TRUE) + return; + if (id >= 1 && id <= 3) + { + EMSGN("E798: ID is reserved for \":match\": %ld", id); + return; + } + + rettv->vval.v_number = match_add(curwin, grp, pat, prio, id); +#endif +} + +/* * "matcharg()" function */ static void @@ -12449,20 +12587,42 @@ if (rettv_list_alloc(rettv) == OK) { #ifdef FEAT_SEARCH_EXTRA - int mi = get_tv_number(&argvars[0]); + int id = get_tv_number(&argvars[0]); + matchitem_T *m; - if (mi >= 1 && mi <= 3) + if (id >= 1 && id <= 3) { - list_append_string(rettv->vval.v_list, - syn_id2name(curwin->w_match_id[mi - 1]), -1); - list_append_string(rettv->vval.v_list, - curwin->w_match_pat[mi - 1], -1); + if ((m = (matchitem_T *)get_match(curwin, id)) != NULL) + { + list_append_string(rettv->vval.v_list, + syn_id2name(m->hlg_id), -1); + list_append_string(rettv->vval.v_list, m->pattern, -1); + } + else + { + list_append_string(rettv->vval.v_list, NUL, -1); + list_append_string(rettv->vval.v_list, NUL, -1); + } } #endif } } /* + * "matchdelete()" function + */ + static void +f_matchdelete(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ +#ifdef FEAT_SEARCH_EXTRA + rettv->vval.v_number = match_delete(curwin, + (int)get_tv_number(&argvars[0]), TRUE); +#endif +} + +/* * "matchend()" function */ static void @@ -13680,7 +13840,7 @@ } /* Shorten "remain". */ if (*q != NUL) - STRCPY(remain, q - 1); + mch_memmove(remain, q - 1, STRLEN(q - 1) + 1); else { vim_free(remain); @@ -13919,6 +14079,8 @@ /* If 'n' flag is used: restore cursor position. */ if (flags & SP_NOMOVE) curwin->w_cursor = save_cursor; + else + curwin->w_set_curswant = TRUE; theend: p_ws = save_p_ws; @@ -14498,6 +14660,66 @@ } /* + * "setmatches()" function + */ + static void +f_setmatches(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ +#ifdef FEAT_SEARCH_EXTRA + list_T *l; + listitem_T *li; + dict_T *d; + + rettv->vval.v_number = -1; + if (argvars[0].v_type != VAR_LIST) + { + EMSG(_(e_listreq)); + return; + } + if ((l = argvars[0].vval.v_list) != NULL) + { + + /* To some extent make sure that we are dealing with a list from + * "getmatches()". */ + li = l->lv_first; + while (li != NULL) + { + if (li->li_tv.v_type != VAR_DICT + || (d = li->li_tv.vval.v_dict) == NULL) + { + EMSG(_(e_invarg)); + return; + } + if (!(dict_find(d, (char_u *)"group", -1) != NULL + && dict_find(d, (char_u *)"pattern", -1) != NULL + && dict_find(d, (char_u *)"priority", -1) != NULL + && dict_find(d, (char_u *)"id", -1) != NULL)) + { + EMSG(_(e_invarg)); + return; + } + li = li->li_next; + } + + clear_matches(curwin); + li = l->lv_first; + while (li != NULL) + { + d = li->li_tv.vval.v_dict; + match_add(curwin, get_dict_string(d, (char_u *)"group", FALSE), + get_dict_string(d, (char_u *)"pattern", FALSE), + (int)get_dict_number(d, (char_u *)"priority"), + (int)get_dict_number(d, (char_u *)"id")); + li = li->li_next; + } + rettv->vval.v_number = 0; + } +#endif +} + +/* * "setpos()" function */ /*ARGSUSED*/ @@ -14785,6 +15007,10 @@ p1 = tv2string(&(*(listitem_T **)s1)->li_tv, &tofree1, numbuf1, 0); p2 = tv2string(&(*(listitem_T **)s2)->li_tv, &tofree2, numbuf2, 0); + if (p1 == NULL) + p1 = (char_u *)""; + if (p2 == NULL) + p2 = (char_u *)""; if (item_compare_ic) res = STRICMP(p1, p2); else @@ -15274,7 +15500,8 @@ rettv->v_type = VAR_STRING; rettv->vval.v_string = tv2string(&argvars[0], &tofree, numbuf, 0); - if (tofree == NULL) + /* Make a copy if we have a value but it's not in allocate memory. */ + if (rettv->vval.v_string != NULL && tofree == NULL) rettv->vval.v_string = vim_strsave(rettv->vval.v_string); } @@ -15599,7 +15826,7 @@ FILE *fd; if (check_restricted() || check_secure()) - return; + goto done; if (argvars[1].v_type != VAR_UNKNOWN) { @@ -15610,7 +15837,7 @@ if ((infile = vim_tempname('i')) == NULL) { EMSG(_(e_notmp)); - return; + goto done; } fd = mch_fopen((char *)infile, WRITEBIN); @@ -16497,9 +16724,9 @@ * Returns NULL when there is an error. */ static pos_T * -var2fpos(varp, lnum, fnum) +var2fpos(varp, dollar_lnum, fnum) typval_T *varp; - int lnum; /* TRUE when $ is last line */ + int dollar_lnum; /* TRUE when $ is last line */ int *fnum; /* set to fnum for '0, 'A, etc. */ { char_u *name; @@ -16512,6 +16739,7 @@ list_T *l; int len; int error = FALSE; + listitem_T *li; l = varp->vval.v_list; if (l == NULL) @@ -16527,6 +16755,14 @@ if (error) return NULL; len = (long)STRLEN(ml_get(pos.lnum)); + + /* We accept "$" for the column number: last column. */ + li = list_find(l, 1L); + if (li != NULL && li->li_tv.v_type == VAR_STRING + && li->li_tv.vval.v_string != NULL + && STRCMP(li->li_tv.vval.v_string, "$") == 0) + pos.col = len + 1; + /* Accept a position up to the NUL after the line. */ if (pos.col == 0 || (int)pos.col > len + 1) return NULL; /* invalid column number */ @@ -16559,7 +16795,7 @@ pos.coladd = 0; #endif - if (name[0] == 'w' && lnum) + if (name[0] == 'w' && dollar_lnum) { pos.col = 0; if (name[1] == '0') /* "w0": first visible line */ @@ -16577,7 +16813,7 @@ } else if (name[0] == '$') /* last column or line */ { - if (lnum) + if (dollar_lnum) { pos.lnum = curbuf->b_ml.ml_line_count; pos.col = 0; @@ -17798,9 +18034,10 @@ * List the value of one internal variable. */ static void -list_one_var(v, prefix) +list_one_var(v, prefix, first) dictitem_T *v; char_u *prefix; + int *first; { char_u *tofree; char_u *s; @@ -17808,18 +18045,21 @@ s = echo_string(&v->di_tv, &tofree, numbuf, ++current_copyID); list_one_var_a(prefix, v->di_key, v->di_tv.v_type, - s == NULL ? (char_u *)"" : s); + s == NULL ? (char_u *)"" : s, first); vim_free(tofree); } static void -list_one_var_a(prefix, name, type, string) +list_one_var_a(prefix, name, type, string, first) char_u *prefix; char_u *name; int type; char_u *string; + int *first; /* when TRUE clear rest of screen and set to FALSE */ { - msg_attr(prefix, 0); /* don't use msg(), it overwrites "v:statusmsg" */ + /* don't use msg() or msg_attr() to avoid overwriting "v:statusmsg" */ + msg_start(); + msg_puts(prefix); if (name != NULL) /* "a:" vars don't have a name stored */ msg_puts(name); msg_putchar(' '); @@ -17847,6 +18087,11 @@ if (type == VAR_FUNC) msg_puts((char_u *)"()"); + if (*first) + { + msg_clr_eos(); + *first = FALSE; + } } /* @@ -19136,6 +19381,28 @@ goto theend; } + /* Check if the name is a Funcref. If so, use the value. */ + if (lv.ll_exp_name != NULL) + { + len = (int)STRLEN(lv.ll_exp_name); + name = deref_func_name(lv.ll_exp_name, &len); + if (name == lv.ll_exp_name) + name = NULL; + } + else + { + len = (int)(end - *pp); + name = deref_func_name(*pp, &len); + if (name == *pp) + name = NULL; + } + if (name != NULL) + { + name = vim_strsave(name); + *pp = end; + goto theend; + } + if (lv.ll_exp_name != NULL) { len = (int)STRLEN(lv.ll_exp_name); @@ -19969,6 +20236,7 @@ char_u buf[MSG_BUF_LEN]; char_u numbuf2[NUMBUFLEN]; char_u *tofree; + char_u *s; msg_puts((char_u *)"("); for (i = 0; i < argcount; ++i) @@ -19979,10 +20247,13 @@ msg_outnum((long)argvars[i].vval.v_number); else { - trunc_string(tv2string(&argvars[i], &tofree, - numbuf2, 0), buf, MSG_BUF_CLEN); - msg_puts(buf); - vim_free(tofree); + s = tv2string(&argvars[i], &tofree, numbuf2, 0); + if (s != NULL) + { + trunc_string(s, buf, MSG_BUF_CLEN); + msg_puts(buf); + vim_free(tofree); + } } } msg_puts((char_u *)")"); @@ -20060,14 +20331,18 @@ char_u buf[MSG_BUF_LEN]; char_u numbuf2[NUMBUFLEN]; char_u *tofree; + char_u *s; /* The value may be very long. Skip the middle part, so that we * have some idea how it starts and ends. smsg() would always * truncate it at the end. */ - trunc_string(tv2string(fc.rettv, &tofree, numbuf2, 0), - buf, MSG_BUF_CLEN); - smsg((char_u *)_("%s returning %s"), sourcing_name, buf); - vim_free(tofree); + s = tv2string(fc.rettv, &tofree, numbuf2, 0); + if (s != NULL) + { + trunc_string(s, buf, MSG_BUF_CLEN); + smsg((char_u *)_("%s returning %s"), sourcing_name, buf); + vim_free(tofree); + } } msg_puts((char_u *)"\n"); /* don't overwrite this either */ @@ -21034,14 +21309,27 @@ *usedlen += 2; s = get_past_head(*fnamep); while (tail > s && after_pathsep(s, tail)) - --tail; + mb_ptr_back(*fnamep, tail); *fnamelen = (int)(tail - *fnamep); #ifdef VMS if (*fnamelen > 0) *fnamelen += 1; /* the path separator is part of the path */ #endif - while (tail > s && !after_pathsep(s, tail)) - mb_ptr_back(*fnamep, tail); + if (*fnamelen == 0) + { + /* Result is empty. Turn it into "." to make ":cd %:h" work. */ + p = vim_strsave((char_u *)"."); + if (p == NULL) + return -1; + vim_free(*bufp); + *bufp = *fnamep = tail = p; + *fnamelen = 1; + } + else + { + while (tail > s && !after_pathsep(s, tail)) + mb_ptr_back(*fnamep, tail); + } } /* ":8" - shortname */ diff -Naur vim71.orig/src/ex_cmds.c vim71/src/ex_cmds.c --- vim71.orig/src/ex_cmds.c 2007-05-07 19:41:01.000000000 +0000 +++ vim71/src/ex_cmds.c 2008-01-04 18:35:01.000000000 +0000 @@ -408,7 +408,11 @@ goto sortend; } *s = NUL; - regmatch.regprog = vim_regcomp(p + 1, RE_MAGIC); + /* Use last search pattern if sort pattern is empty. */ + if (s == p + 1 && last_search_pat() != NULL) + regmatch.regprog = vim_regcomp(last_search_pat(), RE_MAGIC); + else + regmatch.regprog = vim_regcomp(p + 1, RE_MAGIC); if (regmatch.regprog == NULL) goto sortend; p = s; /* continue after the regexp */ @@ -1646,7 +1650,7 @@ { vim_snprintf((char *)IObuff, IOSIZE, _("%sviminfo: %s in line: "), errnum, message); - STRNCAT(IObuff, line, IOSIZE - STRLEN(IObuff)); + STRNCAT(IObuff, line, IOSIZE - STRLEN(IObuff) - 1); if (IObuff[STRLEN(IObuff) - 1] == '\n') IObuff[STRLEN(IObuff) - 1] = NUL; emsg(IObuff); @@ -1770,7 +1774,8 @@ * overwrite a user's viminfo file after a "su root", with a * viminfo file that the user can't read. */ - st_old.st_dev = st_old.st_ino = 0; + st_old.st_dev = 0; + st_old.st_ino = 0; st_old.st_mode = 0600; if (mch_stat((char *)fname, &st_old) == 0 && getuid() != ROOT_UID @@ -2727,6 +2732,9 @@ && vim_strchr(p_cpo, CPO_OVERNEW) == NULL) || (buf->b_flags & BF_READERR)) && !p_wa +#ifdef FEAT_QUICKFIX + && !bt_nofile(buf) +#endif && vim_fexists(ffname)) { if (!eap->forceit && !eap->append) @@ -2912,22 +2920,35 @@ } /* - * Check if a buffer is read-only. Ask for overruling in a dialog. - * Return TRUE and give an error message when the buffer is readonly. + * Check if a buffer is read-only (either 'readonly' option is set or file is + * read-only). Ask for overruling in a dialog. Return TRUE and give an error + * message when the buffer is readonly. */ static int check_readonly(forceit, buf) int *forceit; buf_T *buf; { - if (!*forceit && buf->b_p_ro) + struct stat st; + + /* Handle a file being readonly when the 'readonly' option is set or when + * the file exists and permissions are read-only. + * We will send 0777 to check_file_readonly(), as the "perm" variable is + * important for device checks but not here. */ + if (!*forceit && (buf->b_p_ro + || (mch_stat((char *)buf->b_ffname, &st) >= 0 + && check_file_readonly(buf->b_ffname, 0777)))) { #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) if ((p_confirm || cmdmod.confirm) && buf->b_fname != NULL) { char_u buff[IOSIZE]; - dialog_msg(buff, _("'readonly' option is set for \"%s\".\nDo you wish to write anyway?"), + if (buf->b_p_ro) + dialog_msg(buff, _("'readonly' option is set for \"%s\".\nDo you wish to write anyway?"), + buf->b_fname); + else + dialog_msg(buff, _("File permissions of \"%s\" are read-only.\nIt may still be possible to write it.\nDo you wish to try?"), buf->b_fname); if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2) == VIM_YES) @@ -2941,9 +2962,14 @@ } else #endif + if (buf->b_p_ro) EMSG(_(e_readonly)); + else + EMSG2(_("E505: \"%s\" is read-only (add ! to override)"), + buf->b_fname); return TRUE; } + return FALSE; } @@ -2952,7 +2978,7 @@ * 'fnum' is the number of the file, if zero use ffname/sfname. * * Return 1 for "normal" error, 2 for "not written" error, 0 for success - * -1 for succesfully opening another file. + * -1 for successfully opening another file. * 'lnum' is the line number for the cursor in the new file (if non-zero). */ int @@ -3367,7 +3393,7 @@ * was in this window (or another window). If not used * before, reset the local window options to the global * values. Also restores old folding stuff. */ - get_winopts(buf); + get_winopts(curbuf); #ifdef FEAT_SPELL did_get_winopts = TRUE; #endif @@ -3562,9 +3588,20 @@ curwin_init(); #ifdef FEAT_FOLDING - /* It's like all lines in the buffer changed. Need to update - * automatic folding. */ + /* It's possible that all lines in the buffer changed. Need to update + * automatic folding for all windows where it's used. */ +# ifdef FEAT_WINDOWS + { + win_T *win; + tabpage_T *tp; + + FOR_ALL_TAB_WINDOWS(tp, win) + if (win->w_buffer == curbuf) + foldUpdateAll(win); + } +# else foldUpdateAll(curwin); +# endif #endif /* Change directories when the 'acd' option is set. */ @@ -3649,8 +3686,8 @@ #ifdef FEAT_SPELL /* If the window options were changed may need to set the spell language. * Can only do this after the buffer has been properly setup. */ - if (did_get_winopts && curwin->w_p_spell && *buf->b_p_spl != NUL) - did_set_spelllang(buf); + if (did_get_winopts && curwin->w_p_spell && *curbuf->b_p_spl != NUL) + did_set_spelllang(curbuf); #endif if (command == NULL) @@ -3754,7 +3791,7 @@ workshop_file_opened((char *)curbuf->b_ffname, curbuf->b_p_ro); # endif # ifdef FEAT_NETBEANS_INTG - if (usingNetbeans & ((flags & ECMD_SET_HELP) != ECMD_SET_HELP)) + if (usingNetbeans && ((flags & ECMD_SET_HELP) != ECMD_SET_HELP)) netbeans_file_opened(curbuf); # endif } @@ -4175,11 +4212,6 @@ sub_nlines = 0; } -#ifdef FEAT_FKMAP /* reverse the flow of the Farsi characters */ - if (p_altkeymap && curwin->w_p_rl) - lrF_sub(cmd); -#endif - if (eap->cmdidx == CMD_tilde) which_pat = RE_LAST; /* use last used regexp */ else @@ -4215,6 +4247,10 @@ } else /* find the end of the regexp */ { +#ifdef FEAT_FKMAP /* reverse the flow of the Farsi characters */ + if (p_altkeymap && curwin->w_p_rl) + lrF_sub(cmd); +#endif which_pat = RE_LAST; /* use last used regexp */ delimiter = *cmd++; /* remember delimiter character */ pat = cmd; /* remember start of search pat */ @@ -4294,6 +4330,7 @@ do_error = TRUE; do_print = FALSE; do_count = FALSE; + do_number = FALSE; do_ic = 0; } while (*cmd) @@ -4464,7 +4501,7 @@ * * The new text is built up in new_start[]. It has some extra * room to avoid using alloc()/free() too often. new_start_len is - * the lenght of the allocated memory at new_start. + * the length of the allocated memory at new_start. * * Make a copy of the old line, so it won't be taken away when * updating the screen or handling a multi-line match. The "old_" @@ -4538,6 +4575,7 @@ { matchcol = (colnr_T)STRLEN(sub_firstline); nmatch = 1; + skip_match = TRUE; } sub_nsubs++; did_sub = TRUE; @@ -4635,7 +4673,7 @@ #endif ++no_mapping; /* don't map this key */ ++allow_keys; /* allow special keys */ - i = safe_vgetc(); + i = plain_vgetc(); --allow_keys; --no_mapping; @@ -4850,7 +4888,8 @@ ++line2; /* move the cursor to the new line, like Vi */ ++curwin->w_cursor.lnum; - STRCPY(new_start, p1 + 1); /* copy the rest */ + /* copy the rest */ + mch_memmove(new_start, p1 + 1, STRLEN(p1 + 1) + 1); p1 = new_start - 1; } } @@ -6351,9 +6390,9 @@ for (i = 0; i < ga.ga_len; ++i) { s = ((char_u **)ga.ga_data)[i]; - if (STRNCMP(s, "help-tags", 9) == 0) + if (STRNCMP(s, "help-tags\t", 10) == 0) /* help-tags entry was added in formatted form */ - fprintf(fd_tags, (char *)s); + fputs((char *)s, fd_tags); else { fprintf(fd_tags, "%s\t/*", s); diff -Naur vim71.orig/src/ex_cmds2.c vim71/src/ex_cmds2.c --- vim71.orig/src/ex_cmds2.c 2007-05-07 19:25:02.000000000 +0000 +++ vim71/src/ex_cmds2.c 2008-01-04 18:35:01.000000000 +0000 @@ -93,6 +93,8 @@ int save_emsg_silent = emsg_silent; int save_redir_off = redir_off; tasave_T typeaheadbuf; + int typeahead_saved = FALSE; + int save_ignore_script = 0; # ifdef FEAT_EX_EXTRA int save_ex_normal_busy; # endif @@ -159,18 +161,26 @@ * This makes sure we get input from the user here and don't interfere * with the commands being executed. Reset "ex_normal_busy" to avoid * the side effects of using ":normal". Save the stuff buffer and make - * it empty. */ + * it empty. Set ignore_script to avoid reading from script input. */ # ifdef FEAT_EX_EXTRA save_ex_normal_busy = ex_normal_busy; ex_normal_busy = 0; # endif if (!debug_greedy) + { save_typeahead(&typeaheadbuf); + typeahead_saved = TRUE; + save_ignore_script = ignore_script; + ignore_script = TRUE; + } cmdline = getcmdline_prompt('>', NULL, 0, EXPAND_NOTHING, NULL); - if (!debug_greedy) + if (typeahead_saved) + { restore_typeahead(&typeaheadbuf); + ignore_script = save_ignore_script; + } # ifdef FEAT_EX_EXTRA ex_normal_busy = save_ex_normal_busy; # endif diff -Naur vim71.orig/src/ex_docmd.c vim71/src/ex_docmd.c --- vim71.orig/src/ex_docmd.c 2007-05-07 19:49:38.000000000 +0000 +++ vim71/src/ex_docmd.c 2008-01-04 18:35:01.000000000 +0000 @@ -133,6 +133,7 @@ static void get_flags __ARGS((exarg_T *eap)); #if !defined(FEAT_PERL) || !defined(FEAT_PYTHON) || !defined(FEAT_TCL) \ || !defined(FEAT_RUBY) || !defined(FEAT_MZSCHEME) +# define HAVE_EX_SCRIPT_NI static void ex_script_ni __ARGS((exarg_T *eap)); #endif static char_u *invalid_range __ARGS((exarg_T *eap)); @@ -275,7 +276,6 @@ static void ex_swapname __ARGS((exarg_T *eap)); static void ex_syncbind __ARGS((exarg_T *eap)); static void ex_read __ARGS((exarg_T *eap)); -static void ex_cd __ARGS((exarg_T *eap)); static void ex_pwd __ARGS((exarg_T *eap)); static void ex_equal __ARGS((exarg_T *eap)); static void ex_sleep __ARGS((exarg_T *eap)); @@ -372,7 +372,7 @@ static char_u *arg_all __ARGS((void)); #ifdef FEAT_SESSION static int makeopens __ARGS((FILE *fd, char_u *dirnow)); -static int put_view __ARGS((FILE *fd, win_T *wp, int add_edit, unsigned *flagp)); +static int put_view __ARGS((FILE *fd, win_T *wp, int add_edit, unsigned *flagp, int current_arg_idx)); static void ex_loadview __ARGS((exarg_T *eap)); static char_u *get_view_file __ARGS((int c)); static int did_lcd; /* whether ":lcd" was produced for a session */ @@ -666,7 +666,7 @@ if (ex_pressedreturn) { /* go up one line, to overwrite the ":" line, so the - * output doensn't contain empty lines. */ + * output doesn't contain empty lines. */ msg_row = prev_msg_row; if (prev_msg_row == Rows - 1) msg_row--; @@ -1741,7 +1741,9 @@ } /* ignore comment and empty lines */ - if (*ea.cmd == '"' || *ea.cmd == NUL) + if (*ea.cmd == '"') + goto doend; + if (*ea.cmd == NUL) { ex_pressedreturn = TRUE; goto doend; @@ -2118,7 +2120,11 @@ #ifdef FEAT_USR_CMDS !USER_CMDIDX(ea.cmdidx) && #endif - cmdnames[ea.cmdidx].cmd_func == ex_ni); + (cmdnames[ea.cmdidx].cmd_func == ex_ni +#ifdef HAVE_EX_SCRIPT_NI + || cmdnames[ea.cmdidx].cmd_func == ex_script_ni +#endif + )); #ifndef FEAT_EVAL /* @@ -2654,7 +2660,7 @@ errormsg = IObuff; } STRCAT(errormsg, ": "); - STRNCAT(errormsg, *cmdlinep, IOSIZE - STRLEN(IObuff)); + STRNCAT(errormsg, *cmdlinep, IOSIZE - STRLEN(IObuff) - 1); } emsg(errormsg); } @@ -2756,7 +2762,7 @@ /* * Isolate the command and search for it in the command table. - * Exeptions: + * Exceptions: * - the 'k' command can directly be followed by any character. * - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r' * but :sre[wind] is another command, as are :scrip[tnames], @@ -2957,6 +2963,57 @@ #endif #if defined(FEAT_EVAL) || defined(PROTO) +static struct cmdmod +{ + char *name; + int minlen; + int has_count; /* :123verbose :3tab */ +} cmdmods[] = { + {"aboveleft", 3, FALSE}, + {"belowright", 3, FALSE}, + {"botright", 2, FALSE}, + {"browse", 3, FALSE}, + {"confirm", 4, FALSE}, + {"hide", 3, FALSE}, + {"keepalt", 5, FALSE}, + {"keepjumps", 5, FALSE}, + {"keepmarks", 3, FALSE}, + {"leftabove", 5, FALSE}, + {"lockmarks", 3, FALSE}, + {"rightbelow", 6, FALSE}, + {"sandbox", 3, FALSE}, + {"silent", 3, FALSE}, + {"tab", 3, TRUE}, + {"topleft", 2, FALSE}, + {"verbose", 4, TRUE}, + {"vertical", 4, FALSE}, +}; + +/* + * Return length of a command modifier (including optional count). + * Return zero when it's not a modifier. + */ + int +modifier_len(cmd) + char_u *cmd; +{ + int i, j; + char_u *p = cmd; + + if (VIM_ISDIGIT(*cmd)) + p = skipwhite(skipdigits(cmd)); + for (i = 0; i < sizeof(cmdmods) / sizeof(struct cmdmod); ++i) + { + for (j = 0; p[j] != NUL; ++j) + if (p[j] != cmdmods[i].name[j]) + break; + if (!isalpha(p[j]) && j >= cmdmods[i].minlen + && (p == cmd || cmdmods[i].has_count)) + return j + (p - cmd); + } + return 0; +} + /* * Return > 0 if an Ex command "name" exists. * Return 2 if there is an exact match. @@ -2971,30 +3028,6 @@ int i; int j; char_u *p; - static struct cmdmod - { - char *name; - int minlen; - } cmdmods[] = { - {"aboveleft", 3}, - {"belowright", 3}, - {"botright", 2}, - {"browse", 3}, - {"confirm", 4}, - {"hide", 3}, - {"keepalt", 5}, - {"keepjumps", 5}, - {"keepmarks", 3}, - {"leftabove", 5}, - {"lockmarks", 3}, - {"rightbelow", 6}, - {"sandbox", 3}, - {"silent", 3}, - {"tab", 3}, - {"topleft", 2}, - {"verbose", 4}, - {"vertical", 4}, - }; /* Check command modifiers. */ for (i = 0; i < sizeof(cmdmods) / sizeof(struct cmdmod); ++i) @@ -3276,39 +3309,65 @@ if (ea.argt & XFILE) { - int in_quote = FALSE; - char_u *bow = NULL; /* Beginning of word */ + int c; + int in_quote = FALSE; + char_u *bow = NULL; /* Beginning of word */ /* * Allow spaces within back-quotes to count as part of the argument * being expanded. */ xp->xp_pattern = skipwhite(arg); - for (p = xp->xp_pattern; *p; ) + p = xp->xp_pattern; + while (*p != NUL) { - if (*p == '\\' && p[1] != NUL) +#ifdef FEAT_MBYTE + if (has_mbyte) + c = mb_ptr2char(p); + else +#endif + c = *p; + if (c == '\\' && p[1] != NUL) ++p; + else if (c == '`') + { + if (!in_quote) + { + xp->xp_pattern = p; + bow = p + 1; + } + in_quote = !in_quote; + } #ifdef SPACE_IN_FILENAME - else if (vim_iswhite(*p) && (!(ea.argt & NOSPC) || usefilter)) + else if (!vim_isfilec_or_wc(c) + && (!(ea.argt & NOSPC) || usefilter)) #else - else if (vim_iswhite(*p)) + else if (!vim_isfilec_or_wc(c)) #endif { - p = skipwhite(p); + while (*p != NUL) + { +#ifdef FEAT_MBYTE + if (has_mbyte) + c = mb_ptr2char(p); + else +#endif + c = *p; + if (c == '`' || vim_isfilec_or_wc(c)) + break; +#ifdef FEAT_MBYTE + if (has_mbyte) + len = (*mb_ptr2len)(p); + else +#endif + len = 1; + mb_ptr_adv(p); + } if (in_quote) bow = p; else xp->xp_pattern = p; - --p; - } - else if (*p == '`') - { - if (!in_quote) - { - xp->xp_pattern = p; - bow = p + 1; - } - in_quote = !in_quote; + p -= len; } mb_ptr_adv(p); } @@ -3401,14 +3460,13 @@ case CMD_windo: return arg; -#ifdef FEAT_SEARCH_EXTRA +#ifdef FEAT_CMDL_COMPL +# ifdef FEAT_SEARCH_EXTRA case CMD_match: if (*arg == NUL || !ends_excmd(*arg)) { - /* Dummy call to clear variables. */ - set_context_in_highlight_cmd(xp, (char_u *)"link n"); - xp->xp_context = EXPAND_HIGHLIGHT; - xp->xp_pattern = arg; + /* also complete "None" */ + set_context_in_echohl_cmd(xp, arg); arg = skipwhite(skiptowhite(arg)); if (*arg != NUL) { @@ -3417,9 +3475,8 @@ } } return find_nextcmd(arg); -#endif +# endif -#ifdef FEAT_CMDL_COMPL /* * All completion for the +cmdline_compl feature goes here. */ @@ -3617,8 +3674,7 @@ break; case CMD_echohl: - xp->xp_context = EXPAND_HIGHLIGHT; - xp->xp_pattern = arg; + set_context_in_echohl_cmd(xp, arg); break; #endif case CMD_highlight: @@ -3997,8 +4053,7 @@ eap->errmsg = (char_u *)N_("E319: Sorry, the command is not available in this version"); } -#if !defined(FEAT_PERL) || !defined(FEAT_PYTHON) || !defined(FEAT_TCL) \ - || !defined(FEAT_RUBY) || !defined(FEAT_MZSCHEME) +#ifdef HAVE_EX_SCRIPT_NI /* * Function called for script command which is Not Implemented. NI! * Skips over ":perl <arg, '~') != NULL) { expand_env_esc(eap->arg, NameBuff, MAXPATHL, - TRUE, NULL); + TRUE, TRUE, NULL); has_wildcards = mch_has_wildcard(NameBuff); p = NameBuff; } @@ -4492,7 +4547,8 @@ if (eap->argt & (USECTRLV | XFILE)) ++p; /* skip CTRL-V and next char */ else - STRCPY(p, p + 1); /* remove CTRL-V and skip next char */ + /* remove CTRL-V and skip next char */ + mch_memmove(p, p + 1, STRLEN(p)); if (*p == NUL) /* stop at NUL after CTRL-V */ break; } @@ -6650,7 +6706,7 @@ * The list should be allocated using alloc(), as should each item in the * list. This function takes over responsibility for freeing the list. * - * XXX The list is made into the arggument list. This is freed using + * XXX The list is made into the argument list. This is freed using * FreeWild(), which does a series of vim_free() calls, unless the two defines * __EMX__ and __ALWAYS_HAS_TRAILING_NUL_POINTER are set. In this case, a * routine _fnexplodefree() is used. This may cause problems, but as the drop @@ -7743,6 +7799,7 @@ free_cd_dir() { vim_free(prev_dir); + prev_dir = NULL; } #endif @@ -7750,7 +7807,7 @@ /* * ":cd", ":lcd", ":chdir" and ":lchdir". */ - static void + void ex_cd(eap) exarg_T *eap; { @@ -7768,7 +7825,7 @@ if (vim_strchr(p_cpo, CPO_CHDIR) != NULL && curbufIsChanged() && !eap->forceit) { - EMSG(_("E747: Cannot change directory, buffer is modifed (add ! to override)")); + EMSG(_("E747: Cannot change directory, buffer is modified (add ! to override)")); return; } @@ -8399,21 +8456,17 @@ || *arg == '"') { redir_reg = *arg++; - if (*arg == '>' && arg[1] == '>') + if (*arg == '>' && arg[1] == '>') /* append */ arg += 2; - else if ((*arg == NUL || (*arg == '>' && arg[1] == NUL)) && - (islower(redir_reg) -# ifdef FEAT_CLIPBOARD - || redir_reg == '*' - || redir_reg == '+' -# endif - || redir_reg == '"')) + else { + /* Can use both "@a" and "@a>". */ if (*arg == '>') arg++; - - /* make register empty */ - write_reg_contents(redir_reg, (char_u *)"", -1, FALSE); + /* Make register empty when not using @A-@Z and the + * command is valid. */ + if (*arg == NUL && !isupper(redir_reg)) + write_reg_contents(redir_reg, (char_u *)"", -1, FALSE); } } if (*arg != NUL) @@ -8710,7 +8763,8 @@ } else { - failed |= (put_view(fd, curwin, !using_vdir, flagp) == FAIL); + failed |= (put_view(fd, curwin, !using_vdir, flagp, + -1) == FAIL); } if (put_line(fd, "let &so = s:so_save | let &siso = s:siso_save") == FAIL) @@ -9368,7 +9422,7 @@ if (src > srcstart && src[-1] == '\\') { *usedlen = 0; - STRCPY(src - 1, src); /* remove backslash */ + mch_memmove(src - 1, src, STRLEN(src) + 1); /* remove backslash */ return NULL; } @@ -9468,6 +9522,7 @@ *errormsg = (char_u *)_("E495: no autocommand file name to substitute for \"\""); return NULL; } + result = shorten_fname1(result); break; case SPEC_ABUF: /* buffer number for autocommand */ @@ -9709,6 +9764,8 @@ int tabnr; win_T *tab_firstwin; frame_T *tab_topframe; + int cur_arg_idx = 0; + int next_arg_idx = 0; if (ssop_flags & SSOP_BUFFERS) only_save_windows = FALSE; /* Save ALL buffers */ @@ -9924,12 +9981,19 @@ { if (!ses_do_win(wp)) continue; - if (put_view(fd, wp, wp != edited_win, &ssop_flags) == FAIL) + if (put_view(fd, wp, wp != edited_win, &ssop_flags, + cur_arg_idx) == FAIL) return FAIL; if (nr > 1 && put_line(fd, "wincmd w") == FAIL) return FAIL; + next_arg_idx = wp->w_arg_idx; } + /* The argument index in the first tab page is zero, need to set it in + * each window. For further tab pages it's the window where we do + * "tabedit". */ + cur_arg_idx = next_arg_idx; + /* * Restore cursor to the current window if it's not the first one. */ @@ -10138,11 +10202,13 @@ * Caller must make sure 'scrolloff' is zero. */ static int -put_view(fd, wp, add_edit, flagp) +put_view(fd, wp, add_edit, flagp, current_arg_idx) FILE *fd; win_T *wp; int add_edit; /* add ":edit" command to view */ unsigned *flagp; /* vop_flags or ssop_flags */ + int current_arg_idx; /* current argument index of the window, use + * -1 if unknown */ { win_T *save_curwin; int f; @@ -10172,10 +10238,10 @@ /* Only when part of a session: restore the argument index. Some * arguments may have been deleted, check if the index is valid. */ - if (wp->w_arg_idx != 0 && wp->w_arg_idx <= WARGCOUNT(wp) + if (wp->w_arg_idx != current_arg_idx && wp->w_arg_idx <= WARGCOUNT(wp) && flagp == &ssop_flags) { - if (fprintf(fd, "%ldnext", (long)wp->w_arg_idx) < 0 + if (fprintf(fd, "%ldargu", (long)wp->w_arg_idx + 1) < 0 || put_eol(fd) == FAIL) return FAIL; did_next = TRUE; @@ -10816,12 +10882,13 @@ exarg_T *eap; { char_u *p; + char_u *g = NULL; char_u *end; int c; - int mi; + int id; if (eap->line2 <= 3) - mi = eap->line2 - 1; + id = eap->line2; else { EMSG(e_invcmd); @@ -10830,13 +10897,7 @@ /* First clear any old pattern. */ if (!eap->skip) - { - vim_free(curwin->w_match[mi].regprog); - curwin->w_match[mi].regprog = NULL; - vim_free(curwin->w_match_pat[mi]); - curwin->w_match_pat[mi] = NULL; - redraw_later(SOME_VALID); /* always need a redraw */ - } + match_delete(curwin, id, FALSE); if (ends_excmd(*eap->arg)) end = eap->arg; @@ -10847,15 +10908,7 @@ { p = skiptowhite(eap->arg); if (!eap->skip) - { - curwin->w_match_id[mi] = syn_namen2id(eap->arg, - (int)(p - eap->arg)); - if (curwin->w_match_id[mi] == 0) - { - EMSG2(_(e_nogroup), eap->arg); - return; - } - } + g = vim_strnsave(eap->arg, (int)(p - eap->arg)); p = skipwhite(p); if (*p == NUL) { @@ -10879,14 +10932,8 @@ c = *end; *end = NUL; - curwin->w_match[mi].regprog = vim_regcomp(p + 1, RE_MAGIC); - if (curwin->w_match[mi].regprog == NULL) - { - EMSG2(_(e_invarg2), p); - *end = c; - return; - } - curwin->w_match_pat[mi] = vim_strsave(p + 1); + match_add(curwin, g, p + 1, 10, id); + vim_free(g); *end = c; } } diff -Naur vim71.orig/src/ex_eval.c vim71/src/ex_eval.c --- vim71.orig/src/ex_eval.c 2007-05-07 19:47:50.000000000 +0000 +++ vim71/src/ex_eval.c 2008-01-04 18:35:00.000000000 +0000 @@ -1551,7 +1551,7 @@ } save_cpo = p_cpo; p_cpo = (char_u *)""; - regmatch.regprog = vim_regcomp(pat, TRUE); + regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING); regmatch.rm_ic = FALSE; if (end != NULL) *end = save_char; @@ -2269,9 +2269,18 @@ has_loop_cmd(p) char_u *p; { - p = skipwhite(p); - while (*p == ':') - p = skipwhite(p + 1); + int len; + + /* skip modifiers, white space and ':' */ + for (;;) + { + while (*p == ' ' || *p == '\t' || *p == ':') + ++p; + len = modifier_len(p); + if (len == 0) + break; + p += len; + } if ((p[0] == 'w' && p[1] == 'h') || (p[0] == 'f' && p[1] == 'o' && p[2] == 'r')) return TRUE; diff -Naur vim71.orig/src/ex_getln.c vim71/src/ex_getln.c --- vim71.orig/src/ex_getln.c 2007-05-07 19:47:23.000000000 +0000 +++ vim71/src/ex_getln.c 2008-01-04 18:35:01.000000000 +0000 @@ -268,7 +268,9 @@ { xpc.xp_context = ccline.xp_context; xpc.xp_pattern = ccline.cmdbuff; +# if defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL) xpc.xp_arg = ccline.xp_arg; +# endif } #endif @@ -333,7 +335,14 @@ quit_more = FALSE; /* reset after CTRL-D which had a more-prompt */ cursorcmd(); /* set the cursor on the right spot */ - c = safe_vgetc(); + + /* Get a character. Ignore K_IGNORE, it should not do anything, such + * as stop completion. */ + do + { + c = safe_vgetc(); + } while (c == K_IGNORE); + if (KeyTyped) { some_key_typed = TRUE; @@ -484,7 +493,8 @@ if (xpc.xp_context == EXPAND_MENUNAMES && p_wmnu) { /* Hitting after "emenu Name.": complete submenu */ - if (ccline.cmdbuff[ccline.cmdpos - 1] == '.' && c == K_DOWN) + if (c == K_DOWN && ccline.cmdpos > 0 + && ccline.cmdbuff[ccline.cmdpos - 1] == '.') c = p_wc; else if (c == K_UP) { @@ -533,9 +543,11 @@ upseg[3] = PATHSEP; upseg[4] = NUL; - if (ccline.cmdbuff[ccline.cmdpos - 1] == PATHSEP - && c == K_DOWN - && (ccline.cmdbuff[ccline.cmdpos - 2] != '.' + if (c == K_DOWN + && ccline.cmdpos > 0 + && ccline.cmdbuff[ccline.cmdpos - 1] == PATHSEP + && (ccline.cmdpos < 3 + || ccline.cmdbuff[ccline.cmdpos - 2] != '.' || ccline.cmdbuff[ccline.cmdpos - 3] != '.')) { /* go down a directory */ @@ -636,7 +648,7 @@ { ++no_mapping; ++allow_keys; - c = safe_vgetc(); + c = plain_vgetc(); --no_mapping; --allow_keys; /* CTRL-\ e doesn't work when obtaining an expression. */ @@ -730,8 +742,8 @@ /* In Ex mode a backslash escapes a newline. */ if (exmode_active && c != ESC - && ccline.cmdpos > 0 && ccline.cmdpos == ccline.cmdlen + && ccline.cmdpos > 0 && ccline.cmdbuff[ccline.cmdpos - 1] == '\\') { if (c == K_KENTER) @@ -1086,11 +1098,11 @@ #endif putcmdline('"', TRUE); ++no_mapping; - i = c = safe_vgetc(); /* CTRL-R */ + i = c = plain_vgetc(); /* CTRL-R */ if (i == Ctrl_O) i = Ctrl_R; /* CTRL-R CTRL-O == CTRL-R CTRL-R */ if (i == Ctrl_R) - c = safe_vgetc(); /* CTRL-R CTRL-R */ + c = plain_vgetc(); /* CTRL-R CTRL-R */ --no_mapping; #ifdef FEAT_EVAL /* @@ -1181,10 +1193,10 @@ case K_LEFT: case K_S_LEFT: case K_C_LEFT: + if (ccline.cmdpos == 0) + goto cmdline_not_changed; do { - if (ccline.cmdpos == 0) - break; --ccline.cmdpos; #ifdef FEAT_MBYTE if (has_mbyte) /* move to first byte of char */ @@ -1193,7 +1205,8 @@ #endif ccline.cmdspos -= cmdline_charsize(ccline.cmdpos); } - while ((c == K_S_LEFT || c == K_C_LEFT + while (ccline.cmdpos > 0 + && (c == K_S_LEFT || c == K_C_LEFT || (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL))) && ccline.cmdbuff[ccline.cmdpos - 1] != ' '); #ifdef FEAT_MBYTE @@ -1203,7 +1216,8 @@ goto cmdline_not_changed; case K_IGNORE: - goto cmdline_not_changed; /* Ignore mouse */ + /* Ignore mouse event or ex_window() result. */ + goto cmdline_not_changed; #ifdef FEAT_GUI_W32 /* On Win32 ignore , we get it when closing the window was @@ -2090,11 +2104,11 @@ garray_T line_ga; char_u *pend; int startcol = 0; - int c1; + int c1 = 0; int escaped = FALSE; /* CTRL-V typed */ int vcol = 0; char_u *p; - int prev_char = 0; + int prev_char; /* Switch cursor on now. This avoids that it happens after the "\n", which * confuses the system function that computes tabstops. */ @@ -2147,6 +2161,7 @@ /* Get one character at a time. Don't use inchar(), it can't handle * special characters. */ + prev_char = c1; c1 = vgetc(); /* @@ -2204,7 +2219,6 @@ redraw: /* redraw the line */ msg_col = startcol; - windgoto(msg_row, msg_col); vcol = 0; for (p = (char_u *)line_ga.ga_data; p < (char_u *)line_ga.ga_data + line_ga.ga_len; ++p) @@ -2223,6 +2237,7 @@ } } msg_clr_eos(); + windgoto(msg_row, msg_col); continue; } @@ -2268,7 +2283,6 @@ if (IS_SPECIAL(c1)) c1 = '?'; ((char_u *)line_ga.ga_data)[line_ga.ga_len] = c1; - prev_char = c1; if (c1 == '\n') msg_putchar('\n'); else if (c1 == TAB) @@ -3311,6 +3325,10 @@ * Return a pointer to alloced memory containing the new string. * Return NULL for failure. * + * "orig" is the originally expanded string, copied to allocated memory. It + * should either be kept in orig_save or freed. When "mode" is WILD_NEXT or + * WILD_PREV "orig" should be NULL. + * * Results are cached in xp->xp_files and xp->xp_numfiles, except when "mode" * is WILD_EXPAND_FREE or WILD_ALL. * @@ -3344,6 +3362,7 @@ char_u *ss = NULL; static int findex; static char_u *orig_save = NULL; /* kept value of orig */ + int orig_saved = FALSE; int i; long_u len; int non_suf_match; /* number without matching suffix */ @@ -3395,7 +3414,7 @@ return NULL; } -/* free old names */ + /* free old names */ if (xp->xp_numfiles != -1 && mode != WILD_ALL && mode != WILD_LONGEST) { FreeWild(xp->xp_numfiles, xp->xp_files); @@ -3412,6 +3431,7 @@ { vim_free(orig_save); orig_save = orig; + orig_saved = TRUE; /* * Do the expansion. @@ -3536,6 +3556,10 @@ if (mode == WILD_EXPAND_FREE || mode == WILD_ALL) ExpandCleanup(xp); + /* Free "orig" if it wasn't stored in "orig_save". */ + if (!orig_saved) + vim_free(orig); + return ss; } @@ -4054,6 +4078,7 @@ * ~ would be at the start of the file name, but not the tail. * $ could be anywhere in the tail. * ` could be anywhere in the file name. + * When the name ends in '$' don't add a star, remove the '$'. */ tail = gettail(retval); if ((*retval != '~' || tail != retval) @@ -4061,6 +4086,8 @@ && vim_strchr(tail, '$') == NULL && vim_strchr(retval, '`') == NULL) retval[len++] = '*'; + else if (len > 0 && retval[len - 1] == '$') + --len; retval[len] = NUL; } } @@ -4148,13 +4175,19 @@ #ifdef FEAT_EVAL if (ccline.cmdfirstc == '=') + { +# ifdef FEAT_CMDL_COMPL /* pass CMD_SIZE because there is no real command */ set_context_for_expression(xp, str, CMD_SIZE); +# endif + } else if (ccline.input_fn) { xp->xp_context = ccline.xp_context; xp->xp_pattern = ccline.cmdbuff; +# if defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL) xp->xp_arg = ccline.xp_arg; +# endif } else #endif @@ -4295,10 +4328,11 @@ && pat[i + 1] == '\\' && pat[i + 2] == '\\' && pat[i + 3] == ' ') - STRCPY(pat + i, pat + i + 3); + mch_memmove(pat + i, pat + i + 3, + STRLEN(pat + i + 3) + 1); if (xp->xp_backslash == XP_BS_ONE && pat[i + 1] == ' ') - STRCPY(pat + i, pat + i + 1); + mch_memmove(pat + i, pat + i + 1, STRLEN(pat + i)); } } @@ -4502,6 +4536,12 @@ if (xp->xp_context != EXPAND_MENUNAMES && xp->xp_context != EXPAND_MENUS) sort_strings(*file, *num_file); +#ifdef FEAT_CMDL_COMPL + /* Reset the variables used for special highlight names expansion, so that + * they don't show up when getting normal highlight names by ID. */ + reset_expand_highlight(); +#endif + return OK; } @@ -4535,7 +4575,7 @@ pat = vim_strsave(filepat); for (i = 0; pat[i]; ++i) if (pat[i] == '\\' && pat[i + 1] == ' ') - STRCPY(pat + i, pat + i + 1); + mch_memmove(pat + i, pat + i + 1, STRLEN(pat + i)); flags |= EW_FILE | EW_EXEC; @@ -5907,7 +5947,7 @@ # ifdef FEAT_AUTOCMD /* Don't execute autocommands while creating the window. */ - ++autocmd_block; + block_autocmds(); # endif /* don't use a new tab page */ cmdmod.tab = 0; @@ -5916,6 +5956,9 @@ if (win_split((int)p_cwh, WSP_BOT) == FAIL) { beep_flush(); +# ifdef FEAT_AUTOCMD + unblock_autocmds(); +# endif return K_IGNORE; } cmdwin_type = ccline.cmdfirstc; @@ -5938,7 +5981,7 @@ # ifdef FEAT_AUTOCMD /* Do execute autocommands for setting the filetype (load syntax). */ - --autocmd_block; + unblock_autocmds(); # endif /* Showing the prompt may have set need_wait_return, reset it. */ @@ -6092,7 +6135,7 @@ # ifdef FEAT_AUTOCMD /* Don't execute autocommands while deleting the window. */ - ++autocmd_block; + block_autocmds(); # endif wp = curwin; bp = curbuf; @@ -6104,7 +6147,7 @@ win_size_restore(&winsizes); # ifdef FEAT_AUTOCMD - --autocmd_block; + unblock_autocmds(); # endif } diff -Naur vim71.orig/src/feature.h vim71/src/feature.h --- vim71.orig/src/feature.h 2007-05-07 19:33:19.000000000 +0000 +++ vim71/src/feature.h 2008-01-04 18:34:59.000000000 +0000 @@ -673,7 +673,7 @@ # define ESC_CHG_TO_ENG_MODE /* if defined, when ESC pressed, * turn to english mode */ -# if !defined(FEAT_XFONTSET) && defined(HAVE_X11) +# if !defined(FEAT_XFONTSET) && defined(HAVE_X11) && !defined(HAVE_GTK2) # define FEAT_XFONTSET /* Hangul input requires xfontset */ # endif # if defined(FEAT_XIM) && !defined(LINT) diff -Naur vim71.orig/src/fileio.c vim71/src/fileio.c --- vim71.orig/src/fileio.c 2007-05-10 11:29:44.000000000 +0000 +++ vim71/src/fileio.c 2008-01-04 18:35:01.000000000 +0000 @@ -44,6 +44,10 @@ /* Is there any system that doesn't have access()? */ #define USE_MCH_ACCESS +#if defined(sun) && defined(S_ISCHR) +# define OPEN_CHR_FILES +static int is_dev_fd_file(char_u *fname); +#endif #ifdef FEAT_MBYTE static char_u *next_fenc __ARGS((char_u **pp)); # ifdef FEAT_EVAL @@ -110,7 +114,7 @@ { int bw_fd; /* file descriptor */ char_u *bw_buf; /* buffer with data to be written */ - int bw_len; /* lenght of data */ + int bw_len; /* length of data */ #ifdef HAS_BW_FLAGS int bw_flags; /* FIO_ flags */ #endif @@ -217,11 +221,12 @@ { int fd = 0; int newfile = (flags & READ_NEW); - int set_options = newfile || (eap != NULL && eap->read_edit); int check_readonly; int filtering = (flags & READ_FILTER); int read_stdin = (flags & READ_STDIN); int read_buffer = (flags & READ_BUFFER); + int set_options = newfile || read_buffer + || (eap != NULL && eap->read_edit); linenr_T read_buf_lnum = 1; /* next line to read from curbuf */ colnr_T read_buf_col = 0; /* next char to read from this line */ char_u c; @@ -406,6 +411,10 @@ # ifdef S_ISSOCK && !S_ISSOCK(perm) /* ... or socket */ # endif +# ifdef OPEN_CHR_FILES + && !(S_ISCHR(perm) && is_dev_fd_file(fname)) + /* ... or a character special file named /dev/fd/ */ +# endif ) { if (S_ISDIR(perm)) @@ -424,7 +433,7 @@ */ if (!p_odev && mch_nodetype(fname) == NODE_WRITABLE) { - filemess(curbuf, fname, (char_u *)_("is a device (disabled with 'opendevice' option"), 0); + filemess(curbuf, fname, (char_u *)_("is a device (disabled with 'opendevice' option)"), 0); msg_end(); msg_scroll = msg_save; return FAIL; @@ -642,10 +651,16 @@ if (set_options) { - curbuf->b_p_eol = TRUE; - curbuf->b_start_eol = TRUE; + /* Don't change 'eol' if reading from buffer as it will already be + * correctly set when reading stdin. */ + if (!read_buffer) + { + curbuf->b_p_eol = TRUE; + curbuf->b_start_eol = TRUE; + } #ifdef FEAT_MBYTE curbuf->b_p_bomb = FALSE; + curbuf->b_start_bomb = FALSE; #endif } @@ -904,7 +919,10 @@ file_rewind = FALSE; #ifdef FEAT_MBYTE if (set_options) + { curbuf->b_p_bomb = FALSE; + curbuf->b_start_bomb = FALSE; + } conv_error = 0; #endif } @@ -1353,7 +1371,10 @@ size -= blen; mch_memmove(ptr, ptr + blen, (size_t)size); if (set_options) + { curbuf->b_p_bomb = TRUE; + curbuf->b_start_bomb = TRUE; + } } if (fio_flags == FIO_UCSBOM) @@ -2265,6 +2286,13 @@ } # endif # endif +# ifdef OPEN_CHR_FILES + if (S_ISCHR(perm)) /* or character special */ + { + STRCAT(IObuff, _("[character special]")); + c = TRUE; + } +# endif #endif if (curbuf->b_p_ro) { @@ -2464,6 +2492,25 @@ return OK; } +#ifdef OPEN_CHR_FILES +/* + * Returns TRUE if the file name argument is of the form "/dev/fd/\d\+", + * which is the name of files used for process substitution output by + * some shells on some operating systems, e.g., bash on SunOS. + * Do not accept "/dev/fd/[012]", opening these may hang Vim. + */ + static int +is_dev_fd_file(fname) + char_u *fname; +{ + return (STRNCMP(fname, "/dev/fd/", 8) == 0 + && VIM_ISDIGIT(fname[8]) + && *skipdigits(fname + 9) == NUL + && (fname[9] != NUL + || (fname[8] != '0' && fname[8] != '1' && fname[8] != '2'))); +} +#endif + #ifdef FEAT_MBYTE /* @@ -2734,6 +2781,32 @@ #endif /* + * Return TRUE if a file appears to be read-only from the file permissions. + */ + int +check_file_readonly(fname, perm) + char_u *fname; /* full path to file */ + int perm; /* known permissions on file */ +{ +#ifndef USE_MCH_ACCESS + int fd = 0; +#endif + + return ( +#ifdef USE_MCH_ACCESS +# ifdef UNIX + (perm & 0222) == 0 || +# endif + mch_access((char *)fname, W_OK) +#else + (fd = mch_open((char *)fname, O_RDWR | O_EXTRA, 0)) < 0 + ? TRUE : (close(fd), FALSE) +#endif + ); +} + + +/* * buf_write() - write to file "fname" lines "start" through "end" * * We do our own buffering here because fwrite() is so slow. @@ -3142,7 +3215,8 @@ * Get information about original file (if there is one). */ #if defined(UNIX) && !defined(ARCHIE) - st_old.st_dev = st_old.st_ino = 0; + st_old.st_dev = 0; + st_old.st_ino = 0; perm = -1; if (mch_stat((char *)fname, &st_old) < 0) newfile = TRUE; @@ -3219,17 +3293,8 @@ * Check if the file is really writable (when renaming the file to * make a backup we won't discover it later). */ - file_readonly = ( -# ifdef USE_MCH_ACCESS -# ifdef UNIX - (perm & 0222) == 0 || -# endif - mch_access((char *)fname, W_OK) -# else - (fd = mch_open((char *)fname, O_RDWR | O_EXTRA, 0)) < 0 - ? TRUE : (close(fd), FALSE) -# endif - ); + file_readonly = check_file_readonly(fname, (int)perm); + if (!forceit && file_readonly) { if (vim_strchr(p_cpo, CPO_FWRITE) != NULL) @@ -4193,7 +4258,8 @@ * they don't it adds one. * With other RMS structures it works perfect without this fix. */ - if ((buf->b_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0) + if (buf->b_fab_rfm == FAB$C_VFC + || ((buf->b_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0)) { int b2write; @@ -5495,6 +5561,30 @@ } #endif +#if defined(FEAT_VIMINFO) || defined(FEAT_BROWSE) || \ + defined(FEAT_QUICKFIX) || defined(FEAT_AUTOCMD) || defined(PROTO) +/* + * Try to find a shortname by comparing the fullname with the current + * directory. + * Returns "full_path" or pointer into "full_path" if shortened. + */ + char_u * +shorten_fname1(full_path) + char_u *full_path; +{ + char_u dirname[MAXPATHL]; + char_u *p = full_path; + + if (mch_dirname(dirname, MAXPATHL) == OK) + { + p = shorten_fname(full_path, dirname); + if (p == NULL || *p == NUL) + p = full_path; + } + return p; +} +#endif + /* * Try to find a shortname by comparing the fullname with the current * directory. @@ -7107,6 +7197,7 @@ static event_T last_event; static int last_group; +static int autocmd_blocked = 0; /* block all autocmds */ /* * Show the autocommands for one AutoPat. @@