Submitted By: Matt Burgess (matthew at linuxfromscratch dot org) Date: 2008-02-17 Initial Package Version: 7.1 Origin: Upstream Upstream Status: Applied Description: Contains patches 001-251 from upstream diff -Naur vim71.orig/runtime/doc/Makefile vim71/runtime/doc/Makefile --- vim71.orig/runtime/doc/Makefile 2006-11-07 20:59:05.000000000 +0000 +++ vim71/runtime/doc/Makefile 2008-02-14 21:07:34.000000000 +0000 @@ -301,7 +301,7 @@ # Use Vim to generate the tags file. Can only be used when Vim has been # compiled and installed. Supports multiple languages. vimtags: $(DOCS) - $(VIMEXE) -u NONE -esX -c "helptags ." -c quit + $(VIMEXE) -u NONE -esX -c "helptags ++t ." -c quit # Use "doctags" to generate the tags file. Only works for English! tags: doctags $(DOCS) 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-02-14 21:07:31.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-02-14 21:07:34.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-02-14 21:07:34.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: 2008 Feb 13 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1401,10 +1401,24 @@ This is the screen column number, like with |virtcol()|. The value is zero when there was no mouse button click. + *v:operator* *operator-variable* +v:operator The last operator given in Normal mode. This is a single + character except for commands starting with or , + in which case it is two characters. Best used alongside + |v:prevcount| and |v:register|. Useful if you want to cancel + Operator-pending mode and then use the operator, e.g.: > + :omap O :call MyMotion(v:operator) +< The value remains set until another operator is entered, thus + don't expect it to be empty. + v:operator is not set for |:delete|, |:yank| or other Ex + commands. + Read-only. + *v:prevcount* *prevcount-variable* v:prevcount The count given for the last but one Normal mode command. This is the v:count value of the previous command. Useful if - you want to cancel Visual mode and then use the count. > + you want to cancel Visual or Operator-pending mode and then + use the count, e.g.: > :vmap % :call MyFilter(v:prevcount) < Read-only. @@ -1557,6 +1571,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 +1617,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 +1637,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 +1692,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}]]) @@ -1714,14 +1733,15 @@ repeat( {expr}, {count}) String repeat {expr} {count} times resolve( {filename}) String get filename a shortcut points to reverse( {list}) List reverse {list} in-place -search( {pattern} [, {flags}]) Number search for {pattern} +search( {pattern} [, {flags} [, {stopline} [, {timeout}]]]) + Number search for {pattern} searchdecl({name} [, {global} [, {thisblock}]]) Number search for variable declaration -searchpair( {start}, {middle}, {end} [, {flags} [, {skip} [, {stopline}]]]) +searchpair( {start}, {middle}, {end} [, {flags} [, {skip} [...]]]) Number search for other end of start/end pair -searchpairpos( {start}, {middle}, {end} [, {flags} [, {skip} [, {stopline}]]]) +searchpairpos( {start}, {middle}, {end} [, {flags} [, {skip} [...]]]) List search for other end of start/end pair -searchpos( {pattern} [, {flags} [, {stopline}]]) +searchpos( {pattern} [, {flags} [, {stopline} [, {timeout}]]]) List search for {pattern} server2client( {clientid}, {string}) Number send reply string @@ -1731,6 +1751,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 @@ -1765,6 +1786,7 @@ synIDattr( {synID}, {what} [, {mode}]) String attribute {what} of syntax ID {synID} synIDtrans( {synID}) Number translated syntax ID of {synID} +synstack({lnum}, {col}) List stack of syntax IDs at {lnum} and {col} system( {expr} [, {input}]) String output of shell command/filter {expr} tabpagebuflist( [{arg}]) List list of buffer numbers in tab page tabpagenr( [{arg}]) Number number of current or last tab page @@ -2012,6 +2034,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 +2046,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 +2689,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 +2699,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 +2857,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 +2947,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 +3673,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 +3720,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 @@ -4112,7 +4214,7 @@ If you want a list to remain unmodified make a copy first: > :let revlist = reverse(copy(mylist)) -search({pattern} [, {flags} [, {stopline}]]) *search()* +search({pattern} [, {flags} [, {stopline} [, {timeout}]]]) *search()* Search for regexp pattern {pattern}. The search starts at the cursor position (you can use |cursor()| to set it). @@ -4140,6 +4242,14 @@ let end = search('END', '', line("w$")) < When {stopline} is used and it is not zero this also implies that the search does not wrap around the end of the file. + A zero value is equal to not giving the argument. + + When the {timeout} argument is given the search stops when + more than this many milli seconds have passed. Thus when + {timeout} is 500 the search stops after half a second. + The value must not be negative. A zero value is like not + giving the argument. + {only available when compiled with the +reltime feature} If there is no match a 0 is returned and the cursor doesn't move. No error message is given. @@ -4202,7 +4312,8 @@ endif < *searchpair()* -searchpair({start}, {middle}, {end} [, {flags} [, {skip} [, {stopline}]]]) +searchpair({start}, {middle}, {end} [, {flags} [, {skip} + [, {stopline} [, {timeout}]]]]) Search for the match of a nested start-end pair. This can be used to find the "endif" that matches an "if", while other if/endif pairs in between are ignored. @@ -4237,7 +4348,7 @@ When evaluating {skip} causes an error the search is aborted and -1 returned. - For {stopline} see |search()|. + For {stopline} and {timeout} see |search()|. The value of 'ignorecase' is used. 'magic' is ignored, the patterns are used like it's on. @@ -4283,7 +4394,8 @@ \ 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string"') < *searchpairpos()* -searchpairpos({start}, {middle}, {end} [, {flags} [, {skip} [, {stopline}]]]) +searchpairpos({start}, {middle}, {end} [, {flags} [, {skip} + [, {stopline} [, {timeout}]]]]) Same as searchpair(), but returns a |List| with the line and column position of the match. The first element of the |List| is the line number and the second element is the byte index of @@ -4294,7 +4406,7 @@ < See |match-parens| for a bigger and more useful example. -searchpos({pattern} [, {flags} [, {stopline}]]) *searchpos()* +searchpos({pattern} [, {flags} [, {stopline} [, {timeout}]]]) *searchpos()* Same as |search()|, but returns a |List| with the line and column position of the match. The first element of the |List| is the line number and the second element is the byte index of @@ -4379,7 +4491,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}) @@ -4405,6 +4523,9 @@ character. E.g., a position within a or after the last character. + Returns 0 when the position could be set, -1 otherwise. + An error message is given if {expr} is invalid. + Also see |getpos()| This does not restore the preferred column for moving @@ -4845,6 +4966,20 @@ highlight the character. Highlight links given with ":highlight link" are followed. +synstack({lnum}, {col}) *synstack()* + Return a |List|, which is the stack of syntax items at the + position {lnum} and {col} in the current window. Each item in + the List is an ID like what |synID()| returns. + The first item in the List is the outer region, following are + items contained in that one. The last one is what |synID()| + returns, unless not the whole item is highlighted or it is a + transparent item. + This function is useful for debugging a syntax file. + Example that shows the syntax stack under the cursor: > + for id in synstack(line("."), col(".")) + echo synIDattr(id, "name") + endfor + system({expr} [, {input}]) *system()* *E677* Get the output of the shell command {expr}. When {input} is given, this string is written to a file and @@ -5022,14 +5157,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-02-14 21:07:32.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-02-14 21:07:34.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 "") @@ -3618,6 +3618,7 @@ When you get bored looking at the highlighted matches, you can turn it off with |:nohlsearch|. As soon as you use a search command, the highlighting comes back. + 'redrawtime' specifies the maximum time spend on finding matches. When the search pattern can match an end-of-line, Vim will try to highlight all of the matched text. However, this depends on where the search starts. This will be the first line in the window or the first @@ -3851,6 +3852,10 @@ original position when no match is found and when pressing . You still need to finish the search command with to move the cursor to the match. + When compiled with the |+reltime| feature Vim only searches for about + half a second. With a complicated pattern and/or a lot of text the + match may not be found. This is to avoid that Vim hangs while you + are typing the pattern. The highlighting can be set with the 'i' flag in 'highlight'. See also: 'hlsearch'. CTRL-L can be used to add one character from after the current match @@ -5185,6 +5190,18 @@ {not in Vi:} When using the ":view" command the 'readonly' option is set for the newly edited buffer. + *'redrawtime'* *'rdt'* +'redrawtime' 'rdt' number (default 2000) + global + {not in Vi} + {only available when compiled with the |+reltime| + feature} + The time in milliseconds for redrawing the display. This applies to + searching for patterns for 'hlsearch' and |:match| highlighting. + When redrawing takes more than this many milliseconds no further + matches will be highlighted. This is used to avoid that Vim hangs + when using a very complicated pattern. + *'remap'* *'noremap'* 'remap' boolean (default on) global 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-02-14 21:07:32.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-02-14 21:07:32.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-02-14 21:07:32.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-02-14 21:07:32.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/various.txt vim71/runtime/doc/various.txt --- vim71.orig/runtime/doc/various.txt 2007-05-12 10:18:48.000000000 +0000 +++ vim71/runtime/doc/various.txt 2008-02-14 21:07:34.000000000 +0000 @@ -1,4 +1,4 @@ -*various.txt* For Vim version 7.1. Last change: 2007 Jan 14 +*various.txt* For Vim version 7.1. Last change: 2008 Jan 11 VIM REFERENCE MANUAL by Bram Moolenaar @@ -748,7 +748,8 @@ *:helpt* *:helptags* *E154* *E150* *E151* *E152* *E153* *E670* -:helpt[ags] {dir} Generate the help tags file(s) for directory {dir}. +:helpt[ags] [++t] {dir} + Generate the help tags file(s) for directory {dir}. All "*.txt" and "*.??x" files in the directory are scanned for a help tag definition in between stars. The "*.??x" files are for translated docs, they @@ -756,6 +757,9 @@ The generated tags files are sorted. When there are duplicates an error message is given. An existing tags file is silently overwritten. + The optional "++t" argument forces adding the + "help-tags" tag. This is also done when the {dir} is + equal to $VIMRUNTIME/doc. To rebuild the help tags in the runtime directory (requires write permission there): > :helptags $VIMRUNTIME/doc 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-02-14 21:07:32.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-02-14 21:07:32.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-02-14 21:07:31.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-02-14 21:07:33.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-02-14 21:07:34.000000000 +0000 @@ -1,6 +1,6 @@ " Vim plugin for showing matching parens " Maintainer: Bram Moolenaar -" Last Change: 2006 Oct 12 +" Last Change: 2008 Jan 06 " 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 = '\[' @@ -99,14 +111,19 @@ \ '=~? "string\\|character\\|singlequote\\|comment"' execute 'if' s_skip '| let s_skip = 0 | endif' - let [m_lnum, m_col] = searchpairpos(c, '', c2, s_flags, s_skip, stopline) + try + " Limit the search time to 500 msec to avoid a hang on very long lines. + let [m_lnum, m_col] = searchpairpos(c, '', c2, s_flags, s_skip, stopline, 500) + catch /E118/ + let [m_lnum, m_col] = searchpairpos(c, '', c2, s_flags, s_skip, stopline) + endtry if before > 0 call winrestview(save_cursor) 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 +131,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-02-14 21:07:34.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-02-14 21:07:34.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 \ @@ -14212,7 +14259,7 @@ echo "$as_me:$LINENO: checking how to run man with a section nr" >&5 echo $ECHO_N "checking how to run man with a section nr... $ECHO_C" >&6 MANDEF="man" -(eval man -s 2 read) < /dev/null > /dev/null 2>&5 && MANDEF="man -s" +(eval MANPAGER=cat PAGER=cat man -s 2 read) < /dev/null > /dev/null 2>&5 && MANDEF="man -s" echo "$as_me:$LINENO: result: $MANDEF" >&5 echo "${ECHO_T}$MANDEF" >&6 if test "$MANDEF" = "man -s"; then 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-02-14 21:07:33.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-02-14 21:07:32.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-02-14 21:07:34.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 \ @@ -2718,7 +2726,7 @@ dnl Check how we can run man with a section number AC_MSG_CHECKING(how to run man with a section nr) MANDEF="man" -(eval man -s 2 read) < /dev/null > /dev/null 2>&AC_FD_CC && MANDEF="man -s" +(eval MANPAGER=cat PAGER=cat man -s 2 read) < /dev/null > /dev/null 2>&AC_FD_CC && MANDEF="man -s" AC_MSG_RESULT($MANDEF) if test "$MANDEF" = "man -s"; then AC_DEFINE(USEMAN_S) 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-02-14 21:07:34.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 } @@ -1296,7 +1299,9 @@ } else /* second overlap of new block with existing block */ - dp->df_count[idx_new] += count_new - count_orig; + dp->df_count[idx_new] += count_new - count_orig + + dpl->df_lnum[idx_orig] + dpl->df_count[idx_orig] + - (dp->df_lnum[idx_orig] + dp->df_count[idx_orig]); /* Adjust the size of the block to include all the lines to the * end of the existing block or the new diff, whatever ends last. */ @@ -1310,7 +1315,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; @@ -1625,14 +1630,16 @@ win_T *fromwin; win_T *towin; { - buf_T *buf = fromwin->w_buffer; + buf_T *frombuf = fromwin->w_buffer; linenr_T lnum = fromwin->w_topline; - int idx; + int fromidx; + int toidx; diff_T *dp; + int max_count; int i; - idx = diff_buf_idx(buf); - if (idx == DB_COUNT) + fromidx = diff_buf_idx(frombuf); + if (fromidx == DB_COUNT) return; /* safety check */ if (curtab->tp_diff_invalid) @@ -1642,42 +1649,72 @@ /* search for a change that includes "lnum" in the list of diffblocks. */ for (dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next) - if (lnum <= dp->df_lnum[idx] + dp->df_count[idx]) + if (lnum <= dp->df_lnum[fromidx] + dp->df_count[fromidx]) break; if (dp == NULL) { /* After last change, compute topline relative to end of file; no * filler lines. */ towin->w_topline = towin->w_buffer->b_ml.ml_line_count - - (buf->b_ml.ml_line_count - lnum); + - (frombuf->b_ml.ml_line_count - lnum); } else { /* Find index for "towin". */ - i = diff_buf_idx(towin->w_buffer); - if (i == DB_COUNT) + toidx = diff_buf_idx(towin->w_buffer); + if (toidx == DB_COUNT) return; /* safety check */ - towin->w_topline = lnum + (dp->df_lnum[i] - dp->df_lnum[idx]); - if (lnum >= dp->df_lnum[idx]) + towin->w_topline = lnum + (dp->df_lnum[toidx] - dp->df_lnum[fromidx]); + if (lnum >= dp->df_lnum[fromidx]) { - /* Inside a change: compute filler lines. */ - if (dp->df_count[i] == dp->df_count[idx]) + /* Inside a change: compute filler lines. With three or more + * buffers we need to know the largest count. */ + max_count = 0; + for (i = 0; i < DB_COUNT; ++i) + if (curtab->tp_diffbuf[i] != NULL + && max_count < dp->df_count[i]) + max_count = dp->df_count[i]; + + if (dp->df_count[toidx] == dp->df_count[fromidx]) + { + /* same number of lines: use same filler count */ towin->w_topfill = fromwin->w_topfill; - else if (dp->df_count[i] > dp->df_count[idx]) + } + else if (dp->df_count[toidx] > dp->df_count[fromidx]) { - if (lnum == dp->df_lnum[idx] + dp->df_count[idx]) - towin->w_topline = dp->df_lnum[i] + dp->df_count[i] - - fromwin->w_topfill; + if (lnum == dp->df_lnum[fromidx] + dp->df_count[fromidx]) + { + /* more lines in towin and fromwin doesn't show diff + * lines, only filler lines */ + if (max_count - fromwin->w_topfill >= dp->df_count[toidx]) + { + /* towin also only shows filler lines */ + towin->w_topline = dp->df_lnum[toidx] + + dp->df_count[toidx]; + towin->w_topfill = fromwin->w_topfill; + } + else + /* towin still has some diff lines to show */ + towin->w_topline = dp->df_lnum[toidx] + + max_count - fromwin->w_topfill; + } } - else + else if (towin->w_topline >= dp->df_lnum[toidx] + + dp->df_count[toidx]) { - if (towin->w_topline >= dp->df_lnum[i] + dp->df_count[i]) + /* less lines in towin and no diff lines to show: compute + * filler lines */ + towin->w_topline = dp->df_lnum[toidx] + dp->df_count[toidx]; + if (diff_flags & DIFF_FILLER) { - if (diff_flags & DIFF_FILLER) - towin->w_topfill = dp->df_lnum[idx] - + dp->df_count[idx] - lnum; - towin->w_topline = dp->df_lnum[i] + dp->df_count[i]; + if (lnum == dp->df_lnum[fromidx] + dp->df_count[fromidx]) + /* fromwin is also out of diff lines */ + towin->w_topfill = fromwin->w_topfill; + else + /* fromwin has some diff lines */ + towin->w_topfill = dp->df_lnum[fromidx] + + max_count - lnum; } } } 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-02-14 21:07:34.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-02-14 21:07:34.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 */ @@ -702,10 +703,13 @@ #endif /* - * Get a character for Insert mode. + * Get a character for Insert mode. Ignore K_IGNORE. */ lastc = c; /* remember previous char for CTRL-D */ - c = safe_vgetc(); + do + { + c = safe_vgetc(); + } while (c == K_IGNORE); #ifdef FEAT_AUTOCMD /* Don't want K_CURSORHOLD for the second key, e.g., after CTRL-V. */ @@ -754,8 +758,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; @@ -775,7 +780,7 @@ /* Prepare for or stop CTRL-X mode. This doesn't do completion, but * it does fix up the text when finishing completion. */ compl_get_longest = FALSE; - if (c != K_IGNORE && ins_compl_prep(c)) + if (ins_compl_prep(c)) continue; #endif @@ -788,7 +793,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 +986,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; @@ -1453,6 +1458,14 @@ # endif ) { +# ifdef FEAT_SYN_HL + /* Need to update the screen first, to make sure syntax + * highlighting is correct after making a change (e.g., inserting + * a "(". The autocommand may also require a redraw, so it's done + * again below, unfortunately. */ + if (syntax_present(curbuf) && must_redraw) + update_screen(0); +# endif apply_autocmds(EVENT_CURSORMOVEDI, NULL, NULL, FALSE, curbuf); last_cursormoved = curwin->w_cursor; } @@ -1652,11 +1665,12 @@ * if round is TRUE, round the indent to 'shiftwidth' (only with _INC and _Dec). */ void -change_indent(type, amount, round, replaced) +change_indent(type, amount, round, replaced, call_changed_bytes) int type; int amount; int round; int replaced; /* replaced character, put on replace stack */ + int call_changed_bytes; /* call changed_bytes() */ { int vcol; int last_vcol; @@ -1713,7 +1727,7 @@ * Set the new indent. The cursor will be put on the first non-blank. */ if (type == INDENT_SET) - (void)set_indent(amount, SIN_CHANGED); + (void)set_indent(amount, call_changed_bytes ? SIN_CHANGED : 0); else { #ifdef FEAT_VREPLACE @@ -1723,7 +1737,7 @@ if (State & VREPLACE_FLAG) State = INSERT; #endif - shift_line(type == INDENT_DEC, round, 1); + shift_line(type == INDENT_DEC, round, 1, call_changed_bytes); #ifdef FEAT_VREPLACE State = save_State; #endif @@ -2053,11 +2067,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 +2115,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; + } + } + } + + /* + * 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); } - was_letter = isalpha(compl_orig_text[idx]); } - } - /* Copy the original case of the part we typed */ - STRNCPY(IObuff, compl_orig_text, compl_length); + /* 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 +2982,7 @@ /* * Add the other matches on the line */ + ptr = buf; while (!got_int) { /* Find start of the next word. Skip white @@ -2851,7 +2992,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 +3009,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 +3176,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 +3397,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. */ @@ -3927,7 +4074,7 @@ found_new_match = searchit(NULL, ins_buf, pos, compl_direction, compl_pattern, 1L, SEARCH_KEEP + SEARCH_NFMSG, - RE_LAST, (linenr_T)0); + RE_LAST, (linenr_T)0, NULL); --msg_silent; if (!compl_started) { @@ -4372,15 +4519,17 @@ else { /* Need to get the character to have KeyTyped set. We'll put it - * back with vungetc() below. */ + * back with vungetc() below. But skip K_IGNORE. */ c = safe_vgetc(); + if (c != K_IGNORE) + { + /* Don't interrupt completion when the character wasn't typed, + * e.g., when doing @q to replay keys. */ + if (c != Ctrl_R && KeyTyped) + compl_interrupted = TRUE; - /* Don't interrupt completion when the character wasn't typed, - * e.g., when doing @q to replay keys. */ - if (c != Ctrl_R && KeyTyped) - compl_interrupted = TRUE; - - vungetc(c); + vungetc(c); + } } } if (compl_pending != 0 && !got_int) @@ -4495,14 +4644,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 +5276,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 @@ -5782,7 +5927,7 @@ { #ifdef FEAT_VREPLACE if (State & VREPLACE_FLAG) - change_indent(INDENT_SET, second_indent, FALSE, NUL); + change_indent(INDENT_SET, second_indent, FALSE, NUL, TRUE); else #endif (void)set_indent(second_indent, SIN_CHANGED); @@ -6313,8 +6458,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 +6953,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. @@ -7067,7 +7233,7 @@ fixthisline(get_the_indent) int (*get_the_indent) __ARGS((void)); { - change_indent(INDENT_SET, get_the_indent(), FALSE, 0); + change_indent(INDENT_SET, get_the_indent(), FALSE, 0, TRUE); if (linewhite(curwin->w_cursor.lnum)) did_ai = TRUE; /* delete the indent if the line stays empty */ } @@ -7215,6 +7381,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 +7645,7 @@ * deleted when ESC is hit. */ ++no_mapping; - regname = safe_vgetc(); + regname = plain_vgetc(); #ifdef FEAT_LANGMAP LANGMAP_ADJUST(regname, TRUE); #endif @@ -7488,7 +7656,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 +7747,7 @@ * deleted when ESC is hit. */ ++no_mapping; - c = safe_vgetc(); + c = plain_vgetc(); --no_mapping; switch (c) { @@ -7998,7 +8166,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' */ @@ -8007,10 +8176,10 @@ replace_pop_ins(); if (lastc == '^') old_indent = get_indent(); /* remember curr. indent */ - change_indent(INDENT_SET, 0, TRUE, 0); + change_indent(INDENT_SET, 0, TRUE, 0, TRUE); } else - change_indent(c == Ctrl_D ? INDENT_DEC : INDENT_INC, 0, TRUE, 0); + change_indent(c == Ctrl_D ? INDENT_DEC : INDENT_INC, 0, TRUE, 0, TRUE); if (did_ai && *skipwhite(ml_get_curline()) != NUL) did_ai = FALSE; @@ -8053,6 +8222,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. @@ -8274,6 +8466,7 @@ if ( mode == BACKSPACE_CHAR && ((p_sta && in_indent) || (curbuf->b_p_sts != 0 + && curwin->w_cursor.col > 0 && (*(ml_get_cursor() - 1) == TAB || (*(ml_get_cursor() - 1) == ' ' && (!*inserted_space_p @@ -8282,9 +8475,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 +8486,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 +8495,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 +8512,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); } /* @@ -8461,6 +8624,14 @@ if (vim_strchr(p_cpo, CPO_BACKSPACE) != NULL && dollar_vcol == 0) dollar_vcol = curwin->w_virtcol; +#ifdef FEAT_FOLDING + /* When deleting a char the cursor line must never be in a closed fold. + * E.g., when 'foldmethod' is indent and deleting the first non-white + * char before a Tab. */ + if (did_backspace) + foldOpenCursor(); +#endif + return did_backspace; } @@ -8518,15 +8689,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 +8715,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 +8740,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 +9453,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 +9485,7 @@ } ++no_mapping; ++allow_keys; - cc = safe_vgetc(); + cc = plain_vgetc(); --no_mapping; --allow_keys; if (cc != ESC) @@ -9443,7 +9639,7 @@ curwin->w_cursor = old_pos; #ifdef FEAT_VREPLACE if (State & VREPLACE_FLAG) - change_indent(INDENT_SET, i, FALSE, NUL); + change_indent(INDENT_SET, i, FALSE, NUL, TRUE); else #endif (void)set_indent(i, SIN_CHANGED); @@ -9472,7 +9668,7 @@ curwin->w_cursor = old_pos; } if (temp) - shift_line(TRUE, FALSE, 1); + shift_line(TRUE, FALSE, 1, TRUE); } } 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-02-14 21:07:34.000000000 +0000 @@ -345,6 +345,7 @@ {VV_NAME("mouse_win", VAR_NUMBER), 0}, {VV_NAME("mouse_lnum", VAR_NUMBER), 0}, {VV_NAME("mouse_col", VAR_NUMBER), 0}, + {VV_NAME("operator", VAR_STRING), VV_RO}, }; /* shorthand */ @@ -369,17 +370,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 +476,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 +531,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 +580,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 +623,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)); @@ -645,6 +651,7 @@ static void f_synID __ARGS((typval_T *argvars, typval_T *rettv)); static void f_synIDattr __ARGS((typval_T *argvars, typval_T *rettv)); static void f_synIDtrans __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_synstack __ARGS((typval_T *argvars, typval_T *rettv)); static void f_system __ARGS((typval_T *argvars, typval_T *rettv)); static void f_tabpagebuflist __ARGS((typval_T *argvars, typval_T *rettv)); static void f_tabpagenr __ARGS((typval_T *argvars, typval_T *rettv)); @@ -672,7 +679,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 +706,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 +999,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 +1320,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 +1363,6 @@ if (p_verbose == 0) --emsg_off; - vimvars[VV_VAL].vv_str = NULL; restore_vimvar(VV_VAL, &save_val); return list; @@ -1411,7 +1416,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 +1490,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 +1513,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 +1538,7 @@ clear_tv(&rettv); return retval; } -#endif +# endif /* * Call vimL function "func" and return the result as a list @@ -1556,9 +1564,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 +1699,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 +1716,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 +1933,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 +1952,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 +1961,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 +2000,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 +2012,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 +2106,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 +2131,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); } @@ -3383,6 +3408,7 @@ hashtab_T *ht; hashitem_T *hi; char_u *varname; + dictitem_T *di; ht = find_var_ht(name, &varname); if (ht != NULL && *varname != NUL) @@ -3390,9 +3416,9 @@ hi = hash_find(ht, varname); if (!HASHITEM_EMPTY(hi)) { - if (var_check_fixed(HI2DI(hi)->di_flags, name)) - return FAIL; - if (var_check_ro(HI2DI(hi)->di_flags, name)) + di = HI2DI(hi); + if (var_check_fixed(di->di_flags, name) + || var_check_ro(di->di_flags, name)) return FAIL; delete_var(ht, hi); return OK; @@ -6105,6 +6131,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 +6708,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 +6748,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 +6825,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 +6910,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 +7074,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 +7114,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 +7131,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 +7182,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}, @@ -7179,17 +7214,18 @@ {"repeat", 2, 2, f_repeat}, {"resolve", 1, 1, f_resolve}, {"reverse", 1, 1, f_reverse}, - {"search", 1, 3, f_search}, + {"search", 1, 4, f_search}, {"searchdecl", 1, 3, f_searchdecl}, - {"searchpair", 3, 6, f_searchpair}, - {"searchpairpos", 3, 6, f_searchpairpos}, - {"searchpos", 1, 3, f_searchpos}, + {"searchpair", 3, 7, f_searchpair}, + {"searchpairpos", 3, 7, f_searchpairpos}, + {"searchpos", 1, 4, f_searchpos}, {"server2client", 2, 2, f_server2client}, {"serverlist", 0, 0, f_serverlist}, {"setbufvar", 3, 3, f_setbufvar}, {"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}, @@ -7217,6 +7253,7 @@ {"synID", 3, 3, f_synID}, {"synIDattr", 2, 3, f_synIDattr}, {"synIDtrans", 1, 1, f_synIDtrans}, + {"synstack", 2, 2, f_synstack}, {"system", 1, 2, f_system}, {"tabpagebuflist", 0, 1, f_tabpagebuflist}, {"tabpagenr", 0, 1, f_tabpagenr}, @@ -8240,6 +8277,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 +8733,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 +9390,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 +9418,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 +9724,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 +9925,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 +10199,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 +10338,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 +10392,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 +10888,9 @@ "gui_gtk2", # endif #endif +#ifdef FEAT_GUI_GNOME + "gui_gnome", +#endif #ifdef FEAT_GUI_MAC "gui_mac", #endif @@ -11471,14 +11577,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 +12543,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 +12591,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 +13844,7 @@ } /* Shorten "remain". */ if (*q != NUL) - STRCPY(remain, q - 1); + mch_memmove(remain, q - 1, STRLEN(q - 1) + 1); else { vim_free(remain); @@ -13858,6 +14022,10 @@ int dir; int retval = 0; /* default: FAIL */ long lnum_stop = 0; + proftime_T tm; +#ifdef FEAT_RELTIME + long time_limit = 0; +#endif int options = SEARCH_KEEP; int subpatnum; @@ -13871,15 +14039,27 @@ if (flags & SP_END) options |= SEARCH_END; - /* Optional extra argument: line number to stop searching. */ - if (argvars[1].v_type != VAR_UNKNOWN - && argvars[2].v_type != VAR_UNKNOWN) + /* Optional arguments: line number to stop searching and timeout. */ + if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN) { lnum_stop = get_tv_number_chk(&argvars[2], NULL); if (lnum_stop < 0) goto theend; +#ifdef FEAT_RELTIME + if (argvars[3].v_type != VAR_UNKNOWN) + { + time_limit = get_tv_number_chk(&argvars[3], NULL); + if (time_limit < 0) + goto theend; + } +#endif } +#ifdef FEAT_RELTIME + /* Set the time limit, if there is one. */ + profile_setlimit(time_limit, &tm); +#endif + /* * This function does not accept SP_REPEAT and SP_RETCOUNT flags. * Check to make sure only those flags are set. @@ -13895,7 +14075,7 @@ pos = save_cursor = curwin->w_cursor; subpatnum = searchit(curwin, curbuf, &pos, dir, pat, 1L, - options, RE_SEARCH, (linenr_T)lnum_stop); + options, RE_SEARCH, (linenr_T)lnum_stop, &tm); if (subpatnum != FAIL) { if (flags & SP_SUBPAT) @@ -13919,6 +14099,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; @@ -13983,6 +14165,7 @@ char_u nbuf3[NUMBUFLEN]; int retval = 0; /* default: FAIL */ long lnum_stop = 0; + long time_limit = 0; /* Get the three pattern arguments: start, middle, end. */ spat = get_tv_string_chk(&argvars[0]); @@ -14006,6 +14189,10 @@ goto theend; } + /* Using 'r' implies 'W', otherwise it doesn't work. */ + if (flags & SP_REPEAT) + p_ws = FALSE; + /* Optional fifth argument: skip expression */ if (argvars[3].v_type == VAR_UNKNOWN || argvars[4].v_type == VAR_UNKNOWN) @@ -14018,13 +14205,21 @@ lnum_stop = get_tv_number_chk(&argvars[5], NULL); if (lnum_stop < 0) goto theend; +#ifdef FEAT_RELTIME + if (argvars[6].v_type != VAR_UNKNOWN) + { + time_limit = get_tv_number_chk(&argvars[6], NULL); + if (time_limit < 0) + goto theend; + } +#endif } } if (skip == NULL) goto theend; /* type error */ retval = do_searchpair(spat, mpat, epat, dir, skip, flags, - match_pos, lnum_stop); + match_pos, lnum_stop, time_limit); theend: p_ws = save_p_ws; @@ -14076,7 +14271,8 @@ * Returns 0 or -1 for no match, */ long -do_searchpair(spat, mpat, epat, dir, skip, flags, match_pos, lnum_stop) +do_searchpair(spat, mpat, epat, dir, skip, flags, match_pos, + lnum_stop, time_limit) char_u *spat; /* start pattern */ char_u *mpat; /* middle pattern */ char_u *epat; /* end pattern */ @@ -14085,6 +14281,7 @@ int flags; /* SP_SETPCMARK and other SP_ values */ pos_T *match_pos; linenr_T lnum_stop; /* stop at this line if not zero */ + long time_limit; /* stop after this many msec */ { char_u *save_cpo; char_u *pat, *pat2 = NULL, *pat3 = NULL; @@ -14099,11 +14296,17 @@ int nest = 1; int err; int options = SEARCH_KEEP; + proftime_T tm; /* Make 'cpoptions' empty, the 'l' flag should not be used here. */ save_cpo = p_cpo; p_cpo = (char_u *)""; +#ifdef FEAT_RELTIME + /* Set the time limit, if there is one. */ + profile_setlimit(time_limit, &tm); +#endif + /* Make two search patterns: start/end (pat2, for in nested pairs) and * start/middle/end (pat3, for the top pair). */ pat2 = alloc((unsigned)(STRLEN(spat) + STRLEN(epat) + 15)); @@ -14127,7 +14330,7 @@ for (;;) { n = searchit(curwin, curbuf, &pos, dir, pat, 1L, - options, RE_SEARCH, lnum_stop); + options, RE_SEARCH, lnum_stop, &tm); if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos))) /* didn't find it or found the first match again: FAIL */ break; @@ -14146,6 +14349,9 @@ } foundpos = pos; + /* clear the start flag to avoid getting stuck here */ + options &= ~SEARCH_START; + /* If the skip pattern matches, ignore this match. */ if (*skip != NUL) { @@ -14498,6 +14704,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*/ @@ -14510,24 +14776,31 @@ int fnum; char_u *name; + rettv->vval.v_number = -1; name = get_tv_string_chk(argvars); if (name != NULL) { if (list2fpos(&argvars[1], &pos, &fnum) == OK) { --pos.col; - if (name[0] == '.') /* cursor */ + if (name[0] == '.' && name[1] == NUL) { + /* set cursor */ if (fnum == curbuf->b_fnum) { curwin->w_cursor = pos; check_cursor(); + rettv->vval.v_number = 0; } else EMSG(_(e_invarg)); } - else if (name[0] == '\'') /* mark */ - (void)setmark_pos(name[1], &pos, fnum); + else if (name[0] == '\'' && name[1] != NUL && name[2] == NUL) + { + /* set mark */ + if (setmark_pos(name[1], &pos, fnum) == OK) + rettv->vval.v_number = 0; + } else EMSG(_(e_invarg)); } @@ -14785,6 +15058,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 +15551,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); } @@ -15461,7 +15739,7 @@ if (!transerr && lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count && col >= 0 && col < (long)STRLEN(ml_get(lnum))) - id = syn_get_id(curwin, lnum, (colnr_T)col, trans, NULL); + id = syn_get_id(curwin, lnum, (colnr_T)col, trans, NULL, FALSE); #endif rettv->vval.v_number = id; @@ -15584,6 +15862,46 @@ } /* + * "synstack(lnum, col)" function + */ +/*ARGSUSED*/ + static void +f_synstack(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ +#ifdef FEAT_SYN_HL + long lnum; + long col; + int i; + int id; +#endif + + rettv->v_type = VAR_LIST; + rettv->vval.v_list = NULL; + +#ifdef FEAT_SYN_HL + lnum = get_tv_lnum(argvars); /* -1 on type error */ + col = get_tv_number(&argvars[1]) - 1; /* -1 on type error */ + + if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count + && col >= 0 && col < (long)STRLEN(ml_get(lnum)) + && rettv_list_alloc(rettv) != FAIL) + { + (void)syn_get_id(curwin, lnum, (colnr_T)col, FALSE, NULL, TRUE); + for (i = 0; ; ++i) + { + id = syn_get_stack_item(i); + if (id < 0) + break; + if (list_append_number(rettv->vval.v_list, id) == FAIL) + break; + } + } +#endif +} + +/* * "system()" function */ static void @@ -15599,7 +15917,7 @@ FILE *fd; if (check_restricted() || check_secure()) - return; + goto done; if (argvars[1].v_type != VAR_UNKNOWN) { @@ -15610,7 +15928,7 @@ if ((infile = vim_tempname('i')) == NULL) { EMSG(_(e_notmp)); - return; + goto done; } fd = mch_fopen((char *)infile, WRITEBIN); @@ -16497,9 +16815,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 +16830,7 @@ list_T *l; int len; int error = FALSE; + listitem_T *li; l = varp->vval.v_list; if (l == NULL) @@ -16527,6 +16846,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 +16886,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 +16904,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 +18125,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 +18136,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 +18178,11 @@ if (type == VAR_FUNC) msg_puts((char_u *)"()"); + if (*first) + { + msg_clr_eos(); + *first = FALSE; + } } /* @@ -19136,6 +19472,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 +20327,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 +20338,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 +20422,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 +21400,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-02-14 21:07:34.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 } @@ -4163,7 +4200,6 @@ linenr_T old_line_count = curbuf->b_ml.ml_line_count; linenr_T line2; long nmatch; /* number of lines in match */ - linenr_T sub_firstlnum; /* nr of first sub line */ char_u *sub_firstline; /* allocated copy of first sub line */ int endcolumn = FALSE; /* cursor in last column when done */ pos_T old_cursor = curwin->w_cursor; @@ -4175,11 +4211,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 +4246,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 +4329,7 @@ do_error = TRUE; do_print = FALSE; do_count = FALSE; + do_number = FALSE; do_ic = 0; } while (*cmd) @@ -4410,8 +4446,8 @@ #endif ); ++lnum) { - sub_firstlnum = lnum; - nmatch = vim_regexec_multi(®match, curwin, curbuf, lnum, (colnr_T)0); + nmatch = vim_regexec_multi(®match, curwin, curbuf, lnum, + (colnr_T)0, NULL); if (nmatch) { colnr_T copycol; @@ -4426,6 +4462,7 @@ long nmatch_tl = 0; /* nr of lines matched below lnum */ int do_again; /* do it again after joining lines */ int skip_match = FALSE; + linenr_T sub_firstlnum; /* nr of first sub line */ /* * The new text is build up step by step, to avoid too much @@ -4445,8 +4482,10 @@ * far. * new_end The new text, where to append new text. * - * lnum The line number where we were looking for the - * first match in the old line. + * lnum The line number where we found the start of + * the match. Can be below the line we searched + * when there is a \n before a \zs in the + * pattern. * sub_firstlnum The line number in the buffer where to look * for a match. Can be different from "lnum" * when the pattern or substitute string contains @@ -4464,18 +4503,13 @@ * * 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_" * pointers point into this copy. */ - sub_firstline = vim_strsave(ml_get(sub_firstlnum)); - if (sub_firstline == NULL) - { - vim_free(new_start); - goto outofmem; - } + sub_firstlnum = lnum; copycol = 0; matchcol = 0; @@ -4496,6 +4530,28 @@ */ for (;;) { + /* Advance "lnum" to the line where the match starts. The + * match does not start in the first line when there is a line + * break before \zs. */ + if (regmatch.startpos[0].lnum > 0) + { + lnum += regmatch.startpos[0].lnum; + sub_firstlnum += regmatch.startpos[0].lnum; + nmatch -= regmatch.startpos[0].lnum; + vim_free(sub_firstline); + sub_firstline = NULL; + } + + if (sub_firstline == NULL) + { + sub_firstline = vim_strsave(ml_get(sub_firstlnum)); + if (sub_firstline == NULL) + { + vim_free(new_start); + goto outofmem; + } + } + /* Save the line number of the last change for the final * cursor position (just like Vi). */ curwin->w_cursor.lnum = lnum; @@ -4538,6 +4594,7 @@ { matchcol = (colnr_T)STRLEN(sub_firstline); nmatch = 1; + skip_match = TRUE; } sub_nsubs++; did_sub = TRUE; @@ -4600,7 +4657,8 @@ temp = RedrawingDisabled; RedrawingDisabled = 0; - search_match_lines = regmatch.endpos[0].lnum; + search_match_lines = regmatch.endpos[0].lnum + - regmatch.startpos[0].lnum; search_match_endcol = regmatch.endpos[0].col; highlight_match = TRUE; @@ -4635,7 +4693,7 @@ #endif ++no_mapping; /* don't map this key */ ++allow_keys; /* allow special keys */ - i = safe_vgetc(); + i = plain_vgetc(); --allow_keys; --no_mapping; @@ -4711,7 +4769,8 @@ * 3. substitute the string. */ /* get length of substitution part */ - sublen = vim_regsub_multi(®match, sub_firstlnum, + sublen = vim_regsub_multi(®match, + sub_firstlnum - regmatch.startpos[0].lnum, sub, sub_firstline, FALSE, p_magic, TRUE); /* When the match included the "$" of the last line it may @@ -4781,7 +4840,8 @@ mch_memmove(new_end, sub_firstline + copycol, (size