Submitted By: Jim Gifford (jim at linuxfromscratch dot org) Date: 06-18-2008 Initial Package Version: 7.1 Origin: Upstream Upstream Status: Applied Description: Contains all upstream patches up to 7.1.315 The following patches were skipped 003 007 041 065 070 072 080 088 091 092 124 126 128 129 134 146 158 168 196 204 275 278 280 282 283 285 312 diff -Naur vim71.orig/Filelist vim71/Filelist --- vim71.orig/Filelist 2007-05-06 11:00:23.000000000 -0400 +++ vim71/Filelist 2008-06-18 06:56:41.000000000 -0400 @@ -193,6 +193,7 @@ src/vim_icon.xbm \ src/vim_mask.xbm \ src/vimtutor \ + src/gvimtutor \ src/which.sh \ src/workshop.c \ src/workshop.h \ diff -Naur vim71.orig/runtime/autoload/gzip.vim vim71/runtime/autoload/gzip.vim --- vim71.orig/runtime/autoload/gzip.vim 2007-05-10 07:40:14.000000000 -0400 +++ vim71/runtime/autoload/gzip.vim 2008-06-18 06:56:50.000000000 -0400 @@ -1,6 +1,6 @@ " Vim autoload file for editing compressed files. " Maintainer: Bram Moolenaar -" Last Change: 2007 May 10 +" Last Change: 2008 May 29 " These functions are used by the gzip plugin. @@ -73,8 +73,15 @@ let empty = line("'[") == 1 && line("']") == line("$") let tmp = tempname() let tmpe = tmp . "." . expand(":e") + if exists('*fnameescape') + let tmp_esc = fnameescape(tmp) + let tmpe_esc = fnameescape(tmpe) + else + let tmp_esc = escape(tmp, ' ') + let tmpe_esc = escape(tmpe, ' ') + endif " write the just read lines to a temp file "'[,']w tmp.gz" - execute "silent '[,']w " . escape(tmpe, ' ') + execute "silent '[,']w " . tmpe_esc " uncompress the temp file: call system("gzip -dn tmp.gz") call system(a:cmd . " " . s:escape(tmpe)) if !filereadable(tmp) @@ -95,12 +102,12 @@ setlocal nobin if exists(":lockmarks") if empty - execute "silent lockmarks " . l . "r ++edit " . tmp + execute "silent lockmarks " . l . "r ++edit " . tmp_esc else - execute "silent lockmarks " . l . "r " . tmp + execute "silent lockmarks " . l . "r " . tmp_esc endif else - execute "silent " . l . "r " . tmp + execute "silent " . l . "r " . tmp_esc endif " if buffer became empty, delete trailing blank line @@ -110,8 +117,8 @@ endif " delete the temp file and the used buffers call delete(tmp) - silent! exe "bwipe " . tmp - silent! exe "bwipe " . tmpe + silent! exe "bwipe " . tmp_esc + silent! exe "bwipe " . tmpe_esc endif " Restore saved option values. @@ -124,10 +131,15 @@ " When uncompressed the whole buffer, do autocommands if ok && empty + if exists('*fnameescape') + let fname = fnameescape(expand("%:r")) + else + let fname = escape(expand("%:r"), " \t\n*?[{`$\\%#'\"|!<") + endif if &verbose >= 8 - execute "doau BufReadPost " . expand("%:r") + execute "doau BufReadPost " . fname else - execute "silent! doau BufReadPost " . expand("%:r") + execute "silent! doau BufReadPost " . fname endif endif endfun diff -Naur vim71.orig/runtime/doc/Makefile vim71/runtime/doc/Makefile --- vim71.orig/runtime/doc/Makefile 2006-11-07 15:59:05.000000000 -0500 +++ vim71/runtime/doc/Makefile 2008-06-18 06:55:02.000000000 -0400 @@ -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 06:18:46.000000000 -0400 +++ vim71/runtime/doc/change.txt 2008-06-18 06:51:08.000000000 -0400 @@ -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 06:18:46.000000000 -0400 +++ vim71/runtime/doc/cmdline.txt 2008-06-18 06:54:39.000000000 -0400 @@ -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 06:18:46.000000000 -0400 +++ vim71/runtime/doc/eval.txt 2008-06-18 06:56:43.000000000 -0400 @@ -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 May 28 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 @@ -1594,6 +1609,7 @@ String find directory {name} in {path} findfile( {name}[, {path}[, {count}]]) String find file {name} in {path} +fnameescape( {fname}) String escape special characters in {fname} fnamemodify( {fname}, {mods}) String modify file name foldclosed( {lnum}) Number first line of fold at {lnum} if closed foldclosedend( {lnum}) Number last line of fold at {lnum} if closed @@ -1602,7 +1618,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 +1638,8 @@ 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 +getpid() Number process ID of Vim getpos( {expr}) List position of cursor, mark, etc. getqflist() List list of quickfix items getreg( [{regname} [, 1]]) String contents of register @@ -1676,7 +1694,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 +1735,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 +1753,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 +1788,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 +2036,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 +2048,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()|. @@ -2589,6 +2621,19 @@ < Searches from the directory of the current file upwards until it finds the file "tags.vim". +fnameescape({string}) *fnameescape()* + Escape {string} for use as file name command argument. All + characters that have a special meaning, such as '%' and '|' + are escaped with a backslash. + For most systems the characters escaped are "". For systems + where a backslash appears in a filename, it depends on the + value of 'isfname'. + Example: > + :let fname = 'some str%nge|name' + :exe "edit " . fnameescape(fname) +< results in executing: > + edit some\ str\%nge\|name + fnamemodify({fname}, {mods}) *fnamemodify()* Modify file name {fname} according to {mods}. {mods} is a string of characters like it is used for file names on the @@ -2659,7 +2704,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 +2714,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 +2872,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 +2962,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 +3688,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 +3735,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 @@ -3731,6 +3848,10 @@ characters. nr2char(0) is a real NUL and terminates the string, thus results in an empty string. + *getpid()* +getpid() Return a Number which is the process ID of the Vim process. + On Unix this is a unique number. On MS-DOS it's always zero. + *getpos()* getpos({expr}) Get the position for {expr}. For possible values of {expr} see |line()|. @@ -4112,7 +4233,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 +4261,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 +4331,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 +4367,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 +4413,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 +4425,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 +4510,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 +4542,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 +4985,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 +5176,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/options.txt vim71/runtime/doc/options.txt --- vim71.orig/runtime/doc/options.txt 2007-05-12 06:18:47.000000000 -0400 +++ vim71/runtime/doc/options.txt 2008-06-18 06:56:16.000000000 -0400 @@ -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: 2008 Feb 24 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 @@ -4873,7 +4878,7 @@ |autocmd-osfiletypes| *'paragraphs'* *'para'* -'paragraphs' 'para' string (default "IPLPPPQPP LIpplpipbp") +'paragraphs' 'para' string (default "IPLPPPQPP TPHPLIPpLpItpplpipbp") global Specifies the nroff macros that separate paragraphs. These are pairs of two letters (see |object-motions|). @@ -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 06:18:47.000000000 -0400 +++ vim71/runtime/doc/pattern.txt 2008-06-18 06:51:23.000000000 -0400 @@ -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 06:18:47.000000000 -0400 +++ vim71/runtime/doc/pi_paren.txt 2008-06-18 06:52:15.000000000 -0400 @@ -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/usr_41.txt vim71/runtime/doc/usr_41.txt --- vim71.orig/runtime/doc/usr_41.txt 2007-05-12 06:18:48.000000000 -0400 +++ vim71/runtime/doc/usr_41.txt 2008-06-18 06:51:23.000000000 -0400 @@ -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 06:18:48.000000000 -0400 +++ vim71/runtime/doc/various.txt 2008-06-18 06:55:02.000000000 -0400 @@ -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/vimtutor.1 vim71/runtime/doc/vimtutor.1 --- vim71.orig/runtime/doc/vimtutor.1 2004-06-07 10:32:40.000000000 -0400 +++ vim71/runtime/doc/vimtutor.1 2008-06-18 06:56:38.000000000 -0400 @@ -3,7 +3,7 @@ vimtutor \- the Vim tutor .SH SYNOPSIS .br -.B vimtutor [language] +.B vimtutor [-g] [language] .SH DESCRIPTION .B Vimtutor starts the @@ -18,6 +18,9 @@ .B Vim commands. .PP +The optional argument -g starts vimtutor with gvim rather than vim, if the +GUI version of vim is available, or falls back to Vim if gvim is not found. +.PP The optional [language] argument is the two-letter name of a language, like "it" or "es". If the [language] argument is missing, the language of the current locale will diff -Naur vim71.orig/runtime/doc/windows.txt vim71/runtime/doc/windows.txt --- vim71.orig/runtime/doc/windows.txt 2007-05-12 06:18:49.000000000 -0400 +++ vim71/runtime/doc/windows.txt 2008-06-18 06:51:59.000000000 -0400 @@ -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 11:14:37.000000000 -0400 +++ vim71/runtime/filetype.vim 2008-06-18 06:56:44.000000000 -0400 @@ -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") @@ -16,20 +16,23 @@ augroup filetypedetect " Ignored extensions +if exists("*fnameescape") au BufNewFile,BufRead ?\+.orig,?\+.bak,?\+.old,?\+.new,?\+.rpmsave,?\+.rpmnew - \ exe "doau filetypedetect BufRead " . expand(":r") + \ exe "doau filetypedetect BufRead " . fnameescape(expand(":r")) au BufNewFile,BufRead *~ \ let s:name = expand("") | \ let s:short = substitute(s:name, '\~$', '', '') | \ if s:name != s:short && s:short != "" | - \ exe "doau filetypedetect BufRead " . s:short | + \ exe "doau filetypedetect BufRead " . fnameescape(s:short) | \ endif | - \ unlet s:name | - \ unlet s:short + \ unlet s:name s:short au BufNewFile,BufRead ?\+.in \ if expand(":t") != "configure.in" | - \ exe "doau filetypedetect BufRead " . expand(":r") | + \ exe "doau filetypedetect BufRead " . fnameescape(expand(":r")) | \ endif +elseif &verbose > 0 + echomsg "Warning: some filetypes will not be recognized because this version of Vim does not have fnameescape()" +endif " Pattern used to match file names which should not be inspected. " Currently finds compressed files. @@ -187,7 +190,7 @@ let head = " ".getline(1)." ".getline(2)." ".getline(3)." ".getline(4). \" ".getline(5)." " if head =~ '\sasmsyntax=\S\+\s' - let b:asmsyntax = substitute(head, '.*\sasmsyntax=\(\S\+\)\s.*','\1', "") + let b:asmsyntax = substitute(head, '.*\sasmsyntax=\([a-zA-Z0-9]\+\)\s.*','\1', "") elseif ((head =~? '\.title') || (head =~? '\.ident') || (head =~? '\.macro') || (head =~? '\.subtitle') || (head =~? '\.library')) let b:asmsyntax = "vmasm" endif @@ -1286,7 +1289,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/indent.vim vim71/runtime/indent.vim --- vim71.orig/runtime/indent.vim 2006-02-01 03:54:35.000000000 -0500 +++ vim71/runtime/indent.vim 2008-06-18 06:55:58.000000000 -0400 @@ -1,7 +1,7 @@ " Vim support file to switch on loading indent files for file types " " Maintainer: Bram Moolenaar -" Last Change: 2005 Mar 28 +" Last Change: 2008 Feb 22 if exists("did_indent_on") finish @@ -15,11 +15,17 @@ exe b:undo_indent unlet! b:undo_indent b:did_indent endif - if expand("") != "" + let s = expand("") + if s != "" if exists("b:did_indent") unlet b:did_indent endif - runtime! indent/.vim + + " When there is a dot it is used to separate filetype names. Thus for + " "aaa.bbb" load "indent/aaa.vim" and then "indent/bbb.vim". + for name in split(s, '\.') + exe 'runtime! indent/' . name . '.vim' + endfor endif endfunc augroup END diff -Naur vim71.orig/runtime/menu.vim vim71/runtime/menu.vim --- vim71.orig/runtime/menu.vim 2007-01-09 08:31:40.000000000 -0500 +++ vim71/runtime/menu.vim 2008-06-18 06:53:55.000000000 -0400 @@ -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/optwin.vim vim71/runtime/optwin.vim --- vim71.orig/runtime/optwin.vim 2006-10-10 17:06:34.000000000 -0400 +++ vim71/runtime/optwin.vim 2008-06-18 06:56:54.000000000 -0400 @@ -1,7 +1,7 @@ " These commands create the option window. " " Maintainer: Bram Moolenaar -" Last Change: 2006 Oct 10 +" Last Change: 2008 May 12 " If there already is an option window, jump to that one. if bufwinnr("option-window") > 0 @@ -147,7 +147,7 @@ " Open the window new option-window -setlocal ts=15 tw=0 +setlocal ts=15 tw=0 noro " Insert help and a "set" command for each option. call append(0, '" Each "set" line shows the current value of an option (on the left).') @@ -350,6 +350,10 @@ call append("$", " \tset lines=" . &lines) call append("$", "lazyredraw\tdon't redraw while executing macros") call BinOptionG("lz", &lz) +if has("reltime") + call append("$", "redrawtime\ttimeout for 'hlsearch' and :match highlighting in msec") + call append("$", " \tset rdt=" . &rdt) +endif call append("$", "writedelay\tdelay in msec for each char written to the display") call append("$", "\t(for debugging)") call append("$", " \tset wd=" . &wd) diff -Naur vim71.orig/runtime/plugin/matchparen.vim vim71/runtime/plugin/matchparen.vim --- vim71.orig/runtime/plugin/matchparen.vim 2006-10-12 16:05:05.000000000 -0400 +++ vim71/runtime/plugin/matchparen.vim 2008-06-18 06:56:05.000000000 -0400 @@ -1,6 +1,6 @@ " Vim plugin for showing matching parens " Maintainer: Bram Moolenaar -" Last Change: 2006 Oct 12 +" Last Change: 2008 Feb 27 " 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. @@ -34,7 +34,8 @@ endif " Avoid that we remove the popup menu. - if pumvisible() + " Return when there are no colors (looks like the cursor jumps). + if pumvisible() || (&t_Co < 8 && !has("gui_running")) return endif @@ -60,27 +61,13 @@ endif " 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) 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)]) - else - let stopline = min([line('w$'), c_lnum + 100]) - endif 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)]) - else - let stopline = max([line('w0'), c_lnum - 100]) - endif endif if c == '[' let c = '\[' @@ -99,14 +86,56 @@ \ '=~? "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) + " Limit the search to lines visible in the window. + let stoplinebottom = line('w$') + let stoplinetop = line('w0') + if i % 2 == 0 + let stopline = stoplinebottom + else + let stopline = stoplinetop + endif + + try + " Limit the search time to 300 msec to avoid a hang on very long lines. + " This fails when a timeout is not supported. + let [m_lnum, m_col] = searchpairpos(c, '', c2, s_flags, s_skip, stopline, 300) + catch /E118/ + " Can't use the timeout, restrict the stopline a bit more to avoid taking + " a long time on 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 + if i % 2 == 0 + if has("byte_offset") && has("syntax_items") && &smc > 0 + let stopbyte = min([line2byte("$"), line2byte(".") + col(".") + &smc * 2]) + let stopline = min([bottom_viewable, byte2line(stopbyte)]) + else + let stopline = min([bottom_viewable, c_lnum + 100]) + endif + let stoplinebottom = stopline + else + if has("byte_offset") && has("syntax_items") && &smc > 0 + let stopbyte = max([1, line2byte(".") + col(".") - &smc * 2]) + let stopline = max([top_viewable, byte2line(stopbyte)]) + else + let stopline = max([top_viewable, c_lnum - 100]) + endif + let stoplinetop = stopline + endif + 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 +143,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 07:57:13.000000000 -0400 +++ vim71/src/Makefile 2008-06-18 06:56:55.000000000 -0400 @@ -545,7 +545,7 @@ # For unknown reasons adding "-lc" fixes a linking problem with GCC. That's # probably a bug in the "-pg" implementation. # Need to recompile everything after changing this: "make clean" "make". -#PROFILE_CFLAGS = -pg -g +#PROFILE_CFLAGS = -pg -g -DWE_ARE_PROFILING #PROFILE_LIBS = -pg #PROFILE_LIBS = -pg -lc @@ -780,6 +780,8 @@ # 1) make config # 2) edit auto/config.mk, add -n32 to LDFLAGS # 3) make +# +#Alternatively: use -o32 instead of -n32. ### ### (C) On SCO Unix v3.2.5 (and probably other versions) the termcap library, @@ -1074,7 +1076,7 @@ # default vi editor, it will create a link from vi to Vim when doing # "make install". An existing file will be overwritten! # When not using it, some make programs can't handle an undefined $(LINKIT). -#LINKIT = -ln -f -s $(BINDIR)/$(VIMTARGET) /usr/bin/vi +#LINKIT = ln -f -s $(DEST_BIN)/$(VIMTARGET) $(DESTDIR)/usr/bin/vi LINKIT = @echo >/dev/null ### @@ -1290,6 +1292,9 @@ DEPEND_CFLAGS = -DPROTO -DDEPEND -DFEAT_GUI $(LINT_CFLAGS) +# If you have problems with flags that cproto doesn't support, and you are +# using GNU make, you can try using the other line to filter out arguments. +#PFLAGS = $(PROTO_FLAGS) -DPROTO $(filter -D% -I%, $(LINT_CFLAGS)) PFLAGS = $(PROTO_FLAGS) -DPROTO $(LINT_CFLAGS) ALL_LIB_DIRS = $(GUI_LIBS_DIR) $(X_LIBS_DIR) @@ -1867,6 +1872,8 @@ installtutorbin: $(DEST_VIM) $(INSTALL_DATA) vimtutor $(DEST_BIN)/$(VIMNAME)tutor chmod $(SCRIPTMOD) $(DEST_BIN)/$(VIMNAME)tutor + $(INSTALL_DATA) gvimtutor $(DEST_BIN)/$(GVIMNAME)tutor + chmod $(SCRIPTMOD) $(DEST_BIN)/$(GVIMNAME)tutor installtutor: $(DEST_RT) $(DEST_TUTOR) -$(INSTALL_DATA) $(TUTORSOURCE)/README* $(TUTORSOURCE)/tutor* $(DEST_TUTOR) @@ -2075,6 +2082,7 @@ uninstall: uninstall_runtime -rm -f $(DEST_BIN)/$(VIMTARGET) -rm -f $(DEST_BIN)/vimtutor + -rm -f $(DEST_BIN)/gvimtutor -rm -f $(DEST_BIN)/$(EXTARGET) $(DEST_BIN)/$(VIEWTARGET) -rm -f $(DEST_BIN)/$(GVIMTARGET) $(DEST_BIN)/$(GVIEWTARGET) -rm -f $(DEST_BIN)/$(RVIMTARGET) $(DEST_BIN)/$(RVIEWTARGET) @@ -2171,7 +2179,7 @@ shadow: runtime pixmaps mkdir $(SHADOWDIR) - cd $(SHADOWDIR); ln -s ../*.[ch] ../*.in ../*.sh ../*.xs ../*.xbm ../toolcheck ../proto ../vimtutor ../mkinstalldirs . + cd $(SHADOWDIR); ln -s ../*.[ch] ../*.in ../*.sh ../*.xs ../*.xbm ../toolcheck ../proto ../po ../vimtutor ../gvimtutor ../mkinstalldirs . mkdir $(SHADOWDIR)/auto cd $(SHADOWDIR)/auto; ln -s ../../auto/configure . cd $(SHADOWDIR); rm -f auto/link.sed @@ -2190,7 +2198,7 @@ cd $(SHADOWDIR)/testdir; ln -s ../../testdir/Makefile \ ../../testdir/vimrc.unix \ ../../testdir/*.in \ - ../../testdir/unix.vim \ + ../../testdir/*.vim \ ../../testdir/*.ok . # Link needed for doing "make install" in a shadow directory. @@ -2559,8 +2567,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 07:49:09.000000000 -0400 +++ vim71/src/auto/configure 2008-06-18 06:56:39.000000000 -0400 @@ -845,6 +845,7 @@ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --disable-darwin Disable Darwin (Mac OS X) support. + --disable-selinux Don't check for SELinux support. --disable-xsmp Disable XSMP session management --disable-xsmp-interact Disable XSMP interaction --enable-mzschemeinterp Include MzScheme interpreter. @@ -3611,6 +3612,94 @@ esac fi +echo "$as_me:$LINENO: checking --disable-selinux argument" >&5 +echo $ECHO_N "checking --disable-selinux argument... $ECHO_C" >&6 +# Check whether --enable-selinux or --disable-selinux was given. +if test "${enable_selinux+set}" = set; then + enableval="$enable_selinux" + +else + enable_selinux="yes" +fi; +if test "$enable_selinux" = "yes"; then + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + echo "$as_me:$LINENO: checking for is_selinux_enabled in -lselinux" >&5 +echo $ECHO_N "checking for is_selinux_enabled in -lselinux... $ECHO_C" >&6 +if test "${ac_cv_lib_selinux_is_selinux_enabled+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lselinux $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char is_selinux_enabled (); +int +main () +{ +is_selinux_enabled (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_selinux_is_selinux_enabled=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_selinux_is_selinux_enabled=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_selinux_is_selinux_enabled" >&5 +echo "${ECHO_T}$ac_cv_lib_selinux_is_selinux_enabled" >&6 +if test $ac_cv_lib_selinux_is_selinux_enabled = yes; then + LIBS="$LIBS -lselinux" + cat >>confdefs.h <<\_ACEOF +#define HAVE_SELINUX 1 +_ACEOF + +fi + +else + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +fi echo "$as_me:$LINENO: checking --with-features argument" >&5 @@ -3843,7 +3932,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 +4534,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 +4578,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 @@ -4625,10 +4758,11 @@ echo "$as_me:$LINENO: checking for location of Tcl include" >&5 echo $ECHO_N "checking for location of Tcl include... $ECHO_C" >&6 if test "x$MACOSX" != "xyes"; then - tclinc="$tclloc/include $tclloc/include/tcl $tclloc/include/tcl$tclver /usr/local/include /usr/include" + tclinc="$tclloc/include $tclloc/include/tcl $tclloc/include/tcl$tclver /usr/local/include /usr/include /usr/include/tcl$tclver" else tclinc="/System/Library/Frameworks/Tcl.framework/Headers" fi + TCL_INC= for try in $tclinc; do if test -f "$try/tcl.h"; then echo "$as_me:$LINENO: result: $try/tcl.h" >&5 @@ -4647,6 +4781,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 +4801,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 +10399,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 +14349,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 11:25:59.000000000 -0400 +++ vim71/src/buffer.c 2008-06-18 06:56:11.000000000 -0400 @@ -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 @@ -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; @@ -4898,7 +4912,7 @@ return retval; } -#ifdef FEAT_VIMINFO +#if defined(FEAT_VIMINFO) || defined(PROTO) int read_viminfo_bufferlist(virp, writing) vir_T *virp; @@ -5022,13 +5036,14 @@ #if defined(FEAT_QUICKFIX) && defined(FEAT_WINDOWS) if (bt_quickfix(buf)) { - win_T *win; + win_T *win = NULL; + tabpage_T *tp; /* * For location list window, w_llist_ref points to the location list. * For quickfix window, w_llist_ref is NULL. */ - FOR_ALL_WINDOWS(win) + FOR_ALL_TAB_WINDOWS(tp, win) if (win->w_buffer == buf) break; if (win != NULL && win->w_llist_ref != NULL) @@ -5507,11 +5522,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 16:10:37.000000000 -0400 +++ vim71/src/charset.c 2008-06-18 06:55:55.000000000 -0400 @@ -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. @@ -1270,7 +1290,8 @@ /* If a double-cell char doesn't fit at the end of a line * it wraps to the next line, it's like this char is three * cells wide. */ - if (incr == 2 && wp->w_p_wrap && in_win_border(wp, vcol)) + if (incr == 2 && wp->w_p_wrap && MB_BYTE2LEN(*ptr) > 1 + && in_win_border(wp, vcol)) { ++incr; head = 1; @@ -1898,7 +1919,7 @@ { for ( ; *p; ++p) if (rem_backslash(p)) - STRCPY(p, p + 1); + mch_memmove(p, p + 1, STRLEN(p)); } /* diff -Naur vim71.orig/src/config.h.in vim71/src/config.h.in --- vim71.orig/src/config.h.in 2007-04-26 10:40:34.000000000 -0400 +++ vim71/src/config.h.in 2008-06-18 06:56:39.000000000 -0400 @@ -155,6 +155,7 @@ #undef HAVE_READLINK #undef HAVE_RENAME #undef HAVE_SELECT +#undef HAVE_SELINUX #undef HAVE_SETENV #undef HAVE_SETPGID #undef HAVE_SETSID diff -Naur vim71.orig/src/configure.in vim71/src/configure.in --- vim71.orig/src/configure.in 2007-05-12 05:19:27.000000000 -0400 +++ vim71/src/configure.in 2008-06-18 06:56:39.000000000 -0400 @@ -299,6 +299,19 @@ esac fi +dnl Link with -lselinux for SELinux stuff; if not found +AC_MSG_CHECKING(--disable-selinux argument) +AC_ARG_ENABLE(selinux, + [ --disable-selinux Don't check for SELinux support.], + , enable_selinux="yes") +if test "$enable_selinux" = "yes"; then + AC_MSG_RESULT(no) + AC_CHECK_LIB(selinux, is_selinux_enabled, + [LIBS="$LIBS -lselinux" + AC_DEFINE(HAVE_SELINUX)]) +else + AC_MSG_RESULT(yes) +fi dnl Check user requested features. @@ -423,7 +436,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 +772,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) @@ -788,11 +807,12 @@ AC_MSG_CHECKING(for location of Tcl include) if test "x$MACOSX" != "xyes"; then - tclinc="$tclloc/include $tclloc/include/tcl $tclloc/include/tcl$tclver /usr/local/include /usr/include" + tclinc="$tclloc/include $tclloc/include/tcl $tclloc/include/tcl$tclver /usr/local/include /usr/local/include/tcl$tclver /usr/include /usr/include/tcl$tclver" else dnl For Mac OS X 10.3, use the OS-provided framework location tclinc="/System/Library/Frameworks/Tcl.framework/Headers" fi + TCL_INC= for try in $tclinc; do if test -f "$try/tcl.h"; then AC_MSG_RESULT($try/tcl.h) @@ -808,6 +828,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 +849,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 +2046,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 +2740,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-15 19:18:41.000000000 -0500 +++ vim71/src/diff.c 2008-06-18 06:55:22.000000000 -0400 @@ -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 14:24:04.000000000 -0400 +++ vim71/src/digraph.c 2008-06-18 06:54:32.000000000 -0400 @@ -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 15:43:55.000000000 -0400 +++ vim71/src/edit.c 2008-06-18 06:56:15.000000000 -0400 @@ -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 @@ -5346,7 +5491,7 @@ #if defined(FEAT_EVAL) int do_internal = TRUE; - if (*curbuf->b_p_fex != NUL) + if (*curbuf->b_p_fex != NUL && (flags & INSCHAR_NO_FEX) == 0) { do_internal = (fex_format(curwin->w_cursor.lnum, 1L, c) != 0); /* It may be required to save for undo again, e.g. when setline() @@ -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); @@ -5912,7 +6057,7 @@ * be adjusted for the text formatting. */ saved_cursor = pos; - format_lines((linenr_T)-1); + format_lines((linenr_T)-1, FALSE); curwin->w_cursor = saved_cursor; saved_cursor.lnum = 0; @@ -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 15:47:32.000000000 -0400 +++ vim71/src/eval.c 2008-06-18 06:56:49.000000000 -0400 @@ -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)); @@ -505,6 +507,7 @@ static void f_filter __ARGS((typval_T *argvars, typval_T *rettv)); static void f_finddir __ARGS((typval_T *argvars, typval_T *rettv)); static void f_findfile __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_fnameescape __ARGS((typval_T *argvars, typval_T *rettv)); static void f_fnamemodify __ARGS((typval_T *argvars, typval_T *rettv)); static void f_foldclosed __ARGS((typval_T *argvars, typval_T *rettv)); static void f_foldclosedend __ARGS((typval_T *argvars, typval_T *rettv)); @@ -529,6 +532,8 @@ 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_getpid __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 +582,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 +625,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 +653,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 +681,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 +708,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 +1001,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 +1322,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 +1365,6 @@ if (p_verbose == 0) --emsg_off; - vimvars[VV_VAL].vv_str = NULL; restore_vimvar(VV_VAL, &save_val); return list; @@ -1411,7 +1418,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 +1492,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 +1515,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 +1540,7 @@ clear_tv(&rettv); return retval; } -#endif +# endif /* * Call vimL function "func" and return the result as a list @@ -1556,9 +1566,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 +1701,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 +1718,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 +1935,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 +1954,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 +1963,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 +2002,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 +2014,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 +2108,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 +2133,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 +3410,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 +3418,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 +6133,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 +6710,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 +6750,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 +6827,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 +6912,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 +7076,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}, @@ -7074,6 +7108,7 @@ {"filter", 2, 2, f_filter}, {"finddir", 1, 3, f_finddir}, {"findfile", 1, 3, f_findfile}, + {"fnameescape", 1, 1, f_fnameescape}, {"fnamemodify", 2, 2, f_fnamemodify}, {"foldclosed", 1, 1, f_foldclosed}, {"foldclosedend", 1, 1, f_foldclosedend}, @@ -7082,7 +7117,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 +7134,8 @@ {"getftype", 1, 1, f_getftype}, {"getline", 1, 2, f_getline}, {"getloclist", 1, 1, f_getqflist}, + {"getmatches", 0, 0, f_getmatches}, + {"getpid", 0, 0, f_getpid}, {"getpos", 1, 1, f_getpos}, {"getqflist", 0, 0, f_getqflist}, {"getreg", 0, 2, f_getreg}, @@ -7149,7 +7186,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 +7218,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 +7257,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 +8281,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 +8737,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; @@ -9152,13 +9207,13 @@ rettv->vval.v_number = filewritable(get_tv_string(&argvars[0])); } -static void findfilendir __ARGS((typval_T *argvars, typval_T *rettv, int dir)); +static void findfilendir __ARGS((typval_T *argvars, typval_T *rettv, int find_what)); static void -findfilendir(argvars, rettv, dir) +findfilendir(argvars, rettv, find_what) typval_T *argvars; typval_T *rettv; - int dir; + int find_what; { #ifdef FEAT_SEARCHPATH char_u *fname; @@ -9203,8 +9258,11 @@ vim_free(fresult); fresult = find_file_in_path_option(first ? fname : NULL, first ? (int)STRLEN(fname) : 0, - 0, first, path, dir, curbuf->b_ffname, - dir ? (char_u *)"" : curbuf->b_p_sua); + 0, first, path, + find_what, + curbuf->b_ffname, + find_what == FINDFILE_DIR + ? (char_u *)"" : curbuf->b_p_sua); first = FALSE; if (fresult != NULL && rettv->v_type == VAR_LIST) @@ -9339,15 +9397,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 +9425,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; } /* @@ -9391,7 +9452,7 @@ typval_T *argvars; typval_T *rettv; { - findfilendir(argvars, rettv, TRUE); + findfilendir(argvars, rettv, FINDFILE_DIR); } /* @@ -9402,7 +9463,20 @@ typval_T *argvars; typval_T *rettv; { - findfilendir(argvars, rettv, FALSE); + findfilendir(argvars, rettv, FINDFILE_FILE); +} + +/* + * "fnameescape({string})" function + */ + static void +f_fnameescape(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ + rettv->vval.v_string = vim_strsave_fnameescape( + get_tv_string(&argvars[0]), FALSE); + rettv->v_type = VAR_STRING; } /* @@ -9670,6 +9744,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 +9945,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 +10219,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 +10358,51 @@ } /* + * "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 +} + +/* + * "getpid()" function + */ +/*ARGSUSED*/ + static void +f_getpid(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ + rettv->vval.v_number = mch_get_pid(); +} + +/* * "getpos(string)" function */ static void @@ -10290,7 +10424,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 +10920,9 @@ "gui_gtk2", # endif #endif +#ifdef FEAT_GUI_GNOME + "gui_gnome", +#endif #ifdef FEAT_GUI_MAC "gui_mac", #endif @@ -11471,14 +11609,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 +12575,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 +12623,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 +13876,7 @@ } /* Shorten "remain". */ if (*q != NUL) - STRCPY(remain, q - 1); + mch_memmove(remain, q - 1, STRLEN(q - 1) + 1); else { vim_free(remain); @@ -13773,6 +13969,7 @@ rettv->vval.v_list = l; rettv->v_type = VAR_LIST; ++l->lv_refcount; + l->lv_idx = l->lv_len - l->lv_idx - 1; } } @@ -13858,6 +14055,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 +14072,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 +14108,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 +14132,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 +14198,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 +14222,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 +14238,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 +14304,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 +14314,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 +14329,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 +14363,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 +14382,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) { @@ -14439,6 +14678,8 @@ appended_lines_mark(lcount, added); } +static void set_qf_ll_list __ARGS((win_T *wp, typval_T *list_arg, typval_T *action_arg, typval_T *rettv)); + /* * Used by "setqflist()" and "setloclist()" functions */ @@ -14498,6 +14739,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 +14811,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 +15093,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 @@ -14906,7 +15218,7 @@ if (!item_compare_func_err) { /* Clear the List and append the items in the sorted order. */ - l->lv_first = l->lv_last = NULL; + l->lv_first = l->lv_last = l->lv_idx_item = NULL; l->lv_len = 0; for (i = 0; i < len; ++i) list_append(l, ptrs[i]); @@ -15274,7 +15586,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 +15774,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 +15897,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 +15952,7 @@ FILE *fd; if (check_restricted() || check_secure()) - return; + goto done; if (argvars[1].v_type != VAR_UNKNOWN) { @@ -15610,7 +15963,7 @@ if ((infile = vim_tempname('i')) == NULL) { EMSG(_(e_notmp)); - return; + goto done; } fd = mch_fopen((char *)infile, WRITEBIN); @@ -16497,9 +16850,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 +16865,7 @@ list_T *l; int len; int error = FALSE; + listitem_T *li; l = varp->vval.v_list; if (l == NULL) @@ -16527,6 +16881,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 +16921,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 +16939,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 +18160,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 +18171,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 +18213,11 @@ if (type == VAR_FUNC) msg_puts((char_u *)"()"); + if (*first) + { + msg_clr_eos(); + *first = FALSE; + } } /* @@ -19136,6 +19507,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 +20362,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 +20373,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 +20457,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 */ @@ -20667,8 +21068,12 @@ static int shortpath_for_partial __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen)); /* - * Get the short pathname of a file. - * Returns 1 on success. *fnamelen is 0 for nonexistent path. + * Get the short path (8.3) for the filename in "fnamep". + * Only works for a valid file name. + * When the path gets longer "fnamep" is changed and the allocated buffer + * is put in "bufp". + * *fnamelen is the length of "fnamep" and set to 0 for a nonexistent path. + * Returns OK on success, FAIL on failure. */ static int get_short_pathname(fnamep, bufp, fnamelen) @@ -20676,36 +21081,44 @@ char_u **bufp; int *fnamelen; { - int l,len; + int l, len; char_u *newbuf; len = *fnamelen; - l = GetShortPathName(*fnamep, *fnamep, len); if (l > len - 1) { /* If that doesn't work (not enough space), then save the string - * and try again with a new buffer big enough - */ + * and try again with a new buffer big enough. */ newbuf = vim_strnsave(*fnamep, l); if (newbuf == NULL) - return 0; + return FAIL; vim_free(*bufp); *fnamep = *bufp = newbuf; - l = GetShortPathName(*fnamep,*fnamep,l+1); - - /* Really should always succeed, as the buffer is big enough */ + /* Really should always succeed, as the buffer is big enough. */ + l = GetShortPathName(*fnamep, *fnamep, l+1); } *fnamelen = l; - return 1; + return OK; } /* - * Create a short path name. Returns the length of the buffer it needs. - * Doesn't copy over the end of the buffer passed in. + * Get the short path (8.3) for the filename in "fname". The converted + * path is returned in "bufp". + * + * Some of the directories specified in "fname" may not exist. This function + * will shorten the existing directories at the beginning of the path and then + * append the remaining non-existing path. + * + * fname - Pointer to the filename to shorten. On return, contains the + * pointer to the shortened pathname + * bufp - Pointer to an allocated buffer for the filename. + * fnamelen - Length of the filename pointed to by fname + * + * Returns OK on success (or nothing done) and FAIL on failure (out of memory). */ static int shortpath_for_invalid_fname(fname, bufp, fnamelen) @@ -20713,85 +21126,106 @@ char_u **bufp; int *fnamelen; { - char_u *s, *p, *pbuf2, *pbuf3; + char_u *short_fname, *save_fname, *pbuf_unused; + char_u *endp, *save_endp; char_u ch; - int len, len2, plen, slen; + int old_len, len; + int new_len, sfx_len; + int retval = OK; /* Make a copy */ - len2 = *fnamelen; - pbuf2 = vim_strnsave(*fname, len2); - pbuf3 = NULL; - - s = pbuf2 + len2 - 1; /* Find the end */ - slen = 1; - plen = len2; - - if (after_pathsep(pbuf2, s + 1)) - { - --s; - ++slen; - --plen; - } + old_len = *fnamelen; + save_fname = vim_strnsave(*fname, old_len); + pbuf_unused = NULL; + short_fname = NULL; - do + endp = save_fname + old_len - 1; /* Find the end of the copy */ + save_endp = endp; + + /* + * Try shortening the supplied path till it succeeds by removing one + * directory at a time from the tail of the path. + */ + len = 0; + for (;;) { - /* Go back one path-separator */ - while (s > pbuf2 && !after_pathsep(pbuf2, s + 1)) - { - --s; - ++slen; - --plen; - } - if (s <= pbuf2) - break; + /* go back one path-separator */ + while (endp > save_fname && !after_pathsep(save_fname, endp + 1)) + --endp; + if (endp <= save_fname) + break; /* processed the complete path */ - /* Remember the character that is about to be splatted */ - ch = *s; - *s = 0; /* get_short_pathname requires a null-terminated string */ - - /* Try it in situ */ - p = pbuf2; - if (!get_short_pathname(&p, &pbuf3, &plen)) + /* + * Replace the path separator with a NUL and try to shorten the + * resulting path. + */ + ch = *endp; + *endp = 0; + short_fname = save_fname; + len = STRLEN(short_fname) + 1; + if (get_short_pathname(&short_fname, &pbuf_unused, &len) == FAIL) { - vim_free(pbuf2); - return -1; + retval = FAIL; + goto theend; } - *s = ch; /* Preserve the string */ - } while (plen == 0); + *endp = ch; /* preserve the string */ - if (plen > 0) + if (len > 0) + break; /* successfully shortened the path */ + + /* failed to shorten the path. Skip the path separator */ + --endp; + } + + if (len > 0) { - /* Remember the length of the new string. */ - *fnamelen = len = plen + slen; + /* + * Succeeded in shortening the path. Now concatenate the shortened + * path with the remaining path at the tail. + */ + + /* Compute the length of the new path. */ + sfx_len = (int)(save_endp - endp) + 1; + new_len = len + sfx_len; + + *fnamelen = new_len; vim_free(*bufp); - if (len > len2) + if (new_len > old_len) { - /* If there's not enough space in the currently allocated string, - * then copy it to a buffer big enough. - */ - *fname= *bufp = vim_strnsave(p, len); + /* There is not enough space in the currently allocated string, + * copy it to a buffer big enough. */ + *fname = *bufp = vim_strnsave(short_fname, new_len); if (*fname == NULL) - return -1; + { + retval = FAIL; + goto theend; + } } else { - /* Transfer pbuf2 to being the main buffer (it's big enough) */ - *fname = *bufp = pbuf2; - if (p != pbuf2) - strncpy(*fname, p, plen); - pbuf2 = NULL; - } - /* Concat the next bit */ - strncpy(*fname + plen, s, slen); - (*fname)[len] = '\0'; + /* Transfer short_fname to the main buffer (it's big enough), + * unless get_short_pathname() did its work in-place. */ + *fname = *bufp = save_fname; + if (short_fname != save_fname) + vim_strncpy(save_fname, short_fname, len); + save_fname = NULL; + } + + /* concat the not-shortened part of the path */ + vim_strncpy(*fname + len, endp, sfx_len); + (*fname)[new_len] = NUL; } - vim_free(pbuf3); - vim_free(pbuf2); - return 0; + +theend: + vim_free(pbuf_unused); + vim_free(save_fname); + + return retval; } /* * Get a pathname for a partial path. + * Returns OK for success, FAIL for failure. */ static int shortpath_for_partial(fnamep, bufp, fnamelen) @@ -20821,8 +21255,8 @@ len = tflen = (int)STRLEN(tfname); - if (!get_short_pathname(&tfname, &pbuf, &len)) - return -1; + if (get_short_pathname(&tfname, &pbuf, &len) == FAIL) + return FAIL; if (len == 0) { @@ -20831,8 +21265,8 @@ * there's not a lot of point in guessing what it might be. */ len = tflen; - if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == -1) - return -1; + if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == FAIL) + return FAIL; } /* Count the paths backward to find the beginning of the desired string. */ @@ -20856,7 +21290,7 @@ if (p >= tfname) *p = '~'; else - return -1; + return FAIL; } else ++p; @@ -20867,7 +21301,7 @@ *bufp = pbuf; *fnamep = p; - return 0; + return OK; } #endif /* WIN3264 */ @@ -20875,7 +21309,7 @@ * Adjust a filename, according to a string of modifiers. * *fnamep must be NUL terminated when called. When returning, the length is * determined by *fnamelen. - * Returns valid flags. + * Returns VALID_ flags or -1 for failure. * When there is an error, *fnamep is set to NULL. */ int @@ -21034,14 +21468,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 */ @@ -21074,7 +21521,7 @@ */ if (!has_fullname && !vim_isAbsName(*fnamep)) { - if (shortpath_for_partial(fnamep, bufp, fnamelen) == -1) + if (shortpath_for_partial(fnamep, bufp, fnamelen) == FAIL) return -1; } else @@ -21084,7 +21531,7 @@ /* Simple case, already have the full-name * Nearly always shorter, so try first time. */ l = *fnamelen; - if (!get_short_pathname(fnamep, bufp, &l)) + if (get_short_pathname(fnamep, bufp, &l) == FAIL) return -1; if (l == 0) @@ -21092,7 +21539,7 @@ /* Couldn't find the filename.. search the paths. */ l = *fnamelen; - if (shortpath_for_invalid_fname(fnamep, bufp, &l ) == -1) + if (shortpath_for_invalid_fname(fnamep, bufp, &l) == FAIL) return -1; } *fnamelen = l; diff -Naur vim71.orig/src/ex_cmds.c vim71/src/ex_cmds.c --- vim71.orig/src/ex_cmds.c 2007-05-07 15:41:01.000000000 -0400 +++ vim71/src/ex_cmds.c 2008-06-18 06:56:36.000000000 -0400 @@ -365,6 +365,10 @@ int sort_oct; /* sort on octal number */ int sort_hex; /* sort on hex number */ + /* Sorting one line is really quick! */ + if (count <= 1) + return; + if (u_save((linenr_T)(eap->line1 - 1), (linenr_T)(eap->line2 + 1)) == FAIL) return; sortbuf1 = NULL; @@ -408,7 +412,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 */ @@ -1152,6 +1160,7 @@ if (!do_out) msg_putchar('\n'); + /* Create the shell command in allocated memory. */ cmd_buf = make_filter_cmd(cmd, itmp, otmp); if (cmd_buf == NULL) goto filterend; @@ -1172,7 +1181,10 @@ if (do_out) { if (u_save((linenr_T)(line2), (linenr_T)(line2 + 1)) == FAIL) + { + vim_free(cmd_buf); goto error; + } redraw_curbuf_later(VALID); } read_linecount = curbuf->b_ml.ml_line_count; @@ -1646,7 +1658,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 +1782,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 +2740,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 +2928,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 +2970,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 +2986,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 +3401,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 +3596,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 +3694,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 +3799,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 +4208,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 +4219,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 +4254,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 +4337,7 @@ do_error = TRUE; do_print = FALSE; do_count = FALSE; + do_number = FALSE; do_ic = 0; } while (*cmd) @@ -4410,8 +4454,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,11 +4470,12 @@ 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 * copying. There are these pieces: - * sub_firstline The old text, unmodifed. + * sub_firstline The old text, unmodified. * copycol Column in the old text where we started * looking for a match; from here old text still * needs to be copied to the new text. @@ -4445,8 +4490,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 +4511,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 +4538,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 +4602,7 @@ { matchcol = (colnr_T)STRLEN(sub_firstline); nmatch = 1; + skip_match = TRUE; } sub_nsubs++; did_sub = TRUE; @@ -4600,7 +4665,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 +4701,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 +4777,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 +4848,8 @@ mch_memmove(new_end, sub_firstline + copycol, (size_t)i); new_end += i; - (void)vim_regsub_multi(®match, sub_firstlnum, + (void)vim_regsub_multi(®match, + sub_firstlnum - regmatch.startpos[0].lnum, sub, new_end, TRUE, p_magic, TRUE); sub_nsubs++; did_sub = TRUE; @@ -4850,7 +4918,8 @@ ++line2; /* move the cursor to the new line, like Vi */ ++curwin->w_cursor.lnum; - STRCPY(new_start, p1 + 1); /* copy the rest */ + /* copy the rest */ + mch_memmove(new_start, p1 + 1, STRLEN(p1 + 1) + 1); p1 = new_start - 1; } } @@ -4869,10 +4938,13 @@ skip: /* We already know that we did the last subst when we are at * the end of the line, except that a pattern like - * "bar\|\nfoo" may match at the NUL. */ + * "bar\|\nfoo" may match at the NUL. "lnum" can be below + * "line2" when there is a \zs in the pattern after a line + * break. */ lastone = (skip_match || got_int || got_quit + || lnum > line2 || !(do_all || do_again) || (sub_firstline[matchcol] == NUL && nmatch <= 1 && !re_multiline(regmatch.regprog))); @@ -4887,12 +4959,16 @@ * When asking the user we like to show the already replaced * text, but don't do it when "\<@=" or "\<@!" is used, it * changes what matches. + * When the match starts below where we start searching also + * need to replace the line first (using \zs after \n). */ if (lastone || (do_ask && !re_lookbehind(regmatch.regprog)) || nmatch_tl > 0 || (nmatch = vim_regexec_multi(®match, curwin, - curbuf, sub_firstlnum, matchcol)) == 0) + curbuf, sub_firstlnum, + matchcol, NULL)) == 0 + || regmatch.startpos[0].lnum > 0) { if (new_start != NULL) { @@ -4956,13 +5032,20 @@ } if (nmatch == -1 && !lastone) nmatch = vim_regexec_multi(®match, curwin, curbuf, - sub_firstlnum, matchcol); + sub_firstlnum, matchcol, NULL); /* * 5. break if there isn't another match in this line */ if (nmatch <= 0) + { + /* If the match found didn't start where we were + * searching, do the next search in the line where we + * found the match. */ + if (nmatch == -1) + lnum -= regmatch.startpos[0].lnum; break; + } } line_breakcheck(); @@ -5179,7 +5262,8 @@ for (lnum = eap->line1; lnum <= eap->line2 && !got_int; ++lnum) { /* a match on this line? */ - match = vim_regexec_multi(®match, curwin, curbuf, lnum, (colnr_T)0); + match = vim_regexec_multi(®match, curwin, curbuf, lnum, + (colnr_T)0, NULL); if ((type == 'g' && match) || (type == 'v' && !match)) { ml_setmarked(lnum); @@ -6018,7 +6102,7 @@ } #if defined(FEAT_EX_EXTRA) || defined(PROTO) -static void helptags_one __ARGS((char_u *dir, char_u *ext, char_u *lang)); +static void helptags_one __ARGS((char_u *dir, char_u *ext, char_u *lang, int add_help_tags)); /* * ":helptags" @@ -6033,12 +6117,26 @@ #ifdef FEAT_MULTI_LANG char_u lang[2]; #endif + expand_T xpc; + char_u *dirname; char_u ext[5]; char_u fname[8]; int filecount; char_u **files; + int add_help_tags = FALSE; + + /* Check for ":helptags ++t {dir}". */ + if (STRNCMP(eap->arg, "++t", 3) == 0 && vim_iswhite(eap->arg[3])) + { + add_help_tags = TRUE; + eap->arg = skipwhite(eap->arg + 3); + } - if (!mch_isdir(eap->arg)) + ExpandInit(&xpc); + xpc.xp_context = EXPAND_DIRECTORIES; + dirname = ExpandOne(&xpc, eap->arg, NULL, + WILD_LIST_NOTFOUND|WILD_SILENT, WILD_EXPAND_FREE); + if (dirname == NULL || !mch_isdir(dirname)) { EMSG2(_("E150: Not a directory: %s"), eap->arg); return; @@ -6046,7 +6144,7 @@ #ifdef FEAT_MULTI_LANG /* Get a list of all files in the directory. */ - STRCPY(NameBuff, eap->arg); + STRCPY(NameBuff, dirname); add_pathsep(NameBuff); STRCAT(NameBuff, "*"); if (gen_expand_wildcards(1, &NameBuff, &filecount, &files, @@ -6054,6 +6152,7 @@ || filecount == 0) { EMSG2("E151: No match: %s", NameBuff); + vim_free(dirname); return; } @@ -6119,7 +6218,7 @@ ext[1] = fname[5]; ext[2] = fname[6]; } - helptags_one(eap->arg, ext, fname); + helptags_one(dirname, ext, fname, add_help_tags); } ga_clear(&ga); @@ -6127,15 +6226,17 @@ #else /* No language support, just use "*.txt" and "tags". */ - helptags_one(eap->arg, (char_u *)".txt", (char_u *)"tags"); + helptags_one(dirname, (char_u *)".txt", (char_u *)"tags", add_help_tags); #endif + vim_free(dirname); } static void -helptags_one(dir, ext, tagfname) - char_u *dir; /* doc directory */ - char_u *ext; /* suffix, ".txt", ".itx", ".frx", etc. */ - char_u *tagfname; /* "tags" for English, "tags-it" for Italian. */ +helptags_one(dir, ext, tagfname, add_help_tags) + char_u *dir; /* doc directory */ + char_u *ext; /* suffix, ".txt", ".itx", ".frx", etc. */ + char_u *tagfname; /* "tags" for English, "tags-fr" for French. */ + int add_help_tags; /* add "help-tags" tag */ { FILE *fd_tags; FILE *fd; @@ -6186,10 +6287,12 @@ } /* - * If generating tags for "$VIMRUNTIME/doc" add the "help-tags" tag. + * If using the "++t" argument or generating tags for "$VIMRUNTIME/doc" + * add the "help-tags" tag. */ ga_init2(&ga, (int)sizeof(char_u *), 100); - if (fullpathcmp((char_u *)"$VIMRUNTIME/doc", dir, FALSE) == FPC_SAME) + if (add_help_tags || fullpathcmp((char_u *)"$VIMRUNTIME/doc", + dir, FALSE) == FPC_SAME) { if (ga_grow(&ga, 1) == FAIL) got_int = TRUE; @@ -6351,9 +6454,9 @@ for (i = 0; i < ga.ga_len; ++i) { s = ((char_u **)ga.ga_data)[i]; - if (STRNCMP(s, "help-tags", 9) == 0) + if (STRNCMP(s, "help-tags\t", 10) == 0) /* help-tags entry was added in formatted form */ - fprintf(fd_tags, (char *)s); + fputs((char *)s, fd_tags); else { fprintf(fd_tags, "%s\t/*", s); diff -Naur vim71.orig/src/ex_cmds.h vim71/src/ex_cmds.h --- vim71.orig/src/ex_cmds.h 2007-03-07 15:53:27.000000000 -0500 +++ vim71/src/ex_cmds.h 2008-06-18 06:55:02.000000000 -0400 @@ -422,7 +422,7 @@ EX(CMD_helpgrep, "helpgrep", ex_helpgrep, EXTRA|NOTRLCOM|NEEDARG), EX(CMD_helptags, "helptags", ex_helptags, - NEEDARG|FILE1|TRLBAR|CMDWIN), + NEEDARG|FILES|TRLBAR|CMDWIN), EX(CMD_hardcopy, "hardcopy", ex_hardcopy, RANGE|COUNT|EXTRA|TRLBAR|DFLALL|BANG), EX(CMD_highlight, "highlight", ex_highlight, diff -Naur vim71.orig/src/ex_cmds2.c vim71/src/ex_cmds2.c --- vim71.orig/src/ex_cmds2.c 2007-05-07 15:25:02.000000000 -0400 +++ vim71/src/ex_cmds2.c 2008-06-18 06:55:20.000000000 -0400 @@ -93,6 +93,8 @@ int save_emsg_silent = emsg_silent; int save_redir_off = redir_off; tasave_T typeaheadbuf; + int typeahead_saved = FALSE; + int save_ignore_script = 0; # ifdef FEAT_EX_EXTRA int save_ex_normal_busy; # endif @@ -159,18 +161,26 @@ * This makes sure we get input from the user here and don't interfere * with the commands being executed. Reset "ex_normal_busy" to avoid * the side effects of using ":normal". Save the stuff buffer and make - * it empty. */ + * it empty. Set ignore_script to avoid reading from script input. */ # ifdef FEAT_EX_EXTRA save_ex_normal_busy = ex_normal_busy; ex_normal_busy = 0; # endif if (!debug_greedy) + { save_typeahead(&typeaheadbuf); + typeahead_saved = TRUE; + save_ignore_script = ignore_script; + ignore_script = TRUE; + } cmdline = getcmdline_prompt('>', NULL, 0, EXPAND_NOTHING, NULL); - if (!debug_greedy) + if (typeahead_saved) + { restore_typeahead(&typeaheadbuf); + ignore_script = save_ignore_script; + } # ifdef FEAT_EX_EXTRA ex_normal_busy = save_ex_normal_busy; # endif @@ -885,19 +895,61 @@ sprintf(buf, "%10.6lf", (double)tm->QuadPart / (double)fr.QuadPart); # else sprintf(buf, "%3ld.%06ld", (long)tm->tv_sec, (long)tm->tv_usec); -#endif +# endif return buf; } -# endif /* FEAT_PROFILE || FEAT_RELTIME */ +/* + * Put the time "msec" past now in "tm". + */ + void +profile_setlimit(msec, tm) + long msec; + proftime_T *tm; +{ + if (msec <= 0) /* no limit */ + profile_zero(tm); + else + { +# ifdef WIN3264 + LARGE_INTEGER fr; + + QueryPerformanceCounter(tm); + QueryPerformanceFrequency(&fr); + tm->QuadPart += (LONGLONG)((double)msec / 1000.0 * (double)fr.QuadPart); +# else + long usec; + + gettimeofday(tm, NULL); + usec = (long)tm->tv_usec + (long)msec * 1000; + tm->tv_usec = usec % 1000000L; + tm->tv_sec += usec / 1000000L; +# endif + } +} -# if defined(FEAT_PROFILE) || defined(PROTO) /* - * Functions for profiling. + * Return TRUE if the current time is past "tm". */ -static void script_do_profile __ARGS((scriptitem_T *si)); -static void script_dump_profile __ARGS((FILE *fd)); -static proftime_T prof_wait_time; + int +profile_passed_limit(tm) + proftime_T *tm; +{ + proftime_T now; + +# ifdef WIN3264 + if (tm->QuadPart == 0) /* timer was not set */ + return FALSE; + QueryPerformanceCounter(&now); + return (now.QuadPart > tm->QuadPart); +# else + if (tm->tv_sec == 0) /* timer was not set */ + return FALSE; + gettimeofday(&now, NULL); + return (now.tv_sec > tm->tv_sec + || (now.tv_sec == tm->tv_sec && now.tv_usec > tm->tv_usec)); +# endif +} /* * Set the time in "tm" to zero. @@ -914,6 +966,16 @@ # endif } +# endif /* FEAT_PROFILE || FEAT_RELTIME */ + +# if defined(FEAT_PROFILE) || defined(PROTO) +/* + * Functions for profiling. + */ +static void script_do_profile __ARGS((scriptitem_T *si)); +static void script_dump_profile __ARGS((FILE *fd)); +static proftime_T prof_wait_time; + /* * Add the time "tm2" to "tm". */ @@ -2827,11 +2889,14 @@ if (has_autocmd(EVENT_SOURCECMD, fname_exp, NULL) && apply_autocmds(EVENT_SOURCECMD, fname_exp, fname_exp, FALSE, curbuf)) + { # ifdef FEAT_EVAL - return aborting() ? FAIL : OK; + retval = aborting() ? FAIL : OK; # else - return OK; + retval = OK; # endif + goto theend; + } /* Apply SourcePre autocommands, they may get the file. */ apply_autocmds(EVENT_SOURCEPRE, fname_exp, fname_exp, FALSE, curbuf); diff -Naur vim71.orig/src/ex_docmd.c vim71/src/ex_docmd.c --- vim71.orig/src/ex_docmd.c 2007-05-07 15:49:38.000000000 -0400 +++ vim71/src/ex_docmd.c 2008-06-18 06:56:06.000000000 -0400 @@ -133,6 +133,7 @@ static void get_flags __ARGS((exarg_T *eap)); #if !defined(FEAT_PERL) || !defined(FEAT_PYTHON) || !defined(FEAT_TCL) \ || !defined(FEAT_RUBY) || !defined(FEAT_MZSCHEME) +# define HAVE_EX_SCRIPT_NI static void ex_script_ni __ARGS((exarg_T *eap)); #endif static char_u *invalid_range __ARGS((exarg_T *eap)); @@ -372,7 +373,7 @@ static char_u *arg_all __ARGS((void)); #ifdef FEAT_SESSION static int makeopens __ARGS((FILE *fd, char_u *dirnow)); -static int put_view __ARGS((FILE *fd, win_T *wp, int add_edit, unsigned *flagp)); +static int put_view __ARGS((FILE *fd, win_T *wp, int add_edit, unsigned *flagp, int current_arg_idx)); static void ex_loadview __ARGS((exarg_T *eap)); static char_u *get_view_file __ARGS((int c)); static int did_lcd; /* whether ":lcd" was produced for a session */ @@ -666,7 +667,7 @@ if (ex_pressedreturn) { /* go up one line, to overwrite the ":" line, so the - * output doensn't contain empty lines. */ + * output doesn't contain empty lines. */ msg_row = prev_msg_row; if (prev_msg_row == Rows - 1) msg_row--; @@ -1741,7 +1742,9 @@ } /* ignore comment and empty lines */ - if (*ea.cmd == '"' || *ea.cmd == NUL) + if (*ea.cmd == '"') + goto doend; + if (*ea.cmd == NUL) { ex_pressedreturn = TRUE; goto doend; @@ -2118,7 +2121,11 @@ #ifdef FEAT_USR_CMDS !USER_CMDIDX(ea.cmdidx) && #endif - cmdnames[ea.cmdidx].cmd_func == ex_ni); + (cmdnames[ea.cmdidx].cmd_func == ex_ni +#ifdef HAVE_EX_SCRIPT_NI + || cmdnames[ea.cmdidx].cmd_func == ex_script_ni +#endif + )); #ifndef FEAT_EVAL /* @@ -2654,7 +2661,7 @@ errormsg = IObuff; } STRCAT(errormsg, ": "); - STRNCAT(errormsg, *cmdlinep, IOSIZE - STRLEN(IObuff)); + STRNCAT(errormsg, *cmdlinep, IOSIZE - STRLEN(IObuff) - 1); } emsg(errormsg); } @@ -2756,7 +2763,7 @@ /* * Isolate the command and search for it in the command table. - * Exeptions: + * Exceptions: * - the 'k' command can directly be followed by any character. * - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r' * but :sre[wind] is another command, as are :scrip[tnames], @@ -2957,6 +2964,57 @@ #endif #if defined(FEAT_EVAL) || defined(PROTO) +static struct cmdmod +{ + char *name; + int minlen; + int has_count; /* :123verbose :3tab */ +} cmdmods[] = { + {"aboveleft", 3, FALSE}, + {"belowright", 3, FALSE}, + {"botright", 2, FALSE}, + {"browse", 3, FALSE}, + {"confirm", 4, FALSE}, + {"hide", 3, FALSE}, + {"keepalt", 5, FALSE}, + {"keepjumps", 5, FALSE}, + {"keepmarks", 3, FALSE}, + {"leftabove", 5, FALSE}, + {"lockmarks", 3, FALSE}, + {"rightbelow", 6, FALSE}, + {"sandbox", 3, FALSE}, + {"silent", 3, FALSE}, + {"tab", 3, TRUE}, + {"topleft", 2, FALSE}, + {"verbose", 4, TRUE}, + {"vertical", 4, FALSE}, +}; + +/* + * Return length of a command modifier (including optional count). + * Return zero when it's not a modifier. + */ + int +modifier_len(cmd) + char_u *cmd; +{ + int i, j; + char_u *p = cmd; + + if (VIM_ISDIGIT(*cmd)) + p = skipwhite(skipdigits(cmd)); + for (i = 0; i < sizeof(cmdmods) / sizeof(struct cmdmod); ++i) + { + for (j = 0; p[j] != NUL; ++j) + if (p[j] != cmdmods[i].name[j]) + break; + if (!isalpha(p[j]) && j >= cmdmods[i].minlen + && (p == cmd || cmdmods[i].has_count)) + return j + (p - cmd); + } + return 0; +} + /* * Return > 0 if an Ex command "name" exists. * Return 2 if there is an exact match. @@ -2971,30 +3029,6 @@ int i; int j; char_u *p; - static struct cmdmod - { - char *name; - int minlen; - } cmdmods[] = { - {"aboveleft", 3}, - {"belowright", 3}, - {"botright", 2}, - {"browse", 3}, - {"confirm", 4}, - {"hide", 3}, - {"keepalt", 5}, - {"keepjumps", 5}, - {"keepmarks", 3}, - {"leftabove", 5}, - {"lockmarks", 3}, - {"rightbelow", 6}, - {"sandbox", 3}, - {"silent", 3}, - {"tab", 3}, - {"topleft", 2}, - {"verbose", 4}, - {"vertical", 4}, - }; /* Check command modifiers. */ for (i = 0; i < sizeof(cmdmods) / sizeof(struct cmdmod); ++i) @@ -3276,32 +3310,27 @@ if (ea.argt & XFILE) { - int in_quote = FALSE; - char_u *bow = NULL; /* Beginning of word */ + int c; + int in_quote = FALSE; + char_u *bow = NULL; /* Beginning of word */ /* * Allow spaces within back-quotes to count as part of the argument * being expanded. */ xp->xp_pattern = skipwhite(arg); - for (p = xp->xp_pattern; *p; ) + p = xp->xp_pattern; + while (*p != NUL) { - if (*p == '\\' && p[1] != NUL) - ++p; -#ifdef SPACE_IN_FILENAME - else if (vim_iswhite(*p) && (!(ea.argt & NOSPC) || usefilter)) -#else - else if (vim_iswhite(*p)) +#ifdef FEAT_MBYTE + if (has_mbyte) + c = mb_ptr2char(p); + else #endif - { - p = skipwhite(p); - if (in_quote) - bow = p; - else - xp->xp_pattern = p; - --p; - } - else if (*p == '`') + c = *p; + if (c == '\\' && p[1] != NUL) + ++p; + else if (c == '`') { if (!in_quote) { @@ -3310,6 +3339,39 @@ } in_quote = !in_quote; } + /* An argument can contain just about everything, except + * characters that end the command and white space. */ + else if (c == '|' || c == '\n' || c == '"' || (vim_iswhite(c) +#ifdef SPACE_IN_FILENAME + && (!(ea.argt & NOSPC) || usefilter) +#endif + )) + { + len = 0; /* avoid getting stuck when space is in 'isfname' */ + while (*p != NUL) + { +#ifdef FEAT_MBYTE + if (has_mbyte) + c = mb_ptr2char(p); + else +#endif + c = *p; + if (c == '`' || vim_isfilec_or_wc(c)) + break; +#ifdef FEAT_MBYTE + if (has_mbyte) + len = (*mb_ptr2len)(p); + else +#endif + len = 1; + mb_ptr_adv(p); + } + if (in_quote) + bow = p; + else + xp->xp_pattern = p; + p -= len; + } mb_ptr_adv(p); } @@ -3401,14 +3463,13 @@ case CMD_windo: return arg; -#ifdef FEAT_SEARCH_EXTRA +#ifdef FEAT_CMDL_COMPL +# ifdef FEAT_SEARCH_EXTRA case CMD_match: if (*arg == NUL || !ends_excmd(*arg)) { - /* Dummy call to clear variables. */ - set_context_in_highlight_cmd(xp, (char_u *)"link n"); - xp->xp_context = EXPAND_HIGHLIGHT; - xp->xp_pattern = arg; + /* also complete "None" */ + set_context_in_echohl_cmd(xp, arg); arg = skipwhite(skiptowhite(arg)); if (*arg != NUL) { @@ -3417,9 +3478,8 @@ } } return find_nextcmd(arg); -#endif +# endif -#ifdef FEAT_CMDL_COMPL /* * All completion for the +cmdline_compl feature goes here. */ @@ -3617,8 +3677,7 @@ break; case CMD_echohl: - xp->xp_context = EXPAND_HIGHLIGHT; - xp->xp_pattern = arg; + set_context_in_echohl_cmd(xp, arg); break; #endif case CMD_highlight: @@ -3874,7 +3933,7 @@ curwin->w_cursor.col = 0; searchcmdlen = 0; if (!do_search(NULL, c, cmd, 1L, - SEARCH_HIS + SEARCH_MSG + SEARCH_START)) + SEARCH_HIS | SEARCH_MSG, NULL)) { curwin->w_cursor = pos; cmd = NULL; @@ -3921,9 +3980,8 @@ pos.col = 0; if (searchit(curwin, curbuf, &pos, *cmd == '?' ? BACKWARD : FORWARD, - (char_u *)"", 1L, - SEARCH_MSG + SEARCH_START, - i, (linenr_T)0) != FAIL) + (char_u *)"", 1L, SEARCH_MSG, + i, (linenr_T)0, NULL) != FAIL) lnum = pos.lnum; else { @@ -3997,8 +4055,7 @@ eap->errmsg = (char_u *)N_("E319: Sorry, the command is not available in this version"); } -#if !defined(FEAT_PERL) || !defined(FEAT_PYTHON) || !defined(FEAT_TCL) \ - || !defined(FEAT_RUBY) || !defined(FEAT_MZSCHEME) +#ifdef HAVE_EX_SCRIPT_NI /* * Function called for script command which is Not Implemented. NI! * Skips over ":perl <arg, '~') != NULL) { expand_env_esc(eap->arg, NameBuff, MAXPATHL, - TRUE, NULL); + TRUE, TRUE, NULL); has_wildcards = mch_has_wildcard(NameBuff); p = NameBuff; } @@ -4492,7 +4549,8 @@ if (eap->argt & (USECTRLV | XFILE)) ++p; /* skip CTRL-V and next char */ else - STRCPY(p, p + 1); /* remove CTRL-V and skip next char */ + /* remove CTRL-V and skip next char */ + mch_memmove(p, p + 1, STRLEN(p)); if (*p == NUL) /* stop at NUL after CTRL-V */ break; } @@ -6650,7 +6708,7 @@ * The list should be allocated using alloc(), as should each item in the * list. This function takes over responsibility for freeing the list. * - * XXX The list is made into the arggument list. This is freed using + * XXX The list is made into the argument list. This is freed using * FreeWild(), which does a series of vim_free() calls, unless the two defines * __EMX__ and __ALWAYS_HAS_TRAILING_NUL_POINTER are set. In this case, a * routine _fnexplodefree() is used. This may cause problems, but as the drop @@ -7070,7 +7128,7 @@ : eap->addr_count == 0 ? 0 : (int)eap->line2 + 1) != FAIL) { - do_exedit(eap, NULL); + do_exedit(eap, old_curwin); /* set the alternate buffer for the window we came from */ if (curwin != old_curwin @@ -7743,6 +7801,7 @@ free_cd_dir() { vim_free(prev_dir); + prev_dir = NULL; } #endif @@ -7768,7 +7827,7 @@ if (vim_strchr(p_cpo, CPO_CHDIR) != NULL && curbufIsChanged() && !eap->forceit) { - EMSG(_("E747: Cannot change directory, buffer is modifed (add ! to override)")); + EMSG(_("E747: Cannot change directory, buffer is modified (add ! to override)")); return; } @@ -8399,21 +8458,17 @@ || *arg == '"') { redir_reg = *arg++; - if (*arg == '>' && arg[1] == '>') + if (*arg == '>' && arg[1] == '>') /* append */ arg += 2; - else if ((*arg == NUL || (*arg == '>' && arg[1] == NUL)) && - (islower(redir_reg) -# ifdef FEAT_CLIPBOARD - || redir_reg == '*' - || redir_reg == '+' -# endif - || redir_reg == '"')) + else { + /* Can use both "@a" and "@a>". */ if (*arg == '>') arg++; - - /* make register empty */ - write_reg_contents(redir_reg, (char_u *)"", -1, FALSE); + /* Make register empty when not using @A-@Z and the + * command is valid. */ + if (*arg == NUL && !isupper(redir_reg)) + write_reg_contents(redir_reg, (char_u *)"", -1, FALSE); } } if (*arg != NUL) @@ -8710,7 +8765,8 @@ } else { - failed |= (put_view(fd, curwin, !using_vdir, flagp) == FAIL); + failed |= (put_view(fd, curwin, !using_vdir, flagp, + -1) == FAIL); } if (put_line(fd, "let &so = s:so_save | let &siso = s:siso_save") == FAIL) @@ -9368,7 +9424,7 @@ if (src > srcstart && src[-1] == '\\') { *usedlen = 0; - STRCPY(src - 1, src); /* remove backslash */ + mch_memmove(src - 1, src, STRLEN(src) + 1); /* remove backslash */ return NULL; } @@ -9468,6 +9524,7 @@ *errormsg = (char_u *)_("E495: no autocommand file name to substitute for \"\""); return NULL; } + result = shorten_fname1(result); break; case SPEC_ABUF: /* buffer number for autocommand */ @@ -9709,6 +9766,8 @@ int tabnr; win_T *tab_firstwin; frame_T *tab_topframe; + int cur_arg_idx = 0; + int next_arg_idx = 0; if (ssop_flags & SSOP_BUFFERS) only_save_windows = FALSE; /* Save ALL buffers */ @@ -9924,12 +9983,19 @@ { if (!ses_do_win(wp)) continue; - if (put_view(fd, wp, wp != edited_win, &ssop_flags) == FAIL) + if (put_view(fd, wp, wp != edited_win, &ssop_flags, + cur_arg_idx) == FAIL) return FAIL; if (nr > 1 && put_line(fd, "wincmd w") == FAIL) return FAIL; + next_arg_idx = wp->w_arg_idx; } + /* The argument index in the first tab page is zero, need to set it in + * each window. For further tab pages it's the window where we do + * "tabedit". */ + cur_arg_idx = next_arg_idx; + /* * Restore cursor to the current window if it's not the first one. */ @@ -10138,11 +10204,13 @@ * Caller must make sure 'scrolloff' is zero. */ static int -put_view(fd, wp, add_edit, flagp) +put_view(fd, wp, add_edit, flagp, current_arg_idx) FILE *fd; win_T *wp; int add_edit; /* add ":edit" command to view */ unsigned *flagp; /* vop_flags or ssop_flags */ + int current_arg_idx; /* current argument index of the window, use + * -1 if unknown */ { win_T *save_curwin; int f; @@ -10172,10 +10240,10 @@ /* Only when part of a session: restore the argument index. Some * arguments may have been deleted, check if the index is valid. */ - if (wp->w_arg_idx != 0 && wp->w_arg_idx <= WARGCOUNT(wp) + if (wp->w_arg_idx != current_arg_idx && wp->w_arg_idx <= WARGCOUNT(wp) && flagp == &ssop_flags) { - if (fprintf(fd, "%ldnext", (long)wp->w_arg_idx) < 0 + if (fprintf(fd, "%ldargu", (long)wp->w_arg_idx + 1) < 0 || put_eol(fd) == FAIL) return FAIL; did_next = TRUE; @@ -10816,12 +10884,13 @@ exarg_T *eap; { char_u *p; + char_u *g = NULL; char_u *end; int c; - int mi; + int id; if (eap->line2 <= 3) - mi = eap->line2 - 1; + id = eap->line2; else { EMSG(e_invcmd); @@ -10830,13 +10899,7 @@ /* First clear any old pattern. */ if (!eap->skip) - { - vim_free(curwin->w_match[mi].regprog); - curwin->w_match[mi].regprog = NULL; - vim_free(curwin->w_match_pat[mi]); - curwin->w_match_pat[mi] = NULL; - redraw_later(SOME_VALID); /* always need a redraw */ - } + match_delete(curwin, id, FALSE); if (ends_excmd(*eap->arg)) end = eap->arg; @@ -10847,15 +10910,7 @@ { p = skiptowhite(eap->arg); if (!eap->skip) - { - curwin->w_match_id[mi] = syn_namen2id(eap->arg, - (int)(p - eap->arg)); - if (curwin->w_match_id[mi] == 0) - { - EMSG2(_(e_nogroup), eap->arg); - return; - } - } + g = vim_strnsave(eap->arg, (int)(p - eap->arg)); p = skipwhite(p); if (*p == NUL) { @@ -10879,14 +10934,8 @@ c = *end; *end = NUL; - curwin->w_match[mi].regprog = vim_regcomp(p + 1, RE_MAGIC); - if (curwin->w_match[mi].regprog == NULL) - { - EMSG2(_(e_invarg2), p); - *end = c; - return; - } - curwin->w_match_pat[mi] = vim_strsave(p + 1); + match_add(curwin, g, p + 1, 10, id); + vim_free(g); *end = c; } } diff -Naur vim71.orig/src/ex_eval.c vim71/src/ex_eval.c --- vim71.orig/src/ex_eval.c 2007-05-07 15:47:50.000000000 -0400 +++ vim71/src/ex_eval.c 2008-06-18 06:53:54.000000000 -0400 @@ -1551,7 +1551,7 @@ } save_cpo = p_cpo; p_cpo = (char_u *)""; - regmatch.regprog = vim_regcomp(pat, TRUE); + regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING); regmatch.rm_ic = FALSE; if (end != NULL) *end = save_char; @@ -2269,9 +2269,18 @@ has_loop_cmd(p) char_u *p; { - p = skipwhite(p); - while (*p == ':') - p = skipwhite(p + 1); + int len; + + /* skip modifiers, white space and ':' */ + for (;;) + { + while (*p == ' ' || *p == '\t' || *p == ':') + ++p; + len = modifier_len(p); + if (len == 0) + break; + p += len; + } if ((p[0] == 'w' && p[1] == 'h') || (p[0] == 'f' && p[1] == 'o' && p[2] == 'r')) return TRUE; diff -Naur vim71.orig/src/ex_getln.c vim71/src/ex_getln.c --- vim71.orig/src/ex_getln.c 2007-05-07 15:47:23.000000000 -0400 +++ vim71/src/ex_getln.c 2008-06-18 06:56:47.000000000 -0400 @@ -268,7 +268,9 @@ { xpc.xp_context = ccline.xp_context; xpc.xp_pattern = ccline.cmdbuff; +# if defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL) xpc.xp_arg = ccline.xp_arg; +# endif } #endif @@ -333,7 +335,14 @@ quit_more = FALSE; /* reset after CTRL-D which had a more-prompt */ cursorcmd(); /* set the cursor on the right spot */ - c = safe_vgetc(); + + /* Get a character. Ignore K_IGNORE, it should not do anything, such + * as stop completion. */ + do + { + c = safe_vgetc(); + } while (c == K_IGNORE); + if (KeyTyped) { some_key_typed = TRUE; @@ -484,7 +493,8 @@ if (xpc.xp_context == EXPAND_MENUNAMES && p_wmnu) { /* Hitting after "emenu Name.": complete submenu */ - if (ccline.cmdbuff[ccline.cmdpos - 1] == '.' && c == K_DOWN) + if (c == K_DOWN && ccline.cmdpos > 0 + && ccline.cmdbuff[ccline.cmdpos - 1] == '.') c = p_wc; else if (c == K_UP) { @@ -533,9 +543,11 @@ upseg[3] = PATHSEP; upseg[4] = NUL; - if (ccline.cmdbuff[ccline.cmdpos - 1] == PATHSEP - && c == K_DOWN - && (ccline.cmdbuff[ccline.cmdpos - 2] != '.' + if (c == K_DOWN + && ccline.cmdpos > 0 + && ccline.cmdbuff[ccline.cmdpos - 1] == PATHSEP + && (ccline.cmdpos < 3 + || ccline.cmdbuff[ccline.cmdpos - 2] != '.' || ccline.cmdbuff[ccline.cmdpos - 3] != '.')) { /* go down a directory */ @@ -636,7 +648,7 @@ { ++no_mapping; ++allow_keys; - c = safe_vgetc(); + c = plain_vgetc(); --no_mapping; --allow_keys; /* CTRL-\ e doesn't work when obtaining an expression. */ @@ -730,8 +742,8 @@ /* In Ex mode a backslash escapes a newline. */ if (exmode_active && c != ESC - && ccline.cmdpos > 0 && ccline.cmdpos == ccline.cmdlen + && ccline.cmdpos > 0 && ccline.cmdbuff[ccline.cmdpos - 1] == '\\') { if (c == K_KENTER) @@ -1086,11 +1098,11 @@ #endif putcmdline('"', TRUE); ++no_mapping; - i = c = safe_vgetc(); /* CTRL-R */ + i = c = plain_vgetc(); /* CTRL-R */ if (i == Ctrl_O) i = Ctrl_R; /* CTRL-R CTRL-O == CTRL-R CTRL-R */ if (i == Ctrl_R) - c = safe_vgetc(); /* CTRL-R CTRL-R */ + c = plain_vgetc(); /* CTRL-R CTRL-R */ --no_mapping; #ifdef FEAT_EVAL /* @@ -1181,10 +1193,10 @@ case K_LEFT: case K_S_LEFT: case K_C_LEFT: + if (ccline.cmdpos == 0) + goto cmdline_not_changed; do { - if (ccline.cmdpos == 0) - break; --ccline.cmdpos; #ifdef FEAT_MBYTE if (has_mbyte) /* move to first byte of char */ @@ -1193,7 +1205,8 @@ #endif ccline.cmdspos -= cmdline_charsize(ccline.cmdpos); } - while ((c == K_S_LEFT || c == K_C_LEFT + while (ccline.cmdpos > 0 + && (c == K_S_LEFT || c == K_C_LEFT || (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL))) && ccline.cmdbuff[ccline.cmdpos - 1] != ' '); #ifdef FEAT_MBYTE @@ -1203,7 +1216,8 @@ goto cmdline_not_changed; case K_IGNORE: - goto cmdline_not_changed; /* Ignore mouse */ + /* Ignore mouse event or ex_window() result. */ + goto cmdline_not_changed; #ifdef FEAT_GUI_W32 /* On Win32 ignore , we get it when closing the window was @@ -1695,6 +1709,9 @@ if (p_is && !cmd_silent && (firstc == '/' || firstc == '?')) { pos_T end_pos; +#ifdef FEAT_RELTIME + proftime_T tm; +#endif /* if there is a character waiting, search and redraw later */ if (char_avail()) @@ -1713,8 +1730,18 @@ cursor_off(); /* so the user knows we're busy */ out_flush(); ++emsg_off; /* So it doesn't beep if bad expr */ +#ifdef FEAT_RELTIME + /* Set the time limit to half a second. */ + profile_setlimit(500L, &tm); +#endif i = do_search(NULL, firstc, ccline.cmdbuff, count, - SEARCH_KEEP + SEARCH_OPT + SEARCH_NOOF + SEARCH_PEEK); + SEARCH_KEEP + SEARCH_OPT + SEARCH_NOOF + SEARCH_PEEK, +#ifdef FEAT_RELTIME + &tm +#else + NULL +#endif + ); --emsg_off; /* if interrupted while searching, behave like it failed */ if (got_int) @@ -2090,11 +2117,11 @@ garray_T line_ga; char_u *pend; int startcol = 0; - int c1; + int c1 = 0; int escaped = FALSE; /* CTRL-V typed */ int vcol = 0; char_u *p; - int prev_char = 0; + int prev_char; /* Switch cursor on now. This avoids that it happens after the "\n", which * confuses the system function that computes tabstops. */ @@ -2147,6 +2174,7 @@ /* Get one character at a time. Don't use inchar(), it can't handle * special characters. */ + prev_char = c1; c1 = vgetc(); /* @@ -2204,7 +2232,6 @@ redraw: /* redraw the line */ msg_col = startcol; - windgoto(msg_row, msg_col); vcol = 0; for (p = (char_u *)line_ga.ga_data; p < (char_u *)line_ga.ga_data + line_ga.ga_len; ++p) @@ -2223,6 +2250,7 @@ } } msg_clr_eos(); + windgoto(msg_row, msg_col); continue; } @@ -2268,7 +2296,6 @@ if (IS_SPECIAL(c1)) c1 = '?'; ((char_u *)line_ga.ga_data)[line_ga.ga_len] = c1; - prev_char = c1; if (c1 == '\n') msg_putchar('\n'); else if (c1 == TAB) @@ -3311,6 +3338,10 @@ * Return a pointer to alloced memory containing the new string. * Return NULL for failure. * + * "orig" is the originally expanded string, copied to allocated memory. It + * should either be kept in orig_save or freed. When "mode" is WILD_NEXT or + * WILD_PREV "orig" should be NULL. + * * Results are cached in xp->xp_files and xp->xp_numfiles, except when "mode" * is WILD_EXPAND_FREE or WILD_ALL. * @@ -3344,6 +3375,7 @@ char_u *ss = NULL; static int findex; static char_u *orig_save = NULL; /* kept value of orig */ + int orig_saved = FALSE; int i; long_u len; int non_suf_match; /* number without matching suffix */ @@ -3395,7 +3427,7 @@ return NULL; } -/* free old names */ + /* free old names */ if (xp->xp_numfiles != -1 && mode != WILD_ALL && mode != WILD_LONGEST) { FreeWild(xp->xp_numfiles, xp->xp_files); @@ -3412,6 +3444,7 @@ { vim_free(orig_save); orig_save = orig; + orig_saved = TRUE; /* * Do the expansion. @@ -3536,6 +3569,10 @@ if (mode == WILD_EXPAND_FREE || mode == WILD_ALL) ExpandCleanup(xp); + /* Free "orig" if it wasn't stored in "orig_save". */ + if (!orig_saved) + vim_free(orig); + return ss; } @@ -3620,20 +3657,9 @@ } } #ifdef BACKSLASH_IN_FILENAME - { - char_u buf[20]; - int j = 0; - - /* Don't escape '[' and '{' if they are in 'isfname'. */ - for (p = PATH_ESC_CHARS; *p != NUL; ++p) - if ((*p != '[' && *p != '{') || !vim_isfilec(*p)) - buf[j++] = *p; - buf[j] = NUL; - p = vim_strsave_escaped(files[i], buf); - } + p = vim_strsave_fnameescape(files[i], FALSE); #else - p = vim_strsave_escaped(files[i], - xp->xp_shell ? SHELL_ESC_CHARS : PATH_ESC_CHARS); + p = vim_strsave_fnameescape(files[i], xp->xp_shell); #endif if (p != NULL) { @@ -3673,6 +3699,32 @@ } /* + * Escape special characters in "fname" for when used as a file name argument + * after a Vim command, or, when "shell" is non-zero, a shell command. + * Returns the result in allocated memory. + */ + char_u * +vim_strsave_fnameescape(fname, shell) + char_u *fname; + int shell; +{ +#ifdef BACKSLASH_IN_FILENAME + char_u buf[20]; + int j = 0; + char_u *p; + + /* Don't escape '[' and '{' if they are in 'isfname'. */ + for (p = PATH_ESC_CHARS; *p != NUL; ++p) + if ((*p != '[' && *p != '{') || !vim_isfilec(*p)) + buf[j++] = *p; + buf[j] = NUL; + return vim_strsave_escaped(fname, buf); +#else + return vim_strsave_escaped(fname, shell ? SHELL_ESC_CHARS : PATH_ESC_CHARS); +#endif +} + +/* * Put a backslash before the file name in "pp", which is in allocated memory. */ static void @@ -4054,6 +4106,7 @@ * ~ would be at the start of the file name, but not the tail. * $ could be anywhere in the tail. * ` could be anywhere in the file name. + * When the name ends in '$' don't add a star, remove the '$'. */ tail = gettail(retval); if ((*retval != '~' || tail != retval) @@ -4061,6 +4114,8 @@ && vim_strchr(tail, '$') == NULL && vim_strchr(retval, '`') == NULL) retval[len++] = '*'; + else if (len > 0 && retval[len - 1] == '$') + --len; retval[len] = NUL; } } @@ -4148,13 +4203,19 @@ #ifdef FEAT_EVAL if (ccline.cmdfirstc == '=') + { +# ifdef FEAT_CMDL_COMPL /* pass CMD_SIZE because there is no real command */ set_context_for_expression(xp, str, CMD_SIZE); +# endif + } else if (ccline.input_fn) { xp->xp_context = ccline.xp_context; xp->xp_pattern = ccline.cmdbuff; +# if defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL) xp->xp_arg = ccline.xp_arg; +# endif } else #endif @@ -4295,10 +4356,11 @@ && pat[i + 1] == '\\' && pat[i + 2] == '\\' && pat[i + 3] == ' ') - STRCPY(pat + i, pat + i + 3); + mch_memmove(pat + i, pat + i + 3, + STRLEN(pat + i + 3) + 1); if (xp->xp_backslash == XP_BS_ONE && pat[i + 1] == ' ') - STRCPY(pat + i, pat + i + 1); + mch_memmove(pat + i, pat + i + 1, STRLEN(pat + i)); } } @@ -4502,6 +4564,12 @@ if (xp->xp_context != EXPAND_MENUNAMES && xp->xp_context != EXPAND_MENUS) sort_strings(*file, *num_file); +#ifdef FEAT_CMDL_COMPL + /* Reset the variables used for special highlight names expansion, so that + * they don't show up when getting normal highlight names by ID. */ + reset_expand_highlight(); +#endif + return OK; } @@ -4535,7 +4603,7 @@ pat = vim_strsave(filepat); for (i = 0; pat[i]; ++i) if (pat[i] == '\\' && pat[i + 1] == ' ') - STRCPY(pat + i, pat + i + 1); + mch_memmove(pat + i, pat + i + 1, STRLEN(pat + i)); flags |= EW_FILE | EW_EXEC; @@ -4615,7 +4683,7 @@ static void * call_user_expand_func __ARGS((void *(*user_expand_func) __ARGS((char_u *, int, char_u **, int)), expand_T *xp, int *num_file, char_u ***file)); /* - * call "user_expand_func()" to invoke a user defined VimL function and return + * Call "user_expand_func()" to invoke a user defined VimL function and return * the result (either a string or a List). */ static void * @@ -4637,11 +4705,22 @@ *num_file = 0; *file = NULL; - keep = ccline.cmdbuff[ccline.cmdlen]; - ccline.cmdbuff[ccline.cmdlen] = 0; - sprintf((char *)num, "%d", ccline.cmdpos); + if (ccline.cmdbuff == NULL) + { + /* Completion from Insert mode, pass fake arguments. */ + keep = 0; + sprintf((char *)num, "%d", (int)STRLEN(xp->xp_pattern)); + args[1] = xp->xp_pattern; + } + else + { + /* Completion on the command line, pass real arguments. */ + keep = ccline.cmdbuff[ccline.cmdlen]; + ccline.cmdbuff[ccline.cmdlen] = 0; + sprintf((char *)num, "%d", ccline.cmdpos); + args[1] = ccline.cmdbuff; + } args[0] = xp->xp_pattern; - args[1] = ccline.cmdbuff; args[2] = num; /* Save the cmdline, we don't know what the function may do. */ @@ -4654,8 +4733,8 @@ ccline = save_ccline; current_SID = save_current_SID; - - ccline.cmdbuff[ccline.cmdlen] = keep; + if (ccline.cmdbuff != NULL) + ccline.cmdbuff[ccline.cmdlen] = keep; return ret; } @@ -5907,7 +5986,7 @@ # ifdef FEAT_AUTOCMD /* Don't execute autocommands while creating the window. */ - ++autocmd_block; + block_autocmds(); # endif /* don't use a new tab page */ cmdmod.tab = 0; @@ -5916,6 +5995,9 @@ if (win_split((int)p_cwh, WSP_BOT) == FAIL) { beep_flush(); +# ifdef FEAT_AUTOCMD + unblock_autocmds(); +# endif return K_IGNORE; } cmdwin_type = ccline.cmdfirstc; @@ -5938,7 +6020,7 @@ # ifdef FEAT_AUTOCMD /* Do execute autocommands for setting the filetype (load syntax). */ - --autocmd_block; + unblock_autocmds(); # endif /* Showing the prompt may have set need_wait_return, reset it. */ @@ -6092,7 +6174,7 @@ # ifdef FEAT_AUTOCMD /* Don't execute autocommands while deleting the window. */ - ++autocmd_block; + block_autocmds(); # endif wp = curwin; bp = curbuf; @@ -6104,7 +6186,7 @@ win_size_restore(&winsizes); # ifdef FEAT_AUTOCMD - --autocmd_block; + unblock_autocmds(); # endif } diff -Naur vim71.orig/src/feature.h vim71/src/feature.h --- vim71.orig/src/feature.h 2007-05-07 15:33:19.000000000 -0400 +++ vim71/src/feature.h 2008-06-18 06:51:34.000000000 -0400 @@ -673,7 +673,7 @@ # define ESC_CHG_TO_ENG_MODE /* if defined, when ESC pressed, * turn to english mode */ -# if !defined(FEAT_XFONTSET) && defined(HAVE_X11) +# if !defined(FEAT_XFONTSET) && defined(HAVE_X11) && !defined(HAVE_GTK2) # define FEAT_XFONTSET /* Hangul input requires xfontset */ # endif # if defined(FEAT_XIM) && !defined(LINT) diff -Naur vim71.orig/src/fileio.c vim71/src/fileio.c --- vim71.orig/src/fileio.c 2007-05-10 07:29:44.000000000 -0400 +++ vim71/src/fileio.c 2008-06-18 06:56:56.000000000 -0400 @@ -44,6 +44,10 @@ /* Is there any system that doesn't have access()? */ #define USE_MCH_ACCESS +#if defined(sun) && defined(S_ISCHR) +# define OPEN_CHR_FILES +static int is_dev_fd_file(char_u *fname); +#endif #ifdef FEAT_MBYTE static char_u *next_fenc __ARGS((char_u **pp)); # ifdef FEAT_EVAL @@ -217,11 +221,12 @@ { int fd = 0; int newfile = (flags & READ_NEW); - int set_options = newfile || (eap != NULL && eap->read_edit); int check_readonly; int filtering = (flags & READ_FILTER); int read_stdin = (flags & READ_STDIN); int read_buffer = (flags & READ_BUFFER); + int set_options = newfile || read_buffer + || (eap != NULL && eap->read_edit); linenr_T read_buf_lnum = 1; /* next line to read from curbuf */ colnr_T read_buf_col = 0; /* next char to read from this line */ char_u c; @@ -406,6 +411,10 @@ # ifdef S_ISSOCK && !S_ISSOCK(perm) /* ... or socket */ # endif +# ifdef OPEN_CHR_FILES + && !(S_ISCHR(perm) && is_dev_fd_file(fname)) + /* ... or a character special file named /dev/fd/ */ +# endif ) { if (S_ISDIR(perm)) @@ -424,7 +433,7 @@ */ if (!p_odev && mch_nodetype(fname) == NODE_WRITABLE) { - filemess(curbuf, fname, (char_u *)_("is a device (disabled with 'opendevice' option"), 0); + filemess(curbuf, fname, (char_u *)_("is a device (disabled with 'opendevice' option)"), 0); msg_end(); msg_scroll = msg_save; return FAIL; @@ -642,10 +651,16 @@ if (set_options) { - curbuf->b_p_eol = TRUE; - curbuf->b_start_eol = TRUE; + /* Don't change 'eol' if reading from buffer as it will already be + * correctly set when reading stdin. */ + if (!read_buffer) + { + curbuf->b_p_eol = TRUE; + curbuf->b_start_eol = TRUE; + } #ifdef FEAT_MBYTE curbuf->b_p_bomb = FALSE; + curbuf->b_start_bomb = FALSE; #endif } @@ -904,7 +919,10 @@ file_rewind = FALSE; #ifdef FEAT_MBYTE if (set_options) + { curbuf->b_p_bomb = FALSE; + curbuf->b_start_bomb = FALSE; + } conv_error = 0; #endif } @@ -1270,12 +1288,49 @@ #ifdef FEAT_MBYTE else if (conv_restlen > 0) { - /* Reached end-of-file but some trailing bytes could - * not be converted. Truncated file? */ - if (conv_error == 0) - conv_error = linecnt; - if (bad_char_behavior != BAD_DROP) + /* + * Reached end-of-file but some trailing bytes could + * not be converted. Truncated file? + */ + + /* When we did a conversion report an error. */ + if (fio_flags != 0 +# ifdef USE_ICONV + || iconv_fd != (iconv_t)-1 +# endif + ) { + if (conv_error == 0) + conv_error = curbuf->b_ml.ml_line_count + - linecnt + 1; + } + /* Remember the first linenr with an illegal byte */ + else if (illegal_byte == 0) + illegal_byte = curbuf->b_ml.ml_line_count + - linecnt + 1; + if (bad_char_behavior == BAD_DROP) + { + *(ptr - conv_restlen) = NUL; + conv_restlen = 0; + } + else + { + /* Replace the trailing bytes with the replacement + * character if we were converting; if we weren't, + * leave the UTF8 checking code to do it, as it + * works slightly differently. */ + if (bad_char_behavior != BAD_KEEP && (fio_flags != 0 +# ifdef USE_ICONV + || iconv_fd != (iconv_t)-1 +# endif + )) + { + while (conv_restlen > 0) + { + *(--ptr) = bad_char_behavior; + --conv_restlen; + } + } fio_flags = 0; /* don't convert this */ # ifdef USE_ICONV if (iconv_fd != (iconv_t)-1) @@ -1284,20 +1339,6 @@ iconv_fd = (iconv_t)-1; } # endif - if (bad_char_behavior == BAD_KEEP) - { - /* Keep the trailing bytes as-is. */ - size = conv_restlen; - ptr -= conv_restlen; - } - else - { - /* Replace the trailing bytes with the - * replacement character. */ - size = 1; - *--ptr = bad_char_behavior; - } - conv_restlen = 0; } } #endif @@ -1353,7 +1394,10 @@ size -= blen; mch_memmove(ptr, ptr + blen, (size_t)size); if (set_options) + { curbuf->b_p_bomb = TRUE; + curbuf->b_start_bomb = TRUE; + } } if (fio_flags == FIO_UCSBOM) @@ -1376,6 +1420,11 @@ goto retry; } } + + /* Include not converted bytes. */ + ptr -= conv_restlen; + size += conv_restlen; + conv_restlen = 0; #endif /* * Break here for a read error or end-of-file. @@ -1385,11 +1434,6 @@ #ifdef FEAT_MBYTE - /* Include not converted bytes. */ - ptr -= conv_restlen; - size += conv_restlen; - conv_restlen = 0; - # ifdef USE_ICONV if (iconv_fd != (iconv_t)-1) { @@ -1851,12 +1895,12 @@ size = (long)((ptr + real_size) - dest); ptr = dest; } - else if (enc_utf8 && conv_error == 0 && !curbuf->b_p_bin) + else if (enc_utf8 && !curbuf->b_p_bin) { - /* Reading UTF-8: Check if the bytes are valid UTF-8. - * Need to start before "ptr" when part of the character was - * read in the previous read() call. */ - for (p = ptr - utf_head_off(buffer, ptr); ; ++p) + int incomplete_tail = FALSE; + + /* Reading UTF-8: Check if the bytes are valid UTF-8. */ + for (p = ptr; ; ++p) { int todo = (int)((ptr + size) - p); int l; @@ -1870,43 +1914,56 @@ * read() will get the next bytes, we'll check it * then. */ l = utf_ptr2len_len(p, todo); - if (l > todo) + if (l > todo && !incomplete_tail) { - /* Incomplete byte sequence, the next read() - * should get them and check the bytes. */ - p += todo; - break; + /* Avoid retrying with a different encoding when + * a truncated file is more likely, or attempting + * to read the rest of an incomplete sequence when + * we have already done so. */ + if (p > ptr || filesize > 0) + incomplete_tail = TRUE; + /* Incomplete byte sequence, move it to conv_rest[] + * and try to read the rest of it, unless we've + * already done so. */ + if (p > ptr) + { + conv_restlen = todo; + mch_memmove(conv_rest, p, conv_restlen); + size -= conv_restlen; + break; + } } - if (l == 1) + if (l == 1 || l > todo) { /* Illegal byte. If we can try another encoding - * do that. */ - if (can_retry) + * do that, unless at EOF where a truncated + * file is more likely than a conversion error. */ + if (can_retry && !incomplete_tail) break; - - /* Remember the first linenr with an illegal byte */ - if (illegal_byte == 0) - illegal_byte = readfile_linenr(linecnt, ptr, p); # ifdef USE_ICONV /* When we did a conversion report an error. */ if (iconv_fd != (iconv_t)-1 && conv_error == 0) conv_error = readfile_linenr(linecnt, ptr, p); # endif + /* Remember the first linenr with an illegal byte */ + if (conv_error == 0 && illegal_byte == 0) + illegal_byte = readfile_linenr(linecnt, ptr, p); /* Drop, keep or replace the bad byte. */ if (bad_char_behavior == BAD_DROP) { - mch_memmove(p, p+1, todo - 1); + mch_memmove(p, p + 1, todo - 1); --p; --size; } else if (bad_char_behavior != BAD_KEEP) *p = bad_char_behavior; } - p += l - 1; + else + p += l - 1; } } - if (p < ptr + size) + if (p < ptr + size && !incomplete_tail) { /* Detected a UTF-8 error. */ rewind_retry: @@ -2265,6 +2322,13 @@ } # endif # endif +# ifdef OPEN_CHR_FILES + if (S_ISCHR(perm)) /* or character special */ + { + STRCAT(IObuff, _("[character special]")); + c = TRUE; + } +# endif #endif if (curbuf->b_p_ro) { @@ -2464,6 +2528,25 @@ return OK; } +#ifdef OPEN_CHR_FILES +/* + * Returns TRUE if the file name argument is of the form "/dev/fd/\d\+", + * which is the name of files used for process substitution output by + * some shells on some operating systems, e.g., bash on SunOS. + * Do not accept "/dev/fd/[012]", opening these may hang Vim. + */ + static int +is_dev_fd_file(fname) + char_u *fname; +{ + return (STRNCMP(fname, "/dev/fd/", 8) == 0 + && VIM_ISDIGIT(fname[8]) + && *skipdigits(fname + 9) == NUL + && (fname[9] != NUL + || (fname[8] != '0' && fname[8] != '1' && fname[8] != '2'))); +} +#endif + #ifdef FEAT_MBYTE /* @@ -2734,6 +2817,32 @@ #endif /* + * Return TRUE if a file appears to be read-only from the file permissions. + */ + int +check_file_readonly(fname, perm) + char_u *fname; /* full path to file */ + int perm; /* known permissions on file */ +{ +#ifndef USE_MCH_ACCESS + int fd = 0; +#endif + + return ( +#ifdef USE_MCH_ACCESS +# ifdef UNIX + (perm & 0222) == 0 || +# endif + mch_access((char *)fname, W_OK) +#else + (fd = mch_open((char *)fname, O_RDWR | O_EXTRA, 0)) < 0 + ? TRUE : (close(fd), FALSE) +#endif + ); +} + + +/* * buf_write() - write to file "fname" lines "start" through "end" * * We do our own buffering here because fwrite() is so slow. @@ -3142,7 +3251,8 @@ * Get information about original file (if there is one). */ #if defined(UNIX) && !defined(ARCHIE) - st_old.st_dev = st_old.st_ino = 0; + st_old.st_dev = 0; + st_old.st_ino = 0; perm = -1; if (mch_stat((char *)fname, &st_old) < 0) newfile = TRUE; @@ -3219,17 +3329,8 @@ * Check if the file is really writable (when renaming the file to * make a backup we won't discover it later). */ - file_readonly = ( -# ifdef USE_MCH_ACCESS -# ifdef UNIX - (perm & 0222) == 0 || -# endif - mch_access((char *)fname, W_OK) -# else - (fd = mch_open((char *)fname, O_RDWR | O_EXTRA, 0)) < 0 - ? TRUE : (close(fd), FALSE) -# endif - ); + file_readonly = check_file_readonly(fname, (int)perm); + if (!forceit && file_readonly) { if (vim_strchr(p_cpo, CPO_FWRITE) != NULL) @@ -3586,6 +3687,9 @@ ) mch_setperm(backup, (perm & 0707) | ((perm & 07) << 3)); +# ifdef HAVE_SELINUX + mch_copy_sec(fname, backup); +# endif #endif /* @@ -3622,6 +3726,9 @@ #ifdef HAVE_ACL mch_set_acl(backup, acl); #endif +#ifdef HAVE_SELINUX + mch_copy_sec(fname, backup); +#endif break; } } @@ -4243,6 +4350,12 @@ } #endif +#ifdef HAVE_SELINUX + /* Probably need to set the security context. */ + if (!backup_copy) + mch_copy_sec(backup, wfname); +#endif + #ifdef UNIX /* When creating a new file, set its owner/group to that of the original * file. Get the new device and inode number. */ @@ -5448,10 +5561,11 @@ else if (p[0] == 0xfe && p[1] == 0xff && (flags == FIO_ALL || flags == FIO_UCS2 || flags == FIO_UTF16)) { - if (flags == FIO_UTF16) - name = "utf-16"; /* FE FF */ - else + /* Default to utf-16, it works also for ucs-2 text. */ + if (flags == FIO_UCS2) name = "ucs-2"; /* FE FF */ + else + name = "utf-16"; /* FE FF */ } else if (size >= 4 && p[0] == 0 && p[1] == 0 && p[2] == 0xfe && p[3] == 0xff && (flags == FIO_ALL || flags == FIO_UCS4)) @@ -5495,6 +5609,8 @@ } #endif +#if defined(FEAT_VIMINFO) || defined(FEAT_BROWSE) || \ + defined(FEAT_QUICKFIX) || defined(FEAT_AUTOCMD) || defined(PROTO) /* * Try to find a shortname by comparing the fullname with the current * directory. @@ -5548,6 +5664,7 @@ p = NULL; return p; } +#endif /* * Shorten filenames for all buffers. @@ -7107,6 +7224,7 @@ static event_T last_event; static int last_group; +static int autocmd_blocked = 0; /* block all autocmds */ /* * Show the autocommands for one AutoPat. @@ -8396,7 +8514,7 @@ * Quickly return if there are no autocommands for this event or * autocommands are blocked. */ - if (first_autopat[(int)event] == NULL || autocmd_block > 0) + if (first_autopat[(int)event] == NULL || autocmd_blocked > 0) goto BYPASS_AU; /* @@ -8461,6 +8579,8 @@ /* * Set the file name to be used for . + * Make a copy to avoid that changing a buffer name or directory makes it + * invalid. */ if (fname_io == NULL) { @@ -8473,6 +8593,8 @@ } else autocmd_fname = fname_io; + if (autocmd_fname != NULL) + autocmd_fname = FullName_save(autocmd_fname, FALSE); /* * Set the buffer number to be used for . @@ -8655,6 +8777,7 @@ vim_free(sourcing_name); sourcing_name = save_sourcing_name; sourcing_lnum = save_sourcing_lnum; + vim_free(autocmd_fname); autocmd_fname = save_autocmd_fname; autocmd_bufnr = save_autocmd_bufnr; autocmd_match = save_autocmd_match; @@ -8710,6 +8833,40 @@ return retval; } +# ifdef FEAT_EVAL +static char_u *old_termresponse = NULL; +# endif + +/* + * Block triggering autocommands until unblock_autocmd() is called. + * Can be used recursively, so long as it's symmetric. + */ + void +block_autocmds() +{ +# ifdef FEAT_EVAL + /* Remember the value of v:termresponse. */ + if (autocmd_blocked == 0) + old_termresponse = get_vim_var_str(VV_TERMRESPONSE); +# endif + ++autocmd_blocked; +} + + void +unblock_autocmds() +{ + --autocmd_blocked; + +# ifdef FEAT_EVAL + /* When v:termresponse was set while autocommands were blocked, trigger + * the autocommands now. Esp. useful when executing a shell command + * during startup (vimdiff). */ + if (autocmd_blocked == 0 + && get_vim_var_str(VV_TERMRESPONSE) != old_termresponse) + apply_autocmds(EVENT_TERMRESPONSE, NULL, NULL, FALSE, curbuf); +# endif +} + /* * Find next autocommand pattern that matches. */ @@ -9108,7 +9265,7 @@ aco_save_T *aco; /* structure to save values in */ buf_T *buf; /* new curbuf */ { - aco->save_buf = buf; + aco->save_buf = curbuf; curbuf = buf; curwin->w_buffer = buf; } diff -Naur vim71.orig/src/fold.c vim71/src/fold.c --- vim71.orig/src/fold.c 2007-05-07 15:46:32.000000000 -0400 +++ vim71/src/fold.c 2008-06-18 06:56:03.000000000 -0400 @@ -858,7 +858,14 @@ || foldmethodIsDiff(wp) #endif || foldmethodIsSyntax(wp)) + { + int save_got_int = got_int; + + /* reset got_int here, otherwise it won't work */ + got_int = FALSE; foldUpdateIEMS(wp, top, bot); + got_int |= save_got_int; + } } /* foldUpdateAll() {{{2 */ @@ -2300,7 +2307,7 @@ /* If some fold changed, need to redraw and position cursor. */ if (fold_changed && wp->w_p_fen) - changed_window_setting(); + changed_window_setting_win(wp); /* If we updated folds past "bot", need to redraw more lines. Don't do * this in other situations, the changed lines will be redrawn anyway and @@ -2669,6 +2676,7 @@ if (fp->fd_len < flp->lnum - fp->fd_top) { fp->fd_len = flp->lnum - fp->fd_top; + fp->fd_small = MAYBE; fold_changed = TRUE; } diff -Naur vim71.orig/src/getchar.c vim71/src/getchar.c --- vim71.orig/src/getchar.c 2007-05-07 15:18:20.000000000 -0400 +++ vim71/src/getchar.c 2008-06-18 06:54:12.000000000 -0400 @@ -253,8 +253,9 @@ return; } else if (buf->bh_index != 0) - STRCPY(buf->bh_first.b_next->b_str, - buf->bh_first.b_next->b_str + buf->bh_index); + mch_memmove(buf->bh_first.b_next->b_str, + buf->bh_first.b_next->b_str + buf->bh_index, + STRLEN(buf->bh_first.b_next->b_str + buf->bh_index) + 1); buf->bh_index = 0; if (buf->bh_space >= (int)slen) @@ -1278,8 +1279,14 @@ void free_typebuf() { - vim_free(typebuf.tb_buf); - vim_free(typebuf.tb_noremap); + if (typebuf.tb_buf == typebuf_init) + EMSG2(_(e_intern2), "Free typebuf 1"); + else + vim_free(typebuf.tb_buf); + if (typebuf.tb_buf == noremapbuf_init) + EMSG2(_(e_intern2), "Free typebuf 2"); + else + vim_free(typebuf.tb_noremap); } /* @@ -1358,6 +1365,11 @@ EMSG(_(e_nesting)); return; } +#ifdef FEAT_EVAL + if (ignore_script) + /* Not reading from script, also don't open one. Warning message? */ + return; +#endif if (scriptin[curscript] != NULL) /* already reading script */ ++curscript; @@ -1596,8 +1608,16 @@ continue; } #endif - #ifdef FEAT_GUI + /* Handle focus event here, so that the caller doesn't need to + * know about it. Return K_IGNORE so that we loop once (needed if + * 'lazyredraw' is set). */ + if (c == K_FOCUSGAINED || c == K_FOCUSLOST) + { + ui_focus_change(c == K_FOCUSGAINED); + c = K_IGNORE; + } + /* Translate K_CSI to CSI. The special key is only used to avoid * it being recognized as the start of a special key. */ if (c == K_CSI) @@ -1741,6 +1761,22 @@ } /* + * Like safe_vgetc(), but loop to handle K_IGNORE. + * Also ignore scrollbar events. + */ + int +plain_vgetc() +{ + int c; + + do + { + c = safe_vgetc(); + } while (c == K_IGNORE || c == K_VER_SCROLLBAR || c == K_HOR_SCROLLBAR); + return c; +} + +/* * Check if a character is available, such that vgetc() will not block. * If the next character is a special character or multi-byte, the returned * character is not valid!. @@ -2321,7 +2357,7 @@ current_menu->silent[idx]); } } -#endif /* FEAT_GUI */ +#endif /* FEAT_GUI && FEAT_MENU */ continue; /* try mapping again */ } @@ -2837,11 +2873,15 @@ undo_off = FALSE; /* restart undo now */ /* - * first try script file - * If interrupted: Stop reading script files. + * Get a character from a script file if there is one. + * If interrupted: Stop reading script files, close them all. */ script_char = -1; - while (scriptin[curscript] != NULL && script_char < 0) + while (scriptin[curscript] != NULL && script_char < 0 +#ifdef FEAT_EVAL + && !ignore_script +#endif + ) { if (got_int || (script_char = getc(scriptin[curscript])) < 0) { diff -Naur vim71.orig/src/globals.h vim71/src/globals.h --- vim71.orig/src/globals.h 2007-05-07 15:44:26.000000000 -0400 +++ vim71/src/globals.h 2008-06-18 06:54:12.000000000 -0400 @@ -301,13 +301,17 @@ #endif #ifdef FEAT_EVAL -/* Garbage collection can only take place when we are sure there are no Lists +/* + * Garbage collection can only take place when we are sure there are no Lists * or Dictionaries being used internally. This is flagged with * "may_garbage_collect" when we are at the toplevel. * "want_garbage_collect" is set by the garbagecollect() function, which means - * we do garbage collection before waiting for a char at the toplevel. */ + * we do garbage collection before waiting for a char at the toplevel. + * "garbage_collect_at_exit" indicates garbagecollect(1) was called. + */ EXTERN int may_garbage_collect INIT(= FALSE); EXTERN int want_garbage_collect INIT(= FALSE); +EXTERN int garbage_collect_at_exit INIT(= FALSE); /* ID of script being sourced or was sourced to define the current function. */ EXTERN scid_T current_SID INIT(= 0); @@ -362,7 +366,6 @@ EXTERN int autocmd_busy INIT(= FALSE); /* Is apply_autocmds() busy? */ EXTERN int autocmd_no_enter INIT(= FALSE); /* *Enter autocmds disabled */ EXTERN int autocmd_no_leave INIT(= FALSE); /* *Leave autocmds disabled */ -EXTERN int autocmd_block INIT(= 0); /* block all autocmds */ EXTERN int modified_was_set; /* did ":set modified" */ EXTERN int did_filetype INIT(= FALSE); /* FileType event found */ EXTERN int keep_filetype INIT(= FALSE); /* value for did_filetype when @@ -801,7 +804,7 @@ EXTERN int (*mb_char2bytes) __ARGS((int c, char_u *buf)) INIT(= latin_char2bytes); EXTERN int (*mb_ptr2cells) __ARGS((char_u *p)) INIT(= latin_ptr2cells); EXTERN int (*mb_char2cells) __ARGS((int c)) INIT(= latin_char2cells); -EXTERN int (*mb_off2cells) __ARGS((unsigned off)) INIT(= latin_off2cells); +EXTERN int (*mb_off2cells) __ARGS((unsigned off, unsigned max_off)) INIT(= latin_off2cells); EXTERN int (*mb_ptr2char) __ARGS((char_u *p)) INIT(= latin_ptr2char); EXTERN int (*mb_head_off) __ARGS((char_u *base, char_u *p)) INIT(= latin_head_off); @@ -951,6 +954,9 @@ EXTERN int ex_normal_busy INIT(= 0); /* recursiveness of ex_normal() */ EXTERN int ex_normal_lock INIT(= 0); /* forbid use of ex_normal() */ #endif +#ifdef FEAT_EVAL +EXTERN int ignore_script INIT(= FALSE); /* ignore script input */ +#endif EXTERN int stop_insert_mode; /* for ":stopinsert" and 'insertmode' */ EXTERN int KeyTyped; /* TRUE if user typed current char */ diff -Naur vim71.orig/src/gui.c vim71/src/gui.c --- vim71.orig/src/gui.c 2007-05-07 15:50:55.000000000 -0400 +++ vim71/src/gui.c 2008-06-18 06:56:40.000000000 -0400 @@ -1080,7 +1080,8 @@ cur_width = gui.char_width; } #ifdef FEAT_MBYTE - if (has_mbyte && (*mb_off2cells)(LineOffset[gui.row] + gui.col) > 1) + if (has_mbyte && (*mb_off2cells)(LineOffset[gui.row] + gui.col, + LineOffset[gui.row] + screen_Columns) > 1) { /* Double wide character. */ if (shape_table[idx].shape != SHAPE_VER) @@ -1159,7 +1160,7 @@ #endif # if defined(FEAT_GUI_TABLINE) && (defined(FEAT_GUI_MSWIN) \ - || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_MAC)) + || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_MAC)) if (gui_has_tabline()) text_area_y += gui.tabline_height; #endif @@ -1293,11 +1294,7 @@ out_flush(); gui.num_cols = (pixel_width - gui_get_base_width()) / gui.char_width; - gui.num_rows = (pixel_height - gui_get_base_height() -#if !defined(FEAT_GUI_PHOTON) && !defined(FEAT_GUI_MSWIN) - + (gui.char_height / 2) -#endif - ) / gui.char_height; + gui.num_rows = (pixel_height - gui_get_base_height()) / gui.char_height; gui_position_components(pixel_width); @@ -3733,8 +3730,10 @@ sb->value = value; #ifdef USE_ON_FLY_SCROLL - /* When not allowed to do the scrolling right now, return. */ - if (dont_scroll || input_available()) + /* When not allowed to do the scrolling right now, return. + * This also checked input_available(), but that causes the first click in + * a scrollbar to be ignored when Vim doesn't have focus. */ + if (dont_scroll) return; #endif #ifdef FEAT_INS_EXPAND @@ -4213,7 +4212,19 @@ #endif ) { - redraw_win_later(wp, VALID); + int type = VALID; + +#ifdef FEAT_INS_EXPAND + if (pum_visible()) + { + type = NOT_VALID; + wp->w_lines_valid = 0; + } +#endif + /* Don't set must_redraw here, it may cause the popup menu to + * disappear when losing focus after a scrollbar drag. */ + if (wp->w_redr_type < type) + wp->w_redr_type = type; updateWindow(wp); /* update window, status line, and cmdline */ } @@ -4518,7 +4529,18 @@ xim_set_focus(in_focus); # endif - ui_focus_change(in_focus); + /* Put events in the input queue only when allowed. + * ui_focus_change() isn't called directly, because it invokes + * autocommands and that must not happen asynchronously. */ + if (!hold_gui_events) + { + char_u bytes[3]; + + bytes[0] = CSI; + bytes[1] = KS_EXTRA; + bytes[2] = in_focus ? (int)KE_FOCUSGAINED : (int)KE_FOCUSLOST; + add_to_input_buf(bytes, 3); + } #endif } @@ -4833,6 +4855,15 @@ { update_topline(); validate_cursor(); +#ifdef FEAT_AUTOCMD + /* Trigger CursorMoved if the cursor moved. */ + if (!finish_op && has_cursormoved() + && !equalpos(last_cursormoved, curwin->w_cursor)) + { + apply_autocmds(EVENT_CURSORMOVED, NULL, NULL, FALSE, curbuf); + last_cursormoved = curwin->w_cursor; + } +#endif update_screen(0); /* may need to update the screen */ setcursor(); out_flush(); /* make sure output has been written */ @@ -5026,7 +5057,7 @@ /* Search for the next match. */ i = msg_scroll; do_search(NULL, down ? '/' : '?', ga.ga_data, 1L, - SEARCH_MSG + SEARCH_MARK); + SEARCH_MSG + SEARCH_MARK, NULL); msg_scroll = i; /* don't let an error message set msg_scroll */ } @@ -5117,7 +5148,7 @@ p = vim_strsave_escaped(fnames[i], (char_u *)"\\ \t\"|"); # endif if (p != NULL) - add_to_input_buf(p, (int)STRLEN(p)); + add_to_input_buf_csi(p, (int)STRLEN(p)); vim_free(p); vim_free(fnames[i]); } diff -Naur vim71.orig/src/gui_gtk.c vim71/src/gui_gtk.c --- vim71.orig/src/gui_gtk.c 2007-05-10 04:37:37.000000000 -0400 +++ vim71/src/gui_gtk.c 2008-06-18 06:52:00.000000000 -0400 @@ -53,8 +53,8 @@ # ifdef bindtextdomain # undef bindtextdomain # endif -# ifdef bindtextdomain_codeset -# undef bindtextdomain_codeset +# ifdef bind_textdomain_codeset +# undef bind_textdomain_codeset # endif # if defined(FEAT_GETTEXT) && !defined(ENABLE_NLS) # define ENABLE_NLS /* so the texts in the dialog boxes are translated */ @@ -1630,11 +1630,14 @@ */ /*ARGSUSED*/ static int -dlg_key_press_event(GtkWidget * widget, GdkEventKey * event, CancelData *data) +dlg_key_press_event(GtkWidget *widget, GdkEventKey *event, CancelData *data) { - /* Ignore hitting Enter when there is no default button. */ - if (data->ignore_enter && event->keyval == GDK_Return) + /* Ignore hitting Enter (or Space) when there is no default button. */ + if (data->ignore_enter && (event->keyval == GDK_Return + || event->keyval == ' ')) return TRUE; + else /* A different key was pressed, return to normal behavior */ + data->ignore_enter = FALSE; if (event->keyval != GDK_Escape && event->keyval != GDK_Return) return FALSE; @@ -2224,6 +2227,13 @@ { DialogInfo *di = (DialogInfo *)data; + /* Ignore hitting Enter (or Space) when there is no default button. */ + if (di->ignore_enter && (event->keyval == GDK_Return + || event->keyval == ' ')) + return TRUE; + else /* A different key was pressed, return to normal behavior */ + di->ignore_enter = FALSE; + /* Close the dialog when hitting "Esc". */ if (event->keyval == GDK_Escape) { diff -Naur vim71.orig/src/gui_gtk_x11.c vim71/src/gui_gtk_x11.c --- vim71.orig/src/gui_gtk_x11.c 2007-05-10 04:37:49.000000000 -0400 +++ vim71/src/gui_gtk_x11.c 2008-06-18 06:54:51.000000000 -0400 @@ -36,8 +36,8 @@ # ifdef bindtextdomain # undef bindtextdomain # endif -# ifdef bindtextdomain_codeset -# undef bindtextdomain_codeset +# ifdef bind_textdomain_codeset +# undef bind_textdomain_codeset # endif # if defined(FEAT_GETTEXT) && !defined(ENABLE_NLS) # define ENABLE_NLS /* so the texts in the dialog boxes are translated */ @@ -813,10 +813,15 @@ if (blink_state == BLINK_NONE) gui_mch_start_blink(); - /* make sure keyboard input goes to the draw area (if this is focus for a window) */ + /* make sure keyboard input goes to the draw area (if this is focus for a + * window) */ if (widget != gui.drawarea) gtk_widget_grab_focus(gui.drawarea); + /* make sure the input buffer is read */ + if (gtk_main_level() > 0) + gtk_main_quit(); + return TRUE; } @@ -829,6 +834,10 @@ if (blink_state != BLINK_NONE) gui_mch_stop_blink(); + /* make sure the input buffer is read */ + if (gtk_main_level() > 0) + gtk_main_quit(); + return TRUE; } @@ -2188,8 +2197,10 @@ escaped_filename = vim_strsave_escaped(filename, escape_chars); if (escaped_filename == NULL) return FALSE; - mksession_cmdline = g_strconcat("mksession ", (char *)escaped_filename, NULL); + mksession_cmdline = g_strconcat("mksession ", (char *)escaped_filename, + NULL); vim_free(escaped_filename); + /* * Use a reasonable hardcoded set of 'sessionoptions' flags to avoid * unpredictable effects when the session is saved automatically. Also, @@ -2199,7 +2210,7 @@ */ save_ssop_flags = ssop_flags; ssop_flags = (SSOP_BLANK|SSOP_CURDIR|SSOP_FOLDS|SSOP_GLOBALS - |SSOP_HELP|SSOP_OPTIONS|SSOP_WINSIZE); + |SSOP_HELP|SSOP_OPTIONS|SSOP_WINSIZE|SSOP_TABPAGES); do_cmdline_cmd((char_u *)"let Save_VV_this_session = v:this_session"); failed = (do_cmdline_cmd((char_u *)mksession_cmdline) == FAIL); @@ -3212,8 +3223,9 @@ { if (clicked_page == 0) { - /* Click after all tabs moves to next tab page. */ - if (send_tabline_event(0) && gtk_main_level() > 0) + /* Click after all tabs moves to next tab page. When "x" is + * small guess it's the left button. */ + if (send_tabline_event(x < 50 ? -1 : 0) && gtk_main_level() > 0) gtk_main_quit(); } #ifndef HAVE_GTK2 @@ -4032,6 +4044,8 @@ unsigned int w, h; int x = 0; int y = 0; + guint pixel_width; + guint pixel_height; mask = XParseGeometry((char *)gui.geom, &x, &y, &w, &h); @@ -4043,12 +4057,31 @@ p_window = h - 1; Rows = h; } + + pixel_width = (guint)(gui_get_base_width() + Columns * gui.char_width); + pixel_height = (guint)(gui_get_base_height() + Rows * gui.char_height); + +#ifdef HAVE_GTK2 + pixel_width += get_menu_tool_width(); + pixel_height += get_menu_tool_height(); +#endif + if (mask & (XValue | YValue)) + { + int w, h; + gui_mch_get_screen_dimensions(&w, &h); + h += p_ghr + get_menu_tool_height(); + w += get_menu_tool_width(); + if (mask & XNegative) + x += w - pixel_width; + if (mask & YNegative) + y += h - pixel_height; #ifdef HAVE_GTK2 gtk_window_move(GTK_WINDOW(gui.mainwin), x, y); #else gtk_widget_set_uposition(gui.mainwin, x, y); #endif + } vim_free(gui.geom); gui.geom = NULL; @@ -4059,14 +4092,6 @@ */ if (gtk_socket_id != 0 && (mask & WidthValue || mask & HeightValue)) { - guint pixel_width = (guint)(gui_get_base_width() + Columns * gui.char_width); - guint pixel_height = (guint)(gui_get_base_height() + Rows * gui.char_height); - -#ifdef HAVE_GTK2 - pixel_width += get_menu_tool_width(); - pixel_height += get_menu_tool_height(); -#endif - update_window_manager_hints(pixel_width, pixel_height); init_window_hints_state = 1; g_timeout_add(1000, check_startup_plug_hints, NULL); @@ -6635,6 +6660,7 @@ unsigned i; int nbytes; char_u *buffer; + time_t start; for (i = 0; i < N_SELECTION_TARGETS; ++i) { @@ -6645,7 +6671,11 @@ cbd->gtk_sel_atom, target, (guint32)GDK_CURRENT_TIME); - while (received_selection == RS_NONE) + /* Hack: Wait up to three seconds for the selection. A hang was + * noticed here when using the netrw plugin combined with ":gui" + * during the FocusGained event. */ + start = time(NULL); + while (received_selection == RS_NONE && time(NULL) < start + 3) gtk_main(); /* wait for selection_received_cb */ if (received_selection != RS_FAIL) diff -Naur vim71.orig/src/gui_motif.c vim71/src/gui_motif.c --- vim71.orig/src/gui_motif.c 2007-05-07 15:20:24.000000000 -0400 +++ vim71/src/gui_motif.c 2008-06-18 06:55:26.000000000 -0400 @@ -3813,7 +3813,7 @@ XtAddCallback(frdp->find, XmNactivateCallback, find_replace_callback, - (XtPointer) (do_replace ? FRD_R_FINDNEXT : FRD_FINDNEXT)); + (do_replace ? (XtPointer)FRD_R_FINDNEXT : (XtPointer)FRD_FINDNEXT)); if (do_replace) { diff -Naur vim71.orig/src/gui_xmebw.c vim71/src/gui_xmebw.c --- vim71.orig/src/gui_xmebw.c 2007-05-07 15:30:49.000000000 -0400 +++ vim71/src/gui_xmebw.c 2008-06-18 06:53:43.000000000 -0400 @@ -395,11 +395,15 @@ /* Create the "highlight" pixmap. */ color[4].pixel = eb->primitive.bottom_shadow_color; +#ifdef XpmAllocColor /* SGI doesn't have it */ attr.valuemask = XpmColorSymbols | XpmCloseness | XpmAllocColor; + attr.alloc_color = alloc_color; +#else + attr.valuemask = XpmColorSymbols | XpmCloseness; +#endif attr.closeness = 65535; /* accuracy isn't crucial */ attr.colorsymbols = color; attr.numsymbols = XtNumber(color); - attr.alloc_color = alloc_color; status = XpmCreatePixmapFromData(dpy, root, data, &pix, NULL, &attr); XpmFreeAttributes(&attr); diff -Naur vim71.orig/src/gvimtutor vim71/src/gvimtutor --- vim71.orig/src/gvimtutor 1969-12-31 19:00:00.000000000 -0500 +++ vim71/src/gvimtutor 2008-06-18 06:56:38.000000000 -0400 @@ -0,0 +1,8 @@ +#!/bin/sh + +# Start GUI Vim on a copy of the tutor file. + +# Usage: gvimtutor [xx] +# See vimtutor for usage. + +exec `dirname $0`/vimtutor -g "$@" diff -Naur vim71.orig/src/hardcopy.c vim71/src/hardcopy.c --- vim71.orig/src/hardcopy.c 2007-05-07 15:34:18.000000000 -0400 +++ vim71/src/hardcopy.c 2008-06-18 06:55:04.000000000 -0400 @@ -876,7 +876,7 @@ */ if (psettings->do_syntax) { - id = syn_get_id(curwin, ppos->file_line, col, 1, NULL); + id = syn_get_id(curwin, ppos->file_line, col, 1, NULL, FALSE); if (id > 0) id = syn_get_final_id(id); else diff -Naur vim71.orig/src/if_cscope.c vim71/src/if_cscope.c --- vim71.orig/src/if_cscope.c 2007-03-11 10:29:57.000000000 -0400 +++ vim71/src/if_cscope.c 2008-06-18 06:56:33.000000000 -0400 @@ -24,11 +24,6 @@ /* not UNIX, must be WIN32 */ # include "vimio.h" # include -# include -# define STDIN_FILENO 0 -# define STDOUT_FILENO 1 -# define STDERR_FILENO 2 -# define pipe(fds) _pipe(fds, 256, O_TEXT|O_NOINHERIT) #endif #include "if_cscope.h" @@ -65,7 +60,7 @@ static char * cs_parse_results __ARGS((int cnumber, char *buf, int bufsize, char **context, char **linenumber, char **search)); static char * cs_pathcomponents __ARGS((char *path)); static void cs_print_tags_priv __ARGS((char **, char **, int)); -static int cs_read_prompt __ARGS((int )); +static int cs_read_prompt __ARGS((int)); static void cs_release_csp __ARGS((int, int freefnpp)); static int cs_reset __ARGS((exarg_T *eap)); static char * cs_resolve_file __ARGS((int, char *)); @@ -73,6 +68,8 @@ static csinfo_T csinfo[CSCOPE_MAX_CONNECTIONS]; +static int eap_arg_len; /* length of eap->arg, set in + cs_lookup_cmd() */ static cscmd_T cs_cmds[] = { { "add", cs_add, @@ -260,14 +257,7 @@ if ((p = cs_manage_matches(NULL, NULL, -1, Get)) == NULL) return TRUE; - - if ((int)strlen(p) > size) - { - strncpy((char *)buf, p, size - 1); - buf[size] = '\0'; - } - else - (void)strcpy((char *)buf, p); + vim_strncpy(buf, (char_u *)p, size - 1); return FALSE; } /* cs_fgets */ @@ -386,7 +376,7 @@ * PRIVATE: cs_add * * add cscope database or a directory name (to look for cscope.out) - * the the cscope connection list + * to the cscope connection list * * MAXPATHL 256 */ @@ -509,7 +499,7 @@ #if defined(UNIX) else if (S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode)) #else - /* substitute define S_ISREG from os_unix.h */ + /* WIN32 - substitute define S_ISREG from os_unix.h */ else if (((statbuf.st_mode) & S_IFMT) == S_IFREG) #endif { @@ -722,17 +712,32 @@ cs_create_connection(i) int i; { - int to_cs[2], from_cs[2], len; - char *prog, *cmd, *ppath = NULL; -#ifndef UNIX - int in_save, out_save, err_save; - long_i ph; -# ifdef FEAT_GUI - HWND activewnd = NULL; - HWND consolewnd = NULL; +#ifdef UNIX + int to_cs[2], from_cs[2]; +#endif + int len; + char *prog, *cmd, *ppath = NULL; +#ifdef WIN32 + int fd; + SECURITY_ATTRIBUTES sa; + PROCESS_INFORMATION pi; + STARTUPINFO si; + BOOL pipe_stdin = FALSE, pipe_stdout = FALSE; + HANDLE stdin_rd, stdout_rd; + HANDLE stdout_wr, stdin_wr; + BOOL created; +# ifdef __BORLANDC__ +# define OPEN_OH_ARGTYPE long +# else +# if (_MSC_VER >= 1300) +# define OPEN_OH_ARGTYPE intptr_t +# else +# define OPEN_OH_ARGTYPE long +# endif # endif #endif +#if defined(UNIX) /* * Cscope reads from to_cs[0] and writes to from_cs[1]; vi reads from * from_cs[0] and writes to to_cs[1]. @@ -753,18 +758,12 @@ return CSCOPE_FAILURE; } -#if defined(UNIX) switch (csinfo[i].pid = fork()) { case -1: (void)EMSG(_("E622: Could not fork for cscope")); goto err_closing; case 0: /* child: run cscope. */ -#else - in_save = dup(STDIN_FILENO); - out_save = dup(STDOUT_FILENO); - err_save = dup(STDERR_FILENO); -#endif if (dup2(to_cs[0], STDIN_FILENO) == -1) PERROR("cs_create_connection 1"); if (dup2(from_cs[1], STDOUT_FILENO) == -1) @@ -773,15 +772,32 @@ PERROR("cs_create_connection 3"); /* close unused */ -#if defined(UNIX) (void)close(to_cs[1]); (void)close(from_cs[0]); #else - /* On win32 we must close opposite ends because we are the parent */ - (void)close(to_cs[0]); - to_cs[0] = -1; - (void)close(from_cs[1]); - from_cs[1] = -1; + /* WIN32 */ + /* Create pipes to communicate with cscope */ + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = NULL; + + if (!(pipe_stdin = CreatePipe(&stdin_rd, &stdin_wr, &sa, 0)) + || !(pipe_stdout = CreatePipe(&stdout_rd, &stdout_wr, &sa, 0))) + { + (void)EMSG(_("E566: Could not create cscope pipes")); +err_closing: + if (pipe_stdin) + { + CloseHandle(stdin_rd); + CloseHandle(stdin_wr); + } + if (pipe_stdout) + { + CloseHandle(stdout_rd); + CloseHandle(stdout_wr); + } + return CSCOPE_FAILURE; + } #endif /* expand the cscope exec for env var's */ if ((prog = (char *)alloc(MAXPATHL + 1)) == NULL) @@ -789,6 +805,7 @@ #ifdef UNIX return CSCOPE_FAILURE; #else + /* WIN32 */ goto err_closing; #endif } @@ -805,6 +822,7 @@ #ifdef UNIX return CSCOPE_FAILURE; #else + /* WIN32 */ goto err_closing; #endif } @@ -823,6 +841,7 @@ #ifdef UNIX return CSCOPE_FAILURE; #else + /* WIN32 */ goto err_closing; #endif } @@ -831,6 +850,7 @@ #if defined(UNIX) (void)sprintf(cmd, "exec %s -dl -f %s", prog, csinfo[i].fname); #else + /* WIN32 */ (void)sprintf(cmd, "%s -dl -f %s", prog, csinfo[i].fname); #endif if (csinfo[i].ppath != NULL) @@ -856,60 +876,6 @@ exit(127); /* NOTREACHED */ default: /* parent. */ -#else -# ifdef FEAT_GUI - activewnd = GetForegroundWindow(); /* on win9x cscope steals focus */ - /* Dirty hack to hide annoying console window */ - if (AllocConsole()) - { - char *title; - title = (char *)alloc(1024); - if (title == NULL) - FreeConsole(); - else - { - GetConsoleTitle(title, 1024); /* save for future restore */ - SetConsoleTitle( - "GVIMCS{5499421B-CBEF-45b0-85EF-38167FDEA5C5}GVIMCS"); - Sleep(40); /* as stated in MS KB we must wait 40 ms */ - consolewnd = FindWindow(NULL, - "GVIMCS{5499421B-CBEF-45b0-85EF-38167FDEA5C5}GVIMCS"); - if (consolewnd != NULL) - ShowWindow(consolewnd, SW_HIDE); - SetConsoleTitle(title); - vim_free(title); - } - } -# endif - /* May be use &shell, &shellquote etc */ -# ifdef __BORLANDC__ - /* BCC 5.5 uses a different function name for spawnlp */ - ph = (long_i)spawnlp(P_NOWAIT, prog, cmd, NULL); -# else - ph = (long_i)_spawnlp(_P_NOWAIT, prog, cmd, NULL); -# endif - vim_free(prog); - vim_free(cmd); -# ifdef FEAT_GUI - /* Dirty hack part two */ - if (activewnd != NULL) - /* restoring focus */ - SetForegroundWindow(activewnd); - if (consolewnd != NULL) - FreeConsole(); - -# endif - if (ph == -1) - { - PERROR(_("cs_create_connection exec failed")); - (void)EMSG(_("E623: Could not spawn cscope process")); - goto err_closing; - } - /* else */ - csinfo[i].pid = 0; - csinfo[i].hProc = (HANDLE)ph; - -#endif /* !UNIX */ /* * Save the file descriptors for later duplication, and * reopen as streams. @@ -919,22 +885,54 @@ if ((csinfo[i].fr_fp = fdopen(from_cs[0], "r")) == NULL) PERROR(_("cs_create_connection: fdopen for fr_fp failed")); -#if defined(UNIX) /* close unused */ (void)close(to_cs[0]); (void)close(from_cs[1]); break; } + #else - /* restore stdhandles */ - dup2(in_save, STDIN_FILENO); - dup2(out_save, STDOUT_FILENO); - dup2(err_save, STDERR_FILENO); - close(in_save); - close(out_save); - close(err_save); -#endif + /* WIN32 */ + /* Create a new process to run cscope and use pipes to talk with it */ + GetStartupInfo(&si); + si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; + si.wShowWindow = SW_HIDE; /* Hide child application window */ + si.hStdOutput = stdout_wr; + si.hStdError = stdout_wr; + si.hStdInput = stdin_rd; + created = CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, + NULL, NULL, &si, &pi); + vim_free(prog); + vim_free(cmd); + + if (!created) + { + PERROR(_("cs_create_connection exec failed")); + (void)EMSG(_("E623: Could not spawn cscope process")); + goto err_closing; + } + /* else */ + csinfo[i].pid = pi.dwProcessId; + csinfo[i].hProc = pi.hProcess; + CloseHandle(pi.hThread); + + /* TODO - tidy up after failure to create files on pipe handles. */ + if (((fd = _open_osfhandle((OPEN_OH_ARGTYPE)stdin_wr, + _O_TEXT|_O_APPEND)) < 0) + || ((csinfo[i].to_fp = _fdopen(fd, "w")) == NULL)) + PERROR(_("cs_create_connection: fdopen for to_fp failed")); + if (((fd = _open_osfhandle((OPEN_OH_ARGTYPE)stdout_rd, + _O_TEXT|_O_RDONLY)) < 0) + || ((csinfo[i].fr_fp = _fdopen(fd, "r")) == NULL)) + PERROR(_("cs_create_connection: fdopen for fr_fp failed")); + + /* Close handles for file descriptors inherited by the cscope process */ + CloseHandle(stdin_rd); + CloseHandle(stdout_wr); + +#endif /* !UNIX */ + return CSCOPE_SUCCESS; } /* cs_create_connection */ @@ -966,7 +964,7 @@ } pat = opt + strlen(opt) + 1; - if (pat == NULL || (pat != NULL && pat[0] == '\0')) + if (pat >= (char *)eap->arg + eap_arg_len) { cs_usage_msg(Find); return FALSE; @@ -1317,7 +1315,7 @@ #else /* compare pathnames first */ && ((fullpathcmp(csinfo[j].fname, fname, FALSE) & FPC_SAME) - /* if not Windows 9x, test index file atributes too */ + /* if not Windows 9x, test index file attributes too */ || (!mch_windows95() && csinfo[j].nVolume == bhfi.dwVolumeSerialNumber && csinfo[j].nIndexHigh == bhfi.nFileIndexHigh @@ -1401,6 +1399,9 @@ if (eap->arg == NULL) return NULL; + /* Store length of eap->arg before it gets modified by strtok(). */ + eap_arg_len = STRLEN(eap->arg); + if ((stok = strtok((char *)(eap->arg), (const char *)" ")) == NULL) return NULL; @@ -2095,21 +2096,30 @@ return CSCOPE_SUCCESS; } +#if defined(UNIX) && defined(SIGALRM) +/* + * Used to catch and ignore SIGALRM below. + */ +/* ARGSUSED */ + static RETSIGTYPE +sig_handler SIGDEFARG(sigarg) +{ + /* do nothing */ + SIGRETURN; +} +#endif /* * PRIVATE: cs_release_csp * - * does the actual free'ing for the cs ptr with an optional flag of whether - * or not to free the filename. called by cs_kill and cs_reset. + * Does the actual free'ing for the cs ptr with an optional flag of whether + * or not to free the filename. Called by cs_kill and cs_reset. */ static void cs_release_csp(i, freefnpp) int i; int freefnpp; { -#if defined(UNIX) - int pstat; -#else /* * Trying to exit normally (not sure whether it is fit to UNIX cscope */ @@ -2118,10 +2128,95 @@ (void)fputs("q\n", csinfo[i].to_fp); (void)fflush(csinfo[i].to_fp); } - /* give cscope chance to exit normally */ - if (csinfo[i].hProc != NULL - && WaitForSingleObject(csinfo[i].hProc, 1000) == WAIT_TIMEOUT) - TerminateProcess(csinfo[i].hProc, 0); +#if defined(UNIX) + { + int waitpid_errno; + int pstat; + pid_t pid; + +# if defined(HAVE_SIGACTION) + struct sigaction sa, old; + + /* Use sigaction() to limit the waiting time to two seconds. */ + sigemptyset(&sa.sa_mask); + sa.sa_handler = sig_handler; + sa.sa_flags = SA_NODEFER; + sigaction(SIGALRM, &sa, &old); + alarm(2); /* 2 sec timeout */ + + /* Block until cscope exits or until timer expires */ + pid = waitpid(csinfo[i].pid, &pstat, 0); + waitpid_errno = errno; + + /* cancel pending alarm if still there and restore signal */ + alarm(0); + sigaction(SIGALRM, &old, NULL); +# else + int waited; + + /* Can't use sigaction(), loop for two seconds. First yield the CPU + * to give cscope a chance to exit quickly. */ + sleep(0); + for (waited = 0; waited < 40; ++waited) + { + pid = waitpid(csinfo[i].pid, &pstat, WNOHANG); + waitpid_errno = errno; + if (pid != 0) + break; /* break unless the process is still running */ + mch_delay(50L, FALSE); /* sleep 50 ms */ + } +# endif + /* + * If the cscope process is still running: kill it. + * Safety check: If the PID would be zero here, the entire X session + * would be killed. -1 and 1 are dangerous as well. + */ + if (pid < 0 && csinfo[i].pid > 1) + { +# ifdef ECHILD + int alive = TRUE; + + if (waitpid_errno == ECHILD) + { + /* + * When using 'vim -g', vim is forked and cscope process is + * no longer a child process but a sibling. So waitpid() + * fails with errno being ECHILD (No child processes). + * Don't send SIGKILL to cscope immediately but wait + * (polling) for it to exit normally as result of sending + * the "q" command, hence giving it a chance to clean up + * its temporary files. + */ + int waited; + + sleep(0); + for (waited = 0; waited < 40; ++waited) + { + /* Check whether cscope process is still alive */ + if (kill(csinfo[i].pid, 0) != 0) + { + alive = FALSE; /* cscope process no longer exists */ + break; + } + mch_delay(50L, FALSE); /* sleep 50ms */ + } + } + if (alive) +# endif + { + kill(csinfo[i].pid, SIGKILL); + (void)waitpid(csinfo[i].pid, &pstat, 0); + } + } + } +#else /* !UNIX */ + if (csinfo[i].hProc != NULL) + { + /* Give cscope a chance to exit normally */ + if (WaitForSingleObject(csinfo[i].hProc, 1000) == WAIT_TIMEOUT) + TerminateProcess(csinfo[i].hProc, 0); + CloseHandle(csinfo[i].hProc); + } #endif if (csinfo[i].fr_fp != NULL) @@ -2129,18 +2224,6 @@ if (csinfo[i].to_fp != NULL) (void)fclose(csinfo[i].to_fp); - /* - * Safety check: If the PID would be zero here, the entire X session would - * be killed. -1 and 1 are dangerous as well. - */ -#if defined(UNIX) - if (csinfo[i].pid > 1) - { - kill(csinfo[i].pid, SIGTERM); - (void)waitpid(csinfo[i].pid, &pstat, 0); - } -#endif - if (freefnpp) { vim_free(csinfo[i].fname); @@ -2195,7 +2278,7 @@ cs_add_common(dblist[i], pplist[i], fllist[i]); if (p_csverbose) { - /* dont' use smsg_attr because want to display + /* don't use smsg_attr() because we want to display the * connection number in the same line as * "Added cscope database..." */ @@ -2304,6 +2387,21 @@ return CSCOPE_SUCCESS; } /* cs_show */ + +/* + * PUBLIC: cs_end + * + * Only called when VIM exits to quit any cscope sessions. + */ + void +cs_end() +{ + int i; + + for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++) + cs_release_csp(i, TRUE); +} + #endif /* FEAT_CSCOPE */ /* the end */ diff -Naur vim71.orig/src/if_cscope.h vim71/src/if_cscope.h --- vim71.orig/src/if_cscope.h 2005-06-30 13:14:22.000000000 -0400 +++ vim71/src/if_cscope.h 2008-06-18 06:52:38.000000000 -0400 @@ -72,7 +72,7 @@ ino_t st_ino; /* inode number of cscope db */ #else # if defined(WIN32) - int pid; /* Can't get pid so set it to 0 ;) */ + DWORD pid; /* PID of the connected cscope process. */ HANDLE hProc; /* cscope process handle */ DWORD nVolume; /* Volume serial number, instead of st_dev */ DWORD nIndexHigh; /* st_ino has no meaning in the Windows */ diff -Naur vim71.orig/src/if_mzsch.c vim71/src/if_mzsch.c --- vim71.orig/src/if_mzsch.c 2007-05-12 07:13:47.000000000 -0400 +++ vim71/src/if_mzsch.c 2008-06-18 06:51:00.000000000 -0400 @@ -308,6 +308,8 @@ static Scheme_Config *(*dll_scheme_current_config)(void); static Scheme_Object *(*dll_scheme_char_string_to_byte_string) (Scheme_Object *s); +static Scheme_Object *(*dll_scheme_char_string_to_path) + (Scheme_Object *s); # endif /* arrays are imported directly */ @@ -398,6 +400,8 @@ # define scheme_current_config dll_scheme_current_config # define scheme_char_string_to_byte_string \ dll_scheme_char_string_to_byte_string +# define scheme_char_string_to_path \ + dll_scheme_char_string_to_path # endif typedef struct @@ -498,6 +502,8 @@ {"scheme_current_config", (void **)&dll_scheme_current_config}, {"scheme_char_string_to_byte_string", (void **)&dll_scheme_char_string_to_byte_string}, + {"scheme_char_string_to_path", + (void **)&dll_scheme_char_string_to_path}, # endif {NULL, NULL}}; @@ -773,7 +779,14 @@ #ifdef MZSCHEME_COLLECTS /* setup 'current-library-collection-paths' parameter */ scheme_set_param(scheme_config, MZCONFIG_COLLECTION_PATHS, - scheme_make_pair(scheme_make_string(MZSCHEME_COLLECTS), + scheme_make_pair( +# if MZSCHEME_VERSION_MAJOR >= 299 + scheme_char_string_to_path( + scheme_byte_string_to_char_string( + scheme_make_byte_string(MZSCHEME_COLLECTS))), +# else + scheme_make_string(MZSCHEME_COLLECTS), +# endif scheme_null)); #endif #ifdef HAVE_SANDBOX diff -Naur vim71.orig/src/if_perl.xs vim71/src/if_perl.xs --- vim71.orig/src/if_perl.xs 2006-08-16 08:45:15.000000000 -0400 +++ vim71/src/if_perl.xs 2008-06-18 06:53:25.000000000 -0400 @@ -40,6 +40,28 @@ # define PERL_SUBVERSION SUBVERSION #endif +/* + * Quoting Jan Dubois of Active State: + * ActivePerl build 822 still identifies itself as 5.8.8 but already + * contains many of the changes from the upcoming Perl 5.8.9 release. + * + * The changes include addition of two symbols (Perl_sv_2iv_flags, + * Perl_newXS_flags) not present in earlier releases. + * + * Jan Dubois suggested the following guarding scheme. + * + * Active State defined ACTIVEPERL_VERSION as a string in versions before + * 5.8.8; and so the comparison to 822 below needs to be guarded. + */ +#if (PERL_REVISION == 5) && (PERL_VERSION == 8) && (PERL_SUBVERSION >= 8) +# if (ACTIVEPERL_VERSION >= 822) || (PERL_SUBVERSION >= 9) +# define PERL589_OR_LATER +# endif +#endif +#if (PERL_REVISION == 5) && (PERL_VERSION >= 9) +# define PERL589_OR_LATER +#endif + #ifndef pTHX # define pTHX void # define pTHX_ @@ -109,6 +131,10 @@ # else # define Perl_sv_catpvn dll_Perl_sv_catpvn # endif +#ifdef PERL589_OR_LATER +# define Perl_sv_2iv_flags dll_Perl_sv_2iv_flags +# define Perl_newXS_flags dll_Perl_newXS_flags +#endif # define Perl_sv_free dll_Perl_sv_free # define Perl_sv_isa dll_Perl_sv_isa # define Perl_sv_magic dll_Perl_sv_magic @@ -192,6 +218,10 @@ #else static void (*Perl_sv_catpvn)(pTHX_ SV*, const char*, STRLEN); #endif +#ifdef PERL589_OR_LATER +static IV (*Perl_sv_2iv_flags)(pTHX_ SV* sv, I32 flags); +static CV * (*Perl_newXS_flags)(pTHX_ const char *name, XSUBADDR_t subaddr, const char *const filename, const char *const proto, U32 flags); +#endif static void (*Perl_sv_free)(pTHX_ SV*); static int (*Perl_sv_isa)(pTHX_ SV*, const char*); static void (*Perl_sv_magic)(pTHX_ SV*, SV*, int, const char*, I32); @@ -267,6 +297,10 @@ #else {"Perl_sv_2pv", (PERL_PROC*)&Perl_sv_2pv}, #endif +#ifdef PERL589_OR_LATER + {"Perl_sv_2iv_flags", (PERL_PROC*)&Perl_sv_2iv_flags}, + {"Perl_newXS_flags", (PERL_PROC*)&Perl_newXS_flags}, +#endif {"Perl_sv_bless", (PERL_PROC*)&Perl_sv_bless}, #if (PERL_REVISION == 5) && (PERL_VERSION >= 8) {"Perl_sv_catpvn_flags", (PERL_PROC*)&Perl_sv_catpvn_flags}, @@ -411,13 +445,13 @@ char *next; char *token = (char *)s; - while ((next = strchr(token, '\n'))) + while ((next = strchr(token, '\n')) && !got_int) { *next++ = '\0'; /* replace \n with \0 */ msg_attr((char_u *)token, attr); token = next; } - if (*token) + if (*token && !got_int) msg_attr((char_u *)token, attr); } diff -Naur vim71.orig/src/if_python.c vim71/src/if_python.c --- vim71.orig/src/if_python.c 2007-03-06 17:00:53.000000000 -0500 +++ vim71/src/if_python.c 2008-06-18 06:56:52.000000000 -0400 @@ -38,6 +38,8 @@ # undef HAVE_STDARG_H /* Python's config.h defines it as well. */ #endif +#define PY_SSIZE_T_CLEAN + #include #if defined(MACOS) && !defined(MACOS_X_UNIX) # include "macglue.h" @@ -55,6 +57,22 @@ # define PySequenceMethods int #endif +#if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02050000 +# define PyInt Py_ssize_t +# define PyInquiry lenfunc +# define PyIntArgFunc ssizeargfunc +# define PyIntIntArgFunc ssizessizeargfunc +# define PyIntObjArgProc ssizeobjargproc +# define PyIntIntObjArgProc ssizessizeobjargproc +#else +# define PyInt int +# define PyInquiry inquiry +# define PyIntArgFunc intargfunc +# define PyIntIntArgFunc intintargfunc +# define PyIntObjArgProc intobjargproc +# define PyIntIntObjArgProc intintobjargproc +#endif + /* Parser flags */ #define single_input 256 #define file_input 257 @@ -150,11 +168,11 @@ static long(*dll_PyInt_AsLong)(PyObject *); static PyObject*(*dll_PyInt_FromLong)(long); static PyTypeObject* dll_PyInt_Type; -static PyObject*(*dll_PyList_GetItem)(PyObject *, int); +static PyObject*(*dll_PyList_GetItem)(PyObject *, PyInt); static PyObject*(*dll_PyList_Append)(PyObject *, PyObject *); -static PyObject*(*dll_PyList_New)(int size); -static int(*dll_PyList_SetItem)(PyObject *, int, PyObject *); -static int(*dll_PyList_Size)(PyObject *); +static PyObject*(*dll_PyList_New)(PyInt size); +static int(*dll_PyList_SetItem)(PyObject *, PyInt, PyObject *); +static PyInt(*dll_PyList_Size)(PyObject *); static PyTypeObject* dll_PyList_Type; static PyObject*(*dll_PyImport_ImportModule)(const char *); static PyObject*(*dll_PyDict_New)(void); @@ -163,8 +181,8 @@ static int(*dll_PyRun_SimpleString)(char *); static char*(*dll_PyString_AsString)(PyObject *); static PyObject*(*dll_PyString_FromString)(const char *); -static PyObject*(*dll_PyString_FromStringAndSize)(const char *, int); -static int(*dll_PyString_Size)(PyObject *); +static PyObject*(*dll_PyString_FromStringAndSize)(const char *, PyInt); +static PyInt(*dll_PyString_Size)(PyObject *); static PyTypeObject* dll_PyString_Type; static int(*dll_PySys_SetObject)(char *, PyObject *); static int(*dll_PySys_SetArgv)(int, char **); @@ -367,10 +385,10 @@ * ---------------------------------------------- */ static PyObject *GetBufferLine(buf_T *, int); -static PyObject *GetBufferLineList(buf_T *, int, int); +static PyObject *GetBufferLineList(buf_T *, PyInt, PyInt); static int SetBufferLine(buf_T *, int, PyObject *, int *); -static int SetBufferLineList(buf_T *, int, int, PyObject *, int *); +static int SetBufferLineList(buf_T *, PyInt, PyInt, PyObject *, int *); static int InsertBufferLines(buf_T *, int, PyObject *, int *); static PyObject *LineToString(const char *); @@ -773,8 +791,8 @@ static PyObject * OutputWritelines(PyObject *self, PyObject *args) { - int n; - int i; + PyInt n; + PyInt i; PyObject *list; int error = ((OutputObject *)(self))->error; @@ -986,11 +1004,11 @@ static PyObject *BufferGetattr(PyObject *, char *); static PyObject *BufferRepr(PyObject *); -static int BufferLength(PyObject *); -static PyObject *BufferItem(PyObject *, int); -static PyObject *BufferSlice(PyObject *, int, int); -static int BufferAssItem(PyObject *, int, PyObject *); -static int BufferAssSlice(PyObject *, int, int, PyObject *); +static PyInt BufferLength(PyObject *); +static PyObject *BufferItem(PyObject *, PyInt); +static PyObject *BufferSlice(PyObject *, PyInt, PyInt); +static PyInt BufferAssItem(PyObject *, PyInt, PyObject *); +static PyInt BufferAssSlice(PyObject *, PyInt, PyInt, PyObject *); static PyObject *BufferAppend(PyObject *, PyObject *); static PyObject *BufferMark(PyObject *, PyObject *); @@ -1017,11 +1035,11 @@ static PyObject *RangeGetattr(PyObject *, char *); static PyObject *RangeRepr(PyObject *); -static int RangeLength(PyObject *); -static PyObject *RangeItem(PyObject *, int); -static PyObject *RangeSlice(PyObject *, int, int); -static int RangeAssItem(PyObject *, int, PyObject *); -static int RangeAssSlice(PyObject *, int, int, PyObject *); +static PyInt RangeLength(PyObject *); +static PyObject *RangeItem(PyObject *, PyInt); +static PyObject *RangeSlice(PyObject *, PyInt, PyInt); +static PyInt RangeAssItem(PyObject *, PyInt, PyObject *); +static PyInt RangeAssSlice(PyObject *, PyInt, PyInt, PyObject *); static PyObject *RangeAppend(PyObject *, PyObject *); @@ -1029,15 +1047,15 @@ * ------------------------------------------- */ -static int WinListLength(PyObject *); -static PyObject *WinListItem(PyObject *, int); +static PyInt WinListLength(PyObject *); +static PyObject *WinListItem(PyObject *, PyInt); /* Buffer list type - Implementation functions * ------------------------------------------- */ -static int BufListLength(PyObject *); -static PyObject *BufListItem(PyObject *, int); +static PyInt BufListLength(PyObject *); +static PyObject *BufListItem(PyObject *, PyInt); /* Current objects type - Implementation functions * ----------------------------------------------- @@ -1130,6 +1148,16 @@ result = Py_BuildValue("s", buf); PyDict_SetItemString(lookupDict, ptrBuf, result); } +#ifdef FEAT_FLOAT + else if (our_tv->v_type == VAR_FLOAT) + { + char buf[NUMBUFLEN]; + + sprintf(buf, "%f", our_tv->vval.v_float); + result = Py_BuildValue("s", buf); + PyDict_SetItemString(lookupDict, ptrBuf, result); + } +#endif else if (our_tv->v_type == VAR_LIST) { list_T *list = our_tv->vval.v_list; @@ -1245,7 +1273,7 @@ } static PyObject * -RBItem(BufferObject *self, int n, int start, int end) +RBItem(BufferObject *self, PyInt n, int start, int end) { if (CheckBuffer(self)) return NULL; @@ -1260,9 +1288,9 @@ } static PyObject * -RBSlice(BufferObject *self, int lo, int hi, int start, int end) +RBSlice(BufferObject *self, PyInt lo, PyInt hi, int start, int end) { - int size; + PyInt size; if (CheckBuffer(self)) return NULL; @@ -1283,8 +1311,8 @@ return GetBufferLineList(self->buf, lo+start, hi+start); } - static int -RBAssItem(BufferObject *self, int n, PyObject *val, int start, int end, int *new_end) + static PyInt +RBAssItem(BufferObject *self, PyInt n, PyObject *val, int start, int end, int *new_end) { int len_change; @@ -1306,8 +1334,8 @@ return 0; } - static int -RBAssSlice(BufferObject *self, int lo, int hi, PyObject *val, int start, int end, int *new_end) + static PyInt +RBAssSlice(BufferObject *self, PyInt lo, PyInt hi, PyObject *val, int start, int end, int *new_end) { int size; int len_change; @@ -1384,13 +1412,13 @@ }; static PySequenceMethods BufferAsSeq = { - (inquiry) BufferLength, /* sq_length, len(x) */ + (PyInquiry) BufferLength, /* sq_length, len(x) */ (binaryfunc) 0, /* BufferConcat, */ /* sq_concat, x+y */ - (intargfunc) 0, /* BufferRepeat, */ /* sq_repeat, x*n */ - (intargfunc) BufferItem, /* sq_item, x[i] */ - (intintargfunc) BufferSlice, /* sq_slice, x[i:j] */ - (intobjargproc) BufferAssItem, /* sq_ass_item, x[i]=v */ - (intintobjargproc) BufferAssSlice, /* sq_ass_slice, x[i:j]=v */ + (PyIntArgFunc) 0, /* BufferRepeat, */ /* sq_repeat, x*n */ + (PyIntArgFunc) BufferItem, /* sq_item, x[i] */ + (PyIntIntArgFunc) BufferSlice, /* sq_slice, x[i:j] */ + (PyIntObjArgProc) BufferAssItem, /* sq_ass_item, x[i]=v */ + (PyIntIntObjArgProc) BufferAssSlice, /* sq_ass_slice, x[i:j]=v */ }; static PyTypeObject BufferType = { @@ -1516,7 +1544,7 @@ /******************/ - static int + static PyInt BufferLength(PyObject *self) { /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */ @@ -1527,29 +1555,29 @@ } static PyObject * -BufferItem(PyObject *self, int n) +BufferItem(PyObject *self, PyInt n) { return RBItem((BufferObject *)(self), n, 1, (int)((BufferObject *)(self))->buf->b_ml.ml_line_count); } static PyObject * -BufferSlice(PyObject *self, int lo, int hi) +BufferSlice(PyObject *self, PyInt lo, PyInt hi) { return RBSlice((BufferObject *)(self), lo, hi, 1, (int)((BufferObject *)(self))->buf->b_ml.ml_line_count); } - static int -BufferAssItem(PyObject *self, int n, PyObject *val) + static PyInt +BufferAssItem(PyObject *self, PyInt n, PyObject *val) { return RBAssItem((BufferObject *)(self), n, val, 1, (int)((BufferObject *)(self))->buf->b_ml.ml_line_count, NULL); } - static int -BufferAssSlice(PyObject *self, int lo, int hi, PyObject *val) + static PyInt +BufferAssSlice(PyObject *self, PyInt lo, PyInt hi, PyObject *val) { return RBAssSlice((BufferObject *)(self), lo, hi, val, 1, (int)((BufferObject *)(self))->buf->b_ml.ml_line_count, @@ -1627,13 +1655,13 @@ }; static PySequenceMethods RangeAsSeq = { - (inquiry) RangeLength, /* sq_length, len(x) */ + (PyInquiry) RangeLength, /* sq_length, len(x) */ (binaryfunc) 0, /* RangeConcat, */ /* sq_concat, x+y */ - (intargfunc) 0, /* RangeRepeat, */ /* sq_repeat, x*n */ - (intargfunc) RangeItem, /* sq_item, x[i] */ - (intintargfunc) RangeSlice, /* sq_slice, x[i:j] */ - (intobjargproc) RangeAssItem, /* sq_ass_item, x[i]=v */ - (intintobjargproc) RangeAssSlice, /* sq_ass_slice, x[i:j]=v */ + (PyIntArgFunc) 0, /* RangeRepeat, */ /* sq_repeat, x*n */ + (PyIntArgFunc) RangeItem, /* sq_item, x[i] */ + (PyIntIntArgFunc) RangeSlice, /* sq_slice, x[i:j] */ + (PyIntObjArgProc) RangeAssItem, /* sq_ass_item, x[i]=v */ + (PyIntIntObjArgProc) RangeAssSlice, /* sq_ass_slice, x[i:j]=v */ }; static PyTypeObject RangeType = { @@ -1738,7 +1766,7 @@ /****************/ - static int + static PyInt RangeLength(PyObject *self) { /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */ @@ -1749,7 +1777,7 @@ } static PyObject * -RangeItem(PyObject *self, int n) +RangeItem(PyObject *self, PyInt n) { return RBItem(((RangeObject *)(self))->buf, n, ((RangeObject *)(self))->start, @@ -1757,15 +1785,15 @@ } static PyObject * -RangeSlice(PyObject *self, int lo, int hi) +RangeSlice(PyObject *self, PyInt lo, PyInt hi) { return RBSlice(((RangeObject *)(self))->buf, lo, hi, ((RangeObject *)(self))->start, ((RangeObject *)(self))->end); } - static int -RangeAssItem(PyObject *self, int n, PyObject *val) + static PyInt +RangeAssItem(PyObject *self, PyInt n, PyObject *val) { return RBAssItem(((RangeObject *)(self))->buf, n, val, ((RangeObject *)(self))->start, @@ -1773,8 +1801,8 @@ &((RangeObject *)(self))->end); } - static int -RangeAssSlice(PyObject *self, int lo, int hi, PyObject *val) + static PyInt +RangeAssSlice(PyObject *self, PyInt lo, PyInt hi, PyObject *val) { return RBAssSlice(((RangeObject *)(self))->buf, lo, hi, val, ((RangeObject *)(self))->start, @@ -1801,13 +1829,13 @@ BufListObject; static PySequenceMethods BufListAsSeq = { - (inquiry) BufListLength, /* sq_length, len(x) */ + (PyInquiry) BufListLength, /* sq_length, len(x) */ (binaryfunc) 0, /* sq_concat, x+y */ - (intargfunc) 0, /* sq_repeat, x*n */ - (intargfunc) BufListItem, /* sq_item, x[i] */ - (intintargfunc) 0, /* sq_slice, x[i:j] */ - (intobjargproc) 0, /* sq_ass_item, x[i]=v */ - (intintobjargproc) 0, /* sq_ass_slice, x[i:j]=v */ + (PyIntArgFunc) 0, /* sq_repeat, x*n */ + (PyIntArgFunc) BufListItem, /* sq_item, x[i] */ + (PyIntIntArgFunc) 0, /* sq_slice, x[i:j] */ + (PyIntObjArgProc) 0, /* sq_ass_item, x[i]=v */ + (PyIntIntObjArgProc) 0, /* sq_ass_slice, x[i:j]=v */ }; static PyTypeObject BufListType = { @@ -1837,7 +1865,7 @@ */ /*ARGSUSED*/ - static int + static PyInt BufListLength(PyObject *self) { buf_T *b = firstbuf; @@ -1854,7 +1882,7 @@ /*ARGSUSED*/ static PyObject * -BufListItem(PyObject *self, int n) +BufListItem(PyObject *self, PyInt n) { buf_T *b; @@ -2119,13 +2147,13 @@ WinListObject; static PySequenceMethods WinListAsSeq = { - (inquiry) WinListLength, /* sq_length, len(x) */ + (PyInquiry) WinListLength, /* sq_length, len(x) */ (binaryfunc) 0, /* sq_concat, x+y */ - (intargfunc) 0, /* sq_repeat, x*n */ - (intargfunc) WinListItem, /* sq_item, x[i] */ - (intintargfunc) 0, /* sq_slice, x[i:j] */ - (intobjargproc) 0, /* sq_ass_item, x[i]=v */ - (intintobjargproc) 0, /* sq_ass_slice, x[i:j]=v */ + (PyIntArgFunc) 0, /* sq_repeat, x*n */ + (PyIntArgFunc) WinListItem, /* sq_item, x[i] */ + (PyIntIntArgFunc) 0, /* sq_slice, x[i:j] */ + (PyIntObjArgProc) 0, /* sq_ass_item, x[i]=v */ + (PyIntIntObjArgProc) 0, /* sq_ass_slice, x[i:j]=v */ }; static PyTypeObject WinListType = { @@ -2154,7 +2182,7 @@ /* Window list object - Implementation */ /*ARGSUSED*/ - static int + static PyInt WinListLength(PyObject *self) { win_T *w = firstwin; @@ -2171,7 +2199,7 @@ /*ARGSUSED*/ static PyObject * -WinListItem(PyObject *self, int n) +WinListItem(PyObject *self, PyInt n) { win_T *w; @@ -2351,10 +2379,10 @@ * including, hi. The list is returned as a Python list of string objects. */ static PyObject * -GetBufferLineList(buf_T *buf, int lo, int hi) +GetBufferLineList(buf_T *buf, PyInt lo, PyInt hi) { - int i; - int n = hi - lo; + PyInt i; + PyInt n = hi - lo; PyObject *list = PyList_New(n); if (list == NULL) @@ -2517,7 +2545,7 @@ * is set to the change in the buffer length. */ static int -SetBufferLineList(buf_T *buf, int lo, int hi, PyObject *list, int *len_change) +SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, int *len_change) { /* First of all, we check the thpe of the supplied Python object. * There are three cases: @@ -2527,8 +2555,8 @@ */ if (list == Py_None || list == NULL) { - int i; - int n = hi - lo; + PyInt i; + PyInt n = hi - lo; buf_T *savebuf = curbuf; PyErr_Clear(); @@ -2564,9 +2592,9 @@ } else if (PyList_Check(list)) { - int i; - int new_len = PyList_Size(list); - int old_len = hi - lo; + PyInt i; + PyInt new_len = PyList_Size(list); + PyInt old_len = hi - lo; int extra = 0; /* lines added to text, can be negative */ char **array; buf_T *savebuf; @@ -2745,8 +2773,8 @@ } else if (PyList_Check(lines)) { - int i; - int size = PyList_Size(lines); + PyInt i; + PyInt size = PyList_Size(lines); char **array; buf_T *savebuf; @@ -2831,7 +2859,7 @@ LineToString(const char *str) { PyObject *result; - int len = strlen(str); + PyInt len = strlen(str); char *p; /* Allocate an Python string object, with uninitialised contents. We @@ -2871,8 +2899,8 @@ { const char *str; char *save; - int len; - int i; + PyInt len; + PyInt i; char *p; if (obj == NULL || !PyString_Check(obj)) diff -Naur vim71.orig/src/if_ruby.c vim71/src/if_ruby.c --- vim71.orig/src/if_ruby.c 2007-05-12 05:54:12.000000000 -0400 +++ vim71/src/if_ruby.c 2008-06-18 06:52:39.000000000 -0400 @@ -789,7 +789,7 @@ return get_buffer_line(curbuf, curwin->w_cursor.lnum); } -static VALUE set_current_line(VALUE str) +static VALUE set_current_line(VALUE self, VALUE str) { return set_buffer_line(curbuf, curwin->w_cursor.lnum, str); } diff -Naur vim71.orig/src/keymap.h vim71/src/keymap.h --- vim71.orig/src/keymap.h 2006-08-22 07:38:38.000000000 -0400 +++ vim71/src/keymap.h 2008-06-18 06:52:31.000000000 -0400 @@ -254,6 +254,8 @@ , KE_DROP /* DnD data is available */ , KE_CURSORHOLD /* CursorHold event */ , KE_NOP /* doesn't do something */ + , KE_FOCUSGAINED /* focus gained */ + , KE_FOCUSLOST /* focus lost */ }; /* @@ -445,6 +447,8 @@ #define K_CMDWIN TERMCAP2KEY(KS_EXTRA, KE_CMDWIN) #define K_DROP TERMCAP2KEY(KS_EXTRA, KE_DROP) +#define K_FOCUSGAINED TERMCAP2KEY(KS_EXTRA, KE_FOCUSGAINED) +#define K_FOCUSLOST TERMCAP2KEY(KS_EXTRA, KE_FOCUSLOST) #define K_CURSORHOLD TERMCAP2KEY(KS_EXTRA, KE_CURSORHOLD) diff -Naur vim71.orig/src/macros.h vim71/src/macros.h --- vim71.orig/src/macros.h 2007-05-07 15:38:22.000000000 -0400 +++ vim71/src/macros.h 2008-06-18 06:52:12.000000000 -0400 @@ -54,10 +54,12 @@ /* * toupper() and tolower() that use the current locale. - * On some systems toupper()/tolower() only work on lower/uppercase characters + * On some systems toupper()/tolower() only work on lower/uppercase + * characters, first use islower() or isupper() then. * Careful: Only call TOUPPER_LOC() and TOLOWER_LOC() with a character in the * range 0 - 255. toupper()/tolower() on some systems can't handle others. - * Note: for UTF-8 use utf_toupper() and utf_tolower(). + * Note: It is often better to use MB_TOLOWER() and MB_TOUPPER(), because many + * toupper() and tolower() implementations only work for ASCII. */ #ifdef MSWIN # define TOUPPER_LOC(c) toupper_tab[(c) & 255] diff -Naur vim71.orig/src/main.aap vim71/src/main.aap --- vim71.orig/src/main.aap 2007-05-07 15:46:43.000000000 -0400 +++ vim71/src/main.aap 2008-06-18 06:54:11.000000000 -0400 @@ -56,9 +56,17 @@ config {virtual} auto/config.h auto/config.aap : auto/configure.aap configure.aap config.arg config.h.in config.aap.in + # Use "uname -a" to detect the architecture of the system. + @ok, uname = redir_system('uname -a', 0) + @if string.find(uname, "i386") >= 0: + @ arch = "i386" + @else: + @ arch = "ppc" + :print Building for $arch system + config_args = `file2string("config.arg")` :sys CONFIG_STATUS=auto/config.status - ./configure.aap `file2string("config.arg")` - --with-mac-arch=ppc + ./configure.aap $config_args + --with-mac-arch=$arch --cache-file=auto/config.cache # Configure arguments: create an empty "config.arg" file when its missing @@ -433,11 +441,13 @@ :print >> $target char_u *all_lflags = (char_u *)"$linkcmd"; @if _no.get("COMPILEDBY"): who = $COMPILEDBY - where = '' + where = @else: :syseval whoami | :eval re.sub("\n", "", stdin) | :assign who :syseval hostname | :eval re.sub("\n", "", stdin) | :assign where + @who = string.replace(who, '"', '\\"') + @where = string.replace(where, '"', '\\"') :print >> $target char_u *compiled_user = (char_u *)"$who"; :print >> $target char_u *compiled_sys = (char_u *)"$where"; @@ -1167,7 +1177,7 @@ :symlink `os.getcwd()`/../runtime $RESDIR/vim/runtime # TODO: Create the vimtutor application. -gui_bundle {virtual}: $(RESDIR) bundle-dir bundle-executable bundle-info +gui_bundle {virtual}: $(RESDIR) bundle-dir bundle-executable bundle-info \ bundle-resource bundle-language bundle-dir {virtual}: $(APPDIR)/Contents $(VIMTARGET) @@ -1187,7 +1197,7 @@ :sys m4 $(M4FLAGSX) infplist.xml > $(APPDIR)/Contents/Info.plist bundle-resource {virtual}: bundle-dir bundle-rsrc - :copy {force} $(RSRC_DIR)/*.icns $(RESDIR) + :copy {force} $(RSRC_DIR)/*.icns $(RESDIR) ### Classic resources # Resource fork (in the form of a .rsrc file) for Classic Vim (Mac OS 9) diff -Naur vim71.orig/src/main.c vim71/src/main.c --- vim71.orig/src/main.c 2007-05-07 15:38:44.000000000 -0400 +++ vim71/src/main.c 2008-06-18 06:55:10.000000000 -0400 @@ -954,7 +954,8 @@ int cmdwin; /* TRUE when working in the command-line window */ int noexmode; /* TRUE when return on entering Ex mode */ { - oparg_T oa; /* operator arguments */ + oparg_T oa; /* operator arguments */ + int previous_got_int = FALSE; /* "got_int" was TRUE */ #if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD) /* Setup to catch a terminating error from the X server. Just ignore @@ -1015,12 +1016,32 @@ need_fileinfo = FALSE; } } - if (got_int && !global_busy) + + /* Reset "got_int" now that we got back to the main loop. Except when + * inside a ":g/pat/cmd" command, then the "got_int" needs to abort + * the ":g" command. + * For ":g/pat/vi" we reset "got_int" when used once. When used + * a second time we go back to Ex mode and abort the ":g" command. */ + if (got_int) { - if (!quit_more) - (void)vgetc(); /* flush all buffers */ - got_int = FALSE; + if (noexmode && global_busy && !exmode_active && previous_got_int) + { + /* Typed two CTRL-C in a row: go back to ex mode as if "Q" was + * used and keep "got_int" set, so that it aborts ":g". */ + exmode_active = EXMODE_NORMAL; + State = NORMAL; + } + else if (!global_busy || !exmode_active) + { + if (!quit_more) + (void)vgetc(); /* flush all buffers */ + got_int = FALSE; + } + previous_got_int = TRUE; } + else + previous_got_int = FALSE; + if (!exmode_active) msg_scroll = FALSE; quit_more = FALSE; @@ -1309,6 +1330,13 @@ #ifdef FEAT_NETBEANS_INTG netbeans_end(); #endif +#ifdef FEAT_CSCOPE + cs_end(); +#endif +#ifdef FEAT_EVAL + if (garbage_collect_at_exit) + garbage_collect(); +#endif mch_exit(exitval); } @@ -1360,8 +1388,7 @@ p = vim_getenv((char_u *)"VIMRUNTIME", &mustfree); if (p != NULL && *p != NUL) { - STRCPY(NameBuff, p); - STRCAT(NameBuff, "/lang"); + vim_snprintf((char *)NameBuff, MAXPATHL, "%s/lang", p); bindtextdomain(VIMPACKAGE, (char *)NameBuff); } if (mustfree) @@ -1730,7 +1757,8 @@ case 'F': /* "-F" start in Farsi mode: rl + fkmap set */ #ifdef FEAT_FKMAP - curwin->w_p_rl = p_fkmap = TRUE; + p_fkmap = TRUE; + set_option_value((char_u *)"rl", 1L, NULL, 0); #else mch_errmsg(_(e_nofarsi)); mch_exit(2); @@ -1747,7 +1775,8 @@ case 'H': /* "-H" start in Hebrew mode: rl + hkmap set */ #ifdef FEAT_RIGHTLEFT - curwin->w_p_rl = p_hkmap = TRUE; + p_hkmap = TRUE; + set_option_value((char_u *)"rl", 1L, NULL, 0); #else mch_errmsg(_(e_nohebrew)); mch_exit(2); @@ -3036,7 +3065,7 @@ main_msg(_("--remote-wait As --remote but wait for files to have been edited")); main_msg(_("--remote-wait-silent Same, don't complain if there is no server")); # ifdef FEAT_WINDOWS - main_msg(_("--remote-tab As --remote but open tab page for each file")); + main_msg(_("--remote-tab[-wait][-silent] As --remote but use tab page per file")); # endif main_msg(_("--remote-send \tSend to a Vim server and exit")); main_msg(_("--remote-expr \tEvaluate in a Vim server and print result")); @@ -3632,7 +3661,13 @@ mainerr_arg_missing((char_u *)filev[-1]); if (mch_dirname(cwd, MAXPATHL) != OK) return NULL; - if ((p = vim_strsave_escaped_ext(cwd, PATH_ESC_CHARS, '\\', TRUE)) == NULL) + if ((p = vim_strsave_escaped_ext(cwd, +#ifdef BACKSLASH_IN_FILENAME + "", /* rem_backslash() will tell what chars to escape */ +#else + PATH_ESC_CHARS, +#endif + '\\', TRUE)) == NULL) return NULL; ga_init2(&ga, 1, 100); ga_concat(&ga, (char_u *)":cd "); diff -Naur vim71.orig/src/mark.c vim71/src/mark.c --- vim71.orig/src/mark.c 2007-05-07 15:28:01.000000000 -0400 +++ vim71/src/mark.c 2008-06-18 06:55:40.000000000 -0400 @@ -79,6 +79,12 @@ return OK; } + if (c == '"') + { + curbuf->b_last_cursor = *pos; + return OK; + } + /* Allow setting '[ and '] for an autocommand that simulates reading a * file. */ if (c == '[') @@ -505,9 +511,24 @@ { /* * First expand "~/" in the file name to the home directory. - * Try to shorten the file name. + * Don't expand the whole name, it may contain other '~' chars. */ - expand_env(fm->fname, NameBuff, MAXPATHL); + if (fm->fname[0] == '~' && (fm->fname[1] == '/' +#ifdef BACKSLASH_IN_FILENAME + || fm->fname[1] == '\\' +#endif + )) + { + int len; + + expand_env((char_u *)"~/", NameBuff, MAXPATHL); + len = STRLEN(NameBuff); + vim_strncpy(NameBuff + len, fm->fname + 2, MAXPATHL - len - 1); + } + else + vim_strncpy(NameBuff, fm->fname, MAXPATHL - 1); + + /* Try to shorten the file name. */ mch_dirname(IObuff, IOSIZE); p = shorten_fname(NameBuff, IObuff); diff -Naur vim71.orig/src/mbyte.c vim71/src/mbyte.c --- vim71.orig/src/mbyte.c 2007-05-07 15:47:09.000000000 -0400 +++ vim71/src/mbyte.c 2008-06-18 06:56:57.000000000 -0400 @@ -360,6 +360,12 @@ {"ucs4be", IDX_UCS4}, {"ucs-4be", IDX_UCS4}, {"ucs4le", IDX_UCS4LE}, + {"utf32", IDX_UCS4}, + {"utf-32", IDX_UCS4}, + {"utf32be", IDX_UCS4}, + {"utf-32be", IDX_UCS4}, + {"utf32le", IDX_UCS4LE}, + {"utf-32le", IDX_UCS4LE}, {"932", IDX_CP932}, {"949", IDX_CP949}, {"936", IDX_CP936}, @@ -1310,20 +1316,26 @@ /* * mb_off2cells() function pointer. * Return number of display cells for char at ScreenLines[off]. - * Caller must make sure "off" and "off + 1" are valid! + * We make sure that the offset used is less than "max_off". */ /*ARGSUSED*/ int -latin_off2cells(off) +latin_off2cells(off, max_off) unsigned off; + unsigned max_off; { return 1; } int -dbcs_off2cells(off) +dbcs_off2cells(off, max_off) unsigned off; + unsigned max_off; { + /* never check beyond end of the line */ + if (off >= max_off) + return 1; + /* Number of cells is equal to number of bytes, except for euc-jp when * the first byte is 0x8e. */ if (enc_dbcs == DBCS_JPNU && ScreenLines[off] == 0x8e) @@ -1332,10 +1344,11 @@ } int -utf_off2cells(off) +utf_off2cells(off, max_off) unsigned off; + unsigned max_off; { - return ScreenLines[off + 1] == 0 ? 2 : 1; + return (off + 1 < max_off && ScreenLines[off + 1] == 0) ? 2 : 1; } /* @@ -1635,7 +1648,7 @@ * Get the length of UTF-8 byte sequence "p[size]". Does not include any * following composing characters. * Returns 1 for "". - * Returns 1 for an illegal byte sequence. + * Returns 1 for an illegal byte sequence (also in incomplete byte seq.). * Returns number > "size" for an incomplete byte sequence. */ int @@ -1645,13 +1658,14 @@ { int len; int i; + int m; if (*p == NUL) return 1; - len = utf8len_tab[*p]; + m = len = utf8len_tab[*p]; if (len > size) - return len; /* incomplete byte sequence. */ - for (i = 1; i < len; ++i) + m = size; /* incomplete byte sequence. */ + for (i = 1; i < m; ++i) if ((p[i] & 0xc0) != 0x80) return 1; return len; @@ -1959,8 +1973,10 @@ {0x205f, 0x205f, 0}, {0x2060, 0x27ff, 1}, /* punctuation and symbols */ {0x2070, 0x207f, 0x2070}, /* superscript */ - {0x2080, 0x208f, 0x2080}, /* subscript */ - {0x2983, 0x2998, 1}, + {0x2080, 0x2094, 0x2080}, /* subscript */ + {0x20a0, 0x27ff, 1}, /* all kinds of symbols */ + {0x2800, 0x28ff, 0x2800}, /* braille */ + {0x2900, 0x2998, 1}, /* arrows, brackets, etc. */ {0x29d8, 0x29db, 1}, {0x29fc, 0x29fd, 1}, {0x3000, 0x3000, 0}, /* ideographic space */ @@ -2320,7 +2336,7 @@ /* Single byte: first check normally, then with ignore case. */ if (s1[i] != s2[i]) { - cdiff = TOLOWER_LOC(s1[i]) - TOLOWER_LOC(s2[i]); + cdiff = MB_TOLOWER(s1[i]) - MB_TOLOWER(s2[i]); if (cdiff != 0) return cdiff; } @@ -2855,15 +2871,17 @@ buf[m++] = K_SPECIAL; n += 2; } + else if ((str[n] == K_SPECIAL # ifdef FEAT_GUI - else if (str[n] == CSI + || str[n] == CSI +# endif + ) && str[n + 1] == KS_EXTRA && str[n + 2] == (int)KE_CSI) { buf[m++] = CSI; n += 2; } -# endif else if (str[n] == K_SPECIAL # ifdef FEAT_GUI || str[n] == CSI @@ -2899,12 +2917,8 @@ if (composing_hangul) return TRUE; #endif - if (enc_dbcs != 0) - return dbcs_off2cells(LineOffset[row] + col) > 1; - if (enc_utf8) - return (col + 1 < Columns - && ScreenLines[LineOffset[row] + col + 1] == 0); - return FALSE; + return (*mb_off2cells)(LineOffset[row] + col, + LineOffset[row] + screen_Columns) > 1; } # if defined(FEAT_CLIPBOARD) || defined(FEAT_GUI) || defined(FEAT_RIGHTLEFT) \ @@ -5506,13 +5520,13 @@ preedit_caret_cb.callback = (XIMProc)preedit_caret_cbproc; preedit_done_cb.callback = (XIMProc)preedit_done_cbproc; preedit_attr - = XVaCreateNestedList (0, + = XVaCreateNestedList(0, XNPreeditStartCallback, &preedit_start_cb, XNPreeditDrawCallback, &preedit_draw_cb, XNPreeditCaretCallback, &preedit_caret_cb, XNPreeditDoneCallback, &preedit_done_cb, - 0); - XSetICValues (xxic, XNPreeditAttributes, preedit_attr, 0); + NULL); + XSetICValues(xxic, XNPreeditAttributes, preedit_attr, NULL); XFree(preedit_attr); } @@ -5522,7 +5536,8 @@ { #ifdef USE_X11R6_XIM /* don't change the input context when we call reset */ - XSetICValues(((GdkICPrivate*)ic)->xic, XNResetState, XIMPreserveState, 0); + XSetICValues(((GdkICPrivate *)ic)->xic, XNResetState, XIMPreserveState, + NULL); #endif } diff -Naur vim71.orig/src/memfile.c vim71/src/memfile.c --- vim71.orig/src/memfile.c 2007-05-11 13:50:12.000000000 -0400 +++ vim71/src/memfile.c 2008-06-18 06:56:39.000000000 -0400 @@ -1346,5 +1346,10 @@ mfp->mf_ffname = NULL; } else + { +#ifdef HAVE_SELINUX + mch_copy_sec(fname, mfp->mf_fname); +#endif mch_hide(mfp->mf_fname); /* try setting the 'hidden' flag */ + } } diff -Naur vim71.orig/src/message.c vim71/src/message.c --- vim71.orig/src/message.c 2007-05-07 15:31:59.000000000 -0400 +++ vim71/src/message.c 2008-06-18 06:53:52.000000000 -0400 @@ -828,7 +828,7 @@ _("Messages maintainer: Bram Moolenaar "), hl_attr(HLF_T)); - for (p = first_msg_hist; p != NULL; p = p->next) + for (p = first_msg_hist; p != NULL && !got_int; p = p->next) if (p->msg != NULL) msg_attr(p->msg, p->attr); @@ -944,6 +944,7 @@ c = K_IGNORE; } #endif + /* * Allow scrolling back in the messages. * Also accept scroll-down commands when messages fill the screen, @@ -1840,9 +1841,10 @@ char_u *sb_str = str; int sb_col = msg_col; int wrap; + int did_last_char; did_wait_return = FALSE; - while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen)) + while ((maxlen < 0 || (int)(s - str) < maxlen) && *s != NUL) { /* * We are at the end of the screen line when: @@ -1878,7 +1880,7 @@ /* output postponed text */ t_puts(&t_col, t_s, s, attr); - /* When no more prompt an no more room, truncate here */ + /* When no more prompt and no more room, truncate here */ if (msg_no_more && lines_left == 0) break; @@ -1909,7 +1911,10 @@ else #endif msg_screen_putchar(*s++, attr); + did_last_char = TRUE; } + else + did_last_char = FALSE; if (p_more) /* store text for scrolling back */ @@ -1927,7 +1932,8 @@ * If screen is completely filled and 'more' is set then wait * for a character. */ - --lines_left; + if (lines_left > 0) + --lines_left; if (p_more && lines_left == 0 && State != HITRETURN && !msg_no_more && !exmode_active) { @@ -1943,11 +1949,7 @@ /* When we displayed a char in last column need to check if there * is still more. */ - if (*s >= ' ' -#ifdef FEAT_RIGHTLEFT - && !cmdmsg_rl -#endif - ) + if (did_last_char) continue; } @@ -2234,7 +2236,7 @@ { msgchunk_T *mp; - /* Only show somethign if there is more than one line, otherwise it looks + /* Only show something if there is more than one line, otherwise it looks * weird, typing a command without output results in one line. */ mp = msg_sb_start(last_msgchunk); if (mp == NULL || mp->sb_prev == NULL) @@ -2622,7 +2624,7 @@ } } - if (scroll < 0 || (scroll == 0 && mp_last != NULL)) + if (scroll <= 0) { /* displayed the requested text, more prompt again */ screen_fill((int)Rows - 1, (int)Rows, 0, @@ -2848,6 +2850,15 @@ } else if (State == HITRETURN || State == SETWSIZE) { + if (msg_row == Rows - 1) + { + /* Avoid drawing the "hit-enter" prompt below the previous one, + * overwrite it. Esp. useful when regaining focus and a + * FocusGained autocmd exists but didn't draw anything. */ + msg_didout = FALSE; + msg_col = 0; + msg_clr_eos(); + } hit_return_msg(); msg_row = Rows - 1; } @@ -3456,11 +3467,11 @@ /* advance to next hotkey and set default hotkey */ #ifdef FEAT_MBYTE if (has_mbyte) - hotkp += (*mb_ptr2len)(hotkp); + hotkp += STRLEN(hotkp); else #endif ++hotkp; - (void)copy_char(r + 1, hotkp, TRUE); + hotkp[copy_char(r + 1, hotkp, TRUE)] = NUL; if (dfltbutton) --dfltbutton; @@ -3493,7 +3504,7 @@ *msgp++ = (dfltbutton == 1) ? ']' : ')'; /* redefine hotkey */ - (void)copy_char(r, hotkp, TRUE); + hotkp[copy_char(r, hotkp, TRUE)] = NUL; } } else @@ -3519,8 +3530,6 @@ *msgp++ = ':'; *msgp++ = ' '; *msgp = NUL; - mb_ptr_adv(hotkp); - *hotkp = NUL; } else { @@ -3555,8 +3564,9 @@ msgp = confirm_msg + 1 + STRLEN(message); hotkp = hotk; - /* define first default hotkey */ - (void)copy_char(buttons, hotkp, TRUE); + /* Define first default hotkey. Keep the hotkey string NUL + * terminated to avoid reading past the end. */ + hotkp[copy_char(buttons, hotkp, TRUE)] = NUL; /* Remember where the choices start, displaying starts here when * "hotkp" typed at the more prompt. */ diff -Naur vim71.orig/src/misc1.c vim71/src/misc1.c --- vim71.orig/src/misc1.c 2007-05-07 15:49:03.000000000 -0400 +++ vim71/src/misc1.c 2008-06-18 06:55:59.000000000 -0400 @@ -90,7 +90,7 @@ */ int set_indent(size, flags) - int size; + int size; /* measured in spaces */ int flags; { char_u *p; @@ -98,12 +98,14 @@ char_u *oldline; char_u *s; int todo; - int ind_len; + int ind_len; /* measured in characters */ int line_len; int doit = FALSE; - int ind_done; + int ind_done = 0; /* measured in spaces */ int tab_pad; int retval = FALSE; + int orig_char_len = -1; /* number of initial whitespace chars when + 'et' and 'pi' are both set */ /* * First check if there is anything to do and compute the number of @@ -116,8 +118,10 @@ /* Calculate the buffer size for the new indent, and check to see if it * isn't already set */ - /* if 'expandtab' isn't set: use TABs */ - if (!curbuf->b_p_et) + /* if 'expandtab' isn't set: use TABs; if both 'expandtab' and + * 'preserveindent' are set count the number of characters at the + * beginning of the line to be copied */ + if (!curbuf->b_p_et || (!(flags & SIN_INSERT) && curbuf->b_p_pi)) { /* If 'preserveindent' is set then reuse as much as possible of * the existing indent structure for the new indent */ @@ -148,9 +152,14 @@ ++p; } + /* Set initial number of whitespace chars to copy if we are + * preserving indent but expandtab is set */ + if (curbuf->b_p_et) + orig_char_len = ind_len; + /* Fill to next tabstop with a tab, if possible */ tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts); - if (todo >= tab_pad) + if (todo >= tab_pad && orig_char_len == -1) { doit = TRUE; todo -= tab_pad; @@ -193,13 +202,43 @@ else p = skipwhite(p); line_len = (int)STRLEN(p) + 1; - newline = alloc(ind_len + line_len); - if (newline == NULL) - return FALSE; + + /* If 'preserveindent' and 'expandtab' are both set keep the original + * characters and allocate accordingly. We will fill the rest with spaces + * after the if (!curbuf->b_p_et) below. */ + if (orig_char_len != -1) + { + newline = alloc(orig_char_len + size - ind_done + line_len); + if (newline == NULL) + return FALSE; + todo = size - ind_done; + ind_len = orig_char_len + todo; /* Set total length of indent in + * characters, which may have been + * undercounted until now */ + p = oldline; + s = newline; + while (orig_char_len > 0) + { + *s++ = *p++; + orig_char_len--; + } + + /* Skip over any additional white space (useful when newindent is less + * than old) */ + while (vim_iswhite(*p)) + ++p; + + } + else + { + todo = size; + newline = alloc(ind_len + line_len); + if (newline == NULL) + return FALSE; + s = newline; + } /* Put the characters in the new line. */ - s = newline; - todo = size; /* if 'expandtab' isn't set: use TABs */ if (!curbuf->b_p_et) { @@ -398,7 +437,8 @@ { regmatch.rmm_ic = FALSE; regmatch.rmm_maxcol = 0; - if (vim_regexec_multi(®match, curwin, curbuf, lnum, (colnr_T)0)) + if (vim_regexec_multi(®match, curwin, curbuf, lnum, + (colnr_T)0, NULL)) { pos.lnum = regmatch.endpos[0].lnum + lnum; pos.col = regmatch.endpos[0].col; @@ -553,7 +593,14 @@ replace_push(NUL); p = saved_line + curwin->w_cursor.col; while (*p != NUL) - replace_push(*p++); + { +#ifdef FEAT_MBYTE + if (has_mbyte) + p += replace_push_mb(p); + else +#endif + replace_push(*p++); + } saved_line[curwin->w_cursor.col] = NUL; } #endif @@ -1320,8 +1367,8 @@ newindent += (int)curbuf->b_p_sw; } #endif - /* Copy the indent only if expand tab is disabled */ - if (curbuf->b_p_ci && !curbuf->b_p_et) + /* Copy the indent */ + if (curbuf->b_p_ci) { (void)copy_indent(newindent, saved_line); @@ -1876,7 +1923,6 @@ int charlen; { int c = buf[0]; - int l, j; #endif int newlen; /* nr of bytes inserted */ int oldlen; /* nr of bytes deleted (0 when not replacing) */ @@ -1978,13 +2024,11 @@ for (i = 0; i < oldlen; ++i) { #ifdef FEAT_MBYTE - l = (*mb_ptr2len)(oldp + col + i) - 1; - for (j = l; j >= 0; --j) - replace_push(oldp[col + i + j]); - i += l; -#else - replace_push(oldp[col + i]); + if (has_mbyte) + i += replace_push_mb(oldp + col + i) - 1; + else #endif + replace_push(oldp[col + i]); } } @@ -2226,13 +2270,16 @@ /* * If the old line has been allocated the deletion can be done in the * existing line. Otherwise a new line has to be allocated + * Can't do this when using Netbeans, because we would need to invoke + * netbeans_removed(), which deallocates the line. Let ml_replace() take + * care of notifiying Netbeans. */ - was_alloced = ml_line_alloced(); /* check if oldp was allocated */ #ifdef FEAT_NETBEANS_INTG - if (was_alloced && usingNetbeans) - netbeans_removed(curbuf, lnum, col, count); - /* else is handled by ml_replace() */ + if (usingNetbeans) + was_alloced = FALSE; + else #endif + was_alloced = ml_line_alloced(); /* check if oldp was allocated */ if (was_alloced) newp = oldp; /* use same allocated memory */ else @@ -2982,7 +3029,7 @@ if (direct) r = get_keystroke(); else - r = safe_vgetc(); + r = plain_vgetc(); if (r == Ctrl_C || r == ESC) r = 'n'; msg_putchar(r); /* show what you typed */ @@ -3468,9 +3515,38 @@ #endif /* + * Call expand_env() and store the result in an allocated string. + * This is not very memory efficient, this expects the result to be freed + * again soon. + */ + char_u * +expand_env_save(src) + char_u *src; +{ + return expand_env_save_opt(src, FALSE); +} + +/* + * Idem, but when "one" is TRUE handle the string as one file name, only + * expand "~" at the start. + */ + char_u * +expand_env_save_opt(src, one) + char_u *src; + int one; +{ + char_u *p; + + p = alloc(MAXPATHL); + if (p != NULL) + expand_env_esc(src, p, MAXPATHL, FALSE, one, NULL); + return p; +} + +/* * Expand environment variable with path name. * "~/" is also expanded, using $HOME. For Unix "~user/" is expanded. - * Skips over "\ ", "\~" and "\$". + * Skips over "\ ", "\~" and "\$" (not for Win32 though). * If anything fails no expansion is done and dst equals src. */ void @@ -3479,15 +3555,16 @@ char_u *dst; /* where to put the result */ int dstlen; /* maximum length of the result */ { - expand_env_esc(src, dst, dstlen, FALSE, NULL); + expand_env_esc(src, dst, dstlen, FALSE, FALSE, NULL); } void -expand_env_esc(srcp, dst, dstlen, esc, startstr) +expand_env_esc(srcp, dst, dstlen, esc, one, startstr) char_u *srcp; /* input string e.g. "$HOME/vim.hlp" */ char_u *dst; /* where to put the result */ int dstlen; /* maximum length of the result */ int esc; /* escape spaces in expanded variables */ + int one; /* "srcp" is one file name */ char_u *startstr; /* start again after this (can be NULL) */ { char_u *src; @@ -3728,6 +3805,8 @@ { /* * Recognize the start of a new name, for '~'. + * Don't do this when "one" is TRUE, to avoid expanding "~" in + * ":edit foo ~ foo". */ at_start = FALSE; if (src[0] == '\\' && src[1] != NUL) @@ -3735,7 +3814,7 @@ *dst++ = *src++; --dstlen; } - else if (src[0] == ' ' || src[0] == ',') + else if ((src[0] == ' ' || src[0] == ',') && !one) at_start = TRUE; *dst++ = *src++; --dstlen; @@ -3902,7 +3981,7 @@ /* remove trailing path separator */ #ifndef MACOS_CLASSIC /* With MacOS path (with colons) the final colon is required */ - /* to avoid confusion between absoulute and relative path */ + /* to avoid confusion between absolute and relative path */ if (pend > p && after_pathsep(p, pend)) --pend; #endif @@ -4032,23 +4111,6 @@ } /* - * Call expand_env() and store the result in an allocated string. - * This is not very memory efficient, this expects the result to be freed - * again soon. - */ - char_u * -expand_env_save(src) - char_u *src; -{ - char_u *p; - - p = alloc(MAXPATHL); - if (p != NULL) - expand_env(src, p, MAXPATHL); - return p; -} - -/* * Our portable version of setenv. */ void @@ -4786,7 +4848,7 @@ static int cin_iswhileofdo __ARGS((char_u *, linenr_T, int)); static int cin_iswhileofdo_end __ARGS((int terminated, int ind_maxparen, int ind_maxcomment)); static int cin_isbreak __ARGS((char_u *)); -static int cin_is_cpp_baseclass __ARGS((char_u *line, colnr_T *col)); +static int cin_is_cpp_baseclass __ARGS((colnr_T *col)); static int get_baseclass_amount __ARGS((int col, int ind_maxparen, int ind_maxcomment, int ind_cpp_baseclass)); static int cin_ends_in __ARGS((char_u *, char_u *, char_u *)); static int cin_skip2pos __ARGS((pos_T *trypos)); @@ -5551,13 +5613,13 @@ * This is a lot of guessing. Watch out for "cond ? func() : foo". */ static int -cin_is_cpp_baseclass(line, col) - char_u *line; +cin_is_cpp_baseclass(col) colnr_T *col; /* return: column to align with */ { char_u *s; int class_or_struct, lookfor_ctor_init, cpp_base_class; linenr_T lnum = curwin->w_cursor.lnum; + char_u *line = ml_get_curline(); *col = 0; @@ -5585,7 +5647,8 @@ */ while (lnum > 1) { - s = skipwhite(ml_get(lnum - 1)); + line = ml_get(lnum - 1); + s = skipwhite(line); if (*s == '#' || *s == NUL) break; while (*s != NUL) @@ -5602,7 +5665,8 @@ --lnum; } - s = cin_skipcomment(ml_get(lnum)); + line = ml_get(lnum); + s = cin_skipcomment(line); for (;;) { if (*s == NUL) @@ -5610,7 +5674,10 @@ if (lnum == curwin->w_cursor.lnum) break; /* Continue in the cursor line. */ - s = cin_skipcomment(ml_get(++lnum)); + line = ml_get(++lnum); + s = cin_skipcomment(line); + if (*s == NUL) + continue; } if (s[0] == ':') @@ -5625,7 +5692,7 @@ else if (lookfor_ctor_init || class_or_struct) { /* we have something found, that looks like the start of - * cpp-base-class-declaration or contructor-initialization */ + * cpp-base-class-declaration or constructor-initialization */ cpp_base_class = TRUE; lookfor_ctor_init = class_or_struct = FALSE; *col = 0; @@ -6082,7 +6149,7 @@ pos_T our_paren_pos; char_u *start; int start_brace; -#define BRACE_IN_COL0 1 /* '{' is in comumn 0 */ +#define BRACE_IN_COL0 1 /* '{' is in column 0 */ #define BRACE_AT_START 2 /* '{' is at start of line */ #define BRACE_AT_END 3 /* '{' is at end of line */ linenr_T ourscope; @@ -6305,7 +6372,7 @@ if (curwin->w_cursor.lnum > 1) { /* If the start comment string matches in the previous - * line, use the indent of that line pluss offset. If + * line, use the indent of that line plus offset. If * the middle comment string matches in the previous * line, use the indent of that line. XXX */ look = skipwhite(ml_get(curwin->w_cursor.lnum - 1)); @@ -6827,6 +6894,7 @@ if (trypos != NULL) { curwin->w_cursor.lnum = trypos->lnum + 1; + curwin->w_cursor.col = 0; continue; } @@ -6887,6 +6955,7 @@ if (trypos != NULL) { curwin->w_cursor.lnum = trypos->lnum + 1; + curwin->w_cursor.col = 0; continue; } } @@ -6924,6 +6993,7 @@ if ((trypos = find_start_comment(ind_maxcomment)) != NULL) { curwin->w_cursor.lnum = trypos->lnum + 1; + curwin->w_cursor.col = 0; continue; } @@ -7047,7 +7117,10 @@ { if (find_last_paren(l, '{', '}') && (trypos = find_start_brace(ind_maxcomment)) != NULL) + { curwin->w_cursor.lnum = trypos->lnum + 1; + curwin->w_cursor.col = 0; + } continue; } @@ -7079,7 +7152,7 @@ n = FALSE; if (lookfor != LOOKFOR_TERM && ind_cpp_baseclass > 0) { - n = cin_is_cpp_baseclass(l, &col); + n = cin_is_cpp_baseclass(&col); l = ml_get_curline(); } if (n) @@ -7163,11 +7236,12 @@ * case xx: if ( asdf && * asdf) */ - curwin->w_cursor.lnum = trypos->lnum; + curwin->w_cursor = *trypos; l = ml_get_curline(); if (cin_iscase(l) || cin_isscopedecl(l)) { ++curwin->w_cursor.lnum; + curwin->w_cursor.col = 0; continue; } } @@ -7187,6 +7261,7 @@ if (*l == NUL || l[STRLEN(l) - 1] != '\\') break; --curwin->w_cursor.lnum; + curwin->w_cursor.col = 0; } } @@ -7520,11 +7595,12 @@ * case xx: if ( asdf && * asdf) */ - curwin->w_cursor.lnum = trypos->lnum; + curwin->w_cursor = *trypos; l = ml_get_curline(); if (cin_iscase(l) || cin_isscopedecl(l)) { ++curwin->w_cursor.lnum; + curwin->w_cursor.col = 0; continue; } } @@ -7585,13 +7661,14 @@ && (trypos = find_start_brace(ind_maxcomment)) != NULL) /* XXX */ { - curwin->w_cursor.lnum = trypos->lnum; + curwin->w_cursor = *trypos; /* if not "else {" check for terminated again */ /* but skip block for "} else {" */ l = cin_skipcomment(ml_get_curline()); if (*l == '}' || !cin_iselse(l)) goto term_again; ++curwin->w_cursor.lnum; + curwin->w_cursor.col = 0; } } } @@ -7660,6 +7737,7 @@ if ((trypos = find_start_comment(ind_maxcomment)) != NULL) { curwin->w_cursor.lnum = trypos->lnum + 1; + curwin->w_cursor.col = 0; continue; } @@ -7670,7 +7748,7 @@ n = FALSE; if (ind_cpp_baseclass != 0 && theline[0] != '{') { - n = cin_is_cpp_baseclass(l, &col); + n = cin_is_cpp_baseclass(&col); l = ml_get_curline(); } if (n) @@ -7710,7 +7788,7 @@ if (find_last_paren(l, '(', ')') && (trypos = find_match_paren(ind_maxparen, ind_maxcomment)) != NULL) - curwin->w_cursor.lnum = trypos->lnum; + curwin->w_cursor = *trypos; /* For a line ending in ',' that is a continuation line go * back to the first line with a backslash: @@ -7724,6 +7802,7 @@ if (*l == NUL || l[STRLEN(l) - 1] != '\\') break; --curwin->w_cursor.lnum; + curwin->w_cursor.col = 0; } amount = get_indent(); /* XXX */ @@ -7797,7 +7876,7 @@ if ((trypos = find_match_paren(ind_maxparen, ind_maxcomment)) != NULL) - curwin->w_cursor.lnum = trypos->lnum; + curwin->w_cursor = *trypos; amount = get_indent(); /* XXX */ break; } @@ -8158,7 +8237,7 @@ if (*that && *that != ';') /* not a comment line */ { - /* test *that != '(' to accomodate first let/do + /* test *that != '(' to accommodate first let/do * argument if it is more than one line */ if (!vi_lisp && *that != '(' && *that != '[') firsttry++; @@ -8596,7 +8675,7 @@ for (p = buf + wildoff; p < s; ++p) if (rem_backslash(p)) { - STRCPY(p, p + 1); + mch_memmove(p, p + 1, STRLEN(p)); --e; --s; } @@ -8897,7 +8976,7 @@ for (p = buf + wildoff; p < s; ++p) if (rem_backslash(p)) { - STRCPY(p, p + 1); + mch_memmove(p, p + 1, STRLEN(p)); --e; --s; } @@ -9096,7 +9175,7 @@ */ if (vim_strpbrk(p, (char_u *)"$~") != NULL) { - p = expand_env_save(p); + p = expand_env_save_opt(p, TRUE); if (p == NULL) p = pat[i]; #ifdef UNIX diff -Naur vim71.orig/src/misc2.c vim71/src/misc2.c --- vim71.orig/src/misc2.c 2007-05-07 15:49:26.000000000 -0400 +++ vim71/src/misc2.c 2008-06-18 06:56:31.000000000 -0400 @@ -507,12 +507,17 @@ curwin->w_cursor.col = 0; else if (curwin->w_cursor.col >= len) { - /* Allow cursor past end-of-line in Insert mode, restarting Insert - * mode or when in Visual mode and 'selection' isn't "old" */ + /* Allow cursor past end-of-line when: + * - in Insert mode or restarting Insert mode + * - in Visual mode and 'selection' isn't "old" + * - 'virtualedit' is set */ if ((State & INSERT) || restart_edit #ifdef FEAT_VISUAL || (VIsual_active && *p_sel != 'o') #endif +#ifdef FEAT_VIRTUALEDIT + || (ve_flags & VE_ONEMORE) +#endif || virtual_active()) curwin->w_cursor.col = len; else @@ -746,7 +751,7 @@ #endif /* - * Note: if unsinged is 16 bits we can only allocate up to 64K with alloc(). + * Note: if unsigned is 16 bits we can only allocate up to 64K with alloc(). * Use lalloc for larger blocks. */ char_u * @@ -964,7 +969,6 @@ { buf_T *buf, *nextbuf; static int entered = FALSE; - win_T *win; /* When we cause a crash here it is caught and Vim tries to exit cleanly. * Don't try freeing everything again. */ @@ -972,15 +976,17 @@ return; entered = TRUE; - ++autocmd_block; /* don't want to trigger autocommands here */ +# ifdef FEAT_AUTOCMD + block_autocmds(); /* don't want to trigger autocommands here */ +# endif -#ifdef FEAT_WINDOWS +# ifdef FEAT_WINDOWS /* close all tabs and windows */ if (first_tabpage->tp_next != NULL) do_cmdline_cmd((char_u *)"tabonly!"); if (firstwin != lastwin) do_cmdline_cmd((char_u *)"only!"); -#endif +# endif # if defined(FEAT_SPELL) /* Free all spell info. */ @@ -1031,27 +1037,41 @@ free_regexp_stuff(); free_tag_stuff(); free_cd_dir(); +# ifdef FEAT_EVAL set_expr_line(NULL); +# endif +# ifdef FEAT_DIFF diff_clear(curtab); +# endif clear_sb_text(); /* free any scrollback text */ /* Free some global vars. */ vim_free(username); +# ifdef FEAT_CLIPBOARD vim_free(clip_exclude_prog); +# endif vim_free(last_cmdline); +# ifdef FEAT_CMDHIST vim_free(new_last_cmdline); +# endif set_keep_msg(NULL, 0); vim_free(ff_expand_buffer); /* Clear cmdline history. */ p_hi = 0; +# ifdef FEAT_CMDHIST init_history(); +# endif #ifdef FEAT_QUICKFIX - qf_free_all(NULL); - /* Free all location lists */ - FOR_ALL_WINDOWS(win) - qf_free_all(win); + { + win_T *win; + + qf_free_all(NULL); + /* Free all location lists */ + FOR_ALL_WINDOWS(win) + qf_free_all(win); + } #endif /* Close all script inputs. */ @@ -1062,7 +1082,11 @@ win_free_all(); #endif - /* Free all buffers. */ + /* Free all buffers. Reset 'autochdir' to avoid accessing things that + * were freed already. */ +#ifdef FEAT_AUTOCHDIR + p_acd = FALSE; +#endif for (buf = firstbuf; buf != NULL; ) { nextbuf = buf->b_next; @@ -3757,9 +3781,9 @@ char_u ffs_filearray_cur; /* needed for partly handled dirs */ /* to store status of partly handled directories - * 0: we work the on this directory for the first time + * 0: we work on this directory for the first time * 1: this directory was partly searched in an earlier step - */ + */ int ffs_stage; /* How deep are we in the directory tree? @@ -3828,6 +3852,7 @@ * Set the default maximum depth. */ #define FF_MAX_STAR_STAR_EXPAND ((char_u)30) + /* * The search context: * ffsc_stack_ptr: the stack for the dirs to search @@ -3842,7 +3867,7 @@ * ffsc_wc_path: the part of the given path containing wildcards * ffsc_level: how many levels of dirs to search downwards * ffsc_stopdirs_v: array of stop directories for upward search - * ffsc_need_dir: TRUE if we search for a directory + * ffsc_find_what: FINDFILE_BOTH, FINDFILE_DIR or FINDFILE_FILE */ typedef struct ff_search_ctx_T { @@ -3859,11 +3884,9 @@ int ffsc_level; char_u **ffsc_stopdirs_v; #endif - int ffsc_need_dir; + int ffsc_find_what; } ff_search_ctx_T; -static ff_search_ctx_T *ff_search_ctx = NULL; - /* locally needed functions */ #ifdef FEAT_PATH_EXTRA static int ff_check_visited __ARGS((ff_visited_T **, char_u *, char_u *)); @@ -3877,10 +3900,10 @@ static int ff_wc_equal __ARGS((char_u *s1, char_u *s2)); #endif -static void ff_push __ARGS((ff_stack_T *)); -static ff_stack_T * ff_pop __ARGS((void)); -static void ff_clear __ARGS((void)); -static void ff_free_stack_element __ARGS((ff_stack_T *)); +static void ff_push __ARGS((ff_search_ctx_T *search_ctx, ff_stack_T *stack_ptr)); +static ff_stack_T *ff_pop __ARGS((ff_search_ctx_T *search_ctx)); +static void ff_clear __ARGS((ff_search_ctx_T *search_ctx)); +static void ff_free_stack_element __ARGS((ff_stack_T *stack_ptr)); #ifdef FEAT_PATH_EXTRA static ff_stack_T *ff_create_stack_element __ARGS((char_u *, char_u *, int, int)); #else @@ -3941,6 +3964,9 @@ * not related to restricts given to the '**' wildcard. If 'level' is 100 * and you use '**200' vim_findfile() will stop after 100 levels. * + * 'filename' cannot contain wildcards! It is used as-is, no backslashes to + * escape special characters. + * * If 'stopdirs' is not NULL and nothing is found downward, the search is * restarted on the next higher directory level. This is repeated until the * start-directory of a search is contained in 'stopdirs'. 'stopdirs' has the @@ -3960,74 +3986,74 @@ * The list of visited files/dirs can also be cleared with the function * vim_findfile_free_visited(). * - * Set the parameter 'need_dir' to TRUE if you want to search for a directory - * instead of a file. + * Set the parameter 'find_what' to FINDFILE_DIR if you want to search for + * directories only, FINDFILE_FILE for files only, FINDFILE_BOTH for both. * * A search context returned by a previous call to vim_findfile_init() can be - * passed in the parameter 'search_ctx'. This context is than reused and - * reinitialized with the new parameters. The list of already viseted + * passed in the parameter "search_ctx_arg". This context is reused and + * reinitialized with the new parameters. The list of already visited * directories from this context is only deleted if the parameter - * 'free_visited' is true. Be aware that the passed search_context is freed if - * the reinitialization fails. + * "free_visited" is true. Be aware that the passed "search_ctx_arg" is freed + * if the reinitialization fails. * - * If you don't have a search context from a previous call 'search_ctx' must be - * NULL. + * If you don't have a search context from a previous call "search_ctx_arg" + * must be NULL. * * This function silently ignores a few errors, vim_findfile() will have * limited functionality then. */ /*ARGSUSED*/ void * -vim_findfile_init(path, filename, stopdirs, level, free_visited, need_dir, - search_ctx, tagfile, rel_fname) +vim_findfile_init(path, filename, stopdirs, level, free_visited, find_what, + search_ctx_arg, tagfile, rel_fname) char_u *path; char_u *filename; char_u *stopdirs; int level; int free_visited; - int need_dir; - void *search_ctx; + int find_what; + void *search_ctx_arg; int tagfile; char_u *rel_fname; /* file name to use for "." */ { #ifdef FEAT_PATH_EXTRA - char_u *wc_part; + char_u *wc_part; #endif - ff_stack_T *sptr; + ff_stack_T *sptr; + ff_search_ctx_T *search_ctx; /* If a search context is given by the caller, reuse it, else allocate a * new one. */ - if (search_ctx != NULL) - ff_search_ctx = search_ctx; + if (search_ctx_arg != NULL) + search_ctx = search_ctx_arg; else { - ff_search_ctx = (ff_search_ctx_T*)alloc( - (unsigned)sizeof(ff_search_ctx_T)); - if (ff_search_ctx == NULL) + search_ctx = (ff_search_ctx_T*)alloc((unsigned)sizeof(ff_search_ctx_T)); + if (search_ctx == NULL) goto error_return; - memset(ff_search_ctx, 0, sizeof(ff_search_ctx_T)); + memset(search_ctx, 0, sizeof(ff_search_ctx_T)); } + search_ctx->ffsc_find_what = find_what; /* clear the search context, but NOT the visited lists */ - ff_clear(); + ff_clear(search_ctx); /* clear visited list if wanted */ if (free_visited == TRUE) - vim_findfile_free_visited(ff_search_ctx); + vim_findfile_free_visited(search_ctx); else { /* Reuse old visited lists. Get the visited list for the given * filename. If no list for the current filename exists, creates a new - * one. - */ - ff_search_ctx->ffsc_visited_list = ff_get_visited_list(filename, - &ff_search_ctx->ffsc_visited_lists_list); - if (ff_search_ctx->ffsc_visited_list == NULL) + * one. */ + search_ctx->ffsc_visited_list = ff_get_visited_list(filename, + &search_ctx->ffsc_visited_lists_list); + if (search_ctx->ffsc_visited_list == NULL) goto error_return; - ff_search_ctx->ffsc_dir_visited_list = ff_get_visited_list(filename, - &ff_search_ctx->ffsc_dir_visited_lists_list); - if (ff_search_ctx->ffsc_dir_visited_list == NULL) + search_ctx->ffsc_dir_visited_list = ff_get_visited_list(filename, + &search_ctx->ffsc_dir_visited_lists_list); + if (search_ctx->ffsc_dir_visited_list == NULL) goto error_return; } @@ -4051,12 +4077,11 @@ { /* Make the start dir an absolute path name. */ vim_strncpy(ff_expand_buffer, rel_fname, len); - ff_search_ctx->ffsc_start_dir = FullName_save(ff_expand_buffer, - FALSE); + search_ctx->ffsc_start_dir = FullName_save(ff_expand_buffer, FALSE); } else - ff_search_ctx->ffsc_start_dir = vim_strnsave(rel_fname, len); - if (ff_search_ctx->ffsc_start_dir == NULL) + search_ctx->ffsc_start_dir = vim_strnsave(rel_fname, len); + if (search_ctx->ffsc_start_dir == NULL) goto error_return; if (*++path != NUL) ++path; @@ -4081,8 +4106,8 @@ if (mch_dirname(ff_expand_buffer, MAXPATHL) == FAIL) goto error_return; - ff_search_ctx->ffsc_start_dir = vim_strsave(ff_expand_buffer); - if (ff_search_ctx->ffsc_start_dir == NULL) + search_ctx->ffsc_start_dir = vim_strsave(ff_expand_buffer); + if (search_ctx->ffsc_start_dir == NULL) goto error_return; #ifdef BACKSLASH_IN_FILENAME @@ -4090,8 +4115,8 @@ * directory (but not for "//machine/dir"). Only use the drive name. */ if ((*path == '/' || *path == '\\') && path[1] != path[0] - && ff_search_ctx->ffsc_start_dir[1] == ':') - ff_search_ctx->ffsc_start_dir[2] = NUL; + && search_ctx->ffsc_start_dir[1] == ':') + search_ctx->ffsc_start_dir[2] = NUL; #endif } @@ -4101,7 +4126,7 @@ * If this fails (mem allocation), there is no upward search at all or a * stop directory is not recognized -> continue silently. * If stopdirs just contains a ";" or is empty, - * ff_search_ctx->ffsc_stopdirs_v will only contain a NULL pointer. This + * search_ctx->ffsc_stopdirs_v will only contain a NULL pointer. This * is handled as unlimited upward search. See function * ff_path_in_stoplist() for details. */ @@ -4114,10 +4139,10 @@ walker++; dircount = 1; - ff_search_ctx->ffsc_stopdirs_v = - (char_u **)alloc((unsigned)sizeof(char_u *)); + search_ctx->ffsc_stopdirs_v = + (char_u **)alloc((unsigned)sizeof(char_u *)); - if (ff_search_ctx->ffsc_stopdirs_v != NULL) + if (search_ctx->ffsc_stopdirs_v != NULL) { do { @@ -4125,37 +4150,37 @@ void *ptr; helper = walker; - ptr = vim_realloc(ff_search_ctx->ffsc_stopdirs_v, + ptr = vim_realloc(search_ctx->ffsc_stopdirs_v, (dircount + 1) * sizeof(char_u *)); if (ptr) - ff_search_ctx->ffsc_stopdirs_v = ptr; + search_ctx->ffsc_stopdirs_v = ptr; else /* ignore, keep what we have and continue */ break; walker = vim_strchr(walker, ';'); if (walker) { - ff_search_ctx->ffsc_stopdirs_v[dircount-1] = - vim_strnsave(helper, (int)(walker - helper)); + search_ctx->ffsc_stopdirs_v[dircount-1] = + vim_strnsave(helper, (int)(walker - helper)); walker++; } else /* this might be "", which means ascent till top * of directory tree. */ - ff_search_ctx->ffsc_stopdirs_v[dircount-1] = - vim_strsave(helper); + search_ctx->ffsc_stopdirs_v[dircount-1] = + vim_strsave(helper); dircount++; } while (walker != NULL); - ff_search_ctx->ffsc_stopdirs_v[dircount-1] = NULL; + search_ctx->ffsc_stopdirs_v[dircount-1] = NULL; } } #endif #ifdef FEAT_PATH_EXTRA - ff_search_ctx->ffsc_level = level; + search_ctx->ffsc_level = level; /* split into: * -fix path @@ -4169,8 +4194,7 @@ char *errpt; /* save the fix part of the path */ - ff_search_ctx->ffsc_fix_path = vim_strnsave(path, - (int)(wc_part - path)); + search_ctx->ffsc_fix_path = vim_strnsave(path, (int)(wc_part - path)); /* * copy wc_path and add restricts to the '**' wildcard. @@ -4209,47 +4233,47 @@ ff_expand_buffer[len++] = *wc_part++; } ff_expand_buffer[len] = NUL; - ff_search_ctx->ffsc_wc_path = vim_strsave(ff_expand_buffer); + search_ctx->ffsc_wc_path = vim_strsave(ff_expand_buffer); - if (ff_search_ctx->ffsc_wc_path == NULL) + if (search_ctx->ffsc_wc_path == NULL) goto error_return; } else #endif - ff_search_ctx->ffsc_fix_path = vim_strsave(path); + search_ctx->ffsc_fix_path = vim_strsave(path); - if (ff_search_ctx->ffsc_start_dir == NULL) + if (search_ctx->ffsc_start_dir == NULL) { /* store the fix part as startdir. * This is needed if the parameter path is fully qualified. */ - ff_search_ctx->ffsc_start_dir = vim_strsave(ff_search_ctx->ffsc_fix_path); - if (ff_search_ctx->ffsc_start_dir) - ff_search_ctx->ffsc_fix_path[0] = NUL; + search_ctx->ffsc_start_dir = vim_strsave(search_ctx->ffsc_fix_path); + if (search_ctx->ffsc_start_dir) + search_ctx->ffsc_fix_path[0] = NUL; } /* create an absolute path */ - STRCPY(ff_expand_buffer, ff_search_ctx->ffsc_start_dir); + STRCPY(ff_expand_buffer, search_ctx->ffsc_start_dir); add_pathsep(ff_expand_buffer); - STRCAT(ff_expand_buffer, ff_search_ctx->ffsc_fix_path); + STRCAT(ff_expand_buffer, search_ctx->ffsc_fix_path); add_pathsep(ff_expand_buffer); sptr = ff_create_stack_element(ff_expand_buffer, #ifdef FEAT_PATH_EXTRA - ff_search_ctx->ffsc_wc_path, + search_ctx->ffsc_wc_path, #endif level, 0); if (sptr == NULL) goto error_return; - ff_push(sptr); + ff_push(search_ctx, sptr); - ff_search_ctx->ffsc_file_to_search = vim_strsave(filename); - if (ff_search_ctx->ffsc_file_to_search == NULL) + search_ctx->ffsc_file_to_search = vim_strsave(filename); + if (search_ctx->ffsc_file_to_search == NULL) goto error_return; - return ff_search_ctx; + return search_ctx; error_return: /* @@ -4257,7 +4281,7 @@ * Even when the caller gave us a (perhaps valid) context we free it here, * as we might have already destroyed it. */ - vim_findfile_cleanup(ff_search_ctx); + vim_findfile_cleanup(search_ctx); return NULL; } @@ -4294,7 +4318,9 @@ } #endif -/* Clean up the given search context. Can handle a NULL pointer */ +/* + * Clean up the given search context. Can handle a NULL pointer. + */ void vim_findfile_cleanup(ctx) void *ctx; @@ -4302,12 +4328,9 @@ if (ctx == NULL) return; - ff_search_ctx = ctx; - vim_findfile_free_visited(ctx); - ff_clear(); + ff_clear(ctx); vim_free(ctx); - ff_search_ctx = NULL; } /* @@ -4323,15 +4346,15 @@ * top of the list). */ char_u * -vim_findfile(search_ctx) - void *search_ctx; +vim_findfile(search_ctx_arg) + void *search_ctx_arg; { char_u *file_path; #ifdef FEAT_PATH_EXTRA char_u *rest_of_wildcards; char_u *path_end = NULL; #endif - ff_stack_T *ctx; + ff_stack_T *stackp; #if defined(FEAT_SEARCHPATH) || defined(FEAT_PATH_EXTRA) int len; #endif @@ -4340,11 +4363,12 @@ #ifdef FEAT_SEARCHPATH char_u *suf; #endif + ff_search_ctx_T *search_ctx; - if (search_ctx == NULL) + if (search_ctx_arg == NULL) return NULL; - ff_search_ctx = (ff_search_ctx_T*)search_ctx; + search_ctx = (ff_search_ctx_T *)search_ctx_arg; /* * filepath is used as buffer for various actions and as the storage to @@ -4355,8 +4379,9 @@ #ifdef FEAT_PATH_EXTRA /* store the end of the start dir -- needed for upward search */ - if (ff_search_ctx->ffsc_start_dir != NULL) - path_end = &ff_search_ctx->ffsc_start_dir[STRLEN(ff_search_ctx->ffsc_start_dir)]; + if (search_ctx->ffsc_start_dir != NULL) + path_end = &search_ctx->ffsc_start_dir[ + STRLEN(search_ctx->ffsc_start_dir)]; #endif #ifdef FEAT_PATH_EXTRA @@ -4373,8 +4398,8 @@ break; /* get directory to work on from stack */ - ctx = ff_pop(); - if (ctx == NULL) + stackp = ff_pop(search_ctx); + if (stackp == NULL) break; /* @@ -4394,14 +4419,14 @@ * /etc/rc.d/init.d is linked to /etc/rc.d -> endless loop) * * This check is only needed for directories we work on for the - * first time (hence ctx->ff_filearray == NULL) + * first time (hence stackp->ff_filearray == NULL) */ - if (ctx->ffs_filearray == NULL - && ff_check_visited(&ff_search_ctx->ffsc_dir_visited_list + if (stackp->ffs_filearray == NULL + && ff_check_visited(&search_ctx->ffsc_dir_visited_list ->ffvl_visited_list, - ctx->ffs_fix_path + stackp->ffs_fix_path #ifdef FEAT_PATH_EXTRA - , ctx->ffs_wc_path + , stackp->ffs_wc_path #endif ) == FAIL) { @@ -4410,13 +4435,13 @@ { verbose_enter_scroll(); smsg((char_u *)"Already Searched: %s (%s)", - ctx->ffs_fix_path, ctx->ffs_wc_path); + stackp->ffs_fix_path, stackp->ffs_wc_path); /* don't overwrite this either */ msg_puts((char_u *)"\n"); verbose_leave_scroll(); } #endif - ff_free_stack_element(ctx); + ff_free_stack_element(stackp); continue; } #ifdef FF_VERBOSE @@ -4424,7 +4449,7 @@ { verbose_enter_scroll(); smsg((char_u *)"Searching: %s (%s)", - ctx->ffs_fix_path, ctx->ffs_wc_path); + stackp->ffs_fix_path, stackp->ffs_wc_path); /* don't overwrite this either */ msg_puts((char_u *)"\n"); verbose_leave_scroll(); @@ -4432,9 +4457,9 @@ #endif /* check depth */ - if (ctx->ffs_level <= 0) + if (stackp->ffs_level <= 0) { - ff_free_stack_element(ctx); + ff_free_stack_element(stackp); continue; } @@ -4446,7 +4471,7 @@ * and all possible expands are returned in one array. We use this * to handle the expansion of '**' into an empty string. */ - if (ctx->ffs_filearray == NULL) + if (stackp->ffs_filearray == NULL) { char_u *dirptrs[2]; @@ -4457,19 +4482,19 @@ dirptrs[1] = NULL; /* if we have a start dir copy it in */ - if (!vim_isAbsName(ctx->ffs_fix_path) - && ff_search_ctx->ffsc_start_dir) + if (!vim_isAbsName(stackp->ffs_fix_path) + && search_ctx->ffsc_start_dir) { - STRCPY(file_path, ff_search_ctx->ffsc_start_dir); + STRCPY(file_path, search_ctx->ffsc_start_dir); add_pathsep(file_path); } /* append the fix part of the search path */ - STRCAT(file_path, ctx->ffs_fix_path); + STRCAT(file_path, stackp->ffs_fix_path); add_pathsep(file_path); #ifdef FEAT_PATH_EXTRA - rest_of_wildcards = ctx->ffs_wc_path; + rest_of_wildcards = stackp->ffs_wc_path; if (*rest_of_wildcards != NUL) { len = (int)STRLEN(file_path); @@ -4496,11 +4521,11 @@ else rest_of_wildcards += 3; - if (ctx->ffs_star_star_empty == 0) + if (stackp->ffs_star_star_empty == 0) { /* if not done before, expand '**' to empty */ - ctx->ffs_star_star_empty = 1; - dirptrs[1] = ctx->ffs_fix_path; + stackp->ffs_star_star_empty = 1; + dirptrs[1] = stackp->ffs_fix_path; } } @@ -4527,30 +4552,31 @@ */ if (path_with_url(dirptrs[0])) { - ctx->ffs_filearray = (char_u **) + stackp->ffs_filearray = (char_u **) alloc((unsigned)sizeof(char *)); - if (ctx->ffs_filearray != NULL - && (ctx->ffs_filearray[0] + if (stackp->ffs_filearray != NULL + && (stackp->ffs_filearray[0] = vim_strsave(dirptrs[0])) != NULL) - ctx->ffs_filearray_size = 1; + stackp->ffs_filearray_size = 1; else - ctx->ffs_filearray_size = 0; + stackp->ffs_filearray_size = 0; } else expand_wildcards((dirptrs[1] == NULL) ? 1 : 2, dirptrs, - &ctx->ffs_filearray_size, - &ctx->ffs_filearray, + &stackp->ffs_filearray_size, + &stackp->ffs_filearray, EW_DIR|EW_ADDSLASH|EW_SILENT); - ctx->ffs_filearray_cur = 0; - ctx->ffs_stage = 0; + stackp->ffs_filearray_cur = 0; + stackp->ffs_stage = 0; } #ifdef FEAT_PATH_EXTRA else - rest_of_wildcards = &ctx->ffs_wc_path[STRLEN(ctx->ffs_wc_path)]; + rest_of_wildcards = &stackp->ffs_wc_path[ + STRLEN(stackp->ffs_wc_path)]; #endif - if (ctx->ffs_stage == 0) + if (stackp->ffs_stage == 0) { /* this is the first time we work on this directory */ #ifdef FEAT_PATH_EXTRA @@ -4561,18 +4587,18 @@ * we don't have further wildcards to expand, so we have to * check for the final file now */ - for (i = ctx->ffs_filearray_cur; - i < ctx->ffs_filearray_size; ++i) + for (i = stackp->ffs_filearray_cur; + i < stackp->ffs_filearray_size; ++i) { - if (!path_with_url(ctx->ffs_filearray[i]) - && !mch_isdir(ctx->ffs_filearray[i])) + if (!path_with_url(stackp->ffs_filearray[i]) + && !mch_isdir(stackp->ffs_filearray[i])) continue; /* not a directory */ /* prepare the filename to be checked for existance * below */ - STRCPY(file_path, ctx->ffs_filearray[i]); + STRCPY(file_path, stackp->ffs_filearray[i]); add_pathsep(file_path); - STRCAT(file_path, ff_search_ctx->ffsc_file_to_search); + STRCAT(file_path, search_ctx->ffsc_file_to_search); /* * Try without extra suffix and then with suffixes @@ -4586,12 +4612,15 @@ { /* if file exists and we didn't already find it */ if ((path_with_url(file_path) - || (mch_getperm(file_path) >= 0 - && (!ff_search_ctx->ffsc_need_dir - || mch_isdir(file_path)))) + || (mch_getperm(file_path) >= 0 + && (search_ctx->ffsc_find_what + == FINDFILE_BOTH + || ((search_ctx->ffsc_find_what + == FINDFILE_DIR) + == mch_isdir(file_path))))) #ifndef FF_VERBOSE && (ff_check_visited( - &ff_search_ctx->ffsc_visited_list->ffvl_visited_list, + &search_ctx->ffsc_visited_list->ffvl_visited_list, file_path #ifdef FEAT_PATH_EXTRA , (char_u *)"" @@ -4602,7 +4631,7 @@ { #ifdef FF_VERBOSE if (ff_check_visited( - &ff_search_ctx->ffsc_visited_list->ffvl_visited_list, + &search_ctx->ffsc_visited_list->ffvl_visited_list, file_path #ifdef FEAT_PATH_EXTRA , (char_u *)"" @@ -4623,8 +4652,8 @@ #endif /* push dir to examine rest of subdirs later */ - ctx->ffs_filearray_cur = i + 1; - ff_push(ctx); + stackp->ffs_filearray_cur = i + 1; + ff_push(search_ctx, stackp); simplify_filename(file_path); if (mch_dirname(ff_expand_buffer, MAXPATHL) @@ -4666,19 +4695,22 @@ * still wildcards left, push the directories for further * search */ - for (i = ctx->ffs_filearray_cur; - i < ctx->ffs_filearray_size; ++i) + for (i = stackp->ffs_filearray_cur; + i < stackp->ffs_filearray_size; ++i) { - if (!mch_isdir(ctx->ffs_filearray[i])) + if (!mch_isdir(stackp->ffs_filearray[i])) continue; /* not a directory */ - ff_push(ff_create_stack_element(ctx->ffs_filearray[i], - rest_of_wildcards, ctx->ffs_level - 1, 0)); + ff_push(search_ctx, + ff_create_stack_element( + stackp->ffs_filearray[i], + rest_of_wildcards, + stackp->ffs_level - 1, 0)); } } #endif - ctx->ffs_filearray_cur = 0; - ctx->ffs_stage = 1; + stackp->ffs_filearray_cur = 0; + stackp->ffs_stage = 1; } #ifdef FEAT_PATH_EXTRA @@ -4686,23 +4718,25 @@ * if wildcards contains '**' we have to descent till we reach the * leaves of the directory tree. */ - if (STRNCMP(ctx->ffs_wc_path, "**", 2) == 0) + if (STRNCMP(stackp->ffs_wc_path, "**", 2) == 0) { - for (i = ctx->ffs_filearray_cur; - i < ctx->ffs_filearray_size; ++i) + for (i = stackp->ffs_filearray_cur; + i < stackp->ffs_filearray_size; ++i) { - if (fnamecmp(ctx->ffs_filearray[i], ctx->ffs_fix_path) == 0) + if (fnamecmp(stackp->ffs_filearray[i], + stackp->ffs_fix_path) == 0) continue; /* don't repush same directory */ - if (!mch_isdir(ctx->ffs_filearray[i])) + if (!mch_isdir(stackp->ffs_filearray[i])) continue; /* not a directory */ - ff_push(ff_create_stack_element(ctx->ffs_filearray[i], - ctx->ffs_wc_path, ctx->ffs_level - 1, 1)); + ff_push(search_ctx, + ff_create_stack_element(stackp->ffs_filearray[i], + stackp->ffs_wc_path, stackp->ffs_level - 1, 1)); } } #endif /* we are done with the current directory */ - ff_free_stack_element(ctx); + ff_free_stack_element(stackp); } @@ -4710,40 +4744,40 @@ /* If we reached this, we didn't find anything downwards. * Let's check if we should do an upward search. */ - if (ff_search_ctx->ffsc_start_dir - && ff_search_ctx->ffsc_stopdirs_v != NULL && !got_int) + if (search_ctx->ffsc_start_dir + && search_ctx->ffsc_stopdirs_v != NULL && !got_int) { ff_stack_T *sptr; /* is the last starting directory in the stop list? */ - if (ff_path_in_stoplist(ff_search_ctx->ffsc_start_dir, - (int)(path_end - ff_search_ctx->ffsc_start_dir), - ff_search_ctx->ffsc_stopdirs_v) == TRUE) + if (ff_path_in_stoplist(search_ctx->ffsc_start_dir, + (int)(path_end - search_ctx->ffsc_start_dir), + search_ctx->ffsc_stopdirs_v) == TRUE) break; /* cut of last dir */ - while (path_end > ff_search_ctx->ffsc_start_dir - && vim_ispathsep(*path_end)) + while (path_end > search_ctx->ffsc_start_dir + && vim_ispathsep(*path_end)) path_end--; - while (path_end > ff_search_ctx->ffsc_start_dir - && !vim_ispathsep(path_end[-1])) + while (path_end > search_ctx->ffsc_start_dir + && !vim_ispathsep(path_end[-1])) path_end--; *path_end = 0; path_end--; - if (*ff_search_ctx->ffsc_start_dir == 0) + if (*search_ctx->ffsc_start_dir == 0) break; - STRCPY(file_path, ff_search_ctx->ffsc_start_dir); + STRCPY(file_path, search_ctx->ffsc_start_dir); add_pathsep(file_path); - STRCAT(file_path, ff_search_ctx->ffsc_fix_path); + STRCAT(file_path, search_ctx->ffsc_fix_path); /* create a new stack entry */ sptr = ff_create_stack_element(file_path, - ff_search_ctx->ffsc_wc_path, ff_search_ctx->ffsc_level, 0); + search_ctx->ffsc_wc_path, search_ctx->ffsc_level, 0); if (sptr == NULL) break; - ff_push(sptr); + ff_push(search_ctx, sptr); } else break; @@ -4759,16 +4793,17 @@ * Can handle it if the passed search_context is NULL; */ void -vim_findfile_free_visited(search_ctx) - void *search_ctx; +vim_findfile_free_visited(search_ctx_arg) + void *search_ctx_arg; { - if (search_ctx == NULL) - return; + ff_search_ctx_T *search_ctx; - ff_search_ctx = (ff_search_ctx_T *)search_ctx; + if (search_ctx_arg == NULL) + return; - vim_findfile_free_visited_list(&ff_search_ctx->ffsc_visited_lists_list); - vim_findfile_free_visited_list(&ff_search_ctx->ffsc_dir_visited_lists_list); + search_ctx = (ff_search_ctx_T *)search_ctx_arg; + vim_findfile_free_visited_list(&search_ctx->ffsc_visited_lists_list); + vim_findfile_free_visited_list(&search_ctx->ffsc_dir_visited_lists_list); } static void @@ -5083,33 +5118,35 @@ } /* - * push a dir on the directory stack + * Push a dir on the directory stack. */ static void -ff_push(ctx) - ff_stack_T *ctx; +ff_push(search_ctx, stack_ptr) + ff_search_ctx_T *search_ctx; + ff_stack_T *stack_ptr; { /* check for NULL pointer, not to return an error to the user, but * to prevent a crash */ - if (ctx != NULL) + if (stack_ptr != NULL) { - ctx->ffs_prev = ff_search_ctx->ffsc_stack_ptr; - ff_search_ctx->ffsc_stack_ptr = ctx; + stack_ptr->ffs_prev = search_ctx->ffsc_stack_ptr; + search_ctx->ffsc_stack_ptr = stack_ptr; } } /* - * pop a dir from the directory stack - * returns NULL if stack is empty + * Pop a dir from the directory stack. + * Returns NULL if stack is empty. */ static ff_stack_T * -ff_pop() +ff_pop(search_ctx) + ff_search_ctx_T *search_ctx; { ff_stack_T *sptr; - sptr = ff_search_ctx->ffsc_stack_ptr; - if (ff_search_ctx->ffsc_stack_ptr != NULL) - ff_search_ctx->ffsc_stack_ptr = ff_search_ctx->ffsc_stack_ptr->ffs_prev; + sptr = search_ctx->ffsc_stack_ptr; + if (search_ctx->ffsc_stack_ptr != NULL) + search_ctx->ffsc_stack_ptr = search_ctx->ffsc_stack_ptr->ffs_prev; return sptr; } @@ -5118,62 +5155,63 @@ * free the given stack element */ static void -ff_free_stack_element(ctx) - ff_stack_T *ctx; +ff_free_stack_element(stack_ptr) + ff_stack_T *stack_ptr; { /* vim_free handles possible NULL pointers */ - vim_free(ctx->ffs_fix_path); + vim_free(stack_ptr->ffs_fix_path); #ifdef FEAT_PATH_EXTRA - vim_free(ctx->ffs_wc_path); + vim_free(stack_ptr->ffs_wc_path); #endif - if (ctx->ffs_filearray != NULL) - FreeWild(ctx->ffs_filearray_size, ctx->ffs_filearray); + if (stack_ptr->ffs_filearray != NULL) + FreeWild(stack_ptr->ffs_filearray_size, stack_ptr->ffs_filearray); - vim_free(ctx); + vim_free(stack_ptr); } /* - * clear the search context + * Clear the search context, but NOT the visited list. */ static void -ff_clear() +ff_clear(search_ctx) + ff_search_ctx_T *search_ctx; { ff_stack_T *sptr; /* clear up stack */ - while ((sptr = ff_pop()) != NULL) + while ((sptr = ff_pop(search_ctx)) != NULL) ff_free_stack_element(sptr); - vim_free(ff_search_ctx->ffsc_file_to_search); - vim_free(ff_search_ctx->ffsc_start_dir); - vim_free(ff_search_ctx->ffsc_fix_path); + vim_free(search_ctx->ffsc_file_to_search); + vim_free(search_ctx->ffsc_start_dir); + vim_free(search_ctx->ffsc_fix_path); #ifdef FEAT_PATH_EXTRA - vim_free(ff_search_ctx->ffsc_wc_path); + vim_free(search_ctx->ffsc_wc_path); #endif #ifdef FEAT_PATH_EXTRA - if (ff_search_ctx->ffsc_stopdirs_v != NULL) + if (search_ctx->ffsc_stopdirs_v != NULL) { int i = 0; - while (ff_search_ctx->ffsc_stopdirs_v[i] != NULL) + while (search_ctx->ffsc_stopdirs_v[i] != NULL) { - vim_free(ff_search_ctx->ffsc_stopdirs_v[i]); + vim_free(search_ctx->ffsc_stopdirs_v[i]); i++; } - vim_free(ff_search_ctx->ffsc_stopdirs_v); + vim_free(search_ctx->ffsc_stopdirs_v); } - ff_search_ctx->ffsc_stopdirs_v = NULL; + search_ctx->ffsc_stopdirs_v = NULL; #endif /* reset everything */ - ff_search_ctx->ffsc_file_to_search = NULL; - ff_search_ctx->ffsc_start_dir = NULL; - ff_search_ctx->ffsc_fix_path = NULL; + search_ctx->ffsc_file_to_search = NULL; + search_ctx->ffsc_start_dir = NULL; + search_ctx->ffsc_fix_path = NULL; #ifdef FEAT_PATH_EXTRA - ff_search_ctx->ffsc_wc_path = NULL; - ff_search_ctx->ffsc_level = 0; + search_ctx->ffsc_wc_path = NULL; + search_ctx->ffsc_level = 0; #endif } @@ -5222,7 +5260,7 @@ #if defined(FEAT_SEARCHPATH) || defined(PROTO) /* - * Find the file name "ptr[len]" in the path. + * Find the file name "ptr[len]" in the path. Also finds directory names. * * On the first call set the parameter 'first' to TRUE to initialize * the search. For repeating calls to FALSE. @@ -5256,7 +5294,7 @@ { return find_file_in_path_option(ptr, len, options, first, *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path, - FALSE, rel_fname, curbuf->b_p_sua); + FINDFILE_BOTH, rel_fname, curbuf->b_p_sua); } static char_u *ff_file_to_find = NULL; @@ -5289,17 +5327,17 @@ char_u *rel_fname; /* file name searching relative to */ { return find_file_in_path_option(ptr, len, options, TRUE, p_cdpath, - TRUE, rel_fname, (char_u *)""); + FINDFILE_DIR, rel_fname, (char_u *)""); } char_u * -find_file_in_path_option(ptr, len, options, first, path_option, need_dir, rel_fname, suffixes) +find_file_in_path_option(ptr, len, options, first, path_option, find_what, rel_fname, suffixes) char_u *ptr; /* file name */ int len; /* length of file name */ int options; int first; /* use count'th matching file name */ char_u *path_option; /* p_path or p_cdpath */ - int need_dir; /* looking for directory name */ + int find_what; /* FINDFILE_FILE, _DIR or _BOTH */ char_u *rel_fname; /* file name we are looking relative to. */ char_u *suffixes; /* list of suffixes, 'suffixesadd' option */ { @@ -5401,12 +5439,14 @@ #ifdef DJGPP /* "C:" by itself will fail for mch_getperm(), * assume it's always valid. */ - (need_dir && NameBuff[0] != NUL + (find_what != FINDFILE_FILE && NameBuff[0] != NUL && NameBuff[1] == ':' && NameBuff[2] == NUL) || #endif (mch_getperm(NameBuff) >= 0 - && (!need_dir || mch_isdir(NameBuff)))) + && (find_what == FINDFILE_BOTH + || ((find_what == FINDFILE_DIR) + == mch_isdir(NameBuff))))) { file_name = vim_strsave(NameBuff); goto theend; @@ -5437,9 +5477,7 @@ { if (did_findfile_init) { - ff_search_ctx->ffsc_need_dir = need_dir; file_name = vim_findfile(fdip_search_ctx); - ff_search_ctx->ffsc_need_dir = FALSE; if (file_name != NULL) break; @@ -5472,7 +5510,7 @@ r_ptr = NULL; #endif fdip_search_ctx = vim_findfile_init(buf, ff_file_to_find, - r_ptr, 100, FALSE, TRUE, + r_ptr, 100, FALSE, find_what, fdip_search_ctx, FALSE, rel_fname); if (fdip_search_ctx != NULL) did_findfile_init = TRUE; @@ -5484,7 +5522,7 @@ { if (first == TRUE) { - if (need_dir) + if (find_what == FINDFILE_DIR) EMSG2(_("E344: Can't find directory \"%s\" in cdpath"), ff_file_to_find); else @@ -5493,7 +5531,7 @@ } else { - if (need_dir) + if (find_what == FINDFILE_DIR) EMSG2(_("E346: No more directory \"%s\" found in cdpath"), ff_file_to_find); else @@ -5922,7 +5960,11 @@ { if (emsg_not_now()) return TRUE; /* no error messages at the moment */ +#ifdef HAVE_STDARG_H + vim_snprintf((char *)IObuff, IOSIZE, (char *)s, a1, a2); +#else vim_snprintf((char *)IObuff, IOSIZE, (char *)s, (long_u)a1, (long_u)a2); +#endif return emsg(IObuff); } diff -Naur vim71.orig/src/netbeans.c vim71/src/netbeans.c --- vim71.orig/src/netbeans.c 2007-05-07 15:51:36.000000000 -0400 +++ vim71/src/netbeans.c 2008-06-18 06:57:00.000000000 -0400 @@ -16,6 +16,10 @@ * See ":help netbeans-protocol" for explanation. */ +#if defined(MSDOS) || defined(MSWIN) +# include "vimio.h" /* for mch_open(), must be before vim.h */ +#endif + #include "vim.h" #if defined(FEAT_NETBEANS_INTG) || defined(PROTO) @@ -1204,6 +1208,54 @@ return result; } +/* + * Remove from "first" byte to "last" byte (inclusive), at line "lnum" of the + * current buffer. Remove to end of line when "last" is MAXCOL. + */ + static void +nb_partialremove(linenr_T lnum, colnr_T first, colnr_T last) +{ + char_u *oldtext, *newtext; + int oldlen; + int lastbyte = last; + + oldtext = ml_get(lnum); + oldlen = STRLEN(oldtext); + if (first >= (colnr_T)oldlen || oldlen == 0) /* just in case */ + return; + if (lastbyte >= oldlen) + lastbyte = oldlen - 1; + newtext = alloc(oldlen - (int)(lastbyte - first)); + if (newtext != NULL) + { + mch_memmove(newtext, oldtext, first); + mch_memmove(newtext + first, oldtext + lastbyte + 1, STRLEN(oldtext + lastbyte + 1) + 1); + nbdebug((" NEW LINE %d: %s\n", lnum, newtext)); + ml_replace(lnum, newtext, FALSE); + } +} + +/* + * Replace the "first" line with the concatenation of the "first" and + * the "other" line. The "other" line is not removed. + */ + static void +nb_joinlines(linenr_T first, linenr_T other) +{ + int len_first, len_other; + char_u *p; + + len_first = STRLEN(ml_get(first)); + len_other = STRLEN(ml_get(other)); + p = alloc((unsigned)(len_first + len_other + 1)); + if (p != NULL) + { + mch_memmove(p, ml_get(first), len_first); + mch_memmove(p + len_first, ml_get(other), len_other + 1); + ml_replace(first, p, FALSE); + } +} + #define SKIP_STOP 2 #define streq(a,b) (strcmp(a,b) == 0) static int needupdate = 0; @@ -1371,6 +1423,8 @@ long count; pos_T first, last; pos_T *pos; + pos_T *next; + linenr_T del_from_lnum, del_to_lnum; /* lines to be deleted as a whole */ int oldFire = netbeansFireChanges; int oldSuppress = netbeansSuppressNoLines; int wasChanged; @@ -1420,25 +1474,75 @@ } last = *pos; nbdebug((" LAST POS: line %d, col %d\n", last.lnum, last.col)); - curwin->w_cursor = first; + del_from_lnum = first.lnum; + del_to_lnum = last.lnum; doupdate = 1; - /* keep part of first line */ - if (first.lnum == last.lnum && first.col != last.col) + /* Get the position of the first byte after the deleted + * section. "next" is NULL when deleting to the end of the + * file. */ + next = off2pos(buf->bufp, off + count); + + /* Remove part of the first line. */ + if (first.col != 0 || (next != NULL && first.lnum == next->lnum)) { - /* deletion is within one line */ - char_u *p = ml_get(first.lnum); - mch_memmove(p + first.col, p + last.col + 1, STRLEN(p + last.col) + 1); - nbdebug((" NEW LINE %d: %s\n", first.lnum, p)); - ml_replace(first.lnum, p, TRUE); + if (first.lnum != last.lnum + || (next != NULL && first.lnum != next->lnum)) + { + /* remove to the end of the first line */ + nb_partialremove(first.lnum, first.col, + (colnr_T)MAXCOL); + if (first.lnum == last.lnum) + { + /* Partial line to remove includes the end of + * line. Join the line with the next one, have + * the next line deleted below. */ + nb_joinlines(first.lnum, next->lnum); + del_to_lnum = next->lnum; + } + } + else + { + /* remove within one line */ + nb_partialremove(first.lnum, first.col, last.col); + } + ++del_from_lnum; /* don't delete the first line */ } - if (first.lnum < last.lnum) + /* Remove part of the last line. */ + if (first.lnum != last.lnum && next != NULL + && next->col != 0 && last.lnum == next->lnum) + { + nb_partialremove(last.lnum, 0, last.col); + if (del_from_lnum > first.lnum) + { + /* Join end of last line to start of first line; last + * line is deleted below. */ + nb_joinlines(first.lnum, last.lnum); + } + else + /* First line is deleted as a whole, keep the last + * line. */ + --del_to_lnum; + } + + /* First is partial line; last line to remove includes + * the end of line; join first line to line following last + * line; line following last line is deleted below. */ + if (first.lnum != last.lnum && del_from_lnum > first.lnum + && next != NULL && last.lnum != next->lnum) + { + nb_joinlines(first.lnum, next->lnum); + del_to_lnum = next->lnum; + } + + /* Delete whole lines if there are any. */ + if (del_to_lnum >= del_from_lnum) { int i; /* delete signs from the lines being deleted */ - for (i = first.lnum; i <= last.lnum; i++) + for (i = del_from_lnum; i <= del_to_lnum; i++) { int id = buf_findsign_id(buf->bufp, (linenr_T)i); if (id > 0) @@ -1450,10 +1554,15 @@ nbdebug((" No sign on line %d\n", i)); } - /* delete whole lines */ - nbdebug((" Deleting lines %d through %d\n", first.lnum, last.lnum)); - del_lines(last.lnum - first.lnum + 1, FALSE); + nbdebug((" Deleting lines %d through %d\n", del_from_lnum, del_to_lnum)); + curwin->w_cursor.lnum = del_from_lnum; + curwin->w_cursor.col = 0; + del_lines(del_to_lnum - del_from_lnum + 1, FALSE); } + + /* Leave cursor at first deleted byte. */ + curwin->w_cursor = first; + check_cursor_lnum(); buf->bufp->b_changed = wasChanged; /* logically unchanged */ netbeansFireChanges = oldFire; netbeansSuppressNoLines = oldSuppress; @@ -1869,13 +1978,16 @@ } else if (streq((char *)cmd, "setModified")) { + int prev_b_changed; + if (buf == NULL || buf->bufp == NULL) { /* EMSG("E646: null bufp in setModified"); */ return FAIL; } + prev_b_changed = buf->bufp->b_changed; if (streq((char *)args, "T")) - buf->bufp->b_changed = 1; + buf->bufp->b_changed = TRUE; else { struct stat st; @@ -1885,9 +1997,20 @@ if (buf->bufp->b_ffname != NULL && mch_stat((char *)buf->bufp->b_ffname, &st) >= 0) buf_store_time(buf->bufp, &st, buf->bufp->b_ffname); - buf->bufp->b_changed = 0; + buf->bufp->b_changed = FALSE; } buf->modified = buf->bufp->b_changed; + if (prev_b_changed != buf->bufp->b_changed) + { +#ifdef FEAT_WINDOWS + check_status(buf->bufp); + redraw_tabline = TRUE; +#endif +#ifdef FEAT_TITLE + maketitle(); +#endif + update_screen(0); + } /* =====================================================================*/ } else if (streq((char *)cmd, "setModtime")) @@ -2374,8 +2497,7 @@ * the current buffer as "buf". */ static void -nb_set_curbuf(buf) - buf_T *buf; +nb_set_curbuf(buf_T *buf) { if (curbuf != buf && buf_jump_open_win(buf) == NULL) set_curbuf(buf, DOBUF_GOTO); diff -Naur vim71.orig/src/normal.c vim71/src/normal.c --- vim71.orig/src/normal.c 2007-05-07 15:34:39.000000000 -0400 +++ vim71/src/normal.c 2008-06-18 06:56:27.000000000 -0400 @@ -141,12 +141,16 @@ static void nv_Undo __ARGS((cmdarg_T *cap)); static void nv_tilde __ARGS((cmdarg_T *cap)); static void nv_operator __ARGS((cmdarg_T *cap)); +#ifdef FEAT_EVAL +static void set_op_var __ARGS((int optype)); +#endif static void nv_lineop __ARGS((cmdarg_T *cap)); static void nv_home __ARGS((cmdarg_T *cap)); static void nv_pipe __ARGS((cmdarg_T *cap)); static void nv_bck_word __ARGS((cmdarg_T *cap)); static void nv_wordcmd __ARGS((cmdarg_T *cap)); static void nv_beginline __ARGS((cmdarg_T *cap)); +static void adjust_cursor __ARGS((oparg_T *oap)); #ifdef FEAT_VISUAL static void adjust_for_sel __ARGS((cmdarg_T *cap)); static int unadjust_for_sel __ARGS((void)); @@ -690,13 +694,20 @@ ca.count0 = ca.count0 * 10 + (c - '0'); if (ca.count0 < 0) /* got too large! */ ca.count0 = 999999999L; +#ifdef FEAT_EVAL + /* Set v:count here, when called from main() and not a stuffed + * command, so that v:count can be used in an expression mapping + * right after the count. */ + if (toplevel && stuff_empty()) + set_vcount(ca.count0, ca.count0 == 0 ? 1 : ca.count0); +#endif if (ctrl_w) { ++no_mapping; ++allow_keys; /* no mapping for nchar, but keys */ } ++no_zero_mapping; /* don't map zero here */ - c = safe_vgetc(); + c = plain_vgetc(); #ifdef FEAT_LANGMAP LANGMAP_ADJUST(c, TRUE); #endif @@ -721,7 +732,7 @@ ca.count0 = 0; ++no_mapping; ++allow_keys; /* no mapping for nchar, but keys */ - c = safe_vgetc(); /* get next character */ + c = plain_vgetc(); /* get next character */ #ifdef FEAT_LANGMAP LANGMAP_ADJUST(c, TRUE); #endif @@ -889,13 +900,18 @@ ++no_mapping; ++allow_keys; /* no mapping for nchar, but allow key codes */ +#ifdef FEAT_AUTOCMD + /* Don't generate a CursorHold event here, most commands can't handle + * it, e.g., nv_replace(), nv_csearch(). */ + did_cursorhold = TRUE; +#endif if (ca.cmdchar == 'g') { /* * For 'g' get the next character now, so that we can check for * "gr", "g'" and "g`". */ - ca.nchar = safe_vgetc(); + ca.nchar = plain_vgetc(); #ifdef FEAT_LANGMAP LANGMAP_ADJUST(ca.nchar, TRUE); #endif @@ -952,7 +968,7 @@ im_set_active(TRUE); #endif - *cp = safe_vgetc(); + *cp = plain_vgetc(); if (langmap_active) { @@ -1040,7 +1056,7 @@ } if (c > 0) { - c = safe_vgetc(); + c = plain_vgetc(); if (c != Ctrl_N && c != Ctrl_G) vungetc(c); else @@ -1059,7 +1075,7 @@ while (enc_utf8 && lang && (c = vpeekc()) > 0 && (c >= 0x100 || MB_BYTE2LEN(vpeekc()) > 1)) { - c = safe_vgetc(); + c = plain_vgetc(); if (!utf_iscomposing(c)) { vungetc(c); /* it wasn't, put it back */ @@ -3755,7 +3771,8 @@ extra_len = (int)STRLEN(p); overflow = old_len + extra_len - SHOWCMD_COLS; if (overflow > 0) - STRCPY(showcmd_buf, showcmd_buf + overflow); + mch_memmove(showcmd_buf, showcmd_buf + overflow, + old_len - overflow + 1); STRCAT(showcmd_buf, p); if (char_avail()) @@ -4178,7 +4195,7 @@ for (;;) { t = searchit(curwin, curbuf, &curwin->w_cursor, FORWARD, - pat, 1L, searchflags, RE_LAST, (linenr_T)0); + pat, 1L, searchflags, RE_LAST, (linenr_T)0, NULL); if (curwin->w_cursor.lnum >= old_pos.lnum) t = FAIL; /* match after start is failure too */ @@ -4558,7 +4575,7 @@ #endif ++no_mapping; ++allow_keys; /* no mapping for nchar, but allow key codes */ - nchar = safe_vgetc(); + nchar = plain_vgetc(); #ifdef FEAT_LANGMAP LANGMAP_ADJUST(nchar, TRUE); #endif @@ -4916,7 +4933,7 @@ case 'u': /* "zug" and "zuw": undo "zg" and "zw" */ ++no_mapping; ++allow_keys; /* no mapping for nchar, but allow key codes */ - nchar = safe_vgetc(); + nchar = plain_vgetc(); #ifdef FEAT_LANGMAP LANGMAP_ADJUST(nchar, TRUE); #endif @@ -5836,12 +5853,13 @@ /* When the NL before the first char has to be deleted we * put the cursor on the NUL after the previous line. * This is a very special case, be careful! - * don't adjust op_end now, otherwise it won't work */ + * Don't adjust op_end now, otherwise it won't work. */ if ( (cap->oap->op_type == OP_DELETE || cap->oap->op_type == OP_CHANGE) && !lineempty(curwin->w_cursor.lnum)) { - ++curwin->w_cursor.col; + if (*ml_get_cursor() != NUL) + ++curwin->w_cursor.col; cap->retval |= CA_NO_ADJ_OP_END; } continue; @@ -6075,7 +6093,7 @@ curwin->w_set_curswant = TRUE; i = do_search(cap->oap, dir, pat, cap->count1, - opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG); + opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG, NULL); if (i == 0) clearop(cap->oap); else @@ -6379,7 +6397,7 @@ */ else if (cap->nchar == 'p' || cap->nchar == 'P') { - if (!checkclearopq(cap->oap)) + if (!checkclearop(cap->oap)) { prep_redo_cmd(cap); do_put(cap->oap->regname, @@ -6550,6 +6568,8 @@ clearopbeep(cap->oap); else { + /* Don't leave the cursor on the NUL past end of line. */ + adjust_cursor(cap->oap); #ifdef FEAT_VIRTUALEDIT curwin->w_cursor.coladd = 0; #endif @@ -6662,6 +6682,13 @@ else had_ctrl_v = NUL; + /* Abort if the character is a special key. */ + if (IS_SPECIAL(cap->nchar)) + { + clearopbeep(cap->oap); + return; + } + #ifdef FEAT_VISUAL /* Visual mode "r" */ if (VIsual_active) @@ -6688,11 +6715,9 @@ } #endif - /* - * Check for a special key or not enough characters to replace. - */ + /* Abort if not enough characters to replace. */ ptr = ml_get_cursor(); - if (IS_SPECIAL(cap->nchar) || STRLEN(ptr) < (unsigned)cap->count1 + if (STRLEN(ptr) < (unsigned)cap->count1 #ifdef FEAT_MBYTE || (has_mbyte && mb_charlen(ptr) < cap->count1) #endif @@ -7155,6 +7180,9 @@ { cap->oap->start = curwin->w_cursor; cap->oap->op_type = OP_DELETE; +#ifdef FEAT_EVAL + set_op_var(OP_DELETE); +#endif cap->count1 = 1; nv_dollar(cap); finish_op = TRUE; @@ -8194,9 +8222,34 @@ { cap->oap->start = curwin->w_cursor; cap->oap->op_type = op_type; +#ifdef FEAT_EVAL + set_op_var(op_type); +#endif } } +#ifdef FEAT_EVAL +/* + * Set v:operator to the characters for "optype". + */ + static void +set_op_var(optype) + int optype; +{ + char_u opchars[3]; + + if (optype == OP_NOP) + set_vim_var_string(VV_OP, NULL, 0); + else + { + opchars[0] = get_op_char(optype); + opchars[1] = get_extra_op_char(optype); + opchars[2] = NUL; + set_vim_var_string(VV_OP, opchars, -1); + } +} +#endif + /* * Handle linewise operator "dd", "yy", etc. * @@ -8292,6 +8345,7 @@ int n; int word_end; int flag = FALSE; + pos_T startpos = curwin->w_cursor; /* * Set inclusive for the "E" and "e" command. @@ -8352,12 +8406,10 @@ else n = fwd_word(cap->count1, cap->arg, cap->oap->op_type != OP_NOP); - /* Don't leave the cursor on the NUL past a line */ - if (curwin->w_cursor.col && gchar_cursor() == NUL) - { - --curwin->w_cursor.col; - cap->oap->inclusive = TRUE; - } + /* Don't leave the cursor on the NUL past the end of line. Unless we + * didn't move it forward. */ + if (lt(startpos, curwin->w_cursor)) + adjust_cursor(cap->oap); if (n == FAIL && cap->oap->op_type == OP_NOP) clearopbeep(cap->oap); @@ -8374,6 +8426,39 @@ } /* + * Used after a movement command: If the cursor ends up on the NUL after the + * end of the line, may move it back to the last character and make the motion + * inclusive. + */ + static void +adjust_cursor(oap) + oparg_T *oap; +{ + /* The cursor cannot remain on the NUL when: + * - the column is > 0 + * - not in Visual mode or 'selection' is "o" + * - 'virtualedit' is not "all" and not "onemore". + */ + if (curwin->w_cursor.col > 0 && gchar_cursor() == NUL +#ifdef FEAT_VISUAL + && (!VIsual_active || *p_sel == 'o') +#endif +#ifdef FEAT_VIRTUALEDIT + && !virtual_active() && (ve_flags & VE_ONEMORE) == 0 +#endif + ) + { + --curwin->w_cursor.col; +#ifdef FEAT_MBYTE + /* prevent cursor from moving on the trail byte */ + if (has_mbyte) + mb_adjust_cursor(); +#endif + oap->inclusive = TRUE; + } +} + +/* * "0" and "^" commands. * cap->arg is the argument for beginline(). */ diff -Naur vim71.orig/src/ops.c vim71/src/ops.c --- vim71.orig/src/ops.c 2007-05-07 15:33:47.000000000 -0400 +++ vim71/src/ops.c 2008-06-18 06:56:15.000000000 -0400 @@ -258,7 +258,7 @@ if (first_char != '#' || !preprocs_left()) #endif { - shift_line(oap->op_type == OP_LSHIFT, p_sr, amount); + shift_line(oap->op_type == OP_LSHIFT, p_sr, amount, FALSE); } ++curwin->w_cursor.lnum; } @@ -321,10 +321,11 @@ * leaves cursor on first blank in the line */ void -shift_line(left, round, amount) +shift_line(left, round, amount, call_changed_bytes) int left; int round; int amount; + int call_changed_bytes; /* call changed_bytes() */ { int count; int i, j; @@ -363,10 +364,10 @@ /* Set new indent */ #ifdef FEAT_VREPLACE if (State & VREPLACE_FLAG) - change_indent(INDENT_SET, count, FALSE, NUL); + change_indent(INDENT_SET, count, FALSE, NUL, call_changed_bytes); else #endif - (void)set_indent(count, SIN_CHANGED); + (void)set_indent(count, call_changed_bytes ? SIN_CHANGED : 0); } #if defined(FEAT_VISUALEXTRA) || defined(PROTO) @@ -691,6 +692,7 @@ } } ++curwin->w_cursor.lnum; + curwin->w_cursor.col = 0; /* make sure it's valid */ } /* put cursor on first non-blank of indented line */ @@ -927,15 +929,16 @@ int name; int copy; /* make a copy, if FALSE make register empty. */ { - static struct yankreg *reg; - int i; + struct yankreg *reg; + int i; #ifdef FEAT_CLIPBOARD /* When Visual area changed, may have to update selection. Obtain the * selection too. */ - if (name == '*' && clip_star.available && clip_isautosel()) + if (name == '*' && clip_star.available) { - clip_update_selection(); + if (clip_isautosel()) + clip_update_selection(); may_get_selection(name); } #endif @@ -966,7 +969,7 @@ } /* - * Put "reg" into register "name". Free any previous contents. + * Put "reg" into register "name". Free any previous contents and "reg". */ void put_register(name, reg) @@ -976,6 +979,7 @@ get_yank_register(name, 0); free_yank_all(); *y_current = *(struct yankreg *)reg; + vim_free(reg); # ifdef FEAT_CLIPBOARD /* Send text written to clipboard register to the clipboard. */ @@ -2181,6 +2185,8 @@ } #endif +static int swapchars __ARGS((int op_type, pos_T *pos, int length)); + /* * Handle the (non-standard vi) tilde operator. Also for "gu", "gU" and "g?". */ @@ -2191,9 +2197,8 @@ pos_T pos; #ifdef FEAT_VISUAL struct block_def bd; - int todo; #endif - int did_change = 0; + int did_change = FALSE; if (u_save((linenr_T)(oap->start.lnum - 1), (linenr_T)(oap->end.lnum + 1)) == FAIL) @@ -2207,16 +2212,8 @@ { block_prep(oap, &bd, pos.lnum, FALSE); pos.col = bd.textcol; - for (todo = bd.textlen; todo > 0; --todo) - { -# ifdef FEAT_MBYTE - if (has_mbyte) - todo -= (*mb_ptr2len)(ml_get_pos(&pos)) - 1; -# endif - did_change |= swapchar(oap->op_type, &pos); - if (inc(&pos) == -1) /* at end of file */ - break; - } + did_change = swapchars(oap->op_type, &pos, bd.textlen); + # ifdef FEAT_NETBEANS_INTG if (usingNetbeans && did_change) { @@ -2246,13 +2243,18 @@ else if (!oap->inclusive) dec(&(oap->end)); - while (ltoreq(pos, oap->end)) - { - did_change |= swapchar(oap->op_type, &pos); - if (inc(&pos) == -1) /* at end of file */ - break; - } - + if (pos.lnum == oap->end.lnum) + did_change = swapchars(oap->op_type, &pos, + oap->end.col - pos.col + 1); + else + for (;;) + { + did_change |= swapchars(oap->op_type, &pos, + pos.lnum == oap->end.lnum ? oap->end.col + 1: + (int)STRLEN(ml_get_pos(&pos))); + if (ltoreq(oap->end, pos) || inc(&pos) == -1) + break; + } if (did_change) { changed_lines(oap->start.lnum, oap->start.col, oap->end.lnum + 1, @@ -2306,6 +2308,36 @@ } /* + * Invoke swapchar() on "length" bytes at position "pos". + * "pos" is advanced to just after the changed characters. + * "length" is rounded up to include the whole last multi-byte character. + * Also works correctly when the number of bytes changes. + * Returns TRUE if some character was changed. + */ + static int +swapchars(op_type, pos, length) + int op_type; + pos_T *pos; + int length; +{ + int todo; + int did_change = 0; + + for (todo = length; todo > 0; --todo) + { +# ifdef FEAT_MBYTE + if (has_mbyte) + /* we're counting bytes, not characters */ + todo -= (*mb_ptr2len)(ml_get_pos(pos)) - 1; +# endif + did_change |= swapchar(op_type, pos); + if (inc(pos) == -1) /* at end of file */ + break; + } + return did_change; +} + +/* * If op_type == OP_UPPER: make uppercase, * if op_type == OP_LOWER: make lowercase, * if op_type == OP_ROT13: do rot13 encoding, @@ -2327,7 +2359,8 @@ return FALSE; #ifdef FEAT_MBYTE - if (op_type == OP_UPPER && enc_latin1like && c == 0xdf) + if (op_type == OP_UPPER && c == 0xdf + && (enc_latin1like || STRCMP(p_enc, "iso-8859-2") == 0)) { pos_T sp = curwin->w_cursor; @@ -2466,9 +2499,10 @@ edit(NUL, FALSE, (linenr_T)count1); - /* if user has moved off this line, we don't know what to do, so do - * nothing */ - if (curwin->w_cursor.lnum != oap->start.lnum) + /* If user has moved off this line, we don't know what to do, so do + * nothing. + * Also don't repeat the insert when Insert mode ended with CTRL-C. */ + if (curwin->w_cursor.lnum != oap->start.lnum || got_int) return; if (oap->block_mode) @@ -2477,7 +2511,7 @@ /* * Spaces and tabs in the indent may have changed to other spaces and - * tabs. Get the starting column again and correct the lenght. + * tabs. Get the starting column again and correct the length. * Don't do this when "$" used, end-of-line will have changed. */ block_prep(oap, &bd2, oap->start.lnum, TRUE); @@ -2534,7 +2568,9 @@ #ifdef FEAT_VISUALEXTRA long offset; linenr_T linenr; - long ins_len, pre_textlen = 0; + long ins_len; + long pre_textlen = 0; + long pre_indent = 0; char_u *firstline; char_u *ins_text, *newp, *oldp; struct block_def bd; @@ -2579,7 +2615,9 @@ || gchar_cursor() == NUL)) coladvance_force(getviscol()); # endif - pre_textlen = (long)STRLEN(ml_get(oap->start.lnum)); + firstline = ml_get(oap->start.lnum); + pre_textlen = (long)STRLEN(firstline); + pre_indent = (long)(skipwhite(firstline) - firstline); bd.textcol = curwin->w_cursor.col; } #endif @@ -2595,16 +2633,26 @@ /* * In Visual block mode, handle copying the new text to all lines of the * block. + * Don't repeat the insert when Insert mode ended with CTRL-C. */ - if (oap->block_mode && oap->start.lnum != oap->end.lnum) + if (oap->block_mode && oap->start.lnum != oap->end.lnum && !got_int) { + /* Auto-indenting may have changed the indent. If the cursor was past + * the indent, exclude that indent change from the inserted text. */ firstline = ml_get(oap->start.lnum); - /* - * Subsequent calls to ml_get() flush the firstline data - take a - * copy of the required bit. - */ - if ((ins_len = (long)STRLEN(firstline) - pre_textlen) > 0) + if (bd.textcol > (colnr_T)pre_indent) + { + long new_indent = (long)(skipwhite(firstline) - firstline); + + pre_textlen += new_indent - pre_indent; + bd.textcol += new_indent - pre_indent; + } + + ins_len = (long)STRLEN(firstline) - pre_textlen; + if (ins_len > 0) { + /* Subsequent calls to ml_get() flush the firstline data - take a + * copy of the inserted text. */ if ((ins_text = alloc_check((unsigned)(ins_len + 1))) != NULL) { vim_strncpy(ins_text, firstline + bd.textcol, (size_t)ins_len); @@ -3404,7 +3452,9 @@ #ifdef FEAT_VIRTUALEDIT col += curwin->w_cursor.coladd; - if (ve_flags == VE_ALL && curwin->w_cursor.coladd > 0) + if (ve_flags == VE_ALL + && (curwin->w_cursor.coladd > 0 + || endcol2 == curwin->w_cursor.col)) { if (dir == FORWARD && c == NUL) ++col; @@ -4330,7 +4380,7 @@ if (keep_cursor) saved_cursor = oap->cursor_start; - format_lines(oap->line_count); + format_lines(oap->line_count, keep_cursor); /* * Leave the cursor at the first non-blank of the last formatted line. @@ -4445,8 +4495,9 @@ * first line. */ void -format_lines(line_count) +format_lines(line_count, avoid_fex) linenr_T line_count; + int avoid_fex; /* don't use 'formatexpr' */ { int max_len; int is_not_par; /* current line not part of parag. */ @@ -4616,7 +4667,7 @@ #ifdef FEAT_COMMENTS + (do_comments ? INSCHAR_DO_COM : 0) #endif - , second_indent); + + (avoid_fex ? INSCHAR_NO_FEX : 0), second_indent); State = old_State; p_smd = smd_save; second_indent = -1; diff -Naur vim71.orig/src/option.c vim71/src/option.c --- vim71.orig/src/option.c 2007-05-01 07:26:10.000000000 -0400 +++ vim71/src/option.c 2008-06-18 06:57:01.000000000 -0400 @@ -243,7 +243,8 @@ /* WV_ and BV_ values get typecasted to this for the "indir" field */ typedef enum { - PV_NONE = 0 + PV_NONE = 0, + PV_MAXVAL = 0xffff /* to avoid warnings for value out of range */ } idopt_T; /* @@ -427,6 +428,8 @@ #define P_NOGLOB 0x100000L/* do not use local value for global vimrc */ #define P_NFNAME 0x200000L/* only normal file name chars allowed */ #define P_INSECURE 0x400000L/* option was set from a modeline */ +#define P_PRI_MKRC 0x800000L/* priority for :mkvimrc (setting option has + side effects) */ #define ISK_LATIN1 (char_u *)"@,48-57,_,192-255" @@ -773,6 +776,8 @@ {(char_u *)0L, (char_u *)0L} #endif }, + /* P_PRI_MKRC isn't needed here, optval_default() + * always returns TRUE for 'compatible' */ {"compatible", "cp", P_BOOL|P_RALL, (char_u *)&p_cp, PV_NONE, {(char_u *)TRUE, (char_u *)FALSE}}, @@ -1515,7 +1520,7 @@ {(char_u *)0L, (char_u *)0L} #endif }, - {"keymap", "kmp", P_STRING|P_ALLOCED|P_VI_DEF|P_RBUF|P_RSTAT|P_NFNAME, + {"keymap", "kmp", P_STRING|P_ALLOCED|P_VI_DEF|P_RBUF|P_RSTAT|P_NFNAME|P_PRI_MKRC, #ifdef FEAT_KEYMAP (char_u *)&p_keymap, PV_KMAP, {(char_u *)"", (char_u *)0L} @@ -1835,8 +1840,9 @@ }, {"paragraphs", "para", P_STRING|P_VI_DEF, (char_u *)&p_para, PV_NONE, - {(char_u *)"IPLPPPQPP LIpplpipbp", (char_u *)0L}}, - {"paste", NULL, P_BOOL|P_VI_DEF, + {(char_u *)"IPLPPPQPP TPHPLIPpLpItpplpipbp", + (char_u *)0L}}, + {"paste", NULL, P_BOOL|P_VI_DEF|P_PRI_MKRC, (char_u *)&p_paste, PV_NONE, {(char_u *)FALSE, (char_u *)0L}}, {"pastetoggle", "pt", P_STRING|P_VI_DEF, @@ -1987,6 +1993,13 @@ {"redraw", NULL, P_BOOL|P_VI_DEF, (char_u *)NULL, PV_NONE, {(char_u *)FALSE, (char_u *)0L}}, + {"redrawtime", "rdt", P_NUM|P_VI_DEF, +#ifdef FEAT_RELTIME + (char_u *)&p_rdt, PV_NONE, +#else + (char_u *)NULL, PV_NONE, +#endif + {(char_u *)2000L, (char_u *)0L}}, {"remap", NULL, P_BOOL|P_VI_DEF, (char_u *)&p_remap, PV_NONE, {(char_u *)TRUE, (char_u *)0L}}, @@ -4628,7 +4641,7 @@ if ((!(flags & P_COMMA) || *s != ',') && vim_strchr(s + 1, *s) != NULL) { - STRCPY(s, s + 1); + mch_memmove(s, s + 1, STRLEN(s)); --s; } } @@ -4992,7 +5005,7 @@ * For 'spellsuggest' expand after "file:". */ expand_env_esc(val, NameBuff, MAXPATHL, - (char_u **)options[opt_idx].var == &p_tags, + (char_u **)options[opt_idx].var == &p_tags, FALSE, #ifdef FEAT_SPELL (char_u **)options[opt_idx].var == &p_sps ? (char_u *)"file:" : #endif @@ -5660,7 +5673,7 @@ { if (gvarp == &p_fenc) { - if (!curbuf->b_p_ma) + if (!curbuf->b_p_ma && opt_flags != OPT_GLOBAL) errmsg = e_modifiable; else if (vim_strchr(*varp, ',') != NULL) /* No comma allowed in 'fileencoding'; catches confusing it @@ -6348,7 +6361,7 @@ errmsg = check_stl_option(p_ruf); } /* check 'statusline' only if it doesn't start with "%!" */ - else if (varp != &p_stl || s[0] != '%' || s[1] != '!') + else if (varp == &p_ruf || s[0] != '%' || s[1] != '!') errmsg = check_stl_option(s); if (varp == &p_ruf && errmsg == NULL) comp_col(); @@ -7118,6 +7131,11 @@ /* when 'endofline' is changed, redraw the window title */ else if ((int *)varp == &curbuf->b_p_eol) need_maketitle = TRUE; +#ifdef FEAT_MBYTE + /* when 'bomb' is changed, redraw the window title */ + else if ((int *)varp == &curbuf->b_p_bomb) + need_maketitle = TRUE; +#endif #endif /* when 'bin' is set also set some other options */ @@ -7815,6 +7833,8 @@ errmsg = e_positive; p_ch = 1; } + if (p_ch > Rows - min_rows() + 1) + p_ch = Rows - min_rows() + 1; /* Only compute the new window layout when startup has been * completed. Otherwise the frame sizes may be wrong. */ @@ -8219,6 +8239,25 @@ varp = get_varp(&options[opt_idx]); if (varp != NULL) /* hidden option is not changed */ { + if (number == 0 && string != NULL) + { + int index; + + /* Either we are given a string or we are setting option + * to zero. */ + for (index = 0; string[index] == '0'; ++index) + ; + if (string[index] != NUL || index == 0) + { + /* There's another character after zeros or the string + * is empty. In both cases, we are trying to set a + * num option using a string. */ + EMSG3(_("E521: Number required: &%s = '%s'"), + name, string); + return; /* do nothing as we hit an error */ + + } + } if (flags & P_NUM) (void)set_num_option(opt_idx, varp, number, NULL, 0, opt_flags); @@ -8511,13 +8550,20 @@ char_u *varp_local = NULL; /* fresh value */ char *cmd; int round; + int pri; /* * The options that don't have a default (terminal name, columns, lines) * are never written. Terminal options are also not written. + * Do the loop over "options[]" twice: once for options with the + * P_PRI_MKRC flag and once without. */ - for (p = &options[0]; !istermoption(p); p++) - if (!(p->flags & P_NO_MKRC) && !istermoption(p)) + for (pri = 1; pri >= 0; --pri) + { + for (p = &options[0]; !istermoption(p); p++) + if (!(p->flags & P_NO_MKRC) + && !istermoption(p) + && ((pri == 1) == ((p->flags & P_PRI_MKRC) != 0))) { /* skip global option when only doing locals */ if (p->indir == PV_NONE && !(opt_flags & OPT_GLOBAL)) @@ -8613,6 +8659,7 @@ } } } + } return OK; } @@ -8667,7 +8714,7 @@ { s = *valuep; while (*s != NUL) - if (fputs((char *)str2special(&s, FALSE), fd) < 0) + if (put_escstr(fd, str2special(&s, FALSE), 2) == FAIL) return FAIL; } else if (expand) @@ -8715,6 +8762,8 @@ char *name; int value; { + if (value < 0) /* global/local option using global value */ + return OK; if (fprintf(fd, "%s %s%s", cmd, value ? "" : "no", name) < 0 || put_eol(fd) < 0) return FAIL; @@ -10585,6 +10634,8 @@ buf->b_start_ffc = *buf->b_p_ff; buf->b_start_eol = buf->b_p_eol; #ifdef FEAT_MBYTE + buf->b_start_bomb = buf->b_p_bomb; + /* Only use free/alloc when necessary, they take time. */ if (buf->b_start_fenc == NULL || STRCMP(buf->b_start_fenc, buf->b_p_fenc) != 0) @@ -10598,13 +10649,17 @@ /* * Return TRUE if 'fileformat' and/or 'fileencoding' has a different value * from when editing started (save_file_ff() called). - * Also when 'endofline' was changed and 'binary' is set. + * Also when 'endofline' was changed and 'binary' is set, or when 'bomb' was + * changed and 'binary' is not set. * Don't consider a new, empty buffer to be changed. */ int file_ff_differs(buf) buf_T *buf; { + /* In a buffer that was never loaded the options are not valid. */ + if (buf->b_flags & BF_NEVERLOADED) + return FALSE; if ((buf->b_flags & BF_NEW) && buf->b_ml.ml_line_count == 1 && *ml_get_buf(buf, (linenr_T)1, FALSE) == NUL) @@ -10614,6 +10669,8 @@ if (buf->b_p_bin && buf->b_start_eol != buf->b_p_eol) return TRUE; #ifdef FEAT_MBYTE + if (!buf->b_p_bin && buf->b_start_bomb != buf->b_p_bomb) + return TRUE; if (buf->b_start_fenc == NULL) return (*buf->b_p_fenc != NUL); return (STRCMP(buf->b_start_fenc, buf->b_p_fenc) != 0); diff -Naur vim71.orig/src/option.h vim71/src/option.h --- vim71.orig/src/option.h 2007-05-07 15:23:03.000000000 -0400 +++ vim71/src/option.h 2008-06-18 06:55:25.000000000 -0400 @@ -633,6 +633,9 @@ #ifdef FEAT_SEARCHPATH EXTERN char_u *p_cdpath; /* 'cdpath' */ #endif +#ifdef FEAT_RELTIME +EXTERN long p_rdt; /* 'redrawtime' */ +#endif EXTERN int p_remap; /* 'remap' */ EXTERN long p_report; /* 'report' */ #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX) diff -Naur vim71.orig/src/os_unix.c vim71/src/os_unix.c --- vim71.orig/src/os_unix.c 2007-05-09 15:41:58.000000000 -0400 +++ vim71/src/os_unix.c 2008-06-18 06:56:39.000000000 -0400 @@ -45,6 +45,11 @@ # include #endif +#ifdef HAVE_SELINUX +# include +static int selinux_enabled = -1; +#endif + /* * Use this prototype for select, some include files have a wrong prototype */ @@ -195,6 +200,7 @@ static int show_shell_mess = TRUE; #endif static int deadly_signal = 0; /* The signal we caught */ +static int in_mch_delay = FALSE; /* sleeping in mch_delay() */ static int curr_tmode = TMODE_COOK; /* contains current terminal mode */ @@ -268,8 +274,9 @@ #ifdef SIGVTALRM {SIGVTALRM, "VTALRM", TRUE}, #endif -#if defined(SIGPROF) && !defined(FEAT_MZSCHEME) - /* MzScheme uses SIGPROF for its own needs */ +#if defined(SIGPROF) && !defined(FEAT_MZSCHEME) && !defined(WE_ARE_PROFILING) + /* MzScheme uses SIGPROF for its own needs; On Linux with profiling + * this makes Vim exit. WE_ARE_PROFILING is defined in Makefile. */ {SIGPROF, "PROF", TRUE}, #endif #ifdef SIGXCPU @@ -310,7 +317,7 @@ } /* - * mch_inchar(): low level input funcion. + * mch_inchar(): low level input function. * Get a characters from the keyboard. * Return the number of characters that are available. * If wtime == 0 do not wait for characters. @@ -538,7 +545,9 @@ if (ignoreinput) { /* Go to cooked mode without echo, to allow SIGINT interrupting us - * here */ + * here. But we don't want QUIT to kill us (CTRL-\ used in a + * shell may produce SIGQUIT). */ + in_mch_delay = TRUE; old_tmode = curr_tmode; if (curr_tmode == TMODE_RAW) settmode(TMODE_SLEEP); @@ -602,6 +611,7 @@ #endif settmode(old_tmode); + in_mch_delay = FALSE; } else WaitForChar(msec); @@ -753,7 +763,8 @@ if (signal_stack != NULL) { # ifdef HAVE_SIGALTSTACK -# ifdef __APPLE__ +# if defined(__APPLE__) && (!defined(MAC_OS_X_VERSION_MAX_ALLOWED) \ + || MAC_OS_X_VERSION_MAX_ALLOWED <= 1040) /* missing prototype. Adding it to osdef?.h.in doesn't work, because * "struct sigaltstack" needs to be declared. */ extern int sigaltstack __ARGS((const struct sigaltstack *ss, struct sigaltstack *oss)); @@ -921,6 +932,14 @@ #endif #ifdef SIGHASARG +# ifdef SIGQUIT + /* While in mch_delay() we go to cooked mode to allow a CTRL-C to + * interrupt us. But in cooked mode we may also get SIGQUIT, e.g., when + * pressing CTRL-\, but we don't want Vim to exit then. */ + if (in_mch_delay && sigarg == SIGQUIT) + SIGRETURN; +# endif + /* When SIGHUP, SIGQUIT, etc. are blocked: postpone the effect and return * here. This avoids that a non-reentrant function is interrupted, e.g., * free(). Calling free() again may then cause a crash. */ @@ -1566,18 +1585,19 @@ #ifdef FEAT_XCLIPBOARD if (xterm_dpy != NULL && x11_window != 0) { - /* Checked it already. */ - if (x11_display_from == XD_XTERM) - return OK; - - /* - * If the X11 display was opened here before, for the window where Vim - * was started, close that one now to avoid a memory leak. - */ - if (x11_display_from == XD_HERE && x11_display != NULL) - XCloseDisplay(x11_display); - x11_display = xterm_dpy; - x11_display_from = XD_XTERM; + /* We may have checked it already, but Gnome terminal can move us to + * another window, so we need to check every time. */ + if (x11_display_from != XD_XTERM) + { + /* + * If the X11 display was opened here before, for the window where + * Vim was started, close that one now to avoid a memory leak. + */ + if (x11_display_from == XD_HERE && x11_display != NULL) + XCloseDisplay(x11_display); + x11_display = xterm_dpy; + x11_display_from = XD_XTERM; + } if (test_x11_window(x11_display) == FAIL) { /* probably bad $WINDOWID */ @@ -2420,7 +2440,7 @@ /* * Set the case of the file name, if it already exists. This will cause the * file name to remain exactly the same. - * Only required for file systems where case is ingored and preserved. + * Only required for file systems where case is ignored and preserved. */ /*ARGSUSED*/ void @@ -2499,7 +2519,13 @@ if (stat((char *)name, &statb)) #endif return -1; +#ifdef __INTERIX + /* The top bit makes the value negative, which means the file doesn't + * exist. Remove the bit, we don't use it. */ + return statb.st_mode & ~S_ADDACE; +#else return statb.st_mode; +#endif } /* @@ -2536,6 +2562,62 @@ } vim_acl_solaris_T; # endif +#if defined(HAVE_SELINUX) || defined(PROTO) +/* + * Copy security info from "from_file" to "to_file". + */ + void +mch_copy_sec(from_file, to_file) + char_u *from_file; + char_u *to_file; +{ + if (from_file == NULL) + return; + + if (selinux_enabled == -1) + selinux_enabled = is_selinux_enabled(); + + if (selinux_enabled > 0) + { + security_context_t from_context = NULL; + security_context_t to_context = NULL; + + if (getfilecon((char *)from_file, &from_context) < 0) + { + /* If the filesystem doesn't support extended attributes, + the original had no special security context and the + target cannot have one either. */ + if (errno == EOPNOTSUPP) + return; + + MSG_PUTS(_("\nCould not get security context for ")); + msg_outtrans(from_file); + msg_putchar('\n'); + return; + } + if (getfilecon((char *)to_file, &to_context) < 0) + { + MSG_PUTS(_("\nCould not get security context for ")); + msg_outtrans(to_file); + msg_putchar('\n'); + freecon (from_context); + return ; + } + if (strcmp(from_context, to_context) != 0) + { + if (setfilecon((char *)to_file, from_context) < 0) + { + MSG_PUTS(_("\nCould not set security context for ")); + msg_outtrans(to_file); + msg_putchar('\n'); + } + } + freecon(to_context); + freecon(from_context); + } +} +#endif /* HAVE_SELINUX */ + /* * Return a pointer to the ACL of file "fname" in allocated memory. * Return NULL if the ACL is not available for whatever reason. @@ -4646,7 +4728,7 @@ ret = poll(fds, nfd, towait); # ifdef FEAT_MZSCHEME if (ret == 0 && mzquantum_used) - /* MzThreads scheduling is required and timeout occured */ + /* MzThreads scheduling is required and timeout occurred */ finished = FALSE; # endif @@ -4794,7 +4876,7 @@ #endif # ifdef FEAT_MZSCHEME if (ret == 0 && mzquantum_used) - /* loop if MzThreads must be scheduled and timeout occured */ + /* loop if MzThreads must be scheduled and timeout occurred */ finished = FALSE; # endif @@ -4938,6 +5020,9 @@ char_u *p; int dir; #ifdef __EMX__ + /* + * This is the OS/2 implementation. + */ # define EXPL_ALLOC_INC 16 char_u **expl_files; size_t files_alloced, files_free; @@ -5048,20 +5133,26 @@ return OK; #else /* __EMX__ */ - + /* + * This is the non-OS/2 implementation (really Unix). + */ int j; char_u *tempname; char_u *command; FILE *fd; char_u *buffer; -#define STYLE_ECHO 0 /* use "echo" to expand */ -#define STYLE_GLOB 1 /* use "glob" to expand, for csh */ -#define STYLE_PRINT 2 /* use "print -N" to expand, for zsh */ -#define STYLE_BT 3 /* `cmd` expansion, execute the pattern directly */ +#define STYLE_ECHO 0 /* use "echo", the default */ +#define STYLE_GLOB 1 /* use "glob", for csh */ +#define STYLE_VIMGLOB 2 /* use "vimglob", for Posix sh */ +#define STYLE_PRINT 3 /* use "print -N", for zsh */ +#define STYLE_BT 4 /* `cmd` expansion, execute the pattern + * directly */ int shell_style = STYLE_ECHO; int check_spaces; static int did_find_nul = FALSE; int ampersent = FALSE; + /* vimglob() function to define for Posix shell */ + static char *sh_vimglob_func = "vimglob() { while [ $# -ge 1 ]; do echo -n \"$1\"; echo; shift; done }; vimglob >"; *num_file = 0; /* default: no files found */ *file = NULL; @@ -5099,9 +5190,17 @@ /* * Let the shell expand the patterns and write the result into the temp - * file. if expanding `cmd` execute it directly. - * If we use csh, glob will work better than echo. - * If we use zsh, print -N will work better than glob. + * file. + * STYLE_BT: NL separated + * If expanding `cmd` execute it directly. + * STYLE_GLOB: NUL separated + * If we use *csh, "glob" will work better than "echo". + * STYLE_PRINT: NL or NUL separated + * If we use *zsh, "print -N" will work better than "glob". + * STYLE_VIMGLOB: NL separated + * If we use *sh*, we define "vimglob()". + * STYLE_ECHO: space separated. + * A shell we don't know, stay safe and use "echo". */ if (num_pat == 1 && *pat[0] == '`' && (len = STRLEN(pat[0])) > 2 @@ -5114,9 +5213,17 @@ else if (STRCMP(p_sh + len - 3, "zsh") == 0) shell_style = STYLE_PRINT; } - - /* "unset nonomatch; print -N >" plus two is 29 */ + if (shell_style == STYLE_ECHO && strstr((char *)gettail(p_sh), + "sh") != NULL) + shell_style = STYLE_VIMGLOB; + + /* Compute the length of the command. We need 2 extra bytes: for the + * optional '&' and for the NUL. + * Worst case: "unset nonomatch; print -N >" plus two is 29 */ len = STRLEN(tempname) + 29; + if (shell_style == STYLE_VIMGLOB) + len += STRLEN(sh_vimglob_func); + for (i = 0; i < num_pat; ++i) { /* Count the length of the patterns in the same way as they are put in @@ -5175,16 +5282,20 @@ STRCAT(command, "glob >"); else if (shell_style == STYLE_PRINT) STRCAT(command, "print -N >"); + else if (shell_style == STYLE_VIMGLOB) + STRCAT(command, sh_vimglob_func); else STRCAT(command, "echo >"); } + STRCAT(command, tempname); + if (shell_style != STYLE_BT) for (i = 0; i < num_pat; ++i) { /* When using system() always add extra quotes, because the shell * is started twice. Otherwise put a backslash before special - * characters, except insice ``. */ + * characters, except inside ``. */ #ifdef USE_SYSTEM STRCAT(command, " \""); STRCAT(command, pat[i]); @@ -5224,8 +5335,7 @@ if (flags & EW_SILENT) show_shell_mess = FALSE; if (ampersent) - STRCAT(command, "&"); /* put the '&' back after the - redirection */ + STRCAT(command, "&"); /* put the '&' after the redirection */ /* * Using zsh -G: If a pattern has no matches, it is just deleted from @@ -5257,7 +5367,7 @@ show_shell_mess = TRUE; vim_free(command); - if (i) /* mch_call_shell() failed */ + if (i != 0) /* mch_call_shell() failed */ { mch_remove(tempname); vim_free(tempname); @@ -5328,7 +5438,7 @@ } vim_free(tempname); -#if defined(__CYGWIN__) || defined(__CYGWIN32__) +# if defined(__CYGWIN__) || defined(__CYGWIN32__) /* Translate into . Caution, buffer may contain NUL. */ p = buffer; for (i = 0; i < len; ++i) @@ -5351,7 +5461,7 @@ } } /* file names are separated with NL */ - else if (shell_style == STYLE_BT) + else if (shell_style == STYLE_BT || shell_style == STYLE_VIMGLOB) { buffer[len] = NUL; /* make sure the buffer ends in NUL */ p = buffer; @@ -5430,7 +5540,8 @@ { (*file)[i] = p; /* Space or NL separates */ - if (shell_style == STYLE_ECHO || shell_style == STYLE_BT) + if (shell_style == STYLE_ECHO || shell_style == STYLE_BT + || shell_style == STYLE_VIMGLOB) { while (!(shell_style == STYLE_ECHO && *p == ' ') && *p != '\n' && *p != NUL) @@ -5474,7 +5585,7 @@ { STRCPY(p, (*file)[i]); if (dir) - STRCAT(p, "/"); /* add '/' to a directory name */ + add_pathsep(p); /* add '/' to a directory name */ (*file)[j++] = p; } } @@ -5668,7 +5779,7 @@ /* gpm library tries to handling TSTP causes * problems. Anyways, we close connection to Gpm whenever * we are going to suspend or starting an external process - * so we should'nt have problem with this + * so we shouldn't have problem with this */ signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL); return 1; /* succeed */ @@ -5682,7 +5793,7 @@ /* * Closes connection to gpm - * returns non-zero if connection succesfully closed + * returns non-zero if connection successfully closed */ static void gpm_close() @@ -6108,9 +6219,9 @@ if (xterm_trace == 1) { /* Get the hints just before tracking starts. The font size might - * have changed recently */ - XGetWMNormalHints(xterm_dpy, x11_window, &xterm_hints, &got_hints); - if (!(got_hints & PResizeInc) + * have changed recently. */ + if (!XGetWMNormalHints(xterm_dpy, x11_window, &xterm_hints, &got_hints) + || !(got_hints & PResizeInc) || xterm_hints.width_inc <= 1 || xterm_hints.height_inc <= 1) { diff -Naur vim71.orig/src/os_unix.h vim71/src/os_unix.h --- vim71.orig/src/os_unix.h 2007-05-07 15:35:05.000000000 -0400 +++ vim71/src/os_unix.h 2008-06-18 06:51:07.000000000 -0400 @@ -508,6 +508,9 @@ #if !defined(S_ISFIFO) && defined(S_IFIFO) # define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) #endif +#if !defined(S_ISCHR) && defined(S_IFCHR) +# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +#endif /* Note: Some systems need both string.h and strings.h (Savage). However, * some systems can't handle both, only use string.h in that case. */ diff -Naur vim71.orig/src/popupmnu.c vim71/src/popupmnu.c --- vim71.orig/src/popupmnu.c 2007-03-24 16:07:39.000000000 -0400 +++ vim71/src/popupmnu.c 2008-06-18 06:51:46.000000000 -0400 @@ -75,7 +75,6 @@ row = curwin->w_cline_row + W_WINROW(curwin); height = curwin->w_cline_height; - col = curwin->w_wcol + W_WINCOL(curwin) - curwin->w_leftcol; if (firstwin->w_p_pvw) top_clear = firstwin->w_height; @@ -167,6 +166,15 @@ pum_base_width = max_width; pum_kind_width = kind_width; + /* Calculate column */ +#ifdef FEAT_RIGHTLEFT + if (curwin->w_p_rl) + col = W_WINCOL(curwin) + W_WIDTH(curwin) - curwin->w_wcol - + curwin->w_leftcol - 1; + else +#endif + col = W_WINCOL(curwin) + curwin->w_wcol - curwin->w_leftcol; + /* if there are more items than room we need a scrollbar */ if (pum_height < size) { @@ -179,11 +187,23 @@ if (def_width < max_width) def_width = max_width; - if (col < Columns - PUM_DEF_WIDTH || col < Columns - max_width) + if (((col < Columns - PUM_DEF_WIDTH || col < Columns - max_width) +#ifdef FEAT_RIGHTLEFT + && !curwin->w_p_rl) + || (curwin->w_p_rl && (col > PUM_DEF_WIDTH || col > max_width) +#endif + )) { /* align pum column with "col" */ pum_col = col; - pum_width = Columns - pum_col - pum_scrollbar; + +#ifdef FEAT_RIGHTLEFT + if (curwin->w_p_rl) + pum_width = pum_col - pum_scrollbar + 1; + else +#endif + pum_width = Columns - pum_col - pum_scrollbar; + if (pum_width > max_width + kind_width + extra_width + 1 && pum_width > PUM_DEF_WIDTH) { @@ -195,14 +215,24 @@ else if (Columns < def_width) { /* not enough room, will use what we have */ - pum_col = 0; +#ifdef FEAT_RIGHTLEFT + if (curwin->w_p_rl) + pum_col = Columns - 1; + else +#endif + pum_col = 0; pum_width = Columns - 1; } else { if (max_width > PUM_DEF_WIDTH) max_width = PUM_DEF_WIDTH; /* truncate */ - pum_col = Columns - max_width; +#ifdef FEAT_RIGHTLEFT + if (curwin->w_p_rl) + pum_col = max_width - 1; + else +#endif + pum_col = Columns - max_width; pum_width = max_width - pum_scrollbar; } @@ -255,8 +285,16 @@ attr = (idx == pum_selected) ? attr_select : attr_norm; /* prepend a space if there is room */ - if (pum_col > 0) - screen_putchar(' ', row, pum_col - 1, attr); +#ifdef FEAT_RIGHTLEFT + if (curwin->w_p_rl) + { + if (pum_col < W_WINCOL(curwin) + W_WIDTH(curwin) - 1) + screen_putchar(' ', row, pum_col + 1, attr); + } + else +#endif + if (pum_col > 0) + screen_putchar(' ', row, pum_col - 1, attr); /* Display each entry, use two spaces for a Tab. * Do this 3 times: For the main text, kind and extra info */ @@ -282,26 +320,67 @@ { /* Display the text that fits or comes before a Tab. * First convert it to printable characters. */ - char_u *st; - int saved = *p; + char_u *st; + int saved = *p; *p = NUL; st = transstr(s); *p = saved; - if (st != NULL) +#ifdef FEAT_RIGHTLEFT + if (curwin->w_p_rl) { - screen_puts_len(st, (int)STRLEN(st), row, col, + if (st != NULL) + { + char_u *rt = reverse_text(st); + char_u *rt_saved = rt; + int len, j; + + if (rt != NULL) + { + len = STRLEN(rt); + if (len > pum_width) + { + for (j = pum_width; j < len; ++j) + mb_ptr_adv(rt); + len = pum_width; + } + screen_puts_len(rt, len, row, + col - len + 1, attr); + vim_free(rt_saved); + } + vim_free(st); + } + col -= width; + } + else +#endif + { + if (st != NULL) + { + screen_puts_len(st, (int)STRLEN(st), row, col, attr); - vim_free(st); + vim_free(st); + } + col += width; } - col += width; if (*p != TAB) break; /* Display two spaces for a Tab. */ - screen_puts_len((char_u *)" ", 2, row, col, attr); - col += 2; +#ifdef FEAT_RIGHTLEFT + if (curwin->w_p_rl) + { + screen_puts_len((char_u *)" ", 2, row, col - 1, + attr); + col -= 2; + } + else +#endif + { + screen_puts_len((char_u *)" ", 2, row, col, attr); + col += 2; + } totwidth += 2; s = NULL; /* start text at next char */ width = 0; @@ -322,17 +401,44 @@ && pum_array[idx].pum_extra == NULL) || pum_base_width + n >= pum_width) break; - screen_fill(row, row + 1, col, pum_col + pum_base_width + n, +#ifdef FEAT_RIGHTLEFT + if (curwin->w_p_rl) + { + screen_fill(row, row + 1, pum_col - pum_base_width - n + 1, + col + 1, ' ', ' ', attr); + col = pum_col - pum_base_width - n + 1; + } + else +#endif + { + screen_fill(row, row + 1, col, pum_col + pum_base_width + n, ' ', ' ', attr); - col = pum_col + pum_base_width + n; + col = pum_col + pum_base_width + n; + } totwidth = pum_base_width + n; } - screen_fill(row, row + 1, col, pum_col + pum_width, ' ', ' ', attr); +#ifdef FEAT_RIGHTLEFT + if (curwin->w_p_rl) + screen_fill(row, row + 1, pum_col - pum_width + 1, col + 1, ' ', + ' ', attr); + else +#endif + screen_fill(row, row + 1, col, pum_col + pum_width, ' ', ' ', + attr); if (pum_scrollbar > 0) - screen_putchar(' ', row, pum_col + pum_width, - i >= thumb_pos && i < thumb_pos + thumb_heigth + { +#ifdef FEAT_RIGHTLEFT + if (curwin->w_p_rl) + screen_putchar(' ', row, pum_col - pum_width, + i >= thumb_pos && i < thumb_pos + thumb_heigth ? attr_thumb : attr_scroll); + else +#endif + screen_putchar(' ', row, pum_col + pum_width, + i >= thumb_pos && i < thumb_pos + thumb_heigth + ? attr_thumb : attr_scroll); + } ++row; } @@ -466,7 +572,7 @@ set_option_value((char_u *)"bh", 0L, (char_u *)"wipe", OPT_LOCAL); set_option_value((char_u *)"diff", 0L, - (char_u *)"", OPT_LOCAL); + NULL, OPT_LOCAL); } } if (res == OK) diff -Naur vim71.orig/src/proto/charset.pro vim71/src/proto/charset.pro --- vim71.orig/src/proto/charset.pro 2007-05-12 06:39:01.000000000 -0400 +++ vim71/src/proto/charset.pro 2008-06-18 06:52:16.000000000 -0400 @@ -21,6 +21,7 @@ int vim_iswordp __ARGS((char_u *p)); int vim_iswordc_buf __ARGS((char_u *p, buf_T *buf)); int vim_isfilec __ARGS((int c)); +int vim_isfilec_or_wc __ARGS((int c)); int vim_isprintc __ARGS((int c)); int vim_isprintc_strict __ARGS((int c)); int lbr_chartabsize __ARGS((unsigned char *s, colnr_T col)); diff -Naur vim71.orig/src/proto/edit.pro vim71/src/proto/edit.pro --- vim71.orig/src/proto/edit.pro 2007-05-12 06:39:05.000000000 -0400 +++ vim71/src/proto/edit.pro 2008-06-18 06:55:19.000000000 -0400 @@ -3,7 +3,7 @@ void edit_putchar __ARGS((int c, int highlight)); void edit_unputchar __ARGS((void)); void display_dollar __ARGS((colnr_T col)); -void change_indent __ARGS((int type, int amount, int round, int replaced)); +void change_indent __ARGS((int type, int amount, int round, int replaced, int call_changed_bytes)); void truncate_spaces __ARGS((char_u *line)); void backspace_until_column __ARGS((int col)); int vim_is_ctrl_x_key __ARGS((int c)); @@ -32,6 +32,7 @@ char_u *get_last_insert __ARGS((void)); char_u *get_last_insert_save __ARGS((void)); void replace_push __ARGS((int c)); +int replace_push_mb __ARGS((char_u *p)); void fixthisline __ARGS((int (*get_the_indent)(void))); void fix_indent __ARGS((void)); int in_cinkeys __ARGS((int keytyped, int when, int line_is_empty)); diff -Naur vim71.orig/src/proto/eval.pro vim71/src/proto/eval.pro --- vim71.orig/src/proto/eval.pro 2007-05-12 06:39:06.000000000 -0400 +++ vim71/src/proto/eval.pro 2008-06-18 06:54:54.000000000 -0400 @@ -54,7 +54,7 @@ long get_dict_number __ARGS((dict_T *d, char_u *key)); char_u *get_function_name __ARGS((expand_T *xp, int idx)); char_u *get_expr_name __ARGS((expand_T *xp, int idx)); -long do_searchpair __ARGS((char_u *spat, char_u *mpat, char_u *epat, int dir, char_u *skip, int flags, pos_T *match_pos, linenr_T lnum_stop)); +long do_searchpair __ARGS((char_u *spat, char_u *mpat, char_u *epat, int dir, char_u *skip, int flags, pos_T *match_pos, linenr_T lnum_stop, long time_limit)); void set_vim_var_nr __ARGS((int idx, long val)); long get_vim_var_nr __ARGS((int idx)); char_u *get_vim_var_str __ARGS((int idx)); diff -Naur vim71.orig/src/proto/ex_cmds2.pro vim71/src/proto/ex_cmds2.pro --- vim71.orig/src/proto/ex_cmds2.pro 2007-05-12 06:39:09.000000000 -0400 +++ vim71/src/proto/ex_cmds2.pro 2008-06-18 06:54:54.000000000 -0400 @@ -14,6 +14,8 @@ void profile_end __ARGS((proftime_T *tm)); void profile_sub __ARGS((proftime_T *tm, proftime_T *tm2)); char *profile_msg __ARGS((proftime_T *tm)); +void profile_setlimit __ARGS((long msec, proftime_T *tm)); +int profile_passed_limit __ARGS((proftime_T *tm)); void profile_zero __ARGS((proftime_T *tm)); void profile_add __ARGS((proftime_T *tm, proftime_T *tm2)); void profile_self __ARGS((proftime_T *self, proftime_T *total, proftime_T *children)); diff -Naur vim71.orig/src/proto/ex_docmd.pro vim71/src/proto/ex_docmd.pro --- vim71.orig/src/proto/ex_docmd.pro 2007-05-12 06:39:10.000000000 -0400 +++ vim71/src/proto/ex_docmd.pro 2008-06-18 06:53:54.000000000 -0400 @@ -5,6 +5,7 @@ int getline_equal __ARGS((char_u *(*fgetline)(int, void *, int), void *cookie, char_u *(*func)(int, void *, int))); void *getline_cookie __ARGS((char_u *(*fgetline)(int, void *, int), void *cookie)); int checkforcmd __ARGS((char_u **pp, char *cmd, int len)); +int modifier_len __ARGS((char_u *cmd)); int cmd_exists __ARGS((char_u *name)); char_u *set_one_cmd_context __ARGS((expand_T *xp, char_u *buff)); char_u *skip_range __ARGS((char_u *cmd, int *ctx)); diff -Naur vim71.orig/src/proto/ex_getln.pro vim71/src/proto/ex_getln.pro --- vim71.orig/src/proto/ex_getln.pro 2007-05-12 06:39:13.000000000 -0400 +++ vim71/src/proto/ex_getln.pro 2008-06-18 06:56:43.000000000 -0400 @@ -24,6 +24,7 @@ void ExpandInit __ARGS((expand_T *xp)); void ExpandCleanup __ARGS((expand_T *xp)); void ExpandEscape __ARGS((expand_T *xp, char_u *str, int numfiles, char_u **files, int options)); +char_u *vim_strsave_fnameescape __ARGS((char_u *fname, int shell)); void tilde_replace __ARGS((char_u *orig_pat, int num_files, char_u **files)); char_u *sm_gettail __ARGS((char_u *s)); char_u *addstar __ARGS((char_u *fname, int len, int context)); diff -Naur vim71.orig/src/proto/fileio.pro vim71/src/proto/fileio.pro --- vim71.orig/src/proto/fileio.pro 2007-05-12 06:39:14.000000000 -0400 +++ vim71/src/proto/fileio.pro 2008-06-18 06:53:09.000000000 -0400 @@ -2,6 +2,7 @@ void filemess __ARGS((buf_T *buf, char_u *name, char_u *s, int attr)); int readfile __ARGS((char_u *fname, char_u *sfname, linenr_T from, linenr_T lines_to_skip, linenr_T lines_to_read, exarg_T *eap, int flags)); int prep_exarg __ARGS((exarg_T *eap, buf_T *buf)); +int check_file_readonly __ARGS((char_u *fname, int perm)); int buf_write __ARGS((buf_T *buf, char_u *fname, char_u *sfname, linenr_T start, linenr_T end, exarg_T *eap, int append, int forceit, int reset_changed, int filtering)); void msg_add_fname __ARGS((buf_T *buf, char_u *fname)); void msg_add_lines __ARGS((int insert_space, long lnum, long nchars)); @@ -39,6 +40,8 @@ int trigger_cursorhold __ARGS((void)); int has_cursormoved __ARGS((void)); int has_cursormovedI __ARGS((void)); +void block_autocmds __ARGS((void)); +void unblock_autocmds __ARGS((void)); int has_autocmd __ARGS((event_T event, char_u *sfname, buf_T *buf)); char_u *get_augroup_name __ARGS((expand_T *xp, int idx)); char_u *set_context_in_autocmd __ARGS((expand_T *xp, char_u *arg, int doautocmd)); diff -Naur vim71.orig/src/proto/getchar.pro vim71/src/proto/getchar.pro --- vim71.orig/src/proto/getchar.pro 2007-05-12 06:39:16.000000000 -0400 +++ vim71/src/proto/getchar.pro 2008-06-18 06:52:43.000000000 -0400 @@ -38,6 +38,7 @@ void updatescript __ARGS((int c)); int vgetc __ARGS((void)); int safe_vgetc __ARGS((void)); +int plain_vgetc __ARGS((void)); int vpeekc __ARGS((void)); int vpeekc_nomap __ARGS((void)); int vpeekc_any __ARGS((void)); diff -Naur vim71.orig/src/proto/if_cscope.pro vim71/src/proto/if_cscope.pro --- vim71.orig/src/proto/if_cscope.pro 2007-05-12 06:39:21.000000000 -0400 +++ vim71/src/proto/if_cscope.pro 2008-06-18 06:52:38.000000000 -0400 @@ -6,4 +6,5 @@ void cs_free_tags __ARGS((void)); void cs_print_tags __ARGS((void)); int cs_connection __ARGS((int num, char_u *dbpath, char_u *ppath)); +void cs_end __ARGS((void)); /* vim: set ft=c : */ diff -Naur vim71.orig/src/proto/mbyte.pro vim71/src/proto/mbyte.pro --- vim71.orig/src/proto/mbyte.pro 2007-05-12 06:39:38.000000000 -0400 +++ vim71/src/proto/mbyte.pro 2008-06-18 06:52:29.000000000 -0400 @@ -12,9 +12,9 @@ int utf_ptr2cells __ARGS((char_u *p)); int dbcs_ptr2cells __ARGS((char_u *p)); int latin_char2cells __ARGS((int c)); -int latin_off2cells __ARGS((unsigned off)); -int dbcs_off2cells __ARGS((unsigned off)); -int utf_off2cells __ARGS((unsigned off)); +int latin_off2cells __ARGS((unsigned off, unsigned max_off)); +int dbcs_off2cells __ARGS((unsigned off, unsigned max_off)); +int utf_off2cells __ARGS((unsigned off, unsigned max_off)); int latin_ptr2char __ARGS((char_u *p)); int utf_ptr2char __ARGS((char_u *p)); int mb_ptr2char_adv __ARGS((char_u **pp)); diff -Naur vim71.orig/src/proto/misc1.pro vim71/src/proto/misc1.pro --- vim71.orig/src/proto/misc1.pro 2007-05-12 06:39:34.000000000 -0400 +++ vim71/src/proto/misc1.pro 2008-06-18 06:53:06.000000000 -0400 @@ -48,10 +48,11 @@ void vim_beep __ARGS((void)); void init_homedir __ARGS((void)); void free_homedir __ARGS((void)); +char_u *expand_env_save __ARGS((char_u *src)); +char_u *expand_env_save_opt __ARGS((char_u *src, int one)); void expand_env __ARGS((char_u *src, char_u *dst, int dstlen)); -void expand_env_esc __ARGS((char_u *srcp, char_u *dst, int dstlen, int esc, char_u *startstr)); +void expand_env_esc __ARGS((char_u *srcp, char_u *dst, int dstlen, int esc, int one, char_u *startstr)); char_u *vim_getenv __ARGS((char_u *name, int *mustfree)); -char_u *expand_env_save __ARGS((char_u *src)); void vim_setenv __ARGS((char_u *name, char_u *val)); char_u *get_env_name __ARGS((expand_T *xp, int idx)); void home_replace __ARGS((buf_T *buf, char_u *src, char_u *dst, int dstlen, int one)); diff -Naur vim71.orig/src/proto/ops.pro vim71/src/proto/ops.pro --- vim71.orig/src/proto/ops.pro 2007-05-12 06:39:40.000000000 -0400 +++ vim71/src/proto/ops.pro 2008-06-18 06:56:15.000000000 -0400 @@ -4,7 +4,7 @@ int get_op_char __ARGS((int optype)); int get_extra_op_char __ARGS((int optype)); void op_shift __ARGS((oparg_T *oap, int curs_top, int amount)); -void shift_line __ARGS((int left, int round, int amount)); +void shift_line __ARGS((int left, int round, int amount, int call_changed_bytes)); void op_reindent __ARGS((oparg_T *oap, int (*how)(void))); int get_expr_register __ARGS((void)); void set_expr_line __ARGS((char_u *new_line)); @@ -41,7 +41,7 @@ void op_format __ARGS((oparg_T *oap, int keep_cursor)); void op_formatexpr __ARGS((oparg_T *oap)); int fex_format __ARGS((linenr_T lnum, long count, int c)); -void format_lines __ARGS((linenr_T line_count)); +void format_lines __ARGS((linenr_T line_count, int avoid_fex)); int paragraph_start __ARGS((linenr_T lnum)); int do_addsub __ARGS((int command, linenr_T Prenum1)); int read_viminfo_register __ARGS((vir_T *virp, int force)); diff -Naur vim71.orig/src/proto/os_unix.pro vim71/src/proto/os_unix.pro --- vim71.orig/src/proto/os_unix.pro 2007-05-12 06:39:43.000000000 -0400 +++ vim71/src/proto/os_unix.pro 2008-06-18 06:56:39.000000000 -0400 @@ -34,6 +34,7 @@ void fname_case __ARGS((char_u *name, int len)); long mch_getperm __ARGS((char_u *name)); int mch_setperm __ARGS((char_u *name, long perm)); +void mch_copy_sec __ARGS((char_u *from_file, char_u *to_file)); vim_acl_T mch_get_acl __ARGS((char_u *fname)); void mch_set_acl __ARGS((char_u *fname, vim_acl_T aclent)); void mch_free_acl __ARGS((vim_acl_T aclent)); diff -Naur vim71.orig/src/proto/regexp.pro vim71/src/proto/regexp.pro --- vim71.orig/src/proto/regexp.pro 2007-05-12 06:39:48.000000000 -0400 +++ vim71/src/proto/regexp.pro 2008-06-18 06:55:25.000000000 -0400 @@ -1,13 +1,13 @@ /* regexp.c */ -void free_regexp_stuff __ARGS((void)); int re_multiline __ARGS((regprog_T *prog)); int re_lookbehind __ARGS((regprog_T *prog)); char_u *skip_regexp __ARGS((char_u *startp, int dirc, int magic, char_u **newp)); regprog_T *vim_regcomp __ARGS((char_u *expr, int re_flags)); int vim_regcomp_had_eol __ARGS((void)); +void free_regexp_stuff __ARGS((void)); int vim_regexec __ARGS((regmatch_T *rmp, char_u *line, colnr_T col)); int vim_regexec_nl __ARGS((regmatch_T *rmp, char_u *line, colnr_T col)); -long vim_regexec_multi __ARGS((regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum, colnr_T col)); +long vim_regexec_multi __ARGS((regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum, colnr_T col, proftime_T *tm)); reg_extmatch_T *ref_extmatch __ARGS((reg_extmatch_T *em)); void unref_extmatch __ARGS((reg_extmatch_T *em)); char_u *regtilde __ARGS((char_u *source, int magic)); diff -Naur vim71.orig/src/proto/search.pro vim71/src/proto/search.pro --- vim71.orig/src/proto/search.pro 2007-05-12 06:39:50.000000000 -0400 +++ vim71/src/proto/search.pro 2008-06-18 06:55:25.000000000 -0400 @@ -1,6 +1,7 @@ /* search.c */ int search_regcomp __ARGS((char_u *pat, int pat_save, int pat_use, int options, regmmatch_T *regmatch)); char_u *get_search_pat __ARGS((void)); +char_u *reverse_text __ARGS((char_u *s)); void save_search_patterns __ARGS((void)); void restore_search_patterns __ARGS((void)); void free_search_patterns __ARGS((void)); @@ -9,8 +10,8 @@ void reset_search_dir __ARGS((void)); void set_last_search_pat __ARGS((char_u *s, int idx, int magic, int setlast)); void last_pat_prog __ARGS((regmmatch_T *regmatch)); -int searchit __ARGS((win_T *win, buf_T *buf, pos_T *pos, int dir, char_u *pat, long count, int options, int pat_use, linenr_T stop_lnum)); -int do_search __ARGS((oparg_T *oap, int dirc, char_u *pat, long count, int options)); +int searchit __ARGS((win_T *win, buf_T *buf, pos_T *pos, int dir, char_u *pat, long count, int options, int pat_use, linenr_T stop_lnum, proftime_T *tm)); +int do_search __ARGS((oparg_T *oap, int dirc, char_u *pat, long count, int options, proftime_T *tm)); int search_for_exact_line __ARGS((buf_T *buf, pos_T *pos, int dir, char_u *pat)); int searchc __ARGS((cmdarg_T *cap, int t_cmd)); pos_T *findmatch __ARGS((oparg_T *oap, int initc)); diff -Naur vim71.orig/src/proto/syntax.pro vim71/src/proto/syntax.pro --- vim71.orig/src/proto/syntax.pro 2007-05-12 06:39:52.000000000 -0400 +++ vim71/src/proto/syntax.pro 2008-06-18 06:55:04.000000000 -0400 @@ -4,13 +4,16 @@ void syn_stack_apply_changes __ARGS((buf_T *buf)); void syntax_end_parsing __ARGS((linenr_T lnum)); int syntax_check_changed __ARGS((linenr_T lnum)); -int get_syntax_attr __ARGS((colnr_T col, int *can_spell)); +int get_syntax_attr __ARGS((colnr_T col, int *can_spell, int keep_state)); void syntax_clear __ARGS((buf_T *buf)); void ex_syntax __ARGS((exarg_T *eap)); int syntax_present __ARGS((buf_T *buf)); +void reset_expand_highlight __ARGS((void)); +void set_context_in_echohl_cmd __ARGS((expand_T *xp, char_u *arg)); void set_context_in_syntax_cmd __ARGS((expand_T *xp, char_u *arg)); char_u *get_syntax_name __ARGS((expand_T *xp, int idx)); -int syn_get_id __ARGS((win_T *wp, long lnum, colnr_T col, int trans, int *spellp)); +int syn_get_id __ARGS((win_T *wp, long lnum, colnr_T col, int trans, int *spellp, int keep_state)); +int syn_get_stack_item __ARGS((int i)); int syn_get_foldlevel __ARGS((win_T *wp, long lnum)); void init_highlight __ARGS((int both, int reset)); int load_colors __ARGS((char_u *name)); diff -Naur vim71.orig/src/proto/window.pro vim71/src/proto/window.pro --- vim71.orig/src/proto/window.pro 2007-05-12 06:40:00.000000000 -0400 +++ vim71/src/proto/window.pro 2008-06-18 06:51:23.000000000 -0400 @@ -59,4 +59,8 @@ int only_one_window __ARGS((void)); void check_lnums __ARGS((int do_curwin)); int win_hasvertsplit __ARGS((void)); +int match_add __ARGS((win_T *wp, char_u *grp, char_u *pat, int prio, int id)); +int match_delete __ARGS((win_T *wp, int id, int perr)); +void clear_matches __ARGS((win_T *wp)); +matchitem_T *get_match __ARGS((win_T *wp, int id)); /* vim: set ft=c : */ diff -Naur vim71.orig/src/quickfix.c vim71/src/quickfix.c --- vim71.orig/src/quickfix.c 2007-02-03 19:50:17.000000000 -0500 +++ vim71/src/quickfix.c 2008-06-18 06:56:25.000000000 -0400 @@ -106,7 +106,9 @@ static int qf_init_ext __ARGS((qf_info_T *qi, char_u *efile, buf_T *buf, typval_T *tv, char_u *errorformat, int newlist, linenr_T lnumfirst, linenr_T lnumlast)); static void qf_new_list __ARGS((qf_info_T *qi)); +static void ll_free_all __ARGS((qf_info_T **pqi)); static int qf_add_entry __ARGS((qf_info_T *qi, qfline_T **prevp, char_u *dir, char_u *fname, int bufnum, char_u *mesg, long lnum, int col, int vis_col, char_u *pattern, int nr, int type, int valid)); +static qf_info_T *ll_new_list __ARGS((void)); static void qf_msg __ARGS((qf_info_T *qi)); static void qf_free __ARGS((qf_info_T *qi, int idx)); static char_u *qf_types __ARGS((int, int)); @@ -1612,8 +1614,8 @@ } /* - * If there is only one window and is the quickfix window, create a new - * one above the quickfix window. + * If there is only one window and it is the quickfix window, create a + * new one above the quickfix window. */ if (((firstwin == lastwin) && bt_quickfix(curbuf)) || !usable_win) { @@ -1803,7 +1805,8 @@ /* Move the cursor to the first line in the buffer */ save_cursor = curwin->w_cursor; curwin->w_cursor.lnum = 0; - if (!do_search(NULL, '/', qf_ptr->qf_pattern, (long)1, SEARCH_KEEP)) + if (!do_search(NULL, '/', qf_ptr->qf_pattern, (long)1, + SEARCH_KEEP, NULL)) curwin->w_cursor = save_cursor; } @@ -2331,7 +2334,7 @@ set_option_value((char_u *)"bt", 0L, (char_u *)"quickfix", OPT_LOCAL); set_option_value((char_u *)"bh", 0L, (char_u *)"wipe", OPT_LOCAL); - set_option_value((char_u *)"diff", 0L, (char_u *)"", OPT_LOCAL); + set_option_value((char_u *)"diff", 0L, NULL, OPT_LOCAL); } /* Only set the height when still in the same tab page and there is no @@ -2981,6 +2984,7 @@ buf_T *buf; int duplicate_name = FALSE; int using_dummy; + int redraw_for_dummy = FALSE; int found_match; buf_T *first_match_buf = NULL; time_t seconds = 0; @@ -3097,6 +3101,7 @@ /* Remember that a buffer with this name already exists. */ duplicate_name = (buf != NULL); using_dummy = TRUE; + redraw_for_dummy = TRUE; #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL) /* Don't do Filetype autocommands to avoid loading syntax and @@ -3135,7 +3140,7 @@ { col = 0; while (vim_regexec_multi(®match, curwin, buf, lnum, - col) > 0) + col, NULL) > 0) { if (qf_add_entry(qi, &prevp, NULL, /* dir */ @@ -3243,11 +3248,29 @@ if (qi->qf_lists[qi->qf_curlist].qf_count > 0) { if ((flags & VGR_NOJUMP) == 0) + { + buf = curbuf; qf_jump(qi, 0, 0, eap->forceit); + if (buf != curbuf) + /* If we jumped to another buffer redrawing will already be + * taken care of. */ + redraw_for_dummy = FALSE; + } } else EMSG2(_(e_nomatch2), s); + /* If we loaded a dummy buffer into the current window, the autocommands + * may have messed up things, need to redraw and recompute folds. */ + if (redraw_for_dummy) + { +#ifdef FEAT_FOLDING + foldUpdateAll(curwin); +#else + redraw_later(NOT_VALID); +#endif + } + theend: vim_free(regmatch.regprog); } diff -Naur vim71.orig/src/regexp.c vim71/src/regexp.c --- vim71.orig/src/regexp.c 2007-05-07 15:50:03.000000000 -0400 +++ vim71/src/regexp.c 2008-06-18 06:57:02.000000000 -0400 @@ -378,14 +378,6 @@ static char_u *reg_prev_sub = NULL; -#if defined(EXITFREE) || defined(PROTO) - void -free_regexp_stuff() -{ - vim_free(reg_prev_sub); -} -#endif - /* * REGEXP_INRANGE contains all characters which are always special in a [] * range after '\'. @@ -1288,8 +1280,7 @@ } /* - * regbranch - one alternative of an | operator - * + * Handle one alternative of an | operator. * Implements the & operator. */ static char_u * @@ -1330,8 +1321,7 @@ } /* - * regbranch - one alternative of an | or & operator - * + * Handle one alternative of an | or & operator. * Implements the concatenation operator. */ static char_u * @@ -1708,6 +1698,8 @@ case Magic('|'): case Magic('&'): case Magic(')'): + if (one_exactly) + EMSG_ONE_RET_NULL; EMSG_RET_NULL(_(e_internal)); /* Supposed to be caught earlier. */ /* NOTREACHED */ @@ -2220,7 +2212,7 @@ break; case CLASS_LOWER: for (cu = 1; cu <= 255; cu++) - if (islower(cu)) + if (MB_ISLOWER(cu)) regc(cu); break; case CLASS_PRINT: @@ -2240,7 +2232,7 @@ break; case CLASS_UPPER: for (cu = 1; cu <= 255; cu++) - if (isupper(cu)) + if (MB_ISUPPER(cu)) regc(cu); break; case CLASS_XDIGIT: @@ -2770,7 +2762,8 @@ { #ifdef FEAT_MBYTE if (enc_utf8) - prevchr_len += utf_char2len(mb_ptr2char(regparse + prevchr_len)); + /* exclude composing chars that mb_ptr2len does include */ + prevchr_len += utf_ptr2len(regparse + prevchr_len); else if (has_mbyte) prevchr_len += (*mb_ptr2len)(regparse + prevchr_len); else @@ -3046,13 +3039,25 @@ } se_u; } save_se_T; +/* used for BEHIND and NOBEHIND matching */ +typedef struct regbehind_S +{ + regsave_T save_after; + regsave_T save_behind; + int save_need_clear_subexpr; + save_se_T save_start[NSUBEXP]; + save_se_T save_end[NSUBEXP]; +} regbehind_T; + static char_u *reg_getline __ARGS((linenr_T lnum)); -static long vim_regexec_both __ARGS((char_u *line, colnr_T col)); +static long vim_regexec_both __ARGS((char_u *line, colnr_T col, proftime_T *tm)); static long regtry __ARGS((regprog_T *prog, colnr_T col)); static void cleanup_subexpr __ARGS((void)); #ifdef FEAT_SYN_HL static void cleanup_zsubexpr __ARGS((void)); #endif +static void save_subexpr __ARGS((regbehind_T *bp)); +static void restore_subexpr __ARGS((regbehind_T *bp)); static void reg_nextline __ARGS((void)); static void reg_save __ARGS((regsave_T *save, garray_T *gap)); static void reg_restore __ARGS((regsave_T *save, garray_T *gap)); @@ -3105,7 +3110,7 @@ * slow, we keep one allocated piece of memory and only re-allocate it when * it's too small. It's freed in vim_regexec_both() when finished. */ -static char_u *reg_tofree; +static char_u *reg_tofree = NULL; static unsigned reg_tofreelen; /* @@ -3173,19 +3178,12 @@ save_se_T sesave; regsave_T regsave; } rs_un; /* room for saving reginput */ - short rs_no; /* submatch nr */ + short rs_no; /* submatch nr or BEHIND/NOBEHIND */ } regitem_T; static regitem_T *regstack_push __ARGS((regstate_T state, char_u *scan)); static void regstack_pop __ARGS((char_u **scan)); -/* used for BEHIND and NOBEHIND matching */ -typedef struct regbehind_S -{ - regsave_T save_after; - regsave_T save_behind; -} regbehind_T; - /* used for STAR, PLUS and BRACE_SIMPLE matching */ typedef struct regstar_S { @@ -3205,12 +3203,39 @@ } backpos_T; /* - * regstack and backpos are used by regmatch(). They are kept over calls to - * avoid invoking malloc() and free() often. + * "regstack" and "backpos" are used by regmatch(). They are kept over calls + * to avoid invoking malloc() and free() often. + * "regstack" is a stack with regitem_T items, sometimes preceded by regstar_T + * or regbehind_T. + * "backpos_T" is a table with backpos_T for BACK + */ +static garray_T regstack = {0, 0, 0, 0, NULL}; +static garray_T backpos = {0, 0, 0, 0, NULL}; + +/* + * Both for regstack and backpos tables we use the following strategy of + * allocation (to reduce malloc/free calls): + * - Initial size is fairly small. + * - When needed, the tables are grown bigger (8 times at first, double after + * that). + * - After executing the match we free the memory only if the array has grown. + * Thus the memory is kept allocated when it's at the initial size. + * This makes it fast while not keeping a lot of memory allocated. + * A three times speed increase was observed when using many simple patterns. */ -static garray_T regstack; /* stack with regitem_T items, sometimes - preceded by regstar_T or regbehind_T. */ -static garray_T backpos; /* table with backpos_T for BACK */ +#define REGSTACK_INITIAL 2048 +#define BACKPOS_INITIAL 64 + +#if defined(EXITFREE) || defined(PROTO) + void +free_regexp_stuff() +{ + ga_clear(®stack); + ga_clear(&backpos); + vim_free(reg_tofree); + vim_free(reg_prev_sub); +} +#endif /* * Get pointer to the line "lnum", which is relative to "reg_firstlnum". @@ -3264,7 +3289,7 @@ ireg_icombine = FALSE; #endif ireg_maxcol = 0; - return (vim_regexec_both(line, col) != 0); + return (vim_regexec_both(line, col, NULL) != 0); } #if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) \ @@ -3288,7 +3313,7 @@ ireg_icombine = FALSE; #endif ireg_maxcol = 0; - return (vim_regexec_both(line, col) != 0); + return (vim_regexec_both(line, col, NULL) != 0); } #endif @@ -3301,12 +3326,13 @@ * match otherwise. */ long -vim_regexec_multi(rmp, win, buf, lnum, col) +vim_regexec_multi(rmp, win, buf, lnum, col, tm) regmmatch_T *rmp; win_T *win; /* window in which to search or NULL */ buf_T *buf; /* buffer in which to search */ linenr_T lnum; /* nr of line to start looking for match */ colnr_T col; /* column to start looking for match */ + proftime_T *tm; /* timeout limit or NULL */ { long r; buf_T *save_curbuf = curbuf; @@ -3326,7 +3352,7 @@ /* Need to switch to buffer "buf" to make vim_iswordc() work. */ curbuf = buf; - r = vim_regexec_both(NULL, col); + r = vim_regexec_both(NULL, col, tm); curbuf = save_curbuf; return r; @@ -3336,24 +3362,36 @@ * Match a regexp against a string ("line" points to the string) or multiple * lines ("line" is NULL, use reg_getline()). */ +/*ARGSUSED*/ static long -vim_regexec_both(line, col) +vim_regexec_both(line, col, tm) char_u *line; colnr_T col; /* column to start looking for match */ + proftime_T *tm; /* timeout limit or NULL */ { regprog_T *prog; char_u *s; long retval = 0L; - reg_tofree = NULL; - - /* Init the regstack empty. Use an item size of 1 byte, since we push - * different things onto it. Use a large grow size to avoid reallocating - * it too often. */ - ga_init2(®stack, 1, 10000); - - /* Init the backpos table empty. */ - ga_init2(&backpos, sizeof(backpos_T), 10); + /* Create "regstack" and "backpos" if they are not allocated yet. + * We allocate *_INITIAL amount of bytes first and then set the grow size + * to much bigger value to avoid many malloc calls in case of deep regular + * expressions. */ + if (regstack.ga_data == NULL) + { + /* Use an item size of 1 byte, since we push different things + * onto the regstack. */ + ga_init2(®stack, 1, REGSTACK_INITIAL); + ga_grow(®stack, REGSTACK_INITIAL); + regstack.ga_growsize = REGSTACK_INITIAL * 8; + } + + if (backpos.ga_data == NULL) + { + ga_init2(&backpos, sizeof(backpos_T), BACKPOS_INITIAL); + ga_grow(&backpos, BACKPOS_INITIAL); + backpos.ga_growsize = BACKPOS_INITIAL * 8; + } if (REG_MULTI) { @@ -3465,13 +3503,16 @@ (enc_utf8 && utf_fold(prog->regstart) == utf_fold(c))) || (c < 255 && prog->regstart < 255 && #endif - TOLOWER_LOC(prog->regstart) == TOLOWER_LOC(c))))) + MB_TOLOWER(prog->regstart) == MB_TOLOWER(c))))) retval = regtry(prog, col); else retval = 0; } else { +#ifdef FEAT_RELTIME + int tm_count = 0; +#endif /* Messy cases: unanchored match. */ while (!got_int) { @@ -3520,13 +3561,30 @@ else #endif ++col; +#ifdef FEAT_RELTIME + /* Check for timeout once in a twenty times to avoid overhead. */ + if (tm != NULL && ++tm_count == 20) + { + tm_count = 0; + if (profile_passed_limit(tm)) + break; + } +#endif } } theend: - vim_free(reg_tofree); - ga_clear(®stack); - ga_clear(&backpos); + /* Free "reg_tofree" when it's a bit big. + * Free regstack and backpos if they are bigger than their initial size. */ + if (reg_tofreelen > 400) + { + vim_free(reg_tofree); + reg_tofree = NULL; + } + if (regstack.ga_maxlen > REGSTACK_INITIAL) + ga_clear(®stack); + if (backpos.ga_maxlen > BACKPOS_INITIAL) + ga_clear(&backpos); return retval; } @@ -3716,8 +3774,8 @@ #define RA_MATCH 4 /* successful match */ #define RA_NOMATCH 5 /* didn't match */ - /* Init the regstack and backpos table empty. They are initialized and - * freed in vim_regexec_both() to reduce malloc()/free() calls. */ + /* Make "regstack" and "backpos" empty. They are allocated and freed in + * vim_regexec_both() to reduce malloc()/free() calls. */ regstack.ga_len = 0; backpos.ga_len = 0; @@ -3809,11 +3867,11 @@ break; case RE_BOF: - /* Passing -1 to the getline() function provided for the search - * should always return NULL if the current line is the first - * line of the file. */ + /* We're not at the beginning of the file when below the first + * line where we started, not at the start of the line or we + * didn't start at the first line of the buffer. */ if (reglnum != 0 || reginput != regline - || (REG_MULTI && reg_getline((linenr_T)-1) != NULL)) + || (REG_MULTI && reg_firstlnum > 1)) status = RA_NOMATCH; break; @@ -4200,7 +4258,7 @@ #ifdef FEAT_MBYTE !enc_utf8 && #endif - TOLOWER_LOC(*opnd) != TOLOWER_LOC(*reginput)))) + MB_TOLOWER(*opnd) != MB_TOLOWER(*reginput)))) status = RA_NOMATCH; else if (*opnd == NUL) { @@ -4733,10 +4791,10 @@ rst.nextb = *OPERAND(next); if (ireg_ic) { - if (isupper(rst.nextb)) - rst.nextb_ic = TOLOWER_LOC(rst.nextb); + if (MB_ISUPPER(rst.nextb)) + rst.nextb_ic = MB_TOLOWER(rst.nextb); else - rst.nextb_ic = TOUPPER_LOC(rst.nextb); + rst.nextb_ic = MB_TOUPPER(rst.nextb); } else rst.nextb_ic = rst.nextb; @@ -4835,6 +4893,10 @@ status = RA_FAIL; else { + /* Need to save the subexpr to be able to restore them + * when there is a match but we don't use it. */ + save_subexpr(((regbehind_T *)rp) - 1); + rp->rs_no = op; reg_save(&rp->rs_un.regsave, &backpos); /* First try if what follows matches. If it does then we @@ -5065,15 +5127,20 @@ reg_restore(&(((regbehind_T *)rp) - 1)->save_after, &backpos); else - /* But we didn't want a match. */ + { + /* But we didn't want a match. Need to restore the + * subexpr, because what follows matched, so they have + * been set. */ status = RA_NOMATCH; + restore_subexpr(((regbehind_T *)rp) - 1); + } regstack_pop(&scan); regstack.ga_len -= sizeof(regbehind_T); } else { - /* No match: Go back one character. May go to previous - * line once. */ + /* No match or a match that doesn't end where we want it: Go + * back one character. May go to previous line once. */ no = OK; if (REG_MULTI) { @@ -5107,6 +5174,13 @@ /* Advanced, prepare for finding match again. */ reg_restore(&rp->rs_un.regsave, &backpos); scan = OPERAND(rp->rs_scan); + if (status == RA_MATCH) + { + /* We did match, so subexpr may have been changed, + * need to restore them for the next try. */ + status = RA_NOMATCH; + restore_subexpr(((regbehind_T *)rp) - 1); + } } else { @@ -5119,7 +5193,16 @@ status = RA_MATCH; } else - status = RA_NOMATCH; + { + /* We do want a proper match. Need to restore the + * subexpr if we had a match, because they may have + * been set. */ + if (status == RA_MATCH) + { + status = RA_NOMATCH; + restore_subexpr(((regbehind_T *)rp) - 1); + } + } regstack_pop(&scan); regstack.ga_len -= sizeof(regbehind_T); } @@ -5558,11 +5641,12 @@ int cu, cl; /* This doesn't do a multi-byte character, because a MULTIBYTECODE - * would have been used for it. */ + * would have been used for it. It does handle single-byte + * characters, such as latin1. */ if (ireg_ic) { - cu = TOUPPER_LOC(*opnd); - cl = TOLOWER_LOC(*opnd); + cu = MB_TOUPPER(*opnd); + cl = MB_TOLOWER(*opnd); while (count < maxcount && (*scan == cu || *scan == cl)) { count++; @@ -5766,6 +5850,66 @@ #endif /* + * Save the current subexpr to "bp", so that they can be restored + * later by restore_subexpr(). + */ + static void +save_subexpr(bp) + regbehind_T *bp; +{ + int i; + + /* When "need_clear_subexpr" is set we don't need to save the values, only + * remember that this flag needs to be set again when restoring. */ + bp->save_need_clear_subexpr = need_clear_subexpr; + if (!need_clear_subexpr) + { + for (i = 0; i < NSUBEXP; ++i) + { + if (REG_MULTI) + { + bp->save_start[i].se_u.pos = reg_startpos[i]; + bp->save_end[i].se_u.pos = reg_endpos[i]; + } + else + { + bp->save_start[i].se_u.ptr = reg_startp[i]; + bp->save_end[i].se_u.ptr = reg_endp[i]; + } + } + } +} + +/* + * Restore the subexpr from "bp". + */ + static void +restore_subexpr(bp) + regbehind_T *bp; +{ + int i; + + /* Only need to restore saved values when they are not to be cleared. */ + need_clear_subexpr = bp->save_need_clear_subexpr; + if (!need_clear_subexpr) + { + for (i = 0; i < NSUBEXP; ++i) + { + if (REG_MULTI) + { + reg_startpos[i] = bp->save_start[i].se_u.pos; + reg_endpos[i] = bp->save_end[i].se_u.pos; + } + else + { + reg_startp[i] = bp->save_start[i].se_u.ptr; + reg_endp[i] = bp->save_end[i].se_u.ptr; + } + } + } +} + +/* * Advance reglnum, regline and reginput to the next line. */ static void @@ -6490,10 +6634,10 @@ cc = utf_fold(c); else #endif - if (isupper(c)) - cc = TOLOWER_LOC(c); - else if (islower(c)) - cc = TOUPPER_LOC(c); + if (MB_ISUPPER(c)) + cc = MB_TOLOWER(c); + else if (MB_ISLOWER(c)) + cc = MB_TOUPPER(c); else return vim_strchr(s, c); @@ -6637,9 +6781,9 @@ } } else if (magic) - STRCPY(p, p + 1); /* remove '~' */ + mch_memmove(p, p + 1, STRLEN(p)); /* remove '~' */ else - STRCPY(p, p + 2); /* remove '\~' */ + mch_memmove(p, p + 2, STRLEN(p) - 1); /* remove '\~' */ --p; } else @@ -7014,7 +7158,14 @@ #ifdef FEAT_MBYTE if (has_mbyte) { - int l = mb_ptr2len(s) - 1; + int l; + + /* Copy composing characters separately, one + * at a time. */ + if (enc_utf8) + l = utf_ptr2len(s) - 1; + else + l = mb_ptr2len(s) - 1; s += l; len -= l; diff -Naur vim71.orig/src/screen.c vim71/src/screen.c --- vim71.orig/src/screen.c 2007-05-07 15:27:53.000000000 -0400 +++ vim71/src/screen.c 2008-06-18 06:56:45.000000000 -0400 @@ -100,27 +100,7 @@ static int screen_cur_row, screen_cur_col; /* last known cursor position */ #ifdef FEAT_SEARCH_EXTRA -/* - * Struct used for highlighting 'hlsearch' matches for the last use search - * pattern or a ":match" item. - * For 'hlsearch' there is one pattern for all windows. For ":match" there is - * a different pattern for each window. - */ -typedef struct -{ - regmmatch_T rm; /* points to the regexp program; contains last found - match (may continue in next line) */ - buf_T *buf; /* the buffer to search for a match */ - linenr_T lnum; /* the line to search for a match */ - int attr; /* attributes to be used for a match */ - int attr_cur; /* attributes currently active in win_line() */ - linenr_T first_lnum; /* first lnum to search for multi-line pat */ - colnr_T startcol; /* in win_line() points to char where HL starts */ - colnr_T endcol; /* in win_line() points to char where HL ends */ -} match_T; - static match_T search_hl; /* used for 'hlsearch' highlight matching */ -static match_T match_hl[3]; /* used for ":match" highlight matching */ #endif #ifdef FEAT_FOLDING @@ -155,6 +135,7 @@ static void redraw_custum_statusline __ARGS((win_T *wp)); #endif #ifdef FEAT_SEARCH_EXTRA +#define SEARCH_HL_PRIORITY 0 static void start_search_hl __ARGS((void)); static void end_search_hl __ARGS((void)); static void prepare_search_hl __ARGS((win_T *wp, linenr_T lnum)); @@ -350,6 +331,11 @@ { if (type < must_redraw) /* use maximal type */ type = must_redraw; + + /* must_redraw is reset here, so that when we run into some weird + * reason to redraw while busy redrawing (e.g., asynchronous + * scrolling), or update_topline() in win_update() will cause a + * scroll, the screen will be redrawn later or in win_update(). */ must_redraw = 0; } @@ -787,6 +773,7 @@ w_topline got smaller a bit */ #endif #ifdef FEAT_SEARCH_EXTRA + matchitem_T *cur; /* points to the match list */ int top_to_mod = FALSE; /* redraw above mod_top */ #endif @@ -848,22 +835,29 @@ #endif #ifdef FEAT_SEARCH_EXTRA - /* Setup for ":match" and 'hlsearch' highlighting. Disable any previous + /* Setup for match and 'hlsearch' highlighting. Disable any previous * match */ - for (i = 0; i < 3; ++i) + cur = wp->w_match_head; + while (cur != NULL) { - match_hl[i].rm = wp->w_match[i]; - if (wp->w_match_id[i] == 0) - match_hl[i].attr = 0; - else - match_hl[i].attr = syn_id2attr(wp->w_match_id[i]); - match_hl[i].buf = buf; - match_hl[i].lnum = 0; - match_hl[i].first_lnum = 0; + cur->hl.rm = cur->match; + if (cur->hlg_id == 0) + cur->hl.attr = 0; + else + cur->hl.attr = syn_id2attr(cur->hlg_id); + cur->hl.buf = buf; + cur->hl.lnum = 0; + cur->hl.first_lnum = 0; +# ifdef FEAT_RELTIME + /* Set the time limit to 'redrawtime'. */ + profile_setlimit(p_rdt, &(cur->hl.tm)); +# endif + cur = cur->next; } search_hl.buf = buf; search_hl.lnum = 0; search_hl.first_lnum = 0; + /* time limit is set at the toplevel, for all windows */ #endif #ifdef FEAT_LINEBREAK @@ -923,19 +917,25 @@ * change in one line may make the Search highlighting in a * previous line invalid. Simple solution: redraw all visible * lines above the change. - * Same for a ":match" pattern. + * Same for a match pattern. */ if (search_hl.rm.regprog != NULL && re_multiline(search_hl.rm.regprog)) top_to_mod = TRUE; else - for (i = 0; i < 3; ++i) - if (match_hl[i].rm.regprog != NULL - && re_multiline(match_hl[i].rm.regprog)) + { + cur = wp->w_match_head; + while (cur != NULL) + { + if (cur->match.regprog != NULL + && re_multiline(cur->match.regprog)) { top_to_mod = TRUE; break; } + cur = cur->next; + } + } #endif } #ifdef FEAT_FOLDING @@ -1029,6 +1029,13 @@ type = VALID; } + /* Trick: we want to avoid clearing the screen twice. screenclear() will + * set "screen_cleared" to TRUE. The special value MAYBE (which is still + * non-zero and thus not FALSE) will indicate that screenclear() was not + * called. */ + if (screen_cleared) + screen_cleared = MAYBE; + /* * If there are no changes on the screen that require a complete redraw, * handle three cases: @@ -1230,7 +1237,11 @@ mid_end = wp->w_height; if (lastwin == firstwin) { - screenclear(); + /* Clear the screen when it was not done by win_del_lines() or + * win_ins_lines() above, "screen_cleared" is FALSE or MAYBE + * then. */ + if (screen_cleared != TRUE) + screenclear(); #ifdef FEAT_WINDOWS /* The screen was cleared, redraw the tab pages line. */ if (redraw_tabline) @@ -1238,6 +1249,13 @@ #endif } } + + /* When win_del_lines() or win_ins_lines() caused the screen to be + * cleared (only happens for the first window) or when screenclear() + * was called directly above, "must_redraw" will have been set to + * NOT_VALID, need to reset it here to avoid redrawing twice. */ + if (screen_cleared == TRUE) + must_redraw = 0; } else { @@ -2292,9 +2310,11 @@ prev_c = u8c; #endif /* Non-BMP character: display as ? or fullwidth ?. */ +#ifdef UNICODE16 if (u8c >= 0x10000) ScreenLinesUC[idx] = (cells == 2) ? 0xff1f : (int)'?'; else +#endif ScreenLinesUC[idx] = u8c; for (i = 0; i < Screen_mco; ++i) { @@ -2542,7 +2562,7 @@ char_u extra[18]; /* "%ld" and 'fdc' must fit in here */ int n_extra = 0; /* number of extra chars */ - char_u *p_extra = NULL; /* string of extra chars */ + char_u *p_extra = NULL; /* string of extra chars, plus NUL */ int c_extra = NUL; /* extra chars, all the same */ int extra_attr = 0; /* attributes when n_extra != 0 */ static char_u *at_end_str = (char_u *)""; /* used for p_extra when @@ -2584,6 +2604,7 @@ int syntax_attr = 0; /* attributes desired by syntax */ int has_syntax = FALSE; /* this buffer has syntax highl. */ int save_did_emsg; + int eol_hl_off = 0; /* 1 if highlighted char after EOL */ #endif #ifdef FEAT_SPELL int has_spell = FALSE; /* this buffer has spell checking */ @@ -2623,13 +2644,16 @@ #if defined(FEAT_SIGNS) || (defined(FEAT_QUICKFIX) && defined(FEAT_WINDOWS)) \ || defined(FEAT_SYN_HL) || defined(FEAT_DIFF) # define LINE_ATTR - int line_attr = 0; /* atrribute for the whole line */ + int line_attr = 0; /* attribute for the whole line */ #endif #ifdef FEAT_SEARCH_EXTRA - match_T *shl; /* points to search_hl or match_hl */ -#endif -#if defined(FEAT_SEARCH_EXTRA) || defined(FEAT_MBYTE) - int i; + matchitem_T *cur; /* points to the match list */ + match_T *shl; /* points to search_hl or a match */ + int shl_flag; /* flag to indicate whether search_hl + has been processed or not */ + int prevcol_hl_flag; /* flag to indicate whether prevcol + equals startcol of search_hl or one + of the matches */ #endif #ifdef FEAT_ARABIC int prev_c = 0; /* previous Arabic character */ @@ -3016,18 +3040,25 @@ if (has_spell) { int len; + colnr_T linecol = (colnr_T)(ptr - line); hlf_T spell_hlf = HLF_COUNT; pos = wp->w_cursor; wp->w_cursor.lnum = lnum; - wp->w_cursor.col = (colnr_T)(ptr - line); + wp->w_cursor.col = linecol; len = spell_move_to(wp, FORWARD, TRUE, TRUE, &spell_hlf); + + /* spell_move_to() may call ml_get() and make "line" invalid */ + line = ml_get_buf(wp->w_buffer, lnum, FALSE); + ptr = line + linecol; + if (len == 0 || (int)wp->w_cursor.col > ptr - line) { /* no bad word found at line start, don't check until end of a * word */ spell_hlf = HLF_COUNT; - word_end = (int)(spell_to_word_end(ptr, wp->w_buffer) - line + 1); + word_end = (int)(spell_to_word_end(ptr, wp->w_buffer) + - line + 1); } else { @@ -3074,12 +3105,20 @@ #ifdef FEAT_SEARCH_EXTRA /* - * Handle highlighting the last used search pattern and ":match". - * Do this for both search_hl and match_hl[3]. + * Handle highlighting the last used search pattern and matches. + * Do this for both search_hl and the match list. */ - for (i = 3; i >= 0; --i) + cur = wp->w_match_head; + shl_flag = FALSE; + while (cur != NULL || shl_flag == FALSE) { - shl = (i == 3) ? &search_hl : &match_hl[i]; + if (shl_flag == FALSE) + { + shl = &search_hl; + shl_flag = TRUE; + } + else + shl = &cur->hl; shl->startcol = MAXCOL; shl->endcol = MAXCOL; shl->attr_cur = 0; @@ -3122,6 +3161,8 @@ area_highlighting = TRUE; } } + if (shl != &search_hl && cur != NULL) + cur = cur->next; } #endif @@ -3163,10 +3204,8 @@ if (cmdwin_type != 0 && wp == curwin) { /* Draw the cmdline character. */ - *extra = cmdwin_type; n_extra = 1; - p_extra = extra; - c_extra = NUL; + c_extra = cmdwin_type; char_attr = hl_attr(HLF_AT); } } @@ -3182,6 +3221,7 @@ fill_foldcolumn(extra, wp, FALSE, lnum); n_extra = wp->w_p_fdc; p_extra = extra; + p_extra[n_extra] = NUL; c_extra = NUL; char_attr = hl_attr(HLF_FC); } @@ -3388,13 +3428,24 @@ * After end, check for start/end of next match. * When another match, have to check for start again. * Watch out for matching an empty string! - * Do this first for search_hl, then for match_hl, so that - * ":match" overrules 'hlsearch'. + * Do this for 'search_hl' and the match list (ordered by + * priority). */ v = (long)(ptr - line); - for (i = 3; i >= 0; --i) - { - shl = (i == 3) ? &search_hl : &match_hl[i]; + cur = wp->w_match_head; + shl_flag = FALSE; + while (cur != NULL || shl_flag == FALSE) + { + if (shl_flag == FALSE + && ((cur != NULL + && cur->priority > SEARCH_HL_PRIORITY) + || cur == NULL)) + { + shl = &search_hl; + shl_flag = TRUE; + } + else + shl = &cur->hl; while (shl->rm.regprog != NULL) { if (shl->startcol != MAXCOL @@ -3442,26 +3493,43 @@ } break; } + if (shl != &search_hl && cur != NULL) + cur = cur->next; } - /* ":match" highlighting overrules 'hlsearch' */ - for (i = 0; i <= 3; ++i) - if (i == 3) - search_attr = search_hl.attr_cur; - else if (match_hl[i].attr_cur != 0) + /* Use attributes from match with highest priority among + * 'search_hl' and the match list. */ + search_attr = search_hl.attr_cur; + cur = wp->w_match_head; + shl_flag = FALSE; + while (cur != NULL || shl_flag == FALSE) + { + if (shl_flag == FALSE + && ((cur != NULL + && cur->priority > SEARCH_HL_PRIORITY) + || cur == NULL)) { - search_attr = match_hl[i].attr_cur; - break; + shl = &search_hl; + shl_flag = TRUE; } + else + shl = &cur->hl; + if (shl->attr_cur != 0) + search_attr = shl->attr_cur; + if (shl != &search_hl && cur != NULL) + cur = cur->next; + } } #endif #ifdef FEAT_DIFF if (diff_hlf != (hlf_T)0) { - if (diff_hlf == HLF_CHD && ptr - line >= change_start) + if (diff_hlf == HLF_CHD && ptr - line >= change_start + && n_extra == 0) diff_hlf = HLF_TXD; /* changed text */ - if (diff_hlf == HLF_TXD && ptr - line > change_end) + if (diff_hlf == HLF_TXD && ptr - line > change_end + && n_extra == 0) diff_hlf = HLF_CHD; /* changed line */ line_attr = hl_attr(diff_hlf); } @@ -3496,9 +3564,11 @@ * Get the next character to put on the screen. */ /* - * The 'extra' array contains the extra stuff that is inserted to - * represent special characters (non-printable stuff). When all - * characters are the same, c_extra is used. + * The "p_extra" points to the extra stuff that is inserted to + * represent special characters (non-printable stuff) and other + * things. When all characters are the same, c_extra is used. + * "p_extra" must end in a NUL to avoid mb_ptr2len() reads past + * "p_extra[n_extra]". * For the '$' of the 'list' option, n_extra == 1, p_extra == "". */ if (n_extra > 0) @@ -3611,6 +3681,8 @@ * Draw it as a space with a composing char. */ if (utf_iscomposing(mb_c)) { + int i; + for (i = Screen_mco - 1; i > 0; --i) u8cc[i] = u8cc[i - 1]; u8cc[0] = mb_c; @@ -3621,13 +3693,18 @@ if ((mb_l == 1 && c >= 0x80) || (mb_l >= 1 && mb_c == 0) || (mb_l > 1 && (!vim_isprintc(mb_c) - || mb_c >= 0x10000))) +# ifdef UNICODE16 + || mb_c >= 0x10000 +# endif + ))) { /* * Illegal UTF-8 byte: display as . * Non-BMP character : display as ? or fullwidth ?. */ +# ifdef UNICODE16 if (mb_c < 0x10000) +# endif { transchar_hex(extra, mb_c); # ifdef FEAT_RIGHTLEFT @@ -3635,11 +3712,13 @@ rl_mirror(extra); # endif } +# ifdef UNICODE16 else if (utf_char2cells(mb_c) != 2) STRCPY(extra, "?"); else /* 0xff1f in UTF-8: full-width '?' */ STRCPY(extra, "\357\274\237"); +# endif p_extra = extra; c = *p_extra; @@ -3752,10 +3831,8 @@ * a '<' in the first column. */ if (n_skip > 0 && mb_l > 1) { - extra[0] = '<'; - p_extra = extra; n_extra = 1; - c_extra = NUL; + c_extra = '<'; c = ' '; if (area_attr == 0 && search_attr == 0) { @@ -3820,7 +3897,7 @@ # ifdef FEAT_SPELL has_spell ? &can_spell : # endif - NULL); + NULL, FALSE); if (did_emsg) { @@ -4248,20 +4325,39 @@ { #ifdef FEAT_SEARCH_EXTRA long prevcol = (long)(ptr - line) - (c == NUL); + + /* we're not really at that column when skipping some text */ + if ((long)(wp->w_p_wrap ? wp->w_skipcol : wp->w_leftcol) > prevcol) + ++prevcol; #endif /* invert at least one char, used for Visual and empty line or * highlight match at end of line. If it's beyond the last * char on the screen, just overwrite that one (tricky!) Not * needed when a '$' was displayed for 'list'. */ +#ifdef FEAT_SEARCH_EXTRA + prevcol_hl_flag = FALSE; + if (prevcol == (long)search_hl.startcol) + prevcol_hl_flag = TRUE; + else + { + cur = wp->w_match_head; + while (cur != NULL) + { + if (prevcol == (long)cur->hl.startcol) + { + prevcol_hl_flag = TRUE; + break; + } + cur = cur->next; + } + } +#endif if (lcs_eol == lcs_eol_one && ((area_attr != 0 && vcol == fromcol && c == NUL) #ifdef FEAT_SEARCH_EXTRA /* highlight 'hlsearch' match at end of line */ - || ((prevcol == (long)search_hl.startcol - || prevcol == (long)match_hl[0].startcol - || prevcol == (long)match_hl[1].startcol - || prevcol == (long)match_hl[2].startcol) + || (prevcol_hl_flag == TRUE # if defined(LINE_ATTR) && did_line_attr <= 1 # endif @@ -4302,26 +4398,47 @@ #ifdef FEAT_SEARCH_EXTRA if (area_attr == 0) { - for (i = 0; i <= 3; ++i) - { - if (i == 3) - char_attr = search_hl.attr; - else if ((ptr - line) - 1 == (long)match_hl[i].startcol) + /* Use attributes from match with highest priority among + * 'search_hl' and the match list. */ + char_attr = search_hl.attr; + cur = wp->w_match_head; + shl_flag = FALSE; + while (cur != NULL || shl_flag == FALSE) + { + if (shl_flag == FALSE + && ((cur != NULL + && cur->priority > SEARCH_HL_PRIORITY) + || cur == NULL)) { - char_attr = match_hl[i].attr; - break; + shl = &search_hl; + shl_flag = TRUE; } + else + shl = &cur->hl; + if ((ptr - line) - 1 == (long)shl->startcol) + char_attr = shl->attr; + if (shl != &search_hl && cur != NULL) + cur = cur->next; } } #endif ScreenAttrs[off] = char_attr; #ifdef FEAT_RIGHTLEFT if (wp->w_p_rl) + { --col; + --off; + } else #endif + { ++col; + ++off; + } ++vcol; +#ifdef FEAT_SYN_HL + eol_hl_off = 1; +#endif } } @@ -4331,6 +4448,14 @@ if (c == NUL) { #ifdef FEAT_SYN_HL + if (eol_hl_off > 0 && vcol - eol_hl_off == (long)wp->w_virtcol) + { + /* highlight last char after line */ + --col; + --off; + --vcol; + } + /* Highlight 'cursorcolumn' past end of the line. */ if (wp->w_p_wrap) v = wp->w_skipcol; @@ -4341,7 +4466,7 @@ vcol = v + col - win_col_off(wp); if (wp->w_p_cuc - && (int)wp->w_virtcol >= vcol + && (int)wp->w_virtcol >= vcol - eol_hl_off && (int)wp->w_virtcol < W_WIDTH(wp) * (row - startrow + 1) + v && lnum != wp->w_cursor.lnum @@ -4402,7 +4527,7 @@ #endif col == W_WIDTH(wp) - 1) && (*ptr != NUL - || (wp->w_p_list && lcs_eol != NUL && p_extra != at_end_str) + || (wp->w_p_list && lcs_eol_one > 0) || (n_extra && (c_extra != NUL || *p_extra != NUL)))) { c = lcs_ext; @@ -4460,6 +4585,8 @@ { if (mb_utf8) { + int i; + ScreenLinesUC[off] = mb_c; if ((c & 0xff) == 0) ScreenLines[off] = 0x80; /* avoid storing zero */ @@ -4548,7 +4675,7 @@ /* * At end of screen line and there is more to come: Display the line - * so far. If there is no more to display it is catched above. + * so far. If there is no more to display it is caught above. */ if (( #ifdef FEAT_RIGHTLEFT @@ -4625,9 +4752,13 @@ #endif #ifdef FEAT_MBYTE && !(has_mbyte - && ((*mb_off2cells)(LineOffset[screen_row]) == 2 + && ((*mb_off2cells)(LineOffset[screen_row], + LineOffset[screen_row] + screen_Columns) + == 2 || (*mb_off2cells)(LineOffset[screen_row - 1] - + (int)Columns - 2) == 2)) + + (int)Columns - 2, + LineOffset[screen_row] + screen_Columns) + == 2)) #endif ) { @@ -4787,6 +4918,10 @@ { unsigned off_from; unsigned off_to; +#ifdef FEAT_MBYTE + unsigned max_off_from; + unsigned max_off_to; +#endif int col = 0; #if defined(FEAT_GUI) || defined(UNIX) || defined(FEAT_VERTSPLIT) int hl; @@ -4813,6 +4948,10 @@ off_from = (unsigned)(current_ScreenLine - ScreenLines); off_to = LineOffset[row] + coloff; +#ifdef FEAT_MBYTE + max_off_from = off_from + screen_Columns; + max_off_to = LineOffset[row] + screen_Columns; +#endif #ifdef FEAT_RIGHTLEFT if (rlflag) @@ -4847,7 +4986,7 @@ { #ifdef FEAT_MBYTE if (has_mbyte && (col + 1 < endcol)) - char_cells = (*mb_off2cells)(off_from); + char_cells = (*mb_off2cells)(off_from, max_off_from); else char_cells = 1; #endif @@ -4924,7 +5063,7 @@ * ScreenLinesUC[] is sufficient. */ if (char_cells == 1 && col + 1 < endcol - && (*mb_off2cells)(off_to) > 1) + && (*mb_off2cells)(off_to, max_off_to) > 1) { /* Writing a single-cell character over a double-cell * character: need to redraw the next cell. */ @@ -4933,8 +5072,8 @@ } else if (char_cells == 2 && col + 2 < endcol - && (*mb_off2cells)(off_to) == 1 - && (*mb_off2cells)(off_to + 1) > 1) + && (*mb_off2cells)(off_to, max_off_to) == 1 + && (*mb_off2cells)(off_to + 1, max_off_to) > 1) { /* Writing the second half of a double-cell character over * a double-cell character: need to redraw the second @@ -4953,10 +5092,10 @@ * char over the left halve of an existing one. */ if (has_mbyte && col + char_cells == endcol && ((char_cells == 1 - && (*mb_off2cells)(off_to) > 1) + && (*mb_off2cells)(off_to, max_off_to) > 1) || (char_cells == 2 - && (*mb_off2cells)(off_to) == 1 - && (*mb_off2cells)(off_to + 1) > 1))) + && (*mb_off2cells)(off_to, max_off_to) == 1 + && (*mb_off2cells)(off_to + 1, max_off_to) > 1))) clear_next = TRUE; #endif @@ -5096,10 +5235,11 @@ /* find previous character by counting from first * column and get its width. */ unsigned off = LineOffset[row]; + unsigned max_off = LineOffset[row] + screen_Columns; while (off < off_to) { - prev_cells = (*mb_off2cells)(off); + prev_cells = (*mb_off2cells)(off, max_off); off += prev_cells; } } @@ -5285,7 +5425,7 @@ static int skip_status_match_char __ARGS((expand_T *xp, char_u *s)); /* - * Get the lenght of an item as it will be shown in the status line. + * Get the length of an item as it will be shown in the status line. */ static int status_match_len(xp, s) @@ -5351,7 +5491,7 @@ int row; char_u *buf; int len; - int clen; /* lenght in screen cells */ + int clen; /* length in screen cells */ int fillchar; int attr; int i; @@ -6103,6 +6243,7 @@ char_u *ptr = text; int c; #ifdef FEAT_MBYTE + unsigned max_off; int mbyte_blen = 1; int mbyte_cells = 1; int u8c = 0; @@ -6119,8 +6260,12 @@ return; off = LineOffset[row] + col; - while (*ptr != NUL && col < screen_Columns - && (len < 0 || (int)(ptr - text) < len)) +#ifdef FEAT_MBYTE + max_off = LineOffset[row] + screen_Columns; +#endif + while (col < screen_Columns + && (len < 0 || (int)(ptr - text) < len) + && *ptr != NUL) { c = *ptr; #ifdef FEAT_MBYTE @@ -6143,6 +6288,7 @@ else u8c = utfc_ptr2char(ptr, u8cc); mbyte_cells = utf_char2cells(u8c); +# ifdef UNICODE16 /* Non-BMP character: display as ? or fullwidth ?. */ if (u8c >= 0x10000) { @@ -6150,6 +6296,7 @@ if (attr == 0) attr = hl_attr(HLF_8); } +# endif # ifdef FEAT_ARABIC if (p_arshape && !p_tbidi && ARABIC_CHAR(u8c)) { @@ -6241,19 +6388,19 @@ else if (has_mbyte && (len < 0 ? ptr[mbyte_blen] == NUL : ptr + mbyte_blen >= text + len) - && ((mbyte_cells == 1 && (*mb_off2cells)(off) > 1) + && ((mbyte_cells == 1 && (*mb_off2cells)(off, max_off) > 1) || (mbyte_cells == 2 - && (*mb_off2cells)(off) == 1 - && (*mb_off2cells)(off + 1) > 1))) + && (*mb_off2cells)(off, max_off) == 1 + && (*mb_off2cells)(off + 1, max_off) > 1))) clear_next_cell = TRUE; /* Make sure we never leave a second byte of a double-byte behind, * it confuses mb_off2cells(). */ if (enc_dbcs - && ((mbyte_cells == 1 && (*mb_off2cells)(off) > 1) + && ((mbyte_cells == 1 && (*mb_off2cells)(off, max_off) > 1) || (mbyte_cells == 2 - && (*mb_off2cells)(off) == 1 - && (*mb_off2cells)(off + 1) > 1))) + && (*mb_off2cells)(off, max_off) == 1 + && (*mb_off2cells)(off + 1, max_off) > 1))) ScreenLines[off + mbyte_blen] = 0; #endif ScreenLines[off] = c; @@ -6318,7 +6465,7 @@ #ifdef FEAT_SEARCH_EXTRA /* - * Prepare for 'searchhl' highlighting. + * Prepare for 'hlsearch' highlighting. */ static void start_search_hl() @@ -6327,11 +6474,15 @@ { last_pat_prog(&search_hl.rm); search_hl.attr = hl_attr(HLF_L); +# ifdef FEAT_RELTIME + /* Set the time limit to 'redrawtime'. */ + profile_setlimit(p_rdt, &search_hl.tm); +# endif } } /* - * Clean up for 'searchhl' highlighting. + * Clean up for 'hlsearch' highlighting. */ static void end_search_hl() @@ -6351,18 +6502,28 @@ win_T *wp; linenr_T lnum; { - match_T *shl; /* points to search_hl or match_hl */ + matchitem_T *cur; /* points to the match list */ + match_T *shl; /* points to search_hl or a match */ + int shl_flag; /* flag to indicate whether search_hl + has been processed or not */ int n; - int i; /* * When using a multi-line pattern, start searching at the top * of the window or just after a closed fold. - * Do this both for search_hl and match_hl[3]. + * Do this both for search_hl and the match list. */ - for (i = 3; i >= 0; --i) + cur = wp->w_match_head; + shl_flag = FALSE; + while (cur != NULL || shl_flag == FALSE) { - shl = (i == 3) ? &search_hl : &match_hl[i]; + if (shl_flag == FALSE) + { + shl = &search_hl; + shl_flag = TRUE; + } + else + shl = &cur->hl; if (shl->rm.regprog != NULL && shl->lnum == 0 && re_multiline(shl->rm.regprog)) @@ -6397,11 +6558,13 @@ } } } + if (shl != &search_hl && cur != NULL) + cur = cur->next; } } /* - * Search for a next 'searchl' or ":match" match. + * Search for a next 'hlsearch' or match. * Uses shl->buf. * Sets shl->lnum and shl->rm contents. * Note: Assumes a previous match is always before "lnum", unless @@ -6411,7 +6574,7 @@ static void next_search_hl(win, shl, lnum, mincol) win_T *win; - match_T *shl; /* points to search_hl or match_hl */ + match_T *shl; /* points to search_hl or a match */ linenr_T lnum; colnr_T mincol; /* minimal column for a match */ { @@ -6440,6 +6603,14 @@ called_emsg = FALSE; for (;;) { +#ifdef FEAT_RELTIME + /* Stop searching after passing the time limit. */ + if (profile_passed_limit(&(shl->tm))) + { + shl->lnum = 0; /* no match found in time */ + break; + } +#endif /* Three situations: * 1. No useful previous match: search from start of line. * 2. Not Vi compatible or empty match: continue at next character. @@ -6473,13 +6644,19 @@ matchcol = shl->rm.endpos[0].col; shl->lnum = lnum; - nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, matchcol); + nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, matchcol, +#ifdef FEAT_RELTIME + &(shl->tm) +#else + NULL +#endif + ); if (called_emsg) { /* Error while handling regexp: stop using this regexp. */ if (shl == &search_hl) { - /* don't free the regprog in match_hl[], it's a copy */ + /* don't free regprog in the match list, it's a copy */ vim_free(shl->rm.regprog); no_hlsearch = TRUE; } @@ -6827,6 +7004,9 @@ { int r, c; int off; +#ifdef FEAT_MBYTE + int max_off; +#endif /* Can't use ScreenLines unless initialized */ if (ScreenLines == NULL) @@ -6837,10 +7017,13 @@ for (r = row; r < row + height; ++r) { off = LineOffset[r]; +#ifdef FEAT_MBYTE + max_off = off + screen_Columns; +#endif for (c = col; c < col + width; ++c) { #ifdef FEAT_MBYTE - if (enc_dbcs != 0 && dbcs_off2cells(off + c) > 1) + if (enc_dbcs != 0 && dbcs_off2cells(off + c, max_off) > 1) { screen_char_2(off + c, r, c); ++c; @@ -6850,7 +7033,7 @@ { screen_char(off + c, r, c); #ifdef FEAT_MBYTE - if (utf_off2cells(off + c) > 1) + if (utf_off2cells(off + c, max_off) > 1) ++c; #endif } @@ -7862,9 +8045,13 @@ windgoto(W_WINROW(curwin) + curwin->w_wrow, W_WINCOL(curwin) + ( #ifdef FEAT_RIGHTLEFT + /* With 'rightleft' set and the cursor on a double-wide + * character, position it on the leftmost column. */ curwin->w_p_rl ? ((int)W_WIDTH(curwin) - curwin->w_wcol - ( # ifdef FEAT_MBYTE - has_mbyte ? (*mb_ptr2cells)(ml_get_cursor()) : + (has_mbyte + && (*mb_ptr2cells)(ml_get_cursor()) == 2 + && vim_isprintc(gchar_cursor())) ? 2 : # endif 1)) : #endif @@ -9170,6 +9357,11 @@ ) maketitle(); #endif +#ifdef FEAT_WINDOWS + /* Redraw the tab pages line if needed. */ + if (redraw_tabline) + draw_tabline(); +#endif } #ifdef FEAT_CMDL_INFO diff -Naur vim71.orig/src/search.c vim71/src/search.c --- vim71.orig/src/search.c 2007-05-07 15:42:02.000000000 -0400 +++ vim71/src/search.c 2008-06-18 06:56:06.000000000 -0400 @@ -101,7 +101,6 @@ static char_u *mr_pattern = NULL; /* pattern used by search_regcomp() */ #ifdef FEAT_RIGHTLEFT static int mr_pattern_alloced = FALSE; /* mr_pattern was allocated */ -static char_u *reverse_text __ARGS((char_u *s)); #endif #ifdef FEAT_FIND_ID @@ -228,12 +227,12 @@ return mr_pattern; } -#ifdef FEAT_RIGHTLEFT +#if defined(FEAT_RIGHTLEFT) || defined(PROTO) /* * Reverse text into allocated memory. * Returns the allocated string, NULL when out of memory. */ - static char_u * + char_u * reverse_text(s) char_u *s; { @@ -495,8 +494,9 @@ * When FEAT_EVAL is defined, returns the index of the first matching * subpattern plus one; one if there was none. */ +/*ARGSUSED*/ int -searchit(win, buf, pos, dir, pat, count, options, pat_use, stop_lnum) +searchit(win, buf, pos, dir, pat, count, options, pat_use, stop_lnum, tm) win_T *win; /* window to search in; can be NULL for a buffer without a window! */ buf_T *buf; @@ -507,6 +507,7 @@ int options; int pat_use; /* which pattern to use when "pat" is empty */ linenr_T stop_lnum; /* stop after this line number when != 0 */ + proftime_T *tm; /* timeout limit or NULL */ { int found; linenr_T lnum; /* no init to shut up Apollo cc */ @@ -537,7 +538,10 @@ return FAIL; } - if (options & SEARCH_START) + /* When not accepting a match at the start position set "extra_col" to a + * non-zero value. Don't do that when starting at MAXCOL, since MAXCOL + + * 1 is zero. */ + if ((options & SEARCH_START) || pos->col == MAXCOL) extra_col = 0; #ifdef FEAT_MBYTE /* Watch out for the "col" being MAXCOL - 2, used in a closed fold. */ @@ -573,8 +577,12 @@ /* * Start searching in current line, unless searching backwards and * we're in column 0. + * If we are searching backwards, in column 0, and not including the + * current position, gain some efficiency by skipping back a line. + * Otherwise begin the search in the current line. */ - if (dir == BACKWARD && start_pos.col == 0) + if (dir == BACKWARD && start_pos.col == 0 + && (options & SEARCH_START) == 0) { lnum = pos->lnum - 1; at_first_line = FALSE; @@ -591,12 +599,23 @@ if (stop_lnum != 0 && (dir == FORWARD ? lnum > stop_lnum : lnum < stop_lnum)) break; +#ifdef FEAT_RELTIME + /* Stop after passing the "tm" time limit. */ + if (tm != NULL && profile_passed_limit(tm)) + break; +#endif /* * Look for a match somewhere in line "lnum". */ nmatched = vim_regexec_multi(®match, win, buf, - lnum, (colnr_T)0); + lnum, (colnr_T)0, +#ifdef FEAT_RELTIME + tm +#else + NULL +#endif + ); /* Abort searching on an error (e.g., out of stack). */ if (called_emsg) break; @@ -605,10 +624,10 @@ /* match may actually be in another line when using \zs */ matchpos = regmatch.startpos[0]; endpos = regmatch.endpos[0]; -# ifdef FEAT_EVAL +#ifdef FEAT_EVAL submatch = first_submatch(®match); -# endif - /* Line me be past end of buffer for "\n\zs". */ +#endif + /* "lnum" may be past end of buffer for "\n\zs". */ if (lnum + matchpos.lnum > buf->b_ml.ml_line_count) ptr = (char_u *)""; else @@ -683,7 +702,13 @@ if (ptr[matchcol] == NUL || (nmatched = vim_regexec_multi(®match, win, buf, lnum + matchpos.lnum, - matchcol)) == 0) + matchcol, +#ifdef FEAT_RELTIME + tm +#else + NULL +#endif + )) == 0) { match_ok = FALSE; break; @@ -789,7 +814,13 @@ if (ptr[matchcol] == NUL || (nmatched = vim_regexec_multi(®match, win, buf, lnum + matchpos.lnum, - matchcol)) == 0) + matchcol, +#ifdef FEAT_RELTIME + tm +#else + NULL +#endif + )) == 0) break; /* Need to get the line pointer again, a @@ -805,21 +836,38 @@ continue; } - if (options & SEARCH_END && !(options & SEARCH_NOOF)) + /* With the SEARCH_END option move to the last character + * of the match. Don't do it for an empty match, end + * should be same as start then. */ + if (options & SEARCH_END && !(options & SEARCH_NOOF) + && !(matchpos.lnum == endpos.lnum + && matchpos.col == endpos.col)) { + /* For a match in the first column, set the position + * on the NUL in the previous line. */ pos->lnum = lnum + endpos.lnum; - pos->col = endpos.col - 1; -#ifdef FEAT_MBYTE - if (has_mbyte) + pos->col = endpos.col; + if (endpos.col == 0) { - /* 'e' offset may put us just below the last line */ - if (pos->lnum > buf->b_ml.ml_line_count) - ptr = (char_u *)""; - else - ptr = ml_get_buf(buf, pos->lnum, FALSE); - pos->col -= (*mb_head_off)(ptr, ptr + pos->col); + if (pos->lnum > 1) /* just in case */ + { + --pos->lnum; + pos->col = (colnr_T)STRLEN(ml_get_buf(buf, + pos->lnum, FALSE)); + } } + else + { + --pos->col; +#ifdef FEAT_MBYTE + if (has_mbyte + && pos->lnum <= buf->b_ml.ml_line_count) + { + ptr = ml_get_buf(buf, pos->lnum, FALSE); + pos->col -= (*mb_head_off)(ptr, ptr + pos->col); + } #endif + } } else { @@ -967,12 +1015,13 @@ * return 0 for failure, 1 for found, 2 for found and line offset added */ int -do_search(oap, dirc, pat, count, options) +do_search(oap, dirc, pat, count, options, tm) oparg_T *oap; /* can be NULL */ int dirc; /* '/' or '?' */ char_u *pat; long count; int options; + proftime_T *tm; /* timeout limit or NULL */ { pos_T pos; /* position of the last match */ char_u *searchstr; @@ -1246,7 +1295,7 @@ (SEARCH_KEEP + SEARCH_PEEK + SEARCH_HIS + SEARCH_MSG + SEARCH_START + ((pat != NULL && *pat == ';') ? 0 : SEARCH_NOOF))), - RE_LAST, (linenr_T)0); + RE_LAST, (linenr_T)0, tm); if (dircp != NULL) *dircp = dirc; /* restore second '/' or '?' for normal_cmd() */ @@ -1894,7 +1943,7 @@ } #ifdef FEAT_RIGHTLEFT - /* This is just guessing: when 'rightleft' is set, search for a maching + /* This is just guessing: when 'rightleft' is set, search for a matching * paren/brace in the other direction. */ if (curwin->w_p_rl && vim_strchr((char_u *)"()[]{}<>", initc) != NULL) backwards = !backwards; @@ -2124,6 +2173,9 @@ else if (!backwards) inquote = TRUE; } + + /* ml_get() only keeps one line, need to get linep again */ + linep = ml_get(pos.lnum); } } } @@ -2313,7 +2365,9 @@ #endif while ((p = vim_strchr(p, '/')) != NULL) { - if (p[1] == '/') + /* accept a double /, unless it's preceded with * and followed by *, + * because * / / * is an end and start of a C comment */ + if (p[1] == '/' && (p == line || p[-1] != '*' || p[2] != '*')) break; ++p; } @@ -2795,7 +2849,7 @@ i = inc_cursor(); if (i == -1 || (i >= 1 && last_line)) /* started at last char in file */ return FAIL; - if (i == 1 && eol && count == 0) /* started at last char in line */ + if (i >= 1 && eol && count == 0) /* started at last char in line */ return OK; /* @@ -3600,13 +3654,16 @@ { oap->start = start_pos; oap->motion_type = MCHAR; + oap->inclusive = FALSE; if (sol) - { incl(&curwin->w_cursor); - oap->inclusive = FALSE; - } - else + else if (ltoreq(start_pos, curwin->w_cursor)) + /* Include the character under the cursor. */ oap->inclusive = TRUE; + else + /* End is before the start (no text in between <>, [], etc.): don't + * operate on any text. */ + curwin->w_cursor = start_pos; } return OK; @@ -3717,6 +3774,10 @@ old_pos = curwin->w_cursor; old_end = curwin->w_cursor; /* remember where we started */ old_start = old_end; +#ifdef FEAT_VISUAL + if (!VIsual_active || *p_sel == 'e') +#endif + decl(&old_end); /* old_end is inclusive */ /* * If we start on "" select that block. @@ -3734,7 +3795,7 @@ if (in_html_tag(FALSE)) { - /* cursor on start tag, move to just after it */ + /* cursor on start tag, move to its '>' */ while (*ml_get_cursor() != '>') if (inc_cursor() < 0) break; @@ -3769,7 +3830,7 @@ if (do_searchpair((char_u *)"<[^ \t>/!]\\+\\%(\\_s\\_[^>]\\{-}[^/]>\\|$\\|\\_s\\=>\\)", (char_u *)"", (char_u *)"]*>", BACKWARD, (char_u *)"", 0, - NULL, (linenr_T)0) <= 0) + NULL, (linenr_T)0, 0L) <= 0) { curwin->w_cursor = old_pos; goto theend; @@ -3803,7 +3864,7 @@ sprintf((char *)epat, "\\c", len, p); r = do_searchpair(spat, (char_u *)"", epat, FORWARD, (char_u *)"", - 0, NULL, (linenr_T)0); + 0, NULL, (linenr_T)0, 0L); vim_free(spat); vim_free(epat); @@ -3838,7 +3899,7 @@ /* Exclude the start tag. */ curwin->w_cursor = start_pos; while (inc_cursor() >= 0) - if (*ml_get_cursor() == '>' && lt(curwin->w_cursor, end_pos)) + if (*ml_get_cursor() == '>') { inc_cursor(); start_pos = curwin->w_cursor; @@ -3860,7 +3921,11 @@ #ifdef FEAT_VISUAL if (VIsual_active) { - if (*p_sel == 'e') + /* If the end is before the start there is no text between tags, select + * the char under the cursor. */ + if (lt(end_pos, start_pos)) + curwin->w_cursor = start_pos; + else if (*p_sel == 'e') ++curwin->w_cursor.col; VIsual = start_pos; VIsual_mode = 'v'; @@ -3872,7 +3937,15 @@ { oap->start = start_pos; oap->motion_type = MCHAR; - oap->inclusive = TRUE; + if (lt(end_pos, start_pos)) + { + /* End is before the start: there is no text between tags; operate + * on an empty area. */ + curwin->w_cursor = start_pos; + oap->inclusive = FALSE; + } + else + oap->inclusive = TRUE; } retval = OK; diff -Naur vim71.orig/src/spell.c vim71/src/spell.c --- vim71.orig/src/spell.c 2007-05-07 15:48:38.000000000 -0400 +++ vim71/src/spell.c 2008-06-18 06:56:35.000000000 -0400 @@ -753,6 +753,7 @@ static int spell_iswordp __ARGS((char_u *p, buf_T *buf)); static int spell_iswordp_nmw __ARGS((char_u *p)); #ifdef FEAT_MBYTE +static int spell_mb_isword_class __ARGS((int cl)); static int spell_iswordp_w __ARGS((int *p, buf_T *buf)); #endif static int write_spell_prefcond __ARGS((FILE *fd, garray_T *gap)); @@ -2146,7 +2147,7 @@ { col = (int)(p - buf); (void)syn_get_id(wp, lnum, (colnr_T)col, - FALSE, &can_spell); + FALSE, &can_spell, FALSE); if (!can_spell) attr = HLF_COUNT; } @@ -2268,6 +2269,8 @@ /* * For spell checking: concatenate the start of the following line "line" into * "buf", blanking-out special characters. Copy less then "maxlen" bytes. + * Keep the blanks at the start of the next line, this is used in win_line() + * to skip those bytes if the word was OK. */ void spell_cat_line(buf, line, maxlen) @@ -2284,12 +2287,14 @@ if (*p != NUL) { - *buf = ' '; - vim_strncpy(buf + 1, line, maxlen - 2); - n = (int)(p - line); - if (n >= maxlen) - n = maxlen - 1; - vim_memset(buf + 1, ' ', n); + /* Only worth concatenating if there is something else than spaces to + * concatenate. */ + n = (int)(p - line) + 1; + if (n < maxlen - 1) + { + vim_memset(buf, ' ', n); + vim_strncpy(buf + n, p, maxlen - 1 - n); + } } } @@ -7829,7 +7834,7 @@ # if (_MSC_VER <= 1200) /* This line is required for VC6 without the service pack. Also see the * matching #pragma below. */ -/* # pragma optimize("", off) */ + # pragma optimize("", off) # endif #endif @@ -7859,7 +7864,7 @@ #ifdef _MSC_VER # if (_MSC_VER <= 1200) -/* # pragma optimize("", on) */ + # pragma optimize("", on) # endif #endif @@ -9785,7 +9790,7 @@ c = mb_ptr2char(s); if (c > 255) - return mb_get_class(s) >= 2; + return spell_mb_isword_class(mb_get_class(s)); return spelltab.st_isw[c]; } #endif @@ -9808,7 +9813,7 @@ { c = mb_ptr2char(p); if (c > 255) - return mb_get_class(p) >= 2; + return spell_mb_isword_class(mb_get_class(p)); return spelltab.st_isw[c]; } #endif @@ -9817,6 +9822,18 @@ #ifdef FEAT_MBYTE /* + * Return TRUE if word class indicates a word character. + * Only for characters above 255. + * Unicode subscript and superscript are not considered word characters. + */ + static int +spell_mb_isword_class(cl) + int cl; +{ + return cl >= 2 && cl != 0x2070 && cl != 0x2080; +} + +/* * Return TRUE if "p" points to a word character. * Wide version of spell_iswordp(). */ @@ -9837,7 +9854,7 @@ if (*s > 255) { if (enc_utf8) - return utf_class(*s) >= 2; + return spell_mb_isword_class(utf_class(*s)); if (enc_dbcs) return dbcs_class((unsigned)*s >> 8, *s & 0xff) >= 2; return 0; @@ -10343,7 +10360,7 @@ curwin->w_cursor.lnum = 0; while (!got_int) { - if (do_search(NULL, '/', frompat, 1L, SEARCH_KEEP) == 0 + if (do_search(NULL, '/', frompat, 1L, SEARCH_KEEP, NULL) == 0 || u_save_cursor() == FAIL) break; @@ -12182,7 +12199,9 @@ { n = mb_cptr2len(p); c = mb_ptr2char(p); - if (!soundfold && !spell_iswordp(p + n, curbuf)) + if (p[n] == NUL) + c2 = NUL; + else if (!soundfold && !spell_iswordp(p + n, curbuf)) c2 = c; /* don't swap non-word char */ else c2 = mb_ptr2char(p + n); @@ -12190,12 +12209,21 @@ else #endif { - if (!soundfold && !spell_iswordp(p + 1, curbuf)) + if (p[1] == NUL) + c2 = NUL; + else if (!soundfold && !spell_iswordp(p + 1, curbuf)) c2 = c; /* don't swap non-word char */ else c2 = p[1]; } + /* When the second character is NUL we can't swap. */ + if (c2 == NUL) + { + sp->ts_state = STATE_REP_INI; + break; + } + /* When characters are identical, swap won't do anything. * Also get here if the second char is not a word character. */ if (c == c2) diff -Naur vim71.orig/src/structs.h vim71/src/structs.h --- vim71.orig/src/structs.h 2007-05-07 15:50:49.000000000 -0400 +++ vim71/src/structs.h 2008-06-18 06:55:25.000000000 -0400 @@ -278,6 +278,9 @@ linenr_T ue_lcount; /* linecount when u_save called */ char_u **ue_array; /* array of lines in undo block */ long ue_size; /* number of lines in ue_array */ +#ifdef U_DEBUG + int ue_magic; /* magic number to check allocation */ +#endif }; struct u_header @@ -300,6 +303,9 @@ visualinfo_T uh_visual; /* Visual areas before undo/after redo */ #endif time_t uh_time; /* timestamp when the change was made */ +#ifdef U_DEBUG + int uh_magic; /* magic number to check allocation */ +#endif }; /* values for uh_flags */ @@ -1453,6 +1459,7 @@ #ifdef FEAT_MBYTE char_u *b_start_fenc; /* 'fileencoding' when edit started or NULL */ int b_bad_char; /* "++bad=" argument when edit started or 0 */ + int b_start_bomb; /* 'bomb' when it was read */ #endif #ifdef FEAT_EVAL @@ -1694,6 +1701,44 @@ #define FR_COL 2 /* frame with a column of windows */ /* + * Struct used for highlighting 'hlsearch' matches, matches defined by + * ":match" and matches defined by match functions. + * For 'hlsearch' there is one pattern for all windows. For ":match" and the + * match functions there is a different pattern for each window. + */ +typedef struct +{ + regmmatch_T rm; /* points to the regexp program; contains last found + match (may continue in next line) */ + buf_T *buf; /* the buffer to search for a match */ + linenr_T lnum; /* the line to search for a match */ + int attr; /* attributes to be used for a match */ + int attr_cur; /* attributes currently active in win_line() */ + linenr_T first_lnum; /* first lnum to search for multi-line pat */ + colnr_T startcol; /* in win_line() points to char where HL starts */ + colnr_T endcol; /* in win_line() points to char where HL ends */ +#ifdef FEAT_RELTIME + proftime_T tm; /* for a time limit */ +#endif +} match_T; + +/* + * matchitem_T provides a linked list for storing match items for ":match" and + * the match functions. + */ +typedef struct matchitem matchitem_T; +struct matchitem +{ + matchitem_T *next; + int id; /* match ID */ + int priority; /* match priority */ + char_u *pattern; /* pattern to highlight */ + int hlg_id; /* highlight group ID */ + regmmatch_T match; /* regexp program for pattern */ + match_T hl; /* struct for doing the actual highlighting */ +}; + +/* * Structure which contains all information that belongs to a window * * All row numbers are relative to the start of the window, except w_winrow. @@ -1934,9 +1979,8 @@ #endif #ifdef FEAT_SEARCH_EXTRA - regmmatch_T w_match[3]; /* regexp programs for ":match" */ - char_u *(w_match_pat[3]); /* patterns for ":match" */ - int w_match_id[3]; /* highlight IDs for ":match" */ + matchitem_T *w_match_head; /* head of match list */ + int w_next_match_id; /* next match ID */ #endif /* diff -Naur vim71.orig/src/syntax.c vim71/src/syntax.c --- vim71.orig/src/syntax.c 2007-05-07 15:42:55.000000000 -0400 +++ vim71/src/syntax.c 2008-06-18 06:55:25.000000000 -0400 @@ -66,8 +66,10 @@ #define HL_TABLE() ((struct hl_group *)((highlight_ga.ga_data))) #ifdef FEAT_CMDL_COMPL -static int include_default = FALSE; /* include "default" for expansion */ -static int include_link = FALSE; /* include "link" for expansion */ +/* Flags to indicate an additional string for highlight name completion. */ +static int include_none = 0; /* when 1 include "None" */ +static int include_default = 0; /* when 1 include "default" */ +static int include_link = 0; /* when 2 include "link" and "clear" */ #endif /* @@ -277,7 +279,8 @@ */ typedef struct state_item { - int si_idx; /* index of syntax pattern */ + int si_idx; /* index of syntax pattern or + KEYWORD_IDX */ int si_id; /* highlight group ID for keywords */ int si_trans_id; /* idem, transparancy removed */ int si_m_lnum; /* lnum of the match */ @@ -369,13 +372,13 @@ static int syn_stack_cleanup __ARGS((void)); static void syn_stack_free_entry __ARGS((buf_T *buf, synstate_T *p)); static synstate_T *syn_stack_find_entry __ARGS((linenr_T lnum)); -static synstate_T *store_current_state __ARGS((synstate_T *sp)); +static synstate_T *store_current_state __ARGS((void)); static void load_current_state __ARGS((synstate_T *from)); static void invalidate_current_state __ARGS((void)); static int syn_stack_equal __ARGS((synstate_T *sp)); static void validate_current_state __ARGS((void)); static int syn_finish_line __ARGS((int syncing)); -static int syn_current_attr __ARGS((int syncing, int displaying, int *can_spell)); +static int syn_current_attr __ARGS((int syncing, int displaying, int *can_spell, int keep_state)); static int did_match_already __ARGS((int idx, garray_T *gap)); static stateitem_T *push_next_match __ARGS((stateitem_T *cur_si)); static void check_state_ends __ARGS((void)); @@ -461,7 +464,7 @@ synstate_T *p; synstate_T *last_valid = NULL; synstate_T *last_min_valid = NULL; - synstate_T *sp, *prev; + synstate_T *sp, *prev = NULL; linenr_T parsed_lnum; linenr_T first_stored; int dist; @@ -499,7 +502,7 @@ if (!current_state_stored) { ++current_lnum; - (void)store_current_state(NULL); + (void)store_current_state(); } /* @@ -555,7 +558,6 @@ dist = 999999; else dist = syn_buf->b_ml.ml_line_count / (syn_buf->b_sst_len - Rows) + 1; - prev = syn_stack_find_entry(current_lnum); while (current_lnum < lnum) { syn_start_line(); @@ -570,9 +572,13 @@ * equal to the current state. If so, then validate all saved * states that depended on a change before the parsed line. */ if (prev == NULL) + prev = syn_stack_find_entry(current_lnum - 1); + if (prev == NULL) sp = syn_buf->b_sst_first; else - sp = prev->sst_next; + sp = prev; + while (sp != NULL && sp->sst_lnum < current_lnum) + sp = sp->sst_next; if (sp != NULL && sp->sst_lnum == current_lnum && syn_stack_equal(sp)) @@ -598,7 +604,7 @@ else if (prev == NULL || current_lnum == lnum || current_lnum >= prev->sst_lnum + dist) - prev = store_current_state(prev); + prev = store_current_state(); } /* This can take a long time: break when CTRL-C pressed. The current @@ -835,9 +841,18 @@ current_lnum = end_lnum; break; } - spp = &(SYN_ITEMS(syn_buf)[cur_si->si_idx]); - found_flags = spp->sp_flags; - found_match_idx = spp->sp_sync_idx; + if (cur_si->si_idx < 0) + { + /* Cannot happen? */ + found_flags = 0; + found_match_idx = KEYWORD_IDX; + } + else + { + spp = &(SYN_ITEMS(syn_buf)[cur_si->si_idx]); + found_flags = spp->sp_flags; + found_match_idx = spp->sp_sync_idx; + } found_current_lnum = current_lnum; found_current_col = current_col; found_m_endpos = cur_si->si_m_endpos; @@ -1341,17 +1356,13 @@ * The current state must be valid for the start of the current_lnum line! */ static synstate_T * -store_current_state(sp) - synstate_T *sp; /* at or before where state is to be saved or - NULL */ +store_current_state() { int i; synstate_T *p; bufstate_T *bp; stateitem_T *cur_si; - - if (sp == NULL) - sp = syn_stack_find_entry(current_lnum); + synstate_T *sp = syn_stack_find_entry(current_lnum); /* * If the current state contains a start or end pattern that continues @@ -1655,7 +1666,7 @@ * Store the current state in b_sst_array[] for later use. */ ++current_lnum; - (void)store_current_state(NULL); + (void)store_current_state(); } } @@ -1679,7 +1690,7 @@ { while (!current_finished) { - (void)syn_current_attr(syncing, FALSE, NULL); + (void)syn_current_attr(syncing, FALSE, NULL, FALSE); /* * When syncing, and found some item, need to check the item. */ @@ -1719,12 +1730,20 @@ * done. */ int -get_syntax_attr(col, can_spell) +get_syntax_attr(col, can_spell, keep_state) colnr_T col; int *can_spell; + int keep_state; /* keep state of char at "col" */ { int attr = 0; + if (can_spell != NULL) + /* Default: Only do spelling when there is no @Spell cluster or when + * ":syn spell toplevel" was used. */ + *can_spell = syn_buf->b_syn_spell == SYNSPL_DEFAULT + ? (syn_buf->b_spell_cluster_id == 0) + : (syn_buf->b_syn_spell == SYNSPL_TOP); + /* check for out of memory situation */ if (syn_buf->b_sst_array == NULL) return 0; @@ -1749,7 +1768,8 @@ */ while (current_col <= col) { - attr = syn_current_attr(FALSE, TRUE, can_spell); + attr = syn_current_attr(FALSE, TRUE, can_spell, + current_col == col ? keep_state : FALSE); ++current_col; } @@ -1760,10 +1780,11 @@ * Get syntax attributes for current_lnum, current_col. */ static int -syn_current_attr(syncing, displaying, can_spell) +syn_current_attr(syncing, displaying, can_spell, keep_state) int syncing; /* When 1: called for syncing */ int displaying; /* result will be displayed */ int *can_spell; /* return: do spell checking */ + int keep_state; /* keep syntax stack afterwards */ { int syn_id; lpos_T endpos; /* was: char_u *endp; */ @@ -2279,7 +2300,7 @@ * may be for an empty match and a containing item might end in the * current column. */ - if (!syncing) + if (!syncing && !keep_state) { check_state_ends(); if (current_state.ga_len > 0 @@ -2476,7 +2497,7 @@ if (current_state.ga_len == 0) break; - if (had_extend) + if (had_extend && keepend_level >= 0) { syn_update_ends(FALSE); if (current_state.ga_len == 0) @@ -2524,6 +2545,10 @@ stateitem_T *sip = &CUR_STATE(idx); synpat_T *spp; + /* This should not happen... */ + if (sip->si_idx < 0) + return; + spp = &(SYN_ITEMS(syn_buf)[sip->si_idx]); if (sip->si_flags & HL_MATCH) sip->si_id = spp->sp_syn_match_id; @@ -2639,6 +2664,10 @@ lpos_T end_endpos; int end_idx; + /* return quickly for a keyword */ + if (sip->si_idx < 0) + return; + /* Don't update when it's already done. Can be a match of an end pattern * that started in a previous line. Watch out: can also be a "keepend" * from a containing item. */ @@ -2751,6 +2780,10 @@ char_u *line; int had_match = FALSE; + /* just in case we are invoked for a keyword */ + if (idx < 0) + return; + /* * Check for being called with a START pattern. * Can happen with a match that continues to the next line, because it @@ -3064,7 +3097,7 @@ colnr_T col; { rmp->rmm_maxcol = syn_buf->b_p_smc; - if (vim_regexec_multi(rmp, syn_win, syn_buf, lnum, col) > 0) + if (vim_regexec_multi(rmp, syn_win, syn_buf, lnum, col, NULL) > 0) { rmp->startpos[0].lnum += lnum; rmp->endpos[0].lnum += lnum; @@ -3323,6 +3356,7 @@ { vim_free(SYN_ITEMS(buf)[i].sp_cont_list); vim_free(SYN_ITEMS(buf)[i].sp_next_list); + vim_free(SYN_ITEMS(buf)[i].sp_syn.cont_in_list); } } @@ -4460,8 +4494,8 @@ current_syn_inc_tag = ++running_syn_inc_tag; prev_toplvl_grp = curbuf->b_syn_topgrp; curbuf->b_syn_topgrp = sgl_id; - if (source ? do_source(eap->arg, FALSE, FALSE) == FAIL - : source_runtime(eap->arg, DOSO_NONE) == FAIL) + if (source ? do_source(eap->arg, FALSE, DOSO_NONE) == FAIL + : source_runtime(eap->arg, TRUE) == FAIL) EMSG2(_(e_notopen), eap->arg); curbuf->b_syn_topgrp = prev_toplvl_grp; current_syn_inc_tag = prev_syn_inc_tag; @@ -5956,8 +5990,8 @@ { return (buf->b_syn_patterns.ga_len != 0 || buf->b_syn_clusters.ga_len != 0 - || curbuf->b_keywtab.ht_used > 0 - || curbuf->b_keywtab_ic.ht_used > 0); + || buf->b_keywtab.ht_used > 0 + || buf->b_keywtab_ic.ht_used > 0); } #if defined(FEAT_CMDL_COMPL) || defined(PROTO) @@ -5968,6 +6002,29 @@ EXP_CASE /* expand ":syn case" arguments */ } expand_what; +/* + * Reset include_link, include_default, include_none to 0. + * Called when we are done expanding. + */ + void +reset_expand_highlight() +{ + include_link = include_default = include_none = 0; +} + +/* + * Handle command line completion for :match and :echohl command: Add "None" + * as highlight group. + */ + void +set_context_in_echohl_cmd(xp, arg) + expand_T *xp; + char_u *arg; +{ + xp->xp_context = EXPAND_HIGHLIGHT; + xp->xp_pattern = arg; + include_none = 1; +} /* * Handle command line completion for :syntax command. @@ -5983,8 +6040,8 @@ xp->xp_context = EXPAND_SYNTAX; expand_what = EXP_SUBCMD; xp->xp_pattern = arg; - include_link = FALSE; - include_default = FALSE; + include_link = 0; + include_default = 0; /* (part of) subcommand already typed */ if (*arg != NUL) @@ -6031,12 +6088,13 @@ * Function called for expression evaluation: get syntax ID at file position. */ int -syn_get_id(wp, lnum, col, trans, spellp) +syn_get_id(wp, lnum, col, trans, spellp, keep_state) win_T *wp; long lnum; colnr_T col; - int trans; /* remove transparancy */ - int *spellp; /* return: can do spell checking */ + int trans; /* remove transparancy */ + int *spellp; /* return: can do spell checking */ + int keep_state; /* keep state of char at "col" */ { /* When the position is not after the current position and in the same * line of the same buffer, need to restart parsing. */ @@ -6045,11 +6103,33 @@ || col < current_col) syntax_start(wp, lnum); - (void)get_syntax_attr(col, spellp); + (void)get_syntax_attr(col, spellp, keep_state); return (trans ? current_trans_id : current_id); } +#if defined(FEAT_EVAL) || defined(PROTO) +/* + * Return the syntax ID at position "i" in the current stack. + * The caller must have called syn_get_id() before to fill the stack. + * Returns -1 when "i" is out of range. + */ + int +syn_get_stack_item(i) + int i; +{ + if (i >= current_state.ga_len) + { + /* Need to invalidate the state, because we didn't properly finish it + * for the last character, "keep_state" was TRUE. */ + invalidate_current_state(); + current_col = MAXCOL; + return -1; + } + return CUR_STATE(i).si_id; +} +#endif + #if defined(FEAT_FOLDING) || defined(PROTO) /* * Function called to get folding level for line "lnum" in window "wp". @@ -8479,7 +8559,7 @@ syn_id2name(id) int id; { - if (id <= 0 || id >= highlight_ga.ga_len) + if (id <= 0 || id > highlight_ga.ga_len) return (char_u *)""; return HL_TABLE()[id - 1].sg_name; } @@ -8949,7 +9029,7 @@ return OK; } -#ifdef FEAT_CMDL_COMPL +#if defined(FEAT_CMDL_COMPL) || defined(PROTO) static void highlight_list __ARGS((void)); static void highlight_list_two __ARGS((int cnt, int attr)); @@ -8967,8 +9047,8 @@ /* Default: expand group names */ xp->xp_context = EXPAND_HIGHLIGHT; xp->xp_pattern = arg; - include_link = TRUE; - include_default = TRUE; + include_link = 2; + include_default = 1; /* (part of) subcommand already typed */ if (*arg != NUL) @@ -8976,7 +9056,7 @@ p = skiptowhite(arg); if (*p != NUL) /* past "default" or group name */ { - include_default = FALSE; + include_default = 0; if (STRNCMP("default", arg, p - arg) == 0) { arg = skipwhite(p); @@ -8985,7 +9065,7 @@ } if (*p != NUL) /* past group name */ { - include_link = FALSE; + include_link = 0; if (arg[1] == 'i' && arg[0] == 'N') highlight_list(); if (STRNCMP("link", arg, p - arg) == 0 @@ -9045,31 +9125,25 @@ expand_T *xp; int idx; { - if (idx == highlight_ga.ga_len #ifdef FEAT_CMDL_COMPL - && include_link -#endif - ) + if (idx == highlight_ga.ga_len && include_none != 0) + return (char_u *)"none"; + if (idx == highlight_ga.ga_len + include_none && include_default != 0) + return (char_u *)"default"; + if (idx == highlight_ga.ga_len + include_none + include_default + && include_link != 0) return (char_u *)"link"; - if (idx == highlight_ga.ga_len + 1 -#ifdef FEAT_CMDL_COMPL - && include_link -#endif - ) + if (idx == highlight_ga.ga_len + include_none + include_default + 1 + && include_link != 0) return (char_u *)"clear"; - if (idx == highlight_ga.ga_len + 2 -#ifdef FEAT_CMDL_COMPL - && include_default #endif - ) - return (char_u *)"default"; if (idx < 0 || idx >= highlight_ga.ga_len) return NULL; return HL_TABLE()[idx].sg_name; } #endif -#ifdef FEAT_GUI +#if defined(FEAT_GUI) || defined(PROTO) /* * Free all the highlight group fonts. * Used when quitting for systems which need it. diff -Naur vim71.orig/src/tag.c vim71/src/tag.c --- vim71.orig/src/tag.c 2007-05-07 15:36:40.000000000 -0400 +++ vim71/src/tag.c 2008-06-18 06:55:50.000000000 -0400 @@ -2669,8 +2669,8 @@ tnp->tn_search_ctx = vim_findfile_init(buf, filename, r_ptr, 100, - FALSE, /* don't free visited list */ - FALSE, /* we search for a file */ + FALSE, /* don't free visited list */ + FINDFILE_FILE, /* we search for a file */ tnp->tn_search_ctx, TRUE, curbuf->b_ffname); if (tnp->tn_search_ctx != NULL) tnp->tn_did_filefind_init = TRUE; @@ -2691,6 +2691,7 @@ { vim_free(tnp->tn_tags); vim_findfile_cleanup(tnp->tn_search_ctx); + tnp->tn_search_ctx = NULL; ga_clear_strings(&tag_fnames); } @@ -3191,7 +3192,8 @@ #endif save_lnum = curwin->w_cursor.lnum; curwin->w_cursor.lnum = 0; /* start search before first line */ - if (do_search(NULL, pbuf[0], pbuf + 1, (long)1, search_options)) + if (do_search(NULL, pbuf[0], pbuf + 1, (long)1, + search_options, NULL)) retval = OK; else { @@ -3203,7 +3205,7 @@ */ p_ic = TRUE; if (!do_search(NULL, pbuf[0], pbuf + 1, (long)1, - search_options)) + search_options, NULL)) { /* * Failed to find pattern, take a guess: "^func (" @@ -3213,13 +3215,14 @@ cc = *tagp.tagname_end; *tagp.tagname_end = NUL; sprintf((char *)pbuf, "^%s\\s\\*(", tagp.tagname); - if (!do_search(NULL, '/', pbuf, (long)1, search_options)) + if (!do_search(NULL, '/', pbuf, (long)1, + search_options, NULL)) { /* Guess again: "^char * \[>{x};{vers};{y}c". Also * eat other possible responses to t_RV, rxvt returns - * "[?1;2c". Also accept CSI instead of [. */ + * "[?1;2c". Also accept CSI instead of [. + * mrxvt has been reported to have "+" in the version. Assume + * the escape sequence ends with a letter or one of "{|}~". */ if (*T_CRV != NUL && ((tp[0] == ESC && tp[1] == '[' && len >= 3) || (tp[0] == CSI && len >= 2))) { j = 0; extra = 0; - for (i = 2 + (tp[0] != CSI); - i < len && (VIM_ISDIGIT(tp[i]) - || tp[i] == ';' || tp[i] == '.'); ++i) + for (i = 2 + (tp[0] != CSI); i < len + && !(tp[i] >= '{' && tp[i] <= '~') + && !ASCII_ISALPHA(tp[i]); ++i) if (tp[i] == ';' && ++j == 1) extra = atoi((char *)tp + i + 1); if (i == len) @@ -4809,6 +4811,8 @@ if (num_bytes == -1) return -1; current_tab = (int)bytes[0]; + if (current_tab == 255) /* -1 in a byte gives 255 */ + current_tab = -1; slen += num_bytes; } else if (key_name[0] == (int)KS_TABMENU) diff -Naur vim71.orig/src/termlib.c vim71/src/termlib.c --- vim71.orig/src/termlib.c 2007-05-07 15:39:49.000000000 -0400 +++ vim71/src/termlib.c 2008-06-18 06:51:42.000000000 -0400 @@ -191,7 +191,7 @@ lbuf[0] == '\t' && lbuf[1] == ':') { - strcpy(lbuf, lbuf+2); + mch_memmove(lbuf, lbuf + 2, strlen(lbuf + 2) + 1); llen -= 2; } if (lbuf[llen-2] == '\\') /* and continuations */ diff -Naur vim71.orig/src/testdir/Makefile vim71/src/testdir/Makefile --- vim71.orig/src/testdir/Makefile 2006-04-30 07:08:01.000000000 -0400 +++ vim71/src/testdir/Makefile 2008-06-18 06:53:02.000000000 -0400 @@ -1,9 +1,13 @@ # -# Makefile to run al tests for Vim +# Makefile to run all tests for Vim # VIMPROG = ../vim +# Uncomment this line for using valgrind. +# The output goes into a file "valgrind.$PID" (sorry, no test number). +# VALGRIND = valgrind --tool=memcheck --leak-check=yes --num-callers=15 --logfile=valgrind + SCRIPTS = test1.out test2.out test3.out test4.out test5.out test6.out \ test7.out test8.out test9.out test10.out test11.out \ test12.out test13.out test14.out test15.out test17.out \ @@ -15,7 +19,8 @@ test43.out test44.out test45.out test46.out test47.out \ test48.out test49.out test51.out test52.out test53.out \ test54.out test55.out test56.out test57.out test58.out \ - test59.out test60.out test61.out test62.out + test59.out test60.out test61.out test62.out test63.out \ + test64.out SCRIPTS_GUI = test16.out @@ -34,11 +39,11 @@ $(SCRIPTS) $(SCRIPTS_GUI): $(VIMPROG) clean: - -rm -rf *.out *.failed *.rej *.orig test.log tiny.vim small.vim mbyte.vim test.ok X* viminfo + -rm -rf *.out *.failed *.rej *.orig test.log tiny.vim small.vim mbyte.vim test.ok X* valgrind.pid* viminfo test1.out: test1.in -rm -f $*.failed tiny.vim small.vim mbyte.vim test.ok X* viminfo - $(VIMPROG) -u unix.vim -U NONE --noplugin -s dotest.in $*.in + $(VALGRIND) $(VIMPROG) -u unix.vim -U NONE --noplugin -s dotest.in $*.in @/bin/sh -c "if diff test.out $*.ok; \ then mv -f test.out $*.out; \ else echo; \ @@ -51,7 +56,7 @@ cp $*.ok test.ok # Sleep a moment to avoid that the xterm title is messed up @-sleep .2 - -$(VIMPROG) -u unix.vim -U NONE --noplugin -s dotest.in $*.in + -$(VALGRIND) $(VIMPROG) -u unix.vim -U NONE --noplugin -s dotest.in $*.in @/bin/sh -c "if test -f test.out; then\ if diff test.out $*.ok; \ then mv -f test.out $*.out; \ @@ -61,5 +66,9 @@ fi" -rm -rf X* test.ok viminfo +test49.out: test49.vim + +test60.out: test60.vim + nolog: -echo Test results: >test.log diff -Naur vim71.orig/src/testdir/test14.in vim71/src/testdir/test14.in --- vim71.orig/src/testdir/test14.in 2004-06-07 10:32:05.000000000 -0400 +++ vim71/src/testdir/test14.in 2008-06-18 06:53:02.000000000 -0400 @@ -18,6 +18,7 @@ : let tt = "o\65\x42\o103 \33a\xfg\o78\" :endif :exe "normal " . tt +:unlet tt :.w >>test.out :set vb /^Piece diff -Naur vim71.orig/src/testdir/test26.in vim71/src/testdir/test26.in --- vim71.orig/src/testdir/test26.in 2004-06-07 10:32:05.000000000 -0400 +++ vim71/src/testdir/test26.in 2008-06-18 06:53:02.000000000 -0400 @@ -37,6 +37,7 @@ : endif : endif :endwhile +:unlet i j :'t,$w! test.out :qa! ENDTEST diff -Naur vim71.orig/src/testdir/test34.in vim71/src/testdir/test34.in --- vim71.orig/src/testdir/test34.in 2006-04-30 09:33:24.000000000 -0400 +++ vim71/src/testdir/test34.in 2008-06-18 06:53:02.000000000 -0400 @@ -52,7 +52,15 @@ ---*--- (one (two -[(one again:$-5,$wq! test.out +[(one again:$-5,$w! test.out +:delfunc Table +:delfunc Compute +:delfunc Expr1 +:delfunc Expr2 +:delfunc ListItem +:delfunc ListReset +:unlet retval counter +:q! ENDTEST here diff -Naur vim71.orig/src/testdir/test39.in vim71/src/testdir/test39.in --- vim71.orig/src/testdir/test39.in 2004-06-07 10:32:05.000000000 -0400 +++ vim71/src/testdir/test39.in 2008-06-18 06:55:45.000000000 -0400 @@ -1,8 +1,12 @@ Test Visual block mode commands +And test "U" in Visual mode, also on German sharp S. STARTTEST :so small.vim +:so mbyte.vim +:" This only works when 'encoding' is "latin1", don't depend on the environment +:set enc=latin1 /^abcde :" Test shift-right of a block jlllljj>wlljlll> @@ -14,7 +18,22 @@ Gllllkkklllrq :" Test block-change G$khhhhhkkcmno -:$-4,$wq! test.out +:$-4,$w! test.out +:" gUe must uppercase a whole word, also when ß changes to SS +Gothe youtußeuu endYpk0wgUe +:" gUfx must uppercase until x, inclusive. +O- youßtußexu -0fogUfx +:" VU must uppercase a whole line +YpkVU +:" same, when it's the last line in the buffer +YPGi111VUddP +:" Uppercase two lines +Oblah di +doh dutVkUj +:" Uppercase part of two lines +ddppi333k0i222fyllvjfuUk +:/^the/,$w >> test.out +:qa! ENDTEST abcdefghijklm diff -Naur vim71.orig/src/testdir/test39.ok vim71/src/testdir/test39.ok --- vim71.orig/src/testdir/test39.ok 2004-06-07 10:32:05.000000000 -0400 +++ vim71/src/testdir/test39.ok 2008-06-18 06:55:34.000000000 -0400 @@ -3,3 +3,11 @@ axyzqqqqef mno ghijklm axyzqqqqefgmnoklm abcdqqqqijklm +the YOUTUSSEUU end +- yOUSSTUSSEXu - +THE YOUTUSSEUU END +111THE YOUTUSSEUU END +BLAH DI +DOH DUT +222the yoUTUSSEUU END +333THE YOUTUßeuu end diff -Naur vim71.orig/src/testdir/test42.ok vim71/src/testdir/test42.ok --- vim71.orig/src/testdir/test42.ok 2004-06-07 10:32:05.000000000 -0400 +++ vim71/src/testdir/test42.ok 2008-06-18 06:55:56.000000000 -0400 @@ -15,7 +15,7 @@ utf-8€err - fileencoding=ucs-2 + fileencoding=utf-16 bomb ucs-2 diff -Naur vim71.orig/src/testdir/test45.in vim71/src/testdir/test45.in --- vim71.orig/src/testdir/test45.in 2004-06-07 10:32:05.000000000 -0400 +++ vim71/src/testdir/test45.in 2008-06-18 06:53:02.000000000 -0400 @@ -55,6 +55,7 @@ /kk$ :call append("$", foldlevel(".")) :/^last/+1,$w! test.out +:delfun Flvl :qa! ENDTEST diff -Naur vim71.orig/src/testdir/test47.in vim71/src/testdir/test47.in --- vim71.orig/src/testdir/test47.in 2004-06-07 10:32:05.000000000 -0400 +++ vim71/src/testdir/test47.in 2008-06-18 06:53:02.000000000 -0400 @@ -34,6 +34,7 @@ :call append("$", two) :call append("$", three) :$-2,$w! test.out +:unlet one two three :qa! ENDTEST diff -Naur vim71.orig/src/testdir/test49.in vim71/src/testdir/test49.in --- vim71.orig/src/testdir/test49.in 2006-04-28 05:29:54.000000000 -0400 +++ vim71/src/testdir/test49.in 2008-06-18 06:55:47.000000000 -0400 @@ -1,13 +1,30 @@ This is a test of the script language. If after adding a new test, the test output doesn't appear properly in -test49.failed, try to add one ore more "G"s at the line before ENDTEST. +test49.failed, try to add one ore more "G"s at the line ending in "test.out" STARTTEST :so small.vim :se nocp nomore viminfo+=nviminfo +:lang mess C :so test49.vim -GGGGGGGGGG"rp:.-,$wq! test.out +GGGGGGGGGGGGGG"rp:.-,$w! test.out +:" +:" make valgrind happy +:redir => funclist +:silent func +:redir END +:for line in split(funclist, "\n") +: let name = matchstr(line, 'function \zs[A-Z]\w*\ze(') +: if name != '' +: exe "delfunc " . name +: endif +:endfor +:for v in keys(g:) +: silent! exe "unlet " . v +:endfor +:unlet v +:qa! ENDTEST Results of test49.vim: diff -Naur vim71.orig/src/testdir/test55.in vim71/src/testdir/test55.in --- vim71.orig/src/testdir/test55.in 2006-10-15 10:07:05.000000000 -0400 +++ vim71/src/testdir/test55.in 2008-06-18 06:55:47.000000000 -0400 @@ -146,7 +146,7 @@ :try : let n = d[1500] :catch -: $put =v:exception[:14] . v:exception[-4:-1] +: $put =substitute(v:exception, '\v(.{14}).*( \d{4}).*', '\1\2', '') :endtry :" lookup each items :for i in range(1500) @@ -345,6 +345,10 @@ :endfun :call Test(1, 2, [3, 4], {5: 6}) " This may take a while :" +:delfunc Test +:unlet dict +:call garbagecollect(1) +:" :/^start:/,$wq! test.out ENDTEST diff -Naur vim71.orig/src/testdir/test56.in vim71/src/testdir/test56.in --- vim71.orig/src/testdir/test56.in 2006-09-03 10:28:41.000000000 -0400 +++ vim71/src/testdir/test56.in 2008-06-18 06:53:02.000000000 -0400 @@ -17,5 +17,5 @@ fun s:DoNothing() call append(line('$'), "nothing line") endfun -nnoremap _x :call DoNothing()call DoLast() +nnoremap _x :call DoNothing()call DoLast()delfunc DoNothingdelfunc DoLast end: diff -Naur vim71.orig/src/testdir/test58.in vim71/src/testdir/test58.in --- vim71.orig/src/testdir/test58.in 2006-04-03 14:24:04.000000000 -0400 +++ vim71/src/testdir/test58.in 2008-06-18 06:53:02.000000000 -0400 @@ -86,6 +86,7 @@ :$put =str `m]s:let [str, a] = spellbadword() :$put =str +:unlet str a :" :" Postponed prefixes :call TestOne('2', '1') @@ -100,6 +101,10 @@ :" NOSLITSUGS :call TestOne('8', '8') :" +:" clean up for valgrind +:delfunc TestOne +:set spl= enc=latin1 +:" gg:/^test output:/,$wq! test.out ENDTEST diff -Naur vim71.orig/src/testdir/test59.in vim71/src/testdir/test59.in --- vim71.orig/src/testdir/test59.in 2006-04-03 14:29:24.000000000 -0400 +++ vim71/src/testdir/test59.in 2008-06-18 06:53:02.000000000 -0400 @@ -90,6 +90,7 @@ :$put =str `m]s:let [str, a] = spellbadword() :$put =str +:unlet str a :" :" Postponed prefixes :call TestOne('2', '1') @@ -101,6 +102,10 @@ :call TestOne('6', '6') :call TestOne('7', '7') :" +:" clean up for valgrind +:delfunc TestOne +:set spl= enc=latin1 +:" gg:/^test output:/,$wq! test.out ENDTEST diff -Naur vim71.orig/src/testdir/test60.in vim71/src/testdir/test60.in --- vim71.orig/src/testdir/test60.in 2006-05-05 14:41:18.000000000 -0400 +++ vim71/src/testdir/test60.in 2008-06-18 06:53:02.000000000 -0400 @@ -569,6 +569,9 @@ redir END endfunction :call TestExists() +:delfunc TestExists +:delfunc RunTest +:delfunc TestFuncArg :edit! test.out :set ff=unix :w diff -Naur vim71.orig/src/testdir/test60.vim vim71/src/testdir/test60.vim --- vim71.orig/src/testdir/test60.vim 2006-01-12 14:45:59.000000000 -0500 +++ vim71/src/testdir/test60.vim 2008-06-18 06:53:02.000000000 -0400 @@ -94,4 +94,5 @@ else echo "FAILED" endif +unlet str diff -Naur vim71.orig/src/testdir/test62.in vim71/src/testdir/test62.in --- vim71.orig/src/testdir/test62.in 2006-04-30 07:29:15.000000000 -0400 +++ vim71/src/testdir/test62.in 2008-06-18 06:53:02.000000000 -0400 @@ -7,6 +7,7 @@ :let nr = tabpagenr() :q :call append(line('$'), 'tab page ' . nr) +:unlet nr :" :" Open three tab pages and use ":tabdo" :0tabnew @@ -23,6 +24,7 @@ :q! :call append(line('$'), line1) :call append(line('$'), line2) +:unlet line1 line2 :" :" :/^Results/,$w! test.out diff -Naur vim71.orig/src/testdir/test63.in vim71/src/testdir/test63.in --- vim71.orig/src/testdir/test63.in 1969-12-31 19:00:00.000000000 -0500 +++ vim71/src/testdir/test63.in 2008-06-18 06:53:02.000000000 -0400 @@ -0,0 +1,157 @@ +Test for ":match", ":2match", ":3match", "clearmatches()", "getmatches()", +"matchadd()", "matcharg()", "matchdelete()", and "setmatches()". + +STARTTEST +:so small.vim +:" --- Check that "matcharg()" returns the correct group and pattern if a match +:" --- is defined. +:let @r = "*** Test 1: " +:highlight MyGroup1 ctermbg=red +:highlight MyGroup2 ctermbg=green +:highlight MyGroup3 ctermbg=blue +:match MyGroup1 /TODO/ +:2match MyGroup2 /FIXME/ +:3match MyGroup3 /XXX/ +:if matcharg(1) == ['MyGroup1', 'TODO'] && matcharg(2) == ['MyGroup2', 'FIXME'] && matcharg(3) == ['MyGroup3', 'XXX'] +: let @r .= "OK\n" +:else +: let @r .= "FAILED\n" +:endif +:" --- Check that "matcharg()" returns an empty list if the argument is not 1, +:" --- 2 or 3 (only 0 and 4 are tested). +:let @r .= "*** Test 2: " +:if matcharg(0) == [] && matcharg(4) == [] +: let @r .= "OK\n" +:else +: let @r .= "FAILED\n" +:endif +:" --- Check that "matcharg()" returns ['', ''] if a match is not defined. +:let @r .= "*** Test 3: " +:match +:2match +:3match +:if matcharg(1) == ['', ''] && matcharg(2) == ['', ''] && matcharg(3) == ['', ''] +: let @r .= "OK\n" +:else +: let @r .= "FAILED\n" +:endif +:" --- Check that "matchadd()" and "getmatches()" agree on added matches and +:" --- that default values apply. +:let @r .= "*** Test 4: " +:let m1 = matchadd("MyGroup1", "TODO") +:let m2 = matchadd("MyGroup2", "FIXME", 42) +:let m3 = matchadd("MyGroup3", "XXX", 60, 17) +:if getmatches() == [{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 4}, {'group': 'MyGroup2', 'pattern': 'FIXME', 'priority': 42, 'id': 5}, {'group': 'MyGroup3', 'pattern': 'XXX', 'priority': 60, 'id': 17}] +: let @r .= "OK\n" +:else +: let @r .= "FAILED\n" +:endif +:" --- Check that "matchdelete()" deletes the matches defined in the previous +:" --- test correctly. +:let @r .= "*** Test 5: " +:call matchdelete(m1) +:call matchdelete(m2) +:call matchdelete(m3) +:unlet m1 +:unlet m2 +:unlet m3 +:if getmatches() == [] +: let @r .= "OK\n" +:else +: let @r .= "FAILED\n" +:endif +:" --- Check that "matchdelete()" returns 0 if successful and otherwise -1. +:let @r .= "*** Test 6: " +:let m = matchadd("MyGroup1", "TODO") +:let r1 = matchdelete(m) +:let r2 = matchdelete(42) +:if r1 == 0 && r2 == -1 +: let @r .= "OK\n" +:else +: let @r .= "FAILED\n" +:endif +:unlet m +:unlet r1 +:unlet r2 +:" --- Check that "clearmatches()" clears all matches defined by ":match" and +:" --- "matchadd()". +:let @r .= "*** Test 7: " +:let m1 = matchadd("MyGroup1", "TODO") +:let m2 = matchadd("MyGroup2", "FIXME", 42) +:let m3 = matchadd("MyGroup3", "XXX", 60, 17) +:match MyGroup1 /COFFEE/ +:2match MyGroup2 /HUMPPA/ +:3match MyGroup3 /VIM/ +:call clearmatches() +:if getmatches() == [] +: let @r .= "OK\n" +:else +: let @r .= "FAILED\n" +:endif +:unlet m1 +:unlet m2 +:unlet m3 +:" --- Check that "setmatches()" restores a list of matches saved by +:" --- "getmatches()" without changes. (Matches with equal priority must also +:" --- remain in the same order.) +:let @r .= "*** Test 8: " +:let m1 = matchadd("MyGroup1", "TODO") +:let m2 = matchadd("MyGroup2", "FIXME", 42) +:let m3 = matchadd("MyGroup3", "XXX", 60, 17) +:match MyGroup1 /COFFEE/ +:2match MyGroup2 /HUMPPA/ +:3match MyGroup3 /VIM/ +:let ml = getmatches() +:call clearmatches() +:call setmatches(ml) +:if getmatches() == ml +: let @r .= "OK\n" +:else +: let @r .= "FAILED\n" +:endif +:call clearmatches() +:unlet m1 +:unlet m2 +:unlet m3 +:unlet ml +:" --- Check that "setmatches()" will not add two matches with the same ID. The +:" --- expected behaviour (for now) is to add the first match but not the +:" --- second and to return 0 (even though it is a matter of debate whether +:" --- this can be considered successful behaviour). +:let @r .= "*** Test 9: " +:let r1 = setmatches([{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 1}, {'group': 'MyGroup2', 'pattern': 'FIXME', 'priority': 10, 'id': 1}]) +:if getmatches() == [{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 1}] && r1 == 0 +: let @r .= "OK\n" +:else +: let @r .= "FAILED\n" +:endif +:call clearmatches() +:unlet r1 +:" --- Check that "setmatches()" returns 0 if successful and otherwise -1. +:" --- (A range of valid and invalid input values are tried out to generate the +:" --- return values.) +:let @r .= "*** Test 10: " +:let rs1 = setmatches([]) +:let rs2 = setmatches([{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 1}]) +:call clearmatches() +:let rf1 = setmatches(0) +:let rf2 = setmatches([0]) +:let rf3 = setmatches([{'wrong key': 'wrong value'}]) +:if rs1 == 0 && rs2 == 0 && rf1 == -1 && rf2 == -1 && rf3 == -1 +: let @r .= "OK\n" +:else +: let @r .= "FAILED\n" +:endif +:unlet rs1 +:unlet rs2 +:unlet rf1 +:unlet rf2 +:unlet rf3 +:highlight clear MyGroup1 +:highlight clear MyGroup2 +:highlight clear MyGroup3 +G"rp +:/^Results/,$wq! test.out +ENDTEST + +Results of test63: diff -Naur vim71.orig/src/testdir/test63.ok vim71/src/testdir/test63.ok --- vim71.orig/src/testdir/test63.ok 1969-12-31 19:00:00.000000000 -0500 +++ vim71/src/testdir/test63.ok 2008-06-18 06:51:23.000000000 -0400 @@ -0,0 +1,11 @@ +Results of test63: +*** Test 1: OK +*** Test 2: OK +*** Test 3: OK +*** Test 4: OK +*** Test 5: OK +*** Test 6: OK +*** Test 7: OK +*** Test 8: OK +*** Test 9: OK +*** Test 10: OK diff -Naur vim71.orig/src/testdir/test64.in vim71/src/testdir/test64.in --- vim71.orig/src/testdir/test64.in 1969-12-31 19:00:00.000000000 -0500 +++ vim71/src/testdir/test64.in 2008-06-18 06:54:16.000000000 -0400 @@ -0,0 +1,167 @@ +Test for regexp patterns. + +A pattern that gives the expected result produces OK, so that we know it was +actually tried. + +STARTTEST +:so small.vim +:" tl is a List of Lists with: +:" regexp pattern +:" text to test the pattern on +:" expected match (optional) +:" expected submatch 1 (optional) +:" expected submatch 2 (optional) +:" etc. +:" When there is no match use only the first two items. +:let tl = [] +:call add(tl, ['ab', 'aab', 'ab']) +:call add(tl, ['b', 'abcdef', 'b']) +:call add(tl, ['bc*', 'abccccdef', 'bcccc']) +:call add(tl, ['bc\{-}', 'abccccdef', 'b']) +:call add(tl, ['bc\{-}\(d\)', 'abccccdef', 'bccccd', 'd']) +:call add(tl, ['bc*', 'abbdef', 'b']) +:call add(tl, ['c*', 'ccc', 'ccc']) +:call add(tl, ['bc*', 'abdef', 'b']) +:call add(tl, ['c*', 'abdef', '']) +:call add(tl, ['bc\+', 'abccccdef', 'bcccc']) +:call add(tl, ['bc\+', 'abdef']) "no match +:" +:"operator \| +:call add(tl, ['a\|ab', 'cabd', 'a']) "alternation is ordered +:" +:call add(tl, ['c\?', 'ccb', 'c']) +:call add(tl, ['bc\?', 'abd', 'b']) +:call add(tl, ['bc\?', 'abccd', 'bc']) +:" +:call add(tl, ['\va{1}', 'ab', 'a']) +:" +:call add(tl, ['\va{2}', 'aa', 'aa']) +:call add(tl, ['\va{2}', 'caad', 'aa']) +:call add(tl, ['\va{2}', 'aba']) +:call add(tl, ['\va{2}', 'ab']) +:call add(tl, ['\va{2}', 'abaa', 'aa']) +:call add(tl, ['\va{2}', 'aaa', 'aa']) +:" +:call add(tl, ['\vb{1}', 'abca', 'b']) +:call add(tl, ['\vba{2}', 'abaa', 'baa']) +:call add(tl, ['\vba{3}', 'aabaac']) +:" +:call add(tl, ['\v(ab){1}', 'ab', 'ab', 'ab']) +:call add(tl, ['\v(ab){1}', 'dabc', 'ab', 'ab']) +:call add(tl, ['\v(ab){1}', 'acb']) +:" +:call add(tl, ['\v(ab){0,2}', 'acb', "", ""]) +:call add(tl, ['\v(ab){0,2}', 'ab', 'ab', 'ab']) +:call add(tl, ['\v(ab){1,2}', 'ab', 'ab', 'ab']) +:call add(tl, ['\v(ab){1,2}', 'ababc', 'abab', 'ab']) +:call add(tl, ['\v(ab){2,4}', 'ababcab', 'abab', 'ab']) +:call add(tl, ['\v(ab){2,4}', 'abcababa', 'abab', 'ab']) +:" +:call add(tl, ['\v(ab){2}', 'abab', 'abab', 'ab']) +:call add(tl, ['\v(ab){2}', 'cdababe', 'abab', 'ab']) +:call add(tl, ['\v(ab){2}', 'abac']) +:call add(tl, ['\v(ab){2}', 'abacabab', 'abab', 'ab']) +:call add(tl, ['\v((ab){2}){2}', 'abababab', 'abababab', 'abab', 'ab']) +:call add(tl, ['\v((ab){2}){2}', 'abacabababab', 'abababab', 'abab', 'ab']) +:" +:call add(tl, ['\v(a{1}){1}', 'a', 'a', 'a']) +:call add(tl, ['\v(a{2}){1}', 'aa', 'aa', 'aa']) +:call add(tl, ['\v(a{2}){1}', 'aaac', 'aa', 'aa']) +:call add(tl, ['\v(a{2}){1}', 'daaac', 'aa', 'aa']) +:call add(tl, ['\v(a{1}){2}', 'daaac', 'aa', 'a']) +:call add(tl, ['\v(a{1}){2}', 'aaa', 'aa', 'a']) +:call add(tl, ['\v(a{2})+', 'adaac', 'aa', 'aa']) +:call add(tl, ['\v(a{2})+', 'aa', 'aa', 'aa']) +:call add(tl, ['\v(a{2}){1}', 'aa', 'aa', 'aa']) +:call add(tl, ['\v(a{1}){2}', 'aa', 'aa', 'a']) +:call add(tl, ['\v(a{1}){1}', 'a', 'a', 'a']) +:call add(tl, ['\v(a{2}){2}', 'aaaa', 'aaaa', 'aa']) +:call add(tl, ['\v(a{2}){2}', 'aaabaaaa', 'aaaa', 'aa']) +:" +:call add(tl, ['\v(a+){2}', 'dadaac', 'aa', 'a']) +:call add(tl, ['\v(a{3}){2}', 'aaaaaaa', 'aaaaaa', 'aaa']) +:" +:call add(tl, ['\v(a{1,2}){2}', 'daaac', 'aaa', 'a']) +:call add(tl, ['\v(a{1,3}){2}', 'daaaac', 'aaaa', 'a']) +:call add(tl, ['\v(a{1,3}){2}', 'daaaaac', 'aaaaa', 'aa']) +:call add(tl, ['\v(a{1,3}){3}', 'daac']) +:call add(tl, ['\v(a{1,2}){2}', 'dac']) +:call add(tl, ['\v(a+)+', 'daac', 'aa', 'aa']) +:call add(tl, ['\v(a+)+', 'aaa', 'aaa', 'aaa']) +:call add(tl, ['\v(a+){1,2}', 'aaa', 'aaa', 'aaa']) +:call add(tl, ['\v(a+)(a+)', 'aaa', 'aaa', 'aa', 'a']) +:call add(tl, ['\v(a{3})+', 'daaaac', 'aaa', 'aaa']) +:call add(tl, ['\v(a|b|c)+', 'aacb', 'aacb', 'b']) +:call add(tl, ['\v(a|b|c){2}', 'abcb', 'ab', 'b']) +:call add(tl, ['\v(abc){2}', 'abcabd', ]) +:call add(tl, ['\v(abc){2}', 'abdabcabc','abcabc', 'abc']) +:" +:call add(tl, ['a*', 'cc', '']) +:call add(tl, ['\v(a*)+', 'cc', '']) +:call add(tl, ['\v((ab)+)+', 'ab', 'ab', 'ab', 'ab']) +:call add(tl, ['\v(((ab)+)+)+', 'ab', 'ab', 'ab', 'ab', 'ab']) +:call add(tl, ['\v(((ab)+)+)+', 'dababc', 'abab', 'abab', 'abab', 'ab']) +:call add(tl, ['\v(a{0,2})+', 'cc', '']) +:call add(tl, ['\v(a*)+', '', '']) +:call add(tl, ['\v((a*)+)+', '', '']) +:call add(tl, ['\v((ab)*)+', '', '']) +:call add(tl, ['\va{1,3}', 'aab', 'aa']) +:call add(tl, ['\va{2,3}', 'abaa', 'aa']) +:" +:call add(tl, ['\v((ab)+|c*)+', 'abcccaba', 'abcccab', '', 'ab']) +:call add(tl, ['\v(a{2})|(b{3})', 'bbabbbb', 'bbb', '', 'bbb']) +:call add(tl, ['\va{2}|b{2}', 'abab']) +:call add(tl, ['\v(a)+|(c)+', 'bbacbaacbbb', 'a', 'a']) +:call add(tl, ['\vab{2,3}c', 'aabbccccccccccccc', 'abbc']) +:call add(tl, ['\vab{2,3}c', 'aabbbccccccccccccc', 'abbbc']) +:call add(tl, ['\vab{2,3}cd{2,3}e', 'aabbbcddee', 'abbbcdde']) +:call add(tl, ['\va(bc){2}d', 'aabcbfbc' ]) +:call add(tl, ['\va*a{2}', 'a', ]) +:call add(tl, ['\va*a{2}', 'aa', 'aa' ]) +:call add(tl, ['\va*a{2}', 'aaa', 'aaa' ]) +:call add(tl, ['\va*a{2}', 'bbbabcc', ]) +:call add(tl, ['\va*b*|a*c*', 'a', 'a']) +:call add(tl, ['\va{1}b{1}|a{1}b{1}', '']) +:" +:"submatches +:call add(tl, ['\v(a)', 'ab', 'a', 'a']) +:call add(tl, ['\v(a)(b)', 'ab', 'ab', 'a', 'b']) +:call add(tl, ['\v(ab)(b)(c)', 'abbc', 'abbc', 'ab', 'b', 'c']) +:call add(tl, ['\v((a)(b))', 'ab', 'ab', 'ab', 'a', 'b']) +:call add(tl, ['\v(a)|(b)', 'ab', 'a', 'a']) +:" +:call add(tl, ['\v(a*)+', 'aaaa', 'aaaa', '']) +:call add(tl, ['x', 'abcdef']) +:" +:for t in tl +: let l = matchlist(t[1], t[0]) +:" check the match itself +: if len(l) == 0 && len(t) > 2 +: $put ='ERROR: pat: \"' . t[0] . '\", text: \"' . t[1] . '\", did not match, expected: \"' . t[2] . '\"' +: elseif len(l) > 0 && len(t) == 2 +: $put ='ERROR: pat: \"' . t[0] . '\", text: \"' . t[1] . '\", match: \"' . l[0] . '\", expected no match' +: elseif len(t) > 2 && l[0] != t[2] +: $put ='ERROR: pat: \"' . t[0] . '\", text: \"' . t[1] . '\", match: \"' . l[0] . '\", expected: \"' . t[2] . '\"' +: else +: $put ='OK' +: endif +: if len(l) > 0 +:" check all the nine submatches +: for i in range(1, 9) +: if len(t) <= i + 2 +: let e = '' +: else +: let e = t[i + 2] +: endif +: if l[i] != e +: $put ='ERROR: pat: \"' . t[0] . '\", text: \"' . t[1] . '\", submatch ' . i . ': \"' . l[i] . '\", expected: \"' . e . '\"' +: endif +: endfor +: unlet i +: endif +:endfor +:unlet t tl e l +:/^Results/,$wq! test.out +ENDTEST + +Results of test64: diff -Naur vim71.orig/src/testdir/test64.ok vim71/src/testdir/test64.ok --- vim71.orig/src/testdir/test64.ok 1969-12-31 19:00:00.000000000 -0500 +++ vim71/src/testdir/test64.ok 2008-06-18 06:54:16.000000000 -0400 @@ -0,0 +1,102 @@ +Results of test64: +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK diff -Naur vim71.orig/src/ui.c vim71/src/ui.c --- vim71.orig/src/ui.c 2007-05-07 15:49:09.000000000 -0400 +++ vim71/src/ui.c 2008-06-18 06:52:10.000000000 -0400 @@ -1603,8 +1603,6 @@ #if defined(FEAT_GUI) || defined(FEAT_MOUSE_GPM) \ || defined(FEAT_XCLIPBOARD) || defined(VMS) \ || defined(FEAT_SNIFF) || defined(FEAT_CLIENTSERVER) \ - || (defined(FEAT_GUI) && (!defined(USE_ON_FLY_SCROLL) \ - || defined(FEAT_MENU))) \ || defined(PROTO) /* * Add the given bytes to the input buffer @@ -1630,7 +1628,9 @@ } #endif -#if (defined(FEAT_XIM) && defined(FEAT_GUI_GTK)) \ +#if ((defined(FEAT_XIM) || defined(FEAT_DND)) && defined(FEAT_GUI_GTK)) \ + || defined(FEAT_GUI_MSWIN) \ + || defined(FEAT_GUI_MAC) \ || (defined(FEAT_MBYTE) && defined(FEAT_MBYTE_IME)) \ || (defined(FEAT_GUI) && (!defined(USE_ON_FLY_SCROLL) \ || defined(FEAT_MENU))) \ diff -Naur vim71.orig/src/undo.c vim71/src/undo.c --- vim71.orig/src/undo.c 2007-05-07 15:21:14.000000000 -0400 +++ vim71/src/undo.c 2008-06-18 06:55:41.000000000 -0400 @@ -76,6 +76,12 @@ * buffer is unloaded. */ +/* Uncomment the next line for including the u_check() function. This warns + * for errors in the debug information. */ +/* #define U_DEBUG 1 */ +#define UH_MAGIC 0x18dade /* value for uh_magic when in use */ +#define UE_MAGIC 0xabc123 /* value for ue_magic when in use */ + #include "vim.h" /* See below: use malloc()/free() for memory management. */ @@ -113,6 +119,95 @@ */ static int undo_undoes = FALSE; +#ifdef U_DEBUG +/* + * Check the undo structures for being valid. Print a warning when something + * looks wrong. + */ +static int seen_b_u_curhead; +static int seen_b_u_newhead; +static int header_count; + + static void +u_check_tree(u_header_T *uhp, + u_header_T *exp_uh_next, + u_header_T *exp_uh_alt_prev) +{ + u_entry_T *uep; + + if (uhp == NULL) + return; + ++header_count; + if (uhp == curbuf->b_u_curhead && ++seen_b_u_curhead > 1) + { + EMSG("b_u_curhead found twice (looping?)"); + return; + } + if (uhp == curbuf->b_u_newhead && ++seen_b_u_newhead > 1) + { + EMSG("b_u_newhead found twice (looping?)"); + return; + } + + if (uhp->uh_magic != UH_MAGIC) + EMSG("uh_magic wrong (may be using freed memory)"); + else + { + /* Check pointers back are correct. */ + if (uhp->uh_next != exp_uh_next) + { + EMSG("uh_next wrong"); + smsg((char_u *)"expected: 0x%x, actual: 0x%x", + exp_uh_next, uhp->uh_next); + } + if (uhp->uh_alt_prev != exp_uh_alt_prev) + { + EMSG("uh_alt_prev wrong"); + smsg((char_u *)"expected: 0x%x, actual: 0x%x", + exp_uh_alt_prev, uhp->uh_alt_prev); + } + + /* Check the undo tree at this header. */ + for (uep = uhp->uh_entry; uep != NULL; uep = uep->ue_next) + { + if (uep->ue_magic != UE_MAGIC) + { + EMSG("ue_magic wrong (may be using freed memory)"); + break; + } + } + + /* Check the next alt tree. */ + u_check_tree(uhp->uh_alt_next, uhp->uh_next, uhp); + + /* Check the next header in this branch. */ + u_check_tree(uhp->uh_prev, uhp, NULL); + } +} + + void +u_check(int newhead_may_be_NULL) +{ + seen_b_u_newhead = 0; + seen_b_u_curhead = 0; + header_count = 0; + + u_check_tree(curbuf->b_u_oldhead, NULL, NULL); + + if (seen_b_u_newhead == 0 && curbuf->b_u_oldhead != NULL + && !(newhead_may_be_NULL && curbuf->b_u_newhead == NULL)) + EMSGN("b_u_newhead invalid: 0x%x", curbuf->b_u_newhead); + if (curbuf->b_u_curhead != NULL && seen_b_u_curhead == 0) + EMSGN("b_u_curhead invalid: 0x%x", curbuf->b_u_curhead); + if (header_count != curbuf->b_u_numhead) + { + EMSG("b_u_numhead invalid"); + smsg((char_u *)"expected: %ld, actual: %ld", + (long)header_count, (long)curbuf->b_u_numhead); + } +} +#endif + /* * Save the current line for both the "u" and "U" command. * Returns OK or FAIL. @@ -243,6 +338,9 @@ if (!undo_allowed()) return FAIL; +#ifdef U_DEBUG + u_check(FALSE); +#endif #ifdef FEAT_NETBEANS_INTG /* * Netbeans defines areas that cannot be modified. Bail out here when @@ -294,6 +392,9 @@ uhp = (u_header_T *)U_ALLOC_LINE((unsigned)sizeof(u_header_T)); if (uhp == NULL) goto nomem; +#ifdef U_DEBUG + uhp->uh_magic = UH_MAGIC; +#endif } else uhp = NULL; @@ -316,8 +417,11 @@ { u_header_T *uhfree = curbuf->b_u_oldhead; - /* If there is no branch only free one header. */ - if (uhfree->uh_alt_next == NULL) + if (uhfree == old_curhead) + /* Can't reconnect the branch, delete all of it. */ + u_freebranch(curbuf, uhfree, &old_curhead); + else if (uhfree->uh_alt_next == NULL) + /* There is no branch, only free one header. */ u_freeheader(curbuf, uhfree, &old_curhead); else { @@ -326,6 +430,9 @@ uhfree = uhfree->uh_alt_next; u_freebranch(curbuf, uhfree, &old_curhead); } +#ifdef U_DEBUG + u_check(TRUE); +#endif } if (uhp == NULL) /* no undo at all */ @@ -478,6 +585,9 @@ uep = (u_entry_T *)U_ALLOC_LINE((unsigned)sizeof(u_entry_T)); if (uep == NULL) goto nomem; +#ifdef U_DEBUG + uep->ue_magic = UE_MAGIC; +#endif uep->ue_size = size; uep->ue_top = top; @@ -525,6 +635,9 @@ curbuf->b_u_synced = FALSE; undo_undoes = FALSE; +#ifdef U_DEBUG + u_check(FALSE); +#endif return OK; nomem: @@ -955,6 +1068,9 @@ int empty_buffer; /* buffer became empty */ u_header_T *curhead = curbuf->b_u_curhead; +#ifdef U_DEBUG + u_check(FALSE); +#endif old_flags = curhead->uh_flags; new_flags = (curbuf->b_changed ? UH_CHANGED : 0) + ((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0); @@ -1186,6 +1302,9 @@ /* The timestamp can be the same for multiple changes, just use the one of * the undone/redone change. */ curbuf->b_u_seq_time = curhead->uh_time; +#ifdef U_DEBUG + u_check(FALSE); +#endif } /* @@ -1515,7 +1634,7 @@ } /* - * Free one header and its entry list and adjust the pointers. + * Free one header "uhp" and its entry list and adjust the pointers. */ static void u_freeheader(buf, uhp, uhpp) @@ -1523,6 +1642,8 @@ u_header_T *uhp; u_header_T **uhpp; /* if not NULL reset when freeing this header */ { + u_header_T *uhap; + /* When there is an alternate redo list free that branch completely, * because we can never go there. */ if (uhp->uh_alt_next != NULL) @@ -1540,7 +1661,8 @@ if (uhp->uh_prev == NULL) buf->b_u_newhead = uhp->uh_next; else - uhp->uh_prev->uh_next = uhp->uh_next; + for (uhap = uhp->uh_prev; uhap != NULL; uhap = uhap->uh_alt_next) + uhap->uh_next = uhp->uh_next; u_freeentries(buf, uhp, uhpp); } @@ -1556,6 +1678,14 @@ { u_header_T *tofree, *next; + /* If this is the top branch we may need to use u_freeheader() to update + * all the pointers. */ + if (uhp == buf->b_u_oldhead) + { + u_freeheader(buf, uhp, uhpp); + return; + } + if (uhp->uh_alt_prev != NULL) uhp->uh_alt_prev->uh_alt_next = NULL; @@ -1585,6 +1715,8 @@ /* Check for pointers to the header that become invalid now. */ if (buf->b_u_curhead == uhp) buf->b_u_curhead = NULL; + if (buf->b_u_newhead == uhp) + buf->b_u_newhead = NULL; /* freeing the newest entry */ if (uhpp != NULL && uhp == *uhpp) *uhpp = NULL; @@ -1594,6 +1726,9 @@ u_freeentry(uep, uep->ue_size); } +#ifdef U_DEBUG + uhp->uh_magic = 0; +#endif U_FREE_LINE((char_u *)uhp); --buf->b_u_numhead; } @@ -1609,6 +1744,9 @@ while (n > 0) U_FREE_LINE(uep->ue_array[--n]); U_FREE_LINE((char_u *)uep->ue_array); +#ifdef U_DEBUG + uep->ue_magic = 0; +#endif U_FREE_LINE((char_u *)uep); } @@ -1676,13 +1814,14 @@ if (undo_off) return; - if (curbuf->b_u_line_ptr == NULL || - curbuf->b_u_line_lnum > curbuf->b_ml.ml_line_count) + if (curbuf->b_u_line_ptr == NULL + || curbuf->b_u_line_lnum > curbuf->b_ml.ml_line_count) { beep_flush(); return; } - /* first save the line for the 'u' command */ + + /* first save the line for the 'u' command */ if (u_savecommon(curbuf->b_u_line_lnum - 1, curbuf->b_u_line_lnum + 1, (linenr_T)0) == FAIL) return; @@ -1702,6 +1841,7 @@ curbuf->b_u_line_colnr = curwin->w_cursor.col; curwin->w_cursor.col = t; curwin->w_cursor.lnum = curbuf->b_u_line_lnum; + check_cursor_col(); } /* diff -Naur vim71.orig/src/version.c vim71/src/version.c --- vim71.orig/src/version.c 2007-05-12 06:23:44.000000000 -0400 +++ vim71/src/version.c 2008-06-18 06:57:02.000000000 -0400 @@ -667,6 +667,582 @@ static int included_patches[] = { /* Add new patch number below this line */ /**/ + 315, +/**/ + 314, +/**/ + 313, +/**/ + 311, +/**/ + 310, +/**/ + 309, +/**/ + 308, +/**/ + 307, +/**/ + 306, +/**/ + 305, +/**/ + 304, +/**/ + 303, +/**/ + 302, +/**/ + 301, +/**/ + 300, +/**/ + 299, +/**/ + 298, +/**/ + 297, +/**/ + 296, +/**/ + 295, +/**/ + 294, +/**/ + 293, +/**/ + 292, +/**/ + 291, +/**/ + 290, +/**/ + 289, +/**/ + 288, +/**/ + 287, +/**/ + 286, +/**/ + 284, +/**/ + 281, +/**/ + 279, +/**/ + 277, +/**/ + 276, +/**/ + 274, +/**/ + 273, +/**/ + 272, +/**/ + 271, +/**/ + 270, +/**/ + 269, +/**/ + 268, +/**/ + 267, +/**/ + 266, +/**/ + 265, +/**/ + 264, +/**/ + 263, +/**/ + 262, +/**/ + 261, +/**/ + 260, +/**/ + 259, +/**/ + 258, +/**/ + 257, +/**/ + 256, +/**/ + 255, +/**/ + 254, +/**/ + 253, +/**/ + 252, +/**/ + 251, +/**/ + 250, +/**/ + 249, +/**/ + 248, +/**/ + 247, +/**/ + 246, +/**/ + 245, +/**/ + 244, +/**/ + 243, +/**/ + 242, +/**/ + 241, +/**/ + 240, +/**/ + 239, +/**/ + 238, +/**/ + 237, +/**/ + 236, +/**/ + 235, +/**/ + 234, +/**/ + 233, +/**/ + 232, +/**/ + 231, +/**/ + 230, +/**/ + 229, +/**/ + 228, +/**/ + 227, +/**/ + 226, +/**/ + 225, +/**/ + 224, +/**/ + 223, +/**/ + 222, +/**/ + 221, +/**/ + 220, +/**/ + 219, +/**/ + 218, +/**/ + 217, +/**/ + 216, +/**/ + 215, +/**/ + 214, +/**/ + 213, +/**/ + 212, +/**/ + 211, +/**/ + 210, +/**/ + 209, +/**/ + 208, +/**/ + 207, +/**/ + 206, +/**/ + 205, +/**/ + 203, +/**/ + 202, +/**/ + 201, +/**/ + 200, +/**/ + 199, +/**/ + 198, +/**/ + 197, +/**/ + 195, +/**/ + 194, +/**/ + 193, +/**/ + 192, +/**/ + 191, +/**/ + 190, +/**/ + 189, +/**/ + 188, +/**/ + 187, +/**/ + 186, +/**/ + 185, +/**/ + 184, +/**/ + 183, +/**/ + 182, +/**/ + 181, +/**/ + 180, +/**/ + 179, +/**/ + 178, +/**/ + 177, +/**/ + 176, +/**/ + 175, +/**/ + 174, +/**/ + 173, +/**/ + 172, +/**/ + 171, +/**/ + 170, +/**/ + 169, +/**/ + 167, +/**/ + 166, +/**/ + 165, +/**/ + 164, +/**/ + 163, +/**/ + 162, +/**/ + 161, +/**/ + 160, +/**/ + 159, +/**/ + 157, +/**/ + 156, +/**/ + 155, +/**/ + 154, +/**/ + 153, +/**/ + 152, +/**/ + 151, +/**/ + 150, +/**/ + 149, +/**/ + 148, +/**/ + 147, +/**/ + 145, +/**/ + 144, +/**/ + 143, +/**/ + 142, +/**/ + 141, +/**/ + 140, +/**/ + 139, +/**/ + 138, +/**/ + 137, +/**/ + 136, +/**/ + 135, +/**/ + 133, +/**/ + 132, +/**/ + 131, +/**/ + 130, +/**/ + 127, +/**/ + 125, +/**/ + 123, +/**/ + 122, +/**/ + 121, +/**/ + 120, +/**/ + 119, +/**/ + 118, +/**/ + 117, +/**/ + 116, +/**/ + 115, +/**/ + 114, +/**/ + 113, +/**/ + 112, +/**/ + 111, +/**/ + 110, +/**/ + 109, +/**/ + 108, +/**/ + 107, +/**/ + 106, +/**/ + 105, +/**/ + 104, +/**/ + 103, +/**/ + 102, +/**/ + 101, +/**/ + 100, +/**/ + 99, +/**/ + 98, +/**/ + 97, +/**/ + 96, +/**/ + 95, +/**/ + 94, +/**/ + 93, +/**/ + 90, +/**/ + 89, +/**/ + 87, +/**/ + 86, +/**/ + 85, +/**/ + 84, +/**/ + 83, +/**/ + 82, +/**/ + 81, +/**/ + 79, +/**/ + 78, +/**/ + 77, +/**/ + 76, +/**/ + 75, +/**/ + 74, +/**/ + 73, +/**/ + 71, +/**/ + 69, +/**/ + 68, +/**/ + 67, +/**/ + 66, +/**/ + 64, +/**/ + 63, +/**/ + 62, +/**/ + 61, +/**/ + 60, +/**/ + 59, +/**/ + 58, +/**/ + 57, +/**/ + 56, +/**/ + 55, +/**/ + 54, +/**/ + 53, +/**/ + 52, +/**/ + 51, +/**/ + 50, +/**/ + 49, +/**/ + 48, +/**/ + 47, +/**/ + 46, +/**/ + 45, +/**/ + 44, +/**/ + 43, +/**/ + 42, +/**/ + 40, +/**/ + 39, +/**/ + 38, +/**/ + 37, +/**/ + 36, +/**/ + 35, +/**/ + 34, +/**/ + 33, +/**/ + 32, +/**/ + 31, +/**/ + 30, +/**/ + 29, +/**/ + 28, +/**/ + 27, +/**/ + 26, +/**/ + 25, +/**/ + 24, +/**/ + 23, +/**/ + 22, +/**/ + 21, +/**/ + 20, +/**/ + 19, +/**/ + 18, +/**/ + 17, +/**/ + 16, +/**/ + 15, +/**/ + 14, +/**/ + 13, +/**/ + 12, +/**/ + 11, +/**/ + 10, +/**/ + 9, +/**/ + 8, +/**/ + 6, +/**/ + 5, +/**/ + 4, +/**/ + 2, +/**/ + 1, +/**/ 0 }; @@ -1177,9 +1753,9 @@ if (*mesg == ' ') { - vim_strncpy(modby, _("Modified by "), MODBY_LEN - 1); + vim_strncpy(modby, (char_u *)_("Modified by "), MODBY_LEN - 1); l = STRLEN(modby); - vim_strncpy(modby + l, MODIFIED_BY, MODBY_LEN - l - 1); + vim_strncpy(modby + l, (char_u *)MODIFIED_BY, MODBY_LEN - l - 1); mesg = modby; } #endif diff -Naur vim71.orig/src/vim.h vim71/src/vim.h --- vim71.orig/src/vim.h 2007-05-12 05:53:29.000000000 -0400 +++ vim71/src/vim.h 2008-06-18 06:56:43.000000000 -0400 @@ -336,10 +336,10 @@ # endif #endif #ifdef BACKSLASH_IN_FILENAME -# define PATH_ESC_CHARS ((char_u *)" \t*?[{`%#") +# define PATH_ESC_CHARS ((char_u *)" \t\n*?[{`%#'\"|!<") #else -# define PATH_ESC_CHARS ((char_u *)" \t*?[{`$\\%#'\"|") -# define SHELL_ESC_CHARS ((char_u *)" \t*?[{`$\\%#'\"|<>();&!") +# define PATH_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<") +# define SHELL_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<>();&") #endif #define NUMBUFLEN 30 /* length of a buffer to store a number in ASCII */ @@ -721,6 +721,11 @@ /* Note: mostly EW_NOTFOUND and EW_SILENT are mutually exclusive: EW_NOTFOUND * is used when executing commands and EW_SILENT for interactive expanding. */ +/* Flags for find_file_*() functions. */ +#define FINDFILE_FILE 0 /* only files */ +#define FINDFILE_DIR 1 /* only directories */ +#define FINDFILE_BOTH 2 /* files and directories */ + #ifdef FEAT_VERTSPLIT # define W_WINCOL(wp) (wp->w_wincol) # define W_WIDTH(wp) (wp->w_width) @@ -943,6 +948,7 @@ #define INSCHAR_FORMAT 1 /* force formatting */ #define INSCHAR_DO_COM 2 /* format comments */ #define INSCHAR_CTRLV 4 /* char typed just after CTRL-V */ +#define INSCHAR_NO_FEX 8 /* don't use 'formatexpr' */ /* flags for open_line() */ #define OPENLINE_DELSPACES 1 /* delete spaces after cursor */ @@ -1380,8 +1386,14 @@ #endif #ifdef FEAT_MBYTE -# define MB_STRICMP(d, s) (has_mbyte ? mb_strnicmp((char_u *)(d), (char_u *)(s), (int)MAXCOL) : STRICMP((d), (s))) -# define MB_STRNICMP(d, s, n) (has_mbyte ? mb_strnicmp((char_u *)(d), (char_u *)(s), (int)(n)) : STRNICMP((d), (s), (n))) +/* We need to call mb_stricmp() even when we aren't dealing with a multi-byte + * encoding because mb_stricmp() takes care of all ascii and non-ascii + * encodings, including characters with umluats in latin1, etc., while + * STRICMP() only handles the system locale version, which often does not + * handle non-ascii properly. */ + +# define MB_STRICMP(d, s) mb_strnicmp((char_u *)(d), (char_u *)(s), (int)MAXCOL) +# define MB_STRNICMP(d, s, n) mb_strnicmp((char_u *)(d), (char_u *)(s), (int)(n)) #else # define MB_STRICMP(d, s) STRICMP((d), (s)) # define MB_STRNICMP(d, s, n) STRNICMP((d), (s), (n)) @@ -1544,6 +1556,16 @@ # define MB_MAXBYTES 21 #endif +#if (defined(FEAT_PROFILE) || defined(FEAT_RELTIME)) && !defined(PROTO) +# ifdef WIN3264 +typedef LARGE_INTEGER proftime_T; +# else +typedef struct timeval proftime_T; +# endif +#else +typedef int proftime_T; /* dummy for function prototypes */ +#endif + /* Include option.h before structs.h, because the number of window-local and * buffer-local options is used there. */ #include "option.h" /* options and default values */ @@ -1682,7 +1704,8 @@ #define VV_MOUSE_WIN 49 #define VV_MOUSE_LNUM 50 #define VV_MOUSE_COL 51 -#define VV_LEN 52 /* number of v: vars */ +#define VV_OP 52 +#define VV_LEN 53 /* number of v: vars */ #ifdef FEAT_CLIPBOARD @@ -1755,16 +1778,6 @@ # define stat(a,b) (access(a,0) ? -1 : stat(a,b)) #endif -#if (defined(FEAT_PROFILE) || defined(FEAT_RELTIME)) && !defined(PROTO) -# ifdef WIN3264 -typedef LARGE_INTEGER proftime_T; -# else -typedef struct timeval proftime_T; -# endif -#else -typedef int proftime_T; /* dummy for function prototypes */ -#endif - #include "ex_cmds.h" /* Ex command defines */ #include "proto.h" /* function prototypes */ diff -Naur vim71.orig/src/vimtutor vim71/src/vimtutor --- vim71.orig/src/vimtutor 2004-06-07 10:32:27.000000000 -0400 +++ vim71/src/vimtutor 2008-06-18 06:56:38.000000000 -0400 @@ -2,11 +2,24 @@ # Start Vim on a copy of the tutor file. -# Usage: vimtutor [xx], where xx is a language code like "es" or "nl". +# Usage: vimtutor [-g] [xx] +# Where optional argument -g starts vimtutor in gvim (GUI) instead of vim. +# and xx is a language code like "es" or "nl". # When an argument is given, it tries loading that tutor. # When this fails or no argument was given, it tries using 'v:lang' # When that also fails, it uses the English version. +# Vim could be called "vim" or "vi". Also check for "vimN", for people who +# have Vim installed with its version number. +# We anticipate up to a future Vim 8 version :-). +seq="vim vim8 vim75 vim74 vim73 vim72 vim71 vim70 vim7 vim6 vi" +if test "$1" = "-g"; then + # Try to use the GUI version of Vim if possible, it will fall back + # on Vim if Gvim is not installed. + seq="gvim gvim8 gvim75 gvim74 gvim73 gvim72 gvim71 gvim70 gvim7 gvim6 $seq" + shift +fi + xx=$1 export xx @@ -39,23 +52,23 @@ # remove the copy of the tutor on exit trap "rm -rf $TODELETE" 0 1 2 3 9 11 13 15 -# Vim could be called "vim" or "vi". Also check for "vim6", for people who -# have Vim 5.x installed as "vim" and Vim 6.0 as "vim6". -testvim=`which vim6 2>/dev/null` -if test -f "$testvim"; then - VIM=vim6 -else - testvim=`which vim` +for i in $seq; do + testvim=`which $i 2>/dev/null` if test -f "$testvim"; then - VIM=vim - else - VIM=vi + VIM=$i + break fi +done + +# When no Vim version was found fall back to "vim", you'll get an error message +# below. +if test -z "$VIM"; then + VIM=vim fi # Use Vim to copy the tutor, it knows the value of $VIMRUNTIME # The script tutor.vim tells Vim which file to copy -$VIM -u NONE -c 'so $VIMRUNTIME/tutor/tutor.vim' +$VIM -f -u NONE -c 'so $VIMRUNTIME/tutor/tutor.vim' # Start vim without any .vimrc, set 'nocompatible' -$VIM -u NONE -c "set nocp" $TUTORCOPY +$VIM -f -u NONE -c "set nocp" $TUTORCOPY diff -Naur vim71.orig/src/window.c vim71/src/window.c --- vim71.orig/src/window.c 2007-05-07 15:25:30.000000000 -0400 +++ vim71/src/window.c 2008-06-18 06:53:09.000000000 -0400 @@ -75,6 +75,7 @@ static win_T *restore_snapshot_rec __ARGS((frame_T *sn, frame_T *fr)); #endif /* FEAT_WINDOWS */ + static win_T *win_alloc __ARGS((win_T *after)); static void win_new_height __ARGS((win_T *, int)); @@ -583,7 +584,7 @@ ++no_mapping; ++allow_keys; /* no mapping for xchar, but allow key codes */ if (xchar == NUL) - xchar = safe_vgetc(); + xchar = plain_vgetc(); #ifdef FEAT_LANGMAP LANGMAP_ADJUST(xchar, TRUE); #endif @@ -732,7 +733,6 @@ if (flags & WSP_VERT) { layout = FR_ROW; - do_equal = (p_ea && new_size == 0 && *p_ead != 'v'); /* * Check if we are able to split the current window and compute its @@ -769,16 +769,31 @@ * instead, if possible. */ if (oldwin->w_p_wfw) win_setwidth_win(oldwin->w_width + new_size, oldwin); + + /* Only make all windows the same width if one of them (except oldwin) + * is wider than one of the split windows. */ + if (!do_equal && p_ea && size == 0 && *p_ead != 'v' + && oldwin->w_frame->fr_parent != NULL) + { + frp = oldwin->w_frame->fr_parent->fr_child; + while (frp != NULL) + { + if (frp->fr_win != oldwin && frp->fr_win != NULL + && (frp->fr_win->w_width > new_size + || frp->fr_win->w_width > oldwin->w_width + - new_size - STATUS_HEIGHT)) + { + do_equal = TRUE; + break; + } + frp = frp->fr_next; + } + } } else #endif { layout = FR_COL; - do_equal = (p_ea && new_size == 0 -#ifdef FEAT_VERTSPLIT - && *p_ead != 'h' -#endif - ); /* * Check if we are able to split the current window and compute its @@ -831,6 +846,29 @@ if (need_status) oldwin_height -= STATUS_HEIGHT; } + + /* Only make all windows the same height if one of them (except oldwin) + * is higher than one of the split windows. */ + if (!do_equal && p_ea && size == 0 +#ifdef FEAT_VERTSPLIT + && *p_ead != 'h' +#endif + && oldwin->w_frame->fr_parent != NULL) + { + frp = oldwin->w_frame->fr_parent->fr_child; + while (frp != NULL) + { + if (frp->fr_win != oldwin && frp->fr_win != NULL + && (frp->fr_win->w_height > new_size + || frp->fr_win->w_height > oldwin_height - new_size + - STATUS_HEIGHT)) + { + do_equal = TRUE; + break; + } + frp = frp->fr_next; + } + } } /* @@ -1253,7 +1291,7 @@ * Don't execute autocommands while creating the windows. Must do that * when putting the buffers in the windows. */ - ++autocmd_block; + block_autocmds(); #endif /* todo is number of windows left to create */ @@ -1275,7 +1313,7 @@ } #ifdef FEAT_AUTOCMD - --autocmd_block; + unblock_autocmds(); #endif /* return actual number of windows */ @@ -2120,7 +2158,7 @@ if (wp->w_p_pvw || bt_quickfix(wp->w_buffer)) { /* - * The cursor goes to the preview or the quickfix window, try + * If the cursor goes to the preview or the quickfix window, try * finding another window to go to. */ for (;;) @@ -2307,7 +2345,6 @@ frame_T *frp, *frp2, *frp3; frame_T *frp_close = win->w_frame; win_T *wp; - int old_size = 0; /* * If there is only one window there is nothing to remove. @@ -2328,33 +2365,77 @@ if (frp_close->fr_parent->fr_layout == FR_COL) { #endif - /* When 'winfixheight' is set, remember its old size and restore - * it later (it's a simplistic solution...). Don't do this if the - * window will occupy the full height of the screen. */ - if (frp2->fr_win != NULL - && (frp2->fr_next != NULL || frp2->fr_prev != NULL) - && frp2->fr_win->w_p_wfh) - old_size = frp2->fr_win->w_height; + /* When 'winfixheight' is set, try to find another frame in the column + * (as close to the closed frame as possible) to distribute the height + * to. */ + if (frp2->fr_win != NULL && frp2->fr_win->w_p_wfh) + { + frp = frp_close->fr_prev; + frp3 = frp_close->fr_next; + while (frp != NULL || frp3 != NULL) + { + if (frp != NULL) + { + if (frp->fr_win != NULL && !frp->fr_win->w_p_wfh) + { + frp2 = frp; + wp = frp->fr_win; + break; + } + frp = frp->fr_prev; + } + if (frp3 != NULL) + { + if (frp3->fr_win != NULL && !frp3->fr_win->w_p_wfh) + { + frp2 = frp3; + wp = frp3->fr_win; + break; + } + frp3 = frp3->fr_next; + } + } + } frame_new_height(frp2, frp2->fr_height + frp_close->fr_height, frp2 == frp_close->fr_next ? TRUE : FALSE, FALSE); - if (old_size != 0) - win_setheight_win(old_size, frp2->fr_win); #ifdef FEAT_VERTSPLIT *dirp = 'v'; } else { - /* When 'winfixwidth' is set, remember its old size and restore - * it later (it's a simplistic solution...). Don't do this if the - * window will occupy the full width of the screen. */ - if (frp2->fr_win != NULL - && (frp2->fr_next != NULL || frp2->fr_prev != NULL) - && frp2->fr_win->w_p_wfw) - old_size = frp2->fr_win->w_width; + /* When 'winfixwidth' is set, try to find another frame in the column + * (as close to the closed frame as possible) to distribute the width + * to. */ + if (frp2->fr_win != NULL && frp2->fr_win->w_p_wfw) + { + frp = frp_close->fr_prev; + frp3 = frp_close->fr_next; + while (frp != NULL || frp3 != NULL) + { + if (frp != NULL) + { + if (frp->fr_win != NULL && !frp->fr_win->w_p_wfw) + { + frp2 = frp; + wp = frp->fr_win; + break; + } + frp = frp->fr_prev; + } + if (frp3 != NULL) + { + if (frp3->fr_win != NULL && !frp3->fr_win->w_p_wfw) + { + frp2 = frp3; + wp = frp3->fr_win; + break; + } + frp3 = frp3->fr_next; + } + } + } frame_new_width(frp2, frp2->fr_width + frp_close->fr_width, frp2 == frp_close->fr_next ? TRUE : FALSE, FALSE); - if (old_size != 0) - win_setwidth_win(old_size, frp2->fr_win); *dirp = 'h'; } #endif @@ -3334,7 +3415,7 @@ * Don't execute autocommands while creating the tab pages. Must do that * when putting the buffers in the windows. */ - ++autocmd_block; + block_autocmds(); #endif for (todo = count - 1; todo > 0; --todo) @@ -3342,7 +3423,7 @@ break; #ifdef FEAT_AUTOCMD - --autocmd_block; + unblock_autocmds(); #endif /* return actual number of tab pages */ @@ -4081,7 +4162,7 @@ /* Don't execute autocommands while the window is not properly * initialized yet. gui_create_scrollbar() may trigger a FocusGained * event. */ - ++autocmd_block; + block_autocmds(); #endif /* * link the window in the window list @@ -4126,7 +4207,11 @@ foldInitWin(newwin); #endif #ifdef FEAT_AUTOCMD - --autocmd_block; + unblock_autocmds(); +#endif +#ifdef FEAT_SEARCH_EXTRA + newwin->w_match_head = NULL; + newwin->w_next_match_id = 4; #endif } return newwin; @@ -4147,7 +4232,7 @@ #ifdef FEAT_AUTOCMD /* Don't execute autocommands while the window is halfway being deleted. * gui_mch_destroy_scrollbar() may trigger a FocusGained event. */ - ++autocmd_block; + block_autocmds(); #endif #ifdef FEAT_MZSCHEME @@ -4185,11 +4270,11 @@ vim_free(wp->w_tagstack[i].tagname); vim_free(wp->w_localdir); + #ifdef FEAT_SEARCH_EXTRA - vim_free(wp->w_match[0].regprog); - vim_free(wp->w_match[1].regprog); - vim_free(wp->w_match[2].regprog); + clear_matches(wp); #endif + #ifdef FEAT_JUMPLIST free_jumplist(wp); #endif @@ -4210,7 +4295,7 @@ vim_free(wp); #ifdef FEAT_AUTOCMD - --autocmd_block; + unblock_autocmds(); #endif } @@ -5438,6 +5523,7 @@ { EMSG(_(e_noroom)); p_ch = old_p_ch; + curtab->tp_ch_used = p_ch; cmdline_row = Rows - p_ch; break; } @@ -6174,3 +6260,175 @@ return FALSE; } #endif + +#if defined(FEAT_SEARCH_EXTRA) || defined(PROTO) +/* + * Add match to the match list of window 'wp'. The pattern 'pat' will be + * highligted with the group 'grp' with priority 'prio'. + * Optionally, a desired ID 'id' can be specified (greater than or equal to 1). + * If no particular ID is desired, -1 must be specified for 'id'. + * Return ID of added match, -1 on failure. + */ + int +match_add(wp, grp, pat, prio, id) + win_T *wp; + char_u *grp; + char_u *pat; + int prio; + int id; +{ + matchitem_T *cur; + matchitem_T *prev; + matchitem_T *m; + int hlg_id; + regprog_T *regprog; + + if (*grp == NUL || *pat == NUL) + return -1; + if (id < -1 || id == 0) + { + EMSGN("E799: Invalid ID: %ld (must be greater than or equal to 1)", id); + return -1; + } + if (id != -1) + { + cur = wp->w_match_head; + while (cur != NULL) + { + if (cur->id == id) + { + EMSGN("E801: ID already taken: %ld", id); + return -1; + } + cur = cur->next; + } + } + if ((hlg_id = syn_namen2id(grp, STRLEN(grp))) == 0) + { + EMSG2(_(e_nogroup), grp); + return -1; + } + if ((regprog = vim_regcomp(pat, RE_MAGIC)) == NULL) + { + EMSG2(_(e_invarg2), pat); + return -1; + } + + /* Find available match ID. */ + while (id == -1) + { + cur = wp->w_match_head; + while (cur != NULL && cur->id != wp->w_next_match_id) + cur = cur->next; + if (cur == NULL) + id = wp->w_next_match_id; + wp->w_next_match_id++; + } + + /* Build new match. */ + m = (matchitem_T *)alloc(sizeof(matchitem_T)); + m->id = id; + m->priority = prio; + m->pattern = vim_strsave(pat); + m->hlg_id = hlg_id; + m->match.regprog = regprog; + m->match.rmm_ic = FALSE; + m->match.rmm_maxcol = 0; + + /* Insert new match. The match list is in ascending order with regard to + * the match priorities. */ + cur = wp->w_match_head; + prev = cur; + while (cur != NULL && prio >= cur->priority) + { + prev = cur; + cur = cur->next; + } + if (cur == prev) + wp->w_match_head = m; + else + prev->next = m; + m->next = cur; + + redraw_later(SOME_VALID); + return id; +} + +/* + * Delete match with ID 'id' in the match list of window 'wp'. + * Print error messages if 'perr' is TRUE. + */ + int +match_delete(wp, id, perr) + win_T *wp; + int id; + int perr; +{ + matchitem_T *cur = wp->w_match_head; + matchitem_T *prev = cur; + + if (id < 1) + { + if (perr == TRUE) + EMSGN("E802: Invalid ID: %ld (must be greater than or equal to 1)", + id); + return -1; + } + while (cur != NULL && cur->id != id) + { + prev = cur; + cur = cur->next; + } + if (cur == NULL) + { + if (perr == TRUE) + EMSGN("E803: ID not found: %ld", id); + return -1; + } + if (cur == prev) + wp->w_match_head = cur->next; + else + prev->next = cur->next; + vim_free(cur->match.regprog); + vim_free(cur->pattern); + vim_free(cur); + redraw_later(SOME_VALID); + return 0; +} + +/* + * Delete all matches in the match list of window 'wp'. + */ + void +clear_matches(wp) + win_T *wp; +{ + matchitem_T *m; + + while (wp->w_match_head != NULL) + { + m = wp->w_match_head->next; + vim_free(wp->w_match_head->match.regprog); + vim_free(wp->w_match_head->pattern); + vim_free(wp->w_match_head); + wp->w_match_head = m; + } + redraw_later(SOME_VALID); +} + +/* + * Get match from ID 'id' in window 'wp'. + * Return NULL if match not found. + */ + matchitem_T * +get_match(wp, id) + win_T *wp; + int id; +{ + matchitem_T *cur = wp->w_match_head; + + while (cur != NULL && cur->id != id) + cur = cur->next; + return cur; +} +#endif diff -Naur vim71.orig/src/xxd/xxd.c vim71/src/xxd/xxd.c --- vim71.orig/src/xxd/xxd.c 2007-05-07 15:41:57.000000000 -0400 +++ vim71/src/xxd/xxd.c 2008-06-18 06:54:00.000000000 -0400 @@ -212,7 +212,7 @@ #define TRY_SEEK /* attempt to use lseek, or skip forward by reading */ #define COLS 256 /* change here, if you ever need more columns */ -#define LLEN (9 + (5*COLS-1)/2 + 2 + COLS) +#define LLEN (11 + (9*COLS-1)/1 + COLS + 2) char hexxa[] = "0123456789abcdef0123456789ABCDEF", *hexx = hexxa; @@ -590,7 +590,8 @@ default: octspergrp = 0; break; } - if (cols < 1 || (!hextype && (cols > COLS))) + if (cols < 1 || ((hextype == HEX_NORMAL || hextype == HEX_BITS) + && (cols > COLS))) { fprintf(stderr, "%s: invalid number of columns (max. %d).\n", pname, COLS); exit(1); @@ -750,6 +751,7 @@ } if (ebcdic) e = (e < 64) ? '.' : etoa64[e-64]; + /* When changing this update definition of LLEN above. */ l[11 + (grplen * cols - 1)/octspergrp + p] = #ifdef __MVS__ (e >= 64)