Submitted By: William Harrington (kb0iic at gmail dot com) Date: 07-31-2012 Initial Package Version: 7.3 Origin: Upstream Upstream Status: Applied Description: Contains all upstream patches up to 7.3.608 diff -Naur vim73.orig/Filelist vim73/Filelist --- vim73.orig/Filelist 2010-08-07 11:04:57.000000000 +0000 +++ vim73/Filelist 2012-07-20 20:31:18.230978438 +0000 @@ -39,6 +39,7 @@ src/mark.c \ src/mbyte.c \ src/memfile.c \ + src/memfile_test.c \ src/memline.c \ src/menu.c \ src/message.c \ @@ -80,6 +81,7 @@ src/testdir/test[0-9]*.ok \ src/testdir/test49.vim \ src/testdir/test60.vim \ + src/testdir/test83-tags? \ src/proto.h \ src/proto/blowfish.pro \ src/proto/buffer.pro \ @@ -261,6 +263,7 @@ src/bigvim.bat \ src/msvcsetup.bat \ src/msvc2008.bat \ + src/msvc2010.bat \ src/dimm.idl \ src/dlldata.c \ src/dosinst.c \ @@ -311,6 +314,7 @@ src/xxd/Make_bc5.mak \ src/xxd/Make_cyg.mak \ src/xxd/Make_djg.mak \ + src/xxd/Make_ming.mak \ src/xxd/Make_mvc.mak \ nsis/gvim.nsi \ nsis/README.txt \ @@ -426,9 +430,6 @@ $(SRC_VMS) \ README_os390.txt \ src/Make_mint.mak \ - src/Make_ro.mak \ - src/gui_riscos.c \ - src/gui_riscos.h \ src/if_sniff.c \ src/infplist.xml \ src/link.390 \ @@ -436,10 +437,6 @@ src/os_beos.h \ src/os_beos.rsrc \ src/os_mint.h \ - src/os_riscos.c \ - src/os_riscos.h \ - src/proto/gui_riscos.pro \ - src/proto/os_riscos.pro \ src/os_vms_fix.com \ src/toolbar.phi \ @@ -466,6 +463,7 @@ runtime/macros/hanoi/hanoi.vim \ runtime/macros/hanoi/poster \ runtime/macros/justify.vim \ + runtime/macros/less.bat \ runtime/macros/less.sh \ runtime/macros/less.vim \ runtime/macros/life/click.me \ @@ -669,6 +667,8 @@ # generic language files LANG_GEN = \ + runtime/doc/*-de.1 \ + runtime/doc/*-de.UTF-8.1 \ runtime/doc/*-fr.1 \ runtime/doc/*-fr.UTF-8.1 \ runtime/doc/*-it.1 \ @@ -686,6 +686,8 @@ runtime/tutor/tutor.utf-8 \ runtime/tutor/tutor.?? \ runtime/tutor/tutor.??.* \ + runtime/tutor/tutor.bar \ + runtime/tutor/tutor.bar.* \ runtime/spell/README.txt \ runtime/spell/??/*.diff \ runtime/spell/??/main.aap \ diff -Naur vim73.orig/Makefile vim73/Makefile --- vim73.orig/Makefile 2010-08-15 12:23:34.000000000 +0000 +++ vim73/Makefile 2012-07-20 20:31:09.600972239 +0000 @@ -23,6 +23,9 @@ # has run can result in compiling with $(CC) empty. first: + @if test ! -f src/auto/config.mk; then \ + cp src/config.mk.dist src/auto/config.mk; \ + fi @echo "Starting make in the src directory." @echo "If there are problems, cd to the src directory and run make there" cd src && $(MAKE) $@ @@ -30,6 +33,9 @@ # Some make programs use the last target for the $@ default; put the other # targets separately to always let $@ expand to "first" by default. all install uninstall tools config configure reconfig proto depend lint tags types test testclean clean distclean: + @if test ! -f src/auto/config.mk; then \ + cp src/config.mk.dist src/auto/config.mk; \ + fi @echo "Starting make in the src directory." @echo "If there are problems, cd to the src directory and run make there" cd src && $(MAKE) $@ diff -Naur vim73.orig/README_extra.txt vim73/README_extra.txt --- vim73.orig/README_extra.txt 2010-08-15 12:23:19.000000000 +0000 +++ vim73/README_extra.txt 2012-07-20 20:31:10.880973163 +0000 @@ -13,9 +13,6 @@ src/os_amiga.* Files for the Amiga port. -src/gui_riscos.* -src/os_riscos.* Files for the RISC OS port. - src/gui_beos.* src/os_beos.* Files for the BeOS port. diff -Naur vim73.orig/runtime/doc/autocmd.txt vim73/runtime/doc/autocmd.txt --- vim73.orig/runtime/doc/autocmd.txt 2010-08-15 12:23:19.000000000 +0000 +++ vim73/runtime/doc/autocmd.txt 2012-07-20 20:31:15.250976305 +0000 @@ -299,6 +299,8 @@ |InsertEnter| starting Insert mode |InsertChange| when typing while in Insert or Replace mode |InsertLeave| when leaving Insert mode +|InsertCharPre| when a character was typed in Insert mode, before + inserting it |ColorScheme| after loading a color scheme @@ -657,6 +659,17 @@ indicates the new mode. Be careful not to move the cursor or do anything else that the user does not expect. + *InsertCharPre* +InsertCharPre When a character is typed in Insert mode, + before inserting the char. + The |v:char| variable indicates the char typed + and can be changed during the event to insert + a different character. When |v:char| is set + to more than one character this text is + inserted literally. + It is not allowed to change the text |textlock|. + The event is not triggered when 'paste' is + set. *InsertEnter* InsertEnter Just before starting Insert mode. Also for Replace mode and Virtual Replace mode. The @@ -682,7 +695,10 @@ QuickFixCmdPre Before a quickfix command is run (|:make|, |:lmake|, |:grep|, |:lgrep|, |:grepadd|, |:lgrepadd|, |:vimgrep|, |:lvimgrep|, - |:vimgrepadd|, |:lvimgrepadd|, |:cscope|). + |:vimgrepadd|, |:lvimgrepadd|, |:cscope|, + |:cfile|, |:cgetfile|, |:caddfile|, |:lfile|, + |:lgetfile|, |:laddfile|, |:helpgrep|, + |:lhelpgrep|). The pattern is matched against the command being run. When |:grep| is used but 'grepprg' is set to "internal" it still matches "grep". @@ -693,7 +709,10 @@ *QuickFixCmdPost* QuickFixCmdPost Like QuickFixCmdPre, but after a quickfix command is run, before jumping to the first - location. See |QuickFixCmdPost-example|. + location. For |:cfile| and |:lfile| commands + it is run after error file is read and before + moving to the first error. + See |QuickFixCmdPost-example|. *RemoteReply* RemoteReply When a reply from a Vim that functions as server was received |server2client()|. The @@ -1051,14 +1070,17 @@ argument is included, Vim executes only the matching autocommands for that group. Note: if you use an undefined group name, Vim gives you an error message. - + ** After applying the autocommands the modelines are processed, so that their settings overrule the settings from autocommands, like what happens when - editing a file. + editing a file. This is skipped when the + argument is present. You probably want to use + for events that are not used when loading + a buffer, such as |User|. *:doautoa* *:doautoall* -:doautoa[ll] [group] {event} [fname] +:doautoa[ll] [] [group] {event} [fname] Like ":doautocmd", but apply the autocommands to each loaded buffer. Note that [fname] is used to select the autocommands, not the buffers to which they are diff -Naur vim73.orig/runtime/doc/change.txt vim73/runtime/doc/change.txt --- vim73.orig/runtime/doc/change.txt 2010-08-15 12:23:19.000000000 +0000 +++ vim73/runtime/doc/change.txt 2012-07-20 20:31:16.577643922 +0000 @@ -916,8 +916,10 @@ {Visual}["x]Y Yank the highlighted lines [into register x] (for {Visual} see |Visual-mode|). {not in Vi} - *:y* *:yank* -:[range]y[ank] [x] Yank [range] lines [into register x]. + *:y* *:yank* *E850* +:[range]y[ank] [x] Yank [range] lines [into register x]. Yanking to the + "* or "+ registers is possible only in GUI versions or + when the |+xterm_clipboard| feature is included. :[range]y[ank] [x] {count} Yank {count} lines, starting with last line number @@ -1493,6 +1495,12 @@ characters. Overruled by the 'M' flag. 1 Don't break a line after a one-letter word. It's broken before it instead (if possible). +j Where it makes sense, remove a comment leader when joining lines. For + example, joining: + int i; // the index ~ + // in the list ~ + Becomes: + int i; // the index in the list ~ With 't' and 'c' you can specify when Vim performs auto-wrapping: diff -Naur vim73.orig/runtime/doc/cmdline.txt vim73/runtime/doc/cmdline.txt --- vim73.orig/runtime/doc/cmdline.txt 2010-08-15 12:23:19.000000000 +0000 +++ vim73/runtime/doc/cmdline.txt 2012-07-20 20:31:16.060976885 +0000 @@ -330,12 +330,12 @@ :his[tory] [{name}] [{first}][, [{last}]] List the contents of history {name} which can be: - c[md] or : command-line history - s[earch] or / search string history - e[xpr] or = expression register history - i[nput] or @ input line history - d[ebug] or > debug command history - a[ll] all of the above + c[md] or : command-line history + s[earch] or / or ? search string history + e[xpr] or = expression register history + i[nput] or @ input line history + d[ebug] or > debug command history + a[ll] all of the above {not in Vi} If the numbers {first} and/or {last} are given, the respective diff -Naur vim73.orig/runtime/doc/diff.txt vim73/runtime/doc/diff.txt --- vim73.orig/runtime/doc/diff.txt 2010-08-15 12:23:20.000000000 +0000 +++ vim73/runtime/doc/diff.txt 2012-07-20 20:31:16.204310320 +0000 @@ -178,7 +178,7 @@ nodiff" before hiding it. *:diffu* *:diffupdate* -:diffu[pdate] Update the diff highlighting and folds. +:diffu[pdate][!] Update the diff highlighting and folds. Vim attempts to keep the differences updated when you make changes to the text. This mostly takes care of inserted and deleted lines. Changes within a @@ -187,6 +187,9 @@ :diffupdate +If the ! is included Vim will check if the file was changed externally and +needs to be reloaded. It will prompt for each changed file, like `:checktime` +was used. Vim will show filler lines for lines that are missing in one window but are present in another. These lines were inserted in another file or deleted in diff -Naur vim73.orig/runtime/doc/eval.txt vim73/runtime/doc/eval.txt --- vim73.orig/runtime/doc/eval.txt 2010-08-15 12:23:20.000000000 +0000 +++ vim73/runtime/doc/eval.txt 2012-07-20 20:31:17.304311108 +0000 @@ -798,11 +798,12 @@ For |Lists| only "+" is possible and then both expr6 must be a list. The result is a new list with the two lists Concatenated. -expr7 * expr7 .. number multiplication *expr-star* -expr7 / expr7 .. number division *expr-/* -expr7 % expr7 .. number modulo *expr-%* +expr7 * expr7 .. Number multiplication *expr-star* +expr7 / expr7 .. Number division *expr-/* +expr7 % expr7 .. Number modulo *expr-%* For all, except ".", Strings are converted to Numbers. +For bitwise operators see |and()|, |or()| and |xor()|. Note the difference between "+" and ".": "123" + "456" = 579 @@ -1291,6 +1292,7 @@ *v:char* *char-variable* v:char Argument for evaluating 'formatexpr' and used for the typed character when using in an abbreviation |:map-|. + It is also used by the |InsertPreChar| event. *v:charconvert_from* *charconvert_from-variable* v:charconvert_from @@ -1657,6 +1659,15 @@ *v:warningmsg* *warningmsg-variable* v:warningmsg Last given warning message. It's allowed to set this variable. + *v:windowid* *windowid-variable* +v:windowid When any X11 based GUI is running or when running in a + terminal and Vim connects to the X server (|-X|) this will be + set to the window ID. + When an MS-Windows GUI is running this will be set to the + window handle. + Otherwise the value is zero. + Note: for windows inside Vim use |winnr()|. + ============================================================================== 4. Builtin Functions *functions* @@ -1669,6 +1680,7 @@ abs( {expr}) Float or Number absolute value of {expr} acos( {expr}) Float arc cosine of {expr} add( {list}, {item}) List append {item} to |List| {list} +and( {expr}, {expr}) Number bitwise AND append( {lnum}, {string}) Number append {string} below line {lnum} append( {lnum}, {list}) Number append lines {list} below line {lnum} argc() Number number of files in the argument list @@ -1726,7 +1738,8 @@ extend( {expr1}, {expr2} [, {expr3}]) List/Dict insert items of {expr2} into {expr1} exp( {expr}) Float exponential of {expr} -expand( {expr} [, {flag}]) String expand special keywords in {expr} +expand( {expr} [, {nosuf} [, {list}]]) + any expand special keywords in {expr} feedkeys( {string} [, {mode}]) Number add key sequence to typeahead buffer filereadable( {file}) Number TRUE if {file} is a readable file filewritable( {file}) Number TRUE if {file} is a writable file @@ -1780,7 +1793,8 @@ getwinposx() Number X coord in pixels of GUI Vim window getwinposy() Number Y coord in pixels of GUI Vim window getwinvar( {nr}, {varname}) any variable {varname} in window {nr} -glob( {expr} [, {flag}]) String expand file wildcards in {expr} +glob( {expr} [, {nosuf} [, {list}]]) + any expand file wildcards in {expr} globpath( {path}, {expr} [, {flag}]) String do glob({expr}) for all dirs in {path} has( {feature}) Number TRUE if feature {feature} supported @@ -1807,6 +1821,7 @@ inputsave() Number save and clear typeahead inputsecret( {prompt} [, {text}]) String like input() but hiding the text insert( {list}, {item} [, {idx}]) List insert {item} in {list} [before {idx}] +invert( {expr}) Number bitwise invert isdirectory( {directory}) Number TRUE if {directory} is a directory islocked( {expr}) Number TRUE if {expr} is locked items( {dict}) List key-value pairs in {dict} @@ -1821,9 +1836,11 @@ localtime() Number current time log( {expr}) Float natural logarithm (base e) of {expr} log10( {expr}) Float logarithm of Float {expr} to base 10 +luaeval( {expr}[, {expr}]) any evaluate |Lua| expression map( {expr}, {string}) List/Dict change each item in {expr} to {expr} -maparg( {name}[, {mode} [, {abbr}]]) - String rhs of mapping {name} in mode {mode} +maparg( {name}[, {mode} [, {abbr} [, {dict}]]]) + String or Dict + rhs of mapping {name} in mode {mode} mapcheck( {name}[, {mode} [, {abbr}]]) String check for mappings matching {name} match( {expr}, {pat}[, {start}[, {count}]]) @@ -1846,11 +1863,14 @@ mzeval( {expr}) any evaluate |MzScheme| expression nextnonblank( {lnum}) Number line nr of non-blank line >= {lnum} nr2char( {expr}) String single char with ASCII value {expr} +or( {expr}, {expr}) Number bitwise OR pathshorten( {expr}) String shorten directory names in a path pow( {x}, {y}) Float {x} to the power of {y} prevnonblank( {lnum}) Number line nr of non-blank line <= {lnum} printf( {fmt}, {expr1}...) String format text pumvisible() Number whether popup menu is visible +pyeval( {expr}) any evaluate |Python| expression +py3eval( {expr}) any evaluate |python3| expression range( {expr} [, {max} [, {stride}]]) List items from {expr} to {max} readfile( {fname} [, {binary} [, {max}]]) @@ -1904,7 +1924,8 @@ simplify( {filename}) String simplify filename as much as possible sin( {expr}) Float sine of {expr} sinh( {expr}) Float hyperbolic sine of {expr} -sort( {list} [, {func}]) List sort {list}, using {func} to compare +sort( {list} [, {func} [, {dict}]]) + List sort {list}, using {func} to compare soundfold( {word}) String sound-fold {word} spellbadword() String badly spelled word at cursor spellsuggest( {word} [, {max} [, {capital}]]) @@ -1967,6 +1988,7 @@ winwidth( {nr}) Number width of window {nr} writefile( {list}, {fname} [, {binary}]) Number write list of lines to file {fname} +xor( {expr}, {expr}) Number bitwise XOR abs({expr}) *abs()* Return the absolute value of {expr}. When {expr} evaluates to @@ -2006,6 +2028,13 @@ Use |insert()| to add an item at another position. +and({expr}, {expr}) *and()* + Bitwise AND on the two arguments. The arguments are converted + to a number. A List, Dict or Float argument causes an error. + Example: > + :let flag = and(bits, 0x80) + + append({lnum}, {expr}) *append()* When {expr} is a |List|: Append each item of the |List| as a text line below line {lnum} in the current buffer. @@ -2708,13 +2737,15 @@ {only available when compiled with the |+float| feature} -expand({expr} [, {flag}]) *expand()* +expand({expr} [, {nosuf} [, {list}]]) *expand()* Expand wildcards and the following special keywords in {expr}. - The result is a String. + 'wildignorecase' applies. - When there are several matches, they are separated by - characters. [Note: in version 5.0 a space was used, which - caused problems when a file name contains a space] + If {list} is given and it is non-zero, a List will be returned. + Otherwise the result is a String and when there are several + matches, they are separated by characters. [Note: in + version 5.0 a space was used, which caused problems when a + file name contains a space] If the expansion fails, the result is an empty string. A name for a non-existing file is not included. @@ -2731,6 +2762,7 @@ autocmd buffer number (as a String!) autocmd matched name sourced script file name + sourced script file line number word under the cursor WORD under the cursor the {clientid} of the last received @@ -2767,10 +2799,10 @@ When {expr} does not start with '%', '#' or '<', it is expanded like a file name is expanded on the command line. 'suffixes' and 'wildignore' are used, unless the optional - {flag} argument is given and it is non-zero. Names for - non-existing files are included. The "**" item can be used to - search in a directory tree. For example, to find all "README" - files in the current directory and below: > + {nosuf} argument is given and it is non-zero. + Names for non-existing files are included. The "**" item can + be used to search in a directory tree. For example, to find + all "README" files in the current directory and below: > :echo expand("**/README") < Expand() can also be used to expand variables and environment @@ -3414,17 +3446,23 @@ :let list_is_on = getwinvar(2, '&list') :echo "myvar = " . getwinvar(1, 'myvar') < -glob({expr} [, {flag}]) *glob()* +glob({expr} [, {nosuf} [, {list}]]) *glob()* Expand the file wildcards in {expr}. See |wildcards| for the use of special characters. - The result is a String. - When there are several matches, they are separated by - characters. - Unless the optional {flag} argument is given and is non-zero, + + Unless the optional {nosuf} argument is given and is non-zero, the 'suffixes' and 'wildignore' options apply: Names matching one of the patterns in 'wildignore' will be skipped and 'suffixes' affect the ordering of matches. - If the expansion fails, the result is an empty string. + 'wildignorecase' always applies. + + When {list} is present and it is non-zero the result is a List + with all matching files. The advantage of using a List is, + you also get filenames containing newlines correctly. + Otherwise the result is a String and when there are several + matches, they are separated by characters. + + If the expansion fails, the result is an empty String or List. A name for a non-existing file is not included. For most systems backticks can be used to get files names from @@ -3759,6 +3797,11 @@ Note that when {item} is a |List| it is inserted as a single item. Use |extend()| to concatenate |Lists|. +invert({expr}) *invert()* + Bitwise invert. The argument is converted to a number. A + List, Dict or Float argument causes an error. Example: > + :let bits = invert(bits) + isdirectory({directory}) *isdirectory()* The result is a Number, which is non-zero when a directory with the name {directory} exists. If {directory} doesn't @@ -3941,6 +3984,20 @@ < -2.0 {only available when compiled with the |+float| feature} +luaeval({expr}[, {expr}]) *luaeval()* + Evaluate Lua expression {expr} and return its result converted + to Vim data structures. Second {expr} may hold additional + argument accessible as _A inside first {expr}. + Strings are returned as they are. + Boolean objects are converted to numbers. + Numbers are converted to |Float| values if vim was compiled + with |+float| and to numbers otherwise. + Dictionaries and lists obtained by vim.eval() are returned + as-is. + Other objects are returned as zero without any errors. + See |lua-luaeval| for more details. + {only available when compiled with the |+lua| feature} + map({expr}, {string}) *map()* {expr} must be a |List| or a |Dictionary|. Replace each item in {expr} with the result of evaluating @@ -3966,23 +4023,51 @@ further items in {expr} are processed. -maparg({name}[, {mode} [, {abbr}]]) *maparg()* - Return the rhs of mapping {name} in mode {mode}. When there - is no mapping for {name}, an empty String is returned. +maparg({name}[, {mode} [, {abbr} [, {dict}]]]) *maparg()* + When {dict} is omitted or zero: Return the rhs of mapping + {name} in mode {mode}. The returned String has special + characters translated like in the output of the ":map" command + listing. + + When there is no mapping for {name}, an empty String is + returned. + + The {name} can have special key names, like in the ":map" + command. + {mode} can be one of these strings: "n" Normal - "v" Visual + "v" Visual (including Select) "o" Operator-pending "i" Insert "c" Cmd-line + "s" Select + "x" Visual "l" langmap |language-mapping| "" Normal, Visual and Operator-pending When {mode} is omitted, the modes for "" are used. + When {abbr} is there and it is non-zero use abbreviations instead of mappings. - The {name} can have special key names, like in the ":map" - command. The returned String has special characters - translated like in the output of the ":map" command listing. + + When {dict} is there and it is non-zero return a dictionary + containing all the information of the mapping with the + following items: + "lhs" The {lhs} of the mapping. + "rhs" The {rhs} of the mapping as typed. + "silent" 1 for a |:map-silent| mapping, else 0. + "noremap" 1 if the {rhs} of the mapping is remappable. + "expr" 1 for an expression mapping (|:map-|). + "buffer" 1 for a buffer local mapping (|:map-local|). + "mode" Modes for which the mapping is defined. In + addition to the modes mentioned above, these + characters will be used: + " " Normal, Visual and Operator-pending + "!" Insert and Commandline mode + (|mapmpde-ic|) + "sid" the Script local ID, used for mappings + (||) + The mappings local to the current buffer are checked first, then the global mappings. This function can be used to map a key even when it's already @@ -4295,6 +4380,13 @@ call setpos('.', save_cursor) < Also see |setpos()|. +or({expr}, {expr}) *or()* + Bitwise OR on the two arguments. The arguments are converted + to a number. A List, Dict or Float argument causes an error. + Example: > + :let bits = or(bits, 0x80) + + pathshorten({expr}) *pathshorten()* Shorten directory names in the path {expr} and return the result. The tail, the file name, is kept as-is. The other @@ -4500,6 +4592,29 @@ This can be used to avoid some things that would remove the popup menu. + *E860* *E861* +py3eval({expr}) *py3eval()* + Evaluate Python expression {expr} and return its result + converted to Vim data structures. + Numbers and strings are returned as they are (strings are + copied though, unicode strings are additionally converted to + 'encoding'). + Lists are represented as Vim |List| type. + Dictionaries are represented as Vim |Dictionary| type with + keys converted to strings. + {only available when compiled with the |+python3| feature} + + *E858* *E859* +pyeval({expr}) *pyeval()* + Evaluate Python expression {expr} and return its result + converted to Vim data structures. + Numbers and strings are returned as they are (strings are + copied though). + Lists are represented as Vim |List| type. + Dictionaries are represented as Vim |Dictionary| type with + keys converted to strings. + {only available when compiled with the |+python| feature} + *E726* *E727* range({expr} [, {max} [, {stride}]]) *range()* Returns a |List| with Numbers: @@ -4733,6 +4848,10 @@ Search for regexp pattern {pattern}. The search starts at the cursor position (you can use |cursor()| to set it). + If there is no match a 0 is returned and the cursor doesn't + move. No error message is given. + When a match has been found its line number is returned. + {flags} is a String, which can contain these character flags: 'b' search backward instead of forward 'c' accept a match at the cursor position @@ -5228,7 +5347,7 @@ {only available when compiled with the |+float| feature} -sort({list} [, {func}]) *sort()* *E702* +sort({list} [, {func} [, {dict}]]) *sort()* *E702* Sort the items in {list} in-place. Returns {list}. If you want a list to remain unmodified make a copy first: > :let sortedlist = sort(copy(mylist)) @@ -5236,6 +5355,8 @@ Numbers sort after Strings, |Lists| after Numbers. For sorting text in the current buffer use |:sort|. When {func} is given and it is one then case is ignored. + {dict} is for functions with the "dict" attribute. It will be + used to set the local variable "self". |Dictionary-function| When {func} is a |Funcref| or a function name, this function is called to compare items. The function is invoked with two items as argument and must return zero if they are equal, 1 or @@ -6056,7 +6177,15 @@ To copy a file byte for byte: > :let fl = readfile("foo", "b") :call writefile(fl, "foocopy", "b") -< + + +xor({expr}, {expr}) *xor()* + Bitwise XOR on the two arguments. The arguments are converted + to a number. A List, Dict or Float argument causes an error. + Example: > + :let bits = xor(bits, 0x80) + + *feature-list* There are three types of features: diff -Naur vim73.orig/runtime/doc/eval.txt.orig vim73/runtime/doc/eval.txt.orig --- vim73.orig/runtime/doc/eval.txt.orig 1970-01-01 00:00:00.000000000 +0000 +++ vim73/runtime/doc/eval.txt.orig 2012-07-20 20:31:11.084306643 +0000 @@ -0,0 +1,8362 @@ +*eval.txt* For Vim version 7.3. Last change: 2010 Aug 15 + + + VIM REFERENCE MANUAL by Bram Moolenaar + + +Expression evaluation *expression* *expr* *E15* *eval* + +Using expressions is introduced in chapter 41 of the user manual |usr_41.txt|. + +Note: Expression evaluation can be disabled at compile time. If this has been +done, the features in this document are not available. See |+eval| and +|no-eval-feature|. + +1. Variables |variables| + 1.1 Variable types + 1.2 Function references |Funcref| + 1.3 Lists |Lists| + 1.4 Dictionaries |Dictionaries| + 1.5 More about variables |more-variables| +2. Expression syntax |expression-syntax| +3. Internal variable |internal-variables| +4. Builtin Functions |functions| +5. Defining functions |user-functions| +6. Curly braces names |curly-braces-names| +7. Commands |expression-commands| +8. Exception handling |exception-handling| +9. Examples |eval-examples| +10. No +eval feature |no-eval-feature| +11. The sandbox |eval-sandbox| +12. Textlock |textlock| + +{Vi does not have any of these commands} + +============================================================================== +1. Variables *variables* + +1.1 Variable types ~ + *E712* +There are six types of variables: + +Number A 32 bit signed number. |expr-number| *Number* + Examples: -123 0x10 0177 + +Float A floating point number. |floating-point-format| *Float* + {only when compiled with the |+float| feature} + Examples: 123.456 1.15e-6 -1.1e3 + +String A NUL terminated string of 8-bit unsigned characters (bytes). + |expr-string| Examples: "ab\txx\"--" 'x-z''a,c' + +Funcref A reference to a function |Funcref|. + Example: function("strlen") + +List An ordered sequence of items |List|. + Example: [1, 2, ['a', 'b']] + +Dictionary An associative, unordered array: Each entry has a key and a + value. |Dictionary| + Example: {'blue': "#0000ff", 'red': "#ff0000"} + +The Number and String types are converted automatically, depending on how they +are used. + +Conversion from a Number to a String is by making the ASCII representation of +the Number. Examples: > + Number 123 --> String "123" + Number 0 --> String "0" + Number -1 --> String "-1" + *octal* +Conversion from a String to a Number is done by converting the first digits +to a number. Hexadecimal "0xf9" and Octal "017" numbers are recognized. If +the String doesn't start with digits, the result is zero. Examples: > + String "456" --> Number 456 + String "6bar" --> Number 6 + String "foo" --> Number 0 + String "0xf1" --> Number 241 + String "0100" --> Number 64 + String "-8" --> Number -8 + String "+8" --> Number 0 + +To force conversion from String to Number, add zero to it: > + :echo "0100" + 0 +< 64 ~ + +To avoid a leading zero to cause octal conversion, or for using a different +base, use |str2nr()|. + +For boolean operators Numbers are used. Zero is FALSE, non-zero is TRUE. + +Note that in the command > + :if "foo" +"foo" is converted to 0, which means FALSE. To test for a non-empty string, +use strlen(): > + :if strlen("foo") +< *E745* *E728* *E703* *E729* *E730* *E731* +List, Dictionary and Funcref types are not automatically converted. + + *E805* *E806* *E808* +When mixing Number and Float the Number is converted to Float. Otherwise +there is no automatic conversion of Float. You can use str2float() for String +to Float, printf() for Float to String and float2nr() for Float to Number. + + *E706* *sticky-type-checking* +You will get an error if you try to change the type of a variable. You need +to |:unlet| it first to avoid this error. String and Number are considered +equivalent though, as well are Float and Number. Consider this sequence of +commands: > + :let l = "string" + :let l = 44 " changes type from String to Number + :let l = [1, 2, 3] " error! l is still a Number + :let l = 4.4 " changes type from Number to Float + :let l = "string" " error! + + +1.2 Function references ~ + *Funcref* *E695* *E718* +A Funcref variable is obtained with the |function()| function. It can be used +in an expression in the place of a function name, before the parenthesis +around the arguments, to invoke the function it refers to. Example: > + + :let Fn = function("MyFunc") + :echo Fn() +< *E704* *E705* *E707* +A Funcref variable must start with a capital, "s:", "w:", "t:" or "b:". You +cannot have both a Funcref variable and a function with the same name. + +A special case is defining a function and directly assigning its Funcref to a +Dictionary entry. Example: > + :function dict.init() dict + : let self.val = 0 + :endfunction + +The key of the Dictionary can start with a lower case letter. The actual +function name is not used here. Also see |numbered-function|. + +A Funcref can also be used with the |:call| command: > + :call Fn() + :call dict.init() + +The name of the referenced function can be obtained with |string()|. > + :let func = string(Fn) + +You can use |call()| to invoke a Funcref and use a list variable for the +arguments: > + :let r = call(Fn, mylist) + + +1.3 Lists ~ + *List* *Lists* *E686* +A List is an ordered sequence of items. An item can be of any type. Items +can be accessed by their index number. Items can be added and removed at any +position in the sequence. + + +List creation ~ + *E696* *E697* +A List is created with a comma separated list of items in square brackets. +Examples: > + :let mylist = [1, two, 3, "four"] + :let emptylist = [] + +An item can be any expression. Using a List for an item creates a +List of Lists: > + :let nestlist = [[11, 12], [21, 22], [31, 32]] + +An extra comma after the last item is ignored. + + +List index ~ + *list-index* *E684* +An item in the List can be accessed by putting the index in square brackets +after the List. Indexes are zero-based, thus the first item has index zero. > + :let item = mylist[0] " get the first item: 1 + :let item = mylist[2] " get the third item: 3 + +When the resulting item is a list this can be repeated: > + :let item = nestlist[0][1] " get the first list, second item: 12 +< +A negative index is counted from the end. Index -1 refers to the last item in +the List, -2 to the last but one item, etc. > + :let last = mylist[-1] " get the last item: "four" + +To avoid an error for an invalid index use the |get()| function. When an item +is not available it returns zero or the default value you specify: > + :echo get(mylist, idx) + :echo get(mylist, idx, "NONE") + + +List concatenation ~ + +Two lists can be concatenated with the "+" operator: > + :let longlist = mylist + [5, 6] + :let mylist += [7, 8] + +To prepend or append an item turn the item into a list by putting [] around +it. To change a list in-place see |list-modification| below. + + +Sublist ~ + +A part of the List can be obtained by specifying the first and last index, +separated by a colon in square brackets: > + :let shortlist = mylist[2:-1] " get List [3, "four"] + +Omitting the first index is similar to zero. Omitting the last index is +similar to -1. > + :let endlist = mylist[2:] " from item 2 to the end: [3, "four"] + :let shortlist = mylist[2:2] " List with one item: [3] + :let otherlist = mylist[:] " make a copy of the List + +If the first index is beyond the last item of the List or the second item is +before the first item, the result is an empty list. There is no error +message. + +If the second index is equal to or greater than the length of the list the +length minus one is used: > + :let mylist = [0, 1, 2, 3] + :echo mylist[2:8] " result: [2, 3] + +NOTE: mylist[s:e] means using the variable "s:e" as index. Watch out for +using a single letter variable before the ":". Insert a space when needed: +mylist[s : e]. + + +List identity ~ + *list-identity* +When variable "aa" is a list and you assign it to another variable "bb", both +variables refer to the same list. Thus changing the list "aa" will also +change "bb": > + :let aa = [1, 2, 3] + :let bb = aa + :call add(aa, 4) + :echo bb +< [1, 2, 3, 4] + +Making a copy of a list is done with the |copy()| function. Using [:] also +works, as explained above. This creates a shallow copy of the list: Changing +a list item in the list will also change the item in the copied list: > + :let aa = [[1, 'a'], 2, 3] + :let bb = copy(aa) + :call add(aa, 4) + :let aa[0][1] = 'aaa' + :echo aa +< [[1, aaa], 2, 3, 4] > + :echo bb +< [[1, aaa], 2, 3] + +To make a completely independent list use |deepcopy()|. This also makes a +copy of the values in the list, recursively. Up to a hundred levels deep. + +The operator "is" can be used to check if two variables refer to the same +List. "isnot" does the opposite. In contrast "==" compares if two lists have +the same value. > + :let alist = [1, 2, 3] + :let blist = [1, 2, 3] + :echo alist is blist +< 0 > + :echo alist == blist +< 1 + +Note about comparing lists: Two lists are considered equal if they have the +same length and all items compare equal, as with using "==". There is one +exception: When comparing a number with a string they are considered +different. There is no automatic type conversion, as with using "==" on +variables. Example: > + echo 4 == "4" +< 1 > + echo [4] == ["4"] +< 0 + +Thus comparing Lists is more strict than comparing numbers and strings. You +can compare simple values this way too by putting them in a list: > + + :let a = 5 + :let b = "5" + :echo a == b +< 1 > + :echo [a] == [b] +< 0 + + +List unpack ~ + +To unpack the items in a list to individual variables, put the variables in +square brackets, like list items: > + :let [var1, var2] = mylist + +When the number of variables does not match the number of items in the list +this produces an error. To handle any extra items from the list append ";" +and a variable name: > + :let [var1, var2; rest] = mylist + +This works like: > + :let var1 = mylist[0] + :let var2 = mylist[1] + :let rest = mylist[2:] + +Except that there is no error if there are only two items. "rest" will be an +empty list then. + + +List modification ~ + *list-modification* +To change a specific item of a list use |:let| this way: > + :let list[4] = "four" + :let listlist[0][3] = item + +To change part of a list you can specify the first and last item to be +modified. The value must at least have the number of items in the range: > + :let list[3:5] = [3, 4, 5] + +Adding and removing items from a list is done with functions. Here are a few +examples: > + :call insert(list, 'a') " prepend item 'a' + :call insert(list, 'a', 3) " insert item 'a' before list[3] + :call add(list, "new") " append String item + :call add(list, [1, 2]) " append a List as one new item + :call extend(list, [1, 2]) " extend the list with two more items + :let i = remove(list, 3) " remove item 3 + :unlet list[3] " idem + :let l = remove(list, 3, -1) " remove items 3 to last item + :unlet list[3 : ] " idem + :call filter(list, 'v:val !~ "x"') " remove items with an 'x' + +Changing the order of items in a list: > + :call sort(list) " sort a list alphabetically + :call reverse(list) " reverse the order of items + + +For loop ~ + +The |:for| loop executes commands for each item in a list. A variable is set +to each item in the list in sequence. Example: > + :for item in mylist + : call Doit(item) + :endfor + +This works like: > + :let index = 0 + :while index < len(mylist) + : let item = mylist[index] + : :call Doit(item) + : let index = index + 1 + :endwhile + +Note that all items in the list should be of the same type, otherwise this +results in error |E706|. To avoid this |:unlet| the variable at the end of +the loop. + +If all you want to do is modify each item in the list then the |map()| +function will be a simpler method than a for loop. + +Just like the |:let| command, |:for| also accepts a list of variables. This +requires the argument to be a list of lists. > + :for [lnum, col] in [[1, 3], [2, 8], [3, 0]] + : call Doit(lnum, col) + :endfor + +This works like a |:let| command is done for each list item. Again, the types +must remain the same to avoid an error. + +It is also possible to put remaining items in a List variable: > + :for [i, j; rest] in listlist + : call Doit(i, j) + : if !empty(rest) + : echo "remainder: " . string(rest) + : endif + :endfor + + +List functions ~ + *E714* +Functions that are useful with a List: > + :let r = call(funcname, list) " call a function with an argument list + :if empty(list) " check if list is empty + :let l = len(list) " number of items in list + :let big = max(list) " maximum value in list + :let small = min(list) " minimum value in list + :let xs = count(list, 'x') " count nr of times 'x' appears in list + :let i = index(list, 'x') " index of first 'x' in list + :let lines = getline(1, 10) " get ten text lines from buffer + :call append('$', lines) " append text lines in buffer + :let list = split("a b c") " create list from items in a string + :let string = join(list, ', ') " create string from list items + :let s = string(list) " String representation of list + :call map(list, '">> " . v:val') " prepend ">> " to each item + +Don't forget that a combination of features can make things simple. For +example, to add up all the numbers in a list: > + :exe 'let sum = ' . join(nrlist, '+') + + +1.4 Dictionaries ~ + *Dictionaries* *Dictionary* +A Dictionary is an associative array: Each entry has a key and a value. The +entry can be located with the key. The entries are stored without a specific +ordering. + + +Dictionary creation ~ + *E720* *E721* *E722* *E723* +A Dictionary is created with a comma separated list of entries in curly +braces. Each entry has a key and a value, separated by a colon. Each key can +only appear once. Examples: > + :let mydict = {1: 'one', 2: 'two', 3: 'three'} + :let emptydict = {} +< *E713* *E716* *E717* +A key is always a String. You can use a Number, it will be converted to a +String automatically. Thus the String '4' and the number 4 will find the same +entry. Note that the String '04' and the Number 04 are different, since the +Number will be converted to the String '4'. + +A value can be any expression. Using a Dictionary for a value creates a +nested Dictionary: > + :let nestdict = {1: {11: 'a', 12: 'b'}, 2: {21: 'c'}} + +An extra comma after the last entry is ignored. + + +Accessing entries ~ + +The normal way to access an entry is by putting the key in square brackets: > + :let val = mydict["one"] + :let mydict["four"] = 4 + +You can add new entries to an existing Dictionary this way, unlike Lists. + +For keys that consist entirely of letters, digits and underscore the following +form can be used |expr-entry|: > + :let val = mydict.one + :let mydict.four = 4 + +Since an entry can be any type, also a List and a Dictionary, the indexing and +key lookup can be repeated: > + :echo dict.key[idx].key + + +Dictionary to List conversion ~ + +You may want to loop over the entries in a dictionary. For this you need to +turn the Dictionary into a List and pass it to |:for|. + +Most often you want to loop over the keys, using the |keys()| function: > + :for key in keys(mydict) + : echo key . ': ' . mydict[key] + :endfor + +The List of keys is unsorted. You may want to sort them first: > + :for key in sort(keys(mydict)) + +To loop over the values use the |values()| function: > + :for v in values(mydict) + : echo "value: " . v + :endfor + +If you want both the key and the value use the |items()| function. It returns +a List in which each item is a List with two items, the key and the value: > + :for [key, value] in items(mydict) + : echo key . ': ' . value + :endfor + + +Dictionary identity ~ + *dict-identity* +Just like Lists you need to use |copy()| and |deepcopy()| to make a copy of a +Dictionary. Otherwise, assignment results in referring to the same +Dictionary: > + :let onedict = {'a': 1, 'b': 2} + :let adict = onedict + :let adict['a'] = 11 + :echo onedict['a'] + 11 + +Two Dictionaries compare equal if all the key-value pairs compare equal. For +more info see |list-identity|. + + +Dictionary modification ~ + *dict-modification* +To change an already existing entry of a Dictionary, or to add a new entry, +use |:let| this way: > + :let dict[4] = "four" + :let dict['one'] = item + +Removing an entry from a Dictionary is done with |remove()| or |:unlet|. +Three ways to remove the entry with key "aaa" from dict: > + :let i = remove(dict, 'aaa') + :unlet dict.aaa + :unlet dict['aaa'] + +Merging a Dictionary with another is done with |extend()|: > + :call extend(adict, bdict) +This extends adict with all entries from bdict. Duplicate keys cause entries +in adict to be overwritten. An optional third argument can change this. +Note that the order of entries in a Dictionary is irrelevant, thus don't +expect ":echo adict" to show the items from bdict after the older entries in +adict. + +Weeding out entries from a Dictionary can be done with |filter()|: > + :call filter(dict, 'v:val =~ "x"') +This removes all entries from "dict" with a value not matching 'x'. + + +Dictionary function ~ + *Dictionary-function* *self* *E725* +When a function is defined with the "dict" attribute it can be used in a +special way with a dictionary. Example: > + :function Mylen() dict + : return len(self.data) + :endfunction + :let mydict = {'data': [0, 1, 2, 3], 'len': function("Mylen")} + :echo mydict.len() + +This is like a method in object oriented programming. The entry in the +Dictionary is a |Funcref|. The local variable "self" refers to the dictionary +the function was invoked from. + +It is also possible to add a function without the "dict" attribute as a +Funcref to a Dictionary, but the "self" variable is not available then. + + *numbered-function* *anonymous-function* +To avoid the extra name for the function it can be defined and directly +assigned to a Dictionary in this way: > + :let mydict = {'data': [0, 1, 2, 3]} + :function mydict.len() dict + : return len(self.data) + :endfunction + :echo mydict.len() + +The function will then get a number and the value of dict.len is a |Funcref| +that references this function. The function can only be used through a +|Funcref|. It will automatically be deleted when there is no |Funcref| +remaining that refers to it. + +It is not necessary to use the "dict" attribute for a numbered function. + +If you get an error for a numbered function, you can find out what it is with +a trick. Assuming the function is 42, the command is: > + :function {42} + + +Functions for Dictionaries ~ + *E715* +Functions that can be used with a Dictionary: > + :if has_key(dict, 'foo') " TRUE if dict has entry with key "foo" + :if empty(dict) " TRUE if dict is empty + :let l = len(dict) " number of items in dict + :let big = max(dict) " maximum value in dict + :let small = min(dict) " minimum value in dict + :let xs = count(dict, 'x') " count nr of times 'x' appears in dict + :let s = string(dict) " String representation of dict + :call map(dict, '">> " . v:val') " prepend ">> " to each item + + +1.5 More about variables ~ + *more-variables* +If you need to know the type of a variable or expression, use the |type()| +function. + +When the '!' flag is included in the 'viminfo' option, global variables that +start with an uppercase letter, and don't contain a lowercase letter, are +stored in the viminfo file |viminfo-file|. + +When the 'sessionoptions' option contains "global", global variables that +start with an uppercase letter and contain at least one lowercase letter are +stored in the session file |session-file|. + +variable name can be stored where ~ +my_var_6 not +My_Var_6 session file +MY_VAR_6 viminfo file + + +It's possible to form a variable name with curly braces, see +|curly-braces-names|. + +============================================================================== +2. Expression syntax *expression-syntax* + +Expression syntax summary, from least to most significant: + +|expr1| expr2 ? expr1 : expr1 if-then-else + +|expr2| expr3 || expr3 .. logical OR + +|expr3| expr4 && expr4 .. logical AND + +|expr4| expr5 == expr5 equal + expr5 != expr5 not equal + expr5 > expr5 greater than + expr5 >= expr5 greater than or equal + expr5 < expr5 smaller than + expr5 <= expr5 smaller than or equal + expr5 =~ expr5 regexp matches + expr5 !~ expr5 regexp doesn't match + + expr5 ==? expr5 equal, ignoring case + expr5 ==# expr5 equal, match case + etc. As above, append ? for ignoring case, # for + matching case + + expr5 is expr5 same |List| instance + expr5 isnot expr5 different |List| instance + +|expr5| expr6 + expr6 .. number addition or list concatenation + expr6 - expr6 .. number subtraction + expr6 . expr6 .. string concatenation + +|expr6| expr7 * expr7 .. number multiplication + expr7 / expr7 .. number division + expr7 % expr7 .. number modulo + +|expr7| ! expr7 logical NOT + - expr7 unary minus + + expr7 unary plus + + +|expr8| expr8[expr1] byte of a String or item of a |List| + expr8[expr1 : expr1] substring of a String or sublist of a |List| + expr8.name entry in a |Dictionary| + expr8(expr1, ...) function call with |Funcref| variable + +|expr9| number number constant + "string" string constant, backslash is special + 'string' string constant, ' is doubled + [expr1, ...] |List| + {expr1: expr1, ...} |Dictionary| + &option option value + (expr1) nested expression + variable internal variable + va{ria}ble internal variable with curly braces + $VAR environment variable + @r contents of register 'r' + function(expr1, ...) function call + func{ti}on(expr1, ...) function call with curly braces + + +".." indicates that the operations in this level can be concatenated. +Example: > + &nu || &list && &shell == "csh" + +All expressions within one level are parsed from left to right. + + +expr1 *expr1* *E109* +----- + +expr2 ? expr1 : expr1 + +The expression before the '?' is evaluated to a number. If it evaluates to +non-zero, the result is the value of the expression between the '?' and ':', +otherwise the result is the value of the expression after the ':'. +Example: > + :echo lnum == 1 ? "top" : lnum + +Since the first expression is an "expr2", it cannot contain another ?:. The +other two expressions can, thus allow for recursive use of ?:. +Example: > + :echo lnum == 1 ? "top" : lnum == 1000 ? "last" : lnum + +To keep this readable, using |line-continuation| is suggested: > + :echo lnum == 1 + :\ ? "top" + :\ : lnum == 1000 + :\ ? "last" + :\ : lnum + +You should always put a space before the ':', otherwise it can be mistaken for +use in a variable such as "a:1". + + +expr2 and expr3 *expr2* *expr3* +--------------- + + *expr-barbar* *expr-&&* +The "||" and "&&" operators take one argument on each side. The arguments +are (converted to) Numbers. The result is: + + input output ~ +n1 n2 n1 || n2 n1 && n2 ~ +zero zero zero zero +zero non-zero non-zero zero +non-zero zero non-zero zero +non-zero non-zero non-zero non-zero + +The operators can be concatenated, for example: > + + &nu || &list && &shell == "csh" + +Note that "&&" takes precedence over "||", so this has the meaning of: > + + &nu || (&list && &shell == "csh") + +Once the result is known, the expression "short-circuits", that is, further +arguments are not evaluated. This is like what happens in C. For example: > + + let a = 1 + echo a || b + +This is valid even if there is no variable called "b" because "a" is non-zero, +so the result must be non-zero. Similarly below: > + + echo exists("b") && b == "yes" + +This is valid whether "b" has been defined or not. The second clause will +only be evaluated if "b" has been defined. + + +expr4 *expr4* +----- + +expr5 {cmp} expr5 + +Compare two expr5 expressions, resulting in a 0 if it evaluates to false, or 1 +if it evaluates to true. + + *expr-==* *expr-!=* *expr->* *expr->=* + *expr-<* *expr-<=* *expr-=~* *expr-!~* + *expr-==#* *expr-!=#* *expr->#* *expr->=#* + *expr-<#* *expr-<=#* *expr-=~#* *expr-!~#* + *expr-==?* *expr-!=?* *expr->?* *expr->=?* + *expr- ># >? +greater than or equal >= >=# >=? +smaller than < <# + 1 . 90 + 90.0 +As: > + (1 . 90) + 90.0 +That works, since the String "190" is automatically converted to the Number +190, which can be added to the Float 90.0. However: > + 1 . 90 * 90.0 +Should be read as: > + 1 . (90 * 90.0) +Since '.' has lower precedence than '*'. This does NOT work, since this +attempts to concatenate a Float and a String. + +When dividing a Number by zero the result depends on the value: + 0 / 0 = -0x80000000 (like NaN for Float) + >0 / 0 = 0x7fffffff (like positive infinity) + <0 / 0 = -0x7fffffff (like negative infinity) + (before Vim 7.2 it was always 0x7fffffff) + +When the righthand side of '%' is zero, the result is 0. + +None of these work for |Funcref|s. + +. and % do not work for Float. *E804* + + +expr7 *expr7* +----- +! expr7 logical NOT *expr-!* +- expr7 unary minus *expr-unary--* ++ expr7 unary plus *expr-unary-+* + +For '!' non-zero becomes zero, zero becomes one. +For '-' the sign of the number is changed. +For '+' the number is unchanged. + +A String will be converted to a Number first. + +These three can be repeated and mixed. Examples: + !-1 == 0 + !!8 == 1 + --9 == 9 + + +expr8 *expr8* +----- +expr8[expr1] item of String or |List| *expr-[]* *E111* + +If expr8 is a Number or String this results in a String that contains the +expr1'th single byte from expr8. expr8 is used as a String, expr1 as a +Number. This doesn't recognize multi-byte encodings, see |byteidx()| for +an alternative. + +Index zero gives the first character. This is like it works in C. Careful: +text column numbers start with one! Example, to get the character under the +cursor: > + :let c = getline(".")[col(".") - 1] + +If the length of the String is less than the index, the result is an empty +String. A negative index always results in an empty string (reason: backwards +compatibility). Use [-1:] to get the last byte. + +If expr8 is a |List| then it results the item at index expr1. See |list-index| +for possible index values. If the index is out of range this results in an +error. Example: > + :let item = mylist[-1] " get last item + +Generally, if a |List| index is equal to or higher than the length of the +|List|, or more negative than the length of the |List|, this results in an +error. + + +expr8[expr1a : expr1b] substring or sublist *expr-[:]* + +If expr8 is a Number or String this results in the substring with the bytes +from expr1a to and including expr1b. expr8 is used as a String, expr1a and +expr1b are used as a Number. This doesn't recognize multi-byte encodings, see +|byteidx()| for computing the indexes. + +If expr1a is omitted zero is used. If expr1b is omitted the length of the +string minus one is used. + +A negative number can be used to measure from the end of the string. -1 is +the last character, -2 the last but one, etc. + +If an index goes out of range for the string characters are omitted. If +expr1b is smaller than expr1a the result is an empty string. + +Examples: > + :let c = name[-1:] " last byte of a string + :let c = name[-2:-2] " last but one byte of a string + :let s = line(".")[4:] " from the fifth byte to the end + :let s = s[:-3] " remove last two bytes +< + *sublist* *slice* +If expr8 is a |List| this results in a new |List| with the items indicated by +the indexes expr1a and expr1b. This works like with a String, as explained +just above, except that indexes out of range cause an error. Examples: > + :let l = mylist[:3] " first four items + :let l = mylist[4:4] " List with one item + :let l = mylist[:] " shallow copy of a List + +Using expr8[expr1] or expr8[expr1a : expr1b] on a |Funcref| results in an +error. + + +expr8.name entry in a |Dictionary| *expr-entry* + +If expr8 is a |Dictionary| and it is followed by a dot, then the following +name will be used as a key in the |Dictionary|. This is just like: +expr8[name]. + +The name must consist of alphanumeric characters, just like a variable name, +but it may start with a number. Curly braces cannot be used. + +There must not be white space before or after the dot. + +Examples: > + :let dict = {"one": 1, 2: "two"} + :echo dict.one + :echo dict .2 + +Note that the dot is also used for String concatenation. To avoid confusion +always put spaces around the dot for String concatenation. + + +expr8(expr1, ...) |Funcref| function call + +When expr8 is a |Funcref| type variable, invoke the function it refers to. + + + + *expr9* +number +------ +number number constant *expr-number* + +Decimal, Hexadecimal (starting with 0x or 0X), or Octal (starting with 0). + + *floating-point-format* +Floating point numbers can be written in two forms: + + [-+]{N}.{M} + [-+]{N}.{M}e[-+]{exp} + +{N} and {M} are numbers. Both {N} and {M} must be present and can only +contain digits. +[-+] means there is an optional plus or minus sign. +{exp} is the exponent, power of 10. +Only a decimal point is accepted, not a comma. No matter what the current +locale is. +{only when compiled with the |+float| feature} + +Examples: + 123.456 + +0.0001 + 55.0 + -0.123 + 1.234e03 + 1.0E-6 + -3.1416e+88 + +These are INVALID: + 3. empty {M} + 1e40 missing .{M} + + *float-pi* *float-e* +A few useful values to copy&paste: > + :let pi = 3.14159265359 + :let e = 2.71828182846 + +Rationale: +Before floating point was introduced, the text "123.456" was interpreted as +the two numbers "123" and "456", both converted to a string and concatenated, +resulting in the string "123456". Since this was considered pointless, and we +could not find it intentionally being used in Vim scripts, this backwards +incompatibility was accepted in favor of being able to use the normal notation +for floating point numbers. + + *floating-point-precision* +The precision and range of floating points numbers depends on what "double" +means in the library Vim was compiled with. There is no way to change this at +runtime. + +The default for displaying a |Float| is to use 6 decimal places, like using +printf("%g", f). You can select something else when using the |printf()| +function. Example: > + :echo printf('%.15e', atan(1)) +< 7.853981633974483e-01 + + + +string *expr-string* *E114* +------ +"string" string constant *expr-quote* + +Note that double quotes are used. + +A string constant accepts these special characters: +\... three-digit octal number (e.g., "\316") +\.. two-digit octal number (must be followed by non-digit) +\. one-digit octal number (must be followed by non-digit) +\x.. byte specified with two hex numbers (e.g., "\x1f") +\x. byte specified with one hex number (must be followed by non-hex char) +\X.. same as \x.. +\X. same as \x. +\u.... character specified with up to 4 hex numbers, stored according to the + current value of 'encoding' (e.g., "\u02a4") +\U.... same as \u.... +\b backspace +\e escape +\f formfeed +\n newline +\r return +\t tab +\\ backslash +\" double quote +\ Special key named "xxx". e.g. "\" for CTRL-W. This is for use + in mappings, the 0x80 byte is escaped. Don't use to get a + utf-8 character, use \uxxxx as mentioned above. + +Note that "\xff" is stored as the byte 255, which may be invalid in some +encodings. Use "\u00ff" to store character 255 according to the current value +of 'encoding'. + +Note that "\000" and "\x00" force the end of the string. + + +literal-string *literal-string* *E115* +--------------- +'string' string constant *expr-'* + +Note that single quotes are used. + +This string is taken as it is. No backslashes are removed or have a special +meaning. The only exception is that two quotes stand for one quote. + +Single quoted strings are useful for patterns, so that backslashes do not need +to be doubled. These two commands are equivalent: > + if a =~ "\\s*" + if a =~ '\s*' + + +option *expr-option* *E112* *E113* +------ +&option option value, local value if possible +&g:option global option value +&l:option local option value + +Examples: > + echo "tabstop is " . &tabstop + if &insertmode + +Any option name can be used here. See |options|. When using the local value +and there is no buffer-local or window-local value, the global value is used +anyway. + + +register *expr-register* *@r* +-------- +@r contents of register 'r' + +The result is the contents of the named register, as a single string. +Newlines are inserted where required. To get the contents of the unnamed +register use @" or @@. See |registers| for an explanation of the available +registers. + +When using the '=' register you get the expression itself, not what it +evaluates to. Use |eval()| to evaluate it. + + +nesting *expr-nesting* *E110* +------- +(expr1) nested expression + + +environment variable *expr-env* +-------------------- +$VAR environment variable + +The String value of any environment variable. When it is not defined, the +result is an empty string. + *expr-env-expand* +Note that there is a difference between using $VAR directly and using +expand("$VAR"). Using it directly will only expand environment variables that +are known inside the current Vim session. Using expand() will first try using +the environment variables known inside the current Vim session. If that +fails, a shell will be used to expand the variable. This can be slow, but it +does expand all variables that the shell knows about. Example: > + :echo $version + :echo expand("$version") +The first one probably doesn't echo anything, the second echoes the $version +variable (if your shell supports it). + + +internal variable *expr-variable* +----------------- +variable internal variable +See below |internal-variables|. + + +function call *expr-function* *E116* *E118* *E119* *E120* +------------- +function(expr1, ...) function call +See below |functions|. + + +============================================================================== +3. Internal variable *internal-variables* *E121* + *E461* +An internal variable name can be made up of letters, digits and '_'. But it +cannot start with a digit. It's also possible to use curly braces, see +|curly-braces-names|. + +An internal variable is created with the ":let" command |:let|. +An internal variable is explicitly destroyed with the ":unlet" command +|:unlet|. +Using a name that is not an internal variable or refers to a variable that has +been destroyed results in an error. + +There are several name spaces for variables. Which one is to be used is +specified by what is prepended: + + (nothing) In a function: local to a function; otherwise: global +|buffer-variable| b: Local to the current buffer. +|window-variable| w: Local to the current window. +|tabpage-variable| t: Local to the current tab page. +|global-variable| g: Global. +|local-variable| l: Local to a function. +|script-variable| s: Local to a |:source|'ed Vim script. +|function-argument| a: Function argument (only inside a function). +|vim-variable| v: Global, predefined by Vim. + +The scope name by itself can be used as a |Dictionary|. For example, to +delete all script-local variables: > + :for k in keys(s:) + : unlet s:[k] + :endfor +< + *buffer-variable* *b:var* +A variable name that is preceded with "b:" is local to the current buffer. +Thus you can have several "b:foo" variables, one for each buffer. +This kind of variable is deleted when the buffer is wiped out or deleted with +|:bdelete|. + +One local buffer variable is predefined: + *b:changedtick-variable* *changetick* +b:changedtick The total number of changes to the current buffer. It is + incremented for each change. An undo command is also a change + in this case. This can be used to perform an action only when + the buffer has changed. Example: > + :if my_changedtick != b:changedtick + : let my_changedtick = b:changedtick + : call My_Update() + :endif +< + *window-variable* *w:var* +A variable name that is preceded with "w:" is local to the current window. It +is deleted when the window is closed. + + *tabpage-variable* *t:var* +A variable name that is preceded with "t:" is local to the current tab page, +It is deleted when the tab page is closed. {not available when compiled +without the |+windows| feature} + + *global-variable* *g:var* +Inside functions global variables are accessed with "g:". Omitting this will +access a variable local to a function. But "g:" can also be used in any other +place if you like. + + *local-variable* *l:var* +Inside functions local variables are accessed without prepending anything. +But you can also prepend "l:" if you like. However, without prepending "l:" +you may run into reserved variable names. For example "count". By itself it +refers to "v:count". Using "l:count" you can have a local variable with the +same name. + + *script-variable* *s:var* +In a Vim script variables starting with "s:" can be used. They cannot be +accessed from outside of the scripts, thus are local to the script. + +They can be used in: +- commands executed while the script is sourced +- functions defined in the script +- autocommands defined in the script +- functions and autocommands defined in functions and autocommands which were + defined in the script (recursively) +- user defined commands defined in the script +Thus not in: +- other scripts sourced from this one +- mappings +- menus +- etc. + +Script variables can be used to avoid conflicts with global variable names. +Take this example: > + + let s:counter = 0 + function MyCounter() + let s:counter = s:counter + 1 + echo s:counter + endfunction + command Tick call MyCounter() + +You can now invoke "Tick" from any script, and the "s:counter" variable in +that script will not be changed, only the "s:counter" in the script where +"Tick" was defined is used. + +Another example that does the same: > + + let s:counter = 0 + command Tick let s:counter = s:counter + 1 | echo s:counter + +When calling a function and invoking a user-defined command, the context for +script variables is set to the script where the function or command was +defined. + +The script variables are also available when a function is defined inside a +function that is defined in a script. Example: > + + let s:counter = 0 + function StartCounting(incr) + if a:incr + function MyCounter() + let s:counter = s:counter + 1 + endfunction + else + function MyCounter() + let s:counter = s:counter - 1 + endfunction + endif + endfunction + +This defines the MyCounter() function either for counting up or counting down +when calling StartCounting(). It doesn't matter from where StartCounting() is +called, the s:counter variable will be accessible in MyCounter(). + +When the same script is sourced again it will use the same script variables. +They will remain valid as long as Vim is running. This can be used to +maintain a counter: > + + if !exists("s:counter") + let s:counter = 1 + echo "script executed for the first time" + else + let s:counter = s:counter + 1 + echo "script executed " . s:counter . " times now" + endif + +Note that this means that filetype plugins don't get a different set of script +variables for each buffer. Use local buffer variables instead |b:var|. + + +Predefined Vim variables: *vim-variable* *v:var* + + *v:beval_col* *beval_col-variable* +v:beval_col The number of the column, over which the mouse pointer is. + This is the byte index in the |v:beval_lnum| line. + Only valid while evaluating the 'balloonexpr' option. + + *v:beval_bufnr* *beval_bufnr-variable* +v:beval_bufnr The number of the buffer, over which the mouse pointer is. Only + valid while evaluating the 'balloonexpr' option. + + *v:beval_lnum* *beval_lnum-variable* +v:beval_lnum The number of the line, over which the mouse pointer is. Only + valid while evaluating the 'balloonexpr' option. + + *v:beval_text* *beval_text-variable* +v:beval_text The text under or after the mouse pointer. Usually a word as + it is useful for debugging a C program. 'iskeyword' applies, + but a dot and "->" before the position is included. When on a + ']' the text before it is used, including the matching '[' and + word before it. When on a Visual area within one line the + highlighted text is used. + Only valid while evaluating the 'balloonexpr' option. + + *v:beval_winnr* *beval_winnr-variable* +v:beval_winnr The number of the window, over which the mouse pointer is. Only + valid while evaluating the 'balloonexpr' option. + + *v:char* *char-variable* +v:char Argument for evaluating 'formatexpr' and used for the typed + character when using in an abbreviation |:map-|. + It is also used by the |InsertPreChar| event. + + *v:charconvert_from* *charconvert_from-variable* +v:charconvert_from + The name of the character encoding of a file to be converted. + Only valid while evaluating the 'charconvert' option. + + *v:charconvert_to* *charconvert_to-variable* +v:charconvert_to + The name of the character encoding of a file after conversion. + Only valid while evaluating the 'charconvert' option. + + *v:cmdarg* *cmdarg-variable* +v:cmdarg This variable is used for two purposes: + 1. The extra arguments given to a file read/write command. + Currently these are "++enc=" and "++ff=". This variable is + set before an autocommand event for a file read/write + command is triggered. There is a leading space to make it + possible to append this variable directly after the + read/write command. Note: The "+cmd" argument isn't + included here, because it will be executed anyway. + 2. When printing a PostScript file with ":hardcopy" this is + the argument for the ":hardcopy" command. This can be used + in 'printexpr'. + + *v:cmdbang* *cmdbang-variable* +v:cmdbang Set like v:cmdarg for a file read/write command. When a "!" + was used the value is 1, otherwise it is 0. Note that this + can only be used in autocommands. For user commands || + can be used. + + *v:count* *count-variable* +v:count The count given for the last Normal mode command. Can be used + to get the count before a mapping. Read-only. Example: > + :map _x :echo "the count is " . v:count +< Note: The is required to remove the line range that you + get when typing ':' after a count. + When there are two counts, as in "3d2w", they are multiplied, + just like what happens in the command, "d6w" for the example. + Also used for evaluating the 'formatexpr' option. + "count" also works, for backwards compatibility. + + *v:count1* *count1-variable* +v:count1 Just like "v:count", but defaults to one when no count is + used. + + *v:ctype* *ctype-variable* +v:ctype The current locale setting for characters of the runtime + environment. This allows Vim scripts to be aware of the + current locale encoding. Technical: it's the value of + LC_CTYPE. When not using a locale the value is "C". + This variable can not be set directly, use the |:language| + command. + See |multi-lang|. + + *v:dying* *dying-variable* +v:dying Normally zero. When a deadly signal is caught it's set to + one. When multiple signals are caught the number increases. + Can be used in an autocommand to check if Vim didn't + terminate normally. {only works on Unix} + Example: > + :au VimLeave * if v:dying | echo "\nAAAAaaaarrrggghhhh!!!\n" | endif +< Note: if another deadly signal is caught when v:dying is one, + VimLeave autocommands will not be executed. + + *v:errmsg* *errmsg-variable* +v:errmsg Last given error message. It's allowed to set this variable. + Example: > + :let v:errmsg = "" + :silent! next + :if v:errmsg != "" + : ... handle error +< "errmsg" also works, for backwards compatibility. + + *v:exception* *exception-variable* +v:exception The value of the exception most recently caught and not + finished. See also |v:throwpoint| and |throw-variables|. + Example: > + :try + : throw "oops" + :catch /.*/ + : echo "caught" v:exception + :endtry +< Output: "caught oops". + + *v:fcs_reason* *fcs_reason-variable* +v:fcs_reason The reason why the |FileChangedShell| event was triggered. + Can be used in an autocommand to decide what to do and/or what + to set v:fcs_choice to. Possible values: + deleted file no longer exists + conflict file contents, mode or timestamp was + changed and buffer is modified + changed file contents has changed + mode mode of file changed + time only file timestamp changed + + *v:fcs_choice* *fcs_choice-variable* +v:fcs_choice What should happen after a |FileChangedShell| event was + triggered. Can be used in an autocommand to tell Vim what to + do with the affected buffer: + reload Reload the buffer (does not work if + the file was deleted). + ask Ask the user what to do, as if there + was no autocommand. Except that when + only the timestamp changed nothing + will happen. + Nothing, the autocommand should do + everything that needs to be done. + The default is empty. If another (invalid) value is used then + Vim behaves like it is empty, there is no warning message. + + *v:fname_in* *fname_in-variable* +v:fname_in The name of the input file. Valid while evaluating: + option used for ~ + 'charconvert' file to be converted + 'diffexpr' original file + 'patchexpr' original file + 'printexpr' file to be printed + And set to the swap file name for |SwapExists|. + + *v:fname_out* *fname_out-variable* +v:fname_out The name of the output file. Only valid while + evaluating: + option used for ~ + 'charconvert' resulting converted file (*) + 'diffexpr' output of diff + 'patchexpr' resulting patched file + (*) When doing conversion for a write command (e.g., ":w + file") it will be equal to v:fname_in. When doing conversion + for a read command (e.g., ":e file") it will be a temporary + file and different from v:fname_in. + + *v:fname_new* *fname_new-variable* +v:fname_new The name of the new version of the file. Only valid while + evaluating 'diffexpr'. + + *v:fname_diff* *fname_diff-variable* +v:fname_diff The name of the diff (patch) file. Only valid while + evaluating 'patchexpr'. + + *v:folddashes* *folddashes-variable* +v:folddashes Used for 'foldtext': dashes representing foldlevel of a closed + fold. + Read-only in the |sandbox|. |fold-foldtext| + + *v:foldlevel* *foldlevel-variable* +v:foldlevel Used for 'foldtext': foldlevel of closed fold. + Read-only in the |sandbox|. |fold-foldtext| + + *v:foldend* *foldend-variable* +v:foldend Used for 'foldtext': last line of closed fold. + Read-only in the |sandbox|. |fold-foldtext| + + *v:foldstart* *foldstart-variable* +v:foldstart Used for 'foldtext': first line of closed fold. + Read-only in the |sandbox|. |fold-foldtext| + + *v:insertmode* *insertmode-variable* +v:insertmode Used for the |InsertEnter| and |InsertChange| autocommand + events. Values: + i Insert mode + r Replace mode + v Virtual Replace mode + + *v:key* *key-variable* +v:key Key of the current item of a |Dictionary|. Only valid while + evaluating the expression used with |map()| and |filter()|. + Read-only. + + *v:lang* *lang-variable* +v:lang The current locale setting for messages of the runtime + environment. This allows Vim scripts to be aware of the + current language. Technical: it's the value of LC_MESSAGES. + The value is system dependent. + This variable can not be set directly, use the |:language| + command. + It can be different from |v:ctype| when messages are desired + in a different language than what is used for character + encoding. See |multi-lang|. + + *v:lc_time* *lc_time-variable* +v:lc_time The current locale setting for time messages of the runtime + environment. This allows Vim scripts to be aware of the + current language. Technical: it's the value of LC_TIME. + This variable can not be set directly, use the |:language| + command. See |multi-lang|. + + *v:lnum* *lnum-variable* +v:lnum Line number for the 'foldexpr' |fold-expr|, 'formatexpr' and + 'indentexpr' expressions, tab page number for 'guitablabel' + and 'guitabtooltip'. Only valid while one of these + expressions is being evaluated. Read-only when in the + |sandbox|. + + *v:mouse_win* *mouse_win-variable* +v:mouse_win Window number for a mouse click obtained with |getchar()|. + First window has number 1, like with |winnr()|. The value is + zero when there was no mouse button click. + + *v:mouse_lnum* *mouse_lnum-variable* +v:mouse_lnum Line number for a mouse click obtained with |getchar()|. + This is the text line number, not the screen line number. The + value is zero when there was no mouse button click. + + *v:mouse_col* *mouse_col-variable* +v:mouse_col Column number for a mouse click obtained with |getchar()|. + This is the screen column number, like with |virtcol()|. The + value is zero when there was no mouse button click. + + *v:oldfiles* *oldfiles-variable* +v:oldfiles List of file names that is loaded from the |viminfo| file on + startup. These are the files that Vim remembers marks for. + The length of the List is limited by the ' argument of the + 'viminfo' option (default is 100). + Also see |:oldfiles| and |c_#<|. + The List can be modified, but this has no effect on what is + stored in the |viminfo| file later. If you use values other + than String this will cause trouble. + {only when compiled with the |+viminfo| feature} + + *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 or Operator-pending mode and then + use the count, e.g.: > + :vmap % :call MyFilter(v:prevcount) +< Read-only. + + *v:profiling* *profiling-variable* +v:profiling Normally zero. Set to one after using ":profile start". + See |profiling|. + + *v:progname* *progname-variable* +v:progname Contains the name (with path removed) with which Vim was + invoked. Allows you to do special initialisations for "view", + "evim" etc., or any other name you might symlink to Vim. + Read-only. + + *v:register* *register-variable* +v:register The name of the register supplied to the last normal mode + command. Empty if none were supplied. |getreg()| |setreg()| + + *v:scrollstart* *scrollstart-variable* +v:scrollstart String describing the script or function that caused the + screen to scroll up. It's only set when it is empty, thus the + first reason is remembered. It is set to "Unknown" for a + typed command. + This can be used to find out why your script causes the + hit-enter prompt. + + *v:servername* *servername-variable* +v:servername The resulting registered |x11-clientserver| name if any. + Read-only. + + +v:searchforward *v:searchforward* *searchforward-variable* + Search direction: 1 after a forward search, 0 after a + backward search. It is reset to forward when directly setting + the last search pattern, see |quote/|. + Note that the value is restored when returning from a + function. |function-search-undo|. + Read-write. + + *v:shell_error* *shell_error-variable* +v:shell_error Result of the last shell command. When non-zero, the last + shell command had an error. When zero, there was no problem. + This only works when the shell returns the error code to Vim. + The value -1 is often used when the command could not be + executed. Read-only. + Example: > + :!mv foo bar + :if v:shell_error + : echo 'could not rename "foo" to "bar"!' + :endif +< "shell_error" also works, for backwards compatibility. + + *v:statusmsg* *statusmsg-variable* +v:statusmsg Last given status message. It's allowed to set this variable. + + *v:swapname* *swapname-variable* +v:swapname Only valid when executing |SwapExists| autocommands: Name of + the swap file found. Read-only. + + *v:swapchoice* *swapchoice-variable* +v:swapchoice |SwapExists| autocommands can set this to the selected choice + for handling an existing swap file: + 'o' Open read-only + 'e' Edit anyway + 'r' Recover + 'd' Delete swapfile + 'q' Quit + 'a' Abort + The value should be a single-character string. An empty value + results in the user being asked, as would happen when there is + no SwapExists autocommand. The default is empty. + + *v:swapcommand* *swapcommand-variable* +v:swapcommand Normal mode command to be executed after a file has been + opened. Can be used for a |SwapExists| autocommand to have + another Vim open the file and jump to the right place. For + example, when jumping to a tag the value is ":tag tagname\r". + For ":edit +cmd file" the value is ":cmd\r". + + *v:termresponse* *termresponse-variable* +v:termresponse The escape sequence returned by the terminal for the |t_RV| + termcap entry. It is set when Vim receives an escape sequence + that starts with ESC [ or CSI and ends in a 'c', with only + digits, ';' and '.' in between. + When this option is set, the TermResponse autocommand event is + fired, so that you can react to the response from the + terminal. + The response from a new xterm is: "[ Pp ; Pv ; Pc c". Pp + is the terminal type: 0 for vt100 and 1 for vt220. Pv is the + patch level (since this was introduced in patch 95, it's + always 95 or bigger). Pc is always zero. + {only when compiled with |+termresponse| feature} + + *v:this_session* *this_session-variable* +v:this_session Full filename of the last loaded or saved session file. See + |:mksession|. It is allowed to set this variable. When no + session file has been saved, this variable is empty. + "this_session" also works, for backwards compatibility. + + *v:throwpoint* *throwpoint-variable* +v:throwpoint The point where the exception most recently caught and not + finished was thrown. Not set when commands are typed. See + also |v:exception| and |throw-variables|. + Example: > + :try + : throw "oops" + :catch /.*/ + : echo "Exception from" v:throwpoint + :endtry +< Output: "Exception from test.vim, line 2" + + *v:val* *val-variable* +v:val Value of the current item of a |List| or |Dictionary|. Only + valid while evaluating the expression used with |map()| and + |filter()|. Read-only. + + *v:version* *version-variable* +v:version Version number of Vim: Major version number times 100 plus + minor version number. Version 5.0 is 500. Version 5.1 (5.01) + is 501. Read-only. "version" also works, for backwards + compatibility. + Use |has()| to check if a certain patch was included, e.g.: > + if has("patch123") +< Note that patch numbers are specific to the version, thus both + version 5.0 and 5.1 may have a patch 123, but these are + completely different. + + *v:warningmsg* *warningmsg-variable* +v:warningmsg Last given warning message. It's allowed to set this variable. + + *v:windowid* *windowid-variable* +v:windowid When any X11 based GUI is running or when running in a + terminal and Vim connects to the X server (|-X|) this will be + set to the window ID. + When an MS-Windows GUI is running this will be set to the + window handle. + Otherwise the value is zero. + Note: for windows inside Vim use |winnr()|. + +============================================================================== +4. Builtin Functions *functions* + +See |function-list| for a list grouped by what the function is used for. + +(Use CTRL-] on the function name to jump to the full explanation.) + +USAGE RESULT DESCRIPTION ~ + +abs( {expr}) Float or Number absolute value of {expr} +acos( {expr}) Float arc cosine of {expr} +add( {list}, {item}) List append {item} to |List| {list} +append( {lnum}, {string}) Number append {string} below line {lnum} +append( {lnum}, {list}) Number append lines {list} below line {lnum} +argc() Number number of files in the argument list +argidx() Number current index in the argument list +argv( {nr}) String {nr} entry of the argument list +argv( ) List the argument list +asin( {expr}) Float arc sine of {expr} +atan( {expr}) Float arc tangent of {expr} +atan2( {expr}, {expr}) Float arc tangent of {expr1} / {expr2} +browse( {save}, {title}, {initdir}, {default}) + String put up a file requester +browsedir( {title}, {initdir}) String put up a directory requester +bufexists( {expr}) Number TRUE if buffer {expr} exists +buflisted( {expr}) Number TRUE if buffer {expr} is listed +bufloaded( {expr}) Number TRUE if buffer {expr} is loaded +bufname( {expr}) String Name of the buffer {expr} +bufnr( {expr}) Number Number of the buffer {expr} +bufwinnr( {expr}) Number window number of buffer {expr} +byte2line( {byte}) Number line number at byte count {byte} +byteidx( {expr}, {nr}) Number byte index of {nr}'th char in {expr} +call( {func}, {arglist} [, {dict}]) + any call {func} with arguments {arglist} +ceil( {expr}) Float round {expr} up +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}) none set Insert mode completion +complete_add( {expr}) Number add completion match +complete_check() Number check for key typed during completion +confirm( {msg} [, {choices} [, {default} [, {type}]]]) + Number number of choice picked by user +copy( {expr}) any make a shallow copy of {expr} +cos( {expr}) Float cosine of {expr} +cosh( {expr}) Float hyperbolic cosine of {expr} +count( {list}, {expr} [, {start} [, {ic}]]) + Number count how many {expr} are in {list} +cscope_connection( [{num} , {dbpath} [, {prepend}]]) + Number checks existence of cscope connection +cursor( {lnum}, {col} [, {coladd}]) + Number move cursor to {lnum}, {col}, {coladd} +cursor( {list}) Number move cursor to position in {list} +deepcopy( {expr}) any make a full copy of {expr} +delete( {fname}) Number delete file {fname} +did_filetype() Number TRUE if FileType autocommand event used +diff_filler( {lnum}) Number diff filler lines about {lnum} +diff_hlID( {lnum}, {col}) Number diff highlighting at {lnum}/{col} +empty( {expr}) Number TRUE if {expr} is empty +escape( {string}, {chars}) String escape {chars} in {string} with '\' +eval( {string}) any evaluate {string} into its value +eventhandler( ) Number TRUE if inside an event handler +executable( {expr}) Number 1 if executable {expr} exists +exists( {expr}) Number TRUE if {expr} exists +extend( {expr1}, {expr2} [, {expr3}]) + List/Dict insert items of {expr2} into {expr1} +exp( {expr}) Float exponential of {expr} +expand( {expr} [, {flag}]) String expand special keywords in {expr} +feedkeys( {string} [, {mode}]) Number add key sequence to typeahead buffer +filereadable( {file}) Number TRUE if {file} is a readable file +filewritable( {file}) Number TRUE if {file} is a writable file +filter( {expr}, {string}) List/Dict remove items from {expr} where + {string} is 0 +finddir( {name}[, {path}[, {count}]]) + String find directory {name} in {path} +findfile( {name}[, {path}[, {count}]]) + String find file {name} in {path} +float2nr( {expr}) Number convert Float {expr} to a Number +floor( {expr}) Float round {expr} down +fmod( {expr1}, {expr2}) Float remainder of {expr1} / {expr2} +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 +foldlevel( {lnum}) Number fold level at {lnum} +foldtext( ) String line displayed for closed fold +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( [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}]) + List lines {lnum} to {end} of buffer {expr} +getbufvar( {expr}, {varname}) any variable {varname} in buffer {expr} +getchar( [expr]) Number get one character from the user +getcharmod( ) Number modifiers for the last typed character +getcmdline() String return the current command-line +getcmdpos() Number return cursor position in command-line +getcmdtype() String return the current command-line type +getcwd() String the current working directory +getfperm( {fname}) String file permissions of file {fname} +getfsize( {fname}) Number size in bytes of file {fname} +getfontname( [{name}]) String name of font being used +getftime( {fname}) Number last modification time of file +getftype( {fname}) String description of type of file {fname} +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 +getregtype( [{regname}]) String type of register +gettabvar( {nr}, {varname}) any variable {varname} in tab {nr} +gettabwinvar( {tabnr}, {winnr}, {name}) + any {name} in {winnr} in tab page {tabnr} +getwinposx() Number X coord in pixels of GUI Vim window +getwinposy() Number Y coord in pixels of GUI Vim window +getwinvar( {nr}, {varname}) any variable {varname} in window {nr} +glob( {expr} [, {flag}]) String expand file wildcards in {expr} +globpath( {path}, {expr} [, {flag}]) + String do glob({expr}) for all dirs in {path} +has( {feature}) Number TRUE if feature {feature} supported +has_key( {dict}, {key}) Number TRUE if {dict} has entry {key} +haslocaldir() Number TRUE if current window executed |:lcd| +hasmapto( {what} [, {mode} [, {abbr}]]) + Number TRUE if mapping to {what} exists +histadd( {history},{item}) String add an item to a history +histdel( {history} [, {item}]) String remove an item from a history +histget( {history} [, {index}]) String get the item {index} from a history +histnr( {history}) Number highest index of a history +hlexists( {name}) Number TRUE if highlight group {name} exists +hlID( {name}) Number syntax ID of highlight group {name} +hostname() String name of the machine Vim is running on +iconv( {expr}, {from}, {to}) String convert encoding of {expr} +indent( {lnum}) Number indent of line {lnum} +index( {list}, {expr} [, {start} [, {ic}]]) + Number index in {list} where {expr} appears +input( {prompt} [, {text} [, {completion}]]) + String get input from the user +inputdialog( {p} [, {t} [, {c}]]) String like input() but in a GUI dialog +inputlist( {textlist}) Number let the user pick from a choice list +inputrestore() Number restore typeahead +inputsave() Number save and clear typeahead +inputsecret( {prompt} [, {text}]) String like input() but hiding the text +insert( {list}, {item} [, {idx}]) List insert {item} in {list} [before {idx}] +isdirectory( {directory}) Number TRUE if {directory} is a directory +islocked( {expr}) Number TRUE if {expr} is locked +items( {dict}) List key-value pairs in {dict} +join( {list} [, {sep}]) String join {list} items into one String +keys( {dict}) List keys in {dict} +len( {expr}) Number the length of {expr} +libcall( {lib}, {func}, {arg}) String call {func} in library {lib} with {arg} +libcallnr( {lib}, {func}, {arg}) Number idem, but return a Number +line( {expr}) Number line nr of cursor, last line or mark +line2byte( {lnum}) Number byte count of line {lnum} +lispindent( {lnum}) Number Lisp indent for line {lnum} +localtime() Number current time +log( {expr}) Float natural logarithm (base e) of {expr} +log10( {expr}) Float logarithm of Float {expr} to base 10 +map( {expr}, {string}) List/Dict change each item in {expr} to {expr} +maparg( {name}[, {mode} [, {abbr} [, {dict}]]]) + String rhs of mapping {name} in mode {mode} +mapcheck( {name}[, {mode} [, {abbr}]]) + 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}]]) + List match and submatches of {pat} in {expr} +matchstr( {expr}, {pat}[, {start}[, {count}]]) + String {count}'th match of {pat} in {expr} +max( {list}) Number maximum value of items in {list} +min( {list}) Number minimum value of items in {list} +mkdir( {name} [, {path} [, {prot}]]) + Number create directory {name} +mode( [expr]) String current editing mode +mzeval( {expr}) any evaluate |MzScheme| expression +nextnonblank( {lnum}) Number line nr of non-blank line >= {lnum} +nr2char( {expr}) String single char with ASCII value {expr} +pathshorten( {expr}) String shorten directory names in a path +pow( {x}, {y}) Float {x} to the power of {y} +prevnonblank( {lnum}) Number line nr of non-blank line <= {lnum} +printf( {fmt}, {expr1}...) String format text +pumvisible() Number whether popup menu is visible +range( {expr} [, {max} [, {stride}]]) + List items from {expr} to {max} +readfile( {fname} [, {binary} [, {max}]]) + List get list of lines from file {fname} +reltime( [{start} [, {end}]]) List get time value +reltimestr( {time}) String turn time value into a String +remote_expr( {server}, {string} [, {idvar}]) + String send expression +remote_foreground( {server}) Number bring Vim server to the foreground +remote_peek( {serverid} [, {retvar}]) + Number check for reply string +remote_read( {serverid}) String read reply string +remote_send( {server}, {string} [, {idvar}]) + String send key sequence +remove( {list}, {idx} [, {end}]) any remove items {idx}-{end} from {list} +remove( {dict}, {key}) any remove entry {key} from {dict} +rename( {from}, {to}) Number rename (move) file from {from} to {to} +repeat( {expr}, {count}) String repeat {expr} {count} times +resolve( {filename}) String get filename a shortcut points to +reverse( {list}) List reverse {list} in-place +round( {expr}) Float round off {expr} +search( {pattern} [, {flags} [, {stopline} [, {timeout}]]]) + Number search for {pattern} +searchdecl( {name} [, {global} [, {thisblock}]]) + Number search for variable declaration +searchpair( {start}, {middle}, {end} [, {flags} [, {skip} [...]]]) + Number search for other end of start/end pair +searchpairpos( {start}, {middle}, {end} [, {flags} [, {skip} [...]]]) + List search for other end of start/end pair +searchpos( {pattern} [, {flags} [, {stopline} [, {timeout}]]]) + List search for {pattern} +server2client( {clientid}, {string}) + Number send reply string +serverlist() String get a list of available servers +setbufvar( {expr}, {varname}, {val}) set {varname} in buffer {expr} to {val} +setcmdpos( {pos}) Number set cursor position in command-line +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}) Number 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 +settabvar( {nr}, {varname}, {val}) set {varname} in tab page {nr} to {val} +settabwinvar( {tabnr}, {winnr}, {varname}, {val}) set {varname} in window + {winnr} in tab page {tabnr} to {val} +setwinvar( {nr}, {varname}, {val}) set {varname} in window {nr} to {val} +shellescape( {string} [, {special}]) + String escape {string} for use as shell + command argument +simplify( {filename}) String simplify filename as much as possible +sin( {expr}) Float sine of {expr} +sinh( {expr}) Float hyperbolic sine of {expr} +sort( {list} [, {func}]) List sort {list}, using {func} to compare +soundfold( {word}) String sound-fold {word} +spellbadword() String badly spelled word at cursor +spellsuggest( {word} [, {max} [, {capital}]]) + List spelling suggestions +split( {expr} [, {pat} [, {keepempty}]]) + List make |List| from {pat} separated {expr} +sqrt( {expr} Float squar root of {expr} +str2float( {expr}) Float convert String to Float +str2nr( {expr} [, {base}]) Number convert String to Number +strchars( {expr}) Number character length of the String {expr} +strdisplaywidth( {expr} [, {col}]) Number display length of the String {expr} +strftime( {format}[, {time}]) String time in specified format +stridx( {haystack}, {needle}[, {start}]) + Number index of {needle} in {haystack} +string( {expr}) String String representation of {expr} value +strlen( {expr}) Number length of the String {expr} +strpart( {src}, {start}[, {len}]) + String {len} characters of {src} at {start} +strridx( {haystack}, {needle} [, {start}]) + Number last index of {needle} in {haystack} +strtrans( {expr}) String translate string to make it printable +strwidth( {expr}) Number display cell length of the String {expr} +submatch( {nr}) String specific match in ":substitute" +substitute( {expr}, {pat}, {sub}, {flags}) + String all {pat} in {expr} replaced with {sub} +synID( {lnum}, {col}, {trans}) Number syntax ID at {lnum} and {col} +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 +tabpagewinnr( {tabarg}[, {arg}]) + Number number of current window in tab page +taglist( {expr}) List list of tags matching {expr} +tagfiles() List tags files used +tempname() String name for a temporary file +tan( {expr}) Float tangent of {expr} +tanh( {expr}) Float hyperbolic tangent of {expr} +tolower( {expr}) String the String {expr} switched to lowercase +toupper( {expr}) String the String {expr} switched to uppercase +tr( {src}, {fromstr}, {tostr}) String translate chars of {src} in {fromstr} + to chars in {tostr} +trunc( {expr} Float truncate Float {expr} +type( {name}) Number type of variable {name} +undofile( {name}) String undo file name for {name} +undotree() List undo file tree +values( {dict}) List values in {dict} +virtcol( {expr}) Number screen column of cursor or mark +visualmode( [expr]) String last visual mode used +winbufnr( {nr}) Number buffer number of window {nr} +wincol() Number window column of the cursor +winheight( {nr}) Number height of window {nr} +winline() Number window line of the cursor +winnr( [{expr}]) Number number of current window +winrestcmd() String returns command to restore window sizes +winrestview( {dict}) none restore view of current window +winsaveview() Dict save view of current window +winwidth( {nr}) Number width of window {nr} +writefile( {list}, {fname} [, {binary}]) + Number write list of lines to file {fname} + +abs({expr}) *abs()* + Return the absolute value of {expr}. When {expr} evaluates to + a |Float| abs() returns a |Float|. When {expr} can be + converted to a |Number| abs() returns a |Number|. Otherwise + abs() gives an error message and returns -1. + Examples: > + echo abs(1.456) +< 1.456 > + echo abs(-5.456) +< 5.456 > + echo abs(-4) +< 4 + {only available when compiled with the |+float| feature} + + +acos({expr}) *acos()* + Return the arc cosine of {expr} measured in radians, as a + |Float| in the range of [0, pi]. + {expr} must evaluate to a |Float| or a |Number| in the range + [-1, 1]. + Examples: > + :echo acos(0) +< 1.570796 > + :echo acos(-0.5) +< 2.094395 + {only available when compiled with the |+float| feature} + + +add({list}, {expr}) *add()* + Append the item {expr} to |List| {list}. Returns the + resulting |List|. Examples: > + :let alist = add([1, 2, 3], item) + :call add(mylist, "woodstock") +< Note that when {expr} is a |List| it is appended as a single + item. Use |extend()| to concatenate |Lists|. + Use |insert()| to add an item at another position. + + +append({lnum}, {expr}) *append()* + When {expr} is a |List|: Append each item of the |List| as a + text line below line {lnum} in the current buffer. + Otherwise append {expr} as one text line below line {lnum} in + the current buffer. + {lnum} can be zero to insert a line before the first one. + Returns 1 for failure ({lnum} out of range or out of memory), + 0 for success. Example: > + :let failed = append(line('$'), "# THE END") + :let failed = append(0, ["Chapter 1", "the beginning"]) +< + *argc()* +argc() The result is the number of files in the argument list of the + current window. See |arglist|. + + *argidx()* +argidx() The result is the current index in the argument list. 0 is + the first file. argc() - 1 is the last one. See |arglist|. + + *argv()* +argv([{nr}]) The result is the {nr}th file in the argument list of the + current window. See |arglist|. "argv(0)" is the first one. + Example: > + :let i = 0 + :while i < argc() + : let f = escape(fnameescape(argv(i)), '.') + : exe 'amenu Arg.' . f . ' :e ' . f . '' + : let i = i + 1 + :endwhile +< Without the {nr} argument a |List| with the whole |arglist| is + returned. + +asin({expr}) *asin()* + Return the arc sine of {expr} measured in radians, as a |Float| + in the range of [-pi/2, pi/2]. + {expr} must evaluate to a |Float| or a |Number| in the range + [-1, 1]. + Examples: > + :echo asin(0.8) +< 0.927295 > + :echo asin(-0.5) +< -0.523599 + {only available when compiled with the |+float| feature} + + +atan({expr}) *atan()* + Return the principal value of the arc tangent of {expr}, in + the range [-pi/2, +pi/2] radians, as a |Float|. + {expr} must evaluate to a |Float| or a |Number|. + Examples: > + :echo atan(100) +< 1.560797 > + :echo atan(-4.01) +< -1.326405 + {only available when compiled with the |+float| feature} + + +atan2({expr1}, {expr2}) *atan2()* + Return the arc tangent of {expr1} / {expr2}, measured in + radians, as a |Float| in the range [-pi, pi]. + {expr1} and {expr2} must evaluate to a |Float| or a |Number|. + Examples: > + :echo atan2(-1, 1) +< -0.785398 > + :echo atan2(1, -1) +< 2.356194 + {only available when compiled with the |+float| feature} + + + *browse()* +browse({save}, {title}, {initdir}, {default}) + Put up a file requester. This only works when "has("browse")" + returns non-zero (only in some GUI versions). + The input fields are: + {save} when non-zero, select file to write + {title} title for the requester + {initdir} directory to start browsing in + {default} default file name + When the "Cancel" button is hit, something went wrong, or + browsing is not possible, an empty string is returned. + + *browsedir()* +browsedir({title}, {initdir}) + Put up a directory requester. This only works when + "has("browse")" returns non-zero (only in some GUI versions). + On systems where a directory browser is not supported a file + browser is used. In that case: select a file in the directory + to be used. + The input fields are: + {title} title for the requester + {initdir} directory to start browsing in + When the "Cancel" button is hit, something went wrong, or + browsing is not possible, an empty string is returned. + +bufexists({expr}) *bufexists()* + The result is a Number, which is non-zero if a buffer called + {expr} exists. + If the {expr} argument is a number, buffer numbers are used. + If the {expr} argument is a string it must match a buffer name + exactly. The name can be: + - Relative to the current directory. + - A full path. + - The name of a buffer with 'buftype' set to "nofile". + - A URL name. + Unlisted buffers will be found. + Note that help files are listed by their short name in the + output of |:buffers|, but bufexists() requires using their + long name to be able to find them. + bufexists() may report a buffer exists, but to use the name + with a |:buffer| command you may need to use |expand()|. Esp + for MS-Windows 8.3 names in the form "c:\DOCUME~1" + Use "bufexists(0)" to test for the existence of an alternate + file name. + *buffer_exists()* + Obsolete name: buffer_exists(). + +buflisted({expr}) *buflisted()* + The result is a Number, which is non-zero if a buffer called + {expr} exists and is listed (has the 'buflisted' option set). + The {expr} argument is used like with |bufexists()|. + +bufloaded({expr}) *bufloaded()* + The result is a Number, which is non-zero if a buffer called + {expr} exists and is loaded (shown in a window or hidden). + The {expr} argument is used like with |bufexists()|. + +bufname({expr}) *bufname()* + The result is the name of a buffer, as it is displayed by the + ":ls" command. + If {expr} is a Number, that buffer number's name is given. + Number zero is the alternate buffer for the current window. + If {expr} is a String, it is used as a |file-pattern| to match + with the buffer names. This is always done like 'magic' is + set and 'cpoptions' is empty. When there is more than one + match an empty string is returned. + "" or "%" can be used for the current buffer, "#" for the + alternate buffer. + A full match is preferred, otherwise a match at the start, end + or middle of the buffer name is accepted. If you only want a + full match then put "^" at the start and "$" at the end of the + pattern. + Listed buffers are found first. If there is a single match + with a listed buffer, that one is returned. Next unlisted + buffers are searched for. + If the {expr} is a String, but you want to use it as a buffer + number, force it to be a Number by adding zero to it: > + :echo bufname("3" + 0) +< If the buffer doesn't exist, or doesn't have a name, an empty + string is returned. > + bufname("#") alternate buffer name + bufname(3) name of buffer 3 + bufname("%") name of current buffer + bufname("file2") name of buffer where "file2" matches. +< *buffer_name()* + Obsolete name: buffer_name(). + + *bufnr()* +bufnr({expr} [, {create}]) + The result is the number of a buffer, as it is displayed by + the ":ls" command. For the use of {expr}, see |bufname()| + above. + If the buffer doesn't exist, -1 is returned. Or, if the + {create} argument is present and not zero, a new, unlisted, + buffer is created and its number is returned. + bufnr("$") is the last buffer: > + :let last_buffer = bufnr("$") +< The result is a Number, which is the highest buffer number + of existing buffers. Note that not all buffers with a smaller + number necessarily exist, because ":bwipeout" may have removed + them. Use bufexists() to test for the existence of a buffer. + *buffer_number()* + Obsolete name: buffer_number(). + *last_buffer_nr()* + Obsolete name for bufnr("$"): last_buffer_nr(). + +bufwinnr({expr}) *bufwinnr()* + The result is a Number, which is the number of the first + window associated with buffer {expr}. For the use of {expr}, + see |bufname()| above. If buffer {expr} doesn't exist or + there is no such window, -1 is returned. Example: > + + echo "A window containing buffer 1 is " . (bufwinnr(1)) + +< The number can be used with |CTRL-W_w| and ":wincmd w" + |:wincmd|. + Only deals with the current tab page. + + +byte2line({byte}) *byte2line()* + Return the line number that contains the character at byte + count {byte} in the current buffer. This includes the + end-of-line character, depending on the 'fileformat' option + for the current buffer. The first character has byte count + one. + Also see |line2byte()|, |go| and |:goto|. + {not available when compiled without the |+byte_offset| + feature} + +byteidx({expr}, {nr}) *byteidx()* + Return byte index of the {nr}'th character in the string + {expr}. Use zero for the first character, it returns zero. + This function is only useful when there are multibyte + characters, otherwise the returned value is equal to {nr}. + Composing characters are counted as a separate character. + Example : > + echo matchstr(str, ".", byteidx(str, 3)) +< will display the fourth character. Another way to do the + same: > + let s = strpart(str, byteidx(str, 3)) + echo strpart(s, 0, byteidx(s, 1)) +< If there are less than {nr} characters -1 is returned. + If there are exactly {nr} characters the length of the string + is returned. + +call({func}, {arglist} [, {dict}]) *call()* *E699* + Call function {func} with the items in |List| {arglist} as + arguments. + {func} can either be a |Funcref| or the name of a function. + a:firstline and a:lastline are set to the cursor line. + Returns the return value of the called function. + {dict} is for functions with the "dict" attribute. It will be + used to set the local variable "self". |Dictionary-function| + +ceil({expr}) *ceil()* + Return the smallest integral value greater than or equal to + {expr} as a |Float| (round up). + {expr} must evaluate to a |Float| or a |Number|. + Examples: > + echo ceil(1.456) +< 2.0 > + echo ceil(-5.456) +< -5.0 > + echo ceil(4.0) +< 4.0 + {only available when compiled with the |+float| feature} + +changenr() *changenr()* + Return the number of the most recent change. This is the same + number as what is displayed with |:undolist| and can be used + with the |:undo| command. + When a change was made it is the number of that change. After + redo it is the number of the redone change. After undo it is + one less than the number of the undone change. + +char2nr({expr}) *char2nr()* + Return number value of the first char in {expr}. Examples: > + char2nr(" ") returns 32 + char2nr("ABC") returns 65 +< The current 'encoding' is used. Example for "utf-8": > + char2nr("á") returns 225 + char2nr("á"[0]) returns 195 +< |nr2char()| does the opposite. + +cindent({lnum}) *cindent()* + Get the amount of indent for line {lnum} according the C + indenting rules, as with 'cindent'. + The indent is counted in spaces, the value of 'tabstop' is + relevant. {lnum} is used just like in |getline()|. + When {lnum} is invalid or Vim was not compiled the |+cindent| + 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: + . the cursor position + $ the end of the cursor line (the result is the + 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 last 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()|. + Note that only marks in the current file can be used. + Examples: > + col(".") column of cursor + col("$") length of cursor line plus one + col("'t") column of mark t + col("'" . markname) column of mark markname +< The first column is 1. 0 is returned for an error. + For an uppercase mark the column may actually be in another + buffer. + For the cursor position, when 'virtualedit' is active, the + column is one higher if the cursor is after the end of the + line. This can be used to obtain the column in Insert mode: > + :imap :let save_ve = &ve + \:set ve=all + \:echo col(".") . "\n" + \let &ve = save_ve +< + +complete({startcol}, {matches}) *complete()* *E785* + Set the matches for Insert mode completion. + Can only be used in Insert mode. You need to use a mapping + with CTRL-R = |i_CTRL-R|. It does not work after CTRL-O or + with an expression mapping. + {startcol} is the byte offset in the line where the completed + text start. The text up to the cursor is the original text + that will be replaced by the matches. Use col('.') for an + empty string. "col('.') - 1" will replace one character by a + match. + {matches} must be a |List|. Each |List| item is one match. + See |complete-items| for the kind of items that are possible. + Note that the after calling this function you need to avoid + inserting anything that would cause completion to stop. + The match can be selected with CTRL-N and CTRL-P as usual with + Insert mode completion. The popup menu will appear if + specified, see |ins-completion-menu|. + Example: > + inoremap =ListMonths() + + func! ListMonths() + call complete(col('.'), ['January', 'February', 'March', + \ 'April', 'May', 'June', 'July', 'August', 'September', + \ 'October', 'November', 'December']) + return '' + endfunc +< This isn't very useful, but it shows how it works. Note that + an empty string is returned to avoid a zero being inserted. + +complete_add({expr}) *complete_add()* + Add {expr} to the list of matches. Only to be used by the + function specified with the 'completefunc' option. + Returns 0 for failure (empty string or out of memory), + 1 when the match was added, 2 when the match was already in + the list. + See |complete-functions| for an explanation of {expr}. It is + the same as one item in the list that 'omnifunc' would return. + +complete_check() *complete_check()* + Check for a key typed while looking for completion matches. + This is to be used when looking for matches takes some time. + Returns non-zero when searching for matches is to be aborted, + zero otherwise. + Only to be used by the function specified with the + 'completefunc' option. + + *confirm()* +confirm({msg} [, {choices} [, {default} [, {type}]]]) + Confirm() offers the user a dialog, from which a choice can be + made. It returns the number of the choice. For the first + choice this is 1. + Note: confirm() is only supported when compiled with dialog + support, see |+dialog_con| and |+dialog_gui|. + + {msg} is displayed in a |dialog| with {choices} as the + alternatives. When {choices} is missing or empty, "&OK" is + used (and translated). + {msg} is a String, use '\n' to include a newline. Only on + some systems the string is wrapped when it doesn't fit. + + {choices} is a String, with the individual choices separated + by '\n', e.g. > + confirm("Save changes?", "&Yes\n&No\n&Cancel") +< The letter after the '&' is the shortcut key for that choice. + Thus you can type 'c' to select "Cancel". The shortcut does + not need to be the first letter: > + confirm("file has been modified", "&Save\nSave &All") +< For the console, the first letter of each choice is used as + the default shortcut key. + + The optional {default} argument is the number of the choice + that is made if the user hits . Use 1 to make the first + choice the default one. Use 0 to not set a default. If + {default} is omitted, 1 is used. + + The optional {type} argument gives the type of dialog. This + is only used for the icon of the GTK, Mac, Motif and Win32 + GUI. It can be one of these values: "Error", "Question", + "Info", "Warning" or "Generic". Only the first character is + relevant. When {type} is omitted, "Generic" is used. + + If the user aborts the dialog by pressing , CTRL-C, + or another valid interrupt key, confirm() returns 0. + + An example: > + :let choice = confirm("What do you want?", "&Apples\n&Oranges\n&Bananas", 2) + :if choice == 0 + : echo "make up your mind!" + :elseif choice == 3 + : echo "tasteful" + :else + : echo "I prefer bananas myself." + :endif +< In a GUI dialog, buttons are used. The layout of the buttons + depends on the 'v' flag in 'guioptions'. If it is included, + the buttons are always put vertically. Otherwise, confirm() + tries to put the buttons in one horizontal line. If they + don't fit, a vertical layout is used anyway. For some systems + the horizontal layout is always used. + + *copy()* +copy({expr}) Make a copy of {expr}. For Numbers and Strings this isn't + different from using {expr} directly. + When {expr} is a |List| a shallow copy is created. This means + that the original |List| can be changed without changing the + copy, and vice versa. But the items are identical, thus + changing an item changes the contents of both |Lists|. Also + see |deepcopy()|. + +cos({expr}) *cos()* + Return the cosine of {expr}, measured in radians, as a |Float|. + {expr} must evaluate to a |Float| or a |Number|. + Examples: > + :echo cos(100) +< 0.862319 > + :echo cos(-4.01) +< -0.646043 + {only available when compiled with the |+float| feature} + + +cosh({expr}) *cosh()* + Return the hyperbolic cosine of {expr} as a |Float| in the range + [1, inf]. + {expr} must evaluate to a |Float| or a |Number|. + Examples: > + :echo cosh(0.5) +< 1.127626 > + :echo cosh(-0.5) +< -1.127626 + {only available when compiled with the |+float| feature} + + +count({comp}, {expr} [, {ic} [, {start}]]) *count()* + Return the number of times an item with value {expr} appears + in |List| or |Dictionary| {comp}. + If {start} is given then start with the item with this index. + {start} can only be used with a |List|. + When {ic} is given and it's non-zero then case is ignored. + + + *cscope_connection()* +cscope_connection([{num} , {dbpath} [, {prepend}]]) + Checks for the existence of a |cscope| connection. If no + parameters are specified, then the function returns: + 0, if cscope was not available (not compiled in), or + if there are no cscope connections; + 1, if there is at least one cscope connection. + + If parameters are specified, then the value of {num} + determines how existence of a cscope connection is checked: + + {num} Description of existence check + ----- ------------------------------ + 0 Same as no parameters (e.g., "cscope_connection()"). + 1 Ignore {prepend}, and use partial string matches for + {dbpath}. + 2 Ignore {prepend}, and use exact string matches for + {dbpath}. + 3 Use {prepend}, use partial string matches for both + {dbpath} and {prepend}. + 4 Use {prepend}, use exact string matches for both + {dbpath} and {prepend}. + + Note: All string comparisons are case sensitive! + + Examples. Suppose we had the following (from ":cs show"): > + + # pid database name prepend path + 0 27664 cscope.out /usr/local +< + Invocation Return Val ~ + ---------- ---------- > + cscope_connection() 1 + cscope_connection(1, "out") 1 + cscope_connection(2, "out") 0 + cscope_connection(3, "out") 0 + cscope_connection(3, "out", "local") 1 + cscope_connection(4, "out") 0 + cscope_connection(4, "out", "local") 0 + cscope_connection(4, "cscope.out", "/usr/local") 1 +< +cursor({lnum}, {col} [, {off}]) *cursor()* +cursor({list}) + Positions the cursor at the column (byte count) {col} in the + line {lnum}. The first column is one. + When there is one argument {list} this is used as a |List| + with two or three items {lnum}, {col} and {off}. This is like + the return value of |getpos()|, but without the first item. + Does not change the jumplist. + If {lnum} is greater than the number of lines in the buffer, + the cursor will be positioned at the last line in the buffer. + If {lnum} is zero, the cursor will stay in the current line. + If {col} is greater than the number of bytes in the line, + the cursor will be positioned at the last character in the + line. + If {col} is zero, the cursor will stay in the current column. + When 'virtualedit' is used {off} specifies the offset in + screen columns from the start of the character. E.g., a + position within a or after the last character. + Returns 0 when the position could be set, -1 otherwise. + + +deepcopy({expr}[, {noref}]) *deepcopy()* *E698* + Make a copy of {expr}. For Numbers and Strings this isn't + different from using {expr} directly. + When {expr} is a |List| a full copy is created. This means + that the original |List| can be changed without changing the + copy, and vice versa. When an item is a |List|, a copy for it + is made, recursively. Thus changing an item in the copy does + not change the contents of the original |List|. + When {noref} is omitted or zero a contained |List| or + |Dictionary| is only copied once. All references point to + this single copy. With {noref} set to 1 every occurrence of a + |List| or |Dictionary| results in a new copy. This also means + that a cyclic reference causes deepcopy() to fail. + *E724* + Nesting is possible up to 100 levels. When there is an item + that refers back to a higher level making a deep copy with + {noref} set to 1 will fail. + Also see |copy()|. + +delete({fname}) *delete()* + Deletes the file by the name {fname}. The result is a Number, + which is 0 if the file was deleted successfully, and non-zero + when the deletion failed. + Use |remove()| to delete an item from a |List|. + + *did_filetype()* +did_filetype() Returns non-zero when autocommands are being executed and the + FileType event has been triggered at least once. Can be used + to avoid triggering the FileType event again in the scripts + that detect the file type. |FileType| + When editing another file, the counter is reset, thus this + really checks if the FileType event has been triggered for the + current buffer. This allows an autocommand that starts + editing another buffer to set 'filetype' and load a syntax + file. + +diff_filler({lnum}) *diff_filler()* + Returns the number of filler lines above line {lnum}. + These are the lines that were inserted at this point in + another diff'ed window. These filler lines are shown in the + display but don't exist in the buffer. + {lnum} is used like with |getline()|. Thus "." is the current + line, "'m" mark m, etc. + Returns 0 if the current window is not in diff mode. + +diff_hlID({lnum}, {col}) *diff_hlID()* + Returns the highlight ID for diff mode at line {lnum} column + {col} (byte index). When the current line does not have a + diff change zero is returned. + {lnum} is used like with |getline()|. Thus "." is the current + line, "'m" mark m, etc. + {col} is 1 for the leftmost column, {lnum} is 1 for the first + line. + The highlight ID can be used with |synIDattr()| to obtain + syntax information about the highlighting. + +empty({expr}) *empty()* + Return the Number 1 if {expr} is empty, zero otherwise. + A |List| or |Dictionary| is empty when it does not have any + items. A Number is empty when its value is zero. + For a long |List| this is much faster than comparing the + length with zero. + +escape({string}, {chars}) *escape()* + Escape the characters in {chars} that occur in {string} with a + backslash. Example: > + :echo escape('c:\program files\vim', ' \') +< results in: > + c:\\program\ files\\vim +< Also see |shellescape()|. + + *eval()* +eval({string}) Evaluate {string} and return the result. Especially useful to + turn the result of |string()| back into the original value. + This works for Numbers, Floats, Strings and composites of + them. Also works for |Funcref|s that refer to existing + functions. + +eventhandler() *eventhandler()* + Returns 1 when inside an event handler. That is that Vim got + interrupted while waiting for the user to type a character, + e.g., when dropping a file on Vim. This means interactive + commands cannot be used. Otherwise zero is returned. + +executable({expr}) *executable()* + This function checks if an executable with the name {expr} + exists. {expr} must be the name of the program without any + arguments. + executable() uses the value of $PATH and/or the normal + searchpath for programs. *PATHEXT* + On MS-DOS and MS-Windows the ".exe", ".bat", etc. can + optionally be included. Then the extensions in $PATHEXT are + tried. Thus if "foo.exe" does not exist, "foo.exe.bat" can be + found. If $PATHEXT is not set then ".exe;.com;.bat;.cmd" is + used. A dot by itself can be used in $PATHEXT to try using + the name without an extension. When 'shell' looks like a + Unix shell, then the name is also tried without adding an + extension. + On MS-DOS and MS-Windows it only checks if the file exists and + is not a directory, not if it's really executable. + On MS-Windows an executable in the same directory as Vim is + always found. Since this directory is added to $PATH it + should also work to execute it |win32-PATH|. + The result is a Number: + 1 exists + 0 does not exist + -1 not implemented on this system + + *exists()* +exists({expr}) The result is a Number, which is non-zero if {expr} is + defined, zero otherwise. The {expr} argument is a string, + which contains one of these: + &option-name Vim option (only checks if it exists, + not if it really works) + +option-name Vim option that works. + $ENVNAME environment variable (could also be + done by comparing with an empty + string) + *funcname built-in function (see |functions|) + or user defined function (see + |user-functions|). + varname internal variable (see + |internal-variables|). Also works + for |curly-braces-names|, |Dictionary| + entries, |List| items, etc. Beware + that evaluating an index may cause an + error message for an invalid + expression. E.g.: > + :let l = [1, 2, 3] + :echo exists("l[5]") +< 0 > + :echo exists("l[xx]") +< E121: Undefined variable: xx + 0 + :cmdname Ex command: built-in command, user + command or command modifier |:command|. + Returns: + 1 for match with start of a command + 2 full match with a command + 3 matches several user commands + To check for a supported command + always check the return value to be 2. + :2match The |:2match| command. + :3match The |:3match| command. + #event autocommand defined for this event + #event#pattern autocommand defined for this event and + pattern (the pattern is taken + literally and compared to the + autocommand patterns character by + character) + #group autocommand group exists + #group#event autocommand defined for this group and + event. + #group#event#pattern + autocommand defined for this group, + event and pattern. + ##event autocommand for this event is + supported. + For checking for a supported feature use |has()|. + + Examples: > + exists("&shortname") + exists("$HOSTNAME") + exists("*strftime") + exists("*s:MyFunc") + exists("bufcount") + exists(":Make") + exists("#CursorHold") + exists("#BufReadPre#*.gz") + exists("#filetypeindent") + exists("#filetypeindent#FileType") + exists("#filetypeindent#FileType#*") + exists("##ColorScheme") +< There must be no space between the symbol (&/$/*/#) and the + name. + There must be no extra characters after the name, although in + a few cases this is ignored. That may become more strict in + the future, thus don't count on it! + Working example: > + exists(":make") +< NOT working example: > + exists(":make install") + +< Note that the argument must be a string, not the name of the + variable itself. For example: > + exists(bufcount) +< This doesn't check for existence of the "bufcount" variable, + but gets the value of "bufcount", and checks if that exists. + +exp({expr}) *exp()* + Return the exponential of {expr} as a |Float| in the range + [0, inf]. + {expr} must evaluate to a |Float| or a |Number|. + Examples: > + :echo exp(2) +< 7.389056 > + :echo exp(-1) +< 0.367879 + {only available when compiled with the |+float| feature} + + +expand({expr} [, {flag}]) *expand()* + Expand wildcards and the following special keywords in {expr}. + The result is a String. + + When there are several matches, they are separated by + characters. [Note: in version 5.0 a space was used, which + caused problems when a file name contains a space] + + If the expansion fails, the result is an empty string. A name + for a non-existing file is not included. + + When {expr} starts with '%', '#' or '<', the expansion is done + like for the |cmdline-special| variables with their associated + modifiers. Here is a short overview: + + % current file name + # alternate file name + #n alternate file name n + file name under the cursor + autocmd file name + autocmd buffer number (as a String!) + autocmd matched name + sourced script file name + word under the cursor + WORD under the cursor + the {clientid} of the last received + message |server2client()| + Modifiers: + :p expand to full path + :h head (last path component removed) + :t tail (last path component only) + :r root (one extension removed) + :e extension only + + Example: > + :let &tags = expand("%:p:h") . "/tags" +< Note that when expanding a string that starts with '%', '#' or + '<', any following text is ignored. This does NOT work: > + :let doesntwork = expand("%:h.bak") +< Use this: > + :let doeswork = expand("%:h") . ".bak" +< Also note that expanding "" and others only returns the + referenced file name without further expansion. If "" + is "~/.cshrc", you need to do another expand() to have the + "~/" expanded into the path of the home directory: > + :echo expand(expand("")) +< + There cannot be white space between the variables and the + following modifier. The |fnamemodify()| function can be used + to modify normal file names. + + When using '%' or '#', and the current or alternate file name + is not defined, an empty string is used. Using "%:p" in a + buffer with no name, results in the current directory, with a + '/' added. + + When {expr} does not start with '%', '#' or '<', it is + expanded like a file name is expanded on the command line. + 'suffixes' and 'wildignore' are used, unless the optional + {flag} argument is given and it is non-zero. Names for + non-existing files are included. The "**" item can be used to + search in a directory tree. For example, to find all "README" + files in the current directory and below: > + :echo expand("**/README") +< + Expand() can also be used to expand variables and environment + variables that are only known in a shell. But this can be + slow, because a shell must be started. See |expr-env-expand|. + The expanded variable is still handled like a list of file + names. When an environment variable cannot be expanded, it is + left unchanged. Thus ":echo expand('$FOOBAR')" results in + "$FOOBAR". + + See |glob()| for finding existing files. See |system()| for + getting the raw output of an external command. + +extend({expr1}, {expr2} [, {expr3}]) *extend()* + {expr1} and {expr2} must be both |Lists| or both + |Dictionaries|. + + If they are |Lists|: Append {expr2} to {expr1}. + If {expr3} is given insert the items of {expr2} before item + {expr3} in {expr1}. When {expr3} is zero insert before the + first item. When {expr3} is equal to len({expr1}) then + {expr2} is appended. + Examples: > + :echo sort(extend(mylist, [7, 5])) + :call extend(mylist, [2, 3], 1) +< When {expr1} is the same List as {expr2} then the number of + items copied is equal to the original length of the List. + E.g., when {expr3} is 1 you get N new copies of the first item + (where N is the original length of the List). + Use |add()| to concatenate one item to a list. To concatenate + two lists into a new list use the + operator: > + :let newlist = [1, 2, 3] + [4, 5] +< + If they are |Dictionaries|: + Add all entries from {expr2} to {expr1}. + If a key exists in both {expr1} and {expr2} then {expr3} is + used to decide what to do: + {expr3} = "keep": keep the value of {expr1} + {expr3} = "force": use the value of {expr2} + {expr3} = "error": give an error message *E737* + When {expr3} is omitted then "force" is assumed. + + {expr1} is changed when {expr2} is not empty. If necessary + make a copy of {expr1} first. + {expr2} remains unchanged. + Returns {expr1}. + + +feedkeys({string} [, {mode}]) *feedkeys()* + Characters in {string} are queued for processing as if they + come from a mapping or were typed by the user. They are added + to the end of the typeahead buffer, thus if a mapping is still + being executed these characters come after them. + The function does not wait for processing of keys contained in + {string}. + To include special keys into {string}, use double-quotes + and "\..." notation |expr-quote|. For example, + feedkeys("\") simulates pressing of the key. But + feedkeys('\') pushes 5 characters. + If {mode} is absent, keys are remapped. + {mode} is a String, which can contain these character flags: + 'm' Remap keys. This is default. + 'n' Do not remap keys. + 't' Handle keys as if typed; otherwise they are handled as + if coming from a mapping. This matters for undo, + opening folds, etc. + Return value is always 0. + +filereadable({file}) *filereadable()* + The result is a Number, which is TRUE when a file with the + name {file} exists, and can be read. If {file} doesn't exist, + or is a directory, the result is FALSE. {file} is any + expression, which is used as a String. + If you don't care about the file being readable you can use + |glob()|. + *file_readable()* + Obsolete name: file_readable(). + + +filewritable({file}) *filewritable()* + The result is a Number, which is 1 when a file with the + name {file} exists, and can be written. If {file} doesn't + exist, or is not writable, the result is 0. If {file} is a + directory, and we can write to it, the result is 2. + + +filter({expr}, {string}) *filter()* + {expr} must be a |List| or a |Dictionary|. + For each item in {expr} evaluate {string} and when the result + is zero remove the item from the |List| or |Dictionary|. + Inside {string} |v:val| has the value of the current item. + For a |Dictionary| |v:key| has the key of the current item. + Examples: > + :call filter(mylist, 'v:val !~ "OLD"') +< Removes the items where "OLD" appears. > + :call filter(mydict, 'v:key >= 8') +< Removes the items with a key below 8. > + :call filter(var, 0) +< Removes all the items, thus clears the |List| or |Dictionary|. + + Note that {string} is the result of expression and is then + used as an expression again. Often it is good to use a + |literal-string| to avoid having to double backslashes. + + The operation is done in-place. If you want a |List| or + |Dictionary| to remain unmodified make a copy first: > + :let l = filter(copy(mylist), 'v:val =~ "KEEP"') + +< Returns {expr}, the |List| or |Dictionary| that was filtered. + When an error is encountered while evaluating {string} no + further items in {expr} are processed. + + +finddir({name}[, {path}[, {count}]]) *finddir()* + Find directory {name} in {path}. Supports both downwards and + upwards recursive directory searches. See |file-searching| + for the syntax of {path}. + Returns the path of the first found match. When the found + directory is below the current directory a relative path is + returned. Otherwise a full path is returned. + If {path} is omitted or empty then 'path' is used. + If the optional {count} is given, find {count}'s occurrence of + {name} in {path} instead of the first one. + When {count} is negative return all the matches in a |List|. + This is quite similar to the ex-command |:find|. + {only available when compiled with the |+file_in_path| + feature} + +findfile({name}[, {path}[, {count}]]) *findfile()* + Just like |finddir()|, but find a file instead of a directory. + Uses 'suffixesadd'. + Example: > + :echo findfile("tags.vim", ".;") +< Searches from the directory of the current file upwards until + it finds the file "tags.vim". + +float2nr({expr}) *float2nr()* + Convert {expr} to a Number by omitting the part after the + decimal point. + {expr} must evaluate to a |Float| or a Number. + When the value of {expr} is out of range for a |Number| the + result is truncated to 0x7fffffff or -0x7fffffff. NaN results + in -0x80000000. + Examples: > + echo float2nr(3.95) +< 3 > + echo float2nr(-23.45) +< -23 > + echo float2nr(1.0e100) +< 2147483647 > + echo float2nr(-1.0e150) +< -2147483647 > + echo float2nr(1.0e-100) +< 0 + {only available when compiled with the |+float| feature} + + +floor({expr}) *floor()* + Return the largest integral value less than or equal to + {expr} as a |Float| (round down). + {expr} must evaluate to a |Float| or a |Number|. + Examples: > + echo floor(1.856) +< 1.0 > + echo floor(-5.456) +< -6.0 > + echo floor(4.0) +< 4.0 + {only available when compiled with the |+float| feature} + + +fmod({expr1}, {expr2}) *fmod()* + Return the remainder of {expr1} / {expr2}, even if the + division is not representable. Returns {expr1} - i * {expr2} + for some integer i such that if {expr2} is non-zero, the + result has the same sign as {expr1} and magnitude less than + the magnitude of {expr2}. If {expr2} is zero, the value + returned is zero. The value returned is a |Float|. + {expr1} and {expr2} must evaluate to a |Float| or a |Number|. + Examples: > + :echo fmod(12.33, 1.22) +< 0.13 > + :echo fmod(-12.33, 1.22) +< -0.13 + {only available when compiled with |+float| feature} + + +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 + " \t\n*?[{`$\\%#'\"|!<". For systems where a backslash + appears in a filename, it depends on the value of 'isfname'. + A leading '+' and '>' is also escaped (special after |:edit| + and |:write|). And a "-" by itself (special after |:cd|). + 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 + command line. See |filename-modifiers|. + Example: > + :echo fnamemodify("main.c", ":p:h") +< results in: > + /home/mool/vim/vim/src +< Note: Environment variables don't work in {fname}, use + |expand()| first then. + +foldclosed({lnum}) *foldclosed()* + The result is a Number. If the line {lnum} is in a closed + fold, the result is the number of the first line in that fold. + If the line {lnum} is not in a closed fold, -1 is returned. + +foldclosedend({lnum}) *foldclosedend()* + The result is a Number. If the line {lnum} is in a closed + fold, the result is the number of the last line in that fold. + If the line {lnum} is not in a closed fold, -1 is returned. + +foldlevel({lnum}) *foldlevel()* + The result is a Number, which is the foldlevel of line {lnum} + in the current buffer. For nested folds the deepest level is + returned. If there is no fold at line {lnum}, zero is + returned. It doesn't matter if the folds are open or closed. + When used while updating folds (from 'foldexpr') -1 is + returned for lines where folds are still to be updated and the + foldlevel is unknown. As a special case the level of the + previous line is usually available. + + *foldtext()* +foldtext() Returns a String, to be displayed for a closed fold. This is + the default function used for the 'foldtext' option and should + only be called from evaluating 'foldtext'. It uses the + |v:foldstart|, |v:foldend| and |v:folddashes| variables. + The returned string looks like this: > + +-- 45 lines: abcdef +< The number of dashes depends on the foldlevel. The "45" is + the number of lines in the fold. "abcdef" is the text in the + first non-blank line of the fold. Leading white space, "//" + or "/*" and the text from the 'foldmarker' and 'commentstring' + options is removed. + {not available when compiled without the |+folding| feature} + +foldtextresult({lnum}) *foldtextresult()* + Returns the text that is displayed for the closed fold at line + {lnum}. Evaluates 'foldtext' in the appropriate context. + When there is no closed fold at {lnum} an empty string is + returned. + {lnum} is used like with |getline()|. Thus "." is the current + line, "'m" mark m, etc. + Useful when exporting folded text, e.g., to HTML. + {not available when compiled without the |+folding| feature} + + *foreground()* +foreground() Move the Vim window to the foreground. Useful when sent from + a client to a Vim server. |remote_send()| + On Win32 systems this might not work, the OS does not always + allow a window to bring itself to the foreground. Use + |remote_foreground()| instead. + {only in the Win32, Athena, Motif and GTK GUI versions and the + Win32 console version} + + +function({name}) *function()* *E700* + Return a |Funcref| variable that refers to function {name}. + {name} can be a user defined function or an internal function. + + +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 + memory or is waiting for the user to press a key after + 'updatetime'. Items without circular references are always + freed when they become unused. + 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 + available return {default}. Return zero when {default} is + omitted. +get({dict}, {key} [, {default}]) + Get item with key {key} from |Dictionary| {dict}. When this + item is not available return {default}. Return zero when + {default} is omitted. + + *getbufline()* +getbufline({expr}, {lnum} [, {end}]) + Return a |List| with the lines starting from {lnum} to {end} + (inclusive) in the buffer {expr}. If {end} is omitted, a + |List| with only the line {lnum} is returned. + + For the use of {expr}, see |bufname()| above. + + For {lnum} and {end} "$" can be used for the last line of the + buffer. Otherwise a number must be used. + + When {lnum} is smaller than 1 or bigger than the number of + lines in the buffer, an empty |List| is returned. + + When {end} is greater than the number of lines in the buffer, + it is treated as {end} is set to the number of lines in the + buffer. When {end} is before {lnum} an empty |List| is + returned. + + This function works only for loaded buffers. For unloaded and + non-existing buffers, an empty |List| is returned. + + Example: > + :let lines = getbufline(bufnr("myfile"), 1, "$") + +getbufvar({expr}, {varname}) *getbufvar()* + The result is the value of option or local buffer variable + {varname} in buffer {expr}. Note that the name without "b:" + must be used. + When {varname} is empty returns a dictionary with all the + buffer-local variables. + This also works for a global or buffer-local option, but it + doesn't work for a global variable, window-local variable or + window-local option. + For the use of {expr}, see |bufname()| above. + When the buffer or variable doesn't exist an empty string is + returned, there is no error message. + Examples: > + :let bufmodified = getbufvar(1, "&mod") + :echo "todo myvar = " . getbufvar("todo", "myvar") +< +getchar([expr]) *getchar()* + Get a single character from the user or input stream. + If [expr] is omitted, wait until a character is available. + If [expr] is 0, only get a character when one is available. + Return zero otherwise. + If [expr] is 1, only check if a character is available, it is + not consumed. Return zero if no character available. + + Without {expr} and when {expr} is 0 a whole character or + special key is returned. If it is an 8-bit character, the + result is a number. Use nr2char() to convert it to a String. + Otherwise a String is returned with the encoded character. + For a special key it's a sequence of bytes starting with 0x80 + (decimal: 128). This is the same value as the string + "\", e.g., "\". The returned value is also a + String when a modifier (shift, control, alt) was used that is + not included in the character. + + When {expr} is 1 only the first byte is returned. For a + one-byte character it is the character itself as a number. + Use nr2char() to convert it to a String. + + When the user clicks a mouse button, the mouse event will be + returned. The position can then be found in |v:mouse_col|, + |v:mouse_lnum| and |v:mouse_win|. This example positions the + mouse as it would normally happen: > + let c = getchar() + if c == "\" && v:mouse_win > 0 + exe v:mouse_win . "wincmd w" + exe v:mouse_lnum + exe "normal " . v:mouse_col . "|" + endif +< + There is no prompt, you will somehow have to make clear to the + user that a character has to be typed. + There is no mapping for the character. + Key codes are replaced, thus when the user presses the + key you get the code for the key, not the raw character + sequence. Examples: > + getchar() == "\" + getchar() == "\" +< This example redefines "f" to ignore case: > + :nmap f :call FindChar() + :function FindChar() + : let c = nr2char(getchar()) + : while col('.') < col('$') - 1 + : normal l + : if getline('.')[col('.') - 1] ==? c + : break + : endif + : endwhile + :endfunction + +getcharmod() *getcharmod()* + The result is a Number which is the state of the modifiers for + the last obtained character with getchar() or in another way. + These values are added together: + 2 shift + 4 control + 8 alt (meta) + 16 mouse double click + 32 mouse triple click + 64 mouse quadruple click + 128 Macintosh only: command + Only the modifiers that have not been included in the + character itself are obtained. Thus Shift-a results in "A" + without a modifier. + +getcmdline() *getcmdline()* + Return the current command-line. Only works when the command + line is being edited, thus requires use of |c_CTRL-\_e| or + |c_CTRL-R_=|. + Example: > + :cmap eescape(getcmdline(), ' \') +< Also see |getcmdtype()|, |getcmdpos()| and |setcmdpos()|. + +getcmdpos() *getcmdpos()* + Return the position of the cursor in the command line as a + byte count. The first column is 1. + Only works when editing the command line, thus requires use of + |c_CTRL-\_e| or |c_CTRL-R_=|. Returns 0 otherwise. + Also see |getcmdtype()|, |setcmdpos()| and |getcmdline()|. + +getcmdtype() *getcmdtype()* + Return the current command-line type. Possible return values + are: + : normal Ex command + > debug mode command |debug-mode| + / forward search command + ? backward search command + @ |input()| command + - |:insert| or |:append| command + Only works when editing the command line, thus requires use of + |c_CTRL-\_e| or |c_CTRL-R_=|. Returns an empty string + otherwise. + Also see |getcmdpos()|, |setcmdpos()| and |getcmdline()|. + + *getcwd()* +getcwd() The result is a String, which is the name of the current + working directory. + +getfsize({fname}) *getfsize()* + The result is a Number, which is the size in bytes of the + 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 + used. Like what is used for the Normal highlight group + |hl-Normal|. + With an argument a check is done whether {name} is a valid + font name. If not then an empty string is returned. + Otherwise the actual font name is returned, or {name} if the + GUI does not support obtaining the real name. + Only works when the GUI is running, thus not in your vimrc or + gvimrc file. Use the |GUIEnter| autocommand to use this + function just after the GUI has started. + Note that the GTK 2 GUI accepts any font name, thus checking + for a valid name does not work. + +getfperm({fname}) *getfperm()* + The result is a String, which is the read, write, and execute + permissions of the given file {fname}. + If {fname} does not exist or its directory cannot be read, an + empty string is returned. + The result is of the form "rwxrwxrwx", where each group of + "rwx" flags represent, in turn, the permissions of the owner + of the file, the group the file belongs to, and other users. + If a user does not have a given permission the flag for this + is replaced with the string "-". Example: > + :echo getfperm("/etc/passwd") +< This will hopefully (from a security point of view) display + the string "rw-r--r--" or even "rw-------". + +getftime({fname}) *getftime()* + The result is a Number, which is the last modification time of + the given file {fname}. The value is measured as seconds + since 1st Jan 1970, and may be passed to strftime(). See also + |localtime()| and |strftime()|. + If the file {fname} can't be found -1 is returned. + +getftype({fname}) *getftype()* + The result is a String, which is a description of the kind of + file of the given file {fname}. + If {fname} does not exist an empty string is returned. + Here is a table over different kinds of files and their + results: + Normal file "file" + Directory "dir" + Symbolic link "link" + Block device "bdev" + Character device "cdev" + Socket "socket" + FIFO "fifo" + All other "other" + Example: > + getftype("/home") +< Note that a type such as "link" will only be returned on + systems that support it. On some systems only "dir" and + "file" are returned. + + *getline()* +getline({lnum} [, {end}]) + Without {end} the result is a String, which is line {lnum} + from the current buffer. Example: > + getline(1) +< When {lnum} is a String that doesn't start with a + digit, line() is called to translate the String into a Number. + To get the line under the cursor: > + getline(".") +< When {lnum} is smaller than 1 or bigger than the number of + lines in the buffer, an empty string is returned. + + When {end} is given the result is a |List| where each item is + a line from the current buffer in the range {lnum} to {end}, + including line {end}. + {end} is used in the same way as {lnum}. + Non-existing lines are silently omitted. + When {end} is before {lnum} an empty |List| is returned. + Example: > + :let start = line('.') + :let end = search("^$") - 1 + :let lines = getline(start, end) + +< To get lines from another buffer see |getbufline()| + +getloclist({nr}) *getloclist()* + Returns a list with all the entries in the location list for + window {nr}. When {nr} is zero the current window is used. + For a location list window, the displayed location list is + 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: + bufnr number of buffer that has the file name, use + bufname() to get the name + lnum line number in the buffer (first line is 1) + col column number (first column is 1) + vcol non-zero: "col" is visual column + zero: "col" is byte index + nr error number + pattern search pattern used to locate the error + text description of the error + type type of the error, 'E', '1', etc. + valid non-zero: recognized error message + + When there is no error list or it's empty an empty list is + returned. Quickfix list entries with non-existing buffer + number are returned with "bufnr" set to zero. + + Useful application: Find pattern matches in multiple files and + do something with them: > + :vimgrep /theword/jg *.c + :for d in getqflist() + : echo bufname(d.bufnr) ':' d.lnum '=' d.text + :endfor + + +getreg([{regname} [, 1]]) *getreg()* + The result is a String, which is the contents of register + {regname}. Example: > + :let cliptext = getreg('*') +< getreg('=') returns the last evaluated value of the expression + register. (For use in maps.) + getreg('=', 1) returns the expression itself, so that it can + be restored with |setreg()|. For other registers the extra + argument is ignored, thus you can always give it. + If {regname} is not specified, |v:register| is used. + + +getregtype([{regname}]) *getregtype()* + The result is a String, which is type of register {regname}. + The value will be one of: + "v" for |characterwise| text + "V" for |linewise| text + "{width}" for |blockwise-visual| text + 0 for an empty or unknown register + is one character with value 0x16. + If {regname} is not specified, |v:register| is used. + +gettabvar({tabnr}, {varname}) *gettabvar()* + Get the value of a tab-local variable {varname} in tab page + {tabnr}. |t:var| + Tabs are numbered starting with one. + Note that the name without "t:" must be used. + +gettabwinvar({tabnr}, {winnr}, {varname}) *gettabwinvar()* + Get the value of window-local variable {varname} in window + {winnr} in tab page {tabnr}. + When {varname} starts with "&" get the value of a window-local + option. + Tabs are numbered starting with one. For the current tabpage + use |getwinvar()|. + When {winnr} is zero the current window is used. + This also works for a global option, buffer-local option and + window-local option, but it doesn't work for a global variable + or buffer-local variable. + When {varname} is empty a dictionary with all window-local + variables is returned. + Note that {varname} must be the name without "w:". + Examples: > + :let list_is_on = gettabwinvar(1, 2, '&list') + :echo "myvar = " . gettabwinvar(3, 1, 'myvar') +< + *getwinposx()* +getwinposx() The result is a Number, which is the X coordinate in pixels of + the left hand side of the GUI Vim window. The result will be + -1 if the information is not available. + + *getwinposy()* +getwinposy() The result is a Number, which is the Y coordinate in pixels of + the top of the GUI Vim window. The result will be -1 if the + information is not available. + +getwinvar({winnr}, {varname}) *getwinvar()* + Like |gettabwinvar()| for the current tabpage. + Examples: > + :let list_is_on = getwinvar(2, '&list') + :echo "myvar = " . getwinvar(1, 'myvar') +< +glob({expr} [, {flag}]) *glob()* + Expand the file wildcards in {expr}. See |wildcards| for the + use of special characters. + The result is a String. + When there are several matches, they are separated by + characters. + Unless the optional {flag} argument is given and is non-zero, + the 'suffixes' and 'wildignore' options apply: Names matching + one of the patterns in 'wildignore' will be skipped and + 'suffixes' affect the ordering of matches. + If the expansion fails, the result is an empty string. + A name for a non-existing file is not included. + + For most systems backticks can be used to get files names from + any external command. Example: > + :let tagfiles = glob("`find . -name tags -print`") + :let &tags = substitute(tagfiles, "\n", ",", "g") +< The result of the program inside the backticks should be one + item per line. Spaces inside an item are allowed. + + See |expand()| for expanding special Vim variables. See + |system()| for getting the raw output of an external command. + +globpath({path}, {expr} [, {flag}]) *globpath()* + Perform glob() on all directories in {path} and concatenate + the results. Example: > + :echo globpath(&rtp, "syntax/c.vim") +< {path} is a comma-separated list of directory names. Each + directory name is prepended to {expr} and expanded like with + |glob()|. A path separator is inserted when needed. + To add a comma inside a directory name escape it with a + backslash. Note that on MS-Windows a directory may have a + trailing backslash, remove it if you put a comma after it. + If the expansion fails for one of the directories, there is no + error message. + Unless the optional {flag} argument is given and is non-zero, + the 'suffixes' and 'wildignore' options apply: Names matching + one of the patterns in 'wildignore' will be skipped and + 'suffixes' affect the ordering of matches. + + The "**" item can be used to search in a directory tree. + For example, to find all "README.txt" files in the directories + in 'runtimepath' and below: > + :echo globpath(&rtp, "**/README.txt") +< Upwards search and limiting the depth of "**" is not + supported, thus using 'path' will not always work properly. + + *has()* +has({feature}) The result is a Number, which is 1 if the feature {feature} is + supported, zero otherwise. The {feature} argument is a + string. See |feature-list| below. + Also see |exists()|. + + +has_key({dict}, {key}) *has_key()* + The result is a Number, which is 1 if |Dictionary| {dict} has + an entry with key {key}. Zero otherwise. + +haslocaldir() *haslocaldir()* + The result is a Number, which is 1 when the current + window has set a local path via |:lcd|, and 0 otherwise. + +hasmapto({what} [, {mode} [, {abbr}]]) *hasmapto()* + The result is a Number, which is 1 if there is a mapping that + contains {what} in somewhere in the rhs (what it is mapped to) + and this mapping exists in one of the modes indicated by + {mode}. + When {abbr} is there and it is non-zero use abbreviations + instead of mappings. Don't forget to specify Insert and/or + Command-line mode. + Both the global mappings and the mappings local to the current + buffer are checked for a match. + If no matching mapping is found 0 is returned. + The following characters are recognized in {mode}: + n Normal mode + v Visual mode + o Operator-pending mode + i Insert mode + l Language-Argument ("r", "f", "t", etc.) + c Command-line mode + When {mode} is omitted, "nvo" is used. + + This function is useful to check if a mapping already exists + to a function in a Vim script. Example: > + :if !hasmapto('\ABCdoit') + : map d \ABCdoit + :endif +< This installs the mapping to "\ABCdoit" only if there isn't + already a mapping to "\ABCdoit". + +histadd({history}, {item}) *histadd()* + Add the String {item} to the history {history} which can be + one of: *hist-names* + "cmd" or ":" command line history + "search" or "/" search pattern history + "expr" or "=" typed expression history + "input" or "@" input line history + If {item} does already exist in the history, it will be + shifted to become the newest entry. + The result is a Number: 1 if the operation was successful, + otherwise 0 is returned. + + Example: > + :call histadd("input", strftime("%Y %b %d")) + :let date=input("Enter date: ") +< This function is not available in the |sandbox|. + +histdel({history} [, {item}]) *histdel()* + Clear {history}, i.e. delete all its entries. See |hist-names| + for the possible values of {history}. + + If the parameter {item} evaluates to a String, it is used as a + regular expression. All entries matching that expression will + be removed from the history (if there are any). + Upper/lowercase must match, unless "\c" is used |/\c|. + If {item} evaluates to a Number, it will be interpreted as + an index, see |:history-indexing|. The respective entry will + be removed if it exists. + + The result is a Number: 1 for a successful operation, + otherwise 0 is returned. + + Examples: + Clear expression register history: > + :call histdel("expr") +< + Remove all entries starting with "*" from the search history: > + :call histdel("/", '^\*') +< + The following three are equivalent: > + :call histdel("search", histnr("search")) + :call histdel("search", -1) + :call histdel("search", '^'.histget("search", -1).'$') +< + To delete the last search pattern and use the last-but-one for + the "n" command and 'hlsearch': > + :call histdel("search", -1) + :let @/ = histget("search", -1) + +histget({history} [, {index}]) *histget()* + The result is a String, the entry with Number {index} from + {history}. See |hist-names| for the possible values of + {history}, and |:history-indexing| for {index}. If there is + no such entry, an empty String is returned. When {index} is + omitted, the most recent item from the history is used. + + Examples: + Redo the second last search from history. > + :execute '/' . histget("search", -2) + +< Define an Ex command ":H {num}" that supports re-execution of + the {num}th entry from the output of |:history|. > + :command -nargs=1 H execute histget("cmd", 0+) +< +histnr({history}) *histnr()* + The result is the Number of the current entry in {history}. + See |hist-names| for the possible values of {history}. + If an error occurred, -1 is returned. + + Example: > + :let inp_index = histnr("expr") +< +hlexists({name}) *hlexists()* + The result is a Number, which is non-zero if a highlight group + called {name} exists. This is when the group has been + defined in some way. Not necessarily when highlighting has + been defined for it, it may also have been used for a syntax + item. + *highlight_exists()* + Obsolete name: highlight_exists(). + + *hlID()* +hlID({name}) The result is a Number, which is the ID of the highlight group + with name {name}. When the highlight group doesn't exist, + zero is returned. + This can be used to retrieve information about the highlight + group. For example, to get the background color of the + "Comment" group: > + :echo synIDattr(synIDtrans(hlID("Comment")), "bg") +< *highlightID()* + Obsolete name: highlightID(). + +hostname() *hostname()* + The result is a String, which is the name of the machine on + which Vim is currently running. Machine names greater than + 256 characters long are truncated. + +iconv({expr}, {from}, {to}) *iconv()* + The result is a String, which is the text {expr} converted + from encoding {from} to encoding {to}. + When the conversion completely fails an empty string is + returned. When some characters could not be converted they + are replaced with "?". + The encoding names are whatever the iconv() library function + can accept, see ":!man 3 iconv". + Most conversions require Vim to be compiled with the |+iconv| + feature. Otherwise only UTF-8 to latin1 conversion and back + can be done. + This can be used to display messages with special characters, + no matter what 'encoding' is set to. Write the message in + UTF-8 and use: > + echo iconv(utf8_str, "utf-8", &enc) +< Note that Vim uses UTF-8 for all Unicode encodings, conversion + from/to UCS-2 is automatically changed to use UTF-8. You + cannot use UCS-2 in a string anyway, because of the NUL bytes. + {only available when compiled with the |+multi_byte| feature} + + *indent()* +indent({lnum}) The result is a Number, which is indent of line {lnum} in the + current buffer. The indent is counted in spaces, the value + of 'tabstop' is relevant. {lnum} is used just like in + |getline()|. + When {lnum} is invalid -1 is returned. + + +index({list}, {expr} [, {start} [, {ic}]]) *index()* + Return the lowest index in |List| {list} where the item has a + value equal to {expr}. There is no automatic conversion, so + the String "4" is different from the Number 4. And the number + 4 is different from the Float 4.0. The value of 'ignorecase' + is not used here, case always matters. + If {start} is given then start looking at the item with index + {start} (may be negative for an item relative to the end). + When {ic} is given and it is non-zero, ignore case. Otherwise + case must match. + -1 is returned when {expr} is not found in {list}. + Example: > + :let idx = index(words, "the") + :if index(numbers, 123) >= 0 + + +input({prompt} [, {text} [, {completion}]]) *input()* + The result is a String, which is whatever the user typed on + the command-line. The {prompt} argument is either a prompt + string, or a blank string (for no prompt). A '\n' can be used + in the prompt to start a new line. + The highlighting set with |:echohl| is used for the prompt. + The input is entered just like a command-line, with the same + editing commands and mappings. There is a separate history + for lines typed for input(). + Example: > + :if input("Coffee or beer? ") == "beer" + : echo "Cheers!" + :endif +< + If the optional {text} argument is present and not empty, this + is used for the default reply, as if the user typed this. + Example: > + :let color = input("Color? ", "white") + +< The optional {completion} argument specifies the type of + completion supported for the input. Without it completion is + not performed. The supported completion types are the same as + that can be supplied to a user-defined command using the + "-complete=" argument. Refer to |:command-completion| for + more information. Example: > + let fname = input("File: ", "", "file") +< + NOTE: This function must not be used in a startup file, for + the versions that only run in GUI mode (e.g., the Win32 GUI). + Note: When input() is called from within a mapping it will + consume remaining characters from that mapping, because a + mapping is handled like the characters were typed. + Use |inputsave()| before input() and |inputrestore()| + after input() to avoid that. Another solution is to avoid + that further characters follow in the mapping, e.g., by using + |:execute| or |:normal|. + + Example with a mapping: > + :nmap \x :call GetFoo():exe "/" . Foo + :function GetFoo() + : call inputsave() + : let g:Foo = input("enter search pattern: ") + : call inputrestore() + :endfunction + +inputdialog({prompt} [, {text} [, {cancelreturn}]]) *inputdialog()* + Like |input()|, but when the GUI is running and text dialogs + are supported, a dialog window pops up to input the text. + Example: > + :let n = inputdialog("value for shiftwidth", &sw) + :if n != "" + : let &sw = n + :endif +< When the dialog is cancelled {cancelreturn} is returned. When + omitted an empty string is returned. + Hitting works like pressing the OK button. Hitting + works like pressing the Cancel button. + NOTE: Command-line completion is not supported. + +inputlist({textlist}) *inputlist()* + {textlist} must be a |List| of strings. This |List| is + displayed, one string per line. The user will be prompted to + enter a number, which is returned. + The user can also select an item by clicking on it with the + mouse. For the first string 0 is returned. When clicking + above the first item a negative number is returned. When + clicking on the prompt one more than the length of {textlist} + is returned. + Make sure {textlist} has less than 'lines' entries, otherwise + it won't work. It's a good idea to put the entry number at + the start of the string. And put a prompt in the first item. + Example: > + let color = inputlist(['Select color:', '1. red', + \ '2. green', '3. blue']) + +inputrestore() *inputrestore()* + Restore typeahead that was saved with a previous |inputsave()|. + Should be called the same number of times inputsave() is + called. Calling it more often is harmless though. + Returns 1 when there is nothing to restore, 0 otherwise. + +inputsave() *inputsave()* + Preserve typeahead (also from mappings) and clear it, so that + a following prompt gets input from the user. Should be + followed by a matching inputrestore() after the prompt. Can + be used several times, in which case there must be just as + many inputrestore() calls. + Returns 1 when out of memory, 0 otherwise. + +inputsecret({prompt} [, {text}]) *inputsecret()* + This function acts much like the |input()| function with but + two exceptions: + a) the user's response will be displayed as a sequence of + asterisks ("*") thereby keeping the entry secret, and + b) the user's response will not be recorded on the input + |history| stack. + The result is a String, which is whatever the user actually + typed on the command-line in response to the issued prompt. + NOTE: Command-line completion is not supported. + +insert({list}, {item} [, {idx}]) *insert()* + Insert {item} at the start of |List| {list}. + If {idx} is specified insert {item} before the item with index + {idx}. If {idx} is zero it goes before the first item, just + like omitting {idx}. A negative {idx} is also possible, see + |list-index|. -1 inserts just before the last item. + Returns the resulting |List|. Examples: > + :let mylist = insert([2, 3, 5], 1) + :call insert(mylist, 4, -1) + :call insert(mylist, 6, len(mylist)) +< The last example can be done simpler with |add()|. + Note that when {item} is a |List| it is inserted as a single + item. Use |extend()| to concatenate |Lists|. + +isdirectory({directory}) *isdirectory()* + The result is a Number, which is non-zero when a directory + with the name {directory} exists. If {directory} doesn't + exist, or isn't a directory, the result is FALSE. {directory} + is any expression, which is used as a String. + +islocked({expr}) *islocked()* *E786* + The result is a Number, which is non-zero when {expr} is the + name of a locked variable. + {expr} must be the name of a variable, |List| item or + |Dictionary| entry, not the variable itself! Example: > + :let alist = [0, ['a', 'b'], 2, 3] + :lockvar 1 alist + :echo islocked('alist') " 1 + :echo islocked('alist[1]') " 0 + +< When {expr} is a variable that does not exist you get an error + message. Use |exists()| to check for existence. + +items({dict}) *items()* + Return a |List| with all the key-value pairs of {dict}. Each + |List| item is a list with two items: the key of a {dict} + entry and the value of this entry. The |List| is in arbitrary + order. + + +join({list} [, {sep}]) *join()* + Join the items in {list} together into one String. + When {sep} is specified it is put in between the items. If + {sep} is omitted a single space is used. + Note that {sep} is not added at the end. You might want to + add it there too: > + let lines = join(mylist, "\n") . "\n" +< String items are used as-is. |Lists| and |Dictionaries| are + converted into a string like with |string()|. + The opposite function is |split()|. + +keys({dict}) *keys()* + Return a |List| with all the keys of {dict}. The |List| is in + arbitrary order. + + *len()* *E701* +len({expr}) The result is a Number, which is the length of the argument. + When {expr} is a String or a Number the length in bytes is + used, as with |strlen()|. + When {expr} is a |List| the number of items in the |List| is + returned. + When {expr} is a |Dictionary| the number of entries in the + |Dictionary| is returned. + Otherwise an error is given. + + *libcall()* *E364* *E368* +libcall({libname}, {funcname}, {argument}) + Call function {funcname} in the run-time library {libname} + with single argument {argument}. + This is useful to call functions in a library that you + especially made to be used with Vim. Since only one argument + is possible, calling standard library functions is rather + limited. + The result is the String returned by the function. If the + function returns NULL, this will appear as an empty string "" + to Vim. + If the function returns a number, use libcallnr()! + If {argument} is a number, it is passed to the function as an + int; if {argument} is a string, it is passed as a + null-terminated string. + This function will fail in |restricted-mode|. + + libcall() allows you to write your own 'plug-in' extensions to + Vim without having to recompile the program. It is NOT a + means to call system functions! If you try to do so Vim will + very probably crash. + + For Win32, the functions you write must be placed in a DLL + and use the normal C calling convention (NOT Pascal which is + used in Windows System DLLs). The function must take exactly + one parameter, either a character pointer or a long integer, + and must return a character pointer or NULL. The character + pointer returned must point to memory that will remain valid + after the function has returned (e.g. in static data in the + DLL). If it points to allocated memory, that memory will + leak away. Using a static buffer in the function should work, + it's then freed when the DLL is unloaded. + + WARNING: If the function returns a non-valid pointer, Vim may + crash! This also happens if the function returns a number, + because Vim thinks it's a pointer. + For Win32 systems, {libname} should be the filename of the DLL + without the ".DLL" suffix. A full path is only required if + the DLL is not in the usual places. + For Unix: When compiling your own plugins, remember that the + object code must be compiled as position-independent ('PIC'). + {only in Win32 and some Unix versions, when the |+libcall| + feature is present} + Examples: > + :echo libcall("libc.so", "getenv", "HOME") +< + *libcallnr()* +libcallnr({libname}, {funcname}, {argument}) + Just like |libcall()|, but used for a function that returns an + int instead of a string. + {only in Win32 on some Unix versions, when the |+libcall| + feature is present} + Examples: > + :echo libcallnr("/usr/lib/libc.so", "getpid", "") + :call libcallnr("libc.so", "printf", "Hello World!\n") + :call libcallnr("libc.so", "sleep", 10) +< + *line()* +line({expr}) The result is a Number, which is the line number of the file + position given with {expr}. The accepted positions are: + . the cursor position + $ the last line in the current buffer + 'x position of mark x (if the mark is not set, 0 is + returned) + w0 first line visible in current window + w$ last line visible in current window + v In Visual mode: the start of the Visual area (the + cursor is the end). When not in Visual mode + returns the cursor position. Differs from |'<| in + that it's updated right away. + Note that a mark in another file can be used. The line number + then applies to another buffer. + To get the column number use |col()|. To get both use + |getpos()|. + Examples: > + line(".") line number of the cursor + line("'t") line number of mark t + line("'" . marker) line number of mark marker +< *last-position-jump* + This autocommand jumps to the last known position in a file + just after opening it, if the '" mark is set: > + :au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g`\"" | endif + +line2byte({lnum}) *line2byte()* + Return the byte count from the start of the buffer for line + {lnum}. This includes the end-of-line character, depending on + the 'fileformat' option for the current buffer. The first + line returns 1. + This can also be used to get the byte count for the line just + below the last line: > + line2byte(line("$") + 1) +< This is the file size plus one. + When {lnum} is invalid, or the |+byte_offset| feature has been + disabled at compile time, -1 is returned. + Also see |byte2line()|, |go| and |:goto|. + +lispindent({lnum}) *lispindent()* + Get the amount of indent for line {lnum} according the lisp + indenting rules, as with 'lisp'. + The indent is counted in spaces, the value of 'tabstop' is + relevant. {lnum} is used just like in |getline()|. + When {lnum} is invalid or Vim was not compiled the + |+lispindent| feature, -1 is returned. + +localtime() *localtime()* + Return the current time, measured as seconds since 1st Jan + 1970. See also |strftime()| and |getftime()|. + + +log({expr}) *log()* + Return the natural logarithm (base e) of {expr} as a |Float|. + {expr} must evaluate to a |Float| or a |Number| in the range + (0, inf]. + Examples: > + :echo log(10) +< 2.302585 > + :echo log(exp(5)) +< 5.0 + {only available when compiled with the |+float| feature} + + +log10({expr}) *log10()* + Return the logarithm of Float {expr} to base 10 as a |Float|. + {expr} must evaluate to a |Float| or a |Number|. + Examples: > + :echo log10(1000) +< 3.0 > + :echo log10(0.01) +< -2.0 + {only available when compiled with the |+float| feature} + +map({expr}, {string}) *map()* + {expr} must be a |List| or a |Dictionary|. + Replace each item in {expr} with the result of evaluating + {string}. + Inside {string} |v:val| has the value of the current item. + For a |Dictionary| |v:key| has the key of the current item + and for a |List| |v:key| has the index of the current item. + Example: > + :call map(mylist, '"> " . v:val . " <"') +< This puts "> " before and " <" after each item in "mylist". + + Note that {string} is the result of an expression and is then + used as an expression again. Often it is good to use a + |literal-string| to avoid having to double backslashes. You + still have to double ' quotes + + The operation is done in-place. If you want a |List| or + |Dictionary| to remain unmodified make a copy first: > + :let tlist = map(copy(mylist), ' & . "\t"') + +< Returns {expr}, the |List| or |Dictionary| that was filtered. + When an error is encountered while evaluating {string} no + further items in {expr} are processed. + + +maparg({name}[, {mode} [, {abbr} [, {dict}]]]) *maparg()* + When {dict} is omitted or zero: Return the rhs of mapping + {name} in mode {mode}. The returned String has special + characters translated like in the output of the ":map" command + listing. + + When there is no mapping for {name}, an empty String is + returned. + + The {name} can have special key names, like in the ":map" + command. + + {mode} can be one of these strings: + "n" Normal + "v" Visual (including Select) + "o" Operator-pending + "i" Insert + "c" Cmd-line + "s" Select + "x" Visual + "l" langmap |language-mapping| + "" Normal, Visual and Operator-pending + When {mode} is omitted, the modes for "" are used. + + When {abbr} is there and it is non-zero use abbreviations + instead of mappings. + + When {dict} is there and it is non-zero return a dictionary + containing all the information of the mapping with the + following items: + "lhs" The {lhs} of the mapping. + "rhs" The {rhs} of the mapping as typed. + "silent" 1 for a |:map-silent| mapping, else 0. + "noremap" 1 if the {rhs} of the mapping is remappable. + "expr" 1 for an expression mapping (|:map-|). + "buffer" 1 for a buffer local mapping (|:map-local|). + "mode" Modes for which the mapping is defined. In + addition to the modes mentioned above, these + characters will be used: + " " Normal, Visual and Operator-pending + "!" Insert and Commandline mode + (|mapmpde-ic|) + "sid" the Script local ID, used for mappings + (||) + + The mappings local to the current buffer are checked first, + then the global mappings. + This function can be used to map a key even when it's already + mapped, and have it do the original mapping too. Sketch: > + exe 'nnoremap ==' . maparg('', 'n') + + +mapcheck({name}[, {mode} [, {abbr}]]) *mapcheck()* + Check if there is a mapping that matches with {name} in mode + {mode}. See |maparg()| for {mode} and special names in + {name}. + When {abbr} is there and it is non-zero use abbreviations + instead of mappings. + A match happens with a mapping that starts with {name} and + with a mapping which is equal to the start of {name}. + + matches mapping "a" "ab" "abc" ~ + mapcheck("a") yes yes yes + mapcheck("abc") yes yes yes + mapcheck("ax") yes no no + mapcheck("b") no no no + + The difference with maparg() is that mapcheck() finds a + mapping that matches with {name}, while maparg() only finds a + mapping for {name} exactly. + When there is no mapping that starts with {name}, an empty + String is returned. If there is one, the rhs of that mapping + is returned. If there are several mappings that start with + {name}, the rhs of one of them is returned. + The mappings local to the current buffer are checked first, + then the global mappings. + This function can be used to check if a mapping can be added + without being ambiguous. Example: > + :if mapcheck("_vv") == "" + : map _vv :set guifont=7x13 + :endif +< This avoids adding the "_vv" mapping when there already is a + mapping for "_v" or for "_vvv". + +match({expr}, {pat}[, {start}[, {count}]]) *match()* + When {expr} is a |List| then this returns the index of the + first item where {pat} matches. Each item is used as a + String, |Lists| and |Dictionaries| are used as echoed. + Otherwise, {expr} is used as a String. The result is a + Number, which gives the index (byte offset) in {expr} where + {pat} matches. + A match at the first character or |List| item returns zero. + If there is no match -1 is returned. + Example: > + :echo match("testing", "ing") " results in 4 + :echo match([1, 'x'], '\a') " results in 1 +< See |string-match| for how {pat} is used. + *strpbrk()* + Vim doesn't have a strpbrk() function. But you can do: > + :let sepidx = match(line, '[.,;: \t]') +< *strcasestr()* + Vim doesn't have a strcasestr() function. But you can add + "\c" to the pattern to ignore case: > + :let idx = match(haystack, '\cneedle') +< + If {start} is given, the search starts from byte index + {start} in a String or item {start} in a |List|. + The result, however, is still the index counted from the + first character/item. Example: > + :echo match("testing", "ing", 2) +< result is again "4". > + :echo match("testing", "ing", 4) +< result is again "4". > + :echo match("testing", "t", 2) +< result is "3". + For a String, if {start} > 0 then it is like the string starts + {start} bytes later, thus "^" will match at {start}. Except + when {count} is given, then it's like matches before the + {start} byte are ignored (this is a bit complicated to keep it + backwards compatible). + For a String, if {start} < 0, it will be set to 0. For a list + the index is counted from the end. + If {start} is out of range ({start} > strlen({expr}) for a + String or {start} > len({expr}) for a |List|) -1 is returned. + + When {count} is given use the {count}'th match. When a match + is found in a String the search for the next one starts one + character further. Thus this example results in 1: > + echo match("testing", "..", 0, 2) +< In a |List| the search continues in the next item. + Note that when {count} is added the way {start} works changes, + see above. + + See |pattern| for the patterns that are accepted. + The 'ignorecase' option is used to set the ignore-caseness of + 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|, + |:2match| or |:3match| command. + Return a |List| with two elements: + The name of the highlight group used + 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 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 successful, + 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 the match. Example: > + :echo matchend("testing", "ing") +< results in "7". + *strspn()* *strcspn()* + Vim doesn't have a strspn() or strcspn() function, but you can + do it with matchend(): > + :let span = matchend(line, '[a-zA-Z]') + :let span = matchend(line, '[^a-zA-Z]') +< Except that -1 is returned when there are no matches. + + The {start}, if given, has the same meaning as for |match()|. > + :echo matchend("testing", "ing", 2) +< results in "7". > + :echo matchend("testing", "ing", 5) +< result is "-1". + When {expr} is a |List| the result is equal to |match()|. + +matchlist({expr}, {pat}[, {start}[, {count}]]) *matchlist()* + Same as |match()|, but return a |List|. The first item in the + list is the matched string, same as what matchstr() would + return. Following items are submatches, like "\1", "\2", etc. + in |:substitute|. When an optional submatch didn't match an + empty string is used. Example: > + echo matchlist('acd', '\(a\)\?\(b\)\?\(c\)\?\(.*\)') +< Results in: ['acd', 'a', '', 'c', 'd', '', '', '', '', ''] + When there is no match an empty list is returned. + +matchstr({expr}, {pat}[, {start}[, {count}]]) *matchstr()* + Same as |match()|, but return the matched string. Example: > + :echo matchstr("testing", "ing") +< results in "ing". + When there is no match "" is returned. + The {start}, if given, has the same meaning as for |match()|. > + :echo matchstr("testing", "ing", 2) +< results in "ing". > + :echo matchstr("testing", "ing", 5) +< result is "". + When {expr} is a |List| then the matching item is returned. + The type isn't changed, it's not necessarily a String. + + *max()* +max({list}) Return the maximum value of all items in {list}. + If {list} is not a list or one of the items in {list} cannot + be used as a Number this results in an error. + An empty |List| results in zero. + + *min()* +min({list}) Return the minimum value of all items in {list}. + If {list} is not a list or one of the items in {list} cannot + be used as a Number this results in an error. + An empty |List| results in zero. + + *mkdir()* *E739* +mkdir({name} [, {path} [, {prot}]]) + Create directory {name}. + If {path} is "p" then intermediate directories are created as + necessary. Otherwise it must be "". + If {prot} is given it is used to set the protection bits of + the new directory. The default is 0755 (rwxr-xr-x: r/w for + the user readable for others). Use 0700 to make it unreadable + for others. This is only used for the last part of {name}. + Thus if you create /tmp/foo/bar then /tmp/foo will be created + with 0755. + Example: > + :call mkdir($HOME . "/tmp/foo/bar", "p", 0700) +< This function is not available in the |sandbox|. + Not available on all systems. To check use: > + :if exists("*mkdir") +< + *mode()* +mode([expr]) Return a string that indicates the current mode. + If [expr] is supplied and it evaluates to a non-zero Number or + a non-empty String (|non-zero-arg|), then the full mode is + returned, otherwise only the first letter is returned. Note + that " " and "0" are also non-empty strings. + + n Normal + no Operator-pending + v Visual by character + V Visual by line + CTRL-V Visual blockwise + s Select by character + S Select by line + CTRL-S Select blockwise + i Insert + R Replace |R| + Rv Virtual Replace |gR| + c Command-line + cv Vim Ex mode |gQ| + ce Normal Ex mode |Q| + r Hit-enter prompt + rm The -- more -- prompt + r? A |:confirm| query of some sort + ! Shell or external command is executing + This is useful in the 'statusline' option or when used + with |remote_expr()| In most other places it always returns + "c" or "n". + Also see |visualmode()|. + +mzeval({expr}) *mzeval()* + Evaluate MzScheme expression {expr} and return its result + convert to Vim data structures. + Numbers and strings are returned as they are. + Pairs (including lists and improper lists) and vectors are + returned as Vim |Lists|. + Hash tables are represented as Vim |Dictionary| type with keys + converted to strings. + All other types are converted to string with display function. + Examples: > + :mz (define l (list 1 2 3)) + :mz (define h (make-hash)) (hash-set! h "list" l) + :echo mzeval("l") + :echo mzeval("h") +< + {only available when compiled with the |+mzscheme| feature} + +nextnonblank({lnum}) *nextnonblank()* + Return the line number of the first line at or below {lnum} + that is not blank. Example: > + if getline(nextnonblank(1)) =~ "Java" +< When {lnum} is invalid or there is no non-blank line at or + below it, zero is returned. + See also |prevnonblank()|. + +nr2char({expr}) *nr2char()* + Return a string with a single character, which has the number + value {expr}. Examples: > + nr2char(64) returns "@" + nr2char(32) returns " " +< The current 'encoding' is used. Example for "utf-8": > + nr2char(300) returns I with bow character +< Note that a NUL character in the file is specified with + nr2char(10), because NULs are represented with newline + 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 and MS-Windows this is a unique number, until Vim + exits. On MS-DOS it's always zero. + + *getpos()* +getpos({expr}) Get the position for {expr}. For possible values of {expr} + see |line()|. + The result is a |List| with four numbers: + [bufnum, lnum, col, off] + "bufnum" is zero, unless a mark like '0 or 'A is used, then it + is the buffer number of the mark. + "lnum" and "col" are the position in the buffer. The first + column is 1. + The "off" number is zero, unless 'virtualedit' is used. Then + it is the offset in screen columns from the start of the + character. E.g., a position within a or after the last + character. + This can be used to save and restore the cursor position: > + let save_cursor = getpos(".") + MoveTheCursorAround + call setpos('.', save_cursor) +< Also see |setpos()|. + +pathshorten({expr}) *pathshorten()* + Shorten directory names in the path {expr} and return the + result. The tail, the file name, is kept as-is. The other + components in the path are reduced to single letters. Leading + '~' and '.' characters are kept. Example: > + :echo pathshorten('~/.vim/autoload/myfile.vim') +< ~/.v/a/myfile.vim ~ + It doesn't matter if the path exists or not. + +pow({x}, {y}) *pow()* + Return the power of {x} to the exponent {y} as a |Float|. + {x} and {y} must evaluate to a |Float| or a |Number|. + Examples: > + :echo pow(3, 3) +< 27.0 > + :echo pow(2, 16) +< 65536.0 > + :echo pow(32, 0.20) +< 2.0 + {only available when compiled with the |+float| feature} + +prevnonblank({lnum}) *prevnonblank()* + Return the line number of the first line at or above {lnum} + that is not blank. Example: > + let ind = indent(prevnonblank(v:lnum - 1)) +< When {lnum} is invalid or there is no non-blank line at or + above it, zero is returned. + Also see |nextnonblank()|. + + +printf({fmt}, {expr1} ...) *printf()* + Return a String with {fmt}, where "%" items are replaced by + the formatted form of their respective arguments. Example: > + printf("%4d: E%d %.30s", lnum, errno, msg) +< May result in: + " 99: E42 asdfasdfasdfasdfasdfasdfasdfas" ~ + + Often used items are: + %s string + %6s string right-aligned in 6 bytes + %.9s string truncated to 9 bytes + %c single byte + %d decimal number + %5d decimal number padded with spaces to 5 characters + %x hex number + %04x hex number padded with zeros to at least 4 characters + %X hex number using upper case letters + %o octal number + %f floating point number in the form 123.456 + %e floating point number in the form 1.234e3 + %E floating point number in the form 1.234E3 + %g floating point number, as %f or %e depending on value + %G floating point number, as %f or %E depending on value + %% the % character itself + + Conversion specifications start with '%' and end with the + conversion type. All other characters are copied unchanged to + the result. + + The "%" starts a conversion specification. The following + arguments appear in sequence: + + % [flags] [field-width] [.precision] type + + flags + Zero or more of the following flags: + + # The value should be converted to an "alternate + form". For c, d, and s conversions, this option + has no effect. For o conversions, the precision + of the number is increased to force the first + character of the output string to a zero (except + if a zero value is printed with an explicit + precision of zero). + For x and X conversions, a non-zero result has + the string "0x" (or "0X" for X conversions) + prepended to it. + + 0 (zero) Zero padding. For all conversions the converted + value is padded on the left with zeros rather + than blanks. If a precision is given with a + numeric conversion (d, o, x, and X), the 0 flag + is ignored. + + - A negative field width flag; the converted value + is to be left adjusted on the field boundary. + The converted value is padded on the right with + blanks, rather than on the left with blanks or + zeros. A - overrides a 0 if both are given. + + ' ' (space) A blank should be left before a positive + number produced by a signed conversion (d). + + + A sign must always be placed before a number + produced by a signed conversion. A + overrides + a space if both are used. + + field-width + An optional decimal digit string specifying a minimum + field width. If the converted value has fewer bytes + than the field width, it will be padded with spaces on + the left (or right, if the left-adjustment flag has + been given) to fill out the field width. + + .precision + An optional precision, in the form of a period '.' + followed by an optional digit string. If the digit + string is omitted, the precision is taken as zero. + This gives the minimum number of digits to appear for + d, o, x, and X conversions, or the maximum number of + bytes to be printed from a string for s conversions. + For floating point it is the number of digits after + the decimal point. + + type + A character that specifies the type of conversion to + be applied, see below. + + A field width or precision, or both, may be indicated by an + asterisk '*' instead of a digit string. In this case, a + Number argument supplies the field width or precision. A + negative field width is treated as a left adjustment flag + followed by a positive field width; a negative precision is + treated as though it were missing. Example: > + :echo printf("%d: %.*s", nr, width, line) +< This limits the length of the text used from "line" to + "width" bytes. + + The conversion specifiers and their meanings are: + + *printf-d* *printf-o* *printf-x* *printf-X* + doxX The Number argument is converted to signed decimal + (d), unsigned octal (o), or unsigned hexadecimal (x + and X) notation. The letters "abcdef" are used for + x conversions; the letters "ABCDEF" are used for X + conversions. + The precision, if any, gives the minimum number of + digits that must appear; if the converted value + requires fewer digits, it is padded on the left with + zeros. + In no case does a non-existent or small field width + cause truncation of a numeric field; if the result of + a conversion is wider than the field width, the field + is expanded to contain the conversion result. + + *printf-c* + c The Number argument is converted to a byte, and the + resulting character is written. + + *printf-s* + s The text of the String argument is used. If a + precision is specified, no more bytes than the number + specified are used. + + *printf-f* *E807* + f The Float argument is converted into a string of the + form 123.456. The precision specifies the number of + digits after the decimal point. When the precision is + zero the decimal point is omitted. When the precision + is not specified 6 is used. A really big number + (out of range or dividing by zero) results in "inf". + "0.0 / 0.0" results in "nan". + Example: > + echo printf("%.2f", 12.115) +< 12.12 + Note that roundoff depends on the system libraries. + Use |round()| when in doubt. + + *printf-e* *printf-E* + e E The Float argument is converted into a string of the + form 1.234e+03 or 1.234E+03 when using 'E'. The + precision specifies the number of digits after the + decimal point, like with 'f'. + + *printf-g* *printf-G* + g G The Float argument is converted like with 'f' if the + value is between 0.001 (inclusive) and 10000000.0 + (exclusive). Otherwise 'e' is used for 'g' and 'E' + for 'G'. When no precision is specified superfluous + zeroes and '+' signs are removed, except for the zero + immediately after the decimal point. Thus 10000000.0 + results in 1.0e7. + + *printf-%* + % A '%' is written. No argument is converted. The + complete conversion specification is "%%". + + When a Number argument is expected a String argument is also + accepted and automatically converted. + When a Float or String argument is expected a Number argument + is also accepted and automatically converted. + Any other argument type results in an error message. + + *E766* *E767* + The number of {exprN} arguments must exactly match the number + of "%" items. If there are not sufficient or too many + arguments an error is given. Up to 18 arguments can be used. + + +pumvisible() *pumvisible()* + Returns non-zero when the popup menu is visible, zero + otherwise. See |ins-completion-menu|. + This can be used to avoid some things that would remove the + popup menu. + + *E726* *E727* +range({expr} [, {max} [, {stride}]]) *range()* + Returns a |List| with Numbers: + - If only {expr} is specified: [0, 1, ..., {expr} - 1] + - If {max} is specified: [{expr}, {expr} + 1, ..., {max}] + - If {stride} is specified: [{expr}, {expr} + {stride}, ..., + {max}] (increasing {expr} with {stride} each time, not + producing a value past {max}). + When the maximum is one before the start the result is an + empty list. When the maximum is more than one before the + start this is an error. + Examples: > + range(4) " [0, 1, 2, 3] + range(2, 4) " [2, 3, 4] + range(2, 9, 3) " [2, 5, 8] + range(2, -2, -1) " [2, 1, 0, -1, -2] + range(0) " [] + range(2, 0) " error! +< + *readfile()* +readfile({fname} [, {binary} [, {max}]]) + Read file {fname} and return a |List|, each line of the file + as an item. Lines broken at NL characters. Macintosh files + separated with CR will result in a single long line (unless a + NL appears somewhere). + All NUL characters are replaced with a NL character. + When {binary} is equal to "b" binary mode is used: + - When the last line ends in a NL an extra empty list item is + added. + - No CR characters are removed. + Otherwise: + - CR characters that appear before a NL are removed. + - Whether the last line ends in a NL or not does not matter. + - When 'encoding' is Unicode any UTF-8 byte order mark is + removed from the text. + When {max} is given this specifies the maximum number of lines + to be read. Useful if you only want to check the first ten + lines of a file: > + :for line in readfile(fname, '', 10) + : if line =~ 'Date' | echo line | endif + :endfor +< When {max} is negative -{max} lines from the end of the file + are returned, or as many as there are. + When {max} is zero the result is an empty list. + Note that without {max} the whole file is read into memory. + Also note that there is no recognition of encoding. Read a + file into a buffer if you need to. + When the file can't be opened an error message is given and + the result is an empty list. + Also see |writefile()|. + +reltime([{start} [, {end}]]) *reltime()* + Return an item that represents a time value. The format of + the item depends on the system. It can be passed to + |reltimestr()| to convert it to a string. + Without an argument it returns the current time. + With one argument is returns the time passed since the time + specified in the argument. + With two arguments it returns the time passed between {start} + and {end}. + The {start} and {end} arguments must be values returned by + reltime(). + {only available when compiled with the |+reltime| feature} + +reltimestr({time}) *reltimestr()* + Return a String that represents the time value of {time}. + This is the number of seconds, a dot and the number of + microseconds. Example: > + let start = reltime() + call MyFunction() + echo reltimestr(reltime(start)) +< Note that overhead for the commands will be added to the time. + The accuracy depends on the system. + Leading spaces are used to make the string align nicely. You + can use split() to remove it. > + echo split(reltimestr(reltime(start)))[0] +< Also see |profiling|. + {only available when compiled with the |+reltime| feature} + + *remote_expr()* *E449* +remote_expr({server}, {string} [, {idvar}]) + Send the {string} to {server}. The string is sent as an + expression and the result is returned after evaluation. + The result must be a String or a |List|. A |List| is turned + into a String by joining the items with a line break in + between (not at the end), like with join(expr, "\n"). + If {idvar} is present, it is taken as the name of a + variable and a {serverid} for later use with + remote_read() is stored there. + See also |clientserver| |RemoteReply|. + This function is not available in the |sandbox|. + {only available when compiled with the |+clientserver| feature} + Note: Any errors will cause a local error message to be issued + and the result will be the empty string. + Examples: > + :echo remote_expr("gvim", "2+2") + :echo remote_expr("gvim1", "b:current_syntax") +< + +remote_foreground({server}) *remote_foreground()* + Move the Vim server with the name {server} to the foreground. + This works like: > + remote_expr({server}, "foreground()") +< Except that on Win32 systems the client does the work, to work + around the problem that the OS doesn't always allow the server + to bring itself to the foreground. + Note: This does not restore the window if it was minimized, + like foreground() does. + This function is not available in the |sandbox|. + {only in the Win32, Athena, Motif and GTK GUI versions and the + Win32 console version} + + +remote_peek({serverid} [, {retvar}]) *remote_peek()* + Returns a positive number if there are available strings + from {serverid}. Copies any reply string into the variable + {retvar} if specified. {retvar} must be a string with the + name of a variable. + Returns zero if none are available. + Returns -1 if something is wrong. + See also |clientserver|. + This function is not available in the |sandbox|. + {only available when compiled with the |+clientserver| feature} + Examples: > + :let repl = "" + :echo "PEEK: ".remote_peek(id, "repl").": ".repl + +remote_read({serverid}) *remote_read()* + Return the oldest available reply from {serverid} and consume + it. It blocks until a reply is available. + See also |clientserver|. + This function is not available in the |sandbox|. + {only available when compiled with the |+clientserver| feature} + Example: > + :echo remote_read(id) +< + *remote_send()* *E241* +remote_send({server}, {string} [, {idvar}]) + Send the {string} to {server}. The string is sent as input + keys and the function returns immediately. At the Vim server + the keys are not mapped |:map|. + If {idvar} is present, it is taken as the name of a variable + and a {serverid} for later use with remote_read() is stored + there. + See also |clientserver| |RemoteReply|. + This function is not available in the |sandbox|. + {only available when compiled with the |+clientserver| feature} + Note: Any errors will be reported in the server and may mess + up the display. + Examples: > + :echo remote_send("gvim", ":DropAndReply ".file, "serverid"). + \ remote_read(serverid) + + :autocmd NONE RemoteReply * + \ echo remote_read(expand("")) + :echo remote_send("gvim", ":sleep 10 | echo ". + \ 'server2client(expand(""), "HELLO")') +< +remove({list}, {idx} [, {end}]) *remove()* + Without {end}: Remove the item at {idx} from |List| {list} and + return the item. + With {end}: Remove items from {idx} to {end} (inclusive) and + return a List with these items. When {idx} points to the same + item as {end} a list with one item is returned. When {end} + points to an item before {idx} this is an error. + See |list-index| for possible values of {idx} and {end}. + Example: > + :echo "last item: " . remove(mylist, -1) + :call remove(mylist, 0, 9) +remove({dict}, {key}) + Remove the entry from {dict} with key {key}. Example: > + :echo "removed " . remove(dict, "one") +< If there is no {key} in {dict} this is an error. + + Use |delete()| to remove a file. + +rename({from}, {to}) *rename()* + Rename the file by the name {from} to the name {to}. This + should also work to move files across file systems. The + result is a Number, which is 0 if the file was renamed + successfully, and non-zero when the renaming failed. + NOTE: If {to} exists it is overwritten without warning. + This function is not available in the |sandbox|. + +repeat({expr}, {count}) *repeat()* + Repeat {expr} {count} times and return the concatenated + result. Example: > + :let separator = repeat('-', 80) +< When {count} is zero or negative the result is empty. + When {expr} is a |List| the result is {expr} concatenated + {count} times. Example: > + :let longlist = repeat(['a', 'b'], 3) +< Results in ['a', 'b', 'a', 'b', 'a', 'b']. + + +resolve({filename}) *resolve()* *E655* + On MS-Windows, when {filename} is a shortcut (a .lnk file), + returns the path the shortcut points to in a simplified form. + On Unix, repeat resolving symbolic links in all path + components of {filename} and return the simplified result. + To cope with link cycles, resolving of symbolic links is + stopped after 100 iterations. + On other systems, return the simplified {filename}. + The simplification step is done as by |simplify()|. + resolve() keeps a leading path component specifying the + current directory (provided the result is still a relative + path name) and also keeps a trailing path separator. + + *reverse()* +reverse({list}) Reverse the order of items in {list} in-place. Returns + {list}. + If you want a list to remain unmodified make a copy first: > + :let revlist = reverse(copy(mylist)) + +round({expr}) *round()* + Round off {expr} to the nearest integral value and return it + as a |Float|. If {expr} lies halfway between two integral + values, then use the larger one (away from zero). + {expr} must evaluate to a |Float| or a |Number|. + Examples: > + echo round(0.456) +< 0.0 > + echo round(4.5) +< 5.0 > + echo round(-4.5) +< -5.0 + {only available when compiled with the |+float| feature} + + +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). + + {flags} is a String, which can contain these character flags: + 'b' search backward instead of forward + 'c' accept a match at the cursor position + 'e' move to the End of the match + 'n' do Not move the cursor + 'p' return number of matching sub-pattern (see below) + 's' set the ' mark at the previous location of the cursor + 'w' wrap around the end of the file + 'W' don't wrap around the end of the file + If neither 'w' or 'W' is given, the 'wrapscan' option applies. + + If the 's' flag is supplied, the ' mark is set, only if the + cursor is moved. The 's' flag cannot be combined with the 'n' + flag. + + 'ignorecase', 'smartcase' and 'magic' are used. + + When the {stopline} argument is given then the search stops + after searching this line. This is useful to restrict the + search to a range of lines. Examples: > + let match = search('(', 'b', line("w0")) + 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. + When a match has been found its line number is returned. + *search()-sub-match* + With the 'p' flag the returned value is one more than the + first sub-match in \(\). One if none of them matched but the + whole pattern did match. + To get the column number too use |searchpos()|. + + The cursor will be positioned at the match, unless the 'n' + flag is used. + + Example (goes over all files in the argument list): > + :let n = 1 + :while n <= argc() " loop over all files in arglist + : exe "argument " . n + : " start at the last char in the file and wrap for the + : " first search to find match at start of file + : normal G$ + : let flags = "w" + : while search("foo", flags) > 0 + : s/foo/bar/g + : let flags = "W" + : endwhile + : update " write the file if modified + : let n = n + 1 + :endwhile +< + Example for using some flags: > + :echo search('\ + if searchdecl('myvar') == 0 + echo getline('.') + endif +< + *searchpair()* +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. + The search starts at the cursor. The default is to search + forward, include 'b' in {flags} to search backward. + If a match is found, the cursor is positioned at it and the + line number is returned. If no match is found 0 or -1 is + returned and the cursor doesn't move. No error message is + given. + + {start}, {middle} and {end} are patterns, see |pattern|. They + must not contain \( \) pairs. Use of \%( \) is allowed. When + {middle} is not empty, it is found when searching from either + direction, but only when not in a nested start-end pair. A + typical use is: > + searchpair('\', '\', '\') +< By leaving {middle} empty the "else" is skipped. + + {flags} 'b', 'c', 'n', 's', 'w' and 'W' are used like with + |search()|. Additionally: + 'r' Repeat until no more matches found; will find the + outer pair. Implies the 'W' flag. + 'm' Return number of matches instead of line number with + the match; will be > 1 when 'r' is used. + Note: it's nearly always a good idea to use the 'W' flag, to + avoid wrapping around the end of the file. + + When a match for {start}, {middle} or {end} is found, the + {skip} expression is evaluated with the cursor positioned on + the start of the match. It should return non-zero if this + match is to be skipped. E.g., because it is inside a comment + or a string. + When {skip} is omitted or empty, every match is accepted. + When evaluating {skip} causes an error the search is aborted + and -1 returned. + + For {stopline} and {timeout} see |search()|. + + The value of 'ignorecase' is used. 'magic' is ignored, the + patterns are used like it's on. + + The search starts exactly at the cursor. A match with + {start}, {middle} or {end} at the next character, in the + direction of searching, is the first one found. Example: > + if 1 + if 2 + endif 2 + endif 1 +< When starting at the "if 2", with the cursor on the "i", and + searching forwards, the "endif 2" is found. When starting on + the character just before the "if 2", the "endif 1" will be + found. That's because the "if 2" will be found first, and + then this is considered to be a nested if/endif from "if 2" to + "endif 2". + When searching backwards and {end} is more than one character, + it may be useful to put "\zs" at the end of the pattern, so + that when the cursor is inside a match with the end it finds + the matching start. + + Example, to find the "endif" command in a Vim script: > + + :echo searchpair('\', '\', '\', 'W', + \ 'getline(".") =~ "^\\s*\""') + +< The cursor must be at or after the "if" for which a match is + to be found. Note that single-quote strings are used to avoid + having to double the backslashes. The skip expression only + catches comments at the start of a line, not after a command. + Also, a word "en" or "if" halfway a line is considered a + match. + Another example, to search for the matching "{" of a "}": > + + :echo searchpair('{', '', '}', 'bW') + +< This works when the cursor is at or before the "}" for which a + match is to be found. To reject matches that syntax + highlighting recognized as strings: > + + :echo searchpair('{', '', '}', 'bW', + \ 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string"') +< + *searchpairpos()* +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 + the column position of the match. If no match is found, + returns [0, 0]. > + + :let [lnum,col] = searchpairpos('{', '', '}', 'n') +< + See |match-parens| for a bigger and more useful example. + +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 + the column position of the match. If no match is found, + returns [0, 0]. + Example: > + :let [lnum, col] = searchpos('mypattern', 'n') + +< When the 'p' flag is given then there is an extra item with + the sub-pattern match number |search()-sub-match|. Example: > + :let [lnum, col, submatch] = searchpos('\(\l\)\|\(\u\)', 'np') +< In this example "submatch" is 2 when a lowercase letter is + found |/\l|, 3 when an uppercase letter is found |/\u|. + +server2client( {clientid}, {string}) *server2client()* + Send a reply string to {clientid}. The most recent {clientid} + that sent a string can be retrieved with expand(""). + {only available when compiled with the |+clientserver| feature} + Note: + This id has to be stored before the next command can be + received. I.e. before returning from the received command and + before calling any commands that waits for input. + See also |clientserver|. + Example: > + :echo server2client(expand(""), "HELLO") +< +serverlist() *serverlist()* + Return a list of available server names, one per line. + When there are no servers or the information is not available + an empty string is returned. See also |clientserver|. + {only available when compiled with the |+clientserver| feature} + Example: > + :echo serverlist() +< +setbufvar({expr}, {varname}, {val}) *setbufvar()* + Set option or local variable {varname} in buffer {expr} to + {val}. + This also works for a global or local window option, but it + doesn't work for a global or local window variable. + For a local window option the global value is unchanged. + For the use of {expr}, see |bufname()| above. + Note that the variable name without "b:" must be used. + Examples: > + :call setbufvar(1, "&mod", 1) + :call setbufvar("todo", "myvar", "foobar") +< This function is not available in the |sandbox|. + +setcmdpos({pos}) *setcmdpos()* + Set the cursor position in the command line to byte position + {pos}. The first position is 1. + Use |getcmdpos()| to obtain the current position. + Only works while editing the command line, thus you must use + |c_CTRL-\_e|, |c_CTRL-R_=| or |c_CTRL-R_CTRL-R| with '='. For + |c_CTRL-\_e| and |c_CTRL-R_CTRL-R| with '=' the position is + set after the command line is set to the expression. For + |c_CTRL-R_=| it is set after evaluating the expression but + before inserting the resulting text. + When the number is too big the cursor is put at the end of the + line. A number smaller than one has undefined results. + Returns 0 when successful, 1 when not editing the command + line. + +setline({lnum}, {text}) *setline()* + Set line {lnum} of the current buffer to {text}. + {lnum} is used like with |getline()|. + When {lnum} is just below the last line the {text} will be + added as a new line. + If this succeeds, 0 is returned. If this fails (most likely + because {lnum} is invalid) 1 is returned. Example: > + :call setline(5, strftime("%c")) +< When {text} is a |List| then line {lnum} and following lines + will be set to the items in the list. Example: > + :call setline(5, ['aaa', 'bbb', 'ccc']) +< This is equivalent to: > + :for [n, l] in [[5, 6, 7], ['aaa', 'bbb', 'ccc']] + : call setline(n, l) + :endfor +< Note: The '[ and '] marks are not set. + +setloclist({nr}, {list} [, {action}]) *setloclist()* + Create or replace or add to the location list for window {nr}. + 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()|. + Also see |location-list|. + +setmatches({list}) *setmatches()* + Restores a list of matches saved by |getmatches()|. Returns 0 + if successful, otherwise -1. All current matches are cleared + before the list is restored. See example for |getmatches()|. + + *setpos()* +setpos({expr}, {list}) + Set the position for {expr}. Possible values: + . the cursor + 'x mark x + + {list} must be a |List| with four numbers: + [bufnum, lnum, col, off] + + "bufnum" is the buffer number. Zero can be used for the + current buffer. Setting the cursor is only possible for + the current buffer. To set a mark in another buffer you can + use the |bufnr()| function to turn a file name into a buffer + number. + Does not change the jumplist. + + "lnum" and "col" are the position in the buffer. The first + column is 1. Use a zero "lnum" to delete a mark. If "col" is + smaller than 1 then 1 is used. + + The "off" number is only used when 'virtualedit' is set. Then + it is the offset in screen columns from the start of the + 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 + vertically. See |winrestview()| for that. + + +setqflist({list} [, {action}]) *setqflist()* + Create or replace or add to the quickfix list using the items + in {list}. Each item in {list} is a dictionary. + Non-dictionary items in {list} are ignored. Each dictionary + item can contain the following entries: + + bufnr buffer number; must be the number of a valid + buffer + filename name of a file; only used when "bufnr" is not + present or it is invalid. + lnum line number in the file + pattern search pattern used to locate the error + col column number + vcol when non-zero: "col" is visual column + when zero: "col" is byte index + nr error number + text description of the error + type single-character error type, 'E', 'W', etc. + + The "col", "vcol", "nr", "type" and "text" entries are + optional. Either "lnum" or "pattern" entry can be used to + locate a matching error line. + If the "filename" and "bufnr" entries are not present or + neither the "lnum" or "pattern" entries are present, then the + item will not be handled as an error line. + If both "pattern" and "lnum" are present then "pattern" will + be used. + If you supply an empty {list}, the quickfix list will be + cleared. + Note that the list is not exactly the same as what + |getqflist()| returns. + + If {action} is set to 'a', then the items from {list} are + added to the existing quickfix list. If there is no existing + list, then a new list is created. If {action} is set to 'r', + then the items from the current quickfix list are replaced + with the items from {list}. If {action} is not present or is + set to ' ', then a new list is created. + + Returns zero for success, -1 for failure. + + This function can be used to create a quickfix list + independent of the 'errorformat' setting. Use a command like + ":cc 1" to jump to the first position. + + + *setreg()* +setreg({regname}, {value} [,{options}]) + Set the register {regname} to {value}. + If {options} contains "a" or {regname} is upper case, + then the value is appended. + {options} can also contain a register type specification: + "c" or "v" |characterwise| mode + "l" or "V" |linewise| mode + "b" or "" |blockwise-visual| mode + If a number immediately follows "b" or "" then this is + used as the width of the selection - if it is not specified + then the width of the block is set to the number of characters + in the longest line (counting a as 1 character). + + If {options} contains no register settings, then the default + is to use character mode unless {value} ends in a . + Setting the '=' register is not possible. + Returns zero for success, non-zero for failure. + + Examples: > + :call setreg(v:register, @*) + :call setreg('*', @%, 'ac') + :call setreg('a', "1\n2\n3", 'b5') + +< This example shows using the functions to save and restore a + register. > + :let var_a = getreg('a', 1) + :let var_amode = getregtype('a') + .... + :call setreg('a', var_a, var_amode) + +< You can also change the type of a register by appending + nothing: > + :call setreg('a', '', 'al') + +settabvar({tabnr}, {varname}, {val}) *settabvar()* + Set tab-local variable {varname} to {val} in tab page {tabnr}. + |t:var| + Note that the variable name without "t:" must be used. + Tabs are numbered starting with one. + Vim briefly goes to the tab page {tabnr}, this may trigger + TabLeave and TabEnter autocommands. + This function is not available in the |sandbox|. + +settabwinvar({tabnr}, {winnr}, {varname}, {val}) *settabwinvar()* + Set option or local variable {varname} in window {winnr} to + {val}. + Tabs are numbered starting with one. For the current tabpage + use |setwinvar()|. + When {winnr} is zero the current window is used. + This also works for a global or local buffer option, but it + doesn't work for a global or local buffer variable. + For a local buffer option the global value is unchanged. + Note that the variable name without "w:" must be used. + Vim briefly goes to the tab page {tabnr}, this may trigger + TabLeave and TabEnter autocommands. + Examples: > + :call settabwinvar(1, 1, "&list", 0) + :call settabwinvar(3, 2, "myvar", "foobar") +< This function is not available in the |sandbox|. + +setwinvar({nr}, {varname}, {val}) *setwinvar()* + Like |settabwinvar()| for the current tab page. + Examples: > + :call setwinvar(1, "&list", 0) + :call setwinvar(2, "myvar", "foobar") + +shellescape({string} [, {special}]) *shellescape()* + Escape {string} for use as a shell command argument. + On MS-Windows and MS-DOS, when 'shellslash' is not set, it + will enclose {string} in double quotes and double all double + quotes within {string}. + For other systems, it will enclose {string} in single quotes + and replace all "'" with "'\''". + When the {special} argument is present and it's a non-zero + Number or a non-empty String (|non-zero-arg|), then special + items such as "!", "%", "#" and "" will be preceded by + a backslash. This backslash will be removed again by the |:!| + command. + The "!" character will be escaped (again with a |non-zero-arg| + {special}) when 'shell' contains "csh" in the tail. That is + because for csh and tcsh "!" is used for history replacement + even when inside single quotes. + The character is also escaped. With a |non-zero-arg| + {special} and 'shell' containing "csh" in the tail it's + escaped a second time. + Example of use with a |:!| command: > + :exe '!dir ' . shellescape(expand(''), 1) +< This results in a directory listing for the file under the + cursor. Example of use with |system()|: > + :call system("chmod +w -- " . shellescape(expand("%"))) + + +simplify({filename}) *simplify()* + Simplify the file name as much as possible without changing + the meaning. Shortcuts (on MS-Windows) or symbolic links (on + Unix) are not resolved. If the first path component in + {filename} designates the current directory, this will be + valid for the result as well. A trailing path separator is + not removed either. + Example: > + simplify("./dir/.././/file/") == "./file/" +< Note: The combination "dir/.." is only removed if "dir" is + a searchable directory or does not exist. On Unix, it is also + removed when "dir" is a symbolic link within the same + directory. In order to resolve all the involved symbolic + links before simplifying the path name, use |resolve()|. + + +sin({expr}) *sin()* + Return the sine of {expr}, measured in radians, as a |Float|. + {expr} must evaluate to a |Float| or a |Number|. + Examples: > + :echo sin(100) +< -0.506366 > + :echo sin(-4.01) +< 0.763301 + {only available when compiled with the |+float| feature} + + +sinh({expr}) *sinh()* + Return the hyperbolic sine of {expr} as a |Float| in the range + [-inf, inf]. + {expr} must evaluate to a |Float| or a |Number|. + Examples: > + :echo sinh(0.5) +< 0.521095 > + :echo sinh(-0.9) +< -1.026517 + {only available when compiled with the |+float| feature} + + +sort({list} [, {func}]) *sort()* *E702* + Sort the items in {list} in-place. Returns {list}. If you + want a list to remain unmodified make a copy first: > + :let sortedlist = sort(copy(mylist)) +< Uses the string representation of each item to sort on. + Numbers sort after Strings, |Lists| after Numbers. + For sorting text in the current buffer use |:sort|. + When {func} is given and it is one then case is ignored. + When {func} is a |Funcref| or a function name, this function + is called to compare items. The function is invoked with two + items as argument and must return zero if they are equal, 1 or + bigger if the first one sorts after the second one, -1 or + smaller if the first one sorts before the second one. + Example: > + func MyCompare(i1, i2) + return a:i1 == a:i2 ? 0 : a:i1 > a:i2 ? 1 : -1 + endfunc + let sortedlist = sort(mylist, "MyCompare") +< A shorter compare version for this specific simple case, which + ignores overflow: > + func MyCompare(i1, i2) + return a:i1 - a:i2 + endfunc +< + *soundfold()* +soundfold({word}) + Return the sound-folded equivalent of {word}. Uses the first + language in 'spelllang' for the current window that supports + soundfolding. 'spell' must be set. When no sound folding is + possible the {word} is returned unmodified. + This can be used for making spelling suggestions. Note that + the method can be quite slow. + + *spellbadword()* +spellbadword([{sentence}]) + Without argument: The result is the badly spelled word under + or after the cursor. The cursor is moved to the start of the + bad word. When no bad word is found in the cursor line the + result is an empty string and the cursor doesn't move. + + With argument: The result is the first word in {sentence} that + is badly spelled. If there are no spelling mistakes the + result is an empty string. + + The return value is a list with two items: + - The badly spelled word or an empty string. + - The type of the spelling error: + "bad" spelling mistake + "rare" rare word + "local" word only valid in another region + "caps" word should start with Capital + Example: > + echo spellbadword("the quik brown fox") +< ['quik', 'bad'] ~ + + The spelling information for the current window is used. The + 'spell' option must be set and the value of 'spelllang' is + used. + + *spellsuggest()* +spellsuggest({word} [, {max} [, {capital}]]) + Return a |List| with spelling suggestions to replace {word}. + When {max} is given up to this number of suggestions are + returned. Otherwise up to 25 suggestions are returned. + + When the {capital} argument is given and it's non-zero only + suggestions with a leading capital will be given. Use this + after a match with 'spellcapcheck'. + + {word} can be a badly spelled word followed by other text. + This allows for joining two words that were split. The + suggestions also include the following text, thus you can + replace a line. + + {word} may also be a good word. Similar words will then be + returned. {word} itself is not included in the suggestions, + although it may appear capitalized. + + The spelling information for the current window is used. The + 'spell' option must be set and the values of 'spelllang' and + 'spellsuggest' are used. + + +split({expr} [, {pattern} [, {keepempty}]]) *split()* + Make a |List| out of {expr}. When {pattern} is omitted or + empty each white-separated sequence of characters becomes an + item. + Otherwise the string is split where {pattern} matches, + removing the matched characters. + When the first or last item is empty it is omitted, unless the + {keepempty} argument is given and it's non-zero. + Other empty items are kept when {pattern} matches at least one + character or when {keepempty} is non-zero. + Example: > + :let words = split(getline('.'), '\W\+') +< To split a string in individual characters: > + :for c in split(mystring, '\zs') +< If you want to keep the separator you can also use '\zs': > + :echo split('abc:def:ghi', ':\zs') +< ['abc:', 'def:', 'ghi'] ~ + Splitting a table where the first element can be empty: > + :let items = split(line, ':', 1) +< The opposite function is |join()|. + + +sqrt({expr}) *sqrt()* + Return the non-negative square root of Float {expr} as a + |Float|. + {expr} must evaluate to a |Float| or a |Number|. When {expr} + is negative the result is NaN (Not a Number). + Examples: > + :echo sqrt(100) +< 10.0 > + :echo sqrt(-4.01) +< nan + "nan" may be different, it depends on system libraries. + {only available when compiled with the |+float| feature} + + +str2float( {expr}) *str2float()* + Convert String {expr} to a Float. This mostly works the same + as when using a floating point number in an expression, see + |floating-point-format|. But it's a bit more permissive. + E.g., "1e40" is accepted, while in an expression you need to + write "1.0e40". + Text after the number is silently ignored. + The decimal point is always '.', no matter what the locale is + set to. A comma ends the number: "12,345.67" is converted to + 12.0. You can strip out thousands separators with + |substitute()|: > + let f = str2float(substitute(text, ',', '', 'g')) +< {only available when compiled with the |+float| feature} + + +str2nr( {expr} [, {base}]) *str2nr()* + Convert string {expr} to a number. + {base} is the conversion base, it can be 8, 10 or 16. + When {base} is omitted base 10 is used. This also means that + a leading zero doesn't cause octal conversion to be used, as + with the default String to Number conversion. + When {base} is 16 a leading "0x" or "0X" is ignored. With a + different base the result will be zero. + Text after the number is silently ignored. + + +strchars({expr}) *strchars()* + The result is a Number, which is the number of characters + String {expr} occupies. Composing characters are counted + separately. + Also see |strlen()|, |strdisplaywidth()| and |strwidth()|. + +strdisplaywidth({expr}[, {col}]) *strdisplaywidth()* + The result is a Number, which is the number of display cells + String {expr} occupies on the screen. + When {col} is omitted zero is used. Otherwise it is the + screen column where to start. This matters for Tab + characters. + The option settings of the current window are used. This + matters for anything that's displayed differently, such as + 'tabstop' and 'display'. + When {expr} contains characters with East Asian Width Class + Ambiguous, this function's return value depends on 'ambiwidth'. + Also see |strlen()|, |strwidth()| and |strchars()|. + +strftime({format} [, {time}]) *strftime()* + The result is a String, which is a formatted date and time, as + specified by the {format} string. The given {time} is used, + or the current time if no time is given. The accepted + {format} depends on your system, thus this is not portable! + See the manual page of the C function strftime() for the + format. The maximum length of the result is 80 characters. + See also |localtime()| and |getftime()|. + The language can be changed with the |:language| command. + Examples: > + :echo strftime("%c") Sun Apr 27 11:49:23 1997 + :echo strftime("%Y %b %d %X") 1997 Apr 27 11:53:25 + :echo strftime("%y%m%d %T") 970427 11:53:55 + :echo strftime("%H:%M") 11:55 + :echo strftime("%c", getftime("file.c")) + Show mod time of file.c. +< Not available on all systems. To check use: > + :if exists("*strftime") + +stridx({haystack}, {needle} [, {start}]) *stridx()* + The result is a Number, which gives the byte index in + {haystack} of the first occurrence of the String {needle}. + If {start} is specified, the search starts at index {start}. + This can be used to find a second match: > + :let comma1 = stridx(line, ",") + :let comma2 = stridx(line, ",", comma1 + 1) +< The search is done case-sensitive. + For pattern searches use |match()|. + -1 is returned if the {needle} does not occur in {haystack}. + See also |strridx()|. + Examples: > + :echo stridx("An Example", "Example") 3 + :echo stridx("Starting point", "Start") 0 + :echo stridx("Starting point", "start") -1 +< *strstr()* *strchr()* + stridx() works similar to the C function strstr(). When used + with a single character it works similar to strchr(). + + *string()* +string({expr}) Return {expr} converted to a String. If {expr} is a Number, + Float, String or a composition of them, then the result can be + parsed back with |eval()|. + {expr} type result ~ + String 'string' + Number 123 + Float 123.123456 or 1.123456e8 + Funcref function('name') + List [item, item] + Dictionary {key: value, key: value} + Note that in String values the ' character is doubled. + Also see |strtrans()|. + + *strlen()* +strlen({expr}) The result is a Number, which is the length of the String + {expr} in bytes. + If you want to count the number of multi-byte characters (not + counting composing characters) use something like this: > + + :let len = strlen(substitute(str, ".", "x", "g")) +< + If the argument is a Number it is first converted to a String. + For other types an error is given. + Also see |len()|, |strchars()|, |strdisplaywidth()| and + |strwidth()|. + +strpart({src}, {start}[, {len}]) *strpart()* + The result is a String, which is part of {src}, starting from + byte {start}, with the byte length {len}. + When non-existing bytes are included, this doesn't result in + an error, the bytes are simply omitted. + If {len} is missing, the copy continues from {start} till the + end of the {src}. > + strpart("abcdefg", 3, 2) == "de" + strpart("abcdefg", -2, 4) == "ab" + strpart("abcdefg", 5, 4) == "fg" + strpart("abcdefg", 3) == "defg" +< Note: To get the first character, {start} must be 0. For + example, to get three bytes under and after the cursor: > + strpart(getline("."), col(".") - 1, 3) +< +strridx({haystack}, {needle} [, {start}]) *strridx()* + The result is a Number, which gives the byte index in + {haystack} of the last occurrence of the String {needle}. + When {start} is specified, matches beyond this index are + ignored. This can be used to find a match before a previous + match: > + :let lastcomma = strridx(line, ",") + :let comma2 = strridx(line, ",", lastcomma - 1) +< The search is done case-sensitive. + For pattern searches use |match()|. + -1 is returned if the {needle} does not occur in {haystack}. + If the {needle} is empty the length of {haystack} is returned. + See also |stridx()|. Examples: > + :echo strridx("an angry armadillo", "an") 3 +< *strrchr()* + When used with a single character it works similar to the C + function strrchr(). + +strtrans({expr}) *strtrans()* + The result is a String, which is {expr} with all unprintable + characters translated into printable characters |'isprint'|. + Like they are shown in a window. Example: > + echo strtrans(@a) +< This displays a newline in register a as "^@" instead of + starting a new line. + +strwidth({expr}) *strwidth()* + The result is a Number, which is the number of display cells + String {expr} occupies. A Tab character is counted as one + cell, alternatively use |strdisplaywidth()|. + When {expr} contains characters with East Asian Width Class + Ambiguous, this function's return value depends on 'ambiwidth'. + Also see |strlen()|, |strdisplaywidth()| and |strchars()|. + +submatch({nr}) *submatch()* + Only for an expression in a |:substitute| command. Returns + the {nr}'th submatch of the matched text. When {nr} is 0 + the whole matched text is returned. + Example: > + :s/\d\+/\=submatch(0) + 1/ +< This finds the first number in the line and adds one to it. + A line break is included as a newline character. + +substitute({expr}, {pat}, {sub}, {flags}) *substitute()* + The result is a String, which is a copy of {expr}, in which + the first match of {pat} is replaced with {sub}. This works + like the ":substitute" command (without any flags). But the + matching with {pat} is always done like the 'magic' option is + set and 'cpoptions' is empty (to make scripts portable). + 'ignorecase' is still relevant. 'smartcase' is not used. + See |string-match| for how {pat} is used. + And a "~" in {sub} is not replaced with the previous {sub}. + Note that some codes in {sub} have a special meaning + |sub-replace-special|. For example, to replace something with + "\n" (two characters), use "\\\\n" or '\\n'. + When {pat} does not match in {expr}, {expr} is returned + unmodified. + When {flags} is "g", all matches of {pat} in {expr} are + replaced. Otherwise {flags} should be "". + Example: > + :let &path = substitute(&path, ",\\=[^,]*$", "", "") +< This removes the last component of the 'path' option. > + :echo substitute("testing", ".*", "\\U\\0", "") +< results in "TESTING". + +synID({lnum}, {col}, {trans}) *synID()* + The result is a Number, which is the syntax ID at the position + {lnum} and {col} in the current window. + The syntax ID can be used with |synIDattr()| and + |synIDtrans()| to obtain syntax information about text. + + {col} is 1 for the leftmost column, {lnum} is 1 for the first + line. 'synmaxcol' applies, in a longer line zero is returned. + + When {trans} is non-zero, transparent items are reduced to the + item that they reveal. This is useful when wanting to know + the effective color. When {trans} is zero, the transparent + item is returned. This is useful when wanting to know which + syntax item is effective (e.g. inside parens). + Warning: This function can be very slow. Best speed is + obtained by going through the file in forward direction. + + Example (echoes the name of the syntax item under the cursor): > + :echo synIDattr(synID(line("."), col("."), 1), "name") +< + +synconcealed({lnum}, {col}) *synconcealed()* + The result is a List. The first item in the list is 0 if the + character at the position {lnum} and {col} is not part of a + concealable region, 1 if it is. The second item in the list is + a string. If the first item is 1, the second item contains the + text which will be displayed in place of the concealed text, + depending on the current setting of 'conceallevel'. The third + and final item in the list is a unique number representing the + specific syntax region matched. This allows detection of the + beginning of a new concealable region if there are two + consecutive regions with the same replacement character. + For an example use see $VIMRUNTIME/syntax/2html.vim . + + +synIDattr({synID}, {what} [, {mode}]) *synIDattr()* + The result is a String, which is the {what} attribute of + syntax ID {synID}. This can be used to obtain information + about a syntax item. + {mode} can be "gui", "cterm" or "term", to get the attributes + for that mode. When {mode} is omitted, or an invalid value is + used, the attributes for the currently active highlighting are + used (GUI, cterm or term). + Use synIDtrans() to follow linked highlight groups. + {what} result + "name" the name of the syntax item + "fg" foreground color (GUI: color name used to set + the color, cterm: color number as a string, + term: empty string) + "bg" background color (as with "fg") + "font" font name (only available in the GUI) + |highlight-font| + "sp" special color (as with "fg") |highlight-guisp| + "fg#" like "fg", but for the GUI and the GUI is + running the name in "#RRGGBB" form + "bg#" like "fg#" for "bg" + "sp#" like "fg#" for "sp" + "bold" "1" if bold + "italic" "1" if italic + "reverse" "1" if reverse + "inverse" "1" if inverse (= reverse) + "standout" "1" if standout + "underline" "1" if underlined + "undercurl" "1" if undercurled + + Example (echoes the color of the syntax item under the + cursor): > + :echo synIDattr(synIDtrans(synID(line("."), col("."), 1)), "fg") +< +synIDtrans({synID}) *synIDtrans()* + The result is a Number, which is the translated syntax ID of + {synID}. This is the syntax group ID of what is being used to + 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 +< When the position specified with {lnum} and {col} is invalid + nothing is returned. The position just after the last + character in a line and the first column in an empty line are + valid positions. + +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 + passed as stdin to the command. The string is written as-is, + you need to take care of using the correct line separators + yourself. Pipes are not used. + Note: Use |shellescape()| to escape special characters in a + command argument. Newlines in {expr} may cause the command to + fail. The characters in 'shellquote' and 'shellxquote' may + also cause trouble. + This is not to be used for interactive commands. + + The result is a String. Example: > + :let files = system("ls " . shellescape(expand('%:h'))) + +< To make the result more system-independent, the shell output + is filtered to replace with for Macintosh, and + with for DOS-like systems. + The command executed is constructed using several options: + 'shell' 'shellcmdflag' 'shellxquote' {expr} 'shellredir' {tmp} 'shellxquote' + ({tmp} is an automatically generated file name). + For Unix and OS/2 braces are put around {expr} to allow for + concatenated commands. + + The command will be executed in "cooked" mode, so that a + CTRL-C will interrupt the command (on Unix at least). + + The resulting error code can be found in |v:shell_error|. + This function will fail in |restricted-mode|. + + Note that any wrong value in the options mentioned above may + make the function fail. It has also been reported to fail + when using a security agent application. + Unlike ":!cmd" there is no automatic check for changed files. + Use |:checktime| to force a check. + + +tabpagebuflist([{arg}]) *tabpagebuflist()* + The result is a |List|, where each item is the number of the + buffer associated with each window in the current tab page. + {arg} specifies the number of tab page to be used. When + omitted the current tab page is used. + When {arg} is invalid the number zero is returned. + To get a list of all buffers in all tabs use this: > + tablist = [] + for i in range(tabpagenr('$')) + call extend(tablist, tabpagebuflist(i + 1)) + endfor +< Note that a buffer may appear in more than one window. + + +tabpagenr([{arg}]) *tabpagenr()* + The result is a Number, which is the number of the current + tab page. The first tab page has number 1. + When the optional argument is "$", the number of the last tab + page is returned (the tab page count). + The number can be used with the |:tab| command. + + +tabpagewinnr({tabarg}, [{arg}]) *tabpagewinnr()* + Like |winnr()| but for tab page {tabarg}. + {tabarg} specifies the number of tab page to be used. + {arg} is used like with |winnr()|: + - When omitted the current window number is returned. This is + the window which will be used when going to this tab page. + - When "$" the number of windows is returned. + - When "#" the previous window nr is returned. + Useful examples: > + tabpagewinnr(1) " current window of tab page 1 + tabpagewinnr(4, '$') " number of windows in tab page 4 +< When {tabarg} is invalid zero is returned. + + *tagfiles()* +tagfiles() Returns a |List| with the file names used to search for tags + for the current buffer. This is the 'tags' option expanded. + + +taglist({expr}) *taglist()* + Returns a list of tags matching the regular expression {expr}. + Each list item is a dictionary with at least the following + entries: + name Name of the tag. + filename Name of the file where the tag is + defined. It is either relative to the + current directory or a full path. + cmd Ex command used to locate the tag in + the file. + kind Type of the tag. The value for this + entry depends on the language specific + kind values. Only available when + using a tags file generated by + Exuberant ctags or hdrtag. + static A file specific tag. Refer to + |static-tag| for more information. + More entries may be present, depending on the content of the + tags file: access, implementation, inherits and signature. + Refer to the ctags documentation for information about these + fields. For C code the fields "struct", "class" and "enum" + may appear, they give the name of the entity the tag is + contained in. + + The ex-command 'cmd' can be either an ex search pattern, a + line number or a line number followed by a byte number. + + If there are no matching tags, then an empty list is returned. + + To get an exact tag match, the anchors '^' and '$' should be + used in {expr}. Refer to |tag-regexp| for more information + about the tag search regular expression pattern. + + Refer to |'tags'| for information about how the tags file is + located by Vim. Refer to |tags-file-format| for the format of + the tags file generated by the different ctags tools. + +tempname() *tempname()* *temp-file-name* + The result is a String, which is the name of a file that + doesn't exist. It can be used for a temporary file. The name + is different for at least 26 consecutive calls. Example: > + :let tmpfile = tempname() + :exe "redir > " . tmpfile +< For Unix, the file will be in a private directory |tempfile|. + For MS-Windows forward slashes are used when the 'shellslash' + option is set or when 'shellcmdflag' starts with '-'. + + +tan({expr}) *tan()* + Return the tangent of {expr}, measured in radians, as a |Float| + in the range [-inf, inf]. + {expr} must evaluate to a |Float| or a |Number|. + Examples: > + :echo tan(10) +< 0.648361 > + :echo tan(-4.01) +< -1.181502 + {only available when compiled with the |+float| feature} + + +tanh({expr}) *tanh()* + Return the hyperbolic tangent of {expr} as a |Float| in the + range [-1, 1]. + {expr} must evaluate to a |Float| or a |Number|. + Examples: > + :echo tanh(0.5) +< 0.462117 > + :echo tanh(-1) +< -0.761594 + {only available when compiled with the |+float| feature} + + +tolower({expr}) *tolower()* + The result is a copy of the String given, with all uppercase + characters turned into lowercase (just like applying |gu| to + the string). + +toupper({expr}) *toupper()* + The result is a copy of the String given, with all lowercase + characters turned into uppercase (just like applying |gU| to + the string). + +tr({src}, {fromstr}, {tostr}) *tr()* + The result is a copy of the {src} string with all characters + which appear in {fromstr} replaced by the character in that + position in the {tostr} string. Thus the first character in + {fromstr} is translated into the first character in {tostr} + and so on. Exactly like the unix "tr" command. + This code also deals with multibyte characters properly. + + Examples: > + echo tr("hello there", "ht", "HT") +< returns "Hello THere" > + echo tr("", "<>", "{}") +< returns "{blob}" + +trunc({expr}) *trunc()* + Return the largest integral value with magnitude less than or + equal to {expr} as a |Float| (truncate towards zero). + {expr} must evaluate to a |Float| or a |Number|. + Examples: > + echo trunc(1.456) +< 1.0 > + echo trunc(-5.456) +< -5.0 > + echo trunc(4.0) +< 4.0 + {only available when compiled with the |+float| feature} + + *type()* +type({expr}) The result is a Number, depending on the type of {expr}: + Number: 0 + String: 1 + Funcref: 2 + List: 3 + Dictionary: 4 + Float: 5 + To avoid the magic numbers it should be used this way: > + :if type(myvar) == type(0) + :if type(myvar) == type("") + :if type(myvar) == type(function("tr")) + :if type(myvar) == type([]) + :if type(myvar) == type({}) + :if type(myvar) == type(0.0) + +undofile({name}) *undofile()* + Return the name of the undo file that would be used for a file + with name {name} when writing. This uses the 'undodir' + option, finding directories that exist. It does not check if + the undo file exists. + {name} is always expanded to the full path, since that is what + is used internally. + Useful in combination with |:wundo| and |:rundo|. + When compiled without the +persistent_undo option this always + returns an empty string. + +undotree() *undotree()* + Return the current state of the undo tree in a dictionary with + the following items: + "seq_last" The highest undo sequence number used. + "seq_cur" The sequence number of the current position in + the undo tree. This differs from "seq_last" + when some changes were undone. + "time_cur" Time last used for |:earlier| and related + commands. Use |strftime()| to convert to + something readable. + "save_last" Number of the last file write. Zero when no + write yet. + "save_cur" Number of the current position in the undo + tree. + "synced" Non-zero when the last undo block was synced. + This happens when waiting from input from the + user. See |undo-blocks|. + "entries" A list of dictionaries with information about + undo blocks. + + The first item in the "entries" list is the oldest undo item. + Each List item is a Dictionary with these items: + "seq" Undo sequence number. Same as what appears in + |:undolist|. + "time" Timestamp when the change happened. Use + |strftime()| to convert to something readable. + "newhead" Only appears in the item that is the last one + that was added. This marks the last change + and where further changes will be added. + "curhead" Only appears in the item that is the last one + that was undone. This marks the current + position in the undo tree, the block that will + be used by a redo command. When nothing was + undone after the last change this item will + not appear anywhere. + "save" Only appears on the last block before a file + write. The number is the write count. The + first write has number 1, the last one the + "save_last" mentioned above. + "alt" Alternate entry. This is again a List of undo + blocks. Each item may again have an "alt" + item. + +values({dict}) *values()* + Return a |List| with all the values of {dict}. The |List| is + in arbitrary order. + + +virtcol({expr}) *virtcol()* + The result is a Number, which is the screen column of the file + position given with {expr}. That is, the last screen position + occupied by the character at that position, when the screen + would be of unlimited width. When there is a at the + 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 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. + 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: + . the cursor position + $ the end of the cursor line (the result is the + number of displayed characters in the cursor line + plus one) + 'x position of mark x (if the mark is not set, 0 is + returned) + Note that only marks in the current file can be used. + Examples: > + virtcol(".") with text "foo^Lbar", with cursor on the "^L", returns 5 + virtcol("$") with text "foo^Lbar", returns 9 + virtcol("'t") with text " there", with 't at 'h', returns 6 +< The first column is 1. 0 is returned for an error. + A more advanced example that echoes the maximum length of + all lines: > + echo max(map(range(1, line('$')), "virtcol([v:val, '$'])")) + + +visualmode([expr]) *visualmode()* + The result is a String, which describes the last Visual mode + used in the current buffer. Initially it returns an empty + string, but once Visual mode has been used, it returns "v", + "V", or "" (a single CTRL-V character) for + character-wise, line-wise, or block-wise Visual mode + respectively. + Example: > + :exe "normal " . visualmode() +< This enters the same Visual mode as before. It is also useful + in scripts if you wish to act differently depending on the + Visual mode that was used. + If Visual mode is active, use |mode()| to get the Visual mode + (e.g., in a |:vmap|). + *non-zero-arg* + If [expr] is supplied and it evaluates to a non-zero Number or + a non-empty String, then the Visual mode will be cleared and + the old value is returned. Note that " " and "0" are also + non-empty strings, thus cause the mode to be cleared. A List, + Dictionary or Float is not a Number or String, thus does not + cause the mode to be cleared. + + *winbufnr()* +winbufnr({nr}) The result is a Number, which is the number of the buffer + associated with window {nr}. When {nr} is zero, the number of + the buffer in the current window is returned. When window + {nr} doesn't exist, -1 is returned. + Example: > + :echo "The file in the current window is " . bufname(winbufnr(0)) +< + *wincol()* +wincol() The result is a Number, which is the virtual column of the + cursor in the window. This is counting screen cells from the + left side of the window. The leftmost column is one. + +winheight({nr}) *winheight()* + The result is a Number, which is the height of window {nr}. + When {nr} is zero, the height of the current window is + returned. When window {nr} doesn't exist, -1 is returned. + An existing window always has a height of zero or more. + Examples: > + :echo "The current window has " . winheight(0) . " lines." +< + *winline()* +winline() The result is a Number, which is the screen line of the cursor + in the window. This is counting screen lines from the top of + the window. The first line is one. + If the cursor was moved the view on the file will be updated + first, this may cause a scroll. + + *winnr()* +winnr([{arg}]) The result is a Number, which is the number of the current + window. The top window has number 1. + When the optional argument is "$", the number of the + last window is returned (the window count). + When the optional argument is "#", the number of the last + accessed window is returned (where |CTRL-W_p| goes to). + If there is no previous window or it is in another tab page 0 + is returned. + The number can be used with |CTRL-W_w| and ":wincmd w" + |:wincmd|. + Also see |tabpagewinnr()|. + + *winrestcmd()* +winrestcmd() Returns a sequence of |:resize| commands that should restore + the current window sizes. Only works properly when no windows + are opened or closed and the current window and tab page is + unchanged. + Example: > + :let cmd = winrestcmd() + :call MessWithWindowSizes() + :exe cmd +< + *winrestview()* +winrestview({dict}) + Uses the |Dictionary| returned by |winsaveview()| to restore + the view of the current window. + If you have changed the values the result is unpredictable. + If the window size changed the result won't be the same. + + *winsaveview()* +winsaveview() Returns a |Dictionary| that contains information to restore + the view of the current window. Use |winrestview()| to + restore the view. + This is useful if you have a mapping that jumps around in the + buffer and you want to go back to the original view. + This does not save fold information. Use the 'foldenable' + option to temporarily switch off folding, so that folds are + not opened when moving around. + The return value includes: + lnum cursor line number + col cursor column + coladd cursor column offset for 'virtualedit' + curswant column for vertical movement + topline first line in the window + topfill filler lines, only in diff mode + leftcol first column displayed + skipcol columns skipped + Note that no option values are saved. + + +winwidth({nr}) *winwidth()* + The result is a Number, which is the width of window {nr}. + When {nr} is zero, the width of the current window is + returned. When window {nr} doesn't exist, -1 is returned. + An existing window always has a width of zero or more. + Examples: > + :echo "The current window has " . winwidth(0) . " columns." + :if winwidth(0) <= 50 + : exe "normal 50\|" + :endif +< + *writefile()* +writefile({list}, {fname} [, {binary}]) + Write |List| {list} to file {fname}. Each list item is + separated with a NL. Each list item must be a String or + Number. + When {binary} is equal to "b" binary mode is used: There will + not be a NL after the last list item. An empty item at the + end does cause the last line in the file to end in a NL. + All NL characters are replaced with a NUL character. + Inserting CR characters needs to be done before passing {list} + to writefile(). + An existing file is overwritten, if possible. + When the write fails -1 is returned, otherwise 0. There is an + error message if the file can't be created or when writing + fails. + Also see |readfile()|. + To copy a file byte for byte: > + :let fl = readfile("foo", "b") + :call writefile(fl, "foocopy", "b") +< + + *feature-list* +There are three types of features: +1. Features that are only supported when they have been enabled when Vim + was compiled |+feature-list|. Example: > + :if has("cindent") +2. Features that are only supported when certain conditions have been met. + Example: > + :if has("gui_running") +< *has-patch* +3. Included patches. First check |v:version| for the version of Vim. + Then the "patch123" feature means that patch 123 has been included for + this version. Example (checking version 6.2.148 or later): > + :if v:version > 602 || v:version == 602 && has("patch148") +< Note that it's possible for patch 147 to be omitted even though 148 is + included. + +all_builtin_terms Compiled with all builtin terminals enabled. +amiga Amiga version of Vim. +arabic Compiled with Arabic support |Arabic|. +arp Compiled with ARP support (Amiga). +autocmd Compiled with autocommand support. |autocommand| +balloon_eval Compiled with |balloon-eval| support. +balloon_multiline GUI supports multiline balloons. +beos BeOS version of Vim. +browse Compiled with |:browse| support, and browse() will + work. +builtin_terms Compiled with some builtin terminals. +byte_offset Compiled with support for 'o' in 'statusline' +cindent Compiled with 'cindent' support. +clientserver Compiled with remote invocation support |clientserver|. +clipboard Compiled with 'clipboard' support. +cmdline_compl Compiled with |cmdline-completion| support. +cmdline_hist Compiled with |cmdline-history| support. +cmdline_info Compiled with 'showcmd' and 'ruler' support. +comments Compiled with |'comments'| support. +cryptv Compiled with encryption support |encryption|. +cscope Compiled with |cscope| support. +compatible Compiled to be very Vi compatible. +debug Compiled with "DEBUG" defined. +dialog_con Compiled with console dialog support. +dialog_gui Compiled with GUI dialog support. +diff Compiled with |vimdiff| and 'diff' support. +digraphs Compiled with support for digraphs. +dnd Compiled with support for the "~ register |quote_~|. +dos32 32 bits DOS (DJGPP) version of Vim. +dos16 16 bits DOS version of Vim. +ebcdic Compiled on a machine with ebcdic character set. +emacs_tags Compiled with support for Emacs tags. +eval Compiled with expression evaluation support. Always + true, of course! +ex_extra Compiled with extra Ex commands |+ex_extra|. +extra_search Compiled with support for |'incsearch'| and + |'hlsearch'| +farsi Compiled with Farsi support |farsi|. +file_in_path Compiled with support for |gf| and || +filterpipe When 'shelltemp' is off pipes are used for shell + read/write/filter commands +find_in_path Compiled with support for include file searches + |+find_in_path|. +float Compiled with support for |Float|. +fname_case Case in file names matters (for Amiga, MS-DOS, and + Windows this is not present). +folding Compiled with |folding| support. +footer Compiled with GUI footer support. |gui-footer| +fork Compiled to use fork()/exec() instead of system(). +gettext Compiled with message translation |multi-lang| +gui Compiled with GUI enabled. +gui_athena Compiled with Athena GUI. +gui_gtk Compiled with GTK+ GUI (any version). +gui_gtk2 Compiled with GTK+ 2 GUI (gui_gtk is also defined). +gui_gnome Compiled with Gnome support (gui_gtk is also defined). +gui_mac Compiled with Macintosh GUI. +gui_motif Compiled with Motif GUI. +gui_photon Compiled with Photon GUI. +gui_win32 Compiled with MS Windows Win32 GUI. +gui_win32s idem, and Win32s system being used (Windows 3.1) +gui_running Vim is running in the GUI, or it will start soon. +hangul_input Compiled with Hangul input support. |hangul| +iconv Can use iconv() for conversion. +insert_expand Compiled with support for CTRL-X expansion commands in + Insert mode. +jumplist Compiled with |jumplist| support. +keymap Compiled with 'keymap' support. +langmap Compiled with 'langmap' support. +libcall Compiled with |libcall()| support. +linebreak Compiled with 'linebreak', 'breakat' and 'showbreak' + support. +lispindent Compiled with support for lisp indenting. +listcmds Compiled with commands for the buffer list |:files| + and the argument list |arglist|. +localmap Compiled with local mappings and abbr. |:map-local| +lua Compiled with Lua interface |Lua|. +mac Macintosh version of Vim. +macunix Macintosh version of Vim, using Unix files (OS-X). +menu Compiled with support for |:menu|. +mksession Compiled with support for |:mksession|. +modify_fname Compiled with file name modifiers. |filename-modifiers| +mouse Compiled with support mouse. +mouseshape Compiled with support for 'mouseshape'. +mouse_dec Compiled with support for Dec terminal mouse. +mouse_gpm Compiled with support for gpm (Linux console mouse) +mouse_netterm Compiled with support for netterm mouse. +mouse_pterm Compiled with support for qnx pterm mouse. +mouse_sysmouse Compiled with support for sysmouse (*BSD console mouse) +mouse_xterm Compiled with support for xterm mouse. +multi_byte Compiled with support for 'encoding' +multi_byte_encoding 'encoding' is set to a multi-byte encoding. +multi_byte_ime Compiled with support for IME input method. +multi_lang Compiled with support for multiple languages. +mzscheme Compiled with MzScheme interface |mzscheme|. +netbeans_intg Compiled with support for |netbeans|. +netbeans_enabled Compiled with support for |netbeans| and connected. +ole Compiled with OLE automation support for Win32. +os2 OS/2 version of Vim. +osfiletype Compiled with support for osfiletypes |+osfiletype| +path_extra Compiled with up/downwards search in 'path' and 'tags' +perl Compiled with Perl interface. +persistent_undo Compiled with support for persistent undo history. +postscript Compiled with PostScript file printing. +printer Compiled with |:hardcopy| support. +profile Compiled with |:profile| support. +python Compiled with Python interface. +qnx QNX version of Vim. +quickfix Compiled with |quickfix| support. +reltime Compiled with |reltime()| support. +rightleft Compiled with 'rightleft' support. +ruby Compiled with Ruby interface |ruby|. +scrollbind Compiled with 'scrollbind' support. +showcmd Compiled with 'showcmd' support. +signs Compiled with |:sign| support. +smartindent Compiled with 'smartindent' support. +sniff Compiled with SNiFF interface support. +startuptime Compiled with |--startuptime| support. +statusline Compiled with support for 'statusline', 'rulerformat' + and special formats of 'titlestring' and 'iconstring'. +sun_workshop Compiled with support for Sun |workshop|. +spell Compiled with spell checking support |spell|. +syntax Compiled with syntax highlighting support |syntax|. +syntax_items There are active syntax highlighting items for the + current buffer. +system Compiled to use system() instead of fork()/exec(). +tag_binary Compiled with binary searching in tags files + |tag-binary-search|. +tag_old_static Compiled with support for old static tags + |tag-old-static|. +tag_any_white Compiled with support for any white characters in tags + files |tag-any-white|. +tcl Compiled with Tcl interface. +terminfo Compiled with terminfo instead of termcap. +termresponse Compiled with support for |t_RV| and |v:termresponse|. +textobjects Compiled with support for |text-objects|. +tgetent Compiled with tgetent support, able to use a termcap + or terminfo file. +title Compiled with window title support |'title'|. +toolbar Compiled with support for |gui-toolbar|. +unix Unix version of Vim. +user_commands User-defined commands. +viminfo Compiled with viminfo support. +vim_starting True while initial source'ing takes place. +vertsplit Compiled with vertically split windows |:vsplit|. +virtualedit Compiled with 'virtualedit' option. +visual Compiled with Visual mode. +visualextra Compiled with extra Visual mode commands. + |blockwise-operators|. +vms VMS version of Vim. +vreplace Compiled with |gR| and |gr| commands. +wildignore Compiled with 'wildignore' option. +wildmenu Compiled with 'wildmenu' option. +windows Compiled with support for more than one window. +winaltkeys Compiled with 'winaltkeys' option. +win16 Win16 version of Vim (MS-Windows 3.1). +win32 Win32 version of Vim (MS-Windows 95/98/ME/NT/2000/XP). +win64 Win64 version of Vim (MS-Windows 64 bit). +win32unix Win32 version of Vim, using Unix files (Cygwin) +win95 Win32 version for MS-Windows 95/98/ME. +writebackup Compiled with 'writebackup' default on. +xfontset Compiled with X fontset support |xfontset|. +xim Compiled with X input method support |xim|. +xsmp Compiled with X session management support. +xsmp_interact Compiled with interactive X session management support. +xterm_clipboard Compiled with support for xterm clipboard. +xterm_save Compiled with support for saving and restoring the + xterm screen. +x11 Compiled with X11 support. + + *string-match* +Matching a pattern in a String + +A regexp pattern as explained at |pattern| is normally used to find a match in +the buffer lines. When a pattern is used to find a match in a String, almost +everything works in the same way. The difference is that a String is handled +like it is one line. When it contains a "\n" character, this is not seen as a +line break for the pattern. It can be matched with a "\n" in the pattern, or +with ".". Example: > + :let a = "aaaa\nxxxx" + :echo matchstr(a, "..\n..") + aa + xx + :echo matchstr(a, "a.x") + a + x + +Don't forget that "^" will only match at the first character of the String and +"$" at the last character of the string. They don't match after or before a +"\n". + +============================================================================== +5. Defining functions *user-functions* + +New functions can be defined. These can be called just like builtin +functions. The function executes a sequence of Ex commands. Normal mode +commands can be executed with the |:normal| command. + +The function name must start with an uppercase letter, to avoid confusion with +builtin functions. To prevent from using the same name in different scripts +avoid obvious, short names. A good habit is to start the function name with +the name of the script, e.g., "HTMLcolor()". + +It's also possible to use curly braces, see |curly-braces-names|. And the +|autoload| facility is useful to define a function only when it's called. + + *local-function* +A function local to a script must start with "s:". A local script function +can only be called from within the script and from functions, user commands +and autocommands defined in the script. It is also possible to call the +function from a mapping defined in the script, but then || must be used +instead of "s:" when the mapping is expanded outside of the script. + + *:fu* *:function* *E128* *E129* *E123* +:fu[nction] List all functions and their arguments. + +:fu[nction] {name} List function {name}. + {name} can also be a |Dictionary| entry that is a + |Funcref|: > + :function dict.init + +:fu[nction] /{pattern} List functions with a name matching {pattern}. + Example that lists all functions ending with "File": > + :function /File$ +< + *:function-verbose* +When 'verbose' is non-zero, listing a function will also display where it was +last defined. Example: > + + :verbose function SetFileTypeSH + function SetFileTypeSH(name) + Last set from /usr/share/vim/vim-7.0/filetype.vim +< +See |:verbose-cmd| for more information. + + *E124* *E125* +:fu[nction][!] {name}([arguments]) [range] [abort] [dict] + Define a new function by the name {name}. The name + must be made of alphanumeric characters and '_', and + must start with a capital or "s:" (see above). + + {name} can also be a |Dictionary| entry that is a + |Funcref|: > + :function dict.init(arg) +< "dict" must be an existing dictionary. The entry + "init" is added if it didn't exist yet. Otherwise [!] + is required to overwrite an existing function. The + result is a |Funcref| to a numbered function. The + function can only be used with a |Funcref| and will be + deleted if there are no more references to it. + *E127* *E122* + When a function by this name already exists and [!] is + not used an error message is given. When [!] is used, + an existing function is silently replaced. Unless it + is currently being executed, that is an error. + + For the {arguments} see |function-argument|. + + *a:firstline* *a:lastline* + When the [range] argument is added, the function is + expected to take care of a range itself. The range is + passed as "a:firstline" and "a:lastline". If [range] + is excluded, ":{range}call" will call the function for + each line in the range, with the cursor on the start + of each line. See |function-range-example|. + + When the [abort] argument is added, the function will + abort as soon as an error is detected. + + When the [dict] argument is added, the function must + be invoked through an entry in a |Dictionary|. The + local variable "self" will then be set to the + dictionary. See |Dictionary-function|. + + *function-search-undo* + The last used search pattern and the redo command "." + will not be changed by the function. This also + implies that the effect of |:nohlsearch| is undone + when the function returns. + + *:endf* *:endfunction* *E126* *E193* +:endf[unction] The end of a function definition. Must be on a line + by its own, without other commands. + + *:delf* *:delfunction* *E130* *E131* +:delf[unction] {name} Delete function {name}. + {name} can also be a |Dictionary| entry that is a + |Funcref|: > + :delfunc dict.init +< This will remove the "init" entry from "dict". The + function is deleted if there are no more references to + it. + *:retu* *:return* *E133* +:retu[rn] [expr] Return from a function. When "[expr]" is given, it is + evaluated and returned as the result of the function. + If "[expr]" is not given, the number 0 is returned. + When a function ends without an explicit ":return", + the number 0 is returned. + Note that there is no check for unreachable lines, + thus there is no warning if commands follow ":return". + + If the ":return" is used after a |:try| but before the + matching |:finally| (if present), the commands + following the ":finally" up to the matching |:endtry| + are executed first. This process applies to all + nested ":try"s inside the function. The function + returns at the outermost ":endtry". + + *function-argument* *a:var* +An argument can be defined by giving its name. In the function this can then +be used as "a:name" ("a:" for argument). + *a:0* *a:1* *a:000* *E740* *...* +Up to 20 arguments can be given, separated by commas. After the named +arguments an argument "..." can be specified, which means that more arguments +may optionally be following. In the function the extra arguments can be used +as "a:1", "a:2", etc. "a:0" is set to the number of extra arguments (which +can be 0). "a:000" is set to a |List| that contains these arguments. Note +that "a:1" is the same as "a:000[0]". + *E742* +The a: scope and the variables in it cannot be changed, they are fixed. +However, if a |List| or |Dictionary| is used, you can change their contents. +Thus you can pass a |List| to a function and have the function add an item to +it. If you want to make sure the function cannot change a |List| or +|Dictionary| use |:lockvar|. + +When not using "...", the number of arguments in a function call must be equal +to the number of named arguments. When using "...", the number of arguments +may be larger. + +It is also possible to define a function without any arguments. You must +still supply the () then. The body of the function follows in the next lines, +until the matching |:endfunction|. It is allowed to define another function +inside a function body. + + *local-variables* +Inside a function variables can be used. These are local variables, which +will disappear when the function returns. Global variables need to be +accessed with "g:". + +Example: > + :function Table(title, ...) + : echohl Title + : echo a:title + : echohl None + : echo a:0 . " items:" + : for s in a:000 + : echon ' ' . s + : endfor + :endfunction + +This function can then be called with: > + call Table("Table", "line1", "line2") + call Table("Empty Table") + +To return more than one value, return a |List|: > + :function Compute(n1, n2) + : if a:n2 == 0 + : return ["fail", 0] + : endif + : return ["ok", a:n1 / a:n2] + :endfunction + +This function can then be called with: > + :let [success, div] = Compute(102, 6) + :if success == "ok" + : echo div + :endif +< + *:cal* *:call* *E107* *E117* +:[range]cal[l] {name}([arguments]) + Call a function. The name of the function and its arguments + are as specified with |:function|. Up to 20 arguments can be + used. The returned value is discarded. + Without a range and for functions that accept a range, the + function is called once. When a range is given the cursor is + positioned at the start of the first line before executing the + function. + When a range is given and the function doesn't handle it + itself, the function is executed for each line in the range, + with the cursor in the first column of that line. The cursor + is left at the last line (possibly moved by the last function + call). The arguments are re-evaluated for each line. Thus + this works: + *function-range-example* > + :function Mynumber(arg) + : echo line(".") . " " . a:arg + :endfunction + :1,5call Mynumber(getline(".")) +< + The "a:firstline" and "a:lastline" are defined anyway, they + can be used to do something different at the start or end of + the range. + + Example of a function that handles the range itself: > + + :function Cont() range + : execute (a:firstline + 1) . "," . a:lastline . 's/^/\t\\ ' + :endfunction + :4,8call Cont() +< + This function inserts the continuation character "\" in front + of all the lines in the range, except the first one. + + When the function returns a composite value it can be further + dereferenced, but the range will not be used then. Example: > + :4,8call GetDict().method() +< Here GetDict() gets the range but method() does not. + + *E132* +The recursiveness of user functions is restricted with the |'maxfuncdepth'| +option. + + +AUTOMATICALLY LOADING FUNCTIONS ~ + *autoload-functions* +When using many or large functions, it's possible to automatically define them +only when they are used. There are two methods: with an autocommand and with +the "autoload" directory in 'runtimepath'. + + +Using an autocommand ~ + +This is introduced in the user manual, section |41.14|. + +The autocommand is useful if you have a plugin that is a long Vim script file. +You can define the autocommand and quickly quit the script with |:finish|. +That makes Vim startup faster. The autocommand should then load the same file +again, setting a variable to skip the |:finish| command. + +Use the FuncUndefined autocommand event with a pattern that matches the +function(s) to be defined. Example: > + + :au FuncUndefined BufNet* source ~/vim/bufnetfuncs.vim + +The file "~/vim/bufnetfuncs.vim" should then define functions that start with +"BufNet". Also see |FuncUndefined|. + + +Using an autoload script ~ + *autoload* *E746* +This is introduced in the user manual, section |41.15|. + +Using a script in the "autoload" directory is simpler, but requires using +exactly the right file name. A function that can be autoloaded has a name +like this: > + + :call filename#funcname() + +When such a function is called, and it is not defined yet, Vim will search the +"autoload" directories in 'runtimepath' for a script file called +"filename.vim". For example "~/.vim/autoload/filename.vim". That file should +then define the function like this: > + + function filename#funcname() + echo "Done!" + endfunction + +The file name and the name used before the # in the function must match +exactly, and the defined function must have the name exactly as it will be +called. + +It is possible to use subdirectories. Every # in the function name works like +a path separator. Thus when calling a function: > + + :call foo#bar#func() + +Vim will look for the file "autoload/foo/bar.vim" in 'runtimepath'. + +This also works when reading a variable that has not been set yet: > + + :let l = foo#bar#lvar + +However, when the autoload script was already loaded it won't be loaded again +for an unknown variable. + +When assigning a value to such a variable nothing special happens. This can +be used to pass settings to the autoload script before it's loaded: > + + :let foo#bar#toggle = 1 + :call foo#bar#func() + +Note that when you make a mistake and call a function that is supposed to be +defined in an autoload script, but the script doesn't actually define the +function, the script will be sourced every time you try to call the function. +And you will get an error message every time. + +Also note that if you have two script files, and one calls a function in the +other and vice versa, before the used function is defined, it won't work. +Avoid using the autoload functionality at the toplevel. + +Hint: If you distribute a bunch of scripts you can pack them together with the +|vimball| utility. Also read the user manual |distribute-script|. + +============================================================================== +6. Curly braces names *curly-braces-names* + +Wherever you can use a variable, you can use a "curly braces name" variable. +This is a regular variable name with one or more expressions wrapped in braces +{} like this: > + my_{adjective}_variable + +When Vim encounters this, it evaluates the expression inside the braces, puts +that in place of the expression, and re-interprets the whole as a variable +name. So in the above example, if the variable "adjective" was set to +"noisy", then the reference would be to "my_noisy_variable", whereas if +"adjective" was set to "quiet", then it would be to "my_quiet_variable". + +One application for this is to create a set of variables governed by an option +value. For example, the statement > + echo my_{&background}_message + +would output the contents of "my_dark_message" or "my_light_message" depending +on the current value of 'background'. + +You can use multiple brace pairs: > + echo my_{adverb}_{adjective}_message +..or even nest them: > + echo my_{ad{end_of_word}}_message +where "end_of_word" is either "verb" or "jective". + +However, the expression inside the braces must evaluate to a valid single +variable name, e.g. this is invalid: > + :let foo='a + b' + :echo c{foo}d +.. since the result of expansion is "ca + bd", which is not a variable name. + + *curly-braces-function-names* +You can call and define functions by an evaluated name in a similar way. +Example: > + :let func_end='whizz' + :call my_func_{func_end}(parameter) + +This would call the function "my_func_whizz(parameter)". + +============================================================================== +7. Commands *expression-commands* + +:let {var-name} = {expr1} *:let* *E18* + Set internal variable {var-name} to the result of the + expression {expr1}. The variable will get the type + from the {expr}. If {var-name} didn't exist yet, it + is created. + +:let {var-name}[{idx}] = {expr1} *E689* + Set a list item to the result of the expression + {expr1}. {var-name} must refer to a list and {idx} + must be a valid index in that list. For nested list + the index can be repeated. + This cannot be used to add an item to a |List|. + This cannot be used to set a byte in a String. You + can do that like this: > + :let var = var[0:2] . 'X' . var[4:] +< + *E711* *E719* +:let {var-name}[{idx1}:{idx2}] = {expr1} *E708* *E709* *E710* + Set a sequence of items in a |List| to the result of + the expression {expr1}, which must be a list with the + correct number of items. + {idx1} can be omitted, zero is used instead. + {idx2} can be omitted, meaning the end of the list. + When the selected range of items is partly past the + end of the list, items will be added. + + *:let+=* *:let-=* *:let.=* *E734* +:let {var} += {expr1} Like ":let {var} = {var} + {expr1}". +:let {var} -= {expr1} Like ":let {var} = {var} - {expr1}". +:let {var} .= {expr1} Like ":let {var} = {var} . {expr1}". + These fail if {var} was not set yet and when the type + of {var} and {expr1} don't fit the operator. + + +:let ${env-name} = {expr1} *:let-environment* *:let-$* + Set environment variable {env-name} to the result of + the expression {expr1}. The type is always String. +:let ${env-name} .= {expr1} + Append {expr1} to the environment variable {env-name}. + If the environment variable didn't exist yet this + works like "=". + +:let @{reg-name} = {expr1} *:let-register* *:let-@* + Write the result of the expression {expr1} in register + {reg-name}. {reg-name} must be a single letter, and + must be the name of a writable register (see + |registers|). "@@" can be used for the unnamed + register, "@/" for the search pattern. + If the result of {expr1} ends in a or , the + register will be linewise, otherwise it will be set to + characterwise. + This can be used to clear the last search pattern: > + :let @/ = "" +< This is different from searching for an empty string, + that would match everywhere. + +:let @{reg-name} .= {expr1} + Append {expr1} to register {reg-name}. If the + register was empty it's like setting it to {expr1}. + +:let &{option-name} = {expr1} *:let-option* *:let-&* + Set option {option-name} to the result of the + expression {expr1}. A String or Number value is + always converted to the type of the option. + For an option local to a window or buffer the effect + is just like using the |:set| command: both the local + value and the global value are changed. + Example: > + :let &path = &path . ',/usr/local/include' + +:let &{option-name} .= {expr1} + For a string option: Append {expr1} to the value. + Does not insert a comma like |:set+=|. + +:let &{option-name} += {expr1} +:let &{option-name} -= {expr1} + For a number or boolean option: Add or subtract + {expr1}. + +:let &l:{option-name} = {expr1} +:let &l:{option-name} .= {expr1} +:let &l:{option-name} += {expr1} +:let &l:{option-name} -= {expr1} + Like above, but only set the local value of an option + (if there is one). Works like |:setlocal|. + +:let &g:{option-name} = {expr1} +:let &g:{option-name} .= {expr1} +:let &g:{option-name} += {expr1} +:let &g:{option-name} -= {expr1} + Like above, but only set the global value of an option + (if there is one). Works like |:setglobal|. + +:let [{name1}, {name2}, ...] = {expr1} *:let-unpack* *E687* *E688* + {expr1} must evaluate to a |List|. The first item in + the list is assigned to {name1}, the second item to + {name2}, etc. + The number of names must match the number of items in + the |List|. + Each name can be one of the items of the ":let" + command as mentioned above. + Example: > + :let [s, item] = GetItem(s) +< Detail: {expr1} is evaluated first, then the + assignments are done in sequence. This matters if + {name2} depends on {name1}. Example: > + :let x = [0, 1] + :let i = 0 + :let [i, x[i]] = [1, 2] + :echo x +< The result is [0, 2]. + +:let [{name1}, {name2}, ...] .= {expr1} +:let [{name1}, {name2}, ...] += {expr1} +:let [{name1}, {name2}, ...] -= {expr1} + Like above, but append/add/subtract the value for each + |List| item. + +:let [{name}, ..., ; {lastname}] = {expr1} + Like |:let-unpack| above, but the |List| may have more + items than there are names. A list of the remaining + items is assigned to {lastname}. If there are no + remaining items {lastname} is set to an empty list. + Example: > + :let [a, b; rest] = ["aval", "bval", 3, 4] +< +:let [{name}, ..., ; {lastname}] .= {expr1} +:let [{name}, ..., ; {lastname}] += {expr1} +:let [{name}, ..., ; {lastname}] -= {expr1} + Like above, but append/add/subtract the value for each + |List| item. + *E106* +:let {var-name} .. List the value of variable {var-name}. Multiple + variable names may be given. Special names recognized + here: *E738* + g: global variables + b: local buffer variables + w: local window variables + t: local tab page variables + s: script-local variables + l: local function variables + v: Vim variables. + +:let List the values of all variables. The type of the + variable is indicated before the value: + String + # Number + * Funcref + + +:unl[et][!] {name} ... *:unlet* *:unl* *E108* *E795* + Remove the internal variable {name}. Several variable + names can be given, they are all removed. The name + may also be a |List| or |Dictionary| item. + With [!] no error message is given for non-existing + variables. + One or more items from a |List| can be removed: > + :unlet list[3] " remove fourth item + :unlet list[3:] " remove fourth item to last +< One item from a |Dictionary| can be removed at a time: > + :unlet dict['two'] + :unlet dict.two +< This is especially useful to clean up used global + variables and script-local variables (these are not + deleted when the script ends). Function-local + variables are automatically deleted when the function + ends. + +:lockv[ar][!] [depth] {name} ... *:lockvar* *:lockv* + Lock the internal variable {name}. Locking means that + it can no longer be changed (until it is unlocked). + A locked variable can be deleted: > + :lockvar v + :let v = 'asdf' " fails! + :unlet v +< *E741* + If you try to change a locked variable you get an + error message: "E741: Value of {name} is locked" + + [depth] is relevant when locking a |List| or + |Dictionary|. It specifies how deep the locking goes: + 1 Lock the |List| or |Dictionary| itself, + cannot add or remove items, but can + still change their values. + 2 Also lock the values, cannot change + the items. If an item is a |List| or + |Dictionary|, cannot add or remove + items, but can still change the + values. + 3 Like 2 but for the |List| / + |Dictionary| in the |List| / + |Dictionary|, one level deeper. + The default [depth] is 2, thus when {name} is a |List| + or |Dictionary| the values cannot be changed. + *E743* + For unlimited depth use [!] and omit [depth]. + However, there is a maximum depth of 100 to catch + loops. + + Note that when two variables refer to the same |List| + and you lock one of them, the |List| will also be + locked when used through the other variable. + Example: > + :let l = [0, 1, 2, 3] + :let cl = l + :lockvar l + :let cl[1] = 99 " won't work! +< You may want to make a copy of a list to avoid this. + See |deepcopy()|. + + +:unlo[ckvar][!] [depth] {name} ... *:unlockvar* *:unlo* + Unlock the internal variable {name}. Does the + opposite of |:lockvar|. + + +:if {expr1} *:if* *:endif* *:en* *E171* *E579* *E580* +:en[dif] Execute the commands until the next matching ":else" + or ":endif" if {expr1} evaluates to non-zero. + + From Vim version 4.5 until 5.0, every Ex command in + between the ":if" and ":endif" is ignored. These two + commands were just to allow for future expansions in a + backwards compatible way. Nesting was allowed. Note + that any ":else" or ":elseif" was ignored, the "else" + part was not executed either. + + You can use this to remain compatible with older + versions: > + :if version >= 500 + : version-5-specific-commands + :endif +< The commands still need to be parsed to find the + "endif". Sometimes an older Vim has a problem with a + new command. For example, ":silent" is recognized as + a ":substitute" command. In that case ":execute" can + avoid problems: > + :if version >= 600 + : execute "silent 1,$delete" + :endif +< + NOTE: The ":append" and ":insert" commands don't work + properly in between ":if" and ":endif". + + *:else* *:el* *E581* *E583* +:el[se] Execute the commands until the next matching ":else" + or ":endif" if they previously were not being + executed. + + *:elseif* *:elsei* *E582* *E584* +:elsei[f] {expr1} Short for ":else" ":if", with the addition that there + is no extra ":endif". + +:wh[ile] {expr1} *:while* *:endwhile* *:wh* *:endw* + *E170* *E585* *E588* *E733* +:endw[hile] Repeat the commands between ":while" and ":endwhile", + as long as {expr1} evaluates to non-zero. + When an error is detected from a command inside the + loop, execution continues after the "endwhile". + Example: > + :let lnum = 1 + :while lnum <= line("$") + :call FixLine(lnum) + :let lnum = lnum + 1 + :endwhile +< + NOTE: The ":append" and ":insert" commands don't work + properly inside a ":while" and ":for" loop. + +:for {var} in {list} *:for* *E690* *E732* +:endfo[r] *:endfo* *:endfor* + Repeat the commands between ":for" and ":endfor" for + each item in {list}. Variable {var} is set to the + value of each item. + When an error is detected for a command inside the + loop, execution continues after the "endfor". + Changing {list} inside the loop affects what items are + used. Make a copy if this is unwanted: > + :for item in copy(mylist) +< When not making a copy, Vim stores a reference to the + next item in the list, before executing the commands + with the current item. Thus the current item can be + removed without effect. Removing any later item means + it will not be found. Thus the following example + works (an inefficient way to make a list empty): > + for item in mylist + call remove(mylist, 0) + endfor +< Note that reordering the list (e.g., with sort() or + reverse()) may have unexpected effects. + Note that the type of each list item should be + identical to avoid errors for the type of {var} + changing. Unlet the variable at the end of the loop + to allow multiple item types: > + for item in ["foo", ["bar"]] + echo item + unlet item " E706 without this + endfor + +:for [{var1}, {var2}, ...] in {listlist} +:endfo[r] + Like ":for" above, but each item in {listlist} must be + a list, of which each item is assigned to {var1}, + {var2}, etc. Example: > + :for [lnum, col] in [[1, 3], [2, 5], [3, 8]] + :echo getline(lnum)[col] + :endfor +< + *:continue* *:con* *E586* +:con[tinue] When used inside a ":while" or ":for" loop, jumps back + to the start of the loop. + If it is used after a |:try| inside the loop but + before the matching |:finally| (if present), the + commands following the ":finally" up to the matching + |:endtry| are executed first. This process applies to + all nested ":try"s inside the loop. The outermost + ":endtry" then jumps back to the start of the loop. + + *:break* *:brea* *E587* +:brea[k] When used inside a ":while" or ":for" loop, skips to + the command after the matching ":endwhile" or + ":endfor". + If it is used after a |:try| inside the loop but + before the matching |:finally| (if present), the + commands following the ":finally" up to the matching + |:endtry| are executed first. This process applies to + all nested ":try"s inside the loop. The outermost + ":endtry" then jumps to the command after the loop. + +:try *:try* *:endt* *:endtry* *E600* *E601* *E602* +:endt[ry] Change the error handling for the commands between + ":try" and ":endtry" including everything being + executed across ":source" commands, function calls, + or autocommand invocations. + + When an error or interrupt is detected and there is + a |:finally| command following, execution continues + after the ":finally". Otherwise, or when the + ":endtry" is reached thereafter, the next + (dynamically) surrounding ":try" is checked for + a corresponding ":finally" etc. Then the script + processing is terminated. (Whether a function + definition has an "abort" argument does not matter.) + Example: > + :try | edit too much | finally | echo "cleanup" | endtry + :echo "impossible" " not reached, script terminated above +< + Moreover, an error or interrupt (dynamically) inside + ":try" and ":endtry" is converted to an exception. It + can be caught as if it were thrown by a |:throw| + command (see |:catch|). In this case, the script + processing is not terminated. + + The value "Vim:Interrupt" is used for an interrupt + exception. An error in a Vim command is converted + to a value of the form "Vim({command}):{errmsg}", + other errors are converted to a value of the form + "Vim:{errmsg}". {command} is the full command name, + and {errmsg} is the message that is displayed if the + error exception is not caught, always beginning with + the error number. + Examples: > + :try | sleep 100 | catch /^Vim:Interrupt$/ | endtry + :try | edit | catch /^Vim(edit):E\d\+/ | echo "error" | endtry +< + *:cat* *:catch* *E603* *E604* *E605* +:cat[ch] /{pattern}/ The following commands until the next |:catch|, + |:finally|, or |:endtry| that belongs to the same + |:try| as the ":catch" are executed when an exception + matching {pattern} is being thrown and has not yet + been caught by a previous ":catch". Otherwise, these + commands are skipped. + When {pattern} is omitted all errors are caught. + Examples: > + :catch /^Vim:Interrupt$/ " catch interrupts (CTRL-C) + :catch /^Vim\%((\a\+)\)\=:E/ " catch all Vim errors + :catch /^Vim\%((\a\+)\)\=:/ " catch errors and interrupts + :catch /^Vim(write):/ " catch all errors in :write + :catch /^Vim\%((\a\+)\)\=:E123/ " catch error E123 + :catch /my-exception/ " catch user exception + :catch /.*/ " catch everything + :catch " same as /.*/ +< + Another character can be used instead of / around the + {pattern}, so long as it does not have a special + meaning (e.g., '|' or '"') and doesn't occur inside + {pattern}. + NOTE: It is not reliable to ":catch" the TEXT of + an error message because it may vary in different + locales. + + *:fina* *:finally* *E606* *E607* +:fina[lly] The following commands until the matching |:endtry| + are executed whenever the part between the matching + |:try| and the ":finally" is left: either by falling + through to the ":finally" or by a |:continue|, + |:break|, |:finish|, or |:return|, or by an error or + interrupt or exception (see |:throw|). + + *:th* *:throw* *E608* +:th[row] {expr1} The {expr1} is evaluated and thrown as an exception. + If the ":throw" is used after a |:try| but before the + first corresponding |:catch|, commands are skipped + until the first ":catch" matching {expr1} is reached. + If there is no such ":catch" or if the ":throw" is + used after a ":catch" but before the |:finally|, the + commands following the ":finally" (if present) up to + the matching |:endtry| are executed. If the ":throw" + is after the ":finally", commands up to the ":endtry" + are skipped. At the ":endtry", this process applies + again for the next dynamically surrounding ":try" + (which may be found in a calling function or sourcing + script), until a matching ":catch" has been found. + If the exception is not caught, the command processing + is terminated. + Example: > + :try | throw "oops" | catch /^oo/ | echo "caught" | endtry +< + + *:ec* *:echo* +:ec[ho] {expr1} .. Echoes each {expr1}, with a space in between. The + first {expr1} starts on a new line. + Also see |:comment|. + Use "\n" to start a new line. Use "\r" to move the + cursor to the first column. + Uses the highlighting set by the |:echohl| command. + Cannot be followed by a comment. + Example: > + :echo "the value of 'shell' is" &shell +< *:echo-redraw* + A later redraw may make the message disappear again. + And since Vim mostly postpones redrawing until it's + finished with a sequence of commands this happens + quite often. To avoid that a command from before the + ":echo" causes a redraw afterwards (redraws are often + postponed until you type something), force a redraw + with the |:redraw| command. Example: > + :new | redraw | echo "there is a new window" +< + *:echon* +:echon {expr1} .. Echoes each {expr1}, without anything added. Also see + |:comment|. + Uses the highlighting set by the |:echohl| command. + Cannot be followed by a comment. + Example: > + :echon "the value of 'shell' is " &shell +< + Note the difference between using ":echo", which is a + Vim command, and ":!echo", which is an external shell + command: > + :!echo % --> filename +< The arguments of ":!" are expanded, see |:_%|. > + :!echo "%" --> filename or "filename" +< Like the previous example. Whether you see the double + quotes or not depends on your 'shell'. > + :echo % --> nothing +< The '%' is an illegal character in an expression. > + :echo "%" --> % +< This just echoes the '%' character. > + :echo expand("%") --> filename +< This calls the expand() function to expand the '%'. + + *:echoh* *:echohl* +:echoh[l] {name} Use the highlight group {name} for the following + |:echo|, |:echon| and |:echomsg| commands. Also used + for the |input()| prompt. Example: > + :echohl WarningMsg | echo "Don't panic!" | echohl None +< Don't forget to set the group back to "None", + otherwise all following echo's will be highlighted. + + *:echom* *:echomsg* +:echom[sg] {expr1} .. Echo the expression(s) as a true message, saving the + message in the |message-history|. + Spaces are placed between the arguments as with the + |:echo| command. But unprintable characters are + displayed, not interpreted. + The parsing works slightly different from |:echo|, + more like |:execute|. All the expressions are first + evaluated and concatenated before echoing anything. + The expressions must evaluate to a Number or String, a + Dictionary or List causes an error. + Uses the highlighting set by the |:echohl| command. + Example: > + :echomsg "It's a Zizzer Zazzer Zuzz, as you can plainly see." +< See |:echo-redraw| to avoid the message disappearing + when the screen is redrawn. + *:echoe* *:echoerr* +:echoe[rr] {expr1} .. Echo the expression(s) as an error message, saving the + message in the |message-history|. When used in a + script or function the line number will be added. + Spaces are placed between the arguments as with the + :echo command. When used inside a try conditional, + the message is raised as an error exception instead + (see |try-echoerr|). + Example: > + :echoerr "This script just failed!" +< If you just want a highlighted message use |:echohl|. + And to get a beep: > + :exe "normal \" +< + *:exe* *:execute* +:exe[cute] {expr1} .. Executes the string that results from the evaluation + of {expr1} as an Ex command. + Multiple arguments are concatenated, with a space in + between. To avoid the extra space use the "." + operator to concatenate strings into one argument. + {expr1} is used as the processed command, command line + editing keys are not recognized. + Cannot be followed by a comment. + Examples: > + :execute "buffer" nextbuf + :execute "normal" count . "w" +< + ":execute" can be used to append a command to commands + that don't accept a '|'. Example: > + :execute '!ls' | echo "theend" + +< ":execute" is also a nice way to avoid having to type + control characters in a Vim script for a ":normal" + command: > + :execute "normal ixxx\" +< This has an character, see |expr-string|. + + Be careful to correctly escape special characters in + file names. The |fnameescape()| function can be used + for Vim commands, |shellescape()| for |:!| commands. + Examples: > + :execute "e " . fnameescape(filename) + :execute "!ls " . shellescape(expand('%:h'), 1) +< + Note: The executed string may be any command-line, but + you cannot start or end a "while", "for" or "if" + command. Thus this is illegal: > + :execute 'while i > 5' + :execute 'echo "test" | break' +< + It is allowed to have a "while" or "if" command + completely in the executed string: > + :execute 'while i < 5 | echo i | let i = i + 1 | endwhile' +< + + *:exe-comment* + ":execute", ":echo" and ":echon" cannot be followed by + a comment directly, because they see the '"' as the + start of a string. But, you can use '|' followed by a + comment. Example: > + :echo "foo" | "this is a comment + +============================================================================== +8. Exception handling *exception-handling* + +The Vim script language comprises an exception handling feature. This section +explains how it can be used in a Vim script. + +Exceptions may be raised by Vim on an error or on interrupt, see +|catch-errors| and |catch-interrupt|. You can also explicitly throw an +exception by using the ":throw" command, see |throw-catch|. + + +TRY CONDITIONALS *try-conditionals* + +Exceptions can be caught or can cause cleanup code to be executed. You can +use a try conditional to specify catch clauses (that catch exceptions) and/or +a finally clause (to be executed for cleanup). + A try conditional begins with a |:try| command and ends at the matching +|:endtry| command. In between, you can use a |:catch| command to start +a catch clause, or a |:finally| command to start a finally clause. There may +be none or multiple catch clauses, but there is at most one finally clause, +which must not be followed by any catch clauses. The lines before the catch +clauses and the finally clause is called a try block. > + + :try + : ... + : ... TRY BLOCK + : ... + :catch /{pattern}/ + : ... + : ... CATCH CLAUSE + : ... + :catch /{pattern}/ + : ... + : ... CATCH CLAUSE + : ... + :finally + : ... + : ... FINALLY CLAUSE + : ... + :endtry + +The try conditional allows to watch code for exceptions and to take the +appropriate actions. Exceptions from the try block may be caught. Exceptions +from the try block and also the catch clauses may cause cleanup actions. + When no exception is thrown during execution of the try block, the control +is transferred to the finally clause, if present. After its execution, the +script continues with the line following the ":endtry". + When an exception occurs during execution of the try block, the remaining +lines in the try block are skipped. The exception is matched against the +patterns specified as arguments to the ":catch" commands. The catch clause +after the first matching ":catch" is taken, other catch clauses are not +executed. The catch clause ends when the next ":catch", ":finally", or +":endtry" command is reached - whatever is first. Then, the finally clause +(if present) is executed. When the ":endtry" is reached, the script execution +continues in the following line as usual. + When an exception that does not match any of the patterns specified by the +":catch" commands is thrown in the try block, the exception is not caught by +that try conditional and none of the catch clauses is executed. Only the +finally clause, if present, is taken. The exception pends during execution of +the finally clause. It is resumed at the ":endtry", so that commands after +the ":endtry" are not executed and the exception might be caught elsewhere, +see |try-nesting|. + When during execution of a catch clause another exception is thrown, the +remaining lines in that catch clause are not executed. The new exception is +not matched against the patterns in any of the ":catch" commands of the same +try conditional and none of its catch clauses is taken. If there is, however, +a finally clause, it is executed, and the exception pends during its +execution. The commands following the ":endtry" are not executed. The new +exception might, however, be caught elsewhere, see |try-nesting|. + When during execution of the finally clause (if present) an exception is +thrown, the remaining lines in the finally clause are skipped. If the finally +clause has been taken because of an exception from the try block or one of the +catch clauses, the original (pending) exception is discarded. The commands +following the ":endtry" are not executed, and the exception from the finally +clause is propagated and can be caught elsewhere, see |try-nesting|. + +The finally clause is also executed, when a ":break" or ":continue" for +a ":while" loop enclosing the complete try conditional is executed from the +try block or a catch clause. Or when a ":return" or ":finish" is executed +from the try block or a catch clause of a try conditional in a function or +sourced script, respectively. The ":break", ":continue", ":return", or +":finish" pends during execution of the finally clause and is resumed when the +":endtry" is reached. It is, however, discarded when an exception is thrown +from the finally clause. + When a ":break" or ":continue" for a ":while" loop enclosing the complete +try conditional or when a ":return" or ":finish" is encountered in the finally +clause, the rest of the finally clause is skipped, and the ":break", +":continue", ":return" or ":finish" is executed as usual. If the finally +clause has been taken because of an exception or an earlier ":break", +":continue", ":return", or ":finish" from the try block or a catch clause, +this pending exception or command is discarded. + +For examples see |throw-catch| and |try-finally|. + + +NESTING OF TRY CONDITIONALS *try-nesting* + +Try conditionals can be nested arbitrarily. That is, a complete try +conditional can be put into the try block, a catch clause, or the finally +clause of another try conditional. If the inner try conditional does not +catch an exception thrown in its try block or throws a new exception from one +of its catch clauses or its finally clause, the outer try conditional is +checked according to the rules above. If the inner try conditional is in the +try block of the outer try conditional, its catch clauses are checked, but +otherwise only the finally clause is executed. It does not matter for +nesting, whether the inner try conditional is directly contained in the outer +one, or whether the outer one sources a script or calls a function containing +the inner try conditional. + +When none of the active try conditionals catches an exception, just their +finally clauses are executed. Thereafter, the script processing terminates. +An error message is displayed in case of an uncaught exception explicitly +thrown by a ":throw" command. For uncaught error and interrupt exceptions +implicitly raised by Vim, the error message(s) or interrupt message are shown +as usual. + +For examples see |throw-catch|. + + +EXAMINING EXCEPTION HANDLING CODE *except-examine* + +Exception handling code can get tricky. If you are in doubt what happens, set +'verbose' to 13 or use the ":13verbose" command modifier when sourcing your +script file. Then you see when an exception is thrown, discarded, caught, or +finished. When using a verbosity level of at least 14, things pending in +a finally clause are also shown. This information is also given in debug mode +(see |debug-scripts|). + + +THROWING AND CATCHING EXCEPTIONS *throw-catch* + +You can throw any number or string as an exception. Use the |:throw| command +and pass the value to be thrown as argument: > + :throw 4711 + :throw "string" +< *throw-expression* +You can also specify an expression argument. The expression is then evaluated +first, and the result is thrown: > + :throw 4705 + strlen("string") + :throw strpart("strings", 0, 6) + +An exception might be thrown during evaluation of the argument of the ":throw" +command. Unless it is caught there, the expression evaluation is abandoned. +The ":throw" command then does not throw a new exception. + Example: > + + :function! Foo(arg) + : try + : throw a:arg + : catch /foo/ + : endtry + : return 1 + :endfunction + : + :function! Bar() + : echo "in Bar" + : return 4710 + :endfunction + : + :throw Foo("arrgh") + Bar() + +This throws "arrgh", and "in Bar" is not displayed since Bar() is not +executed. > + :throw Foo("foo") + Bar() +however displays "in Bar" and throws 4711. + +Any other command that takes an expression as argument might also be +abandoned by an (uncaught) exception during the expression evaluation. The +exception is then propagated to the caller of the command. + Example: > + + :if Foo("arrgh") + : echo "then" + :else + : echo "else" + :endif + +Here neither of "then" or "else" is displayed. + + *catch-order* +Exceptions can be caught by a try conditional with one or more |:catch| +commands, see |try-conditionals|. The values to be caught by each ":catch" +command can be specified as a pattern argument. The subsequent catch clause +gets executed when a matching exception is caught. + Example: > + + :function! Foo(value) + : try + : throw a:value + : catch /^\d\+$/ + : echo "Number thrown" + : catch /.*/ + : echo "String thrown" + : endtry + :endfunction + : + :call Foo(0x1267) + :call Foo('string') + +The first call to Foo() displays "Number thrown", the second "String thrown". +An exception is matched against the ":catch" commands in the order they are +specified. Only the first match counts. So you should place the more +specific ":catch" first. The following order does not make sense: > + + : catch /.*/ + : echo "String thrown" + : catch /^\d\+$/ + : echo "Number thrown" + +The first ":catch" here matches always, so that the second catch clause is +never taken. + + *throw-variables* +If you catch an exception by a general pattern, you may access the exact value +in the variable |v:exception|: > + + : catch /^\d\+$/ + : echo "Number thrown. Value is" v:exception + +You may also be interested where an exception was thrown. This is stored in +|v:throwpoint|. Note that "v:exception" and "v:throwpoint" are valid for the +exception most recently caught as long it is not finished. + Example: > + + :function! Caught() + : if v:exception != "" + : echo 'Caught "' . v:exception . '" in ' . v:throwpoint + : else + : echo 'Nothing caught' + : endif + :endfunction + : + :function! Foo() + : try + : try + : try + : throw 4711 + : finally + : call Caught() + : endtry + : catch /.*/ + : call Caught() + : throw "oops" + : endtry + : catch /.*/ + : call Caught() + : finally + : call Caught() + : endtry + :endfunction + : + :call Foo() + +This displays > + + Nothing caught + Caught "4711" in function Foo, line 4 + Caught "oops" in function Foo, line 10 + Nothing caught + +A practical example: The following command ":LineNumber" displays the line +number in the script or function where it has been used: > + + :function! LineNumber() + : return substitute(v:throwpoint, '.*\D\(\d\+\).*', '\1', "") + :endfunction + :command! LineNumber try | throw "" | catch | echo LineNumber() | endtry +< + *try-nested* +An exception that is not caught by a try conditional can be caught by +a surrounding try conditional: > + + :try + : try + : throw "foo" + : catch /foobar/ + : echo "foobar" + : finally + : echo "inner finally" + : endtry + :catch /foo/ + : echo "foo" + :endtry + +The inner try conditional does not catch the exception, just its finally +clause is executed. The exception is then caught by the outer try +conditional. The example displays "inner finally" and then "foo". + + *throw-from-catch* +You can catch an exception and throw a new one to be caught elsewhere from the +catch clause: > + + :function! Foo() + : throw "foo" + :endfunction + : + :function! Bar() + : try + : call Foo() + : catch /foo/ + : echo "Caught foo, throw bar" + : throw "bar" + : endtry + :endfunction + : + :try + : call Bar() + :catch /.*/ + : echo "Caught" v:exception + :endtry + +This displays "Caught foo, throw bar" and then "Caught bar". + + *rethrow* +There is no real rethrow in the Vim script language, but you may throw +"v:exception" instead: > + + :function! Bar() + : try + : call Foo() + : catch /.*/ + : echo "Rethrow" v:exception + : throw v:exception + : endtry + :endfunction +< *try-echoerr* +Note that this method cannot be used to "rethrow" Vim error or interrupt +exceptions, because it is not possible to fake Vim internal exceptions. +Trying so causes an error exception. You should throw your own exception +denoting the situation. If you want to cause a Vim error exception containing +the original error exception value, you can use the |:echoerr| command: > + + :try + : try + : asdf + : catch /.*/ + : echoerr v:exception + : endtry + :catch /.*/ + : echo v:exception + :endtry + +This code displays + + Vim(echoerr):Vim:E492: Not an editor command: asdf ~ + + +CLEANUP CODE *try-finally* + +Scripts often change global settings and restore them at their end. If the +user however interrupts the script by pressing CTRL-C, the settings remain in +an inconsistent state. The same may happen to you in the development phase of +a script when an error occurs or you explicitly throw an exception without +catching it. You can solve these problems by using a try conditional with +a finally clause for restoring the settings. Its execution is guaranteed on +normal control flow, on error, on an explicit ":throw", and on interrupt. +(Note that errors and interrupts from inside the try conditional are converted +to exceptions. When not caught, they terminate the script after the finally +clause has been executed.) +Example: > + + :try + : let s:saved_ts = &ts + : set ts=17 + : + : " Do the hard work here. + : + :finally + : let &ts = s:saved_ts + : unlet s:saved_ts + :endtry + +This method should be used locally whenever a function or part of a script +changes global settings which need to be restored on failure or normal exit of +that function or script part. + + *break-finally* +Cleanup code works also when the try block or a catch clause is left by +a ":continue", ":break", ":return", or ":finish". + Example: > + + :let first = 1 + :while 1 + : try + : if first + : echo "first" + : let first = 0 + : continue + : else + : throw "second" + : endif + : catch /.*/ + : echo v:exception + : break + : finally + : echo "cleanup" + : endtry + : echo "still in while" + :endwhile + :echo "end" + +This displays "first", "cleanup", "second", "cleanup", and "end". > + + :function! Foo() + : try + : return 4711 + : finally + : echo "cleanup\n" + : endtry + : echo "Foo still active" + :endfunction + : + :echo Foo() "returned by Foo" + +This displays "cleanup" and "4711 returned by Foo". You don't need to add an +extra ":return" in the finally clause. (Above all, this would override the +return value.) + + *except-from-finally* +Using either of ":continue", ":break", ":return", ":finish", or ":throw" in +a finally clause is possible, but not recommended since it abandons the +cleanup actions for the try conditional. But, of course, interrupt and error +exceptions might get raised from a finally clause. + Example where an error in the finally clause stops an interrupt from +working correctly: > + + :try + : try + : echo "Press CTRL-C for interrupt" + : while 1 + : endwhile + : finally + : unlet novar + : endtry + :catch /novar/ + :endtry + :echo "Script still running" + :sleep 1 + +If you need to put commands that could fail into a finally clause, you should +think about catching or ignoring the errors in these commands, see +|catch-errors| and |ignore-errors|. + + +CATCHING ERRORS *catch-errors* + +If you want to catch specific errors, you just have to put the code to be +watched in a try block and add a catch clause for the error message. The +presence of the try conditional causes all errors to be converted to an +exception. No message is displayed and |v:errmsg| is not set then. To find +the right pattern for the ":catch" command, you have to know how the format of +the error exception is. + Error exceptions have the following format: > + + Vim({cmdname}):{errmsg} +or > + Vim:{errmsg} + +{cmdname} is the name of the command that failed; the second form is used when +the command name is not known. {errmsg} is the error message usually produced +when the error occurs outside try conditionals. It always begins with +a capital "E", followed by a two or three-digit error number, a colon, and +a space. + +Examples: + +The command > + :unlet novar +normally produces the error message > + E108: No such variable: "novar" +which is converted inside try conditionals to an exception > + Vim(unlet):E108: No such variable: "novar" + +The command > + :dwim +normally produces the error message > + E492: Not an editor command: dwim +which is converted inside try conditionals to an exception > + Vim:E492: Not an editor command: dwim + +You can catch all ":unlet" errors by a > + :catch /^Vim(unlet):/ +or all errors for misspelled command names by a > + :catch /^Vim:E492:/ + +Some error messages may be produced by different commands: > + :function nofunc +and > + :delfunction nofunc +both produce the error message > + E128: Function name must start with a capital: nofunc +which is converted inside try conditionals to an exception > + Vim(function):E128: Function name must start with a capital: nofunc +or > + Vim(delfunction):E128: Function name must start with a capital: nofunc +respectively. You can catch the error by its number independently on the +command that caused it if you use the following pattern: > + :catch /^Vim(\a\+):E128:/ + +Some commands like > + :let x = novar +produce multiple error messages, here: > + E121: Undefined variable: novar + E15: Invalid expression: novar +Only the first is used for the exception value, since it is the most specific +one (see |except-several-errors|). So you can catch it by > + :catch /^Vim(\a\+):E121:/ + +You can catch all errors related to the name "nofunc" by > + :catch /\/ + +You can catch all Vim errors in the ":write" and ":read" commands by > + :catch /^Vim(\(write\|read\)):E\d\+:/ + +You can catch all Vim errors by the pattern > + :catch /^Vim\((\a\+)\)\=:E\d\+:/ +< + *catch-text* +NOTE: You should never catch the error message text itself: > + :catch /No such variable/ +only works in the english locale, but not when the user has selected +a different language by the |:language| command. It is however helpful to +cite the message text in a comment: > + :catch /^Vim(\a\+):E108:/ " No such variable + + +IGNORING ERRORS *ignore-errors* + +You can ignore errors in a specific Vim command by catching them locally: > + + :try + : write + :catch + :endtry + +But you are strongly recommended NOT to use this simple form, since it could +catch more than you want. With the ":write" command, some autocommands could +be executed and cause errors not related to writing, for instance: > + + :au BufWritePre * unlet novar + +There could even be such errors you are not responsible for as a script +writer: a user of your script might have defined such autocommands. You would +then hide the error from the user. + It is much better to use > + + :try + : write + :catch /^Vim(write):/ + :endtry + +which only catches real write errors. So catch only what you'd like to ignore +intentionally. + +For a single command that does not cause execution of autocommands, you could +even suppress the conversion of errors to exceptions by the ":silent!" +command: > + :silent! nunmap k +This works also when a try conditional is active. + + +CATCHING INTERRUPTS *catch-interrupt* + +When there are active try conditionals, an interrupt (CTRL-C) is converted to +the exception "Vim:Interrupt". You can catch it like every exception. The +script is not terminated, then. + Example: > + + :function! TASK1() + : sleep 10 + :endfunction + + :function! TASK2() + : sleep 20 + :endfunction + + :while 1 + : let command = input("Type a command: ") + : try + : if command == "" + : continue + : elseif command == "END" + : break + : elseif command == "TASK1" + : call TASK1() + : elseif command == "TASK2" + : call TASK2() + : else + : echo "\nIllegal command:" command + : continue + : endif + : catch /^Vim:Interrupt$/ + : echo "\nCommand interrupted" + : " Caught the interrupt. Continue with next prompt. + : endtry + :endwhile + +You can interrupt a task here by pressing CTRL-C; the script then asks for +a new command. If you press CTRL-C at the prompt, the script is terminated. + +For testing what happens when CTRL-C would be pressed on a specific line in +your script, use the debug mode and execute the |>quit| or |>interrupt| +command on that line. See |debug-scripts|. + + +CATCHING ALL *catch-all* + +The commands > + + :catch /.*/ + :catch // + :catch + +catch everything, error exceptions, interrupt exceptions and exceptions +explicitly thrown by the |:throw| command. This is useful at the top level of +a script in order to catch unexpected things. + Example: > + + :try + : + : " do the hard work here + : + :catch /MyException/ + : + : " handle known problem + : + :catch /^Vim:Interrupt$/ + : echo "Script interrupted" + :catch /.*/ + : echo "Internal error (" . v:exception . ")" + : echo " - occurred at " . v:throwpoint + :endtry + :" end of script + +Note: Catching all might catch more things than you want. Thus, you are +strongly encouraged to catch only for problems that you can really handle by +specifying a pattern argument to the ":catch". + Example: Catching all could make it nearly impossible to interrupt a script +by pressing CTRL-C: > + + :while 1 + : try + : sleep 1 + : catch + : endtry + :endwhile + + +EXCEPTIONS AND AUTOCOMMANDS *except-autocmd* + +Exceptions may be used during execution of autocommands. Example: > + + :autocmd User x try + :autocmd User x throw "Oops!" + :autocmd User x catch + :autocmd User x echo v:exception + :autocmd User x endtry + :autocmd User x throw "Arrgh!" + :autocmd User x echo "Should not be displayed" + : + :try + : doautocmd User x + :catch + : echo v:exception + :endtry + +This displays "Oops!" and "Arrgh!". + + *except-autocmd-Pre* +For some commands, autocommands get executed before the main action of the +command takes place. If an exception is thrown and not caught in the sequence +of autocommands, the sequence and the command that caused its execution are +abandoned and the exception is propagated to the caller of the command. + Example: > + + :autocmd BufWritePre * throw "FAIL" + :autocmd BufWritePre * echo "Should not be displayed" + : + :try + : write + :catch + : echo "Caught:" v:exception "from" v:throwpoint + :endtry + +Here, the ":write" command does not write the file currently being edited (as +you can see by checking 'modified'), since the exception from the BufWritePre +autocommand abandons the ":write". The exception is then caught and the +script displays: > + + Caught: FAIL from BufWrite Auto commands for "*" +< + *except-autocmd-Post* +For some commands, autocommands get executed after the main action of the +command has taken place. If this main action fails and the command is inside +an active try conditional, the autocommands are skipped and an error exception +is thrown that can be caught by the caller of the command. + Example: > + + :autocmd BufWritePost * echo "File successfully written!" + : + :try + : write /i/m/p/o/s/s/i/b/l/e + :catch + : echo v:exception + :endtry + +This just displays: > + + Vim(write):E212: Can't open file for writing (/i/m/p/o/s/s/i/b/l/e) + +If you really need to execute the autocommands even when the main action +fails, trigger the event from the catch clause. + Example: > + + :autocmd BufWritePre * set noreadonly + :autocmd BufWritePost * set readonly + : + :try + : write /i/m/p/o/s/s/i/b/l/e + :catch + : doautocmd BufWritePost /i/m/p/o/s/s/i/b/l/e + :endtry +< +You can also use ":silent!": > + + :let x = "ok" + :let v:errmsg = "" + :autocmd BufWritePost * if v:errmsg != "" + :autocmd BufWritePost * let x = "after fail" + :autocmd BufWritePost * endif + :try + : silent! write /i/m/p/o/s/s/i/b/l/e + :catch + :endtry + :echo x + +This displays "after fail". + +If the main action of the command does not fail, exceptions from the +autocommands will be catchable by the caller of the command: > + + :autocmd BufWritePost * throw ":-(" + :autocmd BufWritePost * echo "Should not be displayed" + : + :try + : write + :catch + : echo v:exception + :endtry +< + *except-autocmd-Cmd* +For some commands, the normal action can be replaced by a sequence of +autocommands. Exceptions from that sequence will be catchable by the caller +of the command. + Example: For the ":write" command, the caller cannot know whether the file +had actually been written when the exception occurred. You need to tell it in +some way. > + + :if !exists("cnt") + : let cnt = 0 + : + : autocmd BufWriteCmd * if &modified + : autocmd BufWriteCmd * let cnt = cnt + 1 + : autocmd BufWriteCmd * if cnt % 3 == 2 + : autocmd BufWriteCmd * throw "BufWriteCmdError" + : autocmd BufWriteCmd * endif + : autocmd BufWriteCmd * write | set nomodified + : autocmd BufWriteCmd * if cnt % 3 == 0 + : autocmd BufWriteCmd * throw "BufWriteCmdError" + : autocmd BufWriteCmd * endif + : autocmd BufWriteCmd * echo "File successfully written!" + : autocmd BufWriteCmd * endif + :endif + : + :try + : write + :catch /^BufWriteCmdError$/ + : if &modified + : echo "Error on writing (file contents not changed)" + : else + : echo "Error after writing" + : endif + :catch /^Vim(write):/ + : echo "Error on writing" + :endtry + +When this script is sourced several times after making changes, it displays +first > + File successfully written! +then > + Error on writing (file contents not changed) +then > + Error after writing +etc. + + *except-autocmd-ill* +You cannot spread a try conditional over autocommands for different events. +The following code is ill-formed: > + + :autocmd BufWritePre * try + : + :autocmd BufWritePost * catch + :autocmd BufWritePost * echo v:exception + :autocmd BufWritePost * endtry + : + :write + + +EXCEPTION HIERARCHIES AND PARAMETERIZED EXCEPTIONS *except-hier-param* + +Some programming languages allow to use hierarchies of exception classes or to +pass additional information with the object of an exception class. You can do +similar things in Vim. + In order to throw an exception from a hierarchy, just throw the complete +class name with the components separated by a colon, for instance throw the +string "EXCEPT:MATHERR:OVERFLOW" for an overflow in a mathematical library. + When you want to pass additional information with your exception class, add +it in parentheses, for instance throw the string "EXCEPT:IO:WRITEERR(myfile)" +for an error when writing "myfile". + With the appropriate patterns in the ":catch" command, you can catch for +base classes or derived classes of your hierarchy. Additional information in +parentheses can be cut out from |v:exception| with the ":substitute" command. + Example: > + + :function! CheckRange(a, func) + : if a:a < 0 + : throw "EXCEPT:MATHERR:RANGE(" . a:func . ")" + : endif + :endfunction + : + :function! Add(a, b) + : call CheckRange(a:a, "Add") + : call CheckRange(a:b, "Add") + : let c = a:a + a:b + : if c < 0 + : throw "EXCEPT:MATHERR:OVERFLOW" + : endif + : return c + :endfunction + : + :function! Div(a, b) + : call CheckRange(a:a, "Div") + : call CheckRange(a:b, "Div") + : if (a:b == 0) + : throw "EXCEPT:MATHERR:ZERODIV" + : endif + : return a:a / a:b + :endfunction + : + :function! Write(file) + : try + : execute "write" fnameescape(a:file) + : catch /^Vim(write):/ + : throw "EXCEPT:IO(" . getcwd() . ", " . a:file . "):WRITEERR" + : endtry + :endfunction + : + :try + : + : " something with arithmetics and I/O + : + :catch /^EXCEPT:MATHERR:RANGE/ + : let function = substitute(v:exception, '.*(\(\a\+\)).*', '\1', "") + : echo "Range error in" function + : + :catch /^EXCEPT:MATHERR/ " catches OVERFLOW and ZERODIV + : echo "Math error" + : + :catch /^EXCEPT:IO/ + : let dir = substitute(v:exception, '.*(\(.\+\),\s*.\+).*', '\1', "") + : let file = substitute(v:exception, '.*(.\+,\s*\(.\+\)).*', '\1', "") + : if file !~ '^/' + : let file = dir . "/" . file + : endif + : echo 'I/O error for "' . file . '"' + : + :catch /^EXCEPT/ + : echo "Unspecified error" + : + :endtry + +The exceptions raised by Vim itself (on error or when pressing CTRL-C) use +a flat hierarchy: they are all in the "Vim" class. You cannot throw yourself +exceptions with the "Vim" prefix; they are reserved for Vim. + Vim error exceptions are parameterized with the name of the command that +failed, if known. See |catch-errors|. + + +PECULIARITIES + *except-compat* +The exception handling concept requires that the command sequence causing the +exception is aborted immediately and control is transferred to finally clauses +and/or a catch clause. + +In the Vim script language there are cases where scripts and functions +continue after an error: in functions without the "abort" flag or in a command +after ":silent!", control flow goes to the following line, and outside +functions, control flow goes to the line following the outermost ":endwhile" +or ":endif". On the other hand, errors should be catchable as exceptions +(thus, requiring the immediate abortion). + +This problem has been solved by converting errors to exceptions and using +immediate abortion (if not suppressed by ":silent!") only when a try +conditional is active. This is no restriction since an (error) exception can +be caught only from an active try conditional. If you want an immediate +termination without catching the error, just use a try conditional without +catch clause. (You can cause cleanup code being executed before termination +by specifying a finally clause.) + +When no try conditional is active, the usual abortion and continuation +behavior is used instead of immediate abortion. This ensures compatibility of +scripts written for Vim 6.1 and earlier. + +However, when sourcing an existing script that does not use exception handling +commands (or when calling one of its functions) from inside an active try +conditional of a new script, you might change the control flow of the existing +script on error. You get the immediate abortion on error and can catch the +error in the new script. If however the sourced script suppresses error +messages by using the ":silent!" command (checking for errors by testing +|v:errmsg| if appropriate), its execution path is not changed. The error is +not converted to an exception. (See |:silent|.) So the only remaining cause +where this happens is for scripts that don't care about errors and produce +error messages. You probably won't want to use such code from your new +scripts. + + *except-syntax-err* +Syntax errors in the exception handling commands are never caught by any of +the ":catch" commands of the try conditional they belong to. Its finally +clauses, however, is executed. + Example: > + + :try + : try + : throw 4711 + : catch /\(/ + : echo "in catch with syntax error" + : catch + : echo "inner catch-all" + : finally + : echo "inner finally" + : endtry + :catch + : echo 'outer catch-all caught "' . v:exception . '"' + : finally + : echo "outer finally" + :endtry + +This displays: > + inner finally + outer catch-all caught "Vim(catch):E54: Unmatched \(" + outer finally +The original exception is discarded and an error exception is raised, instead. + + *except-single-line* +The ":try", ":catch", ":finally", and ":endtry" commands can be put on +a single line, but then syntax errors may make it difficult to recognize the +"catch" line, thus you better avoid this. + Example: > + :try | unlet! foo # | catch | endtry +raises an error exception for the trailing characters after the ":unlet!" +argument, but does not see the ":catch" and ":endtry" commands, so that the +error exception is discarded and the "E488: Trailing characters" message gets +displayed. + + *except-several-errors* +When several errors appear in a single command, the first error message is +usually the most specific one and therefor converted to the error exception. + Example: > + echo novar +causes > + E121: Undefined variable: novar + E15: Invalid expression: novar +The value of the error exception inside try conditionals is: > + Vim(echo):E121: Undefined variable: novar +< *except-syntax-error* +But when a syntax error is detected after a normal error in the same command, +the syntax error is used for the exception being thrown. + Example: > + unlet novar # +causes > + E108: No such variable: "novar" + E488: Trailing characters +The value of the error exception inside try conditionals is: > + Vim(unlet):E488: Trailing characters +This is done because the syntax error might change the execution path in a way +not intended by the user. Example: > + try + try | unlet novar # | catch | echo v:exception | endtry + catch /.*/ + echo "outer catch:" v:exception + endtry +This displays "outer catch: Vim(unlet):E488: Trailing characters", and then +a "E600: Missing :endtry" error message is given, see |except-single-line|. + +============================================================================== +9. Examples *eval-examples* + +Printing in Binary ~ +> + :" The function Nr2Bin() returns the binary string representation of a number. + :func Nr2Bin(nr) + : let n = a:nr + : let r = "" + : while n + : let r = '01'[n % 2] . r + : let n = n / 2 + : endwhile + : return r + :endfunc + + :" The function String2Bin() converts each character in a string to a + :" binary string, separated with dashes. + :func String2Bin(str) + : let out = '' + : for ix in range(strlen(a:str)) + : let out = out . '-' . Nr2Bin(char2nr(a:str[ix])) + : endfor + : return out[1:] + :endfunc + +Example of its use: > + :echo Nr2Bin(32) +result: "100000" > + :echo String2Bin("32") +result: "110011-110010" + + +Sorting lines ~ + +This example sorts lines with a specific compare function. > + + :func SortBuffer() + : let lines = getline(1, '$') + : call sort(lines, function("Strcmp")) + : call setline(1, lines) + :endfunction + +As a one-liner: > + :call setline(1, sort(getline(1, '$'), function("Strcmp"))) + + +scanf() replacement ~ + *sscanf* +There is no sscanf() function in Vim. If you need to extract parts from a +line, you can use matchstr() and substitute() to do it. This example shows +how to get the file name, line number and column number out of a line like +"foobar.txt, 123, 45". > + :" Set up the match bit + :let mx='\(\f\+\),\s*\(\d\+\),\s*\(\d\+\)' + :"get the part matching the whole expression + :let l = matchstr(line, mx) + :"get each item out of the match + :let file = substitute(l, mx, '\1', '') + :let lnum = substitute(l, mx, '\2', '') + :let col = substitute(l, mx, '\3', '') + +The input is in the variable "line", the results in the variables "file", +"lnum" and "col". (idea from Michael Geddes) + + +getting the scriptnames in a Dictionary ~ + *scriptnames-dictionary* +The |:scriptnames| command can be used to get a list of all script files that +have been sourced. There is no equivalent function or variable for this +(because it's rarely needed). In case you need to manipulate the list this +code can be used: > + " Get the output of ":scriptnames" in the scriptnames_output variable. + let scriptnames_output = '' + redir => scriptnames_output + silent scriptnames + redir END + + " Split the output into lines and parse each line. Add an entry to the + " "scripts" dictionary. + let scripts = {} + for line in split(scriptnames_output, "\n") + " Only do non-blank lines. + if line =~ '\S' + " Get the first number in the line. + let nr = matchstr(line, '\d\+') + " Get the file name, remove the script number " 123: ". + let name = substitute(line, '.\+:\s*', '', '') + " Add an item to the Dictionary + let scripts[nr] = name + endif + endfor + unlet scriptnames_output + +============================================================================== +10. No +eval feature *no-eval-feature* + +When the |+eval| feature was disabled at compile time, none of the expression +evaluation commands are available. To prevent this from causing Vim scripts +to generate all kinds of errors, the ":if" and ":endif" commands are still +recognized, though the argument of the ":if" and everything between the ":if" +and the matching ":endif" is ignored. Nesting of ":if" blocks is allowed, but +only if the commands are at the start of the line. The ":else" command is not +recognized. + +Example of how to avoid executing commands when the |+eval| feature is +missing: > + + :if 1 + : echo "Expression evaluation is compiled in" + :else + : echo "You will _never_ see this message" + :endif + +============================================================================== +11. The sandbox *eval-sandbox* *sandbox* *E48* + +The 'foldexpr', 'formatexpr', 'includeexpr', 'indentexpr', 'statusline' and +'foldtext' options may be evaluated in a sandbox. This means that you are +protected from these expressions having nasty side effects. This gives some +safety for when these options are set from a modeline. It is also used when +the command from a tags file is executed and for CTRL-R = in the command line. +The sandbox is also used for the |:sandbox| command. + +These items are not allowed in the sandbox: + - changing the buffer text + - defining or changing mapping, autocommands, functions, user commands + - setting certain options (see |option-summary|) + - setting certain v: variables (see |v:var|) *E794* + - executing a shell command + - reading or writing a file + - jumping to another buffer or editing a file + - executing Python, Perl, etc. commands +This is not guaranteed 100% secure, but it should block most attacks. + + *:san* *:sandbox* +:san[dbox] {cmd} Execute {cmd} in the sandbox. Useful to evaluate an + option that may have been set from a modeline, e.g. + 'foldexpr'. + + *sandbox-option* +A few options contain an expression. When this expression is evaluated it may +have to be done in the sandbox to avoid a security risk. But the sandbox is +restrictive, thus this only happens when the option was set from an insecure +location. Insecure in this context are: +- sourcing a .vimrc or .exrc in the current directory +- while executing in the sandbox +- value coming from a modeline + +Note that when in the sandbox and saving an option value and restoring it, the +option will still be marked as it was set in the sandbox. + +============================================================================== +12. Textlock *textlock* + +In a few situations it is not allowed to change the text in the buffer, jump +to another window and some other things that might confuse or break what Vim +is currently doing. This mostly applies to things that happen when Vim is +actually doing something else. For example, evaluating the 'balloonexpr' may +happen any moment the mouse cursor is resting at some position. + +This is not allowed when the textlock is active: + - changing the buffer text + - jumping to another buffer or window + - editing another file + - closing a window or quitting Vim + - etc. + + + vim:tw=78:ts=8:ft=help:norl: diff -Naur vim73.orig/runtime/doc/if_cscop.txt vim73/runtime/doc/if_cscop.txt --- vim73.orig/runtime/doc/if_cscop.txt 2010-08-15 12:23:20.000000000 +0000 +++ vim73/runtime/doc/if_cscop.txt 2012-07-20 20:31:11.324306815 +0000 @@ -272,6 +272,15 @@ :set cst :set nocst < + *cscoperelative* *csre* +If 'cscoperelative' set, then in absence of a prefix given to cscope (prefx +is the argument to -P option of cscope), basename of cscope.out location +(usually the project root directory) will be used as the prefix to construt +absolute path.The default is off. Note: This option is only effective when +cscope (cscopeprg) is initialized without a prefix path (-P). Examples: > + :set csre + :set nocsre +< *cscopetagorder* *csto* The value of 'csto' determines the order in which |:cstag| performs a search. If 'csto' is set to zero, cscope database(s) are searched first, followed diff -Naur vim73.orig/runtime/doc/if_cscop.txt.orig vim73/runtime/doc/if_cscop.txt.orig --- vim73.orig/runtime/doc/if_cscop.txt.orig 1970-01-01 00:00:00.000000000 +0000 +++ vim73/runtime/doc/if_cscop.txt.orig 2010-08-15 12:23:20.000000000 +0000 @@ -0,0 +1,490 @@ +*if_cscop.txt* For Vim version 7.3. Last change: 2009 Mar 18 + + + VIM REFERENCE MANUAL by Andy Kahn + + *cscope* *Cscope* +This document explains how to use Vim's cscope interface. + +Cscope is a tool like ctags, but think of it as ctags on steroids since it +does a lot more than what ctags provides. In Vim, jumping to a result from +a cscope query is just like jumping to any tag; it is saved on the tag stack +so that with the right keyboard mappings, you can jump back and forth between +functions as you normally would with |tags|. + +1. Cscope introduction |cscope-intro| +2. Cscope related commands |cscope-commands| +3. Cscope options |cscope-options| +4. How to use cscope in Vim |cscope-howtouse| +5. Limitations |cscope-limitations| +6. Suggested usage |cscope-suggestions| +7. Availability & Information |cscope-info| + +This is currently for Unix and Win32 only. +{Vi does not have any of these commands} + +============================================================================== +1. Cscope introduction *cscope-intro* + +The following text is taken from a version of the cscope man page: + + ----- + + Cscope is an interactive screen-oriented tool that helps you: + + Learn how a C program works without endless flipping through a thick + listing. + + Locate the section of code to change to fix a bug without having to + learn the entire program. + + Examine the effect of a proposed change such as adding a value to an + enum variable. + + Verify that a change has been made in all source files such as adding + an argument to an existing function. + + Rename a global variable in all source files. + + Change a constant to a preprocessor symbol in selected lines of files. + + It is designed to answer questions like: + Where is this symbol used? + Where is it defined? + Where did this variable get its value? + What is this global symbol's definition? + Where is this function in the source files? + What functions call this function? + What functions are called by this function? + Where does the message "out of space" come from? + Where is this source file in the directory structure? + What files include this header file? + + Cscope answers these questions from a symbol database that it builds the + first time it is used on the source files. On a subsequent call, cscope + rebuilds the database only if a source file has changed or the list of + source files is different. When the database is rebuilt the data for the + unchanged files is copied from the old database, which makes rebuilding + much faster than the initial build. + + ----- + +When cscope is normally invoked, you will get a full-screen selection +screen allowing you to make a query for one of the above questions. +However, once a match is found to your query and you have entered your +text editor to edit the source file containing match, you cannot simply +jump from tag to tag as you normally would with vi's Ctrl-] or :tag +command. + +Vim's cscope interface is done by invoking cscope with its line-oriented +interface, and then parsing the output returned from a query. The end +result is that cscope query results become just like regular tags, so +you can jump to them just like you do with normal tags (Ctrl-] or :tag) +and then go back by popping off the tagstack with Ctrl-T. (Please note +however, that you don't actually jump to a cscope tag simply by doing +Ctrl-] or :tag without remapping these commands or setting an option. +See the remaining sections on how the cscope interface works and for +suggested use.) + + +============================================================================== +2. Cscope related commands *cscope-commands* + + *:cscope* *:cs* *:scs* *:scscope* *E259* *E262* *E561* *E560* +All cscope commands are accessed through suboptions to the main cscope +command ":cscope". The shortest abbreviation is ":cs". The ":scscope" +command does the same and also splits the window (short: "scs"). + +The available subcommands are: + + *E563* *E564* *E566* *E568* *E569* *E622* *E623* + *E625* *E626* *E609* + add : Add a new cscope database/connection. + + USAGE :cs add {file|dir} [pre-path] [flags] + + [pre-path] is the pathname used with the -P command to cscope. + + [flags] are any additional flags you want to pass to cscope. + + EXAMPLES > + :cscope add /usr/local/cdb/cscope.out + :cscope add /projects/vim/cscope.out /usr/local/vim + :cscope add cscope.out /usr/local/vim -C +< + *cscope-find* *cs-find* + *E565* *E567* + find : Query cscope. All cscope query options are available + except option #5 ("Change this grep pattern"). + + USAGE :cs find {querytype} {name} + + {querytype} corresponds to the actual cscope line + interface numbers as well as default nvi commands: + + 0 or s: Find this C symbol + 1 or g: Find this definition + 2 or d: Find functions called by this function + 3 or c: Find functions calling this function + 4 or t: Find this text string + 6 or e: Find this egrep pattern + 7 or f: Find this file + 8 or i: Find files #including this file + + For all types, except 4 and 6, leading white space for {name} is + removed. For 4 and 6 there is exactly one space between {querytype} + and {name}. Further white space is included in {name}. + + EXAMPLES > + :cscope find c vim_free + :cscope find 3 vim_free +< + These two examples perform the same query: functions calling + "vim_free". > + + :cscope find t initOnce + :cscope find t initOnce +< + The first one searches for the text "initOnce", the second one for + " initOnce". > + + :cscope find 0 DEFAULT_TERM +< + Executing this example on the source code for Vim 5.1 produces the + following output: + + Cscope tag: DEFAULT_TERM + # line filename / context / line + 1 1009 vim-5.1-gtk/src/term.c <> + #define DEFAULT_TERM (char_u *)"amiga" + 2 1013 vim-5.1-gtk/src/term.c <> + #define DEFAULT_TERM (char_u *)"win32" + 3 1017 vim-5.1-gtk/src/term.c <> + #define DEFAULT_TERM (char_u *)"pcterm" + 4 1021 vim-5.1-gtk/src/term.c <> + #define DEFAULT_TERM (char_u *)"ansi" + 5 1025 vim-5.1-gtk/src/term.c <> + #define DEFAULT_TERM (char_u *)"vt52" + 6 1029 vim-5.1-gtk/src/term.c <> + #define DEFAULT_TERM (char_u *)"os2ansi" + 7 1033 vim-5.1-gtk/src/term.c <> + #define DEFAULT_TERM (char_u *)"ansi" + 8 1037 vim-5.1-gtk/src/term.c <> + # undef DEFAULT_TERM + 9 1038 vim-5.1-gtk/src/term.c <> + #define DEFAULT_TERM (char_u *)"beos-ansi" + 10 1042 vim-5.1-gtk/src/term.c <> + #define DEFAULT_TERM (char_u *)"mac-ansi" + 11 1335 vim-5.1-gtk/src/term.c <> + term = DEFAULT_TERM; + 12 1459 vim-5.1-gtk/src/term.c <> + if (STRCMP(term, DEFAULT_TERM)) + 13 1826 vim-5.1-gtk/src/term.c <> + term = DEFAULT_TERM; + 14 1833 vim-5.1-gtk/src/term.c <> + term = DEFAULT_TERM; + 15 3635 vim-5.1-gtk/src/term.c <> + p = find_builtin_term(DEFAULT_TERM); + Enter nr of choice ( to abort): + + The output shows several pieces of information: + 1. The tag number (there are 15 in this example). + 2. The line number where the tag occurs. + 3. The filename where the tag occurs. + 4. The context of the tag (e.g., global, or the function name). + 5. The line from the file itself. + + help : Show a brief synopsis. + + USAGE :cs help + + *E260* *E261* + kill : Kill a cscope connection (or kill all cscope connections). + + USAGE :cs kill {num|partial_name} + + To kill a cscope connection, the connection number or a partial + name must be specified. The partial name is simply any part of + the pathname of the cscope database. Kill a cscope connection + using the partial name with caution! + + If the specified connection number is -1, then _ALL_ cscope + connections will be killed. + + reset : Reinit all cscope connections. + + USAGE :cs reset + + show : Show cscope connections. + + USAGE :cs show + + *:lcscope* *:lcs* +This command is same as the ":cscope" command, except when the +'cscopequickfix' option is set, the location list for the current window is +used instead of the quickfix list to show the cscope results. + + *:cstag* *E257* *E562* +If you use cscope as well as ctags, |:cstag| allows you to search one or +the other before making a jump. For example, you can choose to first +search your cscope database(s) for a match, and if one is not found, then +your tags file(s) will be searched. The order in which this happens +is determined by the value of |csto|. See |cscope-options| for more +details. + +|:cstag| performs the equivalent of ":cs find g" on the identifier when +searching through the cscope database(s). + +|:cstag| performs the equivalent of |:tjump| on the identifier when searching +through your tags file(s). + + +============================================================================== +3. Cscope options *cscope-options* + +Use the |:set| command to set all cscope options. Ideally, you would do +this in one of your startup files (e.g., .vimrc). Some cscope related +variables are only valid within |.vimrc|. Setting them after vim has +started will have no effect! + + *cscopeprg* *csprg* +'cscopeprg' specifies the command to execute cscope. The default is +"cscope". For example: > + :set csprg=/usr/local/bin/cscope +< + *cscopequickfix* *csqf* *E469* +{not available when compiled without the |+quickfix| feature} +'cscopequickfix' specifies whether to use quickfix window to show cscope +results. This is a list of comma-separated values. Each item consists of +|cscope-find| command (s, g, d, c, t, e, f or i) and flag (+, - or 0). +'+' indicates that results must be appended to quickfix window, +'-' implies previous results clearance, '0' or command absence - don't use +quickfix. Search is performed from start until first command occurrence. +The default value is "" (don't use quickfix anyway). The following value +seems to be useful: > + :set cscopequickfix=s-,c-,d-,i-,t-,e- +< + *cscopetag* *cst* +If 'cscopetag' set, the commands ":tag" and CTRL-] as well as "vim -t" will +always use |:cstag| instead of the default :tag behavior. Effectively, by +setting 'cst', you will always search your cscope databases as well as your +tag files. The default is off. Examples: > + :set cst + :set nocst +< + *cscopetagorder* *csto* +The value of 'csto' determines the order in which |:cstag| performs a search. +If 'csto' is set to zero, cscope database(s) are searched first, followed +by tag file(s) if cscope did not return any matches. If 'csto' is set to +one, tag file(s) are searched before cscope database(s). The default is zero. +Examples: > + :set csto=0 + :set csto=1 +< + *cscopeverbose* *csverb* +If 'cscopeverbose' is not set (the default), messages will not be printed +indicating success or failure when adding a cscope database. Ideally, you +should reset this option in your |.vimrc| before adding any cscope databases, +and after adding them, set it. From then on, when you add more databases +within Vim, you will get a (hopefully) useful message should the database fail +to be added. Examples: > + :set csverb + :set nocsverb +< + *cscopepathcomp* *cspc* +The value of 'cspc' determines how many components of a file's path to +display. With the default value of zero the entire path will be displayed. +The value one will display only the filename with no path. Other values +display that many components. For example: > + :set cspc=3 +will display the last 3 components of the file's path, including the file +name itself. + +============================================================================== +4. How to use cscope in Vim *cscope-howtouse* + +The first thing you need to do is to build a cscope database for your +source files. For the most basic case, simply do "cscope -b". Please +refer to the cscope man page for more details. + +Assuming you have a cscope database, you need to "add" the database to Vim. +This establishes a cscope "connection" and makes it available for Vim to use. +You can do this in your .vimrc file, or you can do it manually after starting +vim. For example, to add the cscope database "cscope.out", you would do: + + :cs add cscope.out + +You can double-check the result of this by executing ":cs show". This will +produce output which looks like this: + + # pid database name prepend path + 0 28806 cscope.out + +Note: +Because of the Microsoft RTL limitations, Win32 version shows 0 instead +of the real pid. + +Once a cscope connection is established, you can make queries to cscope and +the results will be printed to you. Queries are made using the command +":cs find". For example: + + :cs find g ALIGN_SIZE + +This can get a little cumbersome since one ends up doing a significant +amount of typing. Fortunately, there are ways around this by mapping +shortcut keys. See |cscope-suggestions| for suggested usage. + +If the results return only one match, you will automatically be taken to it. +If there is more than one match, you will be given a selection screen to pick +the match you want to go to. After you have jumped to the new location, +simply hit Ctrl-T to get back to the previous one. + + +============================================================================== +5. Limitations *cscope-limitations* + +Cscope support for Vim is only available on systems that support these four +system calls: fork(), pipe(), execl(), waitpid(). This means it is mostly +limited to Unix systems. + +Additionally Cscope support works for Win32. For more information and a +cscope version for Win32 see: + + http://iamphet.nm.ru/cscope/index.html + +The DJGPP-built version from http://cscope.sourceforge.net is known to not +work with Vim. + +Hard-coded limitation: doing a |:tjump| when |:cstag| searches the tag files +is not configurable (e.g., you can't do a tselect instead). + +============================================================================== +6. Suggested usage *cscope-suggestions* + +Put these entries in your .vimrc (adjust the pathname accordingly to your +setup): > + + if has("cscope") + set csprg=/usr/local/bin/cscope + set csto=0 + set cst + set nocsverb + " add any database in current directory + if filereadable("cscope.out") + cs add cscope.out + " else add database pointed to by environment + elseif $CSCOPE_DB != "" + cs add $CSCOPE_DB + endif + set csverb + endif + +By setting 'cscopetag', we have effectively replaced all instances of the :tag +command with :cstag. This includes :tag, Ctrl-], and "vim -t". In doing +this, the regular tag command not only searches your ctags generated tag +files, but your cscope databases as well. + +Some users may want to keep the regular tag behavior and have a different +shortcut to access :cstag. For example, one could map Ctrl-_ (underscore) +to :cstag with the following command: > + + map :cstag =expand("") + +A couple of very commonly used cscope queries (using ":cs find") is to +find all functions calling a certain function and to find all occurrences +of a particular C symbol. To do this, you can use these mappings as an +example: > + + map g :cs find 3 =expand("") + map g :cs find 0 =expand("") + +These mappings for Ctrl-] (right bracket) and Ctrl-\ (backslash) allow you to +place your cursor over the function name or C symbol and quickly query cscope +for any matches. + +Or you may use the following scheme, inspired by Vim/Cscope tutorial from +Cscope Home Page (http://cscope.sourceforge.net/): > + + nmap s :cs find s =expand("") + nmap g :cs find g =expand("") + nmap c :cs find c =expand("") + nmap t :cs find t =expand("") + nmap e :cs find e =expand("") + nmap f :cs find f =expand("") + nmap i :cs find i ^=expand("")$ + nmap d :cs find d =expand("") + + " Using 'CTRL-spacebar' then a search type makes the vim window + " split horizontally, with search result displayed in + " the new window. + + nmap s :scs find s =expand("") + nmap g :scs find g =expand("") + nmap c :scs find c =expand("") + nmap t :scs find t =expand("") + nmap e :scs find e =expand("") + nmap f :scs find f =expand("") + nmap i :scs find i ^=expand("")$ + nmap d :scs find d =expand("") + + " Hitting CTRL-space *twice* before the search type does a vertical + " split instead of a horizontal one + + nmap s + \:vert scs find s =expand("") + nmap g + \:vert scs find g =expand("") + nmap c + \:vert scs find c =expand("") + nmap t + \:vert scs find t =expand("") + nmap e + \:vert scs find e =expand("") + nmap i + \:vert scs find i ^=expand("")$ + nmap d + \:vert scs find d =expand("") + +============================================================================== +7. Cscope availability and information *cscope-info* + +If you do not already have cscope (it did not come with your compiler +license or OS distribution), then you can download it for free from: + http://cscope.sourceforge.net/ +This is released by SCO under the BSD license. + +If you want a newer version of cscope, you will probably have to buy it. +According to the (old) nvi documentation: + + You can buy version 13.3 source with an unrestricted license + for $400 from AT&T Software Solutions by calling +1-800-462-8146. + +Also you can download cscope 13.x and mlcscope 14.x (multi-lingual cscope +which supports C, C++, Java, lex, yacc, breakpoint listing, Ingres, and SDL) +from World-Wide Exptools Open Source packages page: + http://www.bell-labs.com/project/wwexptools/packages.html + +In Solaris 2.x, if you have the C compiler license, you will also have +cscope. Both are usually located under /opt/SUNWspro/bin + +SGI developers can also get it. Search for Cscope on this page: + http://freeware.sgi.com/index-by-alpha.html + https://toolbox.sgi.com/toolbox/utilities/cscope/ +The second one is for those who have a password for the SGI toolbox. + +There is source to an older version of a cscope clone (called "cs") available +on the net. Due to various reasons, this is not supported with Vim. + +The cscope interface/support for Vim was originally written by +Andy Kahn . The original structure (as well as a tiny +bit of code) was adapted from the cscope interface in nvi. Please report +any problems, suggestions, patches, et al., you have for the usage of +cscope within Vim to him. + *cscope-win32* +For a cscope version for Win32 see: + http://code.google.com/p/cscope-win32/ + +Win32 support was added by Sergey Khorev . Contact +him if you have Win32-specific issues. + + vim:tw=78:ts=8:ft=help:norl: diff -Naur vim73.orig/runtime/doc/if_lua.txt vim73/runtime/doc/if_lua.txt --- vim73.orig/runtime/doc/if_lua.txt 2010-08-15 12:23:20.000000000 +0000 +++ vim73/runtime/doc/if_lua.txt 2012-07-20 20:31:15.670976605 +0000 @@ -1,4 +1,4 @@ -*if_lua.txt* For Vim version 7.3. Last change: 2010 Jul 22 +*if_lua.txt* For Vim version 7.3. Last change: 2012 Jan 16 VIM REFERENCE MANUAL by Luis Carvalho @@ -8,8 +8,11 @@ 1. Commands |lua-commands| 2. The vim module |lua-vim| -3. Buffer userdata |lua-buffer| -4. Window userdata |lua-window| +3. List userdata |lua-list| +4. Dict userdata |lua-dict| +5. Buffer userdata |lua-buffer| +6. Window userdata |lua-window| +7. The luaeval function |lua-luaeval| {Vi does not have any of these commands} @@ -88,11 +91,9 @@ All these commands execute a Lua chunk from either the command line (:lua and :luado) or a file (:luafile) with the given line [range]. Similarly to the Lua interpreter, each chunk has its own scope and so only global variables are -shared between command calls. Lua default libraries "table", "string", "math", -and "package" are available, "io" and "debug" are not, and "os" is restricted -to functions "date", "clock", "time", "difftime", and "getenv". In addition, -Lua "print" function has its output redirected to the Vim message area, with -arguments separated by a white space instead of a tab. +shared between command calls. All Lua default libraries are available. In +addition, Lua "print" function has its output redirected to the Vim message +area, with arguments separated by a white space instead of a tab. Lua uses the "vim" module (see |lua-vim|) to issue commands to Vim and manage buffers (|lua-buffer|) and windows (|lua-window|). However, @@ -108,9 +109,9 @@ module also includes routines for buffer, window, and current line queries, Vim evaluation and command execution, and others. - vim.isbuffer(value) Returns 'true' (boolean, not string) if - "value" is a buffer userdata and 'false' - otherwise (see |lua-buffer|). + vim.list() Returns an empty list (see |List|). + + vim.dict() Returns an empty dictionary (see |Dictionary|). vim.buffer([arg]) If "arg" is a number, returns buffer with number "arg" in the buffer list or, if "arg" @@ -121,16 +122,21 @@ 'true' returns the first buffer in the buffer list or else the current buffer. - vim.iswindow(value) Returns 'true' (boolean, not string) if - "value" is a window userdata and - 'false' otherwise (see |lua-window|). - vim.window([arg]) If "arg" is a number, returns window with number "arg" or 'nil' (nil value, not string) if not found. Otherwise, if "toboolean(arg)" is 'true' returns the first window or else the current window. + vim.type({arg}) Returns the type of {arg}. It is equivalent to + Lua's "type" function, but returns "list", + "dict", "buffer", or "window" if {arg} is a + list, dictionary, buffer, or window, + respectively. Examples: > + :lua l = vim.list() + :lua print(type(l), vim.type(l)) + :" userdata list +< vim.command({cmd}) Executes the vim (ex-mode) command {cmd}. Examples: > :lua vim.command"set tw=60" @@ -141,7 +147,7 @@ Vim strings and numbers are directly converted to Lua strings and numbers respectively. Vim lists and dictionaries are converted to Lua - tables (lists become integer-keyed tables). + userdata (see |lua-list| and |lua-dict|). Examples: > :lua tw = vim.eval"&tw" :lua print(vim.eval"{'a': 'one'}".a) @@ -157,7 +163,72 @@ ============================================================================== -3. Buffer userdata *lua-buffer* +3. List userdata *lua-list* + +List userdata represent vim lists, and the interface tries to follow closely +Vim's syntax for lists. Since lists are objects, changes in list references in +Lua are reflected in Vim and vice-versa. A list "l" has the following +properties and methods: + +Properties +---------- + o "#l" is the number of items in list "l", equivalent to "len(l)" + in Vim. + o "l[k]" returns the k-th item in "l"; "l" is zero-indexed, as in Vim. + To modify the k-th item, simply do "l[k] = newitem"; in + particular, "l[k] = nil" removes the k-th item from "l". + o "l()" returns an iterator for "l". + +Methods +------- + o "l:add(item)" appends "item" to the end of "l". + o "l:insert(item[, pos])" inserts "item" at (optional) + position "pos" in the list. The default value for "pos" is 0. + +Examples: +> + :let l = [1, 'item'] + :lua l = vim.eval('l') -- same 'l' + :lua l:add(vim.list()) + :lua l[0] = math.pi + :echo l[0] " 3.141593 + :lua l[0] = nil -- remove first item + :lua l:insert(true, 1) + :lua print(l, #l, l[0], l[1], l[-1]) + :lua for item in l() do print(item) end +< + +============================================================================== +4. Dict userdata *lua-dict* + +Similarly to list userdata, dict userdata represent vim dictionaries; since +dictionaries are also objects, references are kept between Lua and Vim. A dict +"d" has the following properties: + +Properties +---------- + o "#d" is the number of items in dict "d", equivalent to "len(d)" + in Vim. + o "d.key" or "d['key']" returns the value at entry "key" in "d". + To modify the entry at this key, simply do "d.key = newvalue"; in + particular, "d.key = nil" removes the entry from "d". + o "d()" returns an iterator for "d" and is equivalent to "items(d)" in + Vim. + +Examples: +> + :let d = {'n':10} + :lua d = vim.eval('d') -- same 'd' + :lua print(d, d.n, #d) + :let d.self = d + :lua for k, v in d() do print(d, k, v) end + :lua d.x = math.pi + :lua d.self = nil -- remove entry + :echo d +< + +============================================================================== +5. Buffer userdata *lua-buffer* Buffer userdata represent vim buffers. A buffer userdata "b" has the following properties and methods: @@ -209,7 +280,7 @@ < ============================================================================== -4. Window userdata *lua-window* +6. Window userdata *lua-window* Window objects represent vim windows. A window userdata "w" has the following properties and methods: @@ -241,4 +312,29 @@ < ============================================================================== - vim:tw=78:ts=8:ft=help:norl: +7. The luaeval function *lua-luaeval* + +The (dual) equivalent of "vim.eval" for passing Lua values to Vim is +"luaeval". "luaeval" takes an expression string and an optional argument and +returns the result of the expression. It is semantically equivalent in Lua to: +> + local chunkheader = "local _A = select(1, ...) return " + function luaeval (expstr, arg) + local chunk = assert(loadstring(chunkheader .. expstr, "luaeval")) + return chunk(arg) -- return typval + end +< +Note that "_A" receives the argument to "luaeval". Examples: > + + :echo luaeval('math.pi') + :lua a = vim.list():add('newlist') + :let a = luaeval('a') + :echo a[0] " 'newlist' + :function Rand(x,y) " random uniform between x and y + : return luaeval('(_A.y-_A.x)*math.random()+_A.x', {'x':a:x,'y':a:y}) + : endfunction + :echo Rand(1,10) + + +============================================================================== + vim:tw=78:ts=8:noet:ft=help:norl: diff -Naur vim73.orig/runtime/doc/if_pyth.txt vim73/runtime/doc/if_pyth.txt --- vim73.orig/runtime/doc/if_pyth.txt 2010-08-15 12:23:20.000000000 +0000 +++ vim73/runtime/doc/if_pyth.txt 2012-07-20 20:31:17.307644444 +0000 @@ -1,4 +1,4 @@ -*if_pyth.txt* For Vim version 7.3. Last change: 2010 Aug 13 +*if_pyth.txt* For Vim version 7.3. Last change: 2012 Feb 04 VIM REFERENCE MANUAL by Paul Moore @@ -6,13 +6,14 @@ The Python Interface to Vim *python* *Python* -1. Commands |python-commands| -2. The vim module |python-vim| -3. Buffer objects |python-buffer| -4. Range objects |python-range| -5. Window objects |python-window| -6. Dynamic loading |python-dynamic| -7. Python 3 |python3| +1. Commands |python-commands| +2. The vim module |python-vim| +3. Buffer objects |python-buffer| +4. Range objects |python-range| +5. Window objects |python-window| +6. pyeval(), py3eval() Vim functions |python-pyeval| +7. Dynamic loading |python-dynamic| +8. Python 3 |python3| {Vi does not have any of these commands} @@ -150,6 +151,22 @@ [{'cmd': '/^eval_expr(arg, nextcmd)$/', 'static': 0, 'name': 'eval_expr', 'kind': 'f', 'filename': './src/eval.c'}] +vim.bindeval(str) *python-bindeval* + Like |python-eval|, but + 1. if expression evaluates to |List| or |Dictionary| it is returned as + vimlist or vimdictionary python type that are connected to original + list or dictionary. Thus modifications to these objects imply + modifications of the original. + 2. if expression evaluates to a function reference, then it returns + callable vimfunction object. Use self keyword argument to assign + |self| object for dictionary functions. + + Note: this function has the same behavior as |lua-eval| (except that + lua does not support running vim functions), |python-eval| is + kept for backwards compatibility in order not to make scripts + relying on outputs of vim.eval() being a copy of original or + vim.eval("1") returning a string. + Error object of the "vim" module @@ -222,8 +239,9 @@ - from indexing vim.buffers (|python-buffers|) - from the "buffer" attribute of a window (|python-window|) -Buffer objects have one read-only attribute - name - the full file name for -the buffer. They also have three methods (append, mark, and range; see below). +Buffer objects have two read-only attributes - name - the full file name for +the buffer, and number - the buffer number. They also have three methods +(append, mark, and range; see below). You can also treat buffer objects as sequence objects. In this context, they act as if they were lists (yes, they are mutable) of strings, with each @@ -318,7 +336,13 @@ The width attribute is writable only if the screen is split vertically. ============================================================================== -6. Dynamic loading *python-dynamic* +6. pyeval() and py3eval() Vim functions *python-pyeval* + +To facilitate bi-directional interface, you can use |pyeval()| and |py3eval()| +functions to evaluate Python expressions and pass their values to VimL. + +============================================================================== +7. Dynamic loading *python-dynamic* On MS-Windows the Python library can be loaded dynamically. The |:version| output then includes |+python/dyn|. @@ -335,13 +359,14 @@ sure edit "gvim.exe" and search for "python\d*.dll\c". ============================================================================== -7. Python 3 *python3* +8. Python 3 *python3* *:py3* *:python3* The |:py3| and |:python3| commands work similar to |:python|. *:py3file* The |:py3file| command works similar to |:pyfile|. + Vim can be built in four ways (:version output): 1. No Python support (-python, -python3) 2. Python 2 support only (+python or +python/dyn, -python3) @@ -355,7 +380,7 @@ When doing this on Linux/Unix systems and importing global symbols, this leads to a crash when the second Python version is used. So either global symbols are loaded but only one Python version is activated, or no global symbols are -loaded. The latter makes Python's "import" fail on libaries that expect the +loaded. The latter makes Python's "import" fail on libraries that expect the symbols to be provided by Vim. *E836* *E837* Vim's configuration script makes a guess for all libraries based on one @@ -377,6 +402,18 @@ 3. You undefine PY_NO_RTLD_GLOBAL in auto/config.h after configuration. This may crash Vim though. + *has-python* +You can test what Python version is available with: > + if has('python') + echo 'there is Python 2.x' + elseif has('python3') + echo 'there is Python 3.x' + endif + +Note however, that when Python 2 and 3 are both available and loaded +dynamically, these has() calls will try to load them. If only one can be +loaded at a time, just checking if Python 2 or 3 are available will prevent +the other one from being available. ============================================================================== vim:tw=78:ts=8:ft=help:norl: diff -Naur vim73.orig/runtime/doc/indent.txt vim73/runtime/doc/indent.txt --- vim73.orig/runtime/doc/indent.txt 2010-08-15 12:23:20.000000000 +0000 +++ vim73/runtime/doc/indent.txt 2012-07-20 20:31:15.707643298 +0000 @@ -128,13 +128,20 @@ used CTRL-T or CTRL-D. *cinoptions-values* -The 'cinoptions' option sets how Vim performs indentation. In the list below, +The 'cinoptions' option sets how Vim performs indentation. The value after +the option character can be one of these (N is any number): + N indent N spaces + -N indent N spaces to the left + Ns N times 'shiftwidth spaces + -Ns N times 'shiftwidth spaces to the left + +In the list below, "N" represents a number of your choice (the number can be negative). When there is an 's' after the number, Vim multiplies the number by 'shiftwidth': "1s" is 'shiftwidth', "2s" is two times 'shiftwidth', etc. You can use a -decimal point, too: "-0.5s" is minus half a 'shiftwidth'. The examples below -assume a 'shiftwidth' of 4. - +decimal point, too: "-0.5s" is minus half a 'shiftwidth'. +The examples below assume a 'shiftwidth' of 4. + *cino->* >N Amount added for "normal" indent. Used after a line that should increase the indent (lines starting with "if", an opening brace, etc.). (default 'shiftwidth'). @@ -145,6 +152,7 @@ foo; foo; foo; } } } < + *cino-e* eN Add N to the prevailing indent inside a set of braces if the opening brace at the End of the line (more precise: is not the first character in a line). This is useful if you want a @@ -160,6 +168,7 @@ bar; bar; bar; } } } < + *cino-n* nN Add N to the prevailing indent for a statement after an "if", "while", etc., if it is NOT inside a set of braces. This is useful if you want a different indent when there is no '{' @@ -174,6 +183,7 @@ bar; bar; bar; } } } < + *cino-f* fN Place the first opening brace of a function or other block in column N. This applies only for an opening brace that is not inside other braces and is at the start of the line. What comes @@ -184,6 +194,7 @@ { { { int foo; int foo; int foo; < + *cino-{* {N Place opening braces N characters from the prevailing indent. This applies only for opening braces that are inside other braces. (default 0). @@ -193,6 +204,7 @@ { { { foo; foo; foo; < + *cino-}* }N Place closing braces N characters from the matching opening brace. (default 0). @@ -202,6 +214,7 @@ foo; foo; foo; } } } < + *cino-^* ^N Add N to the prevailing indent inside a set of braces if the opening brace is in column 0. This can specify a different indent for whole of a function (some may like to set it to a @@ -216,6 +229,7 @@ } } } } } } < + *cino-L* LN Controls placement of jump labels. If N is negative, the label will be placed at column 1. If N is non-negative, the indent of the label will be the prevailing indent minus N. (default -1). @@ -229,6 +243,7 @@ } } } } } } < + *cino-:* :N Place case labels N characters from the indent of the switch(). (default 'shiftwidth'). @@ -240,6 +255,7 @@ default: default: } } < + *cino-=* =N Place statements occurring after a case label N characters from the indent of the label. (default 'shiftwidth'). @@ -247,6 +263,7 @@ case 11: case 11: a = a + 1; a = a + 1; b = b + 1; < + *cino-l* lN If N != 0 Vim will align with a case label instead of the statement after it in the same line. @@ -256,6 +273,7 @@ break; break; } } < + *cino-b* bN If N != 0 Vim will align a final "break" with the case label, so that case..break looks like a sort of block. (default: 0). @@ -271,6 +289,7 @@ break; break; } } < + *cino-g* gN Place C++ scope declarations N characters from the indent of the block they are in. (default 'shiftwidth'). A scope declaration can be "public:", "protected:" or "private:". @@ -282,6 +301,7 @@ private: private: } } < + *cino-h* hN Place statements occurring after a C++ scope declaration N characters from the indent of the label. (default 'shiftwidth'). @@ -290,6 +310,21 @@ public: public: a = a + 1; a = a + 1; b = b + 1; < + *cino-N* + NN Indent inside C++ namespace N characters extra compared to a + normal block. (default 0). + + cino= cino=N-s > + namespace { namespace { + void function(); void function(); + } } + + namespace my namespace my + { { + void function(); void function(); + } } +< + *cino-p* pN Parameter declarations for K&R-style function declarations will be indented N characters from the margin. (default 'shiftwidth'). @@ -299,6 +334,7 @@ int a; int a; int a; char b; char b; char b; < + *cino-t* tN Indent a function return type declaration N characters from the margin. (default 'shiftwidth'). @@ -306,6 +342,7 @@ int int int func() func() func() < + *cino-i* iN Indent C++ base class declarations and constructor initializations, if they start in a new line (otherwise they are aligned at the right side of the ':'). @@ -319,13 +356,18 @@ BaseClass(3) BaseClass(3) {} {} < - +N Indent a continuation line (a line that spills onto the next) N - additional characters. (default 'shiftwidth'). + *cino-+* + +N Indent a continuation line (a line that spills onto the next) + inside a function N additional characters. (default + 'shiftwidth'). + Outside of a function, when the previous line ended in a + backslash, the 2 * N is used. cino= cino=+10 > a = b + 9 * a = b + 9 * c; c; < + *cino-c* cN Indent comment lines after the comment opener, when there is no other text with which to align, N characters from the comment opener. (default 3). See also |format-comments|. @@ -335,6 +377,7 @@ text. text. */ */ < + *cino-C* CN When N is non-zero, indent comment lines by the amount specified with the c flag above even if there is other text behind the comment opener. (default 0). @@ -345,12 +388,14 @@ ********/ ********/ < (Example uses ":set comments& comments-=s1:/* comments^=s0:/*") + *cino-/* /N Indent comment lines N characters extra. (default 0). cino= cino=/4 > a = b; a = b; /* comment */ /* comment */ c = d; c = d; < + *cino-(* (N When in unclosed parentheses, indent N characters from the line with the unclosed parentheses. Add a 'shiftwidth' for every unclosed parentheses. When N is 0 or the unclosed parentheses @@ -366,6 +411,7 @@ (c2 || c3)) (c2 || c3)) { { < + *cino-u* uN Same as (N, but for one level deeper. (default 'shiftwidth'). cino= cino=u2 > @@ -373,6 +419,7 @@ && (c22345 && (c22345 || c3)) || c3)) < + *cino-U* UN When N is non-zero, do not ignore the indenting specified by ( or u in case that the unclosed parentheses is the first non-white character in its line. (default 0). @@ -384,6 +431,7 @@ c3 c3 ) && c4; ) && c4; < + *cino-2* wN When in unclosed parentheses and N is non-zero and either using "(0" or "u0", respectively, or using "U0" and the unclosed parentheses is the first non-white character in its line, line @@ -396,6 +444,7 @@ || c3)) || c3)) foo; foo; < + *cino-W* WN When in unclosed parentheses and N is non-zero and either using "(0" or "u0", respectively and the unclosed parentheses is the last non-white character in its line and it is not the @@ -410,6 +459,23 @@ a_short_line(argument, a_short_line(argument, argument); argument); < + *cino-k* + kN When in unclosed parentheses which follow "if", "for" or + "while" and N is non-zero, overrides the behaviour defined by + "(N": causes the indent to be N characters relative to the outer + context (i.e. the line where "if", "for" or "while" is). Has + no effect on deeper levels of nesting. Affects flags like "wN" + only for the "if", "for" and "while" conditions. If 0, defaults + to behaviour defined by the "(N" flag. (default: 0). + + cino=(0 cino=(0,ks > + if (condition1 if (condition1 + && condition2) && condition2) + action(); action(); + function(argument1 function(argument1 + && argument2); && argument2); +< + *cino-m* mN When N is non-zero, line up a line starting with a closing parentheses with the first character of the line with the matching opening parentheses. (default 0). @@ -424,6 +490,7 @@ ) ) foo; foo; < + *cino-M* MN When N is non-zero, line up a line starting with a closing parentheses with the first character of the previous line. (default 0). @@ -433,7 +500,7 @@ cond2 cond2 ) ) < - *java-cinoptions* *java-indenting* + *java-cinoptions* *java-indenting* *cino-j* jN Indent java anonymous classes correctly. The value 'N' is currently unused but must be non-zero (e.g. 'j1'). 'j1' will indent for example the following code snippet correctly: > @@ -444,7 +511,7 @@ } }); < - *javascript-cinoptions* *javascript-indenting* + *javascript-cinoptions* *javascript-indenting* *cino-J* JN Indent JavaScript object declarations correctly by not confusing them with labels. The value 'N' is currently unused but must be non-zero (e.g. 'J1'). > @@ -462,23 +529,28 @@ } } < + *cino-)* )N Vim searches for unclosed parentheses at most N lines away. This limits the time needed to search for parentheses. (default 20 lines). + *cino-star* *N Vim searches for unclosed comments at most N lines away. This limits the time needed to search for the start of a comment. + If your /* */ comments stop indenting afer N lines this is the + value you will want to change. (default 70 lines). + *cino-#* #N When N is non-zero recognize shell/Perl comments, starting with - '#'. Default N is zero: don't recognizes '#' comments. Note + '#'. Default N is zero: don't recognize '#' comments. Note that lines starting with # will still be seen as preprocessor lines. The defaults, spelled out in full, are: - cinoptions=>s,e0,n0,f0,{0,}0,^0,L-1,:s,=s,l0,b0,gs,hs,ps,ts,is,+s, - c3,C0,/0,(2s,us,U0,w0,W0,m0,j0,J0,)20,*70,#0 + cinoptions=>s,e0,n0,f0,{0,}0,^0,L-1,:s,=s,l0,b0,gs,hs,N0,ps,ts,is,+s, + c3,C0,/0,(2s,us,U0,w0,W0,k0,m0,j0,J0,)20,*70,#0 Vim puts a line in column 1 if: - It starts with '#' (preprocessor directives), if 'cinkeys' contains '#'. diff -Naur vim73.orig/runtime/doc/indent.txt.orig vim73/runtime/doc/indent.txt.orig --- vim73.orig/runtime/doc/indent.txt.orig 1970-01-01 00:00:00.000000000 +0000 +++ vim73/runtime/doc/indent.txt.orig 2010-08-15 12:23:20.000000000 +0000 @@ -0,0 +1,811 @@ +*indent.txt* For Vim version 7.3. Last change: 2010 Jul 30 + + + VIM REFERENCE MANUAL by Bram Moolenaar + + +This file is about indenting C programs and other files. + +1. Indenting C style programs |C-indenting| +2. Indenting by expression |indent-expression| + +============================================================================== +1. Indenting C style programs *C-indenting* + +The basics for C style indenting are explained in section |30.2| of the user +manual. + +Vim has options for automatically indenting C style program files. Many +programming languages including Java and C++ follow very closely the +formatting conventions established with C. These options affect only the +indent and do not perform other formatting. There are additional options that +affect other kinds of formatting as well as indenting, see |format-comments|, +|fo-table|, |gq| and |formatting| for the main ones. + +Note that this will not work when the |+smartindent| or |+cindent| features +have been disabled at compile time. + +There are in fact four main methods available for indentation, each one +overrides the previous if it is enabled, or non-empty for 'indentexpr': +'autoindent' uses the indent from the previous line. +'smartindent' is like 'autoindent' but also recognizes some C syntax to + increase/reduce the indent where appropriate. +'cindent' Works more cleverly than the other two and is configurable to + different indenting styles. +'indentexpr' The most flexible of all: Evaluates an expression to compute + the indent of a line. When non-empty this method overrides + the other ones. See |indent-expression|. +The rest of this section describes the 'cindent' option. + +Note that 'cindent' indenting does not work for every code scenario. Vim +is not a C compiler: it does not recognize all syntax. One requirement is +that toplevel functions have a '{' in the first column. Otherwise they are +easily confused with declarations. + +These four options control C program indenting: +'cindent' Enables Vim to perform C program indenting automatically. +'cinkeys' Specifies which keys trigger reindenting in insert mode. +'cinoptions' Sets your preferred indent style. +'cinwords' Defines keywords that start an extra indent in the next line. + +If 'lisp' is not on and 'equalprg' is empty, the "=" operator indents using +Vim's built-in algorithm rather than calling an external program. + +See |autocommand| for how to set the 'cindent' option automatically for C code +files and reset it for others. + + *cinkeys-format* *indentkeys-format* +The 'cinkeys' option is a string that controls Vim's indenting in response to +typing certain characters or commands in certain contexts. Note that this not +only triggers C-indenting. When 'indentexpr' is not empty 'indentkeys' is +used instead. The format of 'cinkeys' and 'indentkeys' is equal. + +The default is "0{,0},0),:,0#,!^F,o,O,e" which specifies that indenting occurs +as follows: + + "0{" if you type '{' as the first character in a line + "0}" if you type '}' as the first character in a line + "0)" if you type ')' as the first character in a line + ":" if you type ':' after a label or case statement + "0#" if you type '#' as the first character in a line + "!^F" if you type CTRL-F (which is not inserted) + "o" if you type a anywhere or use the "o" command (not in + insert mode!) + "O" if you use the "O" command (not in insert mode!) + "e" if you type the second 'e' for an "else" at the start of a + line + +Characters that can precede each key: *i_CTRL-F* +! When a '!' precedes the key, Vim will not insert the key but will + instead reindent the current line. This allows you to define a + command key for reindenting the current line. CTRL-F is the default + key for this. Be careful if you define CTRL-I for this because CTRL-I + is the ASCII code for . +* When a '*' precedes the key, Vim will reindent the line before + inserting the key. If 'cinkeys' contains "*", Vim reindents + the current line before opening a new line. +0 When a zero precedes the key (but appears after '!' or '*') Vim will + reindent the line only if the key is the first character you type in + the line. When used before "=" Vim will only reindent the line if + there is only white space before the word. + +When neither '!' nor '*' precedes the key, Vim reindents the line after you +type the key. So ';' sets the indentation of a line which includes the ';'. + +Special key names: +<> Angle brackets mean spelled-out names of keys. For example: "", + "" (see |key-notation|). +^ Letters preceded by a caret (^) are control characters. For example: + "^F" is CTRL-F. +o Reindent a line when you use the "o" command or when Vim opens a new + line below the current one (e.g., when you type in insert + mode). +O Reindent a line when you use the "O" command. +e Reindent a line that starts with "else" when you type the second 'e'. +: Reindent a line when a ':' is typed which is after a label or case + statement. Don't reindent for a ":" in "class::method" for C++. To + Reindent for any ":", use "<:>". +=word Reindent when typing the last character of "word". "word" may + actually be part of another word. Thus "=end" would cause reindenting + when typing the "d" in "endif" or "endwhile". But not when typing + "bend". Also reindent when completion produces a word that starts + with "word". "0=word" reindents when there is only white space before + the word. +=~word Like =word, but ignore case. + +If you really want to reindent when you type 'o', 'O', 'e', '0', '<', '>', +'*', ':' or '!', use "", "", "", "<0>", "<<>", "<>>", "<*>", "<:>" or +"", respectively, for those keys. + +For an emacs-style indent mode where lines aren't indented every time you +press but only if you press , I suggest: + :set cinkeys=0{,0},:,0#,!,!^F +You might also want to switch off 'autoindent' then. + +Note: If you change the current line's indentation manually, Vim ignores the +cindent settings for that line. This prevents vim from reindenting after you +have changed the indent by typing , , or in the indent or +used CTRL-T or CTRL-D. + + *cinoptions-values* +The 'cinoptions' option sets how Vim performs indentation. In the list below, +"N" represents a number of your choice (the number can be negative). When +there is an 's' after the number, Vim multiplies the number by 'shiftwidth': +"1s" is 'shiftwidth', "2s" is two times 'shiftwidth', etc. You can use a +decimal point, too: "-0.5s" is minus half a 'shiftwidth'. The examples below +assume a 'shiftwidth' of 4. + + >N Amount added for "normal" indent. Used after a line that should + increase the indent (lines starting with "if", an opening brace, + etc.). (default 'shiftwidth'). + + cino= cino=>2 cino=>2s > + if (cond) if (cond) if (cond) + { { { + foo; foo; foo; + } } } +< + eN Add N to the prevailing indent inside a set of braces if the + opening brace at the End of the line (more precise: is not the + first character in a line). This is useful if you want a + different indent when the '{' is at the start of the line from + when '{' is at the end of the line. (default 0). + + cino= cino=e2 cino=e-2 > + if (cond) { if (cond) { if (cond) { + foo; foo; foo; + } } } + else else else + { { { + bar; bar; bar; + } } } +< + nN Add N to the prevailing indent for a statement after an "if", + "while", etc., if it is NOT inside a set of braces. This is + useful if you want a different indent when there is no '{' + before the statement from when there is a '{' before it. + (default 0). + + cino= cino=n2 cino=n-2 > + if (cond) if (cond) if (cond) + foo; foo; foo; + else else else + { { { + bar; bar; bar; + } } } +< + fN Place the first opening brace of a function or other block in + column N. This applies only for an opening brace that is not + inside other braces and is at the start of the line. What comes + after the brace is put relative to this brace. (default 0). + + cino= cino=f.5s cino=f1s > + func() func() func() + { { { + int foo; int foo; int foo; +< + {N Place opening braces N characters from the prevailing indent. + This applies only for opening braces that are inside other + braces. (default 0). + + cino= cino={.5s cino={1s > + if (cond) if (cond) if (cond) + { { { + foo; foo; foo; +< + }N Place closing braces N characters from the matching opening + brace. (default 0). + + cino= cino={2,}-0.5s cino=}2 > + if (cond) if (cond) if (cond) + { { { + foo; foo; foo; + } } } +< + ^N Add N to the prevailing indent inside a set of braces if the + opening brace is in column 0. This can specify a different + indent for whole of a function (some may like to set it to a + negative number). (default 0). + + cino= cino=^-2 cino=^-s > + func() func() func() + { { { + if (cond) if (cond) if (cond) + { { { + a = b; a = b; a = b; + } } } + } } } +< + LN Controls placement of jump labels. If N is negative, the label + will be placed at column 1. If N is non-negative, the indent of + the label will be the prevailing indent minus N. (default -1). + + cino= cino=L2 cino=Ls > + func() func() func() + { { { + { { { + stmt; stmt; stmt; + LABEL: LABEL: LABEL: + } } } + } } } +< + :N Place case labels N characters from the indent of the switch(). + (default 'shiftwidth'). + + cino= cino=:0 > + switch (x) switch(x) + { { + case 1: case 1: + a = b; a = b; + default: default: + } } +< + =N Place statements occurring after a case label N characters from + the indent of the label. (default 'shiftwidth'). + + cino= cino==10 > + case 11: case 11: a = a + 1; + a = a + 1; b = b + 1; +< + lN If N != 0 Vim will align with a case label instead of the + statement after it in the same line. + + cino= cino=l1 > + switch (a) { switch (a) { + case 1: { case 1: { + break; break; + } } +< + bN If N != 0 Vim will align a final "break" with the case label, + so that case..break looks like a sort of block. (default: 0). + + cino= cino=b1 > + switch (x) switch(x) + { { + case 1: case 1: + a = b; a = b; + break; break; + + default: default: + a = 0; a = 0; + break; break; + } } +< + gN Place C++ scope declarations N characters from the indent of the + block they are in. (default 'shiftwidth'). A scope declaration + can be "public:", "protected:" or "private:". + + cino= cino=g0 > + { { + public: public: + a = b; a = b; + private: private: + } } +< + hN Place statements occurring after a C++ scope declaration N + characters from the indent of the label. (default + 'shiftwidth'). + + cino= cino=h10 > + public: public: a = a + 1; + a = a + 1; b = b + 1; +< + pN Parameter declarations for K&R-style function declarations will + be indented N characters from the margin. (default + 'shiftwidth'). + + cino= cino=p0 cino=p2s > + func(a, b) func(a, b) func(a, b) + int a; int a; int a; + char b; char b; char b; +< + tN Indent a function return type declaration N characters from the + margin. (default 'shiftwidth'). + + cino= cino=t0 cino=t7 > + int int int + func() func() func() +< + iN Indent C++ base class declarations and constructor + initializations, if they start in a new line (otherwise they + are aligned at the right side of the ':'). + (default 'shiftwidth'). + + cino= cino=i0 > + class MyClass : class MyClass : + public BaseClass public BaseClass + {} {} + MyClass::MyClass() : MyClass::MyClass() : + BaseClass(3) BaseClass(3) + {} {} +< + +N Indent a continuation line (a line that spills onto the next) N + additional characters. (default 'shiftwidth'). + + cino= cino=+10 > + a = b + 9 * a = b + 9 * + c; c; +< + cN Indent comment lines after the comment opener, when there is no + other text with which to align, N characters from the comment + opener. (default 3). See also |format-comments|. + + cino= cino=c5 > + /* /* + text. text. + */ */ +< + CN When N is non-zero, indent comment lines by the amount specified + with the c flag above even if there is other text behind the + comment opener. (default 0). + + cino=c0 cino=c0,C1 > + /******** /******** + text. text. + ********/ ********/ +< (Example uses ":set comments& comments-=s1:/* comments^=s0:/*") + + /N Indent comment lines N characters extra. (default 0). + cino= cino=/4 > + a = b; a = b; + /* comment */ /* comment */ + c = d; c = d; +< + (N When in unclosed parentheses, indent N characters from the line + with the unclosed parentheses. Add a 'shiftwidth' for every + unclosed parentheses. When N is 0 or the unclosed parentheses + is the first non-white character in its line, line up with the + next non-white character after the unclosed parentheses. + (default 'shiftwidth' * 2). + + cino= cino=(0 > + if (c1 && (c2 || if (c1 && (c2 || + c3)) c3)) + foo; foo; + if (c1 && if (c1 && + (c2 || c3)) (c2 || c3)) + { { +< + uN Same as (N, but for one level deeper. (default 'shiftwidth'). + + cino= cino=u2 > + if (c123456789 if (c123456789 + && (c22345 && (c22345 + || c3)) || c3)) +< + UN When N is non-zero, do not ignore the indenting specified by + ( or u in case that the unclosed parentheses is the first + non-white character in its line. (default 0). + + cino= or cino=(s cino=(s,U1 > + c = c1 && c = c1 && + ( ( + c2 || c2 || + c3 c3 + ) && c4; ) && c4; +< + wN When in unclosed parentheses and N is non-zero and either + using "(0" or "u0", respectively, or using "U0" and the unclosed + parentheses is the first non-white character in its line, line + up with the character immediately after the unclosed parentheses + rather than the first non-white character. (default 0). + + cino=(0 cino=(0,w1 > + if ( c1 if ( c1 + && ( c2 && ( c2 + || c3)) || c3)) + foo; foo; +< + WN When in unclosed parentheses and N is non-zero and either + using "(0" or "u0", respectively and the unclosed parentheses is + the last non-white character in its line and it is not the + closing parentheses, indent the following line N characters + relative to the outer context (i.e. start of the line or the + next unclosed parentheses). (default: 0). + + cino=(0 cino=(0,W4 > + a_long_line( a_long_line( + argument, argument, + argument); argument); + a_short_line(argument, a_short_line(argument, + argument); argument); +< + mN When N is non-zero, line up a line starting with a closing + parentheses with the first character of the line with the + matching opening parentheses. (default 0). + + cino=(s cino=(s,m1 > + c = c1 && ( c = c1 && ( + c2 || c2 || + c3 c3 + ) && c4; ) && c4; + if ( if ( + c1 && c2 c1 && c2 + ) ) + foo; foo; +< + MN When N is non-zero, line up a line starting with a closing + parentheses with the first character of the previous line. + (default 0). + + cino= cino=M1 > + if (cond1 && if (cond1 && + cond2 cond2 + ) ) +< + *java-cinoptions* *java-indenting* + jN Indent java anonymous classes correctly. The value 'N' is + currently unused but must be non-zero (e.g. 'j1'). 'j1' will + indent for example the following code snippet correctly: > + + object.add(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + do_something(); + } + }); +< + *javascript-cinoptions* *javascript-indenting* + JN Indent JavaScript object declarations correctly by not confusing + them with labels. The value 'N' is currently unused but must be + non-zero (e.g. 'J1'). > + + var bar = { + foo: { + that: this, + some: ok, + }, + "bar":{ + a : 2, + b: "123abc", + x: 4, + "y": 5 + } + } +< + )N Vim searches for unclosed parentheses at most N lines away. + This limits the time needed to search for parentheses. (default + 20 lines). + + *N Vim searches for unclosed comments at most N lines away. This + limits the time needed to search for the start of a comment. + (default 70 lines). + + #N When N is non-zero recognize shell/Perl comments, starting with + '#'. Default N is zero: don't recognizes '#' comments. Note + that lines starting with # will still be seen as preprocessor + lines. + + +The defaults, spelled out in full, are: + cinoptions=>s,e0,n0,f0,{0,}0,^0,L-1,:s,=s,l0,b0,gs,hs,ps,ts,is,+s, + c3,C0,/0,(2s,us,U0,w0,W0,m0,j0,J0,)20,*70,#0 + +Vim puts a line in column 1 if: +- It starts with '#' (preprocessor directives), if 'cinkeys' contains '#'. +- It starts with a label (a keyword followed by ':', other than "case" and + "default") and 'cinoptions' does not contain an 'L' entry with a positive + value. +- Any combination of indentations causes the line to have less than 0 + indentation. + +============================================================================== +2. Indenting by expression *indent-expression* + +The basics for using flexible indenting are explained in section |30.3| of the +user manual. + +If you want to write your own indent file, it must set the 'indentexpr' +option. Setting the 'indentkeys' option is often useful. See the +$VIMRUNTIME/indent directory for examples. + + +REMARKS ABOUT SPECIFIC INDENT FILES ~ + + +FORTRAN *ft-fortran-indent* + +Block if, select case, and where constructs are indented. Comments, labelled +statements and continuation lines are indented if the Fortran is in free +source form, whereas they are not indented if the Fortran is in fixed source +form because of the left margin requirements. Hence manual indent corrections +will be necessary for labelled statements and continuation lines when fixed +source form is being used. For further discussion of the method used for the +detection of source format see |ft-fortran-syntax|. + +Do loops ~ +All do loops are left unindented by default. Do loops can be unstructured in +Fortran with (possibly multiple) loops ending on a labelled executable +statement of almost arbitrary type. Correct indentation requires +compiler-quality parsing. Old code with do loops ending on labelled statements +of arbitrary type can be indented with elaborate programs such as Tidy +(http://www.unb.ca/chem/ajit/f_tidy.htm). Structured do/continue loops are +also left unindented because continue statements are also used for purposes +other than ending a do loop. Programs such as Tidy can convert structured +do/continue loops to the do/enddo form. Do loops of the do/enddo variety can +be indented. If you use only structured loops of the do/enddo form, you should +declare this by setting the fortran_do_enddo variable in your .vimrc as +follows > + + let fortran_do_enddo=1 + +in which case do loops will be indented. If all your loops are of do/enddo +type only in, say, .f90 files, then you should set a buffer flag with an +autocommand such as > + + au! BufRead,BufNewFile *.f90 let b:fortran_do_enddo=1 + +to get do loops indented in .f90 files and left alone in Fortran files with +other extensions such as .for. + + +PHP *ft-php-indent* *php-indent* *php-indenting* + +NOTE: PHP files will be indented correctly only if PHP |syntax| is active. + +If you are editing a file in Unix 'fileformat' and '\r' characters are present +before new lines, indentation won't proceed correctly ; you have to remove +those useless characters first with a command like: > + + :%s /\r$//g + +Or, you can simply |:let| the variable PHP_removeCRwhenUnix to 1 and the +script will silently remove them when Vim loads a PHP file (at each|BufRead|). + +OPTIONS: ~ + +PHP indenting can be altered in several ways by modifying the values of some +variables: + + *php-comment* +To not enable auto-formating of comments by default (if you want to use your +own 'formatoptions'): > + :let g:PHP_autoformatcomment = 0 + +Else, 't' will be removed from the 'formatoptions' string and "qrowcb" will be +added, see|fo-table|for more information. +------------- + +To add an extra indent to every PHP lines with N being the number of +'shiftwidth' to add: > + :let g:PHP_default_indenting = N + +For example, with N = 1, this will give: +> + +(Notice the extra indent between the PHP container markers and the code) +------------- + +To indent PHP tags as the surrounding code: > + :let g:PHP_outdentphpescape = 0 +------------- + +To automatically remove '\r' characters when the 'fileformat' is set to Unix: > + :let g:PHP_removeCRwhenUnix = 1 +------------- + +To indent braces at the same level than the code they contain: > + :let g:PHP_BracesAtCodeLevel = 1 + +This will give the following result: > + if ($foo) + { + foo(); + } +Instead of: > + if ($foo) + { + foo(); + } + +NOTE: Indenting will be a bit slower if this option is used because some + optimizations won't be available. +------------- + +To indent 'case:' and 'default:' statements in switch() blocks: > + :let g:PHP_vintage_case_default_indent = 1 + +(Since in PHP braces are not required inside 'case/default' blocks, by default they are indented at the same level than the 'switch()' to avoid +unnecessary indentation) + + +PYTHON *ft-python-indent* + +The amount of indent can be set for the following situations. The examples +given are the defaults. Note that the variables are set to an expression, so +that you can change the value of 'shiftwidth' later. + +Indent after an open paren: > + let g:pyindent_open_paren = '&sw * 2' +Indent after a nested paren: > + let g:pyindent_nested_paren = '&sw' +Indent for a continuation line: > + let g:pyindent_continue = '&sw * 2' + + +SHELL *ft-sh-indent* + +The amount of indent applied under various circumstances in a shell file can +be configured by setting the following keys in the |Dictionary| +b:sh_indent_defaults to a specific amount or to a |Funcref| that references a +function that will return the amount desired: + +b:sh_indent_options['default'] Default amount of indent. + +b:sh_indent_options['continuation-line'] + Amount of indent to add to a continued line. + +b:sh_indent_options['case-labels'] + Amount of indent to add for case labels. + (not actually implemented) + +b:sh_indent_options['case-statements'] + Amount of indent to add for case statements. + +b:sh_indent_options['case-breaks'] + Amount of indent to add (or more likely + remove) for case breaks. + +VERILOG *ft-verilog-indent* + +General block statements such as if, for, case, always, initial, function, +specify and begin, etc., are indented. The module block statements (first +level blocks) are not indented by default. you can turn on the indent with +setting a variable in the .vimrc as follows: > + + let b:verilog_indent_modules = 1 + +then the module blocks will be indented. To stop this, remove the variable: > + + :unlet b:verilog_indent_modules + +To set the variable only for Verilog file. The following statements can be +used: > + + au BufReadPost * if exists("b:current_syntax") + au BufReadPost * if b:current_syntax == "verilog" + au BufReadPost * let b:verilog_indent_modules = 1 + au BufReadPost * endif + au BufReadPost * endif + +Furthermore, setting the variable b:verilog_indent_width to change the +indenting width (default is 'shiftwidth'): > + + let b:verilog_indent_width = 4 + let b:verilog_indent_width = &sw * 2 + +In addition, you can turn the verbose mode for debug issue: > + + let b:verilog_indent_verbose = 1 + +Make sure to do ":set cmdheight=2" first to allow the display of the message. + + +VHDL *ft-vhdl-indent* + +Alignment of generic/port mapping statements are performed by default. This +causes the following alignment example: > + + ENTITY sync IS + PORT ( + clk : IN STD_LOGIC; + reset_n : IN STD_LOGIC; + data_input : IN STD_LOGIC; + data_out : OUT STD_LOGIC + ); + END ENTITY sync; + +To turn this off, add > + + let g:vhdl_indent_genportmap = 0 + +to the .vimrc file, which causes the previous alignment example to change: > + + ENTITY sync IS + PORT ( + clk : IN STD_LOGIC; + reset_n : IN STD_LOGIC; + data_input : IN STD_LOGIC; + data_out : OUT STD_LOGIC + ); + END ENTITY sync; + +---------------------------------------- + +Alignment of right-hand side assignment "<=" statements are performed by +default. This causes the following alignment example: > + + sig_out <= (bus_a(1) AND + (sig_b OR sig_c)) OR + (bus_a(0) AND sig_d); + +To turn this off, add > + + let g:vhdl_indent_rhsassign = 0 + +to the .vimrc file, which causes the previous alignment example to change: > + + sig_out <= (bus_a(1) AND + (sig_b OR sig_c)) OR + (bus_a(0) AND sig_d); + +---------------------------------------- + +Full-line comments (lines that begin with "--") are indented to be aligned with +the very previous line's comment, PROVIDED that a whitespace follows after +"--". + +For example: > + + sig_a <= sig_b; -- start of a comment + -- continuation of the comment + -- more of the same comment + +While in Insert mode, after typing "-- " (note the space " "), hitting CTRL-F +will align the current "-- " with the previous line's "--". + +If the very previous line does not contain "--", THEN the full-line comment +will be aligned with the start of the next non-blank line that is NOT a +full-line comment. + +Indenting the following code: > + + sig_c <= sig_d; -- comment 0 + -- comment 1 + -- comment 2 + --debug_code: + --PROCESS(debug_in) + --BEGIN + -- FOR i IN 15 DOWNTO 0 LOOP + -- debug_out(8*i+7 DOWNTO 8*i) <= debug_in(15-i); + -- END LOOP; + --END PROCESS debug_code; + + -- comment 3 + sig_e <= sig_f; -- comment 4 + -- comment 5 + +results in: > + + sig_c <= sig_d; -- comment 0 + -- comment 1 + -- comment 2 + --debug_code: + --PROCESS(debug_in) + --BEGIN + -- FOR i IN 15 DOWNTO 0 LOOP + -- debug_out(8*i+7 DOWNTO 8*i) <= debug_in(15-i); + -- END LOOP; + --END PROCESS debug_code; + + -- comment 3 + sig_e <= sig_f; -- comment 4 + -- comment 5 + +Notice that "--debug_code:" does not align with "-- comment 2" +because there is no whitespace that follows after "--" in "--debug_code:". + +Given the dynamic nature of indenting comments, indenting should be done TWICE. +On the first pass, code will be indented. On the second pass, full-line +comments will be indented according to the correctly indented code. + + +VIM *ft-vim-indent* + +For indenting Vim scripts there is one variable that specifies the amount of +indent for a continuation line, a line that starts with a backslash: > + + :let g:vim_indent_cont = &sw * 3 + +Three times shiftwidth is the default value. + + + vim:tw=78:ts=8:ft=help:norl: diff -Naur vim73.orig/runtime/doc/map.txt vim73/runtime/doc/map.txt --- vim73.orig/runtime/doc/map.txt 2010-08-15 12:23:21.000000000 +0000 +++ vim73/runtime/doc/map.txt 2012-07-20 20:31:16.060976885 +0000 @@ -226,7 +226,7 @@ For abbreviations |v:char| is set to the character that was typed to trigger the abbreviation. You can use this to decide how to expand the {lhs}. You -can't change v:char and you should not insert it. +you should not either insert or change the v:char. Be very careful about side effects! The expression is evaluated while obtaining characters, you may very well make the command dysfunctional. @@ -1202,20 +1202,28 @@ -complete=augroup autocmd groups -complete=buffer buffer names + -complete=behave :behave suboptions + -complete=color color schemes -complete=command Ex command (and arguments) + -complete=compiler compilers + -complete=cscope |:cscope| suboptions -complete=dir directory names -complete=environment environment variable names -complete=event autocommand events -complete=expression Vim expression -complete=file file and directory names + -complete=file_in_path file and directory names in |'path'| -complete=filetype filetype names |'filetype'| -complete=function function name -complete=help help subjects -complete=highlight highlight groups + -complete=history :history suboptions + -complete=locale locale names (as output of locale -a) -complete=mapping mapping name -complete=menu menus -complete=option options -complete=shellcmd Shell command + -complete=sign |:sign| suboptions -complete=syntax syntax file names |'syntax'| -complete=tag tags -complete=tag_listfiles tags, file names are shown when CTRL-D is hit diff -Naur vim73.orig/runtime/doc/motion.txt vim73/runtime/doc/motion.txt --- vim73.orig/runtime/doc/motion.txt 2010-08-15 12:23:21.000000000 +0000 +++ vim73/runtime/doc/motion.txt 2012-07-20 20:31:11.687640410 +0000 @@ -269,11 +269,11 @@ {char} can be entered like with the |f| command. *;* -; Repeat latest f, t, F or T [count] times. +; Repeat latest f, t, F or T [count] times. See |cpo-;| *,* , Repeat latest f, t, F or T in opposite direction - [count] times. + [count] times. See also |cpo-;| ============================================================================== 3. Up-down motions *up-down-motions* diff -Naur vim73.orig/runtime/doc/netbeans.txt vim73/runtime/doc/netbeans.txt --- vim73.orig/runtime/doc/netbeans.txt 2010-08-15 12:23:21.000000000 +0000 +++ vim73/runtime/doc/netbeans.txt 2012-07-20 20:31:13.184308154 +0000 @@ -1,4 +1,4 @@ -*netbeans.txt* For Vim version 7.3. Last change: 2010 Jul 20 +*netbeans.txt* For Vim version 7.3. Last change: 2011 Oct 20 VIM REFERENCE MANUAL by Gordon Prieur et al. @@ -118,7 +118,8 @@ uncommenting a line with "--disable-netbeans" in the Makefile. Currently the NetBeans interface is supported by Vim running in a terminal and -by GVim when it is run with one of the following GUIs: GTK, GNOME, and Motif. +by GVim when it is run with one of the following GUIs: GTK, GNOME, Windows, +Athena and Motif. If Motif support is required the user must supply XPM libraries. See |workshop-xpm| for details on obtaining the latest version of XPM. @@ -262,6 +263,12 @@ plain UTF-8 text this protocol could also be used with any other communication mechanism. +Netbeans messages are processed when Vim is idle, waiting for user input. +When Vim is run in non-interactive mode, for example when running an automated +test case that sources a Vim script, the idle loop may not be called often +enough. In that case, insert |sleep| commands in the Vim script. The |sleep| +command does invoke Netbeans messages processing. + 6.1 Kinds of messages |nb-messages| 6.2 Terms |nb-terms| 6.3 Commands |nb-commands| @@ -819,7 +826,7 @@ ============================================================================== 7. NetBeans commands *netbeans-commands* - *:nbstart* *E511* + *:nbstart* *E511* *E838* :nbs[tart] {connection} Start a new Netbeans session with {connection} as the socket connection parameters. The format of {connection} is described in |netbeans-parameters|. @@ -832,11 +839,16 @@ signs. *:nbkey* -:nb[key] {key} Pass the {key} to the Vim Controller for processing - -When a hot-key has been installed with the specialKeys command, this command -can be used to generate a hotkey messages to the Vim Controller. The events -newDotAndMark, keyCommand and keyAtPos are generated (in this order). +:nb[key] {key} Pass the {key} to the Vim Controller for processing. + When a hot-key has been installed with the specialKeys + command, this command can be used to generate a hotkey + message to the Vim Controller. + This command can also be used to pass any text to the + Vim Controller. It is used by Pyclewn, for example, + to build the complete set of gdb commands as Vim user + commands. + The events newDotAndMark, keyCommand and keyAtPos are + generated (in this order). ============================================================================== diff -Naur vim73.orig/runtime/doc/options.txt vim73/runtime/doc/options.txt --- vim73.orig/runtime/doc/options.txt 2010-08-15 12:23:21.000000000 +0000 +++ vim73/runtime/doc/options.txt 2012-07-20 20:31:18.044311638 +0000 @@ -150,6 +150,18 @@ (the ^[ is a real here, use CTRL-V to enter it) The advantage over a mapping is that it works in all situations. +You can define any key codes, e.g.: > + :set t_xy=^[foo; +There is no warning for using a name that isn't recognized. You can map these +codes as you like: > + :map something +< *E846* +When a key code is not set, it's like it does not exist. Trying to get its +value will result in an error: > + :set t_kb= + :set t_kb + E846: Key code not set: t_kb + The t_xx options cannot be set from a |modeline| or in the |sandbox|, for security reasons. @@ -1425,6 +1437,7 @@ This option is a list of comma separated names. These names are recognized: + *clipboard-unnamed* unnamed When included, Vim will use the clipboard register '*' for all yank, delete, change and put operations which would normally go to the unnamed register. When a @@ -1434,6 +1447,17 @@ explicitly accessed using the "* notation. Also see |gui-clipboard|. + *clipboard-unnamedplus* + unnamedplus A variant of "unnamed" flag which uses the clipboard + register '+' (|quoteplus|) instead of register '*' for + all operations except yank. Yank shall copy the text + into register '+' and also into '*' when "unnamed" is + included. + Only available with the |+X11| feature. + Availability can be checked with: > + if has('unnamedplus') +< + *clipboard-autoselect* autoselect Works like the 'a' flag in 'guioptions': If present, then whenever Visual mode is started, or the Visual area extended, Vim tries to become the owner of the @@ -1445,9 +1469,16 @@ "autoselect" flag is used. Also applies to the modeless selection. + *clipboard-autoselectplus* + autoselectplus Like "autoselect" but using the + register instead of + the * register. Compare to the 'P' flag in + 'guioptions'. + + *clipboard-autoselectml* autoselectml Like "autoselect", but for the modeless selection only. Compare to the 'A' flag in 'guioptions'. + *clipboard-html* html When the clipboard contains HTML, use this when pasting. When putting text on the clipboard, mark it as HTML. This works to copy rendered HTML from @@ -1458,6 +1489,7 @@ Only supported for GTK version 2 and later. Only available with the |+multi_byte| feature. + *clipboard-exclude* exclude:{pattern} Defines a pattern that is matched against the name of the terminal 'term'. If there is a match, no @@ -2069,6 +2101,12 @@ *cpo->* > When appending to a register, put a line break before the appended text. + *cpo-;* + ; When using |,| or |;| to repeat the last |t| search + and the cursor is right in front of the searched + character, the cursor won't move. When not included, + the cursor would skip over it and jump to the + following occurence. POSIX flags. These are not included in the Vi default value, except when $VIM_POSIX was set on startup. |posix| @@ -2161,6 +2199,16 @@ Specifies whether to use quickfix window to show cscope results. See |cscopequickfix|. + *'cscoperelative'* *'csre'* +'cscoperelative' 'csre' boolean (default off) + global + {not available when compiled without the |+cscope| + feature} + {not in Vi} + In the absence of a prefix (-P) for cscope. setting this option enables + to use the basename of cscope.out path as the prefix. + See |cscoperelative|. + *'cscopetag'* *'cst'* *'nocscopetag'* *'nocst'* 'cscopetag' 'cst' boolean (default off) global @@ -3510,6 +3558,9 @@ windowing system's global selection unless explicitly told to by a yank or delete operation for the "* register. The same applies to the modeless selection. + *'go-P'* + 'P' Like autoselect but using the "+ register instead of the "* + register. *'go-A'* 'A' Autoselect for the modeless selection. Like 'a', but only applies to the modeless selection. @@ -5843,16 +5894,21 @@ security reasons. *'shellcmdflag'* *'shcf'* -'shellcmdflag' 'shcf' string (default: "-c", MS-DOS and Win32, when 'shell' - does not contain "sh" somewhere: "/c") +'shellcmdflag' 'shcf' string (default: "-c"; + Win32, when 'shell' is cmd.exe: "/s /c"; + MS-DOS and Win32, when 'shell' neither is + cmd.exe nor contains "sh" somewhere: "/c") global {not in Vi} Flag passed to the shell to execute "!" and ":!" commands; e.g., "bash.exe -c ls" or "command.com /c dir". For the MS-DOS-like systems, the default is set according to the value of 'shell', to reduce the need to set this option by the user. It's not used for - OS/2 (EMX figures this out itself). See |option-backslash| about - including spaces and backslashes. See |dos-shell|. + OS/2 (EMX figures this out itself). + On Unix it can have more than one flag. Each white space separated + part is passed as an argument to the shell command. + See |option-backslash| about including spaces and backslashes. + Also see |dos-shell| for MS-DOS and MS-Windows. This option cannot be set from a |modeline| or in the |sandbox|, for security reasons. @@ -5873,9 +5929,10 @@ For Unix the default it "| tee". The stdout of the compiler is saved in a file and echoed to the screen. If the 'shell' option is "csh" or "tcsh" after initializations, the default becomes "|& tee". If the - 'shell' option is "sh", "ksh", "zsh" or "bash" the default becomes - "2>&1| tee". This means that stderr is also included. Before using - the 'shell' option a path is removed, thus "/bin/sh" uses "sh". + 'shell' option is "sh", "ksh", "mksh", "pdksh", "zsh" or "bash" the + default becomes "2>&1| tee". This means that stderr is also included. + Before using the 'shell' option a path is removed, thus "/bin/sh" uses + "sh". The initialization of this option is done after reading the ".vimrc" and the other initializations, so that when the 'shell' option is set there, the 'shellpipe' option changes automatically, unless it was @@ -5980,6 +6037,7 @@ *'shellxquote'* *'sxq'* 'shellxquote' 'sxq' string (default: ""; + for Win32, when 'shell' is cmd.exe: "(" for Win32, when 'shell' contains "sh" somewhere: "\"" for Unix, when using system(): "\"") @@ -5989,14 +6047,28 @@ the "!" and ":!" commands. Includes the redirection. See 'shellquote' to exclude the redirection. It's probably not useful to set both options. - This is an empty string by default. Known to be useful for - third-party shells when using the Win32 version, such as the MKS Korn - Shell or bash, where it should be "\"". The default is adjusted - according the value of 'shell', to reduce the need to set this option - by the user. See |dos-shell|. + When the value is '(' then ')' is appended. When the value is '"(' + then ')"' is appended. + When the value is '(' then also see 'shellxescape'. + This is an empty string by default on most systems, but is known to be + useful for on Win32 version, either for cmd.exe which automatically + strips off the first and last quote on a command, or 3rd-party shells + such as the MKS Korn Shell or bash, where it should be "\"". The + default is adjusted according the value of 'shell', to reduce the need + to set this option by the user. See |dos-shell|. This option cannot be set from a |modeline| or in the |sandbox|, for security reasons. + *'shellxescape'* *'sxe'* +'shellxescape' 'sxe' string (default: ""; + for MS-DOS and MS-Windows: "\"&|<>()@^") + global + {not in Vi} + When 'shellxquote' is set to "(" then the characters listed in this + option will be escaped with a '^' character. This makes it possible + to execute most external commands with cmd.exe. + + *'shiftround'* *'sr'* *'noshiftround'* *'nosr'* 'shiftround' 'sr' boolean (default off) global @@ -7530,8 +7602,9 @@ ! When included, save and restore global variables that start with an uppercase letter, and don't contain a lowercase letter. Thus "KEEPTHIS and "K_L_M" are stored, but "KeepThis" - and "_K_L_M" are not. Only String and Number types are - stored. + and "_K_L_M" are not. Nested List and Dict items may not be + read back correctly, you end up with a string representation + instead. " Maximum number of lines saved for each register. Old name of the '<' item, with the disadvantage that you need to put a backslash before the ", otherwise it will be recognized as the @@ -7747,6 +7820,17 @@ a pattern from the list. This avoids problems when a future version uses another default. + + *'wildignorecase* *'wic'* *'nowildignorecase* *'nowic'* +'wildignorecase' 'wic' boolean (default off) + global + {not in Vi} + When set case is ignored when completing file names and directories. + Has no effect on systems where file name case is generally ignored. + Does not apply when the shell is used to expand wildcards, which + happens when there are special characters. + + *'wildmenu'* *'wmnu'* *'nowildmenu'* *'nowmnu'* 'wildmenu' 'wmnu' boolean (default off) global diff -Naur vim73.orig/runtime/doc/options.txt.orig vim73/runtime/doc/options.txt.orig --- vim73.orig/runtime/doc/options.txt.orig 1970-01-01 00:00:00.000000000 +0000 +++ vim73/runtime/doc/options.txt.orig 2012-07-20 20:31:09.814305726 +0000 @@ -0,0 +1,8079 @@ +*options.txt* For Vim version 7.3. Last change: 2010 Aug 15 + + + VIM REFERENCE MANUAL by Bram Moolenaar + + +Options *options* + +1. Setting options |set-option| +2. Automatically setting options |auto-setting| +3. Options summary |option-summary| + +For an overview of options see help.txt |option-list|. + +Vim has a number of internal variables and switches which can be set to +achieve special effects. These options come in three forms: + boolean can only be on or off *boolean* *toggle* + number has a numeric value + string has a string value + +============================================================================== +1. Setting options *set-option* *E764* + + *:se* *:set* +:se[t] Show all options that differ from their default value. + +:se[t] all Show all but terminal options. + +:se[t] termcap Show all terminal options. Note that in the GUI the + key codes are not shown, because they are generated + internally and can't be changed. Changing the terminal + codes in the GUI is not useful either... + + *E518* *E519* +:se[t] {option}? Show value of {option}. + +:se[t] {option} Toggle option: set, switch it on. + Number option: show value. + String option: show value. + +:se[t] no{option} Toggle option: Reset, switch it off. + + *:set-!* *:set-inv* +:se[t] {option}! or +:se[t] inv{option} Toggle option: Invert value. {not in Vi} + + *:set-default* *:set-&* *:set-&vi* *:set-&vim* +:se[t] {option}& Reset option to its default value. May depend on the + current value of 'compatible'. {not in Vi} +:se[t] {option}&vi Reset option to its Vi default value. {not in Vi} +:se[t] {option}&vim Reset option to its Vim default value. {not in Vi} + +:se[t] all& Set all options, except terminal options, to their + default value. The values of 'term', 'lines' and + 'columns' are not changed. {not in Vi} + + *:set-args* *E487* *E521* +:se[t] {option}={value} or +:se[t] {option}:{value} + Set string or number option to {value}. + For numeric options the value can be given in decimal, + hex (preceded with 0x) or octal (preceded with '0') + (hex and octal are only available for machines which + have the strtol() function). + The old value can be inserted by typing 'wildchar' (by + default this is a or CTRL-E if 'compatible' is + set). See |cmdline-completion|. + White space between {option} and '=' is allowed and + will be ignored. White space between '=' and {value} + is not allowed. + See |option-backslash| for using white space and + backslashes in {value}. + +:se[t] {option}+={value} *:set+=* + Add the {value} to a number option, or append the + {value} to a string option. When the option is a + comma separated list, a comma is added, unless the + value was empty. + If the option is a list of flags, superfluous flags + are removed. When adding a flag that was already + present the option value doesn't change. + Also see |:set-args| above. + {not in Vi} + +:se[t] {option}^={value} *:set^=* + Multiply the {value} to a number option, or prepend + the {value} to a string option. When the option is a + comma separated list, a comma is added, unless the + value was empty. + Also see |:set-args| above. + {not in Vi} + +:se[t] {option}-={value} *:set-=* + Subtract the {value} from a number option, or remove + the {value} from a string option, if it is there. + If the {value} is not found in a string option, there + is no error or warning. When the option is a comma + separated list, a comma is deleted, unless the option + becomes empty. + When the option is a list of flags, {value} must be + exactly as they appear in the option. Remove flags + one by one to avoid problems. + Also see |:set-args| above. + {not in Vi} + +The {option} arguments to ":set" may be repeated. For example: > + :set ai nosi sw=3 ts=3 +If you make an error in one of the arguments, an error message will be given +and the following arguments will be ignored. + + *:set-verbose* +When 'verbose' is non-zero, displaying an option value will also tell where it +was last set. Example: > + :verbose set shiftwidth cindent? +< shiftwidth=4 ~ + Last set from modeline ~ + cindent ~ + Last set from /usr/local/share/vim/vim60/ftplugin/c.vim ~ +This is only done when specific option values are requested, not for ":verbose +set all" or ":verbose set" without an argument. +When the option was set by hand there is no "Last set" message. +When the option was set while executing a function, user command or +autocommand, the script in which it was defined is reported. +Note that an option may also have been set as a side effect of setting +'compatible'. +A few special texts: + Last set from modeline ~ + Option was set in a |modeline|. + Last set from --cmd argument ~ + Option was set with command line argument |--cmd| or +. + Last set from -c argument ~ + Option was set with command line argument |-c|, +, |-S| or + |-q|. + Last set from environment variable ~ + Option was set from an environment variable, $VIMINIT, + $GVIMINIT or $EXINIT. + Last set from error handler ~ + Option was cleared when evaluating it resulted in an error. + +{not available when compiled without the |+eval| feature} + + *:set-termcap* *E522* +For {option} the form "t_xx" may be used to set a terminal option. This will +override the value from the termcap. You can then use it in a mapping. If +the "xx" part contains special characters, use the form: > + :set =^[Ot +This can also be used to translate a special code for a normal key. For +example, if Alt-b produces b, use this: > + :set =^[b +(the ^[ is a real here, use CTRL-V to enter it) +The advantage over a mapping is that it works in all situations. + +You can define any key codes, e.g.: > + :set t_xy=^[foo; +There is no warning for using a name that isn't recognized. You can map these +codes as you like: > + :map something +< *E846* +When a key code is not set, it's like it does not exist. Trying to get its +value will result in an error: > + :set t_kb= + :set t_kb + E846: Key code not set: t_kb + +The t_xx options cannot be set from a |modeline| or in the |sandbox|, for +security reasons. + +The listing from ":set" looks different from Vi. Long string options are put +at the end of the list. The number of options is quite large. The output of +"set all" probably does not fit on the screen, causing Vim to give the +|more-prompt|. + + *option-backslash* +To include white space in a string option value it has to be preceded with a +backslash. To include a backslash you have to use two. Effectively this +means that the number of backslashes in an option value is halved (rounded +down). +A few examples: > + :set tags=tags\ /usr/tags results in "tags /usr/tags" + :set tags=tags\\,file results in "tags\,file" + :set tags=tags\\\ file results in "tags\ file" + +The "|" character separates a ":set" command from a following command. To +include the "|" in the option value, use "\|" instead. This example sets the +'titlestring' option to "hi|there": > + :set titlestring=hi\|there +This sets the 'titlestring' option to "hi" and 'iconstring' to "there": > + :set titlestring=hi|set iconstring=there + +Similarly, the double quote character starts a comment. To include the '"' in +the option value, use '\"' instead. This example sets the 'titlestring' +option to 'hi "there"': > + :set titlestring=hi\ \"there\" + +For MS-DOS and WIN32 backslashes in file names are mostly not removed. More +precise: For options that expect a file name (those where environment +variables are expanded) a backslash before a normal file name character is not +removed. But a backslash before a special character (space, backslash, comma, +etc.) is used like explained above. +There is one special situation, when the value starts with "\\": > + :set dir=\\machine\path results in "\\machine\path" + :set dir=\\\\machine\\path results in "\\machine\path" + :set dir=\\path\\file results in "\\path\file" (wrong!) +For the first one the start is kept, but for the second one the backslashes +are halved. This makes sure it works both when you expect backslashes to be +halved and when you expect the backslashes to be kept. The third gives a +result which is probably not what you want. Avoid it. + + *add-option-flags* *remove-option-flags* + *E539* *E550* *E551* *E552* +Some options are a list of flags. When you want to add a flag to such an +option, without changing the existing ones, you can do it like this: > + :set guioptions+=a +Remove a flag from an option like this: > + :set guioptions-=a +This removes the 'a' flag from 'guioptions'. +Note that you should add or remove one flag at a time. If 'guioptions' has +the value "ab", using "set guioptions-=ba" won't work, because the string "ba" +doesn't appear. + + *:set_env* *expand-env* *expand-environment-var* +Environment variables in specific string options will be expanded. If the +environment variable exists the '$' and the following environment variable +name is replaced with its value. If it does not exist the '$' and the name +are not modified. Any non-id character (not a letter, digit or '_') may +follow the environment variable name. That character and what follows is +appended to the value of the environment variable. Examples: > + :set term=$TERM.new + :set path=/usr/$INCLUDE,$HOME/include,. +When adding or removing a string from an option with ":set opt-=val" or ":set +opt+=val" the expansion is done before the adding or removing. + + +Handling of local options *local-options* + +Some of the options only apply to a window or buffer. Each window or buffer +has its own copy of this option, thus can each have their own value. This +allows you to set 'list' in one window but not in another. And set +'shiftwidth' to 3 in one buffer and 4 in another. + +The following explains what happens to these local options in specific +situations. You don't really need to know all of this, since Vim mostly uses +the option values you would expect. Unfortunately, doing what the user +expects is a bit complicated... + +When splitting a window, the local options are copied to the new window. Thus +right after the split the contents of the two windows look the same. + +When editing a new buffer, its local option values must be initialized. Since +the local options of the current buffer might be specifically for that buffer, +these are not used. Instead, for each buffer-local option there also is a +global value, which is used for new buffers. With ":set" both the local and +global value is changed. With "setlocal" only the local value is changed, +thus this value is not used when editing a new buffer. + +When editing a buffer that has been edited before, the last used window +options are used again. If this buffer has been edited in this window, the +values from back then are used. Otherwise the values from the window where +the buffer was edited last are used. + +It's possible to set a local window option specifically for a type of buffer. +When you edit another buffer in the same window, you don't want to keep +using these local window options. Therefore Vim keeps a global value of the +local window options, which is used when editing another buffer. Each window +has its own copy of these values. Thus these are local to the window, but +global to all buffers in the window. With this you can do: > + :e one + :set list + :e two +Now the 'list' option will also be set in "two", since with the ":set list" +command you have also set the global value. > + :set nolist + :e one + :setlocal list + :e two +Now the 'list' option is not set, because ":set nolist" resets the global +value, ":setlocal list" only changes the local value and ":e two" gets the +global value. Note that if you do this next: > + :e one +You will not get back the 'list' value as it was the last time you edited +"one". The options local to a window are not remembered for each buffer. + + *:setl* *:setlocal* +:setl[ocal] ... Like ":set" but set only the value local to the + current buffer or window. Not all options have a + local value. If the option does not have a local + value the global value is set. + With the "all" argument: display local values for all + local options. + Without argument: Display local values for all local + options which are different from the default. + When displaying a specific local option, show the + local value. For a global/local boolean option, when + the global value is being used, "--" is displayed + before the option name. + For a global option the global value is + shown (but that might change in the future). + {not in Vi} + +:setl[ocal] {option}< Set the local value of {option} to its global value by + copying the value. + {not in Vi} + +:se[t] {option}< Set the local value of {option} to its global value by + making it empty. Only makes sense for |global-local| + options. + {not in Vi} + + *:setg* *:setglobal* +:setg[lobal] ... Like ":set" but set only the global value for a local + option without changing the local value. + When displaying an option, the global value is shown. + With the "all" argument: display global values for all + local options. + Without argument: display global values for all local + options which are different from the default. + {not in Vi} + +For buffer-local and window-local options: + Command global value local value ~ + :set option=value set set + :setlocal option=value - set +:setglobal option=value set - + :set option? - display + :setlocal option? - display +:setglobal option? display - + + +Global options with a local value *global-local* + +Options are global when you mostly use one value for all buffers and windows. +For some global options it's useful to sometimes have a different local value. +You can set the local value with ":setlocal". That buffer or window will then +use the local value, while other buffers and windows continue using the global +value. + +For example, you have two windows, both on C source code. They use the global +'makeprg' option. If you do this in one of the two windows: > + :set makeprg=gmake +then the other window will switch to the same value. There is no need to set +the 'makeprg' option in the other C source window too. +However, if you start editing a Perl file in a new window, you want to use +another 'makeprg' for it, without changing the value used for the C source +files. You use this command: > + :setlocal makeprg=perlmake +You can switch back to using the global value by making the local value empty: > + :setlocal makeprg= +This only works for a string option. For a boolean option you need to use the +"<" flag, like this: > + :setlocal autoread< +Note that for non-boolean options using "<" copies the global value to the +local value, it doesn't switch back to using the global value (that matters +when the global value changes later). You can also use: > + :set path< +This will make the local value of 'path' empty, so that the global value is +used. Thus it does the same as: > + :setlocal path= +Note: In the future more global options can be made global-local. Using +":setlocal" on a global option might work differently then. + + +Setting the filetype + +:setf[iletype] {filetype} *:setf* *:setfiletype* + Set the 'filetype' option to {filetype}, but only if + not done yet in a sequence of (nested) autocommands. + This is short for: > + :if !did_filetype() + : setlocal filetype={filetype} + :endif +< This command is used in a filetype.vim file to avoid + setting the 'filetype' option twice, causing different + settings and syntax files to be loaded. + {not in Vi} + +:bro[wse] se[t] *:set-browse* *:browse-set* *:opt* *:options* +:opt[ions] Open a window for viewing and setting all options. + Options are grouped by function. + Offers short help for each option. Hit on the + short help to open a help window with more help for + the option. + Modify the value of the option and hit on the + "set" line to set the new value. For window and + buffer specific options, the last accessed window is + used to set the option value in, unless this is a help + window, in which case the window below help window is + used (skipping the option-window). + {not available when compiled without the |+eval| or + |+autocmd| features} + + *$HOME* +Using "~" is like using "$HOME", but it is only recognized at the start of an +option and after a space or comma. + +On Unix systems "~user" can be used too. It is replaced by the home directory +of user "user". Example: > + :set path=~mool/include,/usr/include,. + +On Unix systems the form "${HOME}" can be used too. The name between {} can +contain non-id characters then. Note that if you want to use this for the +"gf" command, you need to add the '{' and '}' characters to 'isfname'. + +NOTE: expanding environment variables and "~/" is only done with the ":set" +command, not when assigning a value to an option with ":let". + + +Note the maximum length of an expanded option is limited. How much depends on +the system, mostly it is something like 256 or 1024 characters. + + *:fix* *:fixdel* +:fix[del] Set the value of 't_kD': + 't_kb' is 't_kD' becomes ~ + CTRL-? CTRL-H + not CTRL-? CTRL-? + + (CTRL-? is 0177 octal, 0x7f hex) {not in Vi} + + If your delete key terminal code is wrong, but the + code for backspace is alright, you can put this in + your .vimrc: > + :fixdel +< This works no matter what the actual code for + backspace is. + + If the backspace key terminal code is wrong you can + use this: > + :if &term == "termname" + : set t_kb=^V + : fixdel + :endif +< Where "^V" is CTRL-V and "" is the backspace key + (don't type four characters!). Replace "termname" + with your terminal name. + + If your key sends a strange key sequence (not + CTRL-? or CTRL-H) you cannot use ":fixdel". Then use: > + :if &term == "termname" + : set t_kD=^V + :endif +< Where "^V" is CTRL-V and "" is the delete key + (don't type eight characters!). Replace "termname" + with your terminal name. + + *Linux-backspace* + Note about Linux: By default the backspace key + produces CTRL-?, which is wrong. You can fix it by + putting this line in your rc.local: > + echo "keycode 14 = BackSpace" | loadkeys +< + *NetBSD-backspace* + Note about NetBSD: If your backspace doesn't produce + the right code, try this: > + xmodmap -e "keycode 22 = BackSpace" +< If this works, add this in your .Xmodmap file: > + keysym 22 = BackSpace +< You need to restart for this to take effect. + +============================================================================== +2. Automatically setting options *auto-setting* + +Besides changing options with the ":set" command, there are three alternatives +to set options automatically for one or more files: + +1. When starting Vim initializations are read from various places. See + |initialization|. Most of them are performed for all editing sessions, + and some of them depend on the directory where Vim is started. + You can create an initialization file with |:mkvimrc|, |:mkview| and + |:mksession|. +2. If you start editing a new file, the automatic commands are executed. + This can be used to set options for files matching a particular pattern and + many other things. See |autocommand|. +3. If you start editing a new file, and the 'modeline' option is on, a + number of lines at the beginning and end of the file are checked for + modelines. This is explained here. + + *modeline* *vim:* *vi:* *ex:* *E520* +There are two forms of modelines. The first form: + [text]{white}{vi:|vim:|ex:}[white]{options} + +[text] any text or empty +{white} at least one blank character ( or ) +{vi:|vim:|ex:} the string "vi:", "vim:" or "ex:" +[white] optional white space +{options} a list of option settings, separated with white space or ':', + where each part between ':' is the argument for a ":set" + command (can be empty) + +Example: + vi:noai:sw=3 ts=6 ~ + +The second form (this is compatible with some versions of Vi): + + [text]{white}{vi:|vim:|ex:}[white]se[t] {options}:[text] + +[text] any text or empty +{white} at least one blank character ( or ) +{vi:|vim:|ex:} the string "vi:", "vim:" or "ex:" +[white] optional white space +se[t] the string "set " or "se " (note the space) +{options} a list of options, separated with white space, which is the + argument for a ":set" command +: a colon +[text] any text or empty + +Example: + /* vim: set ai tw=75: */ ~ + +The white space before {vi:|vim:|ex:} is required. This minimizes the chance +that a normal word like "lex:" is caught. There is one exception: "vi:" and +"vim:" can also be at the start of the line (for compatibility with version +3.0). Using "ex:" at the start of the line will be ignored (this could be +short for "example:"). + + *modeline-local* +The options are set like with ":setlocal": The new value only applies to the +buffer and window that contain the file. Although it's possible to set global +options from a modeline, this is unusual. If you have two windows open and +the files in it set the same global option to a different value, the result +depends on which one was opened last. + +When editing a file that was already loaded, only the window-local options +from the modeline are used. Thus if you manually changed a buffer-local +option after opening the file, it won't be changed if you edit the same buffer +in another window. But window-local options will be set. + + *modeline-version* +If the modeline is only to be used for some versions of Vim, the version +number can be specified where "vim:" is used: + vim{vers}: version {vers} or later + vim<{vers}: version before {vers} + vim={vers}: version {vers} + vim>{vers}: version after {vers} +{vers} is 600 for Vim 6.0 (hundred times the major version plus minor). +For example, to use a modeline only for Vim 6.0 and later: + /* vim600: set foldmethod=marker: */ ~ +To use a modeline for Vim before version 5.7: + /* vim<570: set sw=4: */ ~ +There can be no blanks between "vim" and the ":". + + +The number of lines that are checked can be set with the 'modelines' option. +If 'modeline' is off or 'modelines' is 0 no lines are checked. + +Note that for the first form all of the rest of the line is used, thus a line +like: + /* vi:ts=4: */ ~ +will give an error message for the trailing "*/". This line is OK: + /* vi:set ts=4: */ ~ + +If an error is detected the rest of the line is skipped. + +If you want to include a ':' in a set command precede it with a '\'. The +backslash in front of the ':' will be removed. Example: + /* vi:set dir=c\:\tmp: */ ~ +This sets the 'dir' option to "c:\tmp". Only a single backslash before the +':' is removed. Thus to include "\:" you have to specify "\\:". + +No other commands than "set" are supported, for security reasons (somebody +might create a Trojan horse text file with modelines). And not all options +can be set. For some options a flag is set, so that when it's used the +|sandbox| is effective. Still, there is always a small risk that a modeline +causes trouble. E.g., when some joker sets 'textwidth' to 5 all your lines +are wrapped unexpectedly. So disable modelines before editing untrusted text. +The mail ftplugin does this, for example. + +Hint: If you would like to do something else than setting an option, you could +define an autocommand that checks the file for a specific string. For +example: > + au BufReadPost * if getline(1) =~ "VAR" | call SetVar() | endif +And define a function SetVar() that does something with the line containing +"VAR". + +============================================================================== +3. Options summary *option-summary* + +In the list below all the options are mentioned with their full name and with +an abbreviation if there is one. Both forms may be used. + +In this document when a boolean option is "set" that means that ":set option" +is entered. When an option is "reset", ":set nooption" is used. + +For some options there are two default values: The "Vim default", which is +used when 'compatible' is not set, and the "Vi default", which is used when +'compatible' is set. + +Most options are the same in all windows and buffers. There are a few that +are specific to how the text is presented in a window. These can be set to a +different value in each window. For example the 'list' option can be set in +one window and reset in another for the same text, giving both types of view +at the same time. There are a few options that are specific to a certain +file. These can have a different value for each file or buffer. For example +the 'textwidth' option can be 78 for a normal text file and 0 for a C +program. + + global one option for all buffers and windows + local to window each window has its own copy of this option + local to buffer each buffer has its own copy of this option + +When creating a new window the option values from the currently active window +are used as a default value for the window-specific options. For the +buffer-specific options this depends on the 's' and 'S' flags in the +'cpoptions' option. If 's' is included (which is the default) the values for +buffer options are copied from the currently active buffer when a buffer is +first entered. If 'S' is present the options are copied each time the buffer +is entered, this is almost like having global options. If 's' and 'S' are not +present, the options are copied from the currently active buffer when the +buffer is created. + +Hidden options *hidden-options* + +Not all options are supported in all versions. This depends on the supported +features and sometimes on the system. A remark about this is in curly braces +below. When an option is not supported it may still be set without getting an +error, this is called a hidden option. You can't get the value of a hidden +option though, it is not stored. + +To test if option "foo" can be used with ":set" use something like this: > + if exists('&foo') +This also returns true for a hidden option. To test if option "foo" is really +supported use something like this: > + if exists('+foo') +< + *E355* +A jump table for the options with a short description can be found at |Q_op|. + + *'aleph'* *'al'* *aleph* *Aleph* +'aleph' 'al' number (default 128 for MS-DOS, 224 otherwise) + global + {not in Vi} + {only available when compiled with the |+rightleft| + feature} + The ASCII code for the first letter of the Hebrew alphabet. The + routine that maps the keyboard in Hebrew mode, both in Insert mode + (when hkmap is set) and on the command-line (when hitting CTRL-_) + outputs the Hebrew characters in the range [aleph..aleph+26]. + aleph=128 applies to PC code, and aleph=224 applies to ISO 8859-8. + See |rileft.txt|. + + *'allowrevins'* *'ari'* *'noallowrevins'* *'noari'* +'allowrevins' 'ari' boolean (default off) + global + {not in Vi} + {only available when compiled with the |+rightleft| + feature} + Allow CTRL-_ in Insert and Command-line mode. This is default off, to + avoid that users that accidentally type CTRL-_ instead of SHIFT-_ get + into reverse Insert mode, and don't know how to get out. See + 'revins'. + NOTE: This option is reset when 'compatible' is set. + + *'altkeymap'* *'akm'* *'noaltkeymap'* *'noakm'* +'altkeymap' 'akm' boolean (default off) + global + {not in Vi} + {only available when compiled with the |+farsi| + feature} + When on, the second language is Farsi. In editing mode CTRL-_ toggles + the keyboard map between Farsi and English, when 'allowrevins' set. + + When off, the keyboard map toggles between Hebrew and English. This + is useful to start the Vim in native mode i.e. English (left-to-right + mode) and have default second language Farsi or Hebrew (right-to-left + mode). See |farsi.txt|. + + *'ambiwidth'* *'ambw'* +'ambiwidth' 'ambw' string (default: "single") + global + {not in Vi} + {only available when compiled with the |+multi_byte| + feature} + Only effective when 'encoding' is "utf-8" or another Unicode encoding. + Tells Vim what to do with characters with East Asian Width Class + Ambiguous (such as Euro, Registered Sign, Copyright Sign, Greek + letters, Cyrillic letters). + + There are currently two possible values: + "single": Use the same width as characters in US-ASCII. This is + expected by most users. + "double": Use twice the width of ASCII characters. + *E834* *E835* + The value "double" cannot be used if 'listchars' or 'fillchars' + contains a character that would be double width. + + There are a number of CJK fonts for which the width of glyphs for + those characters are solely based on how many octets they take in + legacy/traditional CJK encodings. In those encodings, Euro, + Registered sign, Greek/Cyrillic letters are represented by two octets, + therefore those fonts have "wide" glyphs for them. This is also + true of some line drawing characters used to make tables in text + file. Therefore, when a CJK font is used for GUI Vim or + Vim is running inside a terminal (emulators) that uses a CJK font + (or Vim is run inside an xterm invoked with "-cjkwidth" option.), + this option should be set to "double" to match the width perceived + by Vim with the width of glyphs in the font. Perhaps it also has + to be set to "double" under CJK Windows 9x/ME or Windows 2k/XP + when the system locale is set to one of CJK locales. See Unicode + Standard Annex #11 (http://www.unicode.org/reports/tr11). + + *'antialias'* *'anti'* *'noantialias'* *'noanti'* +'antialias' 'anti' boolean (default: off) + global + {not in Vi} + {only available when compiled with GUI enabled + on Mac OS X} + This option only has an effect in the GUI version of Vim on Mac OS X + v10.2 or later. When on, Vim will use smooth ("antialiased") fonts, + which can be easier to read at certain sizes on certain displays. + Setting this option can sometimes cause problems if 'guifont' is set + to its default (empty string). + + *'autochdir'* *'acd'* *'noautochdir'* *'noacd'* +'autochdir' 'acd' boolean (default off) + global + {not in Vi} + {only available when compiled with it, use + exists("+autochdir") to check} + When on, Vim will change the current working directory whenever you + open a file, switch buffers, delete a buffer or open/close a window. + It will change to the directory containing the file which was opened + or selected. + This option is provided for backward compatibility with the Vim + released with Sun ONE Studio 4 Enterprise Edition. + Note: When this option is on some plugins may not work. + + *'arabic'* *'arab'* *'noarabic'* *'noarab'* +'arabic' 'arab' boolean (default off) + local to window + {not in Vi} + {only available when compiled with the |+arabic| + feature} + This option can be set to start editing Arabic text. + Setting this option will: + - Set the 'rightleft' option, unless 'termbidi' is set. + - Set the 'arabicshape' option, unless 'termbidi' is set. + - Set the 'keymap' option to "arabic"; in Insert mode CTRL-^ toggles + between typing English and Arabic key mapping. + - Set the 'delcombine' option + Note that 'encoding' must be "utf-8" for working with Arabic text. + + Resetting this option will: + - Reset the 'rightleft' option. + - Disable the use of 'keymap' (without changing its value). + Note that 'arabicshape' and 'delcombine' are not reset (it is a global + option. + Also see |arabic.txt|. + + *'arabicshape'* *'arshape'* + *'noarabicshape'* *'noarshape'* +'arabicshape' 'arshape' boolean (default on) + global + {not in Vi} + {only available when compiled with the |+arabic| + feature} + When on and 'termbidi' is off, the required visual character + corrections that need to take place for displaying the Arabic language + take affect. Shaping, in essence, gets enabled; the term is a broad + one which encompasses: + a) the changing/morphing of characters based on their location + within a word (initial, medial, final and stand-alone). + b) the enabling of the ability to compose characters + c) the enabling of the required combining of some characters + When disabled the display shows each character's true stand-alone + form. + Arabic is a complex language which requires other settings, for + further details see |arabic.txt|. + + *'autoindent'* *'ai'* *'noautoindent'* *'noai'* +'autoindent' 'ai' boolean (default off) + local to buffer + Copy indent from current line when starting a new line (typing + in Insert mode or when using the "o" or "O" command). If you do not + type anything on the new line except or CTRL-D and then type + , CTRL-O or , the indent is deleted again. Moving the cursor + to another line has the same effect, unless the 'I' flag is included + in 'cpoptions'. + When autoindent is on, formatting (with the "gq" command or when you + reach 'textwidth' in Insert mode) uses the indentation of the first + line. + When 'smartindent' or 'cindent' is on the indent is changed in + a different way. + The 'autoindent' option is reset when the 'paste' option is set. + {small difference from Vi: After the indent is deleted when typing + or , the cursor position when moving up or down is after the + deleted indent; Vi puts the cursor somewhere in the deleted indent}. + + *'autoread'* *'ar'* *'noautoread'* *'noar'* +'autoread' 'ar' boolean (default off) + global or local to buffer |global-local| + {not in Vi} + When a file has been detected to have been changed outside of Vim and + it has not been changed inside of Vim, automatically read it again. + When the file has been deleted this is not done. |timestamp| + If this option has a local value, use this command to switch back to + using the global value: > + :set autoread< +< + *'autowrite'* *'aw'* *'noautowrite'* *'noaw'* +'autowrite' 'aw' boolean (default off) + global + Write the contents of the file, if it has been modified, on each + :next, :rewind, :last, :first, :previous, :stop, :suspend, :tag, :!, + :make, CTRL-] and CTRL-^ command; and when a :buffer, CTRL-O, CTRL-I, + '{A-Z0-9}, or `{A-Z0-9} command takes one to another file. + Note that for some commands the 'autowrite' option is not used, see + 'autowriteall' for that. + + *'autowriteall'* *'awa'* *'noautowriteall'* *'noawa'* +'autowriteall' 'awa' boolean (default off) + global + {not in Vi} + Like 'autowrite', but also used for commands ":edit", ":enew", ":quit", + ":qall", ":exit", ":xit", ":recover" and closing the Vim window. + Setting this option also implies that Vim behaves like 'autowrite' has + been set. + + *'background'* *'bg'* +'background' 'bg' string (default "dark" or "light") + global + {not in Vi} + When set to "dark", Vim will try to use colors that look good on a + dark background. When set to "light", Vim will try to use colors that + look good on a light background. Any other value is illegal. + Vim tries to set the default value according to the terminal used. + This will not always be correct. + Setting this option does not change the background color, it tells Vim + what the background color looks like. For changing the background + color, see |:hi-normal|. + + When 'background' is set Vim will adjust the default color groups for + the new value. But the colors used for syntax highlighting will not + change. *g:colors_name* + When a color scheme is loaded (the "g:colors_name" variable is set) + setting 'background' will cause the color scheme to be reloaded. If + the color scheme adjusts to the value of 'background' this will work. + However, if the color scheme sets 'background' itself the effect may + be undone. First delete the "g:colors_name" variable when needed. + + When setting 'background' to the default value with: > + :set background& +< Vim will guess the value. In the GUI this should work correctly, + in other cases Vim might not be able to guess the right value. + + When starting the GUI, the default value for 'background' will be + "light". When the value is not set in the .gvimrc, and Vim detects + that the background is actually quite dark, 'background' is set to + "dark". But this happens only AFTER the .gvimrc file has been read + (because the window needs to be opened to find the actual background + color). To get around this, force the GUI window to be opened by + putting a ":gui" command in the .gvimrc file, before where the value + of 'background' is used (e.g., before ":syntax on"). + Normally this option would be set in the .vimrc file. Possibly + depending on the terminal name. Example: > + :if &term == "pcterm" + : set background=dark + :endif +< When this option is set, the default settings for the highlight groups + will change. To use other settings, place ":highlight" commands AFTER + the setting of the 'background' option. + This option is also used in the "$VIMRUNTIME/syntax/syntax.vim" file + to select the colors for syntax highlighting. After changing this + option, you must load syntax.vim again to see the result. This can be + done with ":syntax on". + + *'backspace'* *'bs'* +'backspace' 'bs' string (default "") + global + {not in Vi} + Influences the working of , , CTRL-W and CTRL-U in Insert + mode. This is a list of items, separated by commas. Each item allows + a way to backspace over something: + value effect ~ + indent allow backspacing over autoindent + eol allow backspacing over line breaks (join lines) + start allow backspacing over the start of insert; CTRL-W and CTRL-U + stop once at the start of insert. + + When the value is empty, Vi compatible backspacing is used. + + For backwards compatibility with version 5.4 and earlier: + value effect ~ + 0 same as ":set backspace=" (Vi compatible) + 1 same as ":set backspace=indent,eol" + 2 same as ":set backspace=indent,eol,start" + + See |:fixdel| if your or key does not do what you want. + NOTE: This option is set to "" when 'compatible' is set. + + *'backup'* *'bk'* *'nobackup'* *'nobk'* +'backup' 'bk' boolean (default off) + global + {not in Vi} + Make a backup before overwriting a file. Leave it around after the + file has been successfully written. If you do not want to keep the + backup file, but you do want a backup while the file is being + written, reset this option and set the 'writebackup' option (this is + the default). If you do not want a backup file at all reset both + options (use this if your file system is almost full). See the + |backup-table| for more explanations. + When the 'backupskip' pattern matches, a backup is not made anyway. + When 'patchmode' is set, the backup may be renamed to become the + oldest version of a file. + NOTE: This option is reset when 'compatible' is set. + + *'backupcopy'* *'bkc'* +'backupcopy' 'bkc' string (Vi default for Unix: "yes", otherwise: "auto") + global + {not in Vi} + When writing a file and a backup is made, this option tells how it's + done. This is a comma separated list of words. + + The main values are: + "yes" make a copy of the file and overwrite the original one + "no" rename the file and write a new one + "auto" one of the previous, what works best + + Extra values that can be combined with the ones above are: + "breaksymlink" always break symlinks when writing + "breakhardlink" always break hardlinks when writing + + Making a copy and overwriting the original file: + - Takes extra time to copy the file. + + When the file has special attributes, is a (hard/symbolic) link or + has a resource fork, all this is preserved. + - When the file is a link the backup will have the name of the link, + not of the real file. + + Renaming the file and writing a new one: + + It's fast. + - Sometimes not all attributes of the file can be copied to the new + file. + - When the file is a link the new file will not be a link. + + The "auto" value is the middle way: When Vim sees that renaming file + is possible without side effects (the attributes can be passed on and + the file is not a link) that is used. When problems are expected, a + copy will be made. + + The "breaksymlink" and "breakhardlink" values can be used in + combination with any of "yes", "no" and "auto". When included, they + force Vim to always break either symbolic or hard links by doing + exactly what the "no" option does, renaming the original file to + become the backup and writing a new file in its place. This can be + useful for example in source trees where all the files are symbolic or + hard links and any changes should stay in the local source tree, not + be propagated back to the original source. + *crontab* + One situation where "no" and "auto" will cause problems: A program + that opens a file, invokes Vim to edit that file, and then tests if + the open file was changed (through the file descriptor) will check the + backup file instead of the newly created file. "crontab -e" is an + example. + + When a copy is made, the original file is truncated and then filled + with the new text. This means that protection bits, owner and + symbolic links of the original file are unmodified. The backup file + however, is a new file, owned by the user who edited the file. The + group of the backup is set to the group of the original file. If this + fails, the protection bits for the group are made the same as for + others. + + When the file is renamed this is the other way around: The backup has + the same attributes of the original file, and the newly written file + is owned by the current user. When the file was a (hard/symbolic) + link, the new file will not! That's why the "auto" value doesn't + rename when the file is a link. The owner and group of the newly + written file will be set to the same ones as the original file, but + the system may refuse to do this. In that case the "auto" value will + again not rename the file. + + *'backupdir'* *'bdir'* +'backupdir' 'bdir' string (default for Amiga: ".,t:", + for MS-DOS and Win32: ".,c:/tmp,c:/temp" + for Unix: ".,~/tmp,~/") + global + {not in Vi} + List of directories for the backup file, separated with commas. + - The backup file will be created in the first directory in the list + where this is possible. The directory must exist, Vim will not + create it for you. + - Empty means that no backup file will be created ('patchmode' is + impossible!). Writing may fail because of this. + - A directory "." means to put the backup file in the same directory + as the edited file. + - A directory starting with "./" (or ".\" for MS-DOS et al.) means to + put the backup file relative to where the edited file is. The + leading "." is replaced with the path name of the edited file. + ("." inside a directory name has no special meaning). + - Spaces after the comma are ignored, other spaces are considered part + of the directory name. To have a space at the start of a directory + name, precede it with a backslash. + - To include a comma in a directory name precede it with a backslash. + - A directory name may end in an '/'. + - Environment variables are expanded |:set_env|. + - Careful with '\' characters, type one before a space, type two to + get one in the option (see |option-backslash|), for example: > + :set bdir=c:\\tmp,\ dir\\,with\\,commas,\\\ dir\ with\ spaces +< - For backwards compatibility with Vim version 3.0 a '>' at the start + of the option is removed. + See also 'backup' and 'writebackup' options. + If you want to hide your backup files on Unix, consider this value: > + :set backupdir=./.backup,~/.backup,.,/tmp +< You must create a ".backup" directory in each directory and in your + home directory for this to work properly. + The use of |:set+=| and |:set-=| is preferred when adding or removing + directories from the list. This avoids problems when a future version + uses another default. + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + *'backupext'* *'bex'* *E589* +'backupext' 'bex' string (default "~", for VMS: "_") + global + {not in Vi} + String which is appended to a file name to make the name of the + backup file. The default is quite unusual, because this avoids + accidentally overwriting existing files with a backup file. You might + prefer using ".bak", but make sure that you don't have files with + ".bak" that you want to keep. + Only normal file name characters can be used, "/\*?[|<>" are illegal. + + If you like to keep a lot of backups, you could use a BufWritePre + autocommand to change 'backupext' just before writing the file to + include a timestamp. > + :au BufWritePre * let &bex = '-' . strftime("%Y%b%d%X") . '~' +< Use 'backupdir' to put the backup in a different directory. + + *'backupskip'* *'bsk'* +'backupskip' 'bsk' string (default: "/tmp/*,$TMPDIR/*,$TMP/*,$TEMP/*") + global + {not in Vi} + {not available when compiled without the |+wildignore| + feature} + A list of file patterns. When one of the patterns matches with the + name of the file which is written, no backup file is created. Both + the specified file name and the full path name of the file are used. + The pattern is used like with |:autocmd|, see |autocmd-patterns|. + Watch out for special characters, see |option-backslash|. + When $TMPDIR, $TMP or $TEMP is not defined, it is not used for the + default value. "/tmp/*" is only used for Unix. + + Note that environment variables are not expanded. If you want to use + $HOME you must expand it explicitly, e.g.: > + :let backupskip = escape(expand('$HOME'), '\') . '/tmp/*' + +< Note that the default also makes sure that "crontab -e" works (when a + backup would be made by renaming the original file crontab won't see + the newly created file). Also see 'backupcopy' and |crontab|. + + *'balloondelay'* *'bdlay'* +'balloondelay' 'bdlay' number (default: 600) + global + {not in Vi} + {only available when compiled with the |+balloon_eval| + feature} + Delay in milliseconds before a balloon may pop up. See |balloon-eval|. + + *'ballooneval'* *'beval'* *'noballooneval'* *'nobeval'* +'ballooneval' 'beval' boolean (default off) + global + {not in Vi} + {only available when compiled with the |+balloon_eval| + feature} + Switch on the |balloon-eval| functionality. + + *'balloonexpr'* *'bexpr'* +'balloonexpr' 'bexpr' string (default "") + global or local to buffer |global-local| + {not in Vi} + {only available when compiled with the |+balloon_eval| + feature} + Expression for text to show in evaluation balloon. It is only used + when 'ballooneval' is on. These variables can be used: + + v:beval_bufnr number of the buffer in which balloon is going to show + v:beval_winnr number of the window + v:beval_lnum line number + v:beval_col column number (byte index) + v:beval_text word under or after the mouse pointer + + The evaluation of the expression must not have side effects! + Example: > + function! MyBalloonExpr() + return 'Cursor is at line ' . v:beval_lnum . + \', column ' . v:beval_col . + \ ' of file ' . bufname(v:beval_bufnr) . + \ ' on word "' . v:beval_text . '"' + endfunction + set bexpr=MyBalloonExpr() + set ballooneval +< + NOTE: The balloon is displayed only if the cursor is on a text + character. If the result of evaluating 'balloonexpr' is not empty, + Vim does not try to send a message to an external debugger (Netbeans + or Sun Workshop). + + The expression may be evaluated in the |sandbox|, see + |sandbox-option|. + + It is not allowed to change text or jump to another window while + evaluating 'balloonexpr' |textlock|. + + To check whether line breaks in the balloon text work use this check: > + if has("balloon_multiline") +< When they are supported "\n" characters will start a new line. If the + expression evaluates to a |List| this is equal to using each List item + as a string and putting "\n" in between them. + + *'binary'* *'bin'* *'nobinary'* *'nobin'* +'binary' 'bin' boolean (default off) + local to buffer + {not in Vi} + This option should be set before editing a binary file. You can also + use the |-b| Vim argument. When this option is switched on a few + options will be changed (also when it already was on): + 'textwidth' will be set to 0 + 'wrapmargin' will be set to 0 + 'modeline' will be off + 'expandtab' will be off + Also, 'fileformat' and 'fileformats' options will not be used, the + file is read and written like 'fileformat' was "unix" (a single + separates lines). + The 'fileencoding' and 'fileencodings' options will not be used, the + file is read without conversion. + NOTE: When you start editing a(nother) file while the 'bin' option is + on, settings from autocommands may change the settings again (e.g., + 'textwidth'), causing trouble when editing. You might want to set + 'bin' again when the file has been loaded. + The previous values of these options are remembered and restored when + 'bin' is switched from on to off. Each buffer has its own set of + saved option values. + To edit a file with 'binary' set you can use the |++bin| argument. + This avoids you have to do ":set bin", which would have effect for all + files you edit. + When writing a file the for the last line is only written if + there was one in the original file (normally Vim appends an to + the last line if there is none; this would make the file longer). See + the 'endofline' option. + + *'bioskey'* *'biosk'* *'nobioskey'* *'nobiosk'* +'bioskey' 'biosk' boolean (default on) + global + {not in Vi} {only for MS-DOS} + When on the BIOS is called to obtain a keyboard character. This works + better to detect CTRL-C, but only works for the console. When using a + terminal over a serial port reset this option. + Also see |'conskey'|. + + *'bomb'* *'nobomb'* +'bomb' boolean (default off) + local to buffer + {not in Vi} + {only available when compiled with the |+multi_byte| + feature} + When writing a file and the following conditions are met, a BOM (Byte + Order Mark) is prepended to the file: + - this option is on + - the 'binary' option is off + - 'fileencoding' is "utf-8", "ucs-2", "ucs-4" or one of the little/big + endian variants. + Some applications use the BOM to recognize the encoding of the file. + Often used for UCS-2 files on MS-Windows. For other applications it + causes trouble, for example: "cat file1 file2" makes the BOM of file2 + appear halfway the resulting file. Gcc doesn't accept a BOM. + When Vim reads a file and 'fileencodings' starts with "ucs-bom", a + check for the presence of the BOM is done and 'bomb' set accordingly. + Unless 'binary' is set, it is removed from the first line, so that you + don't see it when editing. When you don't change the options, the BOM + will be restored when writing the file. + + *'breakat'* *'brk'* +'breakat' 'brk' string (default " ^I!@*-+;:,./?") + global + {not in Vi} + {not available when compiled without the |+linebreak| + feature} + This option lets you choose which characters might cause a line + break if 'linebreak' is on. Only works for ASCII and also for 8-bit + characters when 'encoding' is an 8-bit encoding. + + *'browsedir'* *'bsdir'* +'browsedir' 'bsdir' string (default: "last") + global + {not in Vi} {only for Motif, Athena, GTK, Mac and + Win32 GUI} + Which directory to use for the file browser: + last Use same directory as with last file browser, where a + file was opened or saved. + buffer Use the directory of the related buffer. + current Use the current directory. + {path} Use the specified directory + + *'bufhidden'* *'bh'* +'bufhidden' 'bh' string (default: "") + local to buffer + {not in Vi} + {not available when compiled without the |+quickfix| + feature} + This option specifies what happens when a buffer is no longer + displayed in a window: + follow the global 'hidden' option + hide hide the buffer (don't unload it), also when 'hidden' + is not set + unload unload the buffer, also when 'hidden' is set or using + |:hide| + delete delete the buffer from the buffer list, also when + 'hidden' is set or using |:hide|, like using + |:bdelete| + wipe wipe out the buffer from the buffer list, also when + 'hidden' is set or using |:hide|, like using + |:bwipeout| + + CAREFUL: when "unload", "delete" or "wipe" is used changes in a buffer + are lost without a warning. + This option is used together with 'buftype' and 'swapfile' to specify + special kinds of buffers. See |special-buffers|. + + *'buflisted'* *'bl'* *'nobuflisted'* *'nobl'* *E85* +'buflisted' 'bl' boolean (default: on) + local to buffer + {not in Vi} + When this option is set, the buffer shows up in the buffer list. If + it is reset it is not used for ":bnext", "ls", the Buffers menu, etc. + This option is reset by Vim for buffers that are only used to remember + a file name or marks. Vim sets it when starting to edit a buffer. + But not when moving to a buffer with ":buffer". + + *'buftype'* *'bt'* *E382* +'buftype' 'bt' string (default: "") + local to buffer + {not in Vi} + {not available when compiled without the |+quickfix| + feature} + The value of this option specifies the type of a buffer: + normal buffer + nofile buffer which is not related to a file and will not be + written + nowrite buffer which will not be written + acwrite buffer which will always be written with BufWriteCmd + autocommands. {not available when compiled without the + |+autocmd| feature} + quickfix quickfix buffer, contains list of errors |:cwindow| + or list of locations |:lwindow| + help help buffer (you are not supposed to set this + manually) + + This option is used together with 'bufhidden' and 'swapfile' to + specify special kinds of buffers. See |special-buffers|. + + Be careful with changing this option, it can have many side effects! + + A "quickfix" buffer is only used for the error list and the location + list. This value is set by the |:cwindow| and |:lwindow| commands and + you are not supposed to change it. + + "nofile" and "nowrite" buffers are similar: + both: The buffer is not to be written to disk, ":w" doesn't + work (":w filename" does work though). + both: The buffer is never considered to be |'modified'|. + There is no warning when the changes will be lost, for + example when you quit Vim. + both: A swap file is only created when using too much memory + (when 'swapfile' has been reset there is never a swap + file). + nofile only: The buffer name is fixed, it is not handled like a + file name. It is not modified in response to a |:cd| + command. + *E676* + "acwrite" implies that the buffer name is not related to a file, like + "nofile", but it will be written. Thus, in contrast to "nofile" and + "nowrite", ":w" does work and a modified buffer can't be abandoned + without saving. For writing there must be matching |BufWriteCmd|, + |FileWriteCmd| or |FileAppendCmd| autocommands. + + *'casemap'* *'cmp'* +'casemap' 'cmp' string (default: "internal,keepascii") + global + {not in Vi} + {only available when compiled with the |+multi_byte| + feature} + Specifies details about changing the case of letters. It may contain + these words, separated by a comma: + internal Use internal case mapping functions, the current + locale does not change the case mapping. This only + matters when 'encoding' is a Unicode encoding, + "latin1" or "iso-8859-15". When "internal" is + omitted, the towupper() and towlower() system library + functions are used when available. + keepascii For the ASCII characters (0x00 to 0x7f) use the US + case mapping, the current locale is not effective. + This probably only matters for Turkish. + + *'cdpath'* *'cd'* *E344* *E346* +'cdpath' 'cd' string (default: equivalent to $CDPATH or ",,") + global + {not in Vi} + {not available when compiled without the + |+file_in_path| feature} + This is a list of directories which will be searched when using the + |:cd| and |:lcd| commands, provided that the directory being searched + for has a relative path, not an absolute part starting with "/", "./" + or "../", the 'cdpath' option is not used then. + The 'cdpath' option's value has the same form and semantics as + |'path'|. Also see |file-searching|. + The default value is taken from $CDPATH, with a "," prepended to look + in the current directory first. + If the default value taken from $CDPATH is not what you want, include + a modified version of the following command in your vimrc file to + override it: > + :let &cdpath = ',' . substitute(substitute($CDPATH, '[, ]', '\\\0', 'g'), ':', ',', 'g') +< This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + (parts of 'cdpath' can be passed to the shell to expand file names). + + *'cedit'* +'cedit' string (Vi default: "", Vim default: CTRL-F) + global + {not in Vi} + {not available when compiled without the |+vertsplit| + feature} + The key used in Command-line Mode to open the command-line window. + The default is CTRL-F when 'compatible' is off. + Only non-printable keys are allowed. + The key can be specified as a single character, but it is difficult to + type. The preferred way is to use the <> notation. Examples: > + :set cedit= + :set cedit= +< |Nvi| also has this option, but it only uses the first character. + See |cmdwin|. + + *'charconvert'* *'ccv'* *E202* *E214* *E513* +'charconvert' 'ccv' string (default "") + global + {only available when compiled with the |+multi_byte| + and |+eval| features} + {not in Vi} + An expression that is used for character encoding conversion. It is + evaluated when a file that is to be read or has been written has a + different encoding from what is desired. + 'charconvert' is not used when the internal iconv() function is + supported and is able to do the conversion. Using iconv() is + preferred, because it is much faster. + 'charconvert' is not used when reading stdin |--|, because there is no + file to convert from. You will have to save the text in a file first. + The expression must return zero or an empty string for success, + non-zero for failure. + The possible encoding names encountered are in 'encoding'. + Additionally, names given in 'fileencodings' and 'fileencoding' are + used. + Conversion between "latin1", "unicode", "ucs-2", "ucs-4" and "utf-8" + is done internally by Vim, 'charconvert' is not used for this. + 'charconvert' is also used to convert the viminfo file, if the 'c' + flag is present in 'viminfo'. Also used for Unicode conversion. + Example: > + set charconvert=CharConvert() + fun CharConvert() + system("recode " + \ . v:charconvert_from . ".." . v:charconvert_to + \ . " <" . v:fname_in . " >" v:fname_out) + return v:shell_error + endfun +< The related Vim variables are: + v:charconvert_from name of the current encoding + v:charconvert_to name of the desired encoding + v:fname_in name of the input file + v:fname_out name of the output file + Note that v:fname_in and v:fname_out will never be the same. + Note that v:charconvert_from and v:charconvert_to may be different + from 'encoding'. Vim internally uses UTF-8 instead of UCS-2 or UCS-4. + Encryption is not done by Vim when using 'charconvert'. If you want + to encrypt the file after conversion, 'charconvert' should take care + of this. + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + *'cindent'* *'cin'* *'nocindent'* *'nocin'* +'cindent' 'cin' boolean (default off) + local to buffer + {not in Vi} + {not available when compiled without the |+cindent| + feature} + Enables automatic C program indenting. See 'cinkeys' to set the keys + that trigger reindenting in insert mode and 'cinoptions' to set your + preferred indent style. + If 'indentexpr' is not empty, it overrules 'cindent'. + If 'lisp' is not on and both 'indentexpr' and 'equalprg' are empty, + the "=" operator indents using this algorithm rather than calling an + external program. + See |C-indenting|. + When you don't like the way 'cindent' works, try the 'smartindent' + option or 'indentexpr'. + This option is not used when 'paste' is set. + NOTE: This option is reset when 'compatible' is set. + + *'cinkeys'* *'cink'* +'cinkeys' 'cink' string (default "0{,0},0),:,0#,!^F,o,O,e") + local to buffer + {not in Vi} + {not available when compiled without the |+cindent| + feature} + A list of keys that, when typed in Insert mode, cause reindenting of + the current line. Only used if 'cindent' is on and 'indentexpr' is + empty. + For the format of this option see |cinkeys-format|. + See |C-indenting|. + + *'cinoptions'* *'cino'* +'cinoptions' 'cino' string (default "") + local to buffer + {not in Vi} + {not available when compiled without the |+cindent| + feature} + The 'cinoptions' affect the way 'cindent' reindents lines in a C + program. See |cinoptions-values| for the values of this option, and + |C-indenting| for info on C indenting in general. + + + *'cinwords'* *'cinw'* +'cinwords' 'cinw' string (default "if,else,while,do,for,switch") + local to buffer + {not in Vi} + {not available when compiled without both the + |+cindent| and the |+smartindent| features} + These keywords start an extra indent in the next line when + 'smartindent' or 'cindent' is set. For 'cindent' this is only done at + an appropriate place (inside {}). + Note that 'ignorecase' isn't used for 'cinwords'. If case doesn't + matter, include the keyword both the uppercase and lowercase: + "if,If,IF". + + *'clipboard'* *'cb'* +'clipboard' 'cb' string (default "autoselect,exclude:cons\|linux" + for X-windows, "" otherwise) + global + {not in Vi} + {only in GUI versions or when the |+xterm_clipboard| + feature is included} + This option is a list of comma separated names. + These names are recognized: + + unnamed When included, Vim will use the clipboard register '*' + for all yank, delete, change and put operations which + would normally go to the unnamed register. When a + register is explicitly specified, it will always be + used regardless of whether "unnamed" is in 'clipboard' + or not. The clipboard register can always be + explicitly accessed using the "* notation. Also see + |gui-clipboard|. + + unnamedplus A variant of "unnamed" flag which uses the clipboard + register '+' (|quoteplus|) instead of register '*' for + all operations except yank. Yank shall copy the text + into register '+' and also into '*' when "unnamed" is + included. + Only available with the |+x11| feature. + Availability can be checked with: > + if has('unnamedplus') +< + autoselect Works like the 'a' flag in 'guioptions': If present, + then whenever Visual mode is started, or the Visual + area extended, Vim tries to become the owner of the + windowing system's global selection or put the + selected text on the clipboard used by the selection + register "*. See |guioptions_a| and |quotestar| for + details. When the GUI is active, the 'a' flag in + 'guioptions' is used, when the GUI is not active, this + "autoselect" flag is used. + Also applies to the modeless selection. + + autoselectml Like "autoselect", but for the modeless selection + only. Compare to the 'A' flag in 'guioptions'. + + html When the clipboard contains HTML, use this when + pasting. When putting text on the clipboard, mark it + as HTML. This works to copy rendered HTML from + Firefox, paste it as raw HTML in Vim, select the HTML + in Vim and paste it in a rich edit box in Firefox. + You probably want to add this only temporarily, + possibly use BufEnter autocommands. + Only supported for GTK version 2 and later. + Only available with the |+multi_byte| feature. + + exclude:{pattern} + Defines a pattern that is matched against the name of + the terminal 'term'. If there is a match, no + connection will be made to the X server. This is + useful in this situation: + - Running Vim in a console. + - $DISPLAY is set to start applications on another + display. + - You do not want to connect to the X server in the + console, but do want this in a terminal emulator. + To never connect to the X server use: > + exclude:.* +< This has the same effect as using the |-X| argument. + Note that when there is no connection to the X server + the window title won't be restored and the clipboard + cannot be accessed. + The value of 'magic' is ignored, {pattern} is + interpreted as if 'magic' was on. + The rest of the option value will be used for + {pattern}, this must be the last entry. + + *'cmdheight'* *'ch'* +'cmdheight' 'ch' number (default 1) + global + {not in Vi} + Number of screen lines to use for the command-line. Helps avoiding + |hit-enter| prompts. + The value of this option is stored with the tab page, so that each tab + page can have a different value. + + *'cmdwinheight'* *'cwh'* +'cmdwinheight' 'cwh' number (default 7) + global + {not in Vi} + {not available when compiled without the |+vertsplit| + feature} + Number of screen lines to use for the command-line window. |cmdwin| + + *'columns'* *'co'* *E594* +'columns' 'co' number (default 80 or terminal width) + global + {not in Vi} + Number of columns of the screen. Normally this is set by the terminal + initialization and does not have to be set by hand. Also see + |posix-screen-size|. + When Vim is running in the GUI or in a resizable window, setting this + option will cause the window size to be changed. When you only want + to use the size for the GUI, put the command in your |gvimrc| file. + When you set this option and Vim is unable to change the physical + number of columns of the display, the display may be messed up. For + the GUI it is always possible and Vim limits the number of columns to + what fits on the screen. You can use this command to get the widest + window possible: > + :set columns=9999 +< Minimum value is 12, maximum value is 10000. + + *'comments'* *'com'* *E524* *E525* +'comments' 'com' string (default + "s1:/*,mb:*,ex:*/,://,b:#,:%,:XCOMM,n:>,fb:-") + local to buffer + {not in Vi} + {not available when compiled without the |+comments| + feature} + A comma separated list of strings that can start a comment line. See + |format-comments|. See |option-backslash| about using backslashes to + insert a space. + + *'commentstring'* *'cms'* *E537* +'commentstring' 'cms' string (default "/*%s*/") + local to buffer + {not in Vi} + {not available when compiled without the |+folding| + feature} + A template for a comment. The "%s" in the value is replaced with the + comment text. Currently only used to add markers for folding, see + |fold-marker|. + + *'compatible'* *'cp'* *'nocompatible'* *'nocp'* +'compatible' 'cp' boolean (default on, off when a |vimrc| or |gvimrc| + file is found) + global + {not in Vi} + This option has the effect of making Vim either more Vi-compatible, or + make Vim behave in a more useful way. + This is a special kind of option, because when it's set or reset, + other options are also changed as a side effect. CAREFUL: Setting or + resetting this option can have a lot of unexpected effects: Mappings + are interpreted in another way, undo behaves differently, etc. If you + set this option in your vimrc file, you should probably put it at the + very start. + By default this option is on and the Vi defaults are used for the + options. This default was chosen for those people who want to use Vim + just like Vi, and don't even (want to) know about the 'compatible' + option. + When a |vimrc| or |gvimrc| file is found while Vim is starting up, + this option is switched off, and all options that have not been + modified will be set to the Vim defaults. Effectively, this means + that when a |vimrc| or |gvimrc| file exists, Vim will use the Vim + defaults, otherwise it will use the Vi defaults. (Note: This doesn't + happen for the system-wide vimrc or gvimrc file, nor for a file given + with the |-u| argument). Also see |compatible-default| and + |posix-compliance|. + You can also set this option with the "-C" argument, and reset it with + "-N". See |-C| and |-N|. + Switching this option off makes the Vim defaults be used for options + that have a different Vi and Vim default value. See the options + marked with a '+' below. Other options are not modified. + At the moment this option is set, several other options will be set + or reset to make Vim as Vi-compatible as possible. See the table + below. This can be used if you want to revert to Vi compatible + editing. + See also 'cpoptions'. + + option + set value effect ~ + + 'allowrevins' off no CTRL-_ command + 'backupcopy' Unix: "yes" backup file is a copy + others: "auto" copy or rename backup file + 'backspace' "" normal backspace + 'backup' off no backup file + 'cindent' off no C code indentation + 'cedit' + "" no key to open the |cmdwin| + 'cpoptions' + (all flags) Vi-compatible flags + 'cscopetag' off don't use cscope for ":tag" + 'cscopetagorder' 0 see |cscopetagorder| + 'cscopeverbose' off see |cscopeverbose| + 'digraph' off no digraphs + 'esckeys' + off no -keys in Insert mode + 'expandtab' off tabs not expanded to spaces + 'fileformats' + "" no automatic file format detection, + "dos,unix" except for DOS, Windows and OS/2 + 'formatoptions' + "vt" Vi compatible formatting + 'gdefault' off no default 'g' flag for ":s" + 'history' + 0 no commandline history + 'hkmap' off no Hebrew keyboard mapping + 'hkmapp' off no phonetic Hebrew keyboard mapping + 'hlsearch' off no highlighting of search matches + 'incsearch' off no incremental searching + 'indentexpr' "" no indenting by expression + 'insertmode' off do not start in Insert mode + 'iskeyword' + "@,48-57,_" keywords contain alphanumeric + characters and '_' + 'joinspaces' on insert 2 spaces after period + 'modeline' + off no modelines + 'more' + off no pauses in listings + 'revins' off no reverse insert + 'ruler' off no ruler + 'scrolljump' 1 no jump scroll + 'scrolloff' 0 no scroll offset + 'shiftround' off indent not rounded to shiftwidth + 'shortmess' + "" no shortening of messages + 'showcmd' + off command characters not shown + 'showmode' + off current mode not shown + 'smartcase' off no automatic ignore case switch + 'smartindent' off no smart indentation + 'smarttab' off no smart tab size + 'softtabstop' 0 tabs are always 'tabstop' positions + 'startofline' on goto startofline with some commands + 'tagrelative' + off tag file names are not relative + 'textauto' + off no automatic textmode detection + 'textwidth' 0 no automatic line wrap + 'tildeop' off tilde is not an operator + 'ttimeout' off no terminal timeout + 'whichwrap' + "" left-right movements don't wrap + 'wildchar' + CTRL-E only when the current value is + use CTRL-E for cmdline completion + 'writebackup' on or off depends on the |+writebackup| feature + + *'complete'* *'cpt'* *E535* +'complete' 'cpt' string (default: ".,w,b,u,t,i") + local to buffer + {not in Vi} + This option specifies how keyword completion |ins-completion| works + when CTRL-P or CTRL-N are used. It is also used for whole-line + completion |i_CTRL-X_CTRL-L|. It indicates the type of completion + and the places to scan. It is a comma separated list of flags: + . scan the current buffer ('wrapscan' is ignored) + w scan buffers from other windows + b scan other loaded buffers that are in the buffer list + u scan the unloaded buffers that are in the buffer list + U scan the buffers that are not in the buffer list + k scan the files given with the 'dictionary' option + kspell use the currently active spell checking |spell| + k{dict} scan the file {dict}. Several "k" flags can be given, + patterns are valid too. For example: > + :set cpt=k/usr/dict/*,k~/spanish +< s scan the files given with the 'thesaurus' option + s{tsr} scan the file {tsr}. Several "s" flags can be given, patterns + are valid too. + i scan current and included files + d scan current and included files for defined name or macro + |i_CTRL-X_CTRL-D| + ] tag completion + t same as "]" + + Unloaded buffers are not loaded, thus their autocmds |:autocmd| are + not executed, this may lead to unexpected completions from some files + (gzipped files for example). Unloaded buffers are not scanned for + whole-line completion. + + The default is ".,w,b,u,t,i", which means to scan: + 1. the current buffer + 2. buffers in other windows + 3. other loaded buffers + 4. unloaded buffers + 5. tags + 6. included files + + As you can see, CTRL-N and CTRL-P can be used to do any 'iskeyword'- + based expansion (e.g., dictionary |i_CTRL-X_CTRL-K|, included patterns + |i_CTRL-X_CTRL-I|, tags |i_CTRL-X_CTRL-]| and normal expansions). + + *'completefunc'* *'cfu'* +'completefunc' 'cfu' string (default: empty) + local to buffer + {not in Vi} + {not available when compiled without the |+eval| + or |+insert_expand| features} + This option specifies a function to be used for Insert mode completion + with CTRL-X CTRL-U. |i_CTRL-X_CTRL-U| + See |complete-functions| for an explanation of how the function is + invoked and what it should return. + + + *'completeopt'* *'cot'* +'completeopt' 'cot' string (default: "menu,preview") + global + {not available when compiled without the + |+insert_expand| feature} + {not in Vi} + A comma separated list of options for Insert mode completion + |ins-completion|. The supported values are: + + menu Use a popup menu to show the possible completions. The + menu is only shown when there is more than one match and + sufficient colors are available. |ins-completion-menu| + + menuone Use the popup menu also when there is only one match. + Useful when there is additional information about the + match, e.g., what file it comes from. + + longest Only insert the longest common text of the matches. If + the menu is displayed you can use CTRL-L to add more + characters. Whether case is ignored depends on the kind + of completion. For buffer text the 'ignorecase' option is + used. + + preview Show extra information about the currently selected + completion in the preview window. Only works in + combination with "menu" or "menuone". + + + *'concealcursor'* *'cocu'* +'concealcursor' 'cocu' string (default: "") + local to window + {not in Vi} + {not available when compiled without the |+conceal| + feature} + Sets the modes in which text in the cursor line can also be concealed. + When the current mode is listed then concealing happens just like in + other lines. + n Normal mode + v Visual mode + i Insert mode + c Command line editing, for 'incsearch' + + 'v' applies to all lines in the Visual area, not only the cursor. + A useful value is "nc". This is used in help files. So long as you + are moving around text is concealed, but when starting to insert text + or selecting a Visual area the concealed text is displayed, so that + you can see what you are doing. + Keep in mind that the cursor position is not always where it's + displayed. E.g., when moving vertically it may change column. + + +'conceallevel' 'cole' *'conceallevel'* *'cole'* + number (default 0) + local to window + {not in Vi} + {not available when compiled without the |+conceal| + feature} + Determine how text with the "conceal" syntax attribute |:syn-conceal| + is shown: + + Value Effect ~ + 0 Text is shown normally + 1 Each block of concealed text is replaced with one + character. If the syntax item does not have a custom + replacement character defined (see |:syn-cchar|) the + character defined in 'listchars' is used (default is a + space). + It is highlighted with the "Conceal" highlight group. + 2 Concealed text is completely hidden unless it has a + custom replacement character defined (see + |:syn-cchar|). + 3 Concealed text is completely hidden. + + Note: in the cursor line concealed text is not hidden, so that you can + edit and copy the text. This can be changed with the 'concealcursor' + option. + + *'confirm'* *'cf'* *'noconfirm'* *'nocf'* +'confirm' 'cf' boolean (default off) + global + {not in Vi} + When 'confirm' is on, certain operations that would normally + fail because of unsaved changes to a buffer, e.g. ":q" and ":e", + instead raise a |dialog| asking if you wish to save the current + file(s). You can still use a ! to unconditionally |abandon| a buffer. + If 'confirm' is off you can still activate confirmation for one + command only (this is most useful in mappings) with the |:confirm| + command. + Also see the |confirm()| function and the 'v' flag in 'guioptions'. + + *'conskey'* *'consk'* *'noconskey'* *'noconsk'* +'conskey' 'consk' boolean (default off) + global + {not in Vi} {only for MS-DOS} + When on direct console I/O is used to obtain a keyboard character. + This should work in most cases. Also see |'bioskey'|. Together, + three methods of console input are available: + 'conskey' 'bioskey' action ~ + on on or off direct console input + off on BIOS + off off STDIN + + *'copyindent'* *'ci'* *'nocopyindent'* *'noci'* +'copyindent' 'ci' boolean (default off) + local to buffer + {not in Vi} + Copy the structure of the existing lines indent when autoindenting a + new line. Normally the new indent is reconstructed by a series of + tabs followed by spaces as required (unless |'expandtab'| is enabled, + in which case only spaces are used). Enabling this option makes the + new line copy whatever characters were used for indenting on the + existing line. 'expandtab' has no effect on these characters, a Tab + remains a Tab. If the new indent is greater than on the existing + line, the remaining space is filled in the normal manner. + NOTE: 'copyindent' is reset when 'compatible' is set. + Also see 'preserveindent'. + + *'cpoptions'* *'cpo'* +'cpoptions' 'cpo' string (Vim default: "aABceFs", + Vi default: all flags) + global + {not in Vi} + A sequence of single character flags. When a character is present + this indicates vi-compatible behavior. This is used for things where + not being vi-compatible is mostly or sometimes preferred. + 'cpoptions' stands for "compatible-options". + Commas can be added for readability. + To avoid problems with flags that are added in the future, use the + "+=" and "-=" feature of ":set" |add-option-flags|. + NOTE: This option is set to the Vi default value when 'compatible' is + set and to the Vim default value when 'compatible' is reset. + NOTE: This option is set to the POSIX default value at startup when + the Vi default value would be used and the $VIM_POSIX environment + variable exists |posix|. This means Vim tries to behave like the + POSIX specification. + + contains behavior ~ + *cpo-a* + a When included, a ":read" command with a file name + argument will set the alternate file name for the + current window. + *cpo-A* + A When included, a ":write" command with a file name + argument will set the alternate file name for the + current window. + *cpo-b* + b "\|" in a ":map" command is recognized as the end of + the map command. The '\' is included in the mapping, + the text after the '|' is interpreted as the next + command. Use a CTRL-V instead of a backslash to + include the '|' in the mapping. Applies to all + mapping, abbreviation, menu and autocmd commands. + See also |map_bar|. + *cpo-B* + B A backslash has no special meaning in mappings, + abbreviations and the "to" part of the menu commands. + Remove this flag to be able to use a backslash like a + CTRL-V. For example, the command ":map X \" + results in X being mapped to: + 'B' included: "\^[" (^[ is a real ) + 'B' excluded: "" (5 characters) + ('<' excluded in both cases) + *cpo-c* + c Searching continues at the end of any match at the + cursor position, but not further than the start of the + next line. When not present searching continues + one character from the cursor position. With 'c' + "abababababab" only gets three matches when repeating + "/abab", without 'c' there are five matches. + *cpo-C* + C Do not concatenate sourced lines that start with a + backslash. See |line-continuation|. + *cpo-d* + d Using "./" in the 'tags' option doesn't mean to use + the tags file relative to the current file, but the + tags file in the current directory. + *cpo-D* + D Can't use CTRL-K to enter a digraph after Normal mode + commands with a character argument, like |r|, |f| and + |t|. + *cpo-e* + e When executing a register with ":@r", always add a + to the last line, also when the register is not + linewise. If this flag is not present, the register + is not linewise and the last line does not end in a + , then the last line is put on the command-line + and can be edited before hitting . + *cpo-E* + E It is an error when using "y", "d", "c", "g~", "gu" or + "gU" on an Empty region. The operators only work when + at least one character is to be operate on. Example: + This makes "y0" fail in the first column. + *cpo-f* + f When included, a ":read" command with a file name + argument will set the file name for the current buffer, + if the current buffer doesn't have a file name yet. + *cpo-F* + F When included, a ":write" command with a file name + argument will set the file name for the current + buffer, if the current buffer doesn't have a file name + yet. Also see |cpo-P|. + *cpo-g* + g Goto line 1 when using ":edit" without argument. + *cpo-H* + H When using "I" on a line with only blanks, insert + before the last blank. Without this flag insert after + the last blank. + *cpo-i* + i When included, interrupting the reading of a file will + leave it modified. + *cpo-I* + I When moving the cursor up or down just after inserting + indent for 'autoindent', do not delete the indent. + *cpo-j* + j When joining lines, only add two spaces after a '.', + not after '!' or '?'. Also see 'joinspaces'. + *cpo-J* + J A |sentence| has to be followed by two spaces after + the '.', '!' or '?'. A is not recognized as + white space. + *cpo-k* + k Disable the recognition of raw key codes in + mappings, abbreviations, and the "to" part of menu + commands. For example, if sends ^[OA (where ^[ + is ), the command ":map X ^[OA" results in X + being mapped to: + 'k' included: "^[OA" (3 characters) + 'k' excluded: "" (one key code) + Also see the '<' flag below. + *cpo-K* + K Don't wait for a key code to complete when it is + halfway a mapping. This breaks mapping when + only part of the second has been read. It + enables cancelling the mapping by typing . + *cpo-l* + l Backslash in a [] range in a search pattern is taken + literally, only "\]", "\^", "\-" and "\\" are special. + See |/[]| + 'l' included: "/[ \t]" finds , '\' and 't' + 'l' excluded: "/[ \t]" finds and + Also see |cpo-\|. + *cpo-L* + L When the 'list' option is set, 'wrapmargin', + 'textwidth', 'softtabstop' and Virtual Replace mode + (see |gR|) count a as two characters, instead of + the normal behavior of a . + *cpo-m* + m When included, a showmatch will always wait half a + second. When not included, a showmatch will wait half + a second or until a character is typed. |'showmatch'| + *cpo-M* + M When excluded, "%" matching will take backslashes into + account. Thus in "( \( )" and "\( ( \)" the outer + parenthesis match. When included "%" ignores + backslashes, which is Vi compatible. + *cpo-n* + n When included, the column used for 'number' and + 'relativenumber' will also be used for text of wrapped + lines. + *cpo-o* + o Line offset to search command is not remembered for + next search. + *cpo-O* + O Don't complain if a file is being overwritten, even + when it didn't exist when editing it. This is a + protection against a file unexpectedly created by + someone else. Vi didn't complain about this. + *cpo-p* + p Vi compatible Lisp indenting. When not present, a + slightly better algorithm is used. + *cpo-P* + P When included, a ":write" command that appends to a + file will set the file name for the current buffer, if + the current buffer doesn't have a file name yet and + the 'F' flag is also included |cpo-F|. + *cpo-q* + q When joining multiple lines leave the cursor at the + position where it would be when joining two lines. + *cpo-r* + r Redo ("." command) uses "/" to repeat a search + command, instead of the actually used search string. + *cpo-R* + R Remove marks from filtered lines. Without this flag + marks are kept like |:keepmarks| was used. + *cpo-s* + s Set buffer options when entering the buffer for the + first time. This is like it is in Vim version 3.0. + And it is the default. If not present the options are + set when the buffer is created. + *cpo-S* + S Set buffer options always when entering a buffer + (except 'readonly', 'fileformat', 'filetype' and + 'syntax'). This is the (most) Vi compatible setting. + The options are set to the values in the current + buffer. When you change an option and go to another + buffer, the value is copied. Effectively makes the + buffer options global to all buffers. + + 's' 'S' copy buffer options + no no when buffer created + yes no when buffer first entered (default) + X yes each time when buffer entered (vi comp.) + *cpo-t* + t Search pattern for the tag command is remembered for + "n" command. Otherwise Vim only puts the pattern in + the history for search pattern, but doesn't change the + last used search pattern. + *cpo-u* + u Undo is Vi compatible. See |undo-two-ways|. + *cpo-v* + v Backspaced characters remain visible on the screen in + Insert mode. Without this flag the characters are + erased from the screen right away. With this flag the + screen newly typed text overwrites backspaced + characters. + *cpo-w* + w When using "cw" on a blank character, only change one + character and not all blanks until the start of the + next word. + *cpo-W* + W Don't overwrite a readonly file. When omitted, ":w!" + overwrites a readonly file, if possible. + *cpo-x* + x on the command-line executes the command-line. + The default in Vim is to abandon the command-line, + because normally aborts a command. |c_| + *cpo-X* + X When using a count with "R" the replaced text is + deleted only once. Also when repeating "R" with "." + and a count. + *cpo-y* + y A yank command can be redone with ".". + *cpo-Z* + Z When using "w!" while the 'readonly' option is set, + don't reset 'readonly'. + *cpo-!* + ! When redoing a filter command, use the last used + external command, whatever it was. Otherwise the last + used -filter- command is used. + *cpo-$* + $ When making a change to one line, don't redisplay the + line, but put a '$' at the end of the changed text. + The changed text will be overwritten when you type the + new text. The line is redisplayed if you type any + command that moves the cursor from the insertion + point. + *cpo-%* + % Vi-compatible matching is done for the "%" command. + Does not recognize "#if", "#endif", etc. + Does not recognize "/*" and "*/". + Parens inside single and double quotes are also + counted, causing a string that contains a paren to + disturb the matching. For example, in a line like + "if (strcmp("foo(", s))" the first paren does not + match the last one. When this flag is not included, + parens inside single and double quotes are treated + specially. When matching a paren outside of quotes, + everything inside quotes is ignored. When matching a + paren inside quotes, it will find the matching one (if + there is one). This works very well for C programs. + This flag is also used for other features, such as + C-indenting. + *cpo--* + - When included, a vertical movement command fails when + it would go above the first line or below the last + line. Without it the cursor moves to the first or + last line, unless it already was in that line. + Applies to the commands "-", "k", CTRL-P, "+", "j", + CTRL-N, CTRL-J and ":1234". + *cpo-+* + + When included, a ":write file" command will reset the + 'modified' flag of the buffer, even though the buffer + itself may still be different from its file. + *cpo-star* + * Use ":*" in the same way as ":@". When not included, + ":*" is an alias for ":'<,'>", select the Visual area. + *cpo-<* + < Disable the recognition of special key codes in |<>| + form in mappings, abbreviations, and the "to" part of + menu commands. For example, the command + ":map X " results in X being mapped to: + '<' included: "" (5 characters) + '<' excluded: "^I" (^I is a real ) + Also see the 'k' flag above. + *cpo->* + > When appending to a register, put a line break before + the appended text. + + POSIX flags. These are not included in the Vi default value, except + when $VIM_POSIX was set on startup. |posix| + + contains behavior ~ + *cpo-#* + # A count before "D", "o" and "O" has no effect. + *cpo-&* + & When ":preserve" was used keep the swap file when + exiting normally while this buffer is still loaded. + This flag is tested when exiting. + *cpo-\* + \ Backslash in a [] range in a search pattern is taken + literally, only "\]" is special See |/[]| + '\' included: "/[ \-]" finds , '\' and '-' + '\' excluded: "/[ \-]" finds and '-' + Also see |cpo-l|. + *cpo-/* + / When "%" is used as the replacement string in a |:s| + command, use the previous replacement string. |:s%| + *cpo-{* + { The |{| and |}| commands also stop at a "{" character + at the start of a line. + *cpo-.* + . The ":chdir" and ":cd" commands fail if the current + buffer is modified, unless ! is used. Vim doesn't + need this, since it remembers the full path of an + opened file. + *cpo-bar* + | The value of the $LINES and $COLUMNS environment + variables overrule the terminal size values obtained + with system specific functions. + + + *'cryptmethod'* *'cm'* +'cryptmethod' string (default "zip") + global or local to buffer |global-local| + {not in Vi} + Method used for encryption when the buffer is written to a file: + *pkzip* + zip PkZip compatible method. A weak kind of encryption. + Backwards compatible with Vim 7.2 and older. + *blowfish* + blowfish Blowfish method. Strong encryption. Requires Vim 7.3 + or later, files can NOT be read by Vim 7.2 and older. + This adds a "seed" to the file, every time you write + the file the encrypted bytes will be different. + + When reading an encrypted file 'cryptmethod' will be set automatically + to the detected method of the file being read. Thus if you write it + without changing 'cryptmethod' the same method will be used. + Changing 'cryptmethod' does not mark the file as modified, you have to + explicitly write it, you don't get a warning unless there are other + modifications. Also see |:X|. + + When setting the global value to an empty string, it will end up with + the value "zip". When setting the local value to an empty string the + buffer will use the global value. + + When a new encryption method is added in a later version of Vim, and + the current version does not recognize it, you will get *E821* . + You need to edit this file with the later version of Vim. + + + *'cscopepathcomp'* *'cspc'* +'cscopepathcomp' 'cspc' number (default 0) + global + {not available when compiled without the |+cscope| + feature} + {not in Vi} + Determines how many components of the path to show in a list of tags. + See |cscopepathcomp|. + + *'cscopeprg'* *'csprg'* +'cscopeprg' 'csprg' string (default "cscope") + global + {not available when compiled without the |+cscope| + feature} + {not in Vi} + Specifies the command to execute cscope. See |cscopeprg|. + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + *'cscopequickfix'* *'csqf'* +'cscopequickfix' 'csqf' string (default "") + global + {not available when compiled without the |+cscope| + or |+quickfix| features} + {not in Vi} + Specifies whether to use quickfix window to show cscope results. + See |cscopequickfix|. + + *'cscopetag'* *'cst'* *'nocscopetag'* *'nocst'* +'cscopetag' 'cst' boolean (default off) + global + {not available when compiled without the |+cscope| + feature} + {not in Vi} + Use cscope for tag commands. See |cscope-options|. + NOTE: This option is reset when 'compatible' is set. + + *'cscopetagorder'* *'csto'* +'cscopetagorder' 'csto' number (default 0) + global + {not available when compiled without the |+cscope| + feature} + {not in Vi} + Determines the order in which ":cstag" performs a search. See + |cscopetagorder|. + NOTE: This option is set to 0 when 'compatible' is set. + + *'cscopeverbose'* *'csverb'* + *'nocscopeverbose'* *'nocsverb'* +'cscopeverbose' 'csverb' boolean (default off) + global + {not available when compiled without the |+cscope| + feature} + {not in Vi} + Give messages when adding a cscope database. See |cscopeverbose|. + NOTE: This option is reset when 'compatible' is set. + + *'cursorbind'* *'crb'* *'nocursorbind'* *'nocrb'* +'cursorbind' 'crb' boolean (default off) + local to window + {not in Vi} + {not available when compiled without the |+cursorbind| + feature} + When this option is set, as the cursor in the current + window moves other cursorbound windows (windows that also have + this option set) move their cursors to the corresponding line and + column. This option is useful for viewing the + differences between two versions of a file (see 'diff'); in diff mode, + inserted and deleted lines (though not characters within a line) are + taken into account. + + + *'cursorcolumn'* *'cuc'* *'nocursorcolumn'* *'nocuc'* +'cursorcolumn' 'cuc' boolean (default off) + local to window + {not in Vi} + {not available when compiled without the |+syntax| + feature} + Highlight the screen column of the cursor with CursorColumn + |hl-CursorColumn|. Useful to align text. Will make screen redrawing + slower. + If you only want the highlighting in the current window you can use + these autocommands: > + au WinLeave * set nocursorline nocursorcolumn + au WinEnter * set cursorline cursorcolumn +< + + *'cursorline'* *'cul'* *'nocursorline'* *'nocul'* +'cursorline' 'cul' boolean (default off) + local to window + {not in Vi} + {not available when compiled without the |+syntax| + feature} + Highlight the screen line of the cursor with CursorLine + |hl-CursorLine|. Useful to easily spot the cursor. Will make screen + redrawing slower. + When Visual mode is active the highlighting isn't used to make it + easier to see the selected text. + + + *'debug'* +'debug' string (default "") + global + {not in Vi} + These values can be used: + msg Error messages that would otherwise be omitted will be given + anyway. + throw Error messages that would otherwise be omitted will be given + anyway and also throw an exception and set |v:errmsg|. + beep A message will be given when otherwise only a beep would be + produced. + The values can be combined, separated by a comma. + "msg" and "throw" are useful for debugging 'foldexpr', 'formatexpr' or + 'indentexpr'. + + *'define'* *'def'* +'define' 'def' string (default "^\s*#\s*define") + global or local to buffer |global-local| + {not in Vi} + Pattern to be used to find a macro definition. It is a search + pattern, just like for the "/" command. This option is used for the + commands like "[i" and "[d" |include-search|. The 'isident' option is + used to recognize the defined name after the match: + {match with 'define'}{non-ID chars}{defined name}{non-ID char} + See |option-backslash| about inserting backslashes to include a space + or backslash. + The default value is for C programs. For C++ this value would be + useful, to include const type declarations: > + ^\(#\s*define\|[a-z]*\s*const\s*[a-z]*\) +< When using the ":set" command, you need to double the backslashes! + + *'delcombine'* *'deco'* *'nodelcombine'* *'nodeco'* +'delcombine' 'deco' boolean (default off) + global + {not in Vi} + {only available when compiled with the |+multi_byte| + feature} + If editing Unicode and this option is set, backspace and Normal mode + "x" delete each combining character on its own. When it is off (the + default) the character along with its combining characters are + deleted. + Note: When 'delcombine' is set "xx" may work different from "2x"! + + This is useful for Arabic, Hebrew and many other languages where one + may have combining characters overtop of base characters, and want + to remove only the combining ones. + + *'dictionary'* *'dict'* +'dictionary' 'dict' string (default "") + global or local to buffer |global-local| + {not in Vi} + List of file names, separated by commas, that are used to lookup words + for keyword completion commands |i_CTRL-X_CTRL-K|. Each file should + contain a list of words. This can be one word per line, or several + words per line, separated by non-keyword characters (white space is + preferred). Maximum line length is 510 bytes. + When this option is empty, or an entry "spell" is present, spell + checking is enabled the currently active spelling is used. |spell| + To include a comma in a file name precede it with a backslash. Spaces + after a comma are ignored, otherwise spaces are included in the file + name. See |option-backslash| about using backslashes. + This has nothing to do with the |Dictionary| variable type. + Where to find a list of words? + - On FreeBSD, there is the file "/usr/share/dict/words". + - In the Simtel archive, look in the "msdos/linguist" directory. + - In "miscfiles" of the GNU collection. + The use of |:set+=| and |:set-=| is preferred when adding or removing + directories from the list. This avoids problems when a future version + uses another default. + Backticks cannot be used in this option for security reasons. + + *'diff'* *'nodiff'* +'diff' boolean (default off) + local to window + {not in Vi} + {not available when compiled without the |+diff| + feature} + Join the current window in the group of windows that shows differences + between files. See |vimdiff|. + + *'dex'* *'diffexpr'* +'diffexpr' 'dex' string (default "") + global + {not in Vi} + {not available when compiled without the |+diff| + feature} + Expression which is evaluated to obtain an ed-style diff file from two + versions of a file. See |diff-diffexpr|. + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + *'dip'* *'diffopt'* +'diffopt' 'dip' string (default "filler") + global + {not in Vi} + {not available when compiled without the |+diff| + feature} + Option settings for diff mode. It can consist of the following items. + All are optional. Items must be separated by a comma. + + filler Show filler lines, to keep the text + synchronized with a window that has inserted + lines at the same position. Mostly useful + when windows are side-by-side and 'scrollbind' + is set. + + context:{n} Use a context of {n} lines between a change + and a fold that contains unchanged lines. + When omitted a context of six lines is used. + See |fold-diff|. + + icase Ignore changes in case of text. "a" and "A" + are considered the same. Adds the "-i" flag + to the "diff" command if 'diffexpr' is empty. + + iwhite Ignore changes in amount of white space. Adds + the "-b" flag to the "diff" command if + 'diffexpr' is empty. Check the documentation + of the "diff" command for what this does + exactly. It should ignore adding trailing + white space, but not leading white space. + + horizontal Start diff mode with horizontal splits (unless + explicitly specified otherwise). + + vertical Start diff mode with vertical splits (unless + explicitly specified otherwise). + + foldcolumn:{n} Set the 'foldcolumn' option to {n} when + starting diff mode. Without this 2 is used. + + Examples: > + + :set diffopt=filler,context:4 + :set diffopt= + :set diffopt=filler,foldcolumn:3 +< + *'digraph'* *'dg'* *'nodigraph'* *'nodg'* +'digraph' 'dg' boolean (default off) + global + {not in Vi} + {not available when compiled without the |+digraphs| + feature} + Enable the entering of digraphs in Insert mode with {char1} + {char2}. See |digraphs|. + NOTE: This option is reset when 'compatible' is set. + + *'directory'* *'dir'* +'directory' 'dir' string (default for Amiga: ".,t:", + for MS-DOS and Win32: ".,c:\tmp,c:\temp" + for Unix: ".,~/tmp,/var/tmp,/tmp") + global + List of directory names for the swap file, separated with commas. + - The swap file will be created in the first directory where this is + possible. + - Empty means that no swap file will be used (recovery is + impossible!). + - A directory "." means to put the swap file in the same directory as + the edited file. On Unix, a dot is prepended to the file name, so + it doesn't show in a directory listing. On MS-Windows the "hidden" + attribute is set and a dot prepended if possible. + - A directory starting with "./" (or ".\" for MS-DOS et al.) means to + put the swap file relative to where the edited file is. The leading + "." is replaced with the path name of the edited file. + - For Unix and Win32, if a directory ends in two path separators "//" + or "\\", the swap file name will be built from the complete path to + the file with all path separators substituted to percent '%' signs. + This will ensure file name uniqueness in the preserve directory. + On Win32, when a separating comma is following, you must use "//", + since "\\" will include the comma in the file name. + - Spaces after the comma are ignored, other spaces are considered part + of the directory name. To have a space at the start of a directory + name, precede it with a backslash. + - To include a comma in a directory name precede it with a backslash. + - A directory name may end in an ':' or '/'. + - Environment variables are expanded |:set_env|. + - Careful with '\' characters, type one before a space, type two to + get one in the option (see |option-backslash|), for example: > + :set dir=c:\\tmp,\ dir\\,with\\,commas,\\\ dir\ with\ spaces +< - For backwards compatibility with Vim version 3.0 a '>' at the start + of the option is removed. + Using "." first in the list is recommended. This means that editing + the same file twice will result in a warning. Using "/tmp" on Unix is + discouraged: When the system crashes you lose the swap file. + "/var/tmp" is often not cleared when rebooting, thus is a better + choice than "/tmp". But it can contain a lot of files, your swap + files get lost in the crowd. That is why a "tmp" directory in your + home directory is tried first. + The use of |:set+=| and |:set-=| is preferred when adding or removing + directories from the list. This avoids problems when a future version + uses another default. + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + {Vi: directory to put temp file in, defaults to "/tmp"} + + *'display'* *'dy'* +'display' 'dy' string (default "") + global + {not in Vi} + Change the way text is displayed. This is comma separated list of + flags: + lastline When included, as much as possible of the last line + in a window will be displayed. When not included, a + last line that doesn't fit is replaced with "@" lines. + uhex Show unprintable characters hexadecimal as + instead of using ^C and ~C. + + *'eadirection'* *'ead'* +'eadirection' 'ead' string (default "both") + global + {not in Vi} + {not available when compiled without the |+vertsplit| + feature} + Tells when the 'equalalways' option applies: + ver vertically, width of windows is not affected + hor horizontally, height of windows is not affected + both width and height of windows is affected + + *'ed'* *'edcompatible'* *'noed'* *'noedcompatible'* +'edcompatible' 'ed' boolean (default off) + global + Makes the 'g' and 'c' flags of the ":substitute" command to be + toggled each time the flag is given. See |complex-change|. See + also 'gdefault' option. + Switching this option on is discouraged! + + *'encoding'* *'enc'* *E543* +'encoding' 'enc' string (default: "latin1" or value from $LANG) + global + {only available when compiled with the |+multi_byte| + feature} + {not in Vi} + Sets the character encoding used inside Vim. It applies to text in + the buffers, registers, Strings in expressions, text stored in the + viminfo file, etc. It sets the kind of characters which Vim can work + with. See |encoding-names| for the possible values. + + NOTE: Changing this option will not change the encoding of the + existing text in Vim. It may cause non-ASCII text to become invalid. + It should normally be kept at its default value, or set when Vim + starts up. See |multibyte|. To reload the menus see |:menutrans|. + + This option cannot be set from a |modeline|. It would most likely + corrupt the text. + + NOTE: For GTK+ 2 it is highly recommended to set 'encoding' to + "utf-8". Although care has been taken to allow different values of + 'encoding', "utf-8" is the natural choice for the environment and + avoids unnecessary conversion overhead. "utf-8" has not been made + the default to prevent different behavior of the GUI and terminal + versions, and to avoid changing the encoding of newly created files + without your knowledge (in case 'fileencodings' is empty). + + The character encoding of files can be different from 'encoding'. + This is specified with 'fileencoding'. The conversion is done with + iconv() or as specified with 'charconvert'. + + If you need to know whether 'encoding' is a multi-byte encoding, you + can use: > + if has("multi_byte_encoding") +< + Normally 'encoding' will be equal to your current locale. This will + be the default if Vim recognizes your environment settings. If + 'encoding' is not set to the current locale, 'termencoding' must be + set to convert typed and displayed text. See |encoding-table|. + + When you set this option, it fires the |EncodingChanged| autocommand + event so that you can set up fonts if necessary. + + When the option is set, the value is converted to lowercase. Thus + you can set it with uppercase values too. Underscores are translated + to '-' signs. + When the encoding is recognized, it is changed to the standard name. + For example "Latin-1" becomes "latin1", "ISO_88592" becomes + "iso-8859-2" and "utf8" becomes "utf-8". + + Note: "latin1" is also used when the encoding could not be detected. + This only works when editing files in the same encoding! When the + actual character set is not latin1, make sure 'fileencoding' and + 'fileencodings' are empty. When conversion is needed, switch to using + utf-8. + + When "unicode", "ucs-2" or "ucs-4" is used, Vim internally uses utf-8. + You don't notice this while editing, but it does matter for the + |viminfo-file|. And Vim expects the terminal to use utf-8 too. Thus + setting 'encoding' to one of these values instead of utf-8 only has + effect for encoding used for files when 'fileencoding' is empty. + + When 'encoding' is set to a Unicode encoding, and 'fileencodings' was + not set yet, the default for 'fileencodings' is changed. + + *'endofline'* *'eol'* *'noendofline'* *'noeol'* +'endofline' 'eol' boolean (default on) + local to buffer + {not in Vi} + When writing a file and this option is off and the 'binary' option + is on, no will be written for the last line in the file. This + option is automatically set when starting to edit a new file, unless + the file does not have an for the last line in the file, in + which case it is reset. Normally you don't have to set or reset this + option. When 'binary' is off the value is not used when writing the + file. When 'binary' is on it is used to remember the presence of a + for the last line in the file, so that when you write the file + the situation from the original file can be kept. But you can change + it if you want to. + + *'equalalways'* *'ea'* *'noequalalways'* *'noea'* +'equalalways' 'ea' boolean (default on) + global + {not in Vi} + When on, all the windows are automatically made the same size after + splitting or closing a window. This also happens the moment the + option is switched on. When off, splitting a window will reduce the + size of the current window and leave the other windows the same. When + closing a window the extra lines are given to the window next to it + (depending on 'splitbelow' and 'splitright'). + 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 and width of a window can be avoided by setting + 'winfixheight' and 'winfixwidth', respectively. + If a window size is specified when creating a new window sizes are + currently not equalized (it's complicated, but may be implemented in + the future). + + *'equalprg'* *'ep'* +'equalprg' 'ep' string (default "") + global or local to buffer |global-local| + {not in Vi} + External program to use for "=" command. When this option is empty + the internal formatting functions are used; either 'lisp', 'cindent' + or 'indentexpr'. When Vim was compiled without internal formatting, + the "indent" program is used. + Environment variables are expanded |:set_env|. See |option-backslash| + about including spaces and backslashes. + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + *'errorbells'* *'eb'* *'noerrorbells'* *'noeb'* +'errorbells' 'eb' boolean (default off) + global + Ring the bell (beep or screen flash) for error messages. This only + makes a difference for error messages, the bell will be used always + for a lot of errors without a message (e.g., hitting in Normal + mode). See 'visualbell' on how to make the bell behave like a beep, + screen flash or do nothing. + + *'errorfile'* *'ef'* +'errorfile' 'ef' string (Amiga default: "AztecC.Err", + others: "errors.err") + global + {not in Vi} + {not available when compiled without the |+quickfix| + feature} + Name of the errorfile for the QuickFix mode (see |:cf|). + When the "-q" command-line argument is used, 'errorfile' is set to the + following argument. See |-q|. + NOT used for the ":make" command. See 'makeef' for that. + Environment variables are expanded |:set_env|. + See |option-backslash| about including spaces and backslashes. + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + *'errorformat'* *'efm'* +'errorformat' 'efm' string (default is very long) + global or local to buffer |global-local| + {not in Vi} + {not available when compiled without the |+quickfix| + feature} + Scanf-like description of the format for the lines in the error file + (see |errorformat|). + + *'esckeys'* *'ek'* *'noesckeys'* *'noek'* +'esckeys' 'ek' boolean (Vim default: on, Vi default: off) + global + {not in Vi} + Function keys that start with an are recognized in Insert + mode. When this option is off, the cursor and function keys cannot be + used in Insert mode if they start with an . The advantage of + this is that the single is recognized immediately, instead of + after one second. Instead of resetting this option, you might want to + try changing the values for 'timeoutlen' and 'ttimeoutlen'. Note that + when 'esckeys' is off, you can still map anything, but the cursor keys + won't work by default. + NOTE: This option is set to the Vi default value when 'compatible' is + set and to the Vim default value when 'compatible' is reset. + + *'eventignore'* *'ei'* +'eventignore' 'ei' string (default "") + global + {not in Vi} + {not available when compiled without the |+autocmd| + feature} + A list of autocommand event names, which are to be ignored. + When set to "all" or when "all" is one of the items, all autocommand + events are ignored, autocommands will not be executed. + Otherwise this is a comma separated list of event names. Example: > + :set ei=WinEnter,WinLeave +< + *'expandtab'* *'et'* *'noexpandtab'* *'noet'* +'expandtab' 'et' boolean (default off) + local to buffer + {not in Vi} + In Insert mode: Use the appropriate number of spaces to insert a + . Spaces are used in indents with the '>' and '<' commands and + when 'autoindent' is on. To insert a real tab when 'expandtab' is + on, use CTRL-V. See also |:retab| and |ins-expandtab|. + NOTE: This option is reset when 'compatible' is set. + + *'exrc'* *'ex'* *'noexrc'* *'noex'* +'exrc' 'ex' boolean (default off) + global + {not in Vi} + Enables the reading of .vimrc, .exrc and .gvimrc in the current + directory. If you switch this option on you should also consider + setting the 'secure' option (see |initialization|). Using a local + .exrc, .vimrc or .gvimrc is a potential security leak, use with care! + also see |.vimrc| and |gui-init|. + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + *'fileencoding'* *'fenc'* *E213* +'fileencoding' 'fenc' string (default: "") + local to buffer + {only available when compiled with the |+multi_byte| + feature} + {not in Vi} + Sets the character encoding for the file of this buffer. + + When 'fileencoding' is different from 'encoding', conversion will be + done when writing the file. For reading see below. + When 'fileencoding' is empty, the same value as 'encoding' will be + used (no conversion when reading or writing a file). + Conversion will also be done when 'encoding' and 'fileencoding' are + both a Unicode encoding and 'fileencoding' is not utf-8. That's + because internally Unicode is always stored as utf-8. + WARNING: Conversion can cause loss of information! When + 'encoding' is "utf-8" or another Unicode encoding, conversion + is most likely done in a way that the reverse conversion + results in the same text. When 'encoding' is not "utf-8" some + characters may be lost! + + See 'encoding' for the possible values. Additionally, values may be + specified that can be handled by the converter, see + |mbyte-conversion|. + + When reading a file 'fileencoding' will be set from 'fileencodings'. + To read a file in a certain encoding it won't work by setting + 'fileencoding', use the |++enc| argument. One exception: when + 'fileencodings' is empty the value of 'fileencoding' is used. + For a new file the global value of 'fileencoding' is used. + + Prepending "8bit-" and "2byte-" has no meaning here, they are ignored. + When the option is set, the value is converted to lowercase. Thus + you can set it with uppercase values too. '_' characters are + replaced with '-'. If a name is recognized from the list for + 'encoding', it is replaced by the standard name. For example + "ISO8859-2" becomes "iso-8859-2". + + When this option is set, after starting to edit a file, the 'modified' + option is set, because the file would be different when written. + + Keep in mind that changing 'fenc' from a modeline happens + AFTER the text has been read, thus it applies to when the file will be + written. If you do set 'fenc' in a modeline, you might want to set + 'nomodified' to avoid not being able to ":q". + + This option can not be changed when 'modifiable' is off. + + *'fe'* + NOTE: Before version 6.0 this option specified the encoding for the + whole of Vim, this was a mistake. Now use 'encoding' instead. The + old short name was 'fe', which is no longer used. + + *'fileencodings'* *'fencs'* +'fileencodings' 'fencs' string (default: "ucs-bom", + "ucs-bom,utf-8,default,latin1" when + 'encoding' is set to a Unicode value) + global + {only available when compiled with the |+multi_byte| + feature} + {not in Vi} + This is a list of character encodings considered when starting to edit + an existing file. When a file is read, Vim tries to use the first + mentioned character encoding. If an error is detected, the next one + in the list is tried. When an encoding is found that works, + 'fileencoding' is set to it. If all fail, 'fileencoding' is set to + an empty string, which means the value of 'encoding' is used. + WARNING: Conversion can cause loss of information! When + 'encoding' is "utf-8" (or one of the other Unicode variants) + conversion is most likely done in a way that the reverse + conversion results in the same text. When 'encoding' is not + "utf-8" some non-ASCII characters may be lost! You can use + the |++bad| argument to specify what is done with characters + that can't be converted. + For an empty file or a file with only ASCII characters most encodings + will work and the first entry of 'fileencodings' will be used (except + "ucs-bom", which requires the BOM to be present). If you prefer + another encoding use an BufReadPost autocommand event to test if your + preferred encoding is to be used. Example: > + au BufReadPost * if search('\S', 'w') == 0 | + \ set fenc=iso-2022-jp | endif +< This sets 'fileencoding' to "iso-2022-jp" if the file does not contain + non-blank characters. + When the |++enc| argument is used then the value of 'fileencodings' is + not used. + Note that 'fileencodings' is not used for a new file, the global value + of 'fileencoding' is used instead. You can set it with: > + :setglobal fenc=iso-8859-2 +< This means that a non-existing file may get a different encoding than + an empty file. + The special value "ucs-bom" can be used to check for a Unicode BOM + (Byte Order Mark) at the start of the file. It must not be preceded + by "utf-8" or another Unicode encoding for this to work properly. + An entry for an 8-bit encoding (e.g., "latin1") should be the last, + because Vim cannot detect an error, thus the encoding is always + accepted. + The special value "default" can be used for the encoding from the + environment. This is the default value for 'encoding'. It is useful + when 'encoding' is set to "utf-8" and your environment uses a + non-latin1 encoding, such as Russian. + When 'encoding' is "utf-8" and a file contains an illegal byte + sequence it won't be recognized as UTF-8. You can use the |8g8| + command to find the illegal byte sequence. + WRONG VALUES: WHAT'S WRONG: + latin1,utf-8 "latin1" will always be used + utf-8,ucs-bom,latin1 BOM won't be recognized in an utf-8 + file + cp1250,latin1 "cp1250" will always be used + If 'fileencodings' is empty, 'fileencoding' is not modified. + See 'fileencoding' for the possible values. + Setting this option does not have an effect until the next time a file + is read. + + *'fileformat'* *'ff'* +'fileformat' 'ff' string (MS-DOS, MS-Windows, OS/2 default: "dos", + Unix default: "unix", + Macintosh default: "mac") + local to buffer + {not in Vi} + This gives the of the current buffer, which is used for + reading/writing the buffer from/to a file: + dos + unix + mac + When "dos" is used, CTRL-Z at the end of a file is ignored. + See |file-formats| and |file-read|. + For the character encoding of the file see 'fileencoding'. + When 'binary' is set, the value of 'fileformat' is ignored, file I/O + works like it was set to "unix'. + This option is set automatically when starting to edit a file and + 'fileformats' is not empty and 'binary' is off. + When this option is set, after starting to edit a file, the 'modified' + option is set, because the file would be different when written. + This option can not be changed when 'modifiable' is off. + For backwards compatibility: When this option is set to "dos", + 'textmode' is set, otherwise 'textmode' is reset. + + *'fileformats'* *'ffs'* +'fileformats' 'ffs' string (default: + Vim+Vi MS-DOS, MS-Windows OS/2: "dos,unix", + Vim Unix: "unix,dos", + Vim Mac: "mac,unix,dos", + Vi Cygwin: "unix,dos", + Vi others: "") + global + {not in Vi} + This gives the end-of-line () formats that will be tried when + starting to edit a new buffer and when reading a file into an existing + buffer: + - When empty, the format defined with 'fileformat' will be used + always. It is not set automatically. + - When set to one name, that format will be used whenever a new buffer + is opened. 'fileformat' is set accordingly for that buffer. The + 'fileformats' name will be used when a file is read into an existing + buffer, no matter what 'fileformat' for that buffer is set to. + - When more than one name is present, separated by commas, automatic + detection will be done when reading a file. When starting to + edit a file, a check is done for the : + 1. If all lines end in , and 'fileformats' includes "dos", + 'fileformat' is set to "dos". + 2. If a is found and 'fileformats' includes "unix", 'fileformat' + is set to "unix". Note that when a is found without a + preceding , "unix" is preferred over "dos". + 3. If 'fileformats' includes "mac", 'fileformat' is set to "mac". + This means that "mac" is only chosen when "unix" is not present, + or when no is found in the file, and when "dos" is not + present, or no is present in the file. + Also if "unix" was first chosen, but the first is before + the first and there appears to be more 's than 's in + the file, then 'fileformat' is set to "mac". + 4. If 'fileformat' is still not set, the first name from + 'fileformats' is used. + When reading a file into an existing buffer, the same is done, but + this happens like 'fileformat' has been set appropriately for that + file only, the option is not changed. + When 'binary' is set, the value of 'fileformats' is not used. + + For systems with a Dos-like (), when reading files that + are ":source"ed and for vimrc files, automatic detection may be + done: + - When 'fileformats' is empty, there is no automatic detection. Dos + format will be used. + - When 'fileformats' is set to one or more names, automatic detection + is done. This is based on the first in the file: If there is a + in front of it, Dos format is used, otherwise Unix format is + used. + Also see |file-formats|. + For backwards compatibility: When this option is set to an empty + string or one format (no comma is included), 'textauto' is reset, + otherwise 'textauto' is set. + NOTE: This option is set to the Vi default value when 'compatible' is + set and to the Vim default value when 'compatible' is reset. + + *'filetype'* *'ft'* +'filetype' 'ft' string (default: "") + local to buffer + {not in Vi} + {not available when compiled without the |+autocmd| + feature} + When this option is set, the FileType autocommand event is triggered. + All autocommands that match with the value of this option will be + executed. Thus the value of 'filetype' is used in place of the file + name. + Otherwise this option does not always reflect the current file type. + This option is normally set when the file type is detected. To enable + this use the ":filetype on" command. |:filetype| + Setting this option to a different value is most useful in a modeline, + for a file for which the file type is not automatically recognized. + Example, for in an IDL file: + /* vim: set filetype=idl : */ ~ + |FileType| |filetypes| + When a dot appears in the value then this separates two filetype + names. Example: + /* vim: set filetype=c.doxygen : */ ~ + This will use the "c" filetype first, then the "doxygen" filetype. + This works both for filetype plugins and for syntax files. More than + one dot may appear. + Do not confuse this option with 'osfiletype', which is for the file + type that is actually stored with the file. + This option is not copied to another buffer, independent of the 's' or + 'S' flag in 'cpoptions'. + Only normal file name characters can be used, "/\*?[|<>" are illegal. + + *'fillchars'* *'fcs'* +'fillchars' 'fcs' string (default "vert:|,fold:-") + global + {not in Vi} + {not available when compiled without the |+windows| + and |+folding| features} + Characters to fill the statuslines and vertical separators. + It is a comma separated list of items: + + item default Used for ~ + stl:c ' ' or '^' statusline of the current window + stlnc:c ' ' or '-' statusline of the non-current windows + vert:c '|' vertical separators |:vsplit| + fold:c '-' filling 'foldtext' + diff:c '-' deleted lines of the 'diff' option + + Any one that is omitted will fall back to the default. For "stl" and + "stlnc" the space will be used when there is highlighting, '^' or '-' + otherwise. + + Example: > + :set fillchars=stl:^,stlnc:-,vert:\|,fold:-,diff:- +< This is similar to the default, except that these characters will also + be used when there is highlighting. + + for "stl" and "stlnc" only single-byte values are supported. + + The highlighting used for these items: + item highlight group ~ + stl:c StatusLine |hl-StatusLine| + stlnc:c StatusLineNC |hl-StatusLineNC| + vert:c VertSplit |hl-VertSplit| + fold:c Folded |hl-Folded| + diff:c DiffDelete |hl-DiffDelete| + + *'fkmap'* *'fk'* *'nofkmap'* *'nofk'* +'fkmap' 'fk' boolean (default off) *E198* + global + {not in Vi} + {only available when compiled with the |+rightleft| + feature} + When on, the keyboard is mapped for the Farsi character set. + Normally you would set 'allowrevins' and use CTRL-_ in insert mode to + toggle this option |i_CTRL-_|. See |farsi.txt|. + + *'foldclose'* *'fcl'* +'foldclose' 'fcl' string (default "") + global + {not in Vi} + {not available when compiled without the |+folding| + feature} + When set to "all", a fold is closed when the cursor isn't in it and + its level is higher than 'foldlevel'. Useful if you want folds to + automatically close when moving out of them. + + *'foldcolumn'* *'fdc'* +'foldcolumn' 'fdc' number (default 0) + local to window + {not in Vi} + {not available when compiled without the |+folding| + feature} + When non-zero, a column with the specified width is shown at the side + of the window which indicates open and closed folds. The maximum + value is 12. + See |folding|. + + *'foldenable'* *'fen'* *'nofoldenable'* *'nofen'* +'foldenable' 'fen' boolean (default on) + local to window + {not in Vi} + {not available when compiled without the |+folding| + feature} + When off, all folds are open. This option can be used to quickly + switch between showing all text unfolded and viewing the text with + folds (including manually opened or closed folds). It can be toggled + with the |zi| command. The 'foldcolumn' will remain blank when + 'foldenable' is off. + This option is set by commands that create a new fold or close a fold. + See |folding|. + + *'foldexpr'* *'fde'* +'foldexpr' 'fde' string (default: "0") + local to window + {not in Vi} + {not available when compiled without the |+folding| + or |+eval| features} + The expression used for when 'foldmethod' is "expr". It is evaluated + for each line to obtain its fold level. See |fold-expr|. + + The expression may be evaluated in the |sandbox|, see + |sandbox-option|. + This option can't be set from a |modeline| when the 'diff' option is + on. + + It is not allowed to change text or jump to another window while + evaluating 'foldexpr' |textlock|. + + *'foldignore'* *'fdi'* +'foldignore' 'fdi' string (default: "#") + local to window + {not in Vi} + {not available when compiled without the |+folding| + feature} + Used only when 'foldmethod' is "indent". Lines starting with + characters in 'foldignore' will get their fold level from surrounding + lines. White space is skipped before checking for this character. + The default "#" works well for C programs. See |fold-indent|. + + *'foldlevel'* *'fdl'* +'foldlevel' 'fdl' number (default: 0) + local to window + {not in Vi} + {not available when compiled without the |+folding| + feature} + Sets the fold level: Folds with a higher level will be closed. + Setting this option to zero will close all folds. Higher numbers will + close fewer folds. + This option is set by commands like |zm|, |zM| and |zR|. + See |fold-foldlevel|. + + *'foldlevelstart'* *'fdls'* +'foldlevelstart' 'fdls' number (default: -1) + global + {not in Vi} + {not available when compiled without the |+folding| + feature} + Sets 'foldlevel' when starting to edit another buffer in a window. + Useful to always start editing with all folds closed (value zero), + some folds closed (one) or no folds closed (99). + This is done before reading any modeline, thus a setting in a modeline + overrules this option. Starting to edit a file for |diff-mode| also + ignores this option and closes all folds. + It is also done before BufReadPre autocommands, to allow an autocmd to + overrule the 'foldlevel' value for specific files. + When the value is negative, it is not used. + + *'foldmarker'* *'fmr'* *E536* +'foldmarker' 'fmr' string (default: "{{{,}}}") + local to window + {not in Vi} + {not available when compiled without the |+folding| + feature} + The start and end marker used when 'foldmethod' is "marker". There + must be one comma, which separates the start and end marker. The + marker is a literal string (a regular expression would be too slow). + See |fold-marker|. + + *'foldmethod'* *'fdm'* +'foldmethod' 'fdm' string (default: "manual") + local to window + {not in Vi} + {not available when compiled without the |+folding| + feature} + The kind of folding used for the current window. Possible values: + |fold-manual| manual Folds are created manually. + |fold-indent| indent Lines with equal indent form a fold. + |fold-expr| expr 'foldexpr' gives the fold level of a line. + |fold-marker| marker Markers are used to specify folds. + |fold-syntax| syntax Syntax highlighting items specify folds. + |fold-diff| diff Fold text that is not changed. + + *'foldminlines'* *'fml'* +'foldminlines' 'fml' number (default: 1) + local to window + {not in Vi} + {not available when compiled without the |+folding| + feature} + Sets the minimum number of screen lines for a fold to be displayed + closed. Also for manually closed folds. + Note that this only has an effect of what is displayed. After using + "zc" to close a fold, which is displayed open because it's smaller + than 'foldminlines', a following "zc" may close a containing fold. + + *'foldnestmax'* *'fdn'* +'foldnestmax' 'fdn' number (default: 20) + local to window + {not in Vi} + {not available when compiled without the |+folding| + feature} + Sets the maximum nesting of folds for the "indent" and "syntax" + methods. This avoids that too many folds will be created. Using more + than 20 doesn't work, because the internal limit is 20. + + *'foldopen'* *'fdo'* +'foldopen' 'fdo' string (default: "block,hor,mark,percent,quickfix, + search,tag,undo") + global + {not in Vi} + {not available when compiled without the |+folding| + feature} + Specifies for which type of commands folds will be opened, if the + command moves the cursor into a closed fold. It is a comma separated + list of items. + item commands ~ + all any + block "(", "{", "[[", "[{", etc. + hor horizontal movements: "l", "w", "fx", etc. + insert any command in Insert mode + jump far jumps: "G", "gg", etc. + mark jumping to a mark: "'m", CTRL-O, etc. + percent "%" + quickfix ":cn", ":crew", ":make", etc. + search search for a pattern: "/", "n", "*", "gd", etc. + (not for a search pattern in a ":" command) + Also for |[s| and |]s|. + tag jumping to a tag: ":ta", CTRL-T, etc. + undo undo or redo: "u" and CTRL-R + When the command is part of a mapping this option is not used. Add + the |zv| command to the mapping to get the same effect. + When a movement command is used for an operator (e.g., "dl" or "y%") + this option is not used. This means the operator will include the + whole closed fold. + Note that vertical movements are not here, because it would make it + very difficult to move onto a closed fold. + In insert mode the folds containing the cursor will always be open + when text is inserted. + To close folds you can re-apply 'foldlevel' with the |zx| command or + set the 'foldclose' option to "all". + + *'foldtext'* *'fdt'* +'foldtext' 'fdt' string (default: "foldtext()") + local to window + {not in Vi} + {not available when compiled without the |+folding| + feature} + An expression which is used to specify the text displayed for a closed + fold. See |fold-foldtext|. + + The expression may be evaluated in the |sandbox|, see + |sandbox-option|. + + It is not allowed to change text or jump to another window while + evaluating 'foldtext' |textlock|. + + *'formatoptions'* *'fo'* +'formatoptions' 'fo' string (Vim default: "tcq", Vi default: "vt") + local to buffer + {not in Vi} + This is a sequence of letters which describes how automatic + formatting is to be done. See |fo-table|. When the 'paste' option is + on, no formatting is done (like 'formatoptions' is empty). Commas can + be inserted for readability. + To avoid problems with flags that are added in the future, use the + "+=" and "-=" feature of ":set" |add-option-flags|. + NOTE: This option is set to the Vi default value when 'compatible' is + set and to the Vim default value when 'compatible' is reset. + + *'formatlistpat'* *'flp'* +'formatlistpat' 'flp' string (default: "^\s*\d\+[\]:.)}\t ]\s*") + local to buffer + {not in Vi} + A pattern that is used to recognize a list header. This is used for + the "n" flag in 'formatoptions'. + The pattern must match exactly the text that will be the indent for + the line below it. You can use |/\ze| to mark the end of the match + while still checking more characters. There must be a character + following the pattern, when it matches the whole line it is handled + like there is no match. + The default recognizes a number, followed by an optional punctuation + character and white space. + + *'formatprg'* *'fp'* +'formatprg' 'fp' string (default "") + global + {not in Vi} + The name of an external program that will be used to format the lines + selected with the |gq| operator. The program must take the input on + stdin and produce the output on stdout. The Unix program "fmt" is + such a program. + If the 'formatexpr' option is not empty it will be used instead. + Otherwise, if 'formatprg' option is an empty string, the internal + format function will be used |C-indenting|. + Environment variables are expanded |:set_env|. See |option-backslash| + about including spaces and backslashes. + The expression may be evaluated in the |sandbox|, see + |sandbox-option|. + + *'formatexpr'* *'fex'* +'formatexpr' 'fex' string (default "") + local to buffer + {not in Vi} + {not available when compiled without the |+eval| + feature} + Expression which is evaluated to format a range of lines for the |gq| + operator or automatic formatting (see 'formatoptions'). When this + option is empty 'formatprg' is used. + + The |v:lnum| variable holds the first line to be formatted. + The |v:count| variable holds the number of lines to be formatted. + The |v:char| variable holds the character that is going to be + inserted if the expression is being evaluated due to + automatic formatting. This can be empty. Don't insert + it yet! + + Example: > + :set formatexpr=mylang#Format() +< This will invoke the mylang#Format() function in the + autoload/mylang.vim file in 'runtimepath'. |autoload| + + The expression is also evaluated when 'textwidth' is set and adding + text beyond that limit. This happens under the same conditions as + when internal formatting is used. Make sure the cursor is kept in the + same spot relative to the text then! The |mode()| function will + return "i" or "R" in this situation. + + When the expression evaluates to non-zero Vim will fall back to using + the internal format mechanism. + + The expression may be evaluated in the |sandbox|, see + |sandbox-option|. + + *'fsync'* *'fs'* +'fsync' 'fs' boolean (default on) + global + {not in Vi} + When on, the library function fsync() will be called after writing a + file. This will flush a file to disk, ensuring that it is safely + written even on filesystems which do metadata-only journaling. This + will force the harddrive to spin up on Linux systems running in laptop + mode, so it may be undesirable in some situations. Be warned that + turning this off increases the chances of data loss after a crash. On + systems without an fsync() implementation, this variable is always + off. + Also see 'swapsync' for controlling fsync() on swap files. + + *'gdefault'* *'gd'* *'nogdefault'* *'nogd'* +'gdefault' 'gd' boolean (default off) + global + {not in Vi} + When on, the ":substitute" flag 'g' is default on. This means that + all matches in a line are substituted instead of one. When a 'g' flag + is given to a ":substitute" command, this will toggle the substitution + of all or one match. See |complex-change|. + + command 'gdefault' on 'gdefault' off ~ + :s/// subst. all subst. one + :s///g subst. one subst. all + :s///gg subst. all subst. one + + NOTE: This option is reset when 'compatible' is set. + + *'grepformat'* *'gfm'* +'grepformat' 'gfm' string (default "%f:%l%m,%f %l%m") + global + {not in Vi} + Format to recognize for the ":grep" command output. + This is a scanf-like string that uses the same format as the + 'errorformat' option: see |errorformat|. + + *'grepprg'* *'gp'* +'grepprg' 'gp' string (default "grep -n ", + Unix: "grep -n $* /dev/null", + Win32: "findstr /n" or "grep -n", + VMS: "SEARCH/NUMBERS ") + global or local to buffer |global-local| + {not in Vi} + Program to use for the |:grep| command. This option may contain '%' + and '#' characters, which are expanded like when used in a command- + line. The placeholder "$*" is allowed to specify where the arguments + will be included. Environment variables are expanded |:set_env|. See + |option-backslash| about including spaces and backslashes. + When your "grep" accepts the "-H" argument, use this to make ":grep" + also work well with a single file: > + :set grepprg=grep\ -nH +< Special value: When 'grepprg' is set to "internal" the |:grep| command + works like |:vimgrep|, |:lgrep| like |:lvimgrep|, |:grepadd| like + |:vimgrepadd| and |:lgrepadd| like |:lvimgrepadd|. + See also the section |:make_makeprg|, since most of the comments there + apply equally to 'grepprg'. + For Win32, the default is "findstr /n" if "findstr.exe" can be found, + otherwise it's "grep -n". + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + *'guicursor'* *'gcr'* *E545* *E546* *E548* *E549* +'guicursor' 'gcr' string (default "n-v-c:block-Cursor/lCursor, + ve:ver35-Cursor, + o:hor50-Cursor, + i-ci:ver25-Cursor/lCursor, + r-cr:hor20-Cursor/lCursor, + sm:block-Cursor + -blinkwait175-blinkoff150-blinkon175", + for MS-DOS and Win32 console: + "n-v-c:block,o:hor50,i-ci:hor15, + r-cr:hor30,sm:block") + global + {not in Vi} + {only available when compiled with GUI enabled, and + for MS-DOS and Win32 console} + This option tells Vim what the cursor should look like in different + modes. It fully works in the GUI. In an MSDOS or Win32 console, only + the height of the cursor can be changed. This can be done by + specifying a block cursor, or a percentage for a vertical or + horizontal cursor. + For a console the 't_SI' and 't_EI' escape sequences are used. + + The option is a comma separated list of parts. Each part consist of a + mode-list and an argument-list: + mode-list:argument-list,mode-list:argument-list,.. + The mode-list is a dash separated list of these modes: + n Normal mode + v Visual mode + ve Visual mode with 'selection' "exclusive" (same as 'v', + if not specified) + o Operator-pending mode + i Insert mode + r Replace mode + c Command-line Normal (append) mode + ci Command-line Insert mode + cr Command-line Replace mode + sm showmatch in Insert mode + a all modes + The argument-list is a dash separated list of these arguments: + hor{N} horizontal bar, {N} percent of the character height + ver{N} vertical bar, {N} percent of the character width + block block cursor, fills the whole character + [only one of the above three should be present] + blinkwait{N} *cursor-blinking* + blinkon{N} + blinkoff{N} + blink times for cursor: blinkwait is the delay before + the cursor starts blinking, blinkon is the time that + the cursor is shown and blinkoff is the time that the + cursor is not shown. The times are in msec. When one + of the numbers is zero, there is no blinking. The + default is: "blinkwait700-blinkon400-blinkoff250". + These numbers are used for a missing entry. This + means that blinking is enabled by default. To switch + blinking off you can use "blinkon0". The cursor only + blinks when Vim is waiting for input, not while + executing a command. + To make the cursor blink in an xterm, see + |xterm-blink|. + {group-name} + a highlight group name, that sets the color and font + for the cursor + {group-name}/{group-name} + Two highlight group names, the first is used when + no language mappings are used, the other when they + are. |language-mapping| + + Examples of parts: + n-c-v:block-nCursor in Normal, Command-line and Visual mode, use a + block cursor with colors from the "nCursor" + highlight group + i-ci:ver30-iCursor-blinkwait300-blinkon200-blinkoff150 + In Insert and Command-line Insert mode, use a + 30% vertical bar cursor with colors from the + "iCursor" highlight group. Blink a bit + faster. + + The 'a' mode is different. It will set the given argument-list for + all modes. It does not reset anything to defaults. This can be used + to do a common setting for all modes. For example, to switch off + blinking: "a:blinkon0" + + Examples of cursor highlighting: > + :highlight Cursor gui=reverse guifg=NONE guibg=NONE + :highlight Cursor gui=NONE guifg=bg guibg=fg +< + *'guifont'* *'gfn'* + *E235* *E596* *E610* *E611* +'guifont' 'gfn' string (default "") + global + {not in Vi} + {only available when compiled with GUI enabled} + This is a list of fonts which will be used for the GUI version of Vim. + In its simplest form the value is just one font name. When + the font cannot be found you will get an error message. To try other + font names a list can be specified, font names separated with commas. + The first valid font is used. + + On systems where 'guifontset' is supported (X11) and 'guifontset' is + not empty, then 'guifont' is not used. + + Spaces after a comma are ignored. To include a comma in a font name + precede it with a backslash. Setting an option requires an extra + backslash before a space and a backslash. See also + |option-backslash|. For example: > + :set guifont=Screen15,\ 7x13,font\\,with\\,commas +< will make Vim try to use the font "Screen15" first, and if it fails it + will try to use "7x13" and then "font,with,commas" instead. + + If none of the fonts can be loaded, Vim will keep the current setting. + If an empty font list is given, Vim will try using other resource + settings (for X, it will use the Vim.font resource), and finally it + will try some builtin default which should always be there ("7x13" in + the case of X). The font names given should be "normal" fonts. Vim + will try to find the related bold and italic fonts. + + For Win32, GTK, Motif, Mac OS and Photon: > + :set guifont=* +< will bring up a font requester, where you can pick the font you want. + + The font name depends on the GUI used. See |setting-guifont| for a + way to set 'guifont' for various systems. + + For the GTK+ 2 GUI the font name looks like this: > + :set guifont=Andale\ Mono\ 11 +< That's all. XLFDs are not used. For Chinese this is reported to work + well: > + if has("gui_gtk2") + set guifont=Bitstream\ Vera\ Sans\ Mono\ 12,Fixed\ 12 + set guifontwide=Microsoft\ Yahei\ 12,WenQuanYi\ Zen\ Hei\ 12 + endif +< + For Mac OSX you can use something like this: > + :set guifont=Monaco:h10 +< Also see 'macatsui', it can help fix display problems. + *E236* + Note that the fonts must be mono-spaced (all characters have the same + width). An exception is GTK 2: all fonts are accepted, but + mono-spaced fonts look best. + + To preview a font on X11, you might be able to use the "xfontsel" + program. The "xlsfonts" program gives a list of all available fonts. + + For the Win32 GUI *E244* *E245* + - takes these options in the font name: + hXX - height is XX (points, can be floating-point) + wXX - width is XX (points, can be floating-point) + b - bold + i - italic + u - underline + s - strikeout + cXX - character set XX. Valid charsets are: ANSI, ARABIC, + BALTIC, CHINESEBIG5, DEFAULT, EASTEUROPE, GB2312, GREEK, + HANGEUL, HEBREW, JOHAB, MAC, OEM, RUSSIAN, SHIFTJIS, + SYMBOL, THAI, TURKISH, VIETNAMESE ANSI and BALTIC. + Normally you would use "cDEFAULT". + + Use a ':' to separate the options. + - A '_' can be used in the place of a space, so you don't need to use + backslashes to escape the spaces. + - Examples: > + :set guifont=courier_new:h12:w5:b:cRUSSIAN + :set guifont=Andale_Mono:h7.5:w4.5 +< See also |font-sizes|. + + *'guifontset'* *'gfs'* + *E250* *E252* *E234* *E597* *E598* +'guifontset' 'gfs' string (default "") + global + {not in Vi} + {only available when compiled with GUI enabled and + with the |+xfontset| feature} + {not available in the GTK+ 2 GUI} + When not empty, specifies two (or more) fonts to be used. The first + one for normal English, the second one for your special language. See + |xfontset|. + Setting this option also means that all font names will be handled as + a fontset name. Also the ones used for the "font" argument of the + |:highlight| command. + The fonts must match with the current locale. If fonts for the + character sets that the current locale uses are not included, setting + 'guifontset' will fail. + Note the difference between 'guifont' and 'guifontset': In 'guifont' + the comma-separated names are alternative names, one of which will be + used. In 'guifontset' the whole string is one fontset name, + including the commas. It is not possible to specify alternative + fontset names. + This example works on many X11 systems: > + :set guifontset=-*-*-medium-r-normal--16-*-*-*-c-*-*-* +< + *'guifontwide'* *'gfw'* *E231* *E533* *E534* +'guifontwide' 'gfw' string (default "") + global + {not in Vi} + {only available when compiled with GUI enabled} + When not empty, specifies a comma-separated list of fonts to be used + for double-width characters. The first font that can be loaded is + used. + Note: The size of these fonts must be exactly twice as wide as the one + specified with 'guifont' and the same height. + + All GUI versions but GTK+ 2: + + 'guifontwide' is only used when 'encoding' is set to "utf-8" and + 'guifontset' is empty or invalid. + When 'guifont' is set and a valid font is found in it and + 'guifontwide' is empty Vim will attempt to find a matching + double-width font and set 'guifontwide' to it. + + GTK+ 2 GUI only: *guifontwide_gtk2* + + If set and valid, 'guifontwide' is always used for double width + characters, even if 'encoding' is not set to "utf-8". + Vim does not attempt to find an appropriate value for 'guifontwide' + automatically. If 'guifontwide' is empty Pango/Xft will choose the + font for characters not available in 'guifont'. Thus you do not need + to set 'guifontwide' at all unless you want to override the choice + made by Pango/Xft. + + *'guiheadroom'* *'ghr'* +'guiheadroom' 'ghr' number (default 50) + global + {not in Vi} {only for GTK and X11 GUI} + The number of pixels subtracted from the screen height when fitting + the GUI window on the screen. Set this before the GUI is started, + e.g., in your |gvimrc| file. When zero, the whole screen height will + be used by the window. When positive, the specified number of pixel + lines will be left for window decorations and other items on the + screen. Set it to a negative value to allow windows taller than the + screen. + + *'guioptions'* *'go'* +'guioptions' 'go' string (default "gmrLtT" (MS-Windows), + "agimrLtT" (GTK, Motif and Athena)) + global + {not in Vi} + {only available when compiled with GUI enabled} + This option only has an effect in the GUI version of Vim. It is a + sequence of letters which describes what components and options of the + GUI should be used. + To avoid problems with flags that are added in the future, use the + "+=" and "-=" feature of ":set" |add-option-flags|. + + Valid letters are as follows: + *guioptions_a* *'go-a'* + 'a' Autoselect: If present, then whenever VISUAL mode is started, + or the Visual area extended, Vim tries to become the owner of + the windowing system's global selection. This means that the + Visually highlighted text is available for pasting into other + applications as well as into Vim itself. When the Visual mode + ends, possibly due to an operation on the text, or when an + application wants to paste the selection, the highlighted text + is automatically yanked into the "* selection register. + Thus the selection is still available for pasting into other + applications after the VISUAL mode has ended. + If not present, then Vim won't become the owner of the + windowing system's global selection unless explicitly told to + by a yank or delete operation for the "* register. + The same applies to the modeless selection. + *'go-A'* + 'A' Autoselect for the modeless selection. Like 'a', but only + applies to the modeless selection. + + 'guioptions' autoselect Visual autoselect modeless ~ + "" - - + "a" yes yes + "A" - yes + "aA" yes yes + + *'go-c'* + 'c' Use console dialogs instead of popup dialogs for simple + choices. + *'go-e'* + 'e' Add tab pages when indicated with 'showtabline'. + 'guitablabel' can be used to change the text in the labels. + When 'e' is missing a non-GUI tab pages line may be used. + The GUI tabs are only supported on some systems, currently + GTK, Motif, Mac OS/X and MS-Windows. + *'go-f'* + 'f' Foreground: Don't use fork() to detach the GUI from the shell + where it was started. Use this for programs that wait for the + editor to finish (e.g., an e-mail program). Alternatively you + can use "gvim -f" or ":gui -f" to start the GUI in the + foreground. |gui-fork| + Note: Set this option in the vimrc file. The forking may have + happened already when the |gvimrc| file is read. + *'go-i'* + 'i' Use a Vim icon. For GTK with KDE it is used in the left-upper + corner of the window. It's black&white on non-GTK, because of + limitations of X11. For a color icon, see |X11-icon|. + *'go-m'* + 'm' Menu bar is present. + *'go-M'* + 'M' The system menu "$VIMRUNTIME/menu.vim" is not sourced. Note + that this flag must be added in the .vimrc file, before + switching on syntax or filetype recognition (when the |gvimrc| + file is sourced the system menu has already been loaded; the + ":syntax on" and ":filetype on" commands load the menu too). + *'go-g'* + 'g' Grey menu items: Make menu items that are not active grey. If + 'g' is not included inactive menu items are not shown at all. + Exception: Athena will always use grey menu items. + *'go-t'* + 't' Include tearoff menu items. Currently only works for Win32, + GTK+, and Motif 1.2 GUI. + *'go-T'* + 'T' Include Toolbar. Currently only in Win32, GTK+, Motif, Photon + and Athena GUIs. + *'go-r'* + 'r' Right-hand scrollbar is always present. + *'go-R'* + 'R' Right-hand scrollbar is present when there is a vertically + split window. + *'go-l'* + 'l' Left-hand scrollbar is always present. + *'go-L'* + 'L' Left-hand scrollbar is present when there is a vertically + split window. + *'go-b'* + 'b' Bottom (horizontal) scrollbar is present. Its size depends on + the longest visible line, or on the cursor line if the 'h' + flag is included. |gui-horiz-scroll| + *'go-h'* + 'h' Limit horizontal scrollbar size to the length of the cursor + line. Reduces computations. |gui-horiz-scroll| + + And yes, you may even have scrollbars on the left AND the right if + you really want to :-). See |gui-scrollbars| for more information. + + *'go-v'* + 'v' Use a vertical button layout for dialogs. When not included, + a horizontal layout is preferred, but when it doesn't fit a + vertical layout is used anyway. + *'go-p'* + 'p' Use Pointer callbacks for X11 GUI. This is required for some + window managers. If the cursor is not blinking or hollow at + the right moment, try adding this flag. This must be done + before starting the GUI. Set it in your |gvimrc|. Adding or + removing it after the GUI has started has no effect. + *'go-F'* + 'F' Add a footer. Only for Motif. See |gui-footer|. + + + *'guipty'* *'noguipty'* +'guipty' boolean (default on) + global + {not in Vi} + {only available when compiled with GUI enabled} + Only in the GUI: If on, an attempt is made to open a pseudo-tty for + I/O to/from shell commands. See |gui-pty|. + + *'guitablabel'* *'gtl'* +'guitablabel' 'gtl' string (default empty) + global + {not in Vi} + {only available when compiled with GUI enabled and + with the |+windows| feature} + When nonempty describes the text to use in a label of the GUI tab + pages line. When empty and when the result is empty Vim will use a + default label. See |setting-guitablabel| for more info. + + The format of this option is like that of 'statusline'. + 'guitabtooltip' is used for the tooltip, see below. + + Only used when the GUI tab pages line is displayed. 'e' must be + present in 'guioptions'. For the non-GUI tab pages line 'tabline' is + used. + + *'guitabtooltip'* *'gtt'* +'guitabtooltip' 'gtt' string (default empty) + global + {not in Vi} + {only available when compiled with GUI enabled and + with the |+windows| feature} + When nonempty describes the text to use in a tooltip for the GUI tab + pages line. When empty Vim will use a default tooltip. + This option is otherwise just like 'guitablabel' above. + You can include a line break. Simplest method is to use |:let|: > + :let &guitabtooltip = "line one\nline two" +< + + *'helpfile'* *'hf'* +'helpfile' 'hf' string (default (MSDOS) "$VIMRUNTIME\doc\help.txt" + (others) "$VIMRUNTIME/doc/help.txt") + global + {not in Vi} + Name of the main help file. All distributed help files should be + placed together in one directory. Additionally, all "doc" directories + in 'runtimepath' will be used. + Environment variables are expanded |:set_env|. For example: + "$VIMRUNTIME/doc/help.txt". If $VIMRUNTIME is not set, $VIM is also + tried. Also see |$VIMRUNTIME| and |option-backslash| about including + spaces and backslashes. + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + *'helpheight'* *'hh'* +'helpheight' 'hh' number (default 20) + global + {not in Vi} + {not available when compiled without the |+windows| + feature} + Minimal initial height of the help window when it is opened with the + ":help" command. The initial height of the help window is half of the + current window, or (when the 'ea' option is on) the same as other + windows. When the height is less than 'helpheight', the height is + set to 'helpheight'. Set to zero to disable. + + *'helplang'* *'hlg'* +'helplang' 'hlg' string (default: messages language or empty) + global + {only available when compiled with the |+multi_lang| + feature} + {not in Vi} + Comma separated list of languages. Vim will use the first language + for which the desired help can be found. The English help will always + be used as a last resort. You can add "en" to prefer English over + another language, but that will only find tags that exist in that + language and not in the English help. + Example: > + :set helplang=de,it +< This will first search German, then Italian and finally English help + files. + When using |CTRL-]| and ":help!" in a non-English help file Vim will + try to find the tag in the current language before using this option. + See |help-translated|. + + *'hidden'* *'hid'* *'nohidden'* *'nohid'* +'hidden' 'hid' boolean (default off) + global + {not in Vi} + When off a buffer is unloaded when it is |abandon|ed. When on a + buffer becomes hidden when it is |abandon|ed. If the buffer is still + displayed in another window, it does not become hidden, of course. + The commands that move through the buffer list sometimes make a buffer + hidden although the 'hidden' option is off: When the buffer is + modified, 'autowrite' is off or writing is not possible, and the '!' + flag was used. See also |windows.txt|. + To only make one buffer hidden use the 'bufhidden' option. + This option is set for one command with ":hide {command}" |:hide|. + WARNING: It's easy to forget that you have changes in hidden buffers. + Think twice when using ":q!" or ":qa!". + + *'highlight'* *'hl'* +'highlight' 'hl' string (default (as a single string): + "8:SpecialKey,@:NonText,d:Directory, + e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg, + M:ModeMsg,n:LineNr,r:Question, + s:StatusLine,S:StatusLineNC,c:VertSplit, + t:Title,v:Visual,w:WarningMsg,W:WildMenu, + f:Folded,F:FoldColumn,A:DiffAdd, + C:DiffChange,D:DiffDelete,T:DiffText, + >:SignColumn,B:SpellBad,P:SpellCap, + R:SpellRare,L:SpellLocal,-:Conceal, + +:Pmenu,=:PmenuSel, + x:PmenuSbar,X:PmenuThumb") + global + {not in Vi} + This option can be used to set highlighting mode for various + occasions. It is a comma separated list of character pairs. The + first character in a pair gives the occasion, the second the mode to + use for that occasion. The occasions are: + |hl-SpecialKey| 8 Meta and special keys listed with ":map" + |hl-NonText| @ '~' and '@' at the end of the window and + characters from 'showbreak' + |hl-Directory| d directories in CTRL-D listing and other special + things in listings + |hl-ErrorMsg| e error messages + h (obsolete, ignored) + |hl-IncSearch| i 'incsearch' highlighting + |hl-Search| l last search pattern highlighting (see 'hlsearch') + |hl-MoreMsg| m |more-prompt| + |hl-ModeMsg| M Mode (e.g., "-- INSERT --") + |hl-LineNr| n line number for ":number" and ":#" commands, and + when 'number' or 'relativenumber' option is set. + |hl-Question| r |hit-enter| prompt and yes/no questions + |hl-StatusLine| s status line of current window |status-line| + |hl-StatusLineNC| S status lines of not-current windows + |hl-Title| t Titles for output from ":set all", ":autocmd" etc. + |hl-VertSplit| c column used to separate vertically split windows + |hl-Visual| v Visual mode + |hl-VisualNOS| V Visual mode when Vim does is "Not Owning the + Selection" Only X11 Gui's |gui-x11| and + |xterm-clipboard|. + |hl-WarningMsg| w warning messages + |hl-WildMenu| W wildcard matches displayed for 'wildmenu' + |hl-Folded| f line used for closed folds + |hl-FoldColumn| F 'foldcolumn' + |hl-DiffAdd| A added line in diff mode + |hl-DiffChange| C changed line in diff mode + |hl-DiffDelete| D deleted line in diff mode + |hl-DiffText| T inserted text in diff mode + |hl-SignColumn| > column used for |signs| + |hl-SpellBad| B misspelled word |spell| + |hl-SpellCap| P word that should start with capital |spell| + |hl-SpellRare| R rare word |spell| + |hl-SpellLocal| L word from other region |spell| + |hl-Conceal| - the placeholders used for concealed characters + (see 'conceallevel') + |hl-Pmenu| + popup menu normal line + |hl-PmenuSel| = popup menu normal line + |hl-PmenuSbar| x popup menu scrollbar + |hl-PmenuThumb| X popup menu scrollbar thumb + + The display modes are: + r reverse (termcap entry "mr" and "me") + i italic (termcap entry "ZH" and "ZR") + b bold (termcap entry "md" and "me") + s standout (termcap entry "so" and "se") + u underline (termcap entry "us" and "ue") + c undercurl (termcap entry "Cs" and "Ce") + n no highlighting + - no highlighting + : use a highlight group + The default is used for occasions that are not included. + If you want to change what the display modes do, see |dos-colors| + for an example. + When using the ':' display mode, this must be followed by the name of + a highlight group. A highlight group can be used to define any type + of highlighting, including using color. See |:highlight| on how to + define one. The default uses a different group for each occasion. + See |highlight-default| for the default highlight groups. + + *'hlsearch'* *'hls'* *'nohlsearch'* *'nohls'* +'hlsearch' 'hls' boolean (default off) + global + {not in Vi} + {not available when compiled without the + |+extra_search| feature} + When there is a previous search pattern, highlight all its matches. + The type of highlighting used can be set with the 'l' occasion in the + 'highlight' option. This uses the "Search" highlight group by + default. Note that only the matching text is highlighted, any offsets + are not applied. + See also: 'incsearch' and |:match|. + 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 spent 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 + line below a closed fold. A match in a previous line which is not + drawn may not continue in a newly drawn line. + NOTE: This option is reset when 'compatible' is set. + + *'history'* *'hi'* +'history' 'hi' number (Vim default: 20, Vi default: 0) + global + {not in Vi} + A history of ":" commands, and a history of previous search patterns + are remembered. This option decides how many entries may be stored in + each of these histories (see |cmdline-editing|). + NOTE: This option is set to the Vi default value when 'compatible' is + set and to the Vim default value when 'compatible' is reset. + + *'hkmap'* *'hk'* *'nohkmap'* *'nohk'* +'hkmap' 'hk' boolean (default off) + global + {not in Vi} + {only available when compiled with the |+rightleft| + feature} + When on, the keyboard is mapped for the Hebrew character set. + Normally you would set 'allowrevins' and use CTRL-_ in insert mode to + toggle this option. See |rileft.txt|. + NOTE: This option is reset when 'compatible' is set. + + *'hkmapp'* *'hkp'* *'nohkmapp'* *'nohkp'* +'hkmapp' 'hkp' boolean (default off) + global + {not in Vi} + {only available when compiled with the |+rightleft| + feature} + When on, phonetic keyboard mapping is used. 'hkmap' must also be on. + This is useful if you have a non-Hebrew keyboard. + See |rileft.txt|. + NOTE: This option is reset when 'compatible' is set. + + *'icon'* *'noicon'* +'icon' boolean (default off, on when title can be restored) + global + {not in Vi} + {not available when compiled without the |+title| + feature} + When on, the icon text of the window will be set to the value of + 'iconstring' (if it is not empty), or to the name of the file + currently being edited. Only the last part of the name is used. + Overridden by the 'iconstring' option. + Only works if the terminal supports setting window icons (currently + only X11 GUI and terminals with a non-empty 't_IS' option - these are + Unix xterm and iris-ansi by default, where 't_IS' is taken from the + builtin termcap). + When Vim was compiled with HAVE_X11 defined, the original icon will be + restored if possible |X11|. See |X11-icon| for changing the icon on + X11. + + *'iconstring'* +'iconstring' string (default "") + global + {not in Vi} + {not available when compiled without the |+title| + feature} + When this option is not empty, it will be used for the icon text of + the window. This happens only when the 'icon' option is on. + Only works if the terminal supports setting window icon text + (currently only X11 GUI and terminals with a non-empty 't_IS' option). + Does not work for MS Windows. + When Vim was compiled with HAVE_X11 defined, the original icon will be + restored if possible |X11|. + When this option contains printf-style '%' items, they will be + expanded according to the rules used for 'statusline'. See + 'titlestring' for example settings. + {not available when compiled without the |+statusline| feature} + + *'ignorecase'* *'ic'* *'noignorecase'* *'noic'* +'ignorecase' 'ic' boolean (default off) + global + Ignore case in search patterns. Also used when searching in the tags + file. + Also see 'smartcase'. + Can be overruled by using "\c" or "\C" in the pattern, see + |/ignorecase|. + + *'imactivatekey'* *'imak'* +'imactivatekey' 'imak' string (default "") + global + {not in Vi} + {only available when compiled with |+xim| and + |+GUI_GTK|} *E599* + Specifies the key that your Input Method in X-Windows uses for + activation. When this is specified correctly, vim can fully control + IM with 'imcmdline', 'iminsert' and 'imsearch'. + You can't use this option to change the activation key, the option + tells Vim what the key is. + Format: + [MODIFIER_FLAG-]KEY_STRING + + These characters can be used for MODIFIER_FLAG (case is ignored): + S Shift key + L Lock key + C Control key + 1 Mod1 key + 2 Mod2 key + 3 Mod3 key + 4 Mod4 key + 5 Mod5 key + Combinations are allowed, for example "S-C-space" or "SC-space" are + both shift+ctrl+space. + See and XStringToKeysym for KEY_STRING. + + Example: > + :set imactivatekey=S-space +< "S-space" means shift+space. This is the activation key for kinput2 + + canna (Japanese), and ami (Korean). + + *'imcmdline'* *'imc'* *'noimcmdline'* *'noimc'* +'imcmdline' 'imc' boolean (default off) + global + {not in Vi} + {only available when compiled with the |+xim|, + |+multi_byte_ime| or |global-ime| features} + When set the Input Method is always on when starting to edit a command + line, unless entering a search pattern (see 'imsearch' for that). + Setting this option is useful when your input method allows entering + English characters directly, e.g., when it's used to type accented + characters with dead keys. + + *'imdisable'* *'imd'* *'noimdisable'* *'noimd'* +'imdisable' 'imd' boolean (default off, on for some systems (SGI)) + global + {not in Vi} + {only available when compiled with the |+xim|, + |+multi_byte_ime| or |global-ime| features} + When set the Input Method is never used. This is useful to disable + the IM when it doesn't work properly. + Currently this option is on by default for SGI/IRIX machines. This + may change in later releases. + + *'iminsert'* *'imi'* +'iminsert' 'imi' number (default 0, 2 when an input method is supported) + local to buffer + {not in Vi} + Specifies whether :lmap or an Input Method (IM) is to be used in + Insert mode. Valid values: + 0 :lmap is off and IM is off + 1 :lmap is ON and IM is off + 2 :lmap is off and IM is ON + 2 is available only when compiled with the |+multi_byte_ime|, |+xim| + or |global-ime|. + To always reset the option to zero when leaving Insert mode with + this can be used: > + :inoremap :set iminsert=0 +< This makes :lmap and IM turn off automatically when leaving Insert + mode. + Note that this option changes when using CTRL-^ in Insert mode + |i_CTRL-^|. + The value is set to 1 when setting 'keymap' to a valid keymap name. + It is also used for the argument of commands like "r" and "f". + The value 0 may not work correctly with Athena and Motif with some XIM + methods. Use 'imdisable' to disable XIM then. + + *'imsearch'* *'ims'* +'imsearch' 'ims' number (default 0, 2 when an input method is supported) + local to buffer + {not in Vi} + Specifies whether :lmap or an Input Method (IM) is to be used when + entering a search pattern. Valid values: + -1 the value of 'iminsert' is used, makes it look like + 'iminsert' is also used when typing a search pattern + 0 :lmap is off and IM is off + 1 :lmap is ON and IM is off + 2 :lmap is off and IM is ON + Note that this option changes when using CTRL-^ in Command-line mode + |c_CTRL-^|. + The value is set to 1 when it is not -1 and setting the 'keymap' + option to a valid keymap name. + The value 0 may not work correctly with Athena and Motif with some XIM + methods. Use 'imdisable' to disable XIM then. + + *'include'* *'inc'* +'include' 'inc' string (default "^\s*#\s*include") + global or local to buffer |global-local| + {not in Vi} + {not available when compiled without the + |+find_in_path| feature} + Pattern to be used to find an include command. It is a search + pattern, just like for the "/" command (See |pattern|). The default + value is for C programs. This option is used for the commands "[i", + "]I", "[d", etc. + Normally the 'isfname' option is used to recognize the file name that + comes after the matched pattern. But if "\zs" appears in the pattern + then the text matched from "\zs" to the end, or until "\ze" if it + appears, is used as the file name. Use this to include characters + that are not in 'isfname', such as a space. You can then use + 'includeexpr' to process the matched text. + See |option-backslash| about including spaces and backslashes. + + *'includeexpr'* *'inex'* +'includeexpr' 'inex' string (default "") + local to buffer + {not in Vi} + {not available when compiled without the + |+find_in_path| or |+eval| features} + Expression to be used to transform the string found with the 'include' + option to a file name. Mostly useful to change "." to "/" for Java: > + :set includeexpr=substitute(v:fname,'\\.','/','g') +< The "v:fname" variable will be set to the file name that was detected. + + Also used for the |gf| command if an unmodified file name can't be + found. Allows doing "gf" on the name after an 'include' statement. + Also used for ||. + + The expression may be evaluated in the |sandbox|, see + |sandbox-option|. + + It is not allowed to change text or jump to another window while + evaluating 'includeexpr' |textlock|. + + *'incsearch'* *'is'* *'noincsearch'* *'nois'* +'incsearch' 'is' boolean (default off) + global + {not in Vi} + {not available when compiled without the + |+extra_search| features} + While typing a search command, show where the pattern, as it was typed + so far, matches. The matched string is highlighted. If the pattern + is invalid or not found, nothing is shown. The screen will be updated + often, this is only useful on fast terminals. + Note that the match will be shown, but the cursor will return to its + 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 + to the command line. If 'ignorecase' and 'smartcase' are set and the + command line has no uppercase characters, the added character is + converted to lowercase. + CTRL-R CTRL-W can be used to add the word at the end of the current + match, excluding the characters that were already typed. + NOTE: This option is reset when 'compatible' is set. + + *'indentexpr'* *'inde'* +'indentexpr' 'inde' string (default "") + local to buffer + {not in Vi} + {not available when compiled without the |+cindent| + or |+eval| features} + Expression which is evaluated to obtain the proper indent for a line. + It is used when a new line is created, for the |=| operator and + in Insert mode as specified with the 'indentkeys' option. + When this option is not empty, it overrules the 'cindent' and + 'smartindent' indenting. + When 'paste' is set this option is not used for indenting. + The expression is evaluated with |v:lnum| set to the line number for + which the indent is to be computed. The cursor is also in this line + when the expression is evaluated (but it may be moved around). + The expression must return the number of spaces worth of indent. It + can return "-1" to keep the current indent (this means 'autoindent' is + used for the indent). + Functions useful for computing the indent are |indent()|, |cindent()| + and |lispindent()|. + The evaluation of the expression must not have side effects! It must + not change the text, jump to another window, etc. Afterwards the + cursor position is always restored, thus the cursor may be moved. + Normally this option would be set to call a function: > + :set indentexpr=GetMyIndent() +< Error messages will be suppressed, unless the 'debug' option contains + "msg". + See |indent-expression|. + NOTE: This option is made empty when 'compatible' is set. + + The expression may be evaluated in the |sandbox|, see + |sandbox-option|. + + It is not allowed to change text or jump to another window while + evaluating 'indentexpr' |textlock|. + + + *'indentkeys'* *'indk'* +'indentkeys' 'indk' string (default "0{,0},:,0#,!^F,o,O,e") + local to buffer + {not in Vi} + {not available when compiled without the |+cindent| + feature} + A list of keys that, when typed in Insert mode, cause reindenting of + the current line. Only happens if 'indentexpr' isn't empty. + The format is identical to 'cinkeys', see |indentkeys-format|. + See |C-indenting| and |indent-expression|. + + *'infercase'* *'inf'* *'noinfercase'* *'noinf'* +'infercase' 'inf' boolean (default off) + local to buffer + {not in Vi} + When doing keyword completion in insert mode |ins-completion|, and + 'ignorecase' is also on, the case of the match is adjusted depending + on the typed text. If the typed text contains a lowercase letter + where the match has an upper case letter, the completed part is made + lowercase. If the typed text has no lowercase letters and the match + has a lowercase letter where the typed text has an uppercase letter, + and there is a letter before it, the completed part is made uppercase. + With 'noinfercase' the match is used as-is. + + *'insertmode'* *'im'* *'noinsertmode'* *'noim'* +'insertmode' 'im' boolean (default off) + global + {not in Vi} + Makes Vim work in a way that Insert mode is the default mode. Useful + if you want to use Vim as a modeless editor. Used for |evim|. + These Insert mode commands will be useful: + - Use the cursor keys to move around. + - Use CTRL-O to execute one Normal mode command |i_CTRL-O|). When + this is a mapping, it is executed as if 'insertmode' was off. + Normal mode remains active until the mapping is finished. + - Use CTRL-L to execute a number of Normal mode commands, then use + to get back to Insert mode. Note that CTRL-L moves the cursor + left, like does when 'insertmode' isn't set. |i_CTRL-L| + + These items change when 'insertmode' is set: + - when starting to edit of a file, Vim goes to Insert mode. + - in Insert mode is a no-op and beeps. + - in Normal mode makes Vim go to Insert mode. + - CTRL-L in Insert mode is a command, it is not inserted. + - CTRL-Z in Insert mode suspends Vim, see |CTRL-Z|. *i_CTRL-Z* + However, when is used inside a mapping, it behaves like + 'insertmode' was not set. This was done to be able to use the same + mappings with 'insertmode' set or not set. + When executing commands with |:normal| 'insertmode' is not used. + + NOTE: This option is reset when 'compatible' is set. + + *'isfname'* *'isf'* +'isfname' 'isf' string (default for MS-DOS, Win32 and OS/2: + "@,48-57,/,\,.,-,_,+,,,#,$,%,{,},[,],:,@-@,!,~,=" + for AMIGA: "@,48-57,/,.,-,_,+,,,$,:" + for VMS: "@,48-57,/,.,-,_,+,,,#,$,%,<,>,[,],:,;,~" + for OS/390: "@,240-249,/,.,-,_,+,,,#,$,%,~,=" + otherwise: "@,48-57,/,.,-,_,+,,,#,$,%,~,=") + global + {not in Vi} + The characters specified by this option are included in file names and + path names. Filenames are used for commands like "gf", "[i" and in + the tags file. It is also used for "\f" in a |pattern|. + Multi-byte characters 256 and above are always included, only the + characters up to 255 are specified with this option. + For UTF-8 the characters 0xa0 to 0xff are included as well. + Think twice before adding white space to this option. Although a + space may appear inside a file name, the effect will be that Vim + doesn't know where a file name starts or ends when doing completion. + It most likely works better without a space in 'isfname'. + + Note that on systems using a backslash as path separator, Vim tries to + do its best to make it work as you would expect. That is a bit + tricky, since Vi originally used the backslash to escape special + characters. Vim will not remove a backslash in front of a normal file + name character on these systems, but it will on Unix and alikes. The + '&' and '^' are not included by default, because these are special for + cmd.exe. + + The format of this option is a list of parts, separated with commas. + Each part can be a single character number or a range. A range is two + character numbers with '-' in between. A character number can be a + decimal number between 0 and 255 or the ASCII character itself (does + not work for digits). Example: + "_,-,128-140,#-43" (include '_' and '-' and the range + 128 to 140 and '#' to 43) + If a part starts with '^', the following character number or range + will be excluded from the option. The option is interpreted from left + to right. Put the excluded character after the range where it is + included. To include '^' itself use it as the last character of the + option or the end of a range. Example: + "^a-z,#,^" (exclude 'a' to 'z', include '#' and '^') + If the character is '@', all characters where isalpha() returns TRUE + are included. Normally these are the characters a to z and A to Z, + plus accented characters. To include '@' itself use "@-@". Examples: + "@,^a-z" All alphabetic characters, excluding lower + case ASCII letters. + "a-z,A-Z,@-@" All letters plus the '@' character. + A comma can be included by using it where a character number is + expected. Example: + "48-57,,,_" Digits, comma and underscore. + A comma can be excluded by prepending a '^'. Example: + " -~,^,,9" All characters from space to '~', excluding + comma, plus . + See |option-backslash| about including spaces and backslashes. + + *'isident'* *'isi'* +'isident' 'isi' string (default for MS-DOS, Win32 and OS/2: + "@,48-57,_,128-167,224-235" + otherwise: "@,48-57,_,192-255") + global + {not in Vi} + The characters given by this option are included in identifiers. + Identifiers are used in recognizing environment variables and after a + match of the 'define' option. It is also used for "\i" in a + |pattern|. See 'isfname' for a description of the format of this + option. + Careful: If you change this option, it might break expanding + environment variables. E.g., when '/' is included and Vim tries to + expand "$HOME/.viminfo". Maybe you should change 'iskeyword' instead. + + *'iskeyword'* *'isk'* +'iskeyword' 'isk' string (Vim default for MS-DOS and Win32: + "@,48-57,_,128-167,224-235" + otherwise: "@,48-57,_,192-255" + Vi default: "@,48-57,_") + local to buffer + {not in Vi} + Keywords are used in searching and recognizing with many commands: + "w", "*", "[i", etc. It is also used for "\k" in a |pattern|. See + 'isfname' for a description of the format of this option. For C + programs you could use "a-z,A-Z,48-57,_,.,-,>". + For a help file it is set to all non-blank printable characters except + '*', '"' and '|' (so that CTRL-] on a command finds the help for that + command). + When the 'lisp' option is on the '-' character is always included. + NOTE: This option is set to the Vi default value when 'compatible' is + set and to the Vim default value when 'compatible' is reset. + + *'isprint'* *'isp'* +'isprint' 'isp' string (default for MS-DOS, Win32, OS/2 and Macintosh: + "@,~-255"; otherwise: "@,161-255") + global + {not in Vi} + The characters given by this option are displayed directly on the + screen. It is also used for "\p" in a |pattern|. The characters from + space (ASCII 32) to '~' (ASCII 126) are always displayed directly, + even when they are not included in 'isprint' or excluded. See + 'isfname' for a description of the format of this option. + + Non-printable characters are displayed with two characters: + 0 - 31 "^@" - "^_" + 32 - 126 always single characters + 127 "^?" + 128 - 159 "~@" - "~_" + 160 - 254 "| " - "|~" + 255 "~?" + When 'encoding' is a Unicode one, illegal bytes from 128 to 255 are + displayed as , with the hexadecimal value of the byte. + When 'display' contains "uhex" all unprintable characters are + displayed as . + The SpecialKey highlighting will be used for unprintable characters. + |hl-SpecialKey| + + Multi-byte characters 256 and above are always included, only the + characters up to 255 are specified with this option. When a character + is printable but it is not available in the current font, a + replacement character will be shown. + Unprintable and zero-width Unicode characters are displayed as . + There is no option to specify these characters. + + *'joinspaces'* *'js'* *'nojoinspaces'* *'nojs'* +'joinspaces' 'js' boolean (default on) + global + {not in Vi} + Insert two spaces after a '.', '?' and '!' with a join command. + When 'cpoptions' includes the 'j' flag, only do this after a '.'. + Otherwise only one space is inserted. + NOTE: This option is set when 'compatible' is set. + + *'key'* +'key' string (default "") + local to buffer + {not in Vi} + {only available when compiled with the |+cryptv| + feature} + The key that is used for encrypting and decrypting the current buffer. + See |encryption| and 'cryptmethod'. + Careful: Do not set the key value by hand, someone might see the typed + key. Use the |:X| command. But you can make 'key' empty: > + :set key= +< It is not possible to get the value of this option with ":set key" or + "echo &key". This is to avoid showing it to someone who shouldn't + know. It also means you cannot see it yourself once you have set it, + be careful not to make a typing error! + + *'keymap'* *'kmp'* *E544* +'keymap' 'kmp' string (default "") + local to buffer + {not in Vi} + {only available when compiled with the |+keymap| + feature} + Name of a keyboard mapping. See |mbyte-keymap|. + Setting this option to a valid keymap name has the side effect of + setting 'iminsert' to one, so that the keymap becomes effective. + 'imsearch' is also set to one, unless it was -1 + Only normal file name characters can be used, "/\*?[|<>" are illegal. + + *'keymodel'* *'km'* +'keymodel' 'km' string (default "") + global + {not in Vi} + List of comma separated words, which enable special things that keys + can do. These values can be used: + startsel Using a shifted special key starts selection (either + Select mode or Visual mode, depending on "key" being + present in 'selectmode'). + stopsel Using a not-shifted special key stops selection. + Special keys in this context are the cursor keys, , , + and . + The 'keymodel' option is set by the |:behave| command. + + *'keywordprg'* *'kp'* +'keywordprg' 'kp' string (default "man" or "man -s", DOS: ":help", + OS/2: "view /", VMS: "help") + global or local to buffer |global-local| + {not in Vi} + Program to use for the |K| command. Environment variables are + expanded |:set_env|. ":help" may be used to access the Vim internal + help. (Note that previously setting the global option to the empty + value did this, which is now deprecated.) + When "man" is used, Vim will automatically translate a count for the + "K" command to a section number. Also for "man -s", in which case the + "-s" is removed when there is no count. + See |option-backslash| about including spaces and backslashes. + Example: > + :set keywordprg=man\ -s +< This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + *'langmap'* *'lmap'* *E357* *E358* +'langmap' 'lmap' string (default "") + global + {not in Vi} + {only available when compiled with the |+langmap| + feature} + This option allows switching your keyboard into a special language + mode. When you are typing text in Insert mode the characters are + inserted directly. When in command mode the 'langmap' option takes + care of translating these special characters to the original meaning + of the key. This means you don't have to change the keyboard mode to + be able to execute Normal mode commands. + This is the opposite of the 'keymap' option, where characters are + mapped in Insert mode. + + Example (for Greek, in UTF-8): *greek* > + :set langmap=ΑA,Î’B,ΨC,ΔD,ΕE,ΦF,ΓG,ΗH,ΙI,ΞJ,ΚK,ΛL,ÎœM,ÎN,ΟO,ΠP,QQ,ΡR,ΣS,ΤT,ΘU,ΩV,WW,ΧX,Î¥Y,ΖZ,αa,βb,ψc,δd,εe,φf,γg,ηh,ιi,ξj,κk,λl,μm,νn,οo,Ï€p,qq,Ïr,σs,Ï„t,θu,ωv,Ï‚w,χx,Ï…y,ζz +< Example (exchanges meaning of z and y for commands): > + :set langmap=zy,yz,ZY,YZ +< + The 'langmap' option is a list of parts, separated with commas. Each + part can be in one of two forms: + 1. A list of pairs. Each pair is a "from" character immediately + followed by the "to" character. Examples: "aA", "aAbBcC". + 2. A list of "from" characters, a semi-colon and a list of "to" + characters. Example: "abc;ABC" + Example: "aA,fgh;FGH,cCdDeE" + Special characters need to be preceded with a backslash. These are + ";", ',' and backslash itself. + + This will allow you to activate vim actions without having to switch + back and forth between the languages. Your language characters will + be understood as normal vim English characters (according to the + langmap mappings) in the following cases: + o Normal/Visual mode (commands, buffer/register names, user mappings) + o Insert/Replace Mode: Register names after CTRL-R + o Insert/Replace Mode: Mappings + Characters entered in Command-line mode will NOT be affected by + this option. Note that this option can be changed at any time + allowing to switch between mappings for different languages/encodings. + Use a mapping to avoid having to type it each time! + + *'langmenu'* *'lm'* +'langmenu' 'lm' string (default "") + global + {not in Vi} + {only available when compiled with the |+menu| and + |+multi_lang| features} + Language to use for menu translation. Tells which file is loaded + from the "lang" directory in 'runtimepath': > + "lang/menu_" . &langmenu . ".vim" +< (without the spaces). For example, to always use the Dutch menus, no + matter what $LANG is set to: > + :set langmenu=nl_NL.ISO_8859-1 +< When 'langmenu' is empty, |v:lang| is used. + Only normal file name characters can be used, "/\*?[|<>" are illegal. + If your $LANG is set to a non-English language but you do want to use + the English menus: > + :set langmenu=none +< This option must be set before loading menus, switching on filetype + detection or syntax highlighting. Once the menus are defined setting + this option has no effect. But you could do this: > + :source $VIMRUNTIME/delmenu.vim + :set langmenu=de_DE.ISO_8859-1 + :source $VIMRUNTIME/menu.vim +< Warning: This deletes all menus that you defined yourself! + + *'laststatus'* *'ls'* +'laststatus' 'ls' number (default 1) + global + {not in Vi} + The value of this option influences when the last window will have a + status line: + 0: never + 1: only if there are at least two windows + 2: always + The screen looks nicer with a status line if you have several + windows, but it takes another screen line. |status-line| + + *'lazyredraw'* *'lz'* *'nolazyredraw'* *'nolz'* +'lazyredraw' 'lz' boolean (default off) + global + {not in Vi} + When this option is set, the screen will not be redrawn while + executing macros, registers and other commands that have not been + typed. Also, updating the window title is postponed. To force an + update use |:redraw|. + + *'linebreak'* *'lbr'* *'nolinebreak'* *'nolbr'* +'linebreak' 'lbr' boolean (default off) + local to window + {not in Vi} + {not available when compiled without the |+linebreak| + feature} + If on Vim will wrap long lines at a character in 'breakat' rather + than at the last character that fits on the screen. Unlike + 'wrapmargin' and 'textwidth', this does not insert s in the file, + it only affects the way the file is displayed, not its contents. The + value of 'showbreak' is used to put in front of wrapped lines. + This option is not used when the 'wrap' option is off or 'list' is on. + Note that characters after an are mostly not displayed + with the right amount of white space. + + *'lines'* *E593* +'lines' number (default 24 or terminal height) + global + Number of lines of the Vim window. + Normally you don't need to set this. It is done automatically by the + terminal initialization code. Also see |posix-screen-size|. + When Vim is running in the GUI or in a resizable window, setting this + option will cause the window size to be changed. When you only want + to use the size for the GUI, put the command in your |gvimrc| file. + Vim limits the number of lines to what fits on the screen. You can + use this command to get the tallest window possible: > + :set lines=999 +< Minimum value is 2, maximum value is 1000. + If you get less lines than expected, check the 'guiheadroom' option. + When you set this option and Vim is unable to change the physical + number of lines of the display, the display may be messed up. + + *'linespace'* *'lsp'* +'linespace' 'lsp' number (default 0, 1 for Win32 GUI) + global + {not in Vi} + {only in the GUI} + Number of pixel lines inserted between characters. Useful if the font + uses the full character cell height, making lines touch each other. + When non-zero there is room for underlining. + With some fonts there can be too much room between lines (to have + space for ascents and descents). Then it makes sense to set + 'linespace' to a negative value. This may cause display problems + though! + + *'lisp'* *'nolisp'* +'lisp' boolean (default off) + local to buffer + {not available when compiled without the |+lispindent| + feature} + Lisp mode: When is typed in insert mode set the indent for + the next line to Lisp standards (well, sort of). Also happens with + "cc" or "S". 'autoindent' must also be on for this to work. The 'p' + flag in 'cpoptions' changes the method of indenting: Vi compatible or + better. Also see 'lispwords'. + The '-' character is included in keyword characters. Redefines the + "=" operator to use this same indentation algorithm rather than + calling an external program if 'equalprg' is empty. + This option is not used when 'paste' is set. + {Vi: Does it a little bit differently} + + *'lispwords'* *'lw'* +'lispwords' 'lw' string (default is very long) + global + {not in Vi} + {not available when compiled without the |+lispindent| + feature} + Comma separated list of words that influence the Lisp indenting. + |'lisp'| + + *'list'* *'nolist'* +'list' boolean (default off) + local to window + List mode: Show tabs as CTRL-I is displayed, display $ after end of + line. Useful to see the difference between tabs and spaces and for + trailing blanks. Further changed by the 'listchars' option. + + The cursor is displayed at the start of the space a Tab character + occupies, not at the end as usual in Normal mode. To get this cursor + position while displaying Tabs with spaces, use: > + :set list lcs=tab\ \ +< + Note that list mode will also affect formatting (set with 'textwidth' + or 'wrapmargin') when 'cpoptions' includes 'L'. See 'listchars' for + changing the way tabs are displayed. + + *'listchars'* *'lcs'* +'listchars' 'lcs' string (default "eol:$") + global + {not in Vi} + Strings to use in 'list' mode and for the |:list| command. It is a + comma separated list of string settings. + eol:c Character to show at the end of each line. When + omitted, there is no extra character at the end of the + line. + tab:xy Two characters to be used to show a tab. The first + char is used once. The second char is repeated to + fill the space that the tab normally occupies. + "tab:>-" will show a tab that takes four spaces as + ">---". When omitted, a tab is show as ^I. + trail:c Character to show for trailing spaces. When omitted, + trailing spaces are blank. + extends:c Character to show in the last column, when 'wrap' is + off and the line continues beyond the right of the + screen. + precedes:c Character to show in the first column, when 'wrap' + is off and there is text preceding the character + visible in the first column. + conceal:c Character to show in place of concealed text, when + 'conceallevel' is set to 1. + nbsp:c Character to show for a non-breakable space (character + 0xA0, 160). Left blank when omitted. + + The characters ':' and ',' should not be used. UTF-8 characters can + be used when 'encoding' is "utf-8", otherwise only printable + characters are allowed. All characters must be single width. + + Examples: > + :set lcs=tab:>-,trail:- + :set lcs=tab:>-,eol:<,nbsp:% + :set lcs=extends:>,precedes:< +< The "NonText" highlighting will be used for "eol", "extends" and + "precedes". "SpecialKey" for "nbsp", "tab" and "trail". + |hl-NonText| |hl-SpecialKey| + + *'lpl'* *'nolpl'* *'loadplugins'* *'noloadplugins'* +'loadplugins' 'lpl' boolean (default on) + global + {not in Vi} + When on the plugin scripts are loaded when starting up |load-plugins|. + This option can be reset in your |vimrc| file to disable the loading + of plugins. + Note that using the "-u NONE" and "--noplugin" command line arguments + reset this option. |-u| |--noplugin| + + *'macatsui'* *'nomacatsui'* +'macatsui' boolean (default on) + global + {only available in Mac GUI version} + This is a workaround for when drawing doesn't work properly. When set + and compiled with multi-byte support ATSUI text drawing is used. When + not set ATSUI text drawing is not used. Switch this option off when + you experience drawing problems. In a future version the problems may + be solved and this option becomes obsolete. Therefore use this method + to unset it: > + if exists('&macatsui') + set nomacatsui + endif +< Another option to check if you have drawing problems is + 'termencoding'. + + *'magic'* *'nomagic'* +'magic' boolean (default on) + global + Changes the special characters that can be used in search patterns. + See |pattern|. + NOTE: To avoid portability problems with using patterns, always keep + this option at the default "on". Only switch it off when working with + old Vi scripts. In any other situation write patterns that work when + 'magic' is on. Include "\M" when you want to |/\M|. + + *'makeef'* *'mef'* +'makeef' 'mef' string (default: "") + global + {not in Vi} + {not available when compiled without the |+quickfix| + feature} + Name of the errorfile for the |:make| command (see |:make_makeprg|) + and the |:grep| command. + When it is empty, an internally generated temp file will be used. + When "##" is included, it is replaced by a number to make the name + unique. This makes sure that the ":make" command doesn't overwrite an + existing file. + NOT used for the ":cf" command. See 'errorfile' for that. + Environment variables are expanded |:set_env|. + See |option-backslash| about including spaces and backslashes. + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + *'makeprg'* *'mp'* +'makeprg' 'mp' string (default "make", VMS: "MMS") + global or local to buffer |global-local| + {not in Vi} + Program to use for the ":make" command. See |:make_makeprg|. + This option may contain '%' and '#' characters, which are expanded to + the current and alternate file name. |:_%| |:_#| + Environment variables are expanded |:set_env|. See |option-backslash| + about including spaces and backslashes. + Note that a '|' must be escaped twice: once for ":set" and once for + the interpretation of a command. When you use a filter called + "myfilter" do it like this: > + :set makeprg=gmake\ \\\|\ myfilter +< The placeholder "$*" can be given (even multiple times) to specify + where the arguments will be included, for example: > + :set makeprg=latex\ \\\\nonstopmode\ \\\\input\\{$*} +< This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + *'colorcolumn'* *'cc'* +'colorcolumn' 'cc' string (default "") + local to window + {not in Vi} + {not available when compiled without the |+syntax| + feature} + 'colorcolumn' is a comma separated list of screen columns that are + highlighted with ColorColumn |hl-ColorColumn|. Useful to align + text. Will make screen redrawing slower. + The screen column can be an absolute number, or a number preceded with + '+' or '-', which is added to or subtracted from 'textwidth'. > + + :set cc=+1 " highlight column after 'textwidth' + :set cc=+1,+2,+3 " highlight three columns after 'textwidth' + :hi ColorColumn ctermbg=lightgrey guibg=lightgrey +< + When 'textwidth' is zero then the items with '-' and '+' are not used. + A maximum of 256 columns are highlighted. + + *'matchpairs'* *'mps'* +'matchpairs' 'mps' string (default "(:),{:},[:]") + local to buffer + {not in Vi} + Characters that form pairs. The |%| command jumps from one to the + other. Currently only single byte character pairs are allowed, and + they must be different. The characters must be separated by a colon. + The pairs must be separated by a comma. Example for including '<' and + '>' (HTML): > + :set mps+=<:> + +< A more exotic example, to jump between the '=' and ';' in an + assignment, useful for languages like C and Java: > + :au FileType c,cpp,java set mps+==:; + +< For a more advanced way of using "%", see the matchit.vim plugin in + the $VIMRUNTIME/macros directory. |add-local-help| + + *'matchtime'* *'mat'* +'matchtime' 'mat' number (default 5) + global + {not in Vi}{in Nvi} + Tenths of a second to show the matching paren, when 'showmatch' is + set. Note that this is not in milliseconds, like other options that + set a time. This is to be compatible with Nvi. + + *'maxcombine'* *'mco'* +'maxcombine' 'mco' number (default 2) + global + {not in Vi} + {only available when compiled with the |+multi_byte| + feature} + The maximum number of combining characters supported for displaying. + Only used when 'encoding' is "utf-8". + The default is OK for most languages. Hebrew may require 4. + Maximum value is 6. + Even when this option is set to 2 you can still edit text with more + combining characters, you just can't see them. Use |g8| or |ga|. + See |mbyte-combining|. + + *'maxfuncdepth'* *'mfd'* +'maxfuncdepth' 'mfd' number (default 100) + global + {not in Vi} + {not available when compiled without the |+eval| + feature} + Maximum depth of function calls for user functions. This normally + catches endless recursion. When using a recursive function with + more depth, set 'maxfuncdepth' to a bigger number. But this will use + more memory, there is the danger of failing when memory is exhausted. + See also |:function|. + + *'maxmapdepth'* *'mmd'* *E223* +'maxmapdepth' 'mmd' number (default 1000) + global + {not in Vi} + Maximum number of times a mapping is done without resulting in a + character to be used. This normally catches endless mappings, like + ":map x y" with ":map y x". It still does not catch ":map g wg", + because the 'w' is used before the next mapping is done. See also + |key-mapping|. + + *'maxmem'* *'mm'* +'maxmem' 'mm' number (default between 256 to 5120 (system + dependent) or half the amount of memory + available) + global + {not in Vi} + Maximum amount of memory (in Kbyte) to use for one buffer. When this + limit is reached allocating extra memory for a buffer will cause + other memory to be freed. The maximum usable value is about 2000000. + Use this to work without a limit. Also see 'maxmemtot'. + + *'maxmempattern'* *'mmp'* +'maxmempattern' 'mmp' number (default 1000) + global + {not in Vi} + Maximum amount of memory (in Kbyte) to use for pattern matching. + The maximum value is about 2000000. Use this to work without a limit. + *E363* + When Vim runs into the limit it gives an error message and mostly + behaves like CTRL-C was typed. + Running into the limit often means that the pattern is very + inefficient or too complex. This may already happen with the pattern + "\(.\)*" on a very long line. ".*" works much better. + Vim may run out of memory before hitting the 'maxmempattern' limit. + + *'maxmemtot'* *'mmt'* +'maxmemtot' 'mmt' number (default between 2048 and 10240 (system + dependent) or half the amount of memory + available) + global + {not in Vi} + Maximum amount of memory in Kbyte to use for all buffers together. + The maximum usable value is about 2000000 (2 Gbyte). Use this to work + without a limit. On 64 bit machines higher values might work. But + hey, do you really need more than 2 Gbyte for text editing? + Also see 'maxmem'. + + *'menuitems'* *'mis'* +'menuitems' 'mis' number (default 25) + global + {not in Vi} + {not available when compiled without the |+menu| + feature} + Maximum number of items to use in a menu. Used for menus that are + generated from a list of items, e.g., the Buffers menu. Changing this + option has no direct effect, the menu must be refreshed first. + + *'mkspellmem'* *'msm'* +'mkspellmem' 'msm' string (default "460000,2000,500") + global + {not in Vi} + {not available when compiled without the |+syntax| + feature} + Parameters for |:mkspell|. This tunes when to start compressing the + word tree. Compression can be slow when there are many words, but + it's needed to avoid running out of memory. The amount of memory used + per word depends very much on how similar the words are, that's why + this tuning is complicated. + + There are three numbers, separated by commas: + {start},{inc},{added} + + For most languages the uncompressed word tree fits in memory. {start} + gives the amount of memory in Kbyte that can be used before any + compression is done. It should be a bit smaller than the amount of + memory that is available to Vim. + + When going over the {start} limit the {inc} number specifies the + amount of memory in Kbyte that can be allocated before another + compression is done. A low number means compression is done after + less words are added, which is slow. A high number means more memory + will be allocated. + + After doing compression, {added} times 1024 words can be added before + the {inc} limit is ignored and compression is done when any extra + amount of memory is needed. A low number means there is a smaller + chance of hitting the {inc} limit, less memory is used but it's + slower. + + The languages for which these numbers are important are Italian and + Hungarian. The default works for when you have about 512 Mbyte. If + you have 1 Gbyte you could use: > + :set mkspellmem=900000,3000,800 +< If you have less than 512 Mbyte |:mkspell| may fail for some + languages, no matter what you set 'mkspellmem' to. + + *'modeline'* *'ml'* *'nomodeline'* *'noml'* +'modeline' 'ml' boolean (Vim default: on (off for root), + Vi default: off) + local to buffer + *'modelines'* *'mls'* +'modelines' 'mls' number (default 5) + global + {not in Vi} + If 'modeline' is on 'modelines' gives the number of lines that is + checked for set commands. If 'modeline' is off or 'modelines' is zero + no lines are checked. See |modeline|. + NOTE: 'modeline' is set to the Vi default value when 'compatible' is + set and to the Vim default value when 'compatible' is reset. + + *'modifiable'* *'ma'* *'nomodifiable'* *'noma'* +'modifiable' 'ma' boolean (default on) + local to buffer + {not in Vi} *E21* + When off the buffer contents cannot be changed. The 'fileformat' and + 'fileencoding' options also can't be changed. + Can be reset with the |-M| command line argument. + + *'modified'* *'mod'* *'nomodified'* *'nomod'* +'modified' 'mod' boolean (default off) + local to buffer + {not in Vi} + When on, the buffer is considered to be modified. This option is set + when: + 1. A change was made to the text since it was last written. Using the + |undo| command to go back to the original text will reset the + option. But undoing changes that were made before writing the + buffer will set the option again, since the text is different from + when it was written. + 2. 'fileformat' or 'fileencoding' is different from its original + value. The original value is set when the buffer is read or + written. A ":set nomodified" command also resets the original + values to the current values and the 'modified' option will be + reset. + When 'buftype' is "nowrite" or "nofile" this option may be set, but + will be ignored. + + *'more'* *'nomore'* +'more' boolean (Vim default: on, Vi default: off) + global + {not in Vi} + When on, listings pause when the whole screen is filled. You will get + the |more-prompt|. When this option is off there are no pauses, the + listing continues until finished. + NOTE: This option is set to the Vi default value when 'compatible' is + set and to the Vim default value when 'compatible' is reset. + + *'mouse'* *E538* +'mouse' string (default "", "a" for GUI, MS-DOS and Win32) + global + {not in Vi} + Enable the use of the mouse. Only works for certain terminals + (xterm, MS-DOS, Win32 |win32-mouse|, QNX pterm, *BSD console with + sysmouse and Linux console with gpm). For using the mouse in the + GUI, see |gui-mouse|. + The mouse can be enabled for different modes: + n Normal mode + v Visual mode + i Insert mode + c Command-line mode + h all previous modes when editing a help file + a all previous modes + r for |hit-enter| and |more-prompt| prompt + Normally you would enable the mouse in all four modes with: > + :set mouse=a +< When the mouse is not enabled, the GUI will still use the mouse for + modeless selection. This doesn't move the text cursor. + + See |mouse-using|. Also see |'clipboard'|. + + Note: When enabling the mouse in a terminal, copy/paste will use the + "* register if there is access to an X-server. The xterm handling of + the mouse buttons can still be used by keeping the shift key pressed. + Also see the 'clipboard' option. + + *'mousefocus'* *'mousef'* *'nomousefocus'* *'nomousef'* +'mousefocus' 'mousef' boolean (default off) + global + {not in Vi} + {only works in the GUI} + The window that the mouse pointer is on is automatically activated. + When changing the window layout or window focus in another way, the + mouse pointer is moved to the window with keyboard focus. Off is the + default because it makes using the pull down menus a little goofy, as + a pointer transit may activate a window unintentionally. + + *'mousehide'* *'mh'* *'nomousehide'* *'nomh'* +'mousehide' 'mh' boolean (default on) + global + {not in Vi} + {only works in the GUI} + When on, the mouse pointer is hidden when characters are typed. + The mouse pointer is restored when the mouse is moved. + + *'mousemodel'* *'mousem'* +'mousemodel' 'mousem' string (default "extend", "popup" for MS-DOS and Win32) + global + {not in Vi} + Sets the model to use for the mouse. The name mostly specifies what + the right mouse button is used for: + extend Right mouse button extends a selection. This works + like in an xterm. + popup Right mouse button pops up a menu. The shifted left + mouse button extends a selection. This works like + with Microsoft Windows. + popup_setpos Like "popup", but the cursor will be moved to the + position where the mouse was clicked, and thus the + selected operation will act upon the clicked object. + If clicking inside a selection, that selection will + be acted upon, i.e. no cursor move. This implies of + course, that right clicking outside a selection will + end Visual mode. + Overview of what button does what for each model: + mouse extend popup(_setpos) ~ + left click place cursor place cursor + left drag start selection start selection + shift-left search word extend selection + right click extend selection popup menu (place cursor) + right drag extend selection - + middle click paste paste + + In the "popup" model the right mouse button produces a pop-up menu. + You need to define this first, see |popup-menu|. + + Note that you can further refine the meaning of buttons with mappings. + See |gui-mouse-mapping|. But mappings are NOT used for modeless + selection (because that's handled in the GUI code directly). + + The 'mousemodel' option is set by the |:behave| command. + + *'mouseshape'* *'mouses'* *E547* +'mouseshape' 'mouses' string (default "i:beam,r:beam,s:updown,sd:cross, + m:no,ml:up-arrow,v:rightup-arrow") + global + {not in Vi} + {only available when compiled with the |+mouseshape| + feature} + This option tells Vim what the mouse pointer should look like in + different modes. The option is a comma separated list of parts, much + like used for 'guicursor'. Each part consist of a mode/location-list + and an argument-list: + mode-list:shape,mode-list:shape,.. + The mode-list is a dash separated list of these modes/locations: + In a normal window: ~ + n Normal mode + v Visual mode + ve Visual mode with 'selection' "exclusive" (same as 'v', + if not specified) + o Operator-pending mode + i Insert mode + r Replace mode + + Others: ~ + c appending to the command-line + ci inserting in the command-line + cr replacing in the command-line + m at the 'Hit ENTER' or 'More' prompts + ml idem, but cursor in the last line + e any mode, pointer below last window + s any mode, pointer on a status line + sd any mode, while dragging a status line + vs any mode, pointer on a vertical separator line + vd any mode, while dragging a vertical separator line + a everywhere + + The shape is one of the following: + avail name looks like ~ + w x arrow Normal mouse pointer + w x blank no pointer at all (use with care!) + w x beam I-beam + w x updown up-down sizing arrows + w x leftright left-right sizing arrows + w x busy The system's usual busy pointer + w x no The system's usual 'no input' pointer + x udsizing indicates up-down resizing + x lrsizing indicates left-right resizing + x crosshair like a big thin + + x hand1 black hand + x hand2 white hand + x pencil what you write with + x question big ? + x rightup-arrow arrow pointing right-up + w x up-arrow arrow pointing up + x any X11 pointer number (see X11/cursorfont.h) + + The "avail" column contains a 'w' if the shape is available for Win32, + x for X11. + Any modes not specified or shapes not available use the normal mouse + pointer. + + Example: > + :set mouseshape=s:udsizing,m:no +< will make the mouse turn to a sizing arrow over the status lines and + indicate no input when the hit-enter prompt is displayed (since + clicking the mouse has no effect in this state.) + + *'mousetime'* *'mouset'* +'mousetime' 'mouset' number (default 500) + global + {not in Vi} + Only for GUI, MS-DOS, Win32 and Unix with xterm. Defines the maximum + time in msec between two mouse clicks for the second click to be + recognized as a multi click. + + *'mzquantum'* *'mzq'* +'mzquantum' 'mzq' number (default 100) + global + {not in Vi} + {not available when compiled without the |+mzscheme| + feature} + The number of milliseconds between polls for MzScheme threads. + Negative or zero value means no thread scheduling. + + *'nrformats'* *'nf'* +'nrformats' 'nf' string (default "octal,hex") + local to buffer + {not in Vi} + This defines what bases Vim will consider for numbers when using the + CTRL-A and CTRL-X commands for adding to and subtracting from a number + respectively; see |CTRL-A| for more info on these commands. + alpha If included, single alphabetical characters will be + incremented or decremented. This is useful for a list with a + letter index a), b), etc. *octal-number* + octal If included, numbers that start with a zero will be considered + to be octal. Example: Using CTRL-A on "007" results in "010". + hex If included, numbers starting with "0x" or "0X" will be + considered to be hexadecimal. Example: Using CTRL-X on + "0x100" results in "0x0ff". + Numbers which simply begin with a digit in the range 1-9 are always + considered decimal. This also happens for numbers that are not + recognized as octal or hex. + + *'number'* *'nu'* *'nonumber'* *'nonu'* +'number' 'nu' boolean (default off) + local to window + Print the line number in front of each line. When the 'n' option is + excluded from 'cpoptions' a wrapped line will not use the column of + line numbers (this is the default when 'compatible' isn't set). + The 'numberwidth' option can be used to set the room used for the line + number. + When a long, wrapped line doesn't start with the first character, '-' + characters are put before the number. + See |hl-LineNr| for the highlighting used for the number. + When setting this option, 'relativenumber' is reset. + + *'numberwidth'* *'nuw'* +'numberwidth' 'nuw' number (Vim default: 4 Vi default: 8) + local to window + {not in Vi} + {only available when compiled with the |+linebreak| + feature} + Minimal number of columns to use for the line number. Only relevant + when the 'number' or 'relativenumber' option is set or printing lines + with a line number. Since one space is always between the number and + the text, there is one less character for the number itself. + The value is the minimum width. A bigger width is used when needed to + fit the highest line number in the buffer respectively the number of + rows in the window, depending on whether 'number' or 'relativenumber' + is set. Thus with the Vim default of 4 there is room for a line number + up to 999. When the buffer has 1000 lines five columns will be used. + The minimum value is 1, the maximum value is 10. + NOTE: 'numberwidth' is reset to 8 when 'compatible' is set. + + *'omnifunc'* *'ofu'* +'omnifunc' 'ofu' string (default: empty) + local to buffer + {not in Vi} + {not available when compiled without the |+eval| + or |+insert_expand| features} + This option specifies a function to be used for Insert mode omni + completion with CTRL-X CTRL-O. |i_CTRL-X_CTRL-O| + See |complete-functions| for an explanation of how the function is + invoked and what it should return. + This option is usually set by a filetype plugin: + |:filetype-plugin-on| + + + *'opendevice'* *'odev'* *'noopendevice'* *'noodev'* +'opendevice' 'odev' boolean (default off) + global + {not in Vi} + {only for MS-DOS, MS-Windows and OS/2} + Enable reading and writing from devices. This may get Vim stuck on a + device that can be opened but doesn't actually do the I/O. Therefore + it is off by default. + Note that on MS-Windows editing "aux.h", "lpt1.txt" and the like also + result in editing a device. + + + *'operatorfunc'* *'opfunc'* +'operatorfunc' 'opfunc' string (default: empty) + global + {not in Vi} + This option specifies a function to be called by the |g@| operator. + See |:map-operator| for more info and an example. + + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + + *'osfiletype'* *'oft'* *E366* +'osfiletype' 'oft' string (RISC-OS default: "Text", + others default: "") + local to buffer + {not in Vi} + {only available when compiled with the |+osfiletype| + feature} + Some operating systems store extra information about files besides + name, datestamp and permissions. This option contains the extra + information, the nature of which will vary between systems. + The value of this option is usually set when the file is loaded, and + is used to set the operating system file type when file is written. + It can affect the pattern matching of the automatic commands. + |autocmd-osfiletypes| + + *'paragraphs'* *'para'* +'paragraphs' 'para' string (default "IPLPPPQPP TPHPLIPpLpItpplpipbp") + global + Specifies the nroff macros that separate paragraphs. These are pairs + of two letters (see |object-motions|). + + *'paste'* *'nopaste'* +'paste' boolean (default off) + global + {not in Vi} + Put Vim in Paste mode. This is useful if you want to cut or copy + some text from one window and paste it in Vim. This will avoid + unexpected effects. + Setting this option is useful when using Vim in a terminal, where Vim + cannot distinguish between typed text and pasted text. In the GUI, Vim + knows about pasting and will mostly do the right thing without 'paste' + being set. The same is true for a terminal where Vim handles the + mouse clicks itself. + This option is reset when starting the GUI. Thus if you set it in + your .vimrc it will work in a terminal, but not in the GUI. Setting + 'paste' in the GUI has side effects: e.g., the Paste toolbar button + will no longer work in Insert mode, because it uses a mapping. + When the 'paste' option is switched on (also when it was already on): + - mapping in Insert mode and Command-line mode is disabled + - abbreviations are disabled + - 'textwidth' is set to 0 + - 'wrapmargin' is set to 0 + - 'autoindent' is reset + - 'smartindent' is reset + - 'softtabstop' is set to 0 + - 'revins' is reset + - 'ruler' is reset + - 'showmatch' is reset + - 'formatoptions' is used like it is empty + These options keep their value, but their effect is disabled: + - 'lisp' + - 'indentexpr' + - 'cindent' + NOTE: When you start editing another file while the 'paste' option is + on, settings from the modelines or autocommands may change the + settings again, causing trouble when pasting text. You might want to + set the 'paste' option again. + When the 'paste' option is reset the mentioned options are restored to + the value before the moment 'paste' was switched from off to on. + Resetting 'paste' before ever setting it does not have any effect. + Since mapping doesn't work while 'paste' is active, you need to use + the 'pastetoggle' option to toggle the 'paste' option with some key. + + *'pastetoggle'* *'pt'* +'pastetoggle' 'pt' string (default "") + global + {not in Vi} + When non-empty, specifies the key sequence that toggles the 'paste' + option. This is like specifying a mapping: > + :map {keys} :set invpaste +< Where {keys} is the value of 'pastetoggle'. + The difference is that it will work even when 'paste' is set. + 'pastetoggle' works in Insert mode and Normal mode, but not in + Command-line mode. + Mappings are checked first, thus overrule 'pastetoggle'. However, + when 'paste' is on mappings are ignored in Insert mode, thus you can do + this: > + :map :set paste + :map :set nopaste + :imap :set paste + :imap + :set pastetoggle= +< This will make start paste mode and stop paste mode. + Note that typing in paste mode inserts "", since in paste + mode everything is inserted literally, except the 'pastetoggle' key + sequence. + When the value has several bytes 'ttimeoutlen' applies. + + *'pex'* *'patchexpr'* +'patchexpr' 'pex' string (default "") + global + {not in Vi} + {not available when compiled without the |+diff| + feature} + Expression which is evaluated to apply a patch to a file and generate + the resulting new version of the file. See |diff-patchexpr|. + + *'patchmode'* *'pm'* *E206* +'patchmode' 'pm' string (default "") + global + {not in Vi} + When non-empty the oldest version of a file is kept. This can be used + to keep the original version of a file if you are changing files in a + source distribution. Only the first time that a file is written a + copy of the original file will be kept. The name of the copy is the + name of the original file with the string in the 'patchmode' option + appended. This option should start with a dot. Use a string like + ".org". 'backupdir' must not be empty for this to work (Detail: The + backup file is renamed to the patchmode file after the new file has + been successfully written, that's why it must be possible to write a + backup file). If there was no file to be backed up, an empty file is + created. + When the 'backupskip' pattern matches, a patchmode file is not made. + Using 'patchmode' for compressed files appends the extension at the + end (e.g., "file.gz.orig"), thus the resulting name isn't always + recognized as a compressed file. + Only normal file name characters can be used, "/\*?[|<>" are illegal. + + *'path'* *'pa'* *E343* *E345* *E347* +'path' 'pa' string (default on Unix: ".,/usr/include,," + on OS/2: ".,/emx/include,," + other systems: ".,,") + global or local to buffer |global-local| + {not in Vi} + This is a list of directories which will be searched when using the + |gf|, [f, ]f, ^Wf, |:find|, |:sfind|, |:tabfind| and other commands, + provided that the file being searched for has a relative path (not + starting with "/", "./" or "../"). The directories in the 'path' + option may be relative or absolute. + - Use commas to separate directory names: > + :set path=.,/usr/local/include,/usr/include +< - Spaces can also be used to separate directory names (for backwards + compatibility with version 3.0). To have a space in a directory + name, precede it with an extra backslash, and escape the space: > + :set path=.,/dir/with\\\ space +< - To include a comma in a directory name precede it with an extra + backslash: > + :set path=.,/dir/with\\,comma +< - To search relative to the directory of the current file, use: > + :set path=. +< - To search in the current directory use an empty string between two + commas: > + :set path=,, +< - A directory name may end in a ':' or '/'. + - Environment variables are expanded |:set_env|. + - When using |netrw.vim| URLs can be used. For example, adding + "http://www.vim.org" will make ":find index.html" work. + - Search upwards and downwards in a directory tree using "*", "**" and + ";". See |file-searching| for info and syntax. + {not available when compiled without the |+path_extra| feature} + - Careful with '\' characters, type two to get one in the option: > + :set path=.,c:\\include +< Or just use '/' instead: > + :set path=.,c:/include +< Don't forget "." or files won't even be found in the same directory as + the file! + The maximum length is limited. How much depends on the system, mostly + it is something like 256 or 1024 characters. + You can check if all the include files are found, using the value of + 'path', see |:checkpath|. + The use of |:set+=| and |:set-=| is preferred when adding or removing + directories from the list. This avoids problems when a future version + uses another default. To remove the current directory use: > + :set path-= +< To add the current directory use: > + :set path+= +< To use an environment variable, you probably need to replace the + separator. Here is an example to append $INCL, in which directory + names are separated with a semi-colon: > + :let &path = &path . "," . substitute($INCL, ';', ',', 'g') +< Replace the ';' with a ':' or whatever separator is used. Note that + this doesn't work when $INCL contains a comma or white space. + + *'preserveindent'* *'pi'* *'nopreserveindent'* *'nopi'* +'preserveindent' 'pi' boolean (default off) + local to buffer + {not in Vi} + When changing the indent of the current line, preserve as much of the + indent structure as possible. Normally the indent is replaced by a + series of tabs followed by spaces as required (unless |'expandtab'| is + enabled, in which case only spaces are used). Enabling this option + means the indent will preserve as many existing characters as possible + for indenting, and only add additional tabs or spaces as required. + 'expandtab' does not apply to the preserved white space, a Tab remains + a Tab. + NOTE: When using ">>" multiple times the resulting indent is a mix of + tabs and spaces. You might not like this. + NOTE: 'preserveindent' is reset when 'compatible' is set. + Also see 'copyindent'. + Use |:retab| to clean up white space. + + *'previewheight'* *'pvh'* +'previewheight' 'pvh' number (default 12) + global + {not in Vi} + {not available when compiled without the |+windows| or + |+quickfix| features} + Default height for a preview window. Used for |:ptag| and associated + commands. Used for |CTRL-W_}| when no count is given. + + *'previewwindow'* *'nopreviewwindow'* + *'pvw'* *'nopvw'* *E590* +'previewwindow' 'pvw' boolean (default off) + local to window + {not in Vi} + {not available when compiled without the |+windows| or + |+quickfix| features} + Identifies the preview window. Only one window can have this option + set. It's normally not set directly, but by using one of the commands + |:ptag|, |:pedit|, etc. + + *'printdevice'* *'pdev'* +'printdevice' 'pdev' string (default empty) + global + {not in Vi} + {only available when compiled with the |+printer| + feature} + The name of the printer to be used for |:hardcopy|. + See |pdev-option|. + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + *'printencoding'* *'penc'* +'printencoding' 'penc' String (default empty, except for some systems) + global + {not in Vi} + {only available when compiled with the |+printer| + and |+postscript| features} + Sets the character encoding used when printing. + See |penc-option|. + + *'printexpr'* *'pexpr'* +'printexpr' 'pexpr' String (default: see below) + global + {not in Vi} + {only available when compiled with the |+printer| + and |+postscript| features} + Expression used to print the PostScript produced with |:hardcopy|. + See |pexpr-option|. + + *'printfont'* *'pfn'* +'printfont' 'pfn' string (default "courier") + global + {not in Vi} + {only available when compiled with the |+printer| + feature} + The name of the font that will be used for |:hardcopy|. + See |pfn-option|. + + *'printheader'* *'pheader'* +'printheader' 'pheader' string (default "%<%f%h%m%=Page %N") + global + {not in Vi} + {only available when compiled with the |+printer| + feature} + The format of the header produced in |:hardcopy| output. + See |pheader-option|. + + *'printmbcharset'* *'pmbcs'* +'printmbcharset' 'pmbcs' string (default "") + global + {not in Vi} + {only available when compiled with the |+printer|, + |+postscript| and |+multi_byte| features} + The CJK character set to be used for CJK output from |:hardcopy|. + See |pmbcs-option|. + + *'printmbfont'* *'pmbfn'* +'printmbfont' 'pmbfn' string (default "") + global + {not in Vi} + {only available when compiled with the |+printer|, + |+postscript| and |+multi_byte| features} + List of font names to be used for CJK output from |:hardcopy|. + See |pmbfn-option|. + + *'printoptions'* *'popt'* +'printoptions' 'popt' string (default "") + global + {not in Vi} + {only available when compiled with |+printer| feature} + List of items that control the format of the output of |:hardcopy|. + See |popt-option|. + + *'prompt'* *'noprompt'* +'prompt' boolean (default on) + global + When on a ":" prompt is used in Ex mode. + + *'pumheight'* *'ph'* +'pumheight' 'ph' number (default 0) + global + {not available when compiled without the + |+insert_expand| feature} + {not in Vi} + Determines the maximum number of items to show in the popup menu for + Insert mode completion. When zero as much space as available is used. + |ins-completion-menu|. + + + *'quoteescape'* *'qe'* +'quoteescape' 'qe' string (default "\") + local to buffer + {not in Vi} + The characters that are used to escape quotes in a string. Used for + objects like a', a" and a` |a'|. + When one of the characters in this option is found inside a string, + the following character will be skipped. The default value makes the + text "foo\"bar\\" considered to be one string. + + *'readonly'* *'ro'* *'noreadonly'* *'noro'* +'readonly' 'ro' boolean (default off) + local to buffer + If on, writes fail unless you use a '!'. Protects you from + accidentally overwriting a file. Default on when Vim is started + in read-only mode ("vim -R") or when the executable is called "view". + When using ":w!" the 'readonly' option is reset for the current + buffer, unless the 'Z' flag is in 'cpoptions'. + {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. + + *'relativenumber'* *'rnu'* *'norelativenumber'* *'nornu'* +'relativenumber' 'rnu' boolean (default off) + local to window + {not in Vi} + Show the line number relative to the line with the cursor in front of + each line. Relative line numbers help you use the |count| you can + precede some vertical motion commands (e.g. j k + -) with, without + having to calculate it yourself. Especially useful in combination with + other commands (e.g. y d c < > gq gw =). + When the 'n' option is excluded from 'cpoptions' a wrapped + line will not use the column of line numbers (this is the default when + 'compatible' isn't set). + The 'numberwidth' option can be used to set the room used for the line + number. + When a long, wrapped line doesn't start with the first character, '-' + characters are put before the number. + See |hl-LineNr| for the highlighting used for the number. + When setting this option, 'number' is reset. + + *'remap'* *'noremap'* +'remap' boolean (default on) + global + Allows for mappings to work recursively. If you do not want this for + a single entry, use the :noremap[!] command. + NOTE: To avoid portability problems with Vim scripts, always keep + this option at the default "on". Only switch it off when working with + old Vi scripts. + + *'report'* +'report' number (default 2) + global + Threshold for reporting number of lines changed. When the number of + changed lines is more than 'report' a message will be given for most + ":" commands. If you want it always, set 'report' to 0. + For the ":substitute" command the number of substitutions is used + instead of the number of lines. + + *'restorescreen'* *'rs'* *'norestorescreen'* *'nors'* +'restorescreen' 'rs' boolean (default on) + global + {not in Vi} {only in Windows 95/NT console version} + When set, the screen contents is restored when exiting Vim. This also + happens when executing external commands. + + For non-Windows Vim: You can set or reset the 't_ti' and 't_te' + options in your .vimrc. To disable restoring: + set t_ti= t_te= + To enable restoring (for an xterm): + set t_ti=^[7^[[r^[[?47h t_te=^[[?47l^[8 + (Where ^[ is an , type CTRL-V to insert it) + + *'revins'* *'ri'* *'norevins'* *'nori'* +'revins' 'ri' boolean (default off) + global + {not in Vi} + {only available when compiled with the |+rightleft| + feature} + Inserting characters in Insert mode will work backwards. See "typing + backwards" |ins-reverse|. This option can be toggled with the CTRL-_ + command in Insert mode, when 'allowrevins' is set. + NOTE: This option is reset when 'compatible' or 'paste' is set. + + *'rightleft'* *'rl'* *'norightleft'* *'norl'* +'rightleft' 'rl' boolean (default off) + local to window + {not in Vi} + {only available when compiled with the |+rightleft| + feature} + When on, display orientation becomes right-to-left, i.e., characters + that are stored in the file appear from the right to the left. + Using this option, it is possible to edit files for languages that + are written from the right to the left such as Hebrew and Arabic. + This option is per window, so it is possible to edit mixed files + simultaneously, or to view the same file in both ways (this is + useful whenever you have a mixed text file with both right-to-left + and left-to-right strings so that both sets are displayed properly + in different windows). Also see |rileft.txt|. + + *'rightleftcmd'* *'rlc'* +'rightleftcmd' 'rlc' string (default "search") + local to window + {not in Vi} + {only available when compiled with the |+rightleft| + feature} + Each word in this option enables the command line editing to work in + right-to-left mode for a group of commands: + + search "/" and "?" commands + + This is useful for languages such as Hebrew, Arabic and Farsi. + The 'rightleft' option must be set for 'rightleftcmd' to take effect. + + *'ruler'* *'ru'* *'noruler'* *'noru'* +'ruler' 'ru' boolean (default off) + global + {not in Vi} + {not available when compiled without the + |+cmdline_info| feature} + Show the line and column number of the cursor position, separated by a + comma. When there is room, the relative position of the displayed + text in the file is shown on the far right: + Top first line is visible + Bot last line is visible + All first and last line are visible + 45% relative position in the file + If 'rulerformat' is set, it will determine the contents of the ruler. + Each window has its own ruler. If a window has a status line, the + ruler is shown there. Otherwise it is shown in the last line of the + screen. If the statusline is given by 'statusline' (i.e. not empty), + this option takes precedence over 'ruler' and 'rulerformat' + If the number of characters displayed is different from the number of + bytes in the text (e.g., for a TAB or a multi-byte character), both + the text column (byte number) and the screen column are shown, + separated with a dash. + For an empty line "0-1" is shown. + For an empty buffer the line number will also be zero: "0,0-1". + This option is reset when the 'paste' option is set. + If you don't want to see the ruler all the time but want to know where + you are, use "g CTRL-G" |g_CTRL-G|. + NOTE: This option is reset when 'compatible' is set. + + *'rulerformat'* *'ruf'* +'rulerformat' 'ruf' string (default empty) + global + {not in Vi} + {not available when compiled without the |+statusline| + feature} + When this option is not empty, it determines the content of the ruler + string, as displayed for the 'ruler' option. + The format of this option is like that of 'statusline'. + The default ruler width is 17 characters. To make the ruler 15 + characters wide, put "%15(" at the start and "%)" at the end. + Example: > + :set rulerformat=%15(%c%V\ %p%%%) +< + *'runtimepath'* *'rtp'* *vimfiles* +'runtimepath' 'rtp' string (default: + Unix: "$HOME/.vim, + $VIM/vimfiles, + $VIMRUNTIME, + $VIM/vimfiles/after, + $HOME/.vim/after" + Amiga: "home:vimfiles, + $VIM/vimfiles, + $VIMRUNTIME, + $VIM/vimfiles/after, + home:vimfiles/after" + PC, OS/2: "$HOME/vimfiles, + $VIM/vimfiles, + $VIMRUNTIME, + $VIM/vimfiles/after, + $HOME/vimfiles/after" + Macintosh: "$VIM:vimfiles, + $VIMRUNTIME, + $VIM:vimfiles:after" + RISC-OS: "Choices:vimfiles, + $VIMRUNTIME, + Choices:vimfiles/after" + VMS: "sys$login:vimfiles, + $VIM/vimfiles, + $VIMRUNTIME, + $VIM/vimfiles/after, + sys$login:vimfiles/after") + global + {not in Vi} + This is a list of directories which will be searched for runtime + files: + filetype.vim filetypes by file name |new-filetype| + scripts.vim filetypes by file contents |new-filetype-scripts| + autoload/ automatically loaded scripts |autoload-functions| + colors/ color scheme files |:colorscheme| + compiler/ compiler files |:compiler| + doc/ documentation |write-local-help| + ftplugin/ filetype plugins |write-filetype-plugin| + indent/ indent scripts |indent-expression| + keymap/ key mapping files |mbyte-keymap| + lang/ menu translations |:menutrans| + menu.vim GUI menus |menu.vim| + plugin/ plugin scripts |write-plugin| + print/ files for printing |postscript-print-encoding| + spell/ spell checking files |spell| + syntax/ syntax files |mysyntaxfile| + tutor/ files for vimtutor |tutor| + + And any other file searched for with the |:runtime| command. + + The defaults for most systems are setup to search five locations: + 1. In your home directory, for your personal preferences. + 2. In a system-wide Vim directory, for preferences from the system + administrator. + 3. In $VIMRUNTIME, for files distributed with Vim. + *after-directory* + 4. In the "after" directory in the system-wide Vim directory. This is + for the system administrator to overrule or add to the distributed + defaults (rarely needed) + 5. In the "after" directory in your home directory. This is for + personal preferences to overrule or add to the distributed defaults + or system-wide settings (rarely needed). + + Note that, unlike 'path', no wildcards like "**" are allowed. Normal + wildcards are allowed, but can significantly slow down searching for + runtime files. For speed, use as few items as possible and avoid + wildcards. + See |:runtime|. + Example: > + :set runtimepath=~/vimruntime,/mygroup/vim,$VIMRUNTIME +< This will use the directory "~/vimruntime" first (containing your + personal Vim runtime files), then "/mygroup/vim" (shared between a + group of people) and finally "$VIMRUNTIME" (the distributed runtime + files). + You probably should always include $VIMRUNTIME somewhere, to use the + distributed runtime files. You can put a directory before $VIMRUNTIME + to find files which replace a distributed runtime files. You can put + a directory after $VIMRUNTIME to find files which add to distributed + runtime files. + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + *'scroll'* *'scr'* +'scroll' 'scr' number (default: half the window height) + local to window + Number of lines to scroll with CTRL-U and CTRL-D commands. Will be + set to half the number of lines in the window when the window size + changes. If you give a count to the CTRL-U or CTRL-D command it will + be used as the new value for 'scroll'. Reset to half the window + height with ":set scroll=0". {Vi is a bit different: 'scroll' gives + the number of screen lines instead of file lines, makes a difference + when lines wrap} + + *'scrollbind'* *'scb'* *'noscrollbind'* *'noscb'* +'scrollbind' 'scb' boolean (default off) + local to window + {not in Vi} + {not available when compiled without the |+scrollbind| + feature} + See also |scroll-binding|. When this option is set, the current + window scrolls as other scrollbind windows (windows that also have + this option set) scroll. This option is useful for viewing the + differences between two versions of a file, see 'diff'. + See |'scrollopt'| for options that determine how this option should be + interpreted. + This option is mostly reset when splitting a window to edit another + file. This means that ":split | edit file" results in two windows + with scroll-binding, but ":split file" does not. + + *'scrolljump'* *'sj'* +'scrolljump' 'sj' number (default 1) + global + {not in Vi} + Minimal number of lines to scroll when the cursor gets off the + screen (e.g., with "j"). Not used for scroll commands (e.g., CTRL-E, + CTRL-D). Useful if your terminal scrolls very slowly. + When set to a negative number from -1 to -100 this is used as the + percentage of the window height. Thus -50 scrolls half the window + height. + NOTE: This option is set to 1 when 'compatible' is set. + + *'scrolloff'* *'so'* +'scrolloff' 'so' number (default 0) + global + {not in Vi} + Minimal number of screen lines to keep above and below the cursor. + This will make some context visible around where you are working. If + you set it to a very large value (999) the cursor line will always be + in the middle of the window (except at the start or end of the file or + when long lines wrap). + For scrolling horizontally see 'sidescrolloff'. + NOTE: This option is set to 0 when 'compatible' is set. + + *'scrollopt'* *'sbo'* +'scrollopt' 'sbo' string (default "ver,jump") + global + {not available when compiled without the |+scrollbind| + feature} + {not in Vi} + This is a comma-separated list of words that specifies how + 'scrollbind' windows should behave. 'sbo' stands for ScrollBind + Options. + The following words are available: + ver Bind vertical scrolling for 'scrollbind' windows + hor Bind horizontal scrolling for 'scrollbind' windows + jump Applies to the offset between two windows for vertical + scrolling. This offset is the difference in the first + displayed line of the bound windows. When moving + around in a window, another 'scrollbind' window may + reach a position before the start or after the end of + the buffer. The offset is not changed though, when + moving back the 'scrollbind' window will try to scroll + to the desired position when possible. + When now making that window the current one, two + things can be done with the relative offset: + 1. When "jump" is not included, the relative offset is + adjusted for the scroll position in the new current + window. When going back to the other window, the + new relative offset will be used. + 2. When "jump" is included, the other windows are + scrolled to keep the same relative offset. When + going back to the other window, it still uses the + same relative offset. + Also see |scroll-binding|. + When 'diff' mode is active there always is vertical scroll binding, + even when "ver" isn't there. + + *'sections'* *'sect'* +'sections' 'sect' string (default "SHNHH HUnhsh") + global + Specifies the nroff macros that separate sections. These are pairs of + two letters (See |object-motions|). The default makes a section start + at the nroff macros ".SH", ".NH", ".H", ".HU", ".nh" and ".sh". + + *'secure'* *'nosecure'* *E523* +'secure' boolean (default off) + global + {not in Vi} + When on, ":autocmd", shell and write commands are not allowed in + ".vimrc" and ".exrc" in the current directory and map commands are + displayed. Switch it off only if you know that you will not run into + problems, or when the 'exrc' option is off. On Unix this option is + only used if the ".vimrc" or ".exrc" is not owned by you. This can be + dangerous if the systems allows users to do a "chown". You better set + 'secure' at the end of your ~/.vimrc then. + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + *'selection'* *'sel'* +'selection' 'sel' string (default "inclusive") + global + {not in Vi} + This option defines the behavior of the selection. It is only used + in Visual and Select mode. + Possible values: + value past line inclusive ~ + old no yes + inclusive yes yes + exclusive yes no + "past line" means that the cursor is allowed to be positioned one + character past the line. + "inclusive" means that the last character of the selection is included + in an operation. For example, when "x" is used to delete the + selection. + Note that when "exclusive" is used and selecting from the end + backwards, you cannot include the last character of a line, when + starting in Normal mode and 'virtualedit' empty. + + The 'selection' option is set by the |:behave| command. + + *'selectmode'* *'slm'* +'selectmode' 'slm' string (default "") + global + {not in Vi} + This is a comma separated list of words, which specifies when to start + Select mode instead of Visual mode, when a selection is started. + Possible values: + mouse when using the mouse + key when using shifted special keys + cmd when using "v", "V" or CTRL-V + See |Select-mode|. + The 'selectmode' option is set by the |:behave| command. + + *'sessionoptions'* *'ssop'* +'sessionoptions' 'ssop' string (default: "blank,buffers,curdir,folds, + help,options,tabpages,winsize") + global + {not in Vi} + {not available when compiled without the |+mksession| + feature} + Changes the effect of the |:mksession| command. It is a comma + separated list of words. Each word enables saving and restoring + something: + word save and restore ~ + blank empty windows + buffers hidden and unloaded buffers, not just those in windows + curdir the current directory + folds manually created folds, opened/closed folds and local + fold options + globals global variables that start with an uppercase letter + and contain at least one lowercase letter. Only + String and Number types are stored. + help the help window + localoptions options and mappings local to a window or buffer (not + global values for local options) + options all options and mappings (also global values for local + options) + resize size of the Vim window: 'lines' and 'columns' + sesdir the directory in which the session file is located + will become the current directory (useful with + projects accessed over a network from different + systems) + slash backslashes in file names replaced with forward + slashes + tabpages all tab pages; without this only the current tab page + is restored, so that you can make a session for each + tab page separately + unix with Unix end-of-line format (single ), even when + on Windows or DOS + winpos position of the whole Vim window + winsize window sizes + + Don't include both "curdir" and "sesdir". + When neither "curdir" nor "sesdir" is included, file names are stored + with absolute paths. + "slash" and "unix" are useful on Windows when sharing session files + with Unix. The Unix version of Vim cannot source dos format scripts, + but the Windows version of Vim can source unix format scripts. + + *'shell'* *'sh'* *E91* +'shell' 'sh' string (default $SHELL or "sh", + MS-DOS and Win32: "command.com" or + "cmd.exe", OS/2: "cmd") + global + Name of the shell to use for ! and :! commands. When changing the + value also check these options: 'shelltype', 'shellpipe', 'shellslash' + 'shellredir', 'shellquote', 'shellxquote' and 'shellcmdflag'. + It is allowed to give an argument to the command, e.g. "csh -f". + See |option-backslash| about including spaces and backslashes. + Environment variables are expanded |:set_env|. + If the name of the shell contains a space, you might need to enclose + it in quotes. Example: > + :set shell=\"c:\program\ files\unix\sh.exe\"\ -f +< Note the backslash before each quote (to avoid starting a comment) and + each space (to avoid ending the option value). Also note that the + "-f" is not inside the quotes, because it is not part of the command + name. And Vim automagically recognizes the backslashes that are path + separators. + For Dos 32 bits (DJGPP), you can set the $DJSYSFLAGS environment + variable to change the way external commands are executed. See the + libc.inf file of DJGPP. + Under MS-Windows, when the executable ends in ".com" it must be + included. Thus setting the shell to "command.com" or "4dos.com" + works, but "command" and "4dos" do not work for all commands (e.g., + filtering). + For unknown reasons, when using "4dos.com" the current directory is + changed to "C:\". To avoid this set 'shell' like this: > + :set shell=command.com\ /c\ 4dos +< This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + *'shellcmdflag'* *'shcf'* +'shellcmdflag' 'shcf' string (default: "-c", MS-DOS and Win32, when 'shell' + does not contain "sh" somewhere: "/c") + global + {not in Vi} + Flag passed to the shell to execute "!" and ":!" commands; e.g., + "bash.exe -c ls" or "command.com /c dir". For the MS-DOS-like + systems, the default is set according to the value of 'shell', to + reduce the need to set this option by the user. It's not used for + OS/2 (EMX figures this out itself). See |option-backslash| about + including spaces and backslashes. See |dos-shell|. + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + *'shellpipe'* *'sp'* +'shellpipe' 'sp' string (default ">", "| tee", "|& tee" or "2>&1| tee") + global + {not in Vi} + {not available when compiled without the |+quickfix| + feature} + String to be used to put the output of the ":make" command in the + error file. See also |:make_makeprg|. See |option-backslash| about + including spaces and backslashes. + The name of the temporary file can be represented by "%s" if necessary + (the file name is appended automatically if no %s appears in the value + of this option). + For the Amiga and MS-DOS the default is ">". The output is directly + saved in a file and not echoed to the screen. + For Unix the default it "| tee". The stdout of the compiler is saved + in a file and echoed to the screen. If the 'shell' option is "csh" or + "tcsh" after initializations, the default becomes "|& tee". If the + 'shell' option is "sh", "ksh", "zsh" or "bash" the default becomes + "2>&1| tee". This means that stderr is also included. Before using + the 'shell' option a path is removed, thus "/bin/sh" uses "sh". + The initialization of this option is done after reading the ".vimrc" + and the other initializations, so that when the 'shell' option is set + there, the 'shellpipe' option changes automatically, unless it was + explicitly set before. + When 'shellpipe' is set to an empty string, no redirection of the + ":make" output will be done. This is useful if you use a 'makeprg' + that writes to 'makeef' by itself. If you want no piping, but do + want to include the 'makeef', set 'shellpipe' to a single space. + Don't forget to precede the space with a backslash: ":set sp=\ ". + In the future pipes may be used for filtering and this option will + become obsolete (at least for Unix). + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + *'shellquote'* *'shq'* +'shellquote' 'shq' string (default: ""; MS-DOS and Win32, when 'shell' + contains "sh" somewhere: "\"") + global + {not in Vi} + Quoting character(s), put around the command passed to the shell, for + the "!" and ":!" commands. The redirection is kept outside of the + quoting. See 'shellxquote' to include the redirection. It's + probably not useful to set both options. + This is an empty string by default. Only known to be useful for + third-party shells on MS-DOS-like systems, such as the MKS Korn Shell + or bash, where it should be "\"". The default is adjusted according + the value of 'shell', to reduce the need to set this option by the + user. See |dos-shell|. + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + *'shellredir'* *'srr'* +'shellredir' 'srr' string (default ">", ">&" or ">%s 2>&1") + global + {not in Vi} + String to be used to put the output of a filter command in a temporary + file. See also |:!|. See |option-backslash| about including spaces + and backslashes. + The name of the temporary file can be represented by "%s" if necessary + (the file name is appended automatically if no %s appears in the value + of this option). + The default is ">". For Unix, if the 'shell' option is "csh", "tcsh" + or "zsh" during initializations, the default becomes ">&". If the + 'shell' option is "sh", "ksh" or "bash" the default becomes + ">%s 2>&1". This means that stderr is also included. + For Win32, the Unix checks are done and additionally "cmd" is checked + for, which makes the default ">%s 2>&1". Also, the same names with + ".exe" appended are checked for. + The initialization of this option is done after reading the ".vimrc" + and the other initializations, so that when the 'shell' option is set + there, the 'shellredir' option changes automatically unless it was + explicitly set before. + In the future pipes may be used for filtering and this option will + become obsolete (at least for Unix). + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + *'shellslash'* *'ssl'* *'noshellslash'* *'nossl'* +'shellslash' 'ssl' boolean (default off) + global + {not in Vi} {only for MSDOS, MS-Windows and OS/2} + When set, a forward slash is used when expanding file names. This is + useful when a Unix-like shell is used instead of command.com or + cmd.exe. Backward slashes can still be typed, but they are changed to + forward slashes by Vim. + Note that setting or resetting this option has no effect for some + existing file names, thus this option needs to be set before opening + any file for best results. This might change in the future. + 'shellslash' only works when a backslash can be used as a path + separator. To test if this is so use: > + if exists('+shellslash') +< + *'shelltemp'* *'stmp'* *'noshelltemp'* *'nostmp'* +'shelltemp' 'stmp' boolean (Vi default off, Vim default on) + global + {not in Vi} + When on, use temp files for shell commands. When off use a pipe. + When using a pipe is not possible temp files are used anyway. + Currently a pipe is only supported on Unix. You can check it with: > + :if has("filterpipe") +< The advantage of using a pipe is that nobody can read the temp file + and the 'shell' command does not need to support redirection. + The advantage of using a temp file is that the file type and encoding + can be detected. + The |FilterReadPre|, |FilterReadPost| and |FilterWritePre|, + |FilterWritePost| autocommands event are not triggered when + 'shelltemp' is off. + + *'shelltype'* *'st'* +'shelltype' 'st' number (default 0) + global + {not in Vi} {only for the Amiga} + On the Amiga this option influences the way how the commands work + which use a shell. + 0 and 1: always use the shell + 2 and 3: use the shell only to filter lines + 4 and 5: use shell only for ':sh' command + When not using the shell, the command is executed directly. + + 0 and 2: use "shell 'shellcmdflag' cmd" to start external commands + 1 and 3: use "shell cmd" to start external commands + + *'shellxquote'* *'sxq'* +'shellxquote' 'sxq' string (default: ""; + for Win32, when 'shell' contains "sh" + somewhere: "\"" + for Unix, when using system(): "\"") + global + {not in Vi} + Quoting character(s), put around the command passed to the shell, for + the "!" and ":!" commands. Includes the redirection. See + 'shellquote' to exclude the redirection. It's probably not useful + to set both options. + This is an empty string by default. Known to be useful for + third-party shells when using the Win32 version, such as the MKS Korn + Shell or bash, where it should be "\"". The default is adjusted + according the value of 'shell', to reduce the need to set this option + by the user. See |dos-shell|. + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + *'shiftround'* *'sr'* *'noshiftround'* *'nosr'* +'shiftround' 'sr' boolean (default off) + global + {not in Vi} + Round indent to multiple of 'shiftwidth'. Applies to > and < + commands. CTRL-T and CTRL-D in Insert mode always round the indent to + a multiple of 'shiftwidth' (this is Vi compatible). + NOTE: This option is reset when 'compatible' is set. + + *'shiftwidth'* *'sw'* +'shiftwidth' 'sw' number (default 8) + local to buffer + Number of spaces to use for each step of (auto)indent. Used for + |'cindent'|, |>>|, |<<|, etc. + + *'shortmess'* *'shm'* +'shortmess' 'shm' string (Vim default "filnxtToO", Vi default: "", + POSIX default: "A") + global + {not in Vi} + This option helps to avoid all the |hit-enter| prompts caused by file + messages, for example with CTRL-G, and to avoid some other messages. + It is a list of flags: + flag meaning when present ~ + f use "(3 of 5)" instead of "(file 3 of 5)" + i use "[noeol]" instead of "[Incomplete last line]" + l use "999L, 888C" instead of "999 lines, 888 characters" + m use "[+]" instead of "[Modified]" + n use "[New]" instead of "[New File]" + r use "[RO]" instead of "[readonly]" + w use "[w]" instead of "written" for file write message + and "[a]" instead of "appended" for ':w >> file' command + x use "[dos]" instead of "[dos format]", "[unix]" instead of + "[unix format]" and "[mac]" instead of "[mac format]". + a all of the above abbreviations + + o overwrite message for writing a file with subsequent message + for reading a file (useful for ":wn" or when 'autowrite' on) + O message for reading a file overwrites any previous message. + Also for quickfix message (e.g., ":cn"). + s don't give "search hit BOTTOM, continuing at TOP" or "search + hit TOP, continuing at BOTTOM" messages + t truncate file message at the start if it is too long to fit + on the command-line, "<" will appear in the left most column. + Ignored in Ex mode. + T truncate other messages in the middle if they are too long to + fit on the command line. "..." will appear in the middle. + Ignored in Ex mode. + W don't give "written" or "[w]" when writing a file + A don't give the "ATTENTION" message when an existing swap file + is found. + I don't give the intro message when starting Vim |:intro|. + + This gives you the opportunity to avoid that a change between buffers + requires you to hit , but still gives as useful a message as + possible for the space available. To get the whole message that you + would have got with 'shm' empty, use ":file!" + Useful values: + shm= No abbreviation of message. + shm=a Abbreviation, but no loss of information. + shm=at Abbreviation, and truncate message when necessary. + + NOTE: This option is set to the Vi default value when 'compatible' is + set and to the Vim default value when 'compatible' is reset. + + *'shortname'* *'sn'* *'noshortname'* *'nosn'* +'shortname' 'sn' boolean (default off) + local to buffer + {not in Vi, not in MS-DOS versions} + Filenames are assumed to be 8 characters plus one extension of 3 + characters. Multiple dots in file names are not allowed. When this + option is on, dots in file names are replaced with underscores when + adding an extension (".~" or ".swp"). This option is not available + for MS-DOS, because then it would always be on. This option is useful + when editing files on an MS-DOS compatible filesystem, e.g., messydos + or crossdos. When running the Win32 GUI version under Win32s, this + option is always on by default. + + *'showbreak'* *'sbr'* *E595* +'showbreak' 'sbr' string (default "") + global + {not in Vi} + {not available when compiled without the |+linebreak| + feature} + String to put at the start of lines that have been wrapped. Useful + values are "> " or "+++ ": > + :set showbreak=>\ +< Note the backslash to escape the trailing space. It's easier like + this: > + :let &showbreak = '+++ ' +< Only printable single-cell characters are allowed, excluding and + comma (in a future version the comma might be used to separate the + part that is shown at the end and at the start of a line). + The characters are highlighted according to the '@' flag in + 'highlight'. + Note that tabs after the showbreak will be displayed differently. + If you want the 'showbreak' to appear in between line numbers, add the + "n" flag to 'cpoptions'. + + *'showcmd'* *'sc'* *'noshowcmd'* *'nosc'* +'showcmd' 'sc' boolean (Vim default: on, off for Unix, Vi default: + off) + global + {not in Vi} + {not available when compiled without the + |+cmdline_info| feature} + Show (partial) command in the last line of the screen. Set this + option off if your terminal is slow. + In Visual mode the size of the selected area is shown: + - When selecting characters within a line, the number of characters. + If the number of bytes is different it is also displayed: "2-6" + means two characters and six bytes. + - When selecting more than one line, the number of lines. + - When selecting a block, the size in screen characters: + {lines}x{columns}. + NOTE: This option is set to the Vi default value when 'compatible' is + set and to the Vim default value when 'compatible' is reset. + + *'showfulltag'* *'sft'* *'noshowfulltag'* *'nosft'* +'showfulltag' 'sft' boolean (default off) + global + {not in Vi} + When completing a word in insert mode (see |ins-completion|) from the + tags file, show both the tag name and a tidied-up form of the search + pattern (if there is one) as possible matches. Thus, if you have + matched a C function, you can see a template for what arguments are + required (coding style permitting). + Note that this doesn't work well together with having "longest" in + 'completeopt', because the completion from the search pattern may not + match the typed text. + + *'showmatch'* *'sm'* *'noshowmatch'* *'nosm'* +'showmatch' 'sm' boolean (default off) + global + When a bracket is inserted, briefly jump to the matching one. The + jump is only done if the match can be seen on the screen. The time to + show the match can be set with 'matchtime'. + A Beep is given if there is no match (no matter if the match can be + seen or not). This option is reset when the 'paste' option is set. + When the 'm' flag is not included in 'cpoptions', typing a character + will immediately move the cursor back to where it belongs. + See the "sm" field in 'guicursor' for setting the cursor shape and + blinking when showing the match. + The 'matchpairs' option can be used to specify the characters to show + matches for. 'rightleft' and 'revins' are used to look for opposite + matches. + Also see the matchparen plugin for highlighting the match when moving + around |pi_paren.txt|. + Note: Use of the short form is rated PG. + + *'showmode'* *'smd'* *'noshowmode'* *'nosmd'* +'showmode' 'smd' boolean (Vim default: on, Vi default: off) + global + If in Insert, Replace or Visual mode put a message on the last line. + Use the 'M' flag in 'highlight' to set the type of highlighting for + this message. + When |XIM| may be used the message will include "XIM". But this + doesn't mean XIM is really active, especially when 'imactivatekey' is + not set. + NOTE: This option is set to the Vi default value when 'compatible' is + set and to the Vim default value when 'compatible' is reset. + + *'showtabline'* *'stal'* +'showtabline' 'stal' number (default 1) + global + {not in Vi} + {not available when compiled without the |+windows| + feature} + The value of this option specifies when the line with tab page labels + will be displayed: + 0: never + 1: only if there are at least two tab pages + 2: always + This is both for the GUI and non-GUI implementation of the tab pages + line. + See |tab-page| for more information about tab pages. + + *'sidescroll'* *'ss'* +'sidescroll' 'ss' number (default 0) + global + {not in Vi} + The minimal number of columns to scroll horizontally. Used only when + the 'wrap' option is off and the cursor is moved off of the screen. + When it is zero the cursor will be put in the middle of the screen. + When using a slow terminal set it to a large number or 0. When using + a fast terminal use a small number or 1. Not used for "zh" and "zl" + commands. + + *'sidescrolloff'* *'siso'* +'sidescrolloff' 'siso' number (default 0) + global + {not in Vi} + The minimal number of screen columns to keep to the left and to the + right of the cursor if 'nowrap' is set. Setting this option to a + value greater than 0 while having |'sidescroll'| also at a non-zero + value makes some context visible in the line you are scrolling in + horizontally (except at beginning of the line). Setting this option + to a large value (like 999) has the effect of keeping the cursor + horizontally centered in the window, as long as one does not come too + close to the beginning of the line. + NOTE: This option is set to 0 when 'compatible' is set. + + Example: Try this together with 'sidescroll' and 'listchars' as + in the following example to never allow the cursor to move + onto the "extends" character: + + :set nowrap sidescroll=1 listchars=extends:>,precedes:< + :set sidescrolloff=1 + + + *'smartcase'* *'scs'* *'nosmartcase'* *'noscs'* +'smartcase' 'scs' boolean (default off) + global + {not in Vi} + Override the 'ignorecase' option if the search pattern contains upper + case characters. Only used when the search pattern is typed and + 'ignorecase' option is on. Used for the commands "/", "?", "n", "N", + ":g" and ":s". Not used for "*", "#", "gd", tag search, etc.. After + "*" and "#" you can make 'smartcase' used by doing a "/" command, + recalling the search pattern from history and hitting . + NOTE: This option is reset when 'compatible' is set. + + *'smartindent'* *'si'* *'nosmartindent'* *'nosi'* +'smartindent' 'si' boolean (default off) + local to buffer + {not in Vi} + {not available when compiled without the + |+smartindent| feature} + Do smart autoindenting when starting a new line. Works for C-like + programs, but can also be used for other languages. 'cindent' does + something like this, works better in most cases, but is more strict, + see |C-indenting|. When 'cindent' is on, setting 'si' has no effect. + 'indentexpr' is a more advanced alternative. + Normally 'autoindent' should also be on when using 'smartindent'. + An indent is automatically inserted: + - After a line ending in '{'. + - After a line starting with a keyword from 'cinwords'. + - Before a line starting with '}' (only with the "O" command). + When typing '}' as the first character in a new line, that line is + given the same indent as the matching '{'. + When typing '#' as the first character in a new line, the indent for + that line is removed, the '#' is put in the first column. The indent + is restored for the next line. If you don't want this, use this + mapping: ":inoremap # X^H#", where ^H is entered with CTRL-V CTRL-H. + When using the ">>" command, lines starting with '#' are not shifted + right. + NOTE: 'smartindent' is reset when 'compatible' is set. When 'paste' + is set smart indenting is disabled. + + *'smarttab'* *'sta'* *'nosmarttab'* *'nosta'* +'smarttab' 'sta' boolean (default off) + global + {not in Vi} + When on, a in front of a line inserts blanks according to + 'shiftwidth'. 'tabstop' or 'softtabstop' is used in other places. A + will delete a 'shiftwidth' worth of space at the start of the + line. + When off, a always inserts blanks according to 'tabstop' or + 'softtabstop'. 'shiftwidth' is only used for shifting text left or + right |shift-left-right|. + What gets inserted (a or spaces) depends on the 'expandtab' + option. Also see |ins-expandtab|. When 'expandtab' is not set, the + number of spaces is minimized by using s. + NOTE: This option is reset when 'compatible' is set. + + *'softtabstop'* *'sts'* +'softtabstop' 'sts' number (default 0) + local to buffer + {not in Vi} + Number of spaces that a counts for while performing editing + operations, like inserting a or using . It "feels" like + s are being inserted, while in fact a mix of spaces and s is + used. This is useful to keep the 'ts' setting at its standard value + of 8, while being able to edit like it is set to 'sts'. However, + commands like "x" still work on the actual characters. + When 'sts' is zero, this feature is off. + 'softtabstop' is set to 0 when the 'paste' option is set. + See also |ins-expandtab|. When 'expandtab' is not set, the number of + spaces is minimized by using s. + The 'L' flag in 'cpoptions' changes how tabs are used when 'list' is + set. + NOTE: This option is set to 0 when 'compatible' is set. + + *'spell'* *'nospell'* +'spell' boolean (default off) + local to window + {not in Vi} + {not available when compiled without the |+syntax| + feature} + When on spell checking will be done. See |spell|. + The languages are specified with 'spelllang'. + + *'spellcapcheck'* *'spc'* +'spellcapcheck' 'spc' string (default "[.?!]\_[\])'" \t]\+") + local to buffer + {not in Vi} + {not available when compiled without the |+syntax| + feature} + Pattern to locate the end of a sentence. The following word will be + checked to start with a capital letter. If not then it is highlighted + with SpellCap |hl-SpellCap| (unless the word is also badly spelled). + When this check is not wanted make this option empty. + Only used when 'spell' is set. + Be careful with special characters, see |option-backslash| about + including spaces and backslashes. + To set this option automatically depending on the language, see + |set-spc-auto|. + + *'spellfile'* *'spf'* +'spellfile' 'spf' string (default empty) + local to buffer + {not in Vi} + {not available when compiled without the |+syntax| + feature} + Name of the word list file where words are added for the |zg| and |zw| + commands. It must end in ".{encoding}.add". You need to include the + path, otherwise the file is placed in the current directory. + *E765* + It may also be a comma separated list of names. A count before the + |zg| and |zw| commands can be used to access each. This allows using + a personal word list file and a project word list file. + When a word is added while this option is empty Vim will set it for + you: Using the first directory in 'runtimepath' that is writable. If + there is no "spell" directory yet it will be created. For the file + name the first language name that appears in 'spelllang' is used, + ignoring the region. + The resulting ".spl" file will be used for spell checking, it does not + have to appear in 'spelllang'. + Normally one file is used for all regions, but you can add the region + name if you want to. However, it will then only be used when + 'spellfile' is set to it, for entries in 'spelllang' only files + without region name will be found. + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + *'spelllang'* *'spl'* +'spelllang' 'spl' string (default "en") + local to buffer + {not in Vi} + {not available when compiled without the |+syntax| + feature} + A comma separated list of word list names. When the 'spell' option is + on spellchecking will be done for these languages. Example: > + set spelllang=en_us,nl,medical +< This means US English, Dutch and medical words are recognized. Words + that are not recognized will be highlighted. + The word list name must not include a comma or dot. Using a dash is + recommended to separate the two letter language name from a + specification. Thus "en-rare" is used for rare English words. + A region name must come last and have the form "_xx", where "xx" is + the two-letter, lower case region name. You can use more than one + region by listing them: "en_us,en_ca" supports both US and Canadian + English, but not words specific for Australia, New Zealand or Great + Britain. + *E757* + As a special case the name of a .spl file can be given as-is. The + first "_xx" in the name is removed and used as the region name + (_xx is an underscore, two letters and followed by a non-letter). + This is mainly for testing purposes. You must make sure the correct + encoding is used, Vim doesn't check it. + When 'encoding' is set the word lists are reloaded. Thus it's a good + idea to set 'spelllang' after setting 'encoding' to avoid loading the + files twice. + How the related spell files are found is explained here: |spell-load|. + + If the |spellfile.vim| plugin is active and you use a language name + for which Vim cannot find the .spl file in 'runtimepath' the plugin + will ask you if you want to download the file. + + After this option has been set successfully, Vim will source the files + "spell/LANG.vim" in 'runtimepath'. "LANG" is the value of 'spelllang' + up to the first comma, dot or underscore. + Also see |set-spc-auto|. + + + *'spellsuggest'* *'sps'* +'spellsuggest' 'sps' string (default "best") + global + {not in Vi} + {not available when compiled without the |+syntax| + feature} + Methods used for spelling suggestions. Both for the |z=| command and + the |spellsuggest()| function. This is a comma-separated list of + items: + + best Internal method that works best for English. Finds + changes like "fast" and uses a bit of sound-a-like + scoring to improve the ordering. + + double Internal method that uses two methods and mixes the + results. The first method is "fast", the other method + computes how much the suggestion sounds like the bad + word. That only works when the language specifies + sound folding. Can be slow and doesn't always give + better results. + + fast Internal method that only checks for simple changes: + character inserts/deletes/swaps. Works well for + simple typing mistakes. + + {number} The maximum number of suggestions listed for |z=|. + Not used for |spellsuggest()|. The number of + suggestions is never more than the value of 'lines' + minus two. + + file:{filename} Read file {filename}, which must have two columns, + separated by a slash. The first column contains the + bad word, the second column the suggested good word. + Example: + theribal/terrible ~ + Use this for common mistakes that do not appear at the + top of the suggestion list with the internal methods. + Lines without a slash are ignored, use this for + comments. + The file is used for all languages. + + expr:{expr} Evaluate expression {expr}. Use a function to avoid + trouble with spaces. |v:val| holds the badly spelled + word. The expression must evaluate to a List of + Lists, each with a suggestion and a score. + Example: + [['the', 33], ['that', 44]] + Set 'verbose' and use |z=| to see the scores that the + internal methods use. A lower score is better. + This may invoke |spellsuggest()| if you temporarily + set 'spellsuggest' to exclude the "expr:" part. + Errors are silently ignored, unless you set the + 'verbose' option to a non-zero value. + + Only one of "best", "double" or "fast" may be used. The others may + appear several times in any order. Example: > + :set sps=file:~/.vim/sugg,best,expr:MySuggest() +< + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + + *'splitbelow'* *'sb'* *'nosplitbelow'* *'nosb'* +'splitbelow' 'sb' boolean (default off) + global + {not in Vi} + {not available when compiled without the |+windows| + feature} + When on, splitting a window will put the new window below the current + one. |:split| + + *'splitright'* *'spr'* *'nosplitright'* *'nospr'* +'splitright' 'spr' boolean (default off) + global + {not in Vi} + {not available when compiled without the |+vertsplit| + feature} + When on, splitting a window will put the new window right of the + current one. |:vsplit| + + *'startofline'* *'sol'* *'nostartofline'* *'nosol'* +'startofline' 'sol' boolean (default on) + global + {not in Vi} + When "on" the commands listed below move the cursor to the first + non-blank of the line. When off the cursor is kept in the same column + (if possible). This applies to the commands: CTRL-D, CTRL-U, CTRL-B, + CTRL-F, "G", "H", "M", "L", gg, and to the commands "d", "<<" and ">>" + with a linewise operator, with "%" with a count and to buffer changing + commands (CTRL-^, :bnext, :bNext, etc.). Also for an Ex command that + only has a line number, e.g., ":25" or ":+". + In case of buffer changing commands the cursor is placed at the column + where it was the last time the buffer was edited. + NOTE: This option is set when 'compatible' is set. + + *'statusline'* *'stl'* *E540* *E541* *E542* +'statusline' 'stl' string (default empty) + global or local to window |global-local| + {not in Vi} + {not available when compiled without the |+statusline| + feature} + When nonempty, this option determines the content of the status line. + Also see |status-line|. + + The option consists of printf style '%' items interspersed with + normal text. Each status line item is of the form: + %-0{minwid}.{maxwid}{item} + All fields except the {item} is optional. A single percent sign can + be given as "%%". Up to 80 items can be specified. + + When the option starts with "%!" then it is used as an expression, + evaluated and the result is used as the option value. Example: > + :set statusline=%!MyStatusLine() +< The result can contain %{} items that will be evaluated too. + + When there is error while evaluating the option then it will be made + empty to avoid further errors. Otherwise screen updating would loop. + + Note that the only effect of 'ruler' when this option is set (and + 'laststatus' is 2) is controlling the output of |CTRL-G|. + + field meaning ~ + - Left justify the item. The default is right justified + when minwid is larger than the length of the item. + 0 Leading zeroes in numeric items. Overridden by '-'. + minwid Minimum width of the item, padding as set by '-' & '0'. + Value must be 50 or less. + maxwid Maximum width of the item. Truncation occurs with a '<' + on the left for text items. Numeric items will be + shifted down to maxwid-2 digits followed by '>'number + where number is the amount of missing digits, much like + an exponential notation. + item A one letter code as described below. + + Following is a description of the possible statusline items. The + second character in "item" is the type: + N for number + S for string + F for flags as described below + - not applicable + + item meaning ~ + f S Path to the file in the buffer, as typed or relative to current + directory. + F S Full path to the file in the buffer. + t S File name (tail) of file in the buffer. + m F Modified flag, text is "[+]"; "[-]" if 'modifiable' is off. + M F Modified flag, text is ",+" or ",-". + r F Readonly flag, text is "[RO]". + R F Readonly flag, text is ",RO". + h F Help buffer flag, text is "[help]". + H F Help buffer flag, text is ",HLP". + w F Preview window flag, text is "[Preview]". + W F Preview window flag, text is ",PRV". + y F Type of file in the buffer, e.g., "[vim]". See 'filetype'. + Y F Type of file in the buffer, e.g., ",VIM". See 'filetype'. + {not available when compiled without |+autocmd| feature} + q S "[Quickfix List]", "[Location List]" or empty. + k S Value of "b:keymap_name" or 'keymap' when |:lmap| mappings are + being used: "" + n N Buffer number. + b N Value of byte under cursor. + B N As above, in hexadecimal. + o N Byte number in file of byte under cursor, first byte is 1. + Mnemonic: Offset from start of file (with one added) + {not available when compiled without |+byte_offset| feature} + O N As above, in hexadecimal. + N N Printer page number. (Only works in the 'printheader' option.) + l N Line number. + L N Number of lines in buffer. + c N Column number. + v N Virtual column number. + V N Virtual column number as -{num}. Not displayed if equal to 'c'. + p N Percentage through file in lines as in |CTRL-G|. + P S Percentage through file of displayed window. This is like the + percentage described for 'ruler'. Always 3 in length. + a S Argument list status as in default title. ({current} of {max}) + Empty if the argument file count is zero or one. + { NF Evaluate expression between '%{' and '}' and substitute result. + Note that there is no '%' before the closing '}'. + ( - Start of item group. Can be used for setting the width and + alignment of a section. Must be followed by %) somewhere. + ) - End of item group. No width fields allowed. + T N For 'tabline': start of tab page N label. Use %T after the last + label. This information is used for mouse clicks. + X N For 'tabline': start of close tab N label. Use %X after the + label, e.g.: %3Xclose%X. Use %999X for a "close current tab" + mark. This information is used for mouse clicks. + < - Where to truncate line if too long. Default is at the start. + No width fields allowed. + = - Separation point between left and right aligned items. + No width fields allowed. + # - Set highlight group. The name must follow and then a # again. + Thus use %#HLname# for highlight group HLname. The same + highlighting is used, also for the statusline of non-current + windows. + * - Set highlight group to User{N}, where {N} is taken from the + minwid field, e.g. %1*. Restore normal highlight with %* or %0*. + The difference between User{N} and StatusLine will be applied + to StatusLineNC for the statusline of non-current windows. + The number N must be between 1 and 9. See |hl-User1..9| + + When displaying a flag, Vim removes the leading comma, if any, when + that flag comes right after plaintext. This will make a nice display + when flags are used like in the examples below. + + When all items in a group becomes an empty string (i.e. flags that are + not set) and a minwid is not set for the group, the whole group will + become empty. This will make a group like the following disappear + completely from the statusline when none of the flags are set. > + :set statusline=...%(\ [%M%R%H]%)... +< + Beware that an expression is evaluated each and every time the status + line is displayed. The current buffer and current window will be set + temporarily to that of the window (and buffer) whose statusline is + currently being drawn. The expression will evaluate in this context. + The variable "actual_curbuf" is set to the 'bufnr()' number of the + real current buffer. + + The 'statusline' option may be evaluated in the |sandbox|, see + |sandbox-option|. + + It is not allowed to change text or jump to another window while + evaluating 'statusline' |textlock|. + + If the statusline is not updated when you want it (e.g., after setting + a variable that's used in an expression), you can force an update by + setting an option without changing its value. Example: > + :let &ro = &ro + +< A result of all digits is regarded a number for display purposes. + Otherwise the result is taken as flag text and applied to the rules + described above. + + Watch out for errors in expressions. They may render Vim unusable! + If you are stuck, hold down ':' or 'Q' to get a prompt, then quit and + edit your .vimrc or whatever with "vim -u NONE" to get it right. + + Examples: + Emulate standard status line with 'ruler' set > + :set statusline=%<%f\ %h%m%r%=%-14.(%l,%c%V%)\ %P +< Similar, but add ASCII value of char under the cursor (like "ga") > + :set statusline=%<%f%h%m%r%=%b\ 0x%B\ \ %l,%c%V\ %P +< Display byte count and byte value, modified flag in red. > + :set statusline=%<%f%=\ [%1*%M%*%n%R%H]\ %-19(%3l,%02c%03V%)%O'%02b' + :hi User1 term=inverse,bold cterm=inverse,bold ctermfg=red +< Display a ,GZ flag if a compressed file is loaded > + :set statusline=...%r%{VarExists('b:gzflag','\ [GZ]')}%h... +< In the |:autocmd|'s: > + :let b:gzflag = 1 +< And: > + :unlet b:gzflag +< And define this function: > + :function VarExists(var, val) + : if exists(a:var) | return a:val | else | return '' | endif + :endfunction +< + *'suffixes'* *'su'* +'suffixes' 'su' string (default ".bak,~,.o,.h,.info,.swp,.obj") + global + {not in Vi} + Files with these suffixes get a lower priority when multiple files + match a wildcard. See |suffixes|. Commas can be used to separate the + suffixes. Spaces after the comma are ignored. A dot is also seen as + the start of a suffix. To avoid a dot or comma being recognized as a + separator, precede it with a backslash (see |option-backslash| about + including spaces and backslashes). + See 'wildignore' for completely ignoring files. + The use of |:set+=| and |:set-=| is preferred when adding or removing + suffixes from the list. This avoids problems when a future version + uses another default. + + *'suffixesadd'* *'sua'* +'suffixesadd' 'sua' string (default "") + local to buffer + {not in Vi} + {not available when compiled without the + |+file_in_path| feature} + Comma separated list of suffixes, which are used when searching for a + file for the "gf", "[I", etc. commands. Example: > + :set suffixesadd=.java +< + *'swapfile'* *'swf'* *'noswapfile'* *'noswf'* +'swapfile' 'swf' boolean (default on) + local to buffer + {not in Vi} + Use a swapfile for the buffer. This option can be reset when a + swapfile is not wanted for a specific buffer. For example, with + confidential information that even root must not be able to access. + Careful: All text will be in memory: + - Don't use this for big files. + - Recovery will be impossible! + A swapfile will only be present when |'updatecount'| is non-zero and + 'swapfile' is set. + When 'swapfile' is reset, the swap file for the current buffer is + immediately deleted. When 'swapfile' is set, and 'updatecount' is + non-zero, a swap file is immediately created. + Also see |swap-file| and |'swapsync'|. + + This option is used together with 'bufhidden' and 'buftype' to + specify special kinds of buffers. See |special-buffers|. + + *'swapsync'* *'sws'* +'swapsync' 'sws' string (default "fsync") + global + {not in Vi} + When this option is not empty a swap file is synced to disk after + writing to it. This takes some time, especially on busy unix systems. + When this option is empty parts of the swap file may be in memory and + not written to disk. When the system crashes you may lose more work. + On Unix the system does a sync now and then without Vim asking for it, + so the disadvantage of setting this option off is small. On some + systems the swap file will not be written at all. For a unix system + setting it to "sync" will use the sync() call instead of the default + fsync(), which may work better on some systems. + The 'fsync' option is used for the actual file. + + *'switchbuf'* *'swb'* +'switchbuf' 'swb' string (default "") + global + {not in Vi} + This option controls the behavior when switching between buffers. + Possible values (comma separated list): + useopen If included, jump to the first open window that + contains the specified buffer (if there is one). + Otherwise: Do not examine other windows. + This setting is checked with |quickfix| commands, when + jumping to errors (":cc", ":cn", "cp", etc.). It is + also used in all buffer related split commands, for + example ":sbuffer", ":sbnext", or ":sbrewind". + usetab Like "useopen", but also consider windows in other tab + pages. + split If included, split the current window before loading + a buffer. Otherwise: do not split, use current window. + Supported in |quickfix| commands that display errors. + newtab Like "split", but open a new tab page. Overrules + "split" when both are present. + + *'synmaxcol'* *'smc'* +'synmaxcol' 'smc' number (default 3000) + local to buffer + {not in Vi} + {not available when compiled without the |+syntax| + feature} + Maximum column in which to search for syntax items. In long lines the + text after this column is not highlighted and following lines may not + be highlighted correctly, because the syntax state is cleared. + This helps to avoid very slow redrawing for an XML file that is one + long line. + Set to zero to remove the limit. + + *'syntax'* *'syn'* +'syntax' 'syn' string (default empty) + local to buffer + {not in Vi} + {not available when compiled without the |+syntax| + feature} + When this option is set, the syntax with this name is loaded, unless + syntax highlighting has been switched off with ":syntax off". + Otherwise this option does not always reflect the current syntax (the + b:current_syntax variable does). + This option is most useful in a modeline, for a file which syntax is + not automatically recognized. Example, in an IDL file: + /* vim: set syntax=idl : */ ~ + When a dot appears in the value then this separates two filetype + names. Example: + /* vim: set syntax=c.doxygen : */ ~ + This will use the "c" syntax first, then the "doxygen" syntax. + Note that the second one must be prepared to be loaded as an addition, + otherwise it will be skipped. More than one dot may appear. + To switch off syntax highlighting for the current file, use: > + :set syntax=OFF +< To switch syntax highlighting on according to the current value of the + 'filetype' option: > + :set syntax=ON +< What actually happens when setting the 'syntax' option is that the + Syntax autocommand event is triggered with the value as argument. + This option is not copied to another buffer, independent of the 's' or + 'S' flag in 'cpoptions'. + Only normal file name characters can be used, "/\*?[|<>" are illegal. + + *'tabline'* *'tal'* +'tabline' 'tal' string (default empty) + global + {not in Vi} + {not available when compiled without the |+windows| + feature} + When nonempty, this option determines the content of the tab pages + line at the top of the Vim window. When empty Vim will use a default + tab pages line. See |setting-tabline| for more info. + + The tab pages line only appears as specified with the 'showtabline' + option and only when there is no GUI tab line. When 'e' is in + 'guioptions' and the GUI supports a tab line 'guitablabel' is used + instead. Note that the two tab pages lines are very different. + + The value is evaluated like with 'statusline'. You can use + |tabpagenr()|, |tabpagewinnr()| and |tabpagebuflist()| to figure out + the text to be displayed. Use "%1T" for the first label, "%2T" for + the second one, etc. Use "%X" items for closing labels. + + Keep in mind that only one of the tab pages is the current one, others + are invisible and you can't jump to their windows. + + + *'tabpagemax'* *'tpm'* +'tabpagemax' 'tpm' number (default 10) + global + {not in Vi} + {not available when compiled without the |+windows| + feature} + Maximum number of tab pages to be opened by the |-p| command line + argument or the ":tab all" command. |tabpage| + + + *'tabstop'* *'ts'* +'tabstop' 'ts' number (default 8) + local to buffer + Number of spaces that a in the file counts for. Also see + |:retab| command, and 'softtabstop' option. + + Note: Setting 'tabstop' to any other value than 8 can make your file + appear wrong in many places (e.g., when printing it). + + There are four main ways to use tabs in Vim: + 1. Always keep 'tabstop' at 8, set 'softtabstop' and 'shiftwidth' to 4 + (or 3 or whatever you prefer) and use 'noexpandtab'. Then Vim + will use a mix of tabs and spaces, but typing and will + behave like a tab appears every 4 (or 3) characters. + 2. Set 'tabstop' and 'shiftwidth' to whatever you prefer and use + 'expandtab'. This way you will always insert spaces. The + formatting will never be messed up when 'tabstop' is changed. + 3. Set 'tabstop' and 'shiftwidth' to whatever you prefer and use a + |modeline| to set these values when editing the file again. Only + works when using Vim to edit the file. + 4. Always set 'tabstop' and 'shiftwidth' to the same value, and + 'noexpandtab'. This should then work (for initial indents only) + for any tabstop setting that people use. It might be nice to have + tabs after the first non-blank inserted as spaces if you do this + though. Otherwise aligned comments will be wrong when 'tabstop' is + changed. + + *'tagbsearch'* *'tbs'* *'notagbsearch'* *'notbs'* +'tagbsearch' 'tbs' boolean (default on) + global + {not in Vi} + When searching for a tag (e.g., for the |:ta| command), Vim can either + use a binary search or a linear search in a tags file. Binary + searching makes searching for a tag a LOT faster, but a linear search + will find more tags if the tags file wasn't properly sorted. + Vim normally assumes that your tags files are sorted, or indicate that + they are not sorted. Only when this is not the case does the + 'tagbsearch' option need to be switched off. + + When 'tagbsearch' is on, binary searching is first used in the tags + files. In certain situations, Vim will do a linear search instead for + certain files, or retry all files with a linear search. When + 'tagbsearch' is off, only a linear search is done. + + Linear searching is done anyway, for one file, when Vim finds a line + at the start of the file indicating that it's not sorted: > + !_TAG_FILE_SORTED 0 /some comment/ +< [The whitespace before and after the '0' must be a single ] + + When a binary search was done and no match was found in any of the + files listed in 'tags', and 'ignorecase' is set or a pattern is used + instead of a normal tag name, a retry is done with a linear search. + Tags in unsorted tags files, and matches with different case will only + be found in the retry. + + If a tag file indicates that it is case-fold sorted, the second, + linear search can be avoided for the 'ignorecase' case. Use a value + of '2' in the "!_TAG_FILE_SORTED" line for this. A tag file can be + case-fold sorted with the -f switch to "sort" in most unices, as in + the command: "sort -f -o tags tags". For "Exuberant ctags" version + 5.x or higher (at least 5.5) the --sort=foldcase switch can be used + for this as well. Note that case must be folded to uppercase for this + to work. + + When 'tagbsearch' is off, tags searching is slower when a full match + exists, but faster when no full match exists. Tags in unsorted tags + files may only be found with 'tagbsearch' off. + When the tags file is not sorted, or sorted in a wrong way (not on + ASCII byte value), 'tagbsearch' should be off, or the line given above + must be included in the tags file. + This option doesn't affect commands that find all matching tags (e.g., + command-line completion and ":help"). + {Vi: always uses binary search in some versions} + + *'taglength'* *'tl'* +'taglength' 'tl' number (default 0) + global + If non-zero, tags are significant up to this number of characters. + + *'tagrelative'* *'tr'* *'notagrelative'* *'notr'* +'tagrelative' 'tr' boolean (Vim default: on, Vi default: off) + global + {not in Vi} + If on and using a tags file in another directory, file names in that + tags file are relative to the directory where the tags file is. + NOTE: This option is set to the Vi default value when 'compatible' is + set and to the Vim default value when 'compatible' is reset. + + *'tags'* *'tag'* *E433* +'tags' 'tag' string (default "./tags,tags", when compiled with + |+emacs_tags|: "./tags,./TAGS,tags,TAGS") + global or local to buffer |global-local| + Filenames for the tag command, separated by spaces or commas. To + include a space or comma in a file name, precede it with a backslash + (see |option-backslash| about including spaces and backslashes). + When a file name starts with "./", the '.' is replaced with the path + of the current file. But only when the 'd' flag is not included in + 'cpoptions'. Environment variables are expanded |:set_env|. Also see + |tags-option|. + "*", "**" and other wildcards can be used to search for tags files in + a directory tree. See |file-searching|. E.g., "/lib/**/tags" will + find all files named "tags" below "/lib". The filename itself cannot + contain wildcards, it is used as-is. E.g., "/lib/**/tags?" will find + files called "tags?". {not available when compiled without the + |+path_extra| feature} + The |tagfiles()| function can be used to get a list of the file names + actually used. + If Vim was compiled with the |+emacs_tags| feature, Emacs-style tag + files are also supported. They are automatically recognized. The + default value becomes "./tags,./TAGS,tags,TAGS", unless case + differences are ignored (MS-Windows). |emacs-tags| + The use of |:set+=| and |:set-=| is preferred when adding or removing + file names from the list. This avoids problems when a future version + uses another default. + {Vi: default is "tags /usr/lib/tags"} + + *'tagstack'* *'tgst'* *'notagstack'* *'notgst'* +'tagstack' 'tgst' boolean (default on) + global + {not in all versions of Vi} + When on, the |tagstack| is used normally. When off, a ":tag" or + ":tselect" command with an argument will not push the tag onto the + tagstack. A following ":tag" without an argument, a ":pop" command or + any other command that uses the tagstack will use the unmodified + tagstack, but does change the pointer to the active entry. + Resetting this option is useful when using a ":tag" command in a + mapping which should not change the tagstack. + + *'term'* *E529* *E530* *E531* +'term' string (default is $TERM, if that fails: + in the GUI: "builtin_gui" + on Amiga: "amiga" + on BeOS: "beos-ansi" + on Mac: "mac-ansi" + on MiNT: "vt52" + on MS-DOS: "pcterm" + on OS/2: "os2ansi" + on Unix: "ansi" + on VMS: "ansi" + on Win 32: "win32") + global + Name of the terminal. Used for choosing the terminal control + characters. Environment variables are expanded |:set_env|. + For example: > + :set term=$TERM +< See |termcap|. + + *'termbidi'* *'tbidi'* + *'notermbidi'* *'notbidi'* +'termbidi' 'tbidi' boolean (default off, on for "mlterm") + global + {not in Vi} + {only available when compiled with the |+arabic| + feature} + The terminal is in charge of Bi-directionality of text (as specified + by Unicode). The terminal is also expected to do the required shaping + that some languages (such as Arabic) require. + Setting this option implies that 'rightleft' will not be set when + 'arabic' is set and the value of 'arabicshape' will be ignored. + Note that setting 'termbidi' has the immediate effect that + 'arabicshape' is ignored, but 'rightleft' isn't changed automatically. + This option is reset when the GUI is started. + For further details see |arabic.txt|. + + *'termencoding'* *'tenc'* +'termencoding' 'tenc' string (default ""; with GTK+ 2 GUI: "utf-8"; with + Macintosh GUI: "macroman") + global + {only available when compiled with the |+multi_byte| + feature} + {not in Vi} + Encoding used for the terminal. This specifies what character + encoding the keyboard produces and the display will understand. For + the GUI it only applies to the keyboard ('encoding' is used for the + display). Except for the Mac when 'macatsui' is off, then + 'termencoding' should be "macroman". + In the Win32 console version the default value is the console codepage + when it differs from the ANSI codepage. + *E617* + Note: This does not apply to the GTK+ 2 GUI. After the GUI has been + successfully initialized, 'termencoding' is forcibly set to "utf-8". + Any attempts to set a different value will be rejected, and an error + message is shown. + For the Win32 GUI 'termencoding' is not used for typed characters, + because the Win32 system always passes Unicode characters. + When empty, the same encoding is used as for the 'encoding' option. + This is the normal value. + Not all combinations for 'termencoding' and 'encoding' are valid. See + |encoding-table|. + The value for this option must be supported by internal conversions or + iconv(). When this is not possible no conversion will be done and you + will probably experience problems with non-ASCII characters. + Example: You are working with the locale set to euc-jp (Japanese) and + want to edit a UTF-8 file: > + :let &termencoding = &encoding + :set encoding=utf-8 +< You need to do this when your system has no locale support for UTF-8. + + *'terse'* *'noterse'* +'terse' boolean (default off) + global + When set: Add 's' flag to 'shortmess' option (this makes the message + for a search that hits the start or end of the file not being + displayed). When reset: Remove 's' flag from 'shortmess' option. {Vi + shortens a lot of messages} + + *'textauto'* *'ta'* *'notextauto'* *'nota'* +'textauto' 'ta' boolean (Vim default: on, Vi default: off) + global + {not in Vi} + This option is obsolete. Use 'fileformats'. + For backwards compatibility, when 'textauto' is set, 'fileformats' is + set to the default value for the current system. When 'textauto' is + reset, 'fileformats' is made empty. + NOTE: This option is set to the Vi default value when 'compatible' is + set and to the Vim default value when 'compatible' is reset. + + *'textmode'* *'tx'* *'notextmode'* *'notx'* +'textmode' 'tx' boolean (MS-DOS, Win32 and OS/2: default on, + others: default off) + local to buffer + {not in Vi} + This option is obsolete. Use 'fileformat'. + For backwards compatibility, when 'textmode' is set, 'fileformat' is + set to "dos". When 'textmode' is reset, 'fileformat' is set to + "unix". + + *'textwidth'* *'tw'* +'textwidth' 'tw' number (default 0) + local to buffer + {not in Vi} + Maximum width of text that is being inserted. A longer line will be + broken after white space to get this width. A zero value disables + this. 'textwidth' is set to 0 when the 'paste' option is set. When + 'textwidth' is zero, 'wrapmargin' may be used. See also + 'formatoptions' and |ins-textwidth|. + When 'formatexpr' is set it will be used to break the line. + NOTE: This option is set to 0 when 'compatible' is set. + + *'thesaurus'* *'tsr'* +'thesaurus' 'tsr' string (default "") + global or local to buffer |global-local| + {not in Vi} + List of file names, separated by commas, that are used to lookup words + for thesaurus completion commands |i_CTRL-X_CTRL-T|. Each line in + the file should contain words with similar meaning, separated by + non-keyword characters (white space is preferred). Maximum line + length is 510 bytes. + To obtain a file to be used here, check out the wordlist FAQ at + http://www.hyphenologist.co.uk . + To include a comma in a file name precede it with a backslash. Spaces + after a comma are ignored, otherwise spaces are included in the file + name. See |option-backslash| about using backslashes. + The use of |:set+=| and |:set-=| is preferred when adding or removing + directories from the list. This avoids problems when a future version + uses another default. + Backticks cannot be used in this option for security reasons. + + *'tildeop'* *'top'* *'notildeop'* *'notop'* +'tildeop' 'top' boolean (default off) + global + {not in Vi} + When on: The tilde command "~" behaves like an operator. + NOTE: This option is reset when 'compatible' is set. + + *'timeout'* *'to'* *'notimeout'* *'noto'* +'timeout' 'to' boolean (default on) + global + *'ttimeout'* *'nottimeout'* +'ttimeout' boolean (default off) + global + {not in Vi} + These two options together determine the behavior when part of a + mapped key sequence or keyboard code has been received: + + 'timeout' 'ttimeout' action ~ + off off do not time out + on on or off time out on :mappings and key codes + off on time out on key codes + + If both options are off, Vim will wait until either the complete + mapping or key sequence has been received, or it is clear that there + is no mapping or key sequence for the received characters. For + example: if you have mapped "vl" and Vim has received 'v', the next + character is needed to see if the 'v' is followed by an 'l'. + When one of the options is on, Vim will wait for about 1 second for + the next character to arrive. After that the already received + characters are interpreted as single characters. The waiting time can + be changed with the 'timeoutlen' option. + On slow terminals or very busy systems timing out may cause + malfunctioning cursor keys. If both options are off, Vim waits + forever after an entered if there are key codes that start + with . You will have to type twice. If you do not have + problems with key codes, but would like to have :mapped key + sequences not timing out in 1 second, set the 'ttimeout' option and + reset the 'timeout' option. + + NOTE: 'ttimeout' is reset when 'compatible' is set. + + *'timeoutlen'* *'tm'* +'timeoutlen' 'tm' number (default 1000) + global + {not in all versions of Vi} + *'ttimeoutlen'* *'ttm'* +'ttimeoutlen' 'ttm' number (default -1) + global + {not in Vi} + The time in milliseconds that is waited for a key code or mapped key + sequence to complete. Also used for CTRL-\ CTRL-N and CTRL-\ CTRL-G + when part of a command has been typed. + Normally only 'timeoutlen' is used and 'ttimeoutlen' is -1. When a + different timeout value for key codes is desired set 'ttimeoutlen' to + a non-negative number. + + ttimeoutlen mapping delay key code delay ~ + < 0 'timeoutlen' 'timeoutlen' + >= 0 'timeoutlen' 'ttimeoutlen' + + The timeout only happens when the 'timeout' and 'ttimeout' options + tell so. A useful setting would be > + :set timeout timeoutlen=3000 ttimeoutlen=100 +< (time out on mapping after three seconds, time out on key codes after + a tenth of a second). + + *'title'* *'notitle'* +'title' boolean (default off, on when title can be restored) + global + {not in Vi} + {not available when compiled without the |+title| + feature} + When on, the title of the window will be set to the value of + 'titlestring' (if it is not empty), or to: + filename [+=-] (path) - VIM + Where: + filename the name of the file being edited + - indicates the file cannot be modified, 'ma' off + + indicates the file was modified + = indicates the file is read-only + =+ indicates the file is read-only and modified + (path) is the path of the file being edited + - VIM the server name |v:servername| or "VIM" + Only works if the terminal supports setting window titles + (currently Amiga console, Win32 console, all GUI versions and + terminals with a non- empty 't_ts' option - these are Unix xterm and + iris-ansi by default, where 't_ts' is taken from the builtin termcap). + *X11* + When Vim was compiled with HAVE_X11 defined, the original title will + be restored if possible. The output of ":version" will include "+X11" + when HAVE_X11 was defined, otherwise it will be "-X11". This also + works for the icon name |'icon'|. + But: When Vim was started with the |-X| argument, restoring the title + will not work (except in the GUI). + If the title cannot be restored, it is set to the value of 'titleold'. + You might want to restore the title outside of Vim then. + When using an xterm from a remote machine you can use this command: + rsh machine_name xterm -display $DISPLAY & + then the WINDOWID environment variable should be inherited and the + title of the window should change back to what it should be after + exiting Vim. + + *'titlelen'* +'titlelen' number (default 85) + global + {not in Vi} + {not available when compiled without the |+title| + feature} + Gives the percentage of 'columns' to use for the length of the window + title. When the title is longer, only the end of the path name is + shown. A '<' character before the path name is used to indicate this. + Using a percentage makes this adapt to the width of the window. But + it won't work perfectly, because the actual number of characters + available also depends on the font used and other things in the title + bar. When 'titlelen' is zero the full path is used. Otherwise, + values from 1 to 30000 percent can be used. + 'titlelen' is also used for the 'titlestring' option. + + *'titleold'* +'titleold' string (default "Thanks for flying Vim") + global + {not in Vi} + {only available when compiled with the |+title| + feature} + This option will be used for the window title when exiting Vim if the + original title cannot be restored. Only happens if 'title' is on or + 'titlestring' is not empty. + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + *'titlestring'* +'titlestring' string (default "") + global + {not in Vi} + {not available when compiled without the |+title| + feature} + When this option is not empty, it will be used for the title of the + window. This happens only when the 'title' option is on. + Only works if the terminal supports setting window titles (currently + Amiga console, Win32 console, all GUI versions and terminals with a + non-empty 't_ts' option). + When Vim was compiled with HAVE_X11 defined, the original title will + be restored if possible |X11|. + When this option contains printf-style '%' items, they will be + expanded according to the rules used for 'statusline'. + Example: > + :auto BufEnter * let &titlestring = hostname() . "/" . expand("%:p") + :set title titlestring=%<%F%=%l/%L-%P titlelen=70 +< The value of 'titlelen' is used to align items in the middle or right + of the available space. + Some people prefer to have the file name first: > + :set titlestring=%t%(\ %M%)%(\ (%{expand(\"%:~:.:h\")})%)%(\ %a%) +< Note the use of "%{ }" and an expression to get the path of the file, + without the file name. The "%( %)" constructs are used to add a + separating space only when needed. + NOTE: Use of special characters in 'titlestring' may cause the display + to be garbled (e.g., when it contains a CR or NL character). + {not available when compiled without the |+statusline| feature} + + *'toolbar'* *'tb'* +'toolbar' 'tb' string (default "icons,tooltips") + global + {only for |+GUI_GTK|, |+GUI_Athena|, |+GUI_Motif| and + |+GUI_Photon|} + The contents of this option controls various toolbar settings. The + possible values are: + icons Toolbar buttons are shown with icons. + text Toolbar buttons shown with text. + horiz Icon and text of a toolbar button are + horizontally arranged. {only in GTK+ 2 GUI} + tooltips Tooltips are active for toolbar buttons. + Tooltips refer to the popup help text which appears after the mouse + cursor is placed over a toolbar button for a brief moment. + + If you want the toolbar to be shown with icons as well as text, do the + following: > + :set tb=icons,text +< Motif and Athena cannot display icons and text at the same time. They + will show icons if both are requested. + + If none of the strings specified in 'toolbar' are valid or if + 'toolbar' is empty, this option is ignored. If you want to disable + the toolbar, you need to set the 'guioptions' option. For example: > + :set guioptions-=T +< Also see |gui-toolbar|. + + *'toolbariconsize'* *'tbis'* +'toolbariconsize' 'tbis' string (default "small") + global + {not in Vi} + {only in the GTK+ 2 GUI} + Controls the size of toolbar icons. The possible values are: + tiny Use tiny toolbar icons. + small Use small toolbar icons (default). + medium Use medium-sized toolbar icons. + large Use large toolbar icons. + The exact dimensions in pixels of the various icon sizes depend on + the current theme. Common dimensions are large=32x32, medium=24x24, + small=20x20 and tiny=16x16. + + If 'toolbariconsize' is empty, the global default size as determined + by user preferences or the current theme is used. + + *'ttybuiltin'* *'tbi'* *'nottybuiltin'* *'notbi'* +'ttybuiltin' 'tbi' boolean (default on) + global + {not in Vi} + When on, the builtin termcaps are searched before the external ones. + When off the builtin termcaps are searched after the external ones. + When this option is changed, you should set the 'term' option next for + the change to take effect, for example: > + :set notbi term=$TERM +< See also |termcap|. + Rationale: The default for this option is "on", because the builtin + termcap entries are generally better (many systems contain faulty + xterm entries...). + + *'ttyfast'* *'tf'* *'nottyfast'* *'notf'* +'ttyfast' 'tf' boolean (default off, on when 'term' is xterm, hpterm, + sun-cmd, screen, rxvt, dtterm or + iris-ansi; also on when running Vim in + a DOS console) + global + {not in Vi} + Indicates a fast terminal connection. More characters will be sent to + the screen for redrawing, instead of using insert/delete line + commands. Improves smoothness of redrawing when there are multiple + windows and the terminal does not support a scrolling region. + Also enables the extra writing of characters at the end of each screen + line for lines that wrap. This helps when using copy/paste with the + mouse in an xterm and other terminals. + + *'ttymouse'* *'ttym'* +'ttymouse' 'ttym' string (default depends on 'term') + global + {not in Vi} + {only in Unix and VMS, doesn't work in the GUI; not + available when compiled without |+mouse|} + Name of the terminal type for which mouse codes are to be recognized. + Currently these strings are valid: + *xterm-mouse* + xterm xterm-like mouse handling. The mouse generates + "[Mscr", where "scr" is three bytes: + "s" = button state + "c" = column plus 33 + "r" = row plus 33 + This only works up to 223 columns! See "dec" for a + solution. + xterm2 Works like "xterm", but with the xterm reporting the + mouse position while the mouse is dragged. This works + much faster and more precise. Your xterm must at + least at patchlevel 88 / XFree 3.3.3 for this to + work. See below for how Vim detects this + automatically. + *netterm-mouse* + netterm NetTerm mouse handling. The mouse generates + "}r,c", where "r,c" are two decimal numbers + for the row and column. + *dec-mouse* + dec DEC terminal mouse handling. The mouse generates a + rather complex sequence, starting with "[". + This is also available for an Xterm, if it was + configured with "--enable-dec-locator". + *jsbterm-mouse* + jsbterm JSB term mouse handling. + *pterm-mouse* + pterm QNX pterm mouse handling. + + The mouse handling must be enabled at compile time |+mouse_xterm| + |+mouse_dec| |+mouse_netterm|. + Only "xterm"(2) is really recognized. NetTerm mouse codes are always + recognized, if enabled at compile time. DEC terminal mouse codes + are recognized if enabled at compile time, and 'ttymouse' is not + "xterm" (because the xterm and dec mouse codes conflict). + This option is automatically set to "xterm", when the 'term' option is + set to a name that starts with "xterm", and 'ttymouse' is not "xterm" + or "xterm2" already. The main use of this option is to set it to + "xterm", when the terminal name doesn't start with "xterm", but it can + handle xterm mouse codes. + The "xterm2" value will be set if the xterm version is reported to be + 95 or higher. This only works when compiled with the |+termresponse| + feature and if |t_RV| is set to the escape sequence to request the + xterm version number. Otherwise "xterm2" must be set explicitly. + If you do not want 'ttymouse' to be set to "xterm2" automatically, set + t_RV to an empty string: > + :set t_RV= +< + *'ttyscroll'* *'tsl'* +'ttyscroll' 'tsl' number (default 999) + global + Maximum number of lines to scroll the screen. If there are more lines + to scroll the window is redrawn. For terminals where scrolling is + very slow and redrawing is not slow this can be set to a small number, + e.g., 3, to speed up displaying. + + *'ttytype'* *'tty'* +'ttytype' 'tty' string (default from $TERM) + global + Alias for 'term', see above. + + *'undodir'* *'udir'* +'undodir' 'udir' string (default ".") + global + {not in Vi} + {only when compiled with the |+persistent_undo| feature} + List of directory names for undo files, separated with commas. + See |'backupdir'| for details of the format. + "." means using the directory of the file. The undo file name for + "file.txt" is ".file.txt.un~". + For other directories the file name is the full path of the edited + file, with path separators replaced with "%". + When writing: The first directory that exists is used. "." always + works, no directories after "." will be used for writing. + When reading all entries are tried to find an undo file. The first + undo file that exists is used. When it cannot be read an error is + given, no further entry is used. + See |undo-persistence|. + + *'undofile'* *'udf'* +'undofile' 'udf' boolean (default off) + local to buffer + {not in Vi} + {only when compiled with the |+persistent_undo| feature} + When on, Vim automatically saves undo history to an undo file when + writing a buffer to a file, and restores undo history from the same + file on buffer read. + The directory where the undo file is stored is specified by 'undodir'. + For more information about this feature see |undo-persistence|. + The undo file is not read when 'undoreload' causes the buffer from + before a reload to be saved for undo. + WARNING: this is a very new feature. Use at your own risk! + + *'undolevels'* *'ul'* +'undolevels' 'ul' number (default 100, 1000 for Unix, VMS, + Win32 and OS/2) + global + {not in Vi} + Maximum number of changes that can be undone. Since undo information + is kept in memory, higher numbers will cause more memory to be used + (nevertheless, a single change can use an unlimited amount of memory). + Set to 0 for Vi compatibility: One level of undo and "u" undoes + itself: > + set ul=0 +< But you can also get Vi compatibility by including the 'u' flag in + 'cpoptions', and still be able to use CTRL-R to repeat undo. + Also see |undo-two-ways|. + Set to a negative number for no undo at all: > + set ul=-1 +< This helps when you run out of memory for a single change. + Also see |clear-undo|. + + *'undoreload'* *'ur'* +'undoreload' 'ur' number (default 10000) + global + {not in Vi} + Save the whole buffer for undo when reloading it. This applies to the + ":e!" command and reloading for when the buffer changed outside of + Vim. |FileChangedShell| + The save only happens when this options is negative or when the number + of lines is smaller than the value of this option. + Set this option to zero to disable undo for a reload. + + When saving undo for a reload, any undo file is not read. + + Note that this causes the whole buffer to be stored in memory. Set + this option to a lower value if you run out of memory. + + *'updatecount'* *'uc'* +'updatecount' 'uc' number (default: 200) + global + {not in Vi} + After typing this many characters the swap file will be written to + disk. When zero, no swap file will be created at all (see chapter on + recovery |crash-recovery|). 'updatecount' is set to zero by starting + Vim with the "-n" option, see |startup|. When editing in readonly + mode this option will be initialized to 10000. + The swapfile can be disabled per buffer with |'swapfile'|. + When 'updatecount' is set from zero to non-zero, swap files are + created for all buffers that have 'swapfile' set. When 'updatecount' + is set to zero, existing swap files are not deleted. + Also see |'swapsync'|. + This option has no meaning in buffers where |'buftype'| is "nofile" + or "nowrite". + + *'updatetime'* *'ut'* +'updatetime' 'ut' number (default 4000) + global + {not in Vi} + If this many milliseconds nothing is typed the swap file will be + written to disk (see |crash-recovery|). Also used for the + |CursorHold| autocommand event. + + *'verbose'* *'vbs'* +'verbose' 'vbs' number (default 0) + global + {not in Vi, although some versions have a boolean + verbose option} + When bigger than zero, Vim will give messages about what it is doing. + Currently, these messages are given: + >= 1 When the viminfo file is read or written. + >= 2 When a file is ":source"'ed. + >= 5 Every searched tags file and include file. + >= 8 Files for which a group of autocommands is executed. + >= 9 Every executed autocommand. + >= 12 Every executed function. + >= 13 When an exception is thrown, caught, finished, or discarded. + >= 14 Anything pending in a ":finally" clause. + >= 15 Every executed Ex command (truncated at 200 characters). + + This option can also be set with the "-V" argument. See |-V|. + This option is also set by the |:verbose| command. + + When the 'verbosefile' option is set then the verbose messages are not + displayed. + + *'verbosefile'* *'vfile'* +'verbosefile' 'vfile' string (default empty) + global + {not in Vi} + When not empty all messages are written in a file with this name. + When the file exists messages are appended. + Writing to the file ends when Vim exits or when 'verbosefile' is made + empty. Writes are buffered, thus may not show up for some time. + Setting 'verbosefile' to a new value is like making it empty first. + The difference with |:redir| is that verbose messages are not + displayed when 'verbosefile' is set. + + *'viewdir'* *'vdir'* +'viewdir' 'vdir' string (default for Amiga, MS-DOS, OS/2 and Win32: + "$VIM/vimfiles/view", + for Unix: "~/.vim/view", + for Macintosh: "$VIM:vimfiles:view" + for VMS: "sys$login:vimfiles/view" + for RiscOS: "Choices:vimfiles/view") + global + {not in Vi} + {not available when compiled without the |+mksession| + feature} + Name of the directory where to store files for |:mkview|. + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + *'viewoptions'* *'vop'* +'viewoptions' 'vop' string (default: "folds,options,cursor") + global + {not in Vi} + {not available when compiled without the |+mksession| + feature} + Changes the effect of the |:mkview| command. It is a comma separated + list of words. Each word enables saving and restoring something: + word save and restore ~ + cursor cursor position in file and in window + folds manually created folds, opened/closed folds and local + fold options + options options and mappings local to a window or buffer (not + global values for local options) + slash backslashes in file names replaced with forward + slashes + unix with Unix end-of-line format (single ), even when + on Windows or DOS + + "slash" and "unix" are useful on Windows when sharing view files + with Unix. The Unix version of Vim cannot source dos format scripts, + but the Windows version of Vim can source unix format scripts. + + *'viminfo'* *'vi'* *E526* *E527* *E528* +'viminfo' 'vi' string (Vi default: "", Vim default for MS-DOS, + Windows and OS/2: '100,<50,s10,h,rA:,rB:, + for Amiga: '100,<50,s10,h,rdf0:,rdf1:,rdf2: + for others: '100,<50,s10,h) + global + {not in Vi} + {not available when compiled without the |+viminfo| + feature} + When non-empty, the viminfo file is read upon startup and written + when exiting Vim (see |viminfo-file|). The string should be a comma + separated list of parameters, each consisting of a single character + identifying the particular parameter, followed by a number or string + which specifies the value of that parameter. If a particular + character is left out, then the default value is used for that + parameter. The following is a list of the identifying characters and + the effect of their value. + CHAR VALUE ~ + ! When included, save and restore global variables that start + with an uppercase letter, and don't contain a lowercase + letter. Thus "KEEPTHIS and "K_L_M" are stored, but "KeepThis" + and "_K_L_M" are not. Nested List and Dict items may not be + read back correctly, you end up with a string representation + instead. + " Maximum number of lines saved for each register. Old name of + the '<' item, with the disadvantage that you need to put a + backslash before the ", otherwise it will be recognized as the + start of a comment! + % When included, save and restore the buffer list. If Vim is + started with a file name argument, the buffer list is not + restored. If Vim is started without a file name argument, the + buffer list is restored from the viminfo file. Buffers + without a file name and buffers for help files are not written + to the viminfo file. + When followed by a number, the number specifies the maximum + number of buffers that are stored. Without a number all + buffers are stored. + ' Maximum number of previously edited files for which the marks + are remembered. This parameter must always be included when + 'viminfo' is non-empty. + Including this item also means that the |jumplist| and the + |changelist| are stored in the viminfo file. + / Maximum number of items in the search pattern history to be + saved. If non-zero, then the previous search and substitute + patterns are also saved. When not included, the value of + 'history' is used. + : Maximum number of items in the command-line history to be + saved. When not included, the value of 'history' is used. + < Maximum number of lines saved for each register. If zero then + registers are not saved. When not included, all lines are + saved. '"' is the old name for this item. + Also see the 's' item below: limit specified in Kbyte. + @ Maximum number of items in the input-line history to be + saved. When not included, the value of 'history' is used. + c When included, convert the text in the viminfo file from the + 'encoding' used when writing the file to the current + 'encoding'. See |viminfo-encoding|. + f Whether file marks need to be stored. If zero, file marks ('0 + to '9, 'A to 'Z) are not stored. When not present or when + non-zero, they are all stored. '0 is used for the current + cursor position (when exiting or when doing ":wviminfo"). + h Disable the effect of 'hlsearch' when loading the viminfo + file. When not included, it depends on whether ":nohlsearch" + has been used since the last search command. + n Name of the viminfo file. The name must immediately follow + the 'n'. Must be the last one! If the "-i" argument was + given when starting Vim, that file name overrides the one + given here with 'viminfo'. Environment variables are expanded + when opening the file, not when setting the option. + r Removable media. The argument is a string (up to the next + ','). This parameter can be given several times. Each + specifies the start of a path for which no marks will be + stored. This is to avoid removable media. For MS-DOS you + could use "ra:,rb:", for Amiga "rdf0:,rdf1:,rdf2:". You can + also use it for temp files, e.g., for Unix: "r/tmp". Case is + ignored. Maximum length of each 'r' argument is 50 + characters. + s Maximum size of an item in Kbyte. If zero then registers are + not saved. Currently only applies to registers. The default + "s10" will exclude registers with more than 10 Kbyte of text. + Also see the '<' item above: line count limit. + + Example: > + :set viminfo='50,<1000,s100,:0,n~/vim/viminfo +< + '50 Marks will be remembered for the last 50 files you + edited. + <1000 Contents of registers (up to 1000 lines each) will be + remembered. + s100 Registers with more than 100 Kbyte text are skipped. + :0 Command-line history will not be saved. + n~/vim/viminfo The name of the file to use is "~/vim/viminfo". + no / Since '/' is not specified, the default will be used, + that is, save all of the search history, and also the + previous search and substitute patterns. + no % The buffer list will not be saved nor read back. + no h 'hlsearch' highlighting will be restored. + + When setting 'viminfo' from an empty value you can use |:rviminfo| to + load the contents of the file, this is not done automatically. + + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + + *'virtualedit'* *'ve'* +'virtualedit' 've' string (default "") + global + {not in Vi} + {not available when compiled without the + |+virtualedit| feature} + A comma separated list of these words: + block Allow virtual editing in Visual block mode. + insert Allow virtual editing in Insert mode. + all Allow virtual editing in all modes. + onemore Allow the cursor to move just past the end of the line + + Virtual editing means that the cursor can be positioned where there is + no actual character. This can be halfway into a tab or beyond the end + of the line. Useful for selecting a rectangle in Visual mode and + editing a table. + "onemore" is not the same, it will only allow moving the cursor just + after the last character of the line. This makes some commands more + consistent. Previously the cursor was always past the end of the line + if the line was empty. But it is far from Vi compatible. It may also + break some plugins or Vim scripts. For example because |l| can move + the cursor after the last character. Use with care! + Using the |$| command will move to the last character in the line, not + past it. This may actually move the cursor to the left! + It doesn't make sense to combine "all" with "onemore", but you will + not get a warning for it. + + *'visualbell'* *'vb'* *'novisualbell'* *'novb'* *beep* +'visualbell' 'vb' boolean (default off) + global + {not in Vi} + Use visual bell instead of beeping. The terminal code to display the + visual bell is given with 't_vb'. When no beep or flash is wanted, + use ":set vb t_vb=". + Note: When the GUI starts, 't_vb' is reset to its default value. You + might want to set it again in your |gvimrc|. + In the GUI, 't_vb' defaults to "|f", which inverts the display + for 20 msec. If you want to use a different time, use "|40f", + where 40 is the time in msec. + Does not work on the Amiga, you always get a screen flash. + Also see 'errorbells'. + + *'warn'* *'nowarn'* +'warn' boolean (default on) + global + Give a warning message when a shell command is used while the buffer + has been changed. + + *'weirdinvert'* *'wiv'* *'noweirdinvert'* *'nowiv'* +'weirdinvert' 'wiv' boolean (default off) + global + {not in Vi} + This option has the same effect as the 't_xs' terminal option. + It is provided for backwards compatibility with version 4.x. + Setting 'weirdinvert' has the effect of making 't_xs' non-empty, and + vice versa. Has no effect when the GUI is running. + + *'whichwrap'* *'ww'* +'whichwrap' 'ww' string (Vim default: "b,s", Vi default: "") + global + {not in Vi} + Allow specified keys that move the cursor left/right to move to the + previous/next line when the cursor is on the first/last character in + the line. Concatenate characters to allow this for these keys: + char key mode ~ + b Normal and Visual + s Normal and Visual + h "h" Normal and Visual (not recommended) + l "l" Normal and Visual (not recommended) + < Normal and Visual + > Normal and Visual + ~ "~" Normal + [ Insert and Replace + ] Insert and Replace + For example: > + :set ww=<,>,[,] +< allows wrap only when cursor keys are used. + When the movement keys are used in combination with a delete or change + operator, the also counts for a character. This makes "3h" + different from "3dh" when the cursor crosses the end of a line. This + is also true for "x" and "X", because they do the same as "dl" and + "dh". If you use this, you may also want to use the mapping + ":map X" to make backspace delete the character in front of the + cursor. + When 'l' is included and it is used after an operator at the end of a + line then it will not move to the next line. This makes "dl", "cl", + "yl" etc. work normally. + NOTE: This option is set to the Vi default value when 'compatible' is + set and to the Vim default value when 'compatible' is reset. + + *'wildchar'* *'wc'* +'wildchar' 'wc' number (Vim default: , Vi default: CTRL-E) + global + {not in Vi} + Character you have to type to start wildcard expansion in the + command-line, as specified with 'wildmode'. + More info here: |cmdline-completion|. + The character is not recognized when used inside a macro. See + 'wildcharm' for that. + Although 'wc' is a number option, you can set it to a special key: > + :set wc= +< NOTE: This option is set to the Vi default value when 'compatible' is + set and to the Vim default value when 'compatible' is reset. + + *'wildcharm'* *'wcm'* +'wildcharm' 'wcm' number (default: none (0)) + global + {not in Vi} + 'wildcharm' works exactly like 'wildchar', except that it is + recognized when used inside a macro. You can find "spare" command-line + keys suitable for this option by looking at |ex-edit-index|. Normally + you'll never actually type 'wildcharm', just use it in mappings that + automatically invoke completion mode, e.g.: > + :set wcm= + :cnoremap ss so $vim/sessions/*.vim +< Then after typing :ss you can use CTRL-P & CTRL-N. + + *'wildignore'* *'wig'* +'wildignore' 'wig' string (default "") + global + {not in Vi} + {not available when compiled without the |+wildignore| + feature} + A list of file patterns. A file that matches with one of these + patterns is ignored when completing file or directory names, and + influences the result of |expand()|, |glob()| and |globpath()| unless + a flag is passed to disable this. + The pattern is used like with |:autocmd|, see |autocmd-patterns|. + Also see 'suffixes'. + Example: > + :set wildignore=*.o,*.obj +< The use of |:set+=| and |:set-=| is preferred when adding or removing + a pattern from the list. This avoids problems when a future version + uses another default. + + + *'wildignorecase* *'wic'* *'nowildignorecase* *'nowic'* +'wildignorecase' 'wic' boolean (default off) + global + {not in Vi} + When set case is ignored when completing file names and directories. + Has no effect on systems where file name case is generally ignored. + Does not apply when the shell is used to expand wildcards, which + happens when there are special characters. + + + *'wildmenu'* *'wmnu'* *'nowildmenu'* *'nowmnu'* +'wildmenu' 'wmnu' boolean (default off) + global + {not in Vi} + {not available if compiled without the |+wildmenu| + feature} + When 'wildmenu' is on, command-line completion operates in an enhanced + mode. On pressing 'wildchar' (usually ) to invoke completion, + the possible matches are shown just above the command line, with the + first match highlighted (overwriting the status line, if there is + one). Keys that show the previous/next match, such as or + CTRL-P/CTRL-N, cause the highlight to move to the appropriate match. + When 'wildmode' is used, "wildmenu" mode is used where "full" is + specified. "longest" and "list" do not start "wildmenu" mode. + If there are more matches than can fit in the line, a ">" is shown on + the right and/or a "<" is shown on the left. The status line scrolls + as needed. + The "wildmenu" mode is abandoned when a key is hit that is not used + for selecting a completion. + While the "wildmenu" is active the following keys have special + meanings: + + - select previous/next match (like CTRL-P/CTRL-N) + - in filename/menu name completion: move into a + subdirectory or submenu. + - in menu completion, when the cursor is just after a + dot: move into a submenu. + - in filename/menu name completion: move up into + parent directory or parent menu. + + This makes the menus accessible from the console |console-menus|. + + If you prefer the and keys to move the cursor instead + of selecting a different match, use this: > + :cnoremap + :cnoremap +< + The "WildMenu" highlighting is used for displaying the current match + |hl-WildMenu|. + + *'wildmode'* *'wim'* +'wildmode' 'wim' string (Vim default: "full") + global + {not in Vi} + Completion mode that is used for the character specified with + 'wildchar'. It is a comma separated list of up to four parts. Each + part specifies what to do for each consecutive use of 'wildchar'. The + first part specifies the behavior for the first use of 'wildchar', + The second part for the second use, etc. + These are the possible values for each part: + "" Complete only the first match. + "full" Complete the next full match. After the last match, + the original string is used and then the first match + again. + "longest" Complete till longest common string. If this doesn't + result in a longer string, use the next part. + "longest:full" Like "longest", but also start 'wildmenu' if it is + enabled. + "list" When more than one match, list all matches. + "list:full" When more than one match, list all matches and + complete first match. + "list:longest" When more than one match, list all matches and + complete till longest common string. + When there is only a single match, it is fully completed in all cases. + + Examples: > + :set wildmode=full +< Complete first full match, next match, etc. (the default) > + :set wildmode=longest,full +< Complete longest common string, then each full match > + :set wildmode=list:full +< List all matches and complete each full match > + :set wildmode=list,full +< List all matches without completing, then each full match > + :set wildmode=longest,list +< Complete longest common string, then list alternatives. + More info here: |cmdline-completion|. + + *'wildoptions'* *'wop'* +'wildoptions' 'wop' string (default "") + global + {not in Vi} + {not available when compiled without the |+wildignore| + feature} + A list of words that change how command line completion is done. + Currently only one word is allowed: + tagfile When using CTRL-D to list matching tags, the kind of + tag and the file of the tag is listed. Only one match + is displayed per line. Often used tag kinds are: + d #define + f function + Also see |cmdline-completion|. + + *'winaltkeys'* *'wak'* +'winaltkeys' 'wak' string (default "menu") + global + {not in Vi} + {only used in Win32, Motif, GTK and Photon GUI} + Some GUI versions allow the access to menu entries by using the ALT + key in combination with a character that appears underlined in the + menu. This conflicts with the use of the ALT key for mappings and + entering special characters. This option tells what to do: + no Don't use ALT keys for menus. ALT key combinations can be + mapped, but there is no automatic handling. This can then be + done with the |:simalt| command. + yes ALT key handling is done by the windowing system. ALT key + combinations cannot be mapped. + menu Using ALT in combination with a character that is a menu + shortcut key, will be handled by the windowing system. Other + keys can be mapped. + If the menu is disabled by excluding 'm' from 'guioptions', the ALT + key is never used for the menu. + This option is not used for ; on Win32 and with GTK will + select the menu, unless it has been mapped. + + *'window'* *'wi'* +'window' 'wi' number (default screen height - 1) + global + Window height. Do not confuse this with the height of the Vim window, + use 'lines' for that. + Used for |CTRL-F| and |CTRL-B| when there is only one window and the + value is smaller than 'lines' minus one. The screen will scroll + 'window' minus two lines, with a minimum of one. + When 'window' is equal to 'lines' minus one CTRL-F and CTRL-B scroll + in a much smarter way, taking care of wrapping lines. + When resizing the Vim window, the value is smaller than 1 or more than + or equal to 'lines' it will be set to 'lines' minus 1. + {Vi also uses the option to specify the number of displayed lines} + + *'winheight'* *'wh'* *E591* +'winheight' 'wh' number (default 1) + global + {not in Vi} + {not available when compiled without the |+windows| + feature} + Minimal number of lines for the current window. This is not a hard + minimum, Vim will use fewer lines if there is not enough room. If the + focus goes to a window that is smaller, its size is increased, at the + cost of the height of other windows. + Set 'winheight' to a small number for normal editing. + Set it to 999 to make the current window fill most of the screen. + Other windows will be only 'winminheight' high. This has the drawback + that ":all" will create only two windows. To avoid "vim -o 1 2 3 4" + to create only two windows, set the option after startup is done, + using the |VimEnter| event: > + au VimEnter * set winheight=999 +< Minimum value is 1. + The height is not adjusted after one of the commands that change the + height of the current window. + 'winheight' applies to the current window. Use 'winminheight' to set + the minimal height for other windows. + + *'winfixheight'* *'wfh'* *'nowinfixheight'* *'nowfh'* +'winfixheight' 'wfh' boolean (default off) + local to window + {not in Vi} + {not available when compiled without the |+windows| + feature} + Keep the window height when windows are opened or closed and + 'equalalways' is set. Also for |CTRL-W_=|. Set by default for the + |preview-window| and |quickfix-window|. + The height may be changed anyway when running out of room. + + *'winfixwidth'* *'wfw'* *'nowinfixwidth'* *'nowfw'* +'winfixwidth' 'wfw' boolean (default off) + local to window + {not in Vi} + {not available when compiled without the |+windows| + feature} + Keep the window width when windows are opened or closed and + 'equalalways' is set. Also for |CTRL-W_=|. + The width may be changed anyway when running out of room. + + *'winminheight'* *'wmh'* +'winminheight' 'wmh' number (default 1) + global + {not in Vi} + {not available when compiled without the |+windows| + feature} + The minimal height of a window, when it's not the current window. + This is a hard minimum, windows will never become smaller. + When set to zero, windows may be "squashed" to zero lines (i.e. just a + status bar) if necessary. They will return to at least one line when + they become active (since the cursor has to have somewhere to go.) + Use 'winheight' to set the minimal height of the current window. + This option is only checked when making a window smaller. Don't use a + large number, it will cause errors when opening more than a few + windows. A value of 0 to 3 is reasonable. + + *'winminwidth'* *'wmw'* +'winminwidth' 'wmw' number (default 1) + global + {not in Vi} + {not available when compiled without the |+vertsplit| + feature} + The minimal width of a window, when it's not the current window. + This is a hard minimum, windows will never become smaller. + When set to zero, windows may be "squashed" to zero columns (i.e. just + a vertical separator) if necessary. They will return to at least one + line when they become active (since the cursor has to have somewhere + to go.) + Use 'winwidth' to set the minimal width of the current window. + This option is only checked when making a window smaller. Don't use a + large number, it will cause errors when opening more than a few + windows. A value of 0 to 12 is reasonable. + + *'winwidth'* *'wiw'* *E592* +'winwidth' 'wiw' number (default 20) + global + {not in Vi} + {not available when compiled without the |+vertsplit| + feature} + Minimal number of columns for the current window. This is not a hard + minimum, Vim will use fewer columns if there is not enough room. If + the current window is smaller, its size is increased, at the cost of + the width of other windows. Set it to 999 to make the current window + always fill the screen. Set it to a small number for normal editing. + The width is not adjusted after one of the commands to change the + width of the current window. + 'winwidth' applies to the current window. Use 'winminwidth' to set + the minimal width for other windows. + + *'wrap'* *'nowrap'* +'wrap' boolean (default on) + local to window + {not in Vi} + This option changes how text is displayed. It doesn't change the text + in the buffer, see 'textwidth' for that. + When on, lines longer than the width of the window will wrap and + displaying continues on the next line. When off lines will not wrap + and only part of long lines will be displayed. When the cursor is + moved to a part that is not shown, the screen will scroll + horizontally. + The line will be broken in the middle of a word if necessary. See + 'linebreak' to get the break at a word boundary. + To make scrolling horizontally a bit more useful, try this: > + :set sidescroll=5 + :set listchars+=precedes:<,extends:> +< See 'sidescroll', 'listchars' and |wrap-off|. + This option can't be set from a |modeline| when the 'diff' option is + on. + + *'wrapmargin'* *'wm'* +'wrapmargin' 'wm' number (default 0) + local to buffer + Number of characters from the right window border where wrapping + starts. When typing text beyond this limit, an will be inserted + and inserting continues on the next line. + Options that add a margin, such as 'number' and 'foldcolumn', cause + the text width to be further reduced. This is Vi compatible. + When 'textwidth' is non-zero, this option is not used. + See also 'formatoptions' and |ins-textwidth|. {Vi: works differently + and less usefully} + + *'wrapscan'* *'ws'* *'nowrapscan'* *'nows'* +'wrapscan' 'ws' boolean (default on) *E384* *E385* + global + Searches wrap around the end of the file. Also applies to |]s| and + |[s|, searching for spelling mistakes. + + *'write'* *'nowrite'* +'write' boolean (default on) + global + {not in Vi} + Allows writing files. When not set, writing a file is not allowed. + Can be used for a view-only mode, where modifications to the text are + still allowed. Can be reset with the |-m| or |-M| command line + argument. Filtering text is still possible, even though this requires + writing a temporary file. + + *'writeany'* *'wa'* *'nowriteany'* *'nowa'* +'writeany' 'wa' boolean (default off) + global + Allows writing to any file with no need for "!" override. + + *'writebackup'* *'wb'* *'nowritebackup'* *'nowb'* +'writebackup' 'wb' boolean (default on with |+writebackup| feature, off + otherwise) + global + {not in Vi} + Make a backup before overwriting a file. The backup is removed after + the file was successfully written, unless the 'backup' option is + also on. Reset this option if your file system is almost full. See + |backup-table| for another explanation. + When the 'backupskip' pattern matches, a backup is not made anyway. + NOTE: This option is set to the default value when 'compatible' is + set. + + *'writedelay'* *'wd'* +'writedelay' 'wd' number (default 0) + global + {not in Vi} + The number of microseconds to wait for each character sent to the + screen. When non-zero, characters are sent to the terminal one by + one. For MS-DOS pcterm this does not work. For debugging purposes. + + vim:tw=78:ts=8:ft=help:norl: diff -Naur vim73.orig/runtime/doc/os_risc.txt vim73/runtime/doc/os_risc.txt --- vim73.orig/runtime/doc/os_risc.txt 2010-08-15 12:23:21.000000000 +0000 +++ vim73/runtime/doc/os_risc.txt 2012-07-20 20:31:10.844306469 +0000 @@ -1,322 +1,12 @@ -*os_risc.txt* For Vim version 7.3. Last change: 2010 Aug 07 +*os_risc.txt* For Vim version 7.3. Last change: 2011 May 10 VIM REFERENCE MANUAL by Thomas Leonard *riscos* *RISCOS* *RISC-OS* -This file contains the particularities for the RISC OS version of Vim. +The RISC OS support has been removed from Vim with patch 7.3.187. +If you would like to use Vim on RISC OS get the files from before that patch. -The RISC OS port is a completely new port and is not based on the old "archi" -port. -1. File locations |riscos-locations| -2. Filename munging |riscos-munging| -3. Command-line use |riscos-commandline| -4. Desktop (GUI) use |riscos-gui| -5. Remote use (telnet) |riscos-remote| -6. Temporary files |riscos-temp-files| -7. Interrupting |riscos-interrupt| -8. Memory usage |riscos-memory| -9. Filetypes |riscos-filetypes| -10. The shell |riscos-shell| -11. Porting new releases |riscos-porting| - -If I've missed anything, email me and I'll try to fix it. In fact, even if I -haven't missed anything then email me anyway to give me some confidence that it -actually works! - -Thomas Leonard - - [these URLs no longer work...] - Port homepage: http://www.ecs.soton.ac.uk/~tal197/ - or try: http://www.soton.ac.uk/~tal197/ - -============================================================================== - *riscos-locations* -1. File locations - -The Vim executable and shared resource files are all stored inside the !Vim -application directory. - -When !Vim is first seen by the filer, it aliases the *vi and *ex commands to -run the command-line versions of Vim (see |riscos-commandline|). - -!Vim.Resources and !Vim.Resources2 contain the files from the standard Vim -distribution, but modified slightly to work within the limits of ADFS, plus -some extra files such as the window templates. - -User choices are read from "Choices:*" and are saved to ".*". -If you have the new !Boot structure then these should be set up already. If -not, set Choices$Path to a list of directories to search when looking for -user configuration files. Set Choices$Write to the directory you want files -to be saved into (so your search patterns and marks can be remembered between -sessions). - -============================================================================== - *riscos-munging* -2. Filename munging - -All pathname munging is disabled by default, so Vim should behave like a -normal RISC OS application now. So, if you want to edit "doc/html" then you -actually type "*vi doc/html". - -The only times munging is done is when: - -- Searching included files from C programs, since these are always munged. - See |[I|. - Note: make sure you are in the right directory when you use this - command (i.e. the one with subdirectories "c" and "h"). - -- Sourcing files using |:so|. - Paths starting "$VIM/" are munged like this: - - $VIM/syntax/help.vim -> Vim:syntax.help - - Also, files ending in ".vim" have their extensions removed, and slashes - replaced with dots. - -Some tag files and script files may have to be edited to work under this port. - -============================================================================== - *riscos-commandline* -3. Command-line use - -To use Vim from the command-line use the "*vi" command (or "*ex" for -|Ex-mode|). - -Type "*vi -h" for a list of options. - -Running the command-line version of Vim in a large high-color mode may cause -the scrolling to be very slow. Either change to a mode with fewer colors or -use the GUI version. - -Also, holding down Ctrl will slow it down even more, and Ctrl-Shift will -freeze it, as usual for text programs. - -============================================================================== - *riscos-gui* -4. Desktop use - -Limitations: - -- Left scrollbars don't work properly (right and bottom are fine). -- Doesn't increase scroll speed if it gets behind. - -You can resize the window by dragging the lower-right corner, even though -there is no icon shown there. - -You can use the --rows and --columns arguments to specify the initial size of -the Vim window, like this: > - - *Vi -g --rows 20 --columns 80 - -The global clipboard is supported, so you can select some text and then -paste it directly into another application (provided it supports the -clipboard too). - -Clicking Menu now opens a menu like a normal RISC OS program. Hold down Shift -when clicking Menu to paste (from the global clipboard). - -Dragging a file to the window replaces the CURRENT buffer (the one with the -cursor, NOT the one you dragged to) with the file. - -Dragging with Ctrl held down causes a new Vim window to be opened for the -file (see |:sp|). - -Dragging a file in with Shift held down in insert mode inserts the pathname of -the file. - -:browse :w opens a standard RISC OS save box. -:browse :e opens a directory viewer. - -For fonts, you have the choice of the system font, an outline font, the system -font via ZapRedraw and any of the Zap fonts via ZapRedraw: > - - :set guifont= -< To use the system font via the VDU drivers. Supports - bold and underline. -> - :set guifont=Corpus.Medium -< Use the named outline font. You can use any font, but - only monospaced ones like Corpus look right. -> - :set guifont=Corpus.Medium:w8:h12:b:i -< As before, but with size of 8 point by 12 point, and - in bold italic. - If only one of width and height is given then that - value is used for both. If neither is given then 10 - point is used. - -Thanks to John Kortink, Vim can use the ZapRedraw module. Start the font name -with "!" (or "!!" for double height), like this: > - - :set guifont=!! -< Use the system font, but via ZapRedraw. This gives a - faster redraw on StrongARM processors, but you can't - get bold or italic text. Double height. -> - :set guifont=!script -< Uses the named Zap font (a directory in VimFont$Path). - The redraw is the same speed as for "!!", but you get - a nicer looking font. - Only the "man+" and "script" fonts are supplied - currently, but you can use any of the Zap fonts if - they are in VimFont$Path. - Vim will try to load font files "0", "B", "I" and "IB" - from the named directory. Only "0" (normal style) MUST - be present. Link files are not currently supported. - -Note that when using ZapRedraw the edit bar is drawn in front of the character -you are on rather than behind it. Also redraw is incorrect for screen modes -with eigen values of 0. If the font includes control characters then you can -get Vim to display them by changing the 'isprint' option. - -If you find the scrolling is too slow on your machine, try experimenting -with the 'scrolljump' and 'ttyscroll' options. - -In particular, StrongARM users may find that: > - - :set ttyscroll=0 - -makes scrolling faster in high-color modes. - -============================================================================= - *riscos-remote* -5. Remote use (telnet) - -I have included a built-in termcap entry, but you can edit the termcap file to -allow other codes to be used if you want to use Vim from a remote terminal. - -Although I do not have an internet connection to my Acorn, I have managed to -run Vim in a FreeTerm window using the loopback connection. - -It seems to work pretty well now, using "*vi -T ansi". - -============================================================================== - *riscos-temp-files* -6. Temporary files - -If Vim crashes then the swap and backup files (if any) will be in the -directories set with the 'directory' and 'bdir' options. By default the swap -files are in (i.e. inside !Scrap) and backups are in the -directory you were saving to. Vim will allow you to try and recover the file -when you next try to edit it. - -To see a list of swap files, press and type "*vi -r". - -Vim no longer brings up ATTENTION warnings if you try to edit two files with -the same name in different directories. - -However, it also no longer warns if you try to edit the same file twice (with -two copies of Vim), though you will still be warned when you save that the -datestamp has changed. - -============================================================================== - *riscos-interrupt* -7. Interrupting - -To break out of a looping macro, or similar, hold down Escape in the -command-line version, or press CTRL-C in the GUI version. - -============================================================================== - *riscos-memory* -8. Memory usage - -Vim will use dynamic areas on RISC OS 3.5 or later. If you can use them on -older machines then edit the !RunTxt and GVim files. I don't know what UnixLib -does by default on these machines so I'm playing safe. - -It doesn't work at all well without dynamic areas, since it can't change its -memory allocation once running. Hence you should edit "!Vim.GVim" and -"!Vim.!RunTxt" to choose the best size for you. You probably need at least -about 1400K. - -============================================================================== - *riscos-filetypes* -9. Filetypes - -You can now specify that autocommands are only executed for files of certain -types. The filetype is given in the form &xxx, when xxx is the filetype. - -Filetypes must be specified by number (e.g. &fff for Text). - -The system has changed from version 5.3. The new sequence of events is: - -- A file is loaded. |'osfiletype'| is set to the RISC OS filetype. -- Based on the filetype and pathname, Vim will try to set |'filetype'| to the - Vim-type of the file. -- Setting this option may load syntax files and perform other actions. -- Saving the file will give it a filetype of |'osfiletype'|. - -Some examples may make this clearer: - - Kind of file loaded osfiletype filetype ~ - C code "c.hellow" Text (&fff) C - LaTeX document LaTeX (&2a8) TeX - Draw document DrawFile (&aff) (not changed) - -============================================================================== - *riscos-shell* -10. The shell - -- Bangs (!s) are only replaced if they are followed by a space or end-of-line, - since many pathnames contain them. - -- You can prefix the command with "~", which stops any output from being - displayed. This also means that you don't have to press afterwards, - and stops the screen from being redrawn. {only in the GUI version} - -============================================================================== - *riscos-porting* -11. Porting new releases to RISC OS - -Downloading everything you need: - -- Get the latest source distribution (see www.vim.org) -- Get the runtime environment files (e.g. these help files) -- Get the RISC OS binary distribution (if possible) - - -Unarchiving: - -- Create a raFS disk and put the archives on it -- Un-gzip them -- Un-tar them (*tar xELf 50 archive/tar) - - -Recompiling the sources: - -- Create c, s, and h directories. -- Put all the header files in "h". \ -- Put all the C files in "c". | And lose the extensions -- Put the assembler file ("swis/s") in "s". / -- Rename all the files in "proto" to "h", like this: - raFS::VimSrc.source.proto.file/pro - becomes - raFS::VimSrc.source.h.file_pro -- In the files "h.proto" and "c.termlib", search and replace - .pro" - with - _pro.h" -- Create a simple Makefile if desired and do "*make -k". - Use "CC = gcc -DRISCOS -DUSE_GUI -O2 -x c" in the Makefile. -- Save the binary as !Vim.Vim in the binary distribution. - - -Updating the run-time environment: - -- Replace old or missing files inside !Vim.Resources with the - new files. -- Remove files in "doc" not ending in "/txt", except for "tags". -- Lose the extensions from the files in "doc". -- Edit the "doc.tags" file. Remove extensions from the second column: > - :%s/^\(.[^\t]*\t.*\)\.txt\t/\1\t/ -- Remove extensions from the syntax files. Split them into two directories - to avoid the 77 entry limit on old ADFS filesystems. -- Edit "Vim:FileType" to match "*.c.*" as well as "*/c" and so on. - Add filetype checking too. -- Edit "Vim:Menu" and remove all the keys from the menus: > - :%s/[^ \t]*// -< vim:tw=78:ts=8:ft=help:norl: diff -Naur vim73.orig/runtime/doc/os_win32.txt vim73/runtime/doc/os_win32.txt --- vim73.orig/runtime/doc/os_win32.txt 2010-08-15 12:23:21.000000000 +0000 +++ vim73/runtime/doc/os_win32.txt 2012-07-20 20:31:11.650973718 +0000 @@ -313,6 +313,37 @@ with :!start do not get passed Vim's open file handles, which means they do not have to be closed before Vim. To avoid this special treatment, use ":! start". + There are two optional arguments (see the next Q): + /min the window will be minimized. + /b" no console window will be opened + You can only one of these flags at a time. A second second one will be + treated as the start of the command. + +Q. How do I avoid getting a window for programs that I run asynchronously? +A. You have two possible solutions depending on what exactly do you want: + 1) You may use the /min flag in order to run program in a minimized state + with no other changes. It will work equally for console and GUI + applications. + 2) You can use the /b flag to run console applications without creating a + console window for them (GUI applications are not affected). But you + should use this flag only if the application you run doesn't require any + input. Otherwise it will get an EOF error because its input stream + (stdin) would be redirected to \\.\NUL (stdoud and stderr too). + + Example for a console application, run Exuberant ctags: > + :!start /min ctags -R . +< When it has finished you should see file named "tags" in your current + directory. You should notice the window title blinking on your taskbar. + This is more noticable for commands that take longer. + Now delete the "tags" file and run this command: > + :!start /b ctags -R . +< You should have the same "tags" file, but this time there will be no + blinking on the taskbar. + Example for a GUI application: > + :!start /min notepad + :!start /b notepad +< The first command runs notepad minimized and the second one runs it + normally. Q. I'm using Win32s, and when I try to run an external command like "make", Vim doesn't wait for it to finish! Help! diff -Naur vim73.orig/runtime/doc/pattern.txt vim73/runtime/doc/pattern.txt --- vim73.orig/runtime/doc/pattern.txt 2010-08-15 12:23:21.000000000 +0000 +++ vim73/runtime/doc/pattern.txt 2012-07-20 20:31:12.107640712 +0000 @@ -1027,11 +1027,9 @@ These items only work for 8-bit characters. */[[=* *[==]* - An equivalence class. This means that characters are matched that - have almost the same meaning, e.g., when ignoring accents. The form - is: + have almost the same meaning, e.g., when ignoring accents. This + only works for Unicode, latin1 and latin9. The form is: [=a=] - Currently this is only implemented for latin1. Also works for the - latin1 characters in utf-8 and latin9. */[[.* *[..]* - A collation element. This currently simply accepts a single character in the form: diff -Naur vim73.orig/runtime/doc/sign.txt vim73/runtime/doc/sign.txt --- vim73.orig/runtime/doc/sign.txt 2010-08-15 12:23:22.000000000 +0000 +++ vim73/runtime/doc/sign.txt 2012-07-20 20:31:18.004311609 +0000 @@ -150,8 +150,14 @@ Remove the previously placed sign {id} from file {fname}. See remark above about {fname} |:sign-fname|. +:sign unplace * file={fname} + Remove all placed signs in file {fname}. + :sign unplace {id} buffer={nr} - Same, but use buffer {nr}. + Remove the previously placed sign {id} from buffer {nr}. + +:sign unplace * buffer={nr} + Remove all placed signs in buffer {nr}. :sign unplace {id} Remove the previously placed sign {id} from all files it diff -Naur vim73.orig/runtime/doc/tabpage.txt vim73/runtime/doc/tabpage.txt --- vim73.orig/runtime/doc/tabpage.txt 2010-08-15 12:23:22.000000000 +0000 +++ vim73/runtime/doc/tabpage.txt 2012-07-20 20:31:17.920978216 +0000 @@ -173,10 +173,20 @@ REORDERING TAB PAGES: :tabm[ove] [N] *:tabm* *:tabmove* +:[N]tabm[ove] Move the current tab page to after tab page N. Use zero to make the current tab page the first one. Without N the tab page is made the last one. +:tabm[ove] +[N] +:tabm[ove] -[N] + Move the current tab page N places to the right (with +) or to + the left (with -). + +Note that although it is possible to move a tab behind the N-th one by using +:Ntabmove, it is impossible to move it by N places by using :+Ntabmove. For +clarification what +N means in this context see |[range]|. + LOOPING OVER TAB PAGES: diff -Naur vim73.orig/runtime/filetype.vim vim73/runtime/filetype.vim --- vim73.orig/runtime/filetype.vim 2010-08-03 20:44:00.000000000 +0000 +++ vim73/runtime/filetype.vim 2012-07-20 20:31:14.564309144 +0000 @@ -2475,17 +2475,19 @@ " detected filetypes. runtime! ftdetect/*.vim +" NOTE: The above command could have ended the filetypedetect autocmd group +" and started another one. Let's make sure it has ended to get to a consistant +" state. +augroup END " Generic configuration file (check this last, it's just guessing!) -au BufNewFile,BufRead,StdinReadPost * +au filetypedetect BufNewFile,BufRead,StdinReadPost * \ if !did_filetype() && expand("") !~ g:ft_ignore_pat \ && (getline(1) =~ '^#' || getline(2) =~ '^#' || getline(3) =~ '^#' \ || getline(4) =~ '^#' || getline(5) =~ '^#') | \ setf conf | \ endif -augroup END - " If the GUI is already running, may still need to install the Syntax menu. " Don't do it when the 'M' flag is included in 'guioptions'. diff -Naur vim73.orig/runtime/filetype.vim.orig vim73/runtime/filetype.vim.orig --- vim73.orig/runtime/filetype.vim.orig 1970-01-01 00:00:00.000000000 +0000 +++ vim73/runtime/filetype.vim.orig 2010-08-03 20:44:00.000000000 +0000 @@ -0,0 +1,2514 @@ +" Vim support file to detect file types +" +" Maintainer: Bram Moolenaar +" Last Change: 2010 Jul 30 + +" Listen very carefully, I will say this only once +if exists("did_load_filetypes") + finish +endif +let did_load_filetypes = 1 + +" Line continuation is used here, remove 'C' from 'cpoptions' +let s:cpo_save = &cpo +set cpo&vim + +augroup filetypedetect + +" Ignored extensions +if exists("*fnameescape") +au BufNewFile,BufRead ?\+.orig,?\+.bak,?\+.old,?\+.new,?\+.dpkg-dist,?\+.dpkg-old,?\+.rpmsave,?\+.rpmnew + \ 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 " . fnameescape(s:short) | + \ endif | + \ unlet! s:name s:short +au BufNewFile,BufRead ?\+.in + \ if expand(":t") != "configure.in" | + \ 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. +if !exists("g:ft_ignore_pat") + let g:ft_ignore_pat = '\.\(Z\|gz\|bz2\|zip\|tgz\)$' +endif + +" Function used for patterns that end in a star: don't set the filetype if the +" file name matches ft_ignore_pat. +func! s:StarSetf(ft) + if expand("") !~ g:ft_ignore_pat + exe 'setf ' . a:ft + endif +endfunc + +" Abaqus or Trasys +au BufNewFile,BufRead *.inp call s:Check_inp() + +func! s:Check_inp() + if getline(1) =~ '^\*' + setf abaqus + else + let n = 1 + if line("$") > 500 + let nmax = 500 + else + let nmax = line("$") + endif + while n <= nmax + if getline(n) =~? "^header surface data" + setf trasys + break + endif + let n = n + 1 + endwhile + endif +endfunc + +" A-A-P recipe +au BufNewFile,BufRead *.aap setf aap + +" A2ps printing utility +au BufNewFile,BufRead etc/a2ps.cfg,etc/a2ps/*.cfg,a2psrc,.a2psrc setf a2ps + +" ABAB/4 +au BufNewFile,BufRead *.abap setf abap + +" ABC music notation +au BufNewFile,BufRead *.abc setf abc + +" ABEL +au BufNewFile,BufRead *.abl setf abel + +" AceDB +au BufNewFile,BufRead *.wrm setf acedb + +" Ada (83, 9X, 95) +au BufNewFile,BufRead *.adb,*.ads,*.ada setf ada +if has("vms") + au BufNewFile,BufRead *.gpr,*.ada_m,*.adc setf ada +else + au BufNewFile,BufRead *.gpr setf ada +endif + +" AHDL +au BufNewFile,BufRead *.tdf setf ahdl + +" AMPL +au BufNewFile,BufRead *.run setf ampl + +" Ant +au BufNewFile,BufRead build.xml setf ant + +" Apache style config file +au BufNewFile,BufRead proftpd.conf* call s:StarSetf('apachestyle') + +" Apache config file +au BufNewFile,BufRead .htaccess,/etc/httpd/*.conf setf apache +au BufNewFile,BufRead httpd.conf*,srm.conf*,access.conf*,apache.conf*,apache2.conf*,/etc/apache2/*.conf*,/etc/httpd/conf.d/*.conf* call s:StarSetf('apache') + +" XA65 MOS6510 cross assembler +au BufNewFile,BufRead *.a65 setf a65 + +" Applescript +au BufNewFile,BufRead *.scpt setf applescript + +" Applix ELF +au BufNewFile,BufRead *.am + \ if expand("") !~? 'Makefile.am\>' | setf elf | endif + +" ALSA configuration +au BufNewFile,BufRead ~/.asoundrc,/usr/share/alsa/alsa.conf,/etc/asound.conf setf alsaconf + +" Arc Macro Language +au BufNewFile,BufRead *.aml setf aml + +" Arch Inventory file +au BufNewFile,BufRead .arch-inventory,=tagging-method setf arch + +" ART*Enterprise (formerly ART-IM) +au BufNewFile,BufRead *.art setf art + +" ASN.1 +au BufNewFile,BufRead *.asn,*.asn1 setf asn + +" Active Server Pages (with Visual Basic Script) +au BufNewFile,BufRead *.asa + \ if exists("g:filetype_asa") | + \ exe "setf " . g:filetype_asa | + \ else | + \ setf aspvbs | + \ endif + +" Active Server Pages (with Perl or Visual Basic Script) +au BufNewFile,BufRead *.asp + \ if exists("g:filetype_asp") | + \ exe "setf " . g:filetype_asp | + \ elseif getline(1) . getline(2) . getline(3) =~? "perlscript" | + \ setf aspperl | + \ else | + \ setf aspvbs | + \ endif + +" Grub (must be before catch *.lst) +au BufNewFile,BufRead /boot/grub/menu.lst,/boot/grub/grub.conf,/etc/grub.conf setf grub + +" Assembly (all kinds) +" *.lst is not pure assembly, it has two extra columns (address, byte codes) +au BufNewFile,BufRead *.asm,*.[sS],*.[aA],*.mac,*.lst call s:FTasm() + +" This function checks for the kind of assembly that is wanted by the user, or +" can be detected from the first five lines of the file. +func! s:FTasm() + " make sure b:asmsyntax exists + if !exists("b:asmsyntax") + let b:asmsyntax = "" + endif + + if b:asmsyntax == "" + call s:FTasmsyntax() + endif + + " if b:asmsyntax still isn't set, default to asmsyntax or GNU + if b:asmsyntax == "" + if exists("g:asmsyntax") + let b:asmsyntax = g:asmsyntax + else + let b:asmsyntax = "asm" + endif + endif + + exe "setf " . fnameescape(b:asmsyntax) +endfunc + +func! s:FTasmsyntax() + " see if file contains any asmsyntax=foo overrides. If so, change + " b:asmsyntax appropriately + let head = " ".getline(1)." ".getline(2)." ".getline(3)." ".getline(4). + \" ".getline(5)." " + let match = matchstr(head, '\sasmsyntax=\zs[a-zA-Z0-9]\+\ze\s') + if match != '' + let b:asmsyntax = match + elseif ((head =~? '\.title') || (head =~? '\.ident') || (head =~? '\.macro') || (head =~? '\.subtitle') || (head =~? '\.library')) + let b:asmsyntax = "vmasm" + endif +endfunc + +" Macro (VAX) +au BufNewFile,BufRead *.mar setf vmasm + +" Atlas +au BufNewFile,BufRead *.atl,*.as setf atlas + +" Autoit v3 +au BufNewFile,BufRead *.au3 setf autoit + +" Autohotkey +au BufNewFile,BufRead *.ahk setf autohotkey + +" Automake +au BufNewFile,BufRead [mM]akefile.am,GNUmakefile.am setf automake + +" Autotest .at files are actually m4 +au BufNewFile,BufRead *.at setf m4 + +" Avenue +au BufNewFile,BufRead *.ave setf ave + +" Awk +au BufNewFile,BufRead *.awk setf awk + +" B +au BufNewFile,BufRead *.mch,*.ref,*.imp setf b + +" BASIC or Visual Basic +au BufNewFile,BufRead *.bas call s:FTVB("basic") + +" Check if one of the first five lines contains "VB_Name". In that case it is +" probably a Visual Basic file. Otherwise it's assumed to be "alt" filetype. +func! s:FTVB(alt) + if getline(1).getline(2).getline(3).getline(4).getline(5) =~? 'VB_Name\|Begin VB\.\(Form\|MDIForm\|UserControl\)' + setf vb + else + exe "setf " . a:alt + endif +endfunc + +" Visual Basic Script (close to Visual Basic) +au BufNewFile,BufRead *.vbs,*.dsm,*.ctl setf vb + +" IBasic file (similar to QBasic) +au BufNewFile,BufRead *.iba,*.ibi setf ibasic + +" FreeBasic file (similar to QBasic) +au BufNewFile,BufRead *.fb,*.bi setf freebasic + +" Batch file for MSDOS. +au BufNewFile,BufRead *.bat,*.sys setf dosbatch +" *.cmd is close to a Batch file, but on OS/2 Rexx files also use *.cmd. +au BufNewFile,BufRead *.cmd + \ if getline(1) =~ '^/\*' | setf rexx | else | setf dosbatch | endif + +" Batch file for 4DOS +au BufNewFile,BufRead *.btm call s:FTbtm() +func! s:FTbtm() + if exists("g:dosbatch_syntax_for_btm") && g:dosbatch_syntax_for_btm + setf dosbatch + else + setf btm + endif +endfunc + +" BC calculator +au BufNewFile,BufRead *.bc setf bc + +" BDF font +au BufNewFile,BufRead *.bdf setf bdf + +" BibTeX bibliography database file +au BufNewFile,BufRead *.bib setf bib + +" BibTeX Bibliography Style +au BufNewFile,BufRead *.bst setf bst + +" BIND configuration +au BufNewFile,BufRead named.conf,rndc.conf setf named + +" BIND zone +au BufNewFile,BufRead named.root setf bindzone +au BufNewFile,BufRead *.db call s:BindzoneCheck('') + +func! s:BindzoneCheck(default) + if getline(1).getline(2).getline(3).getline(4) =~ '^; <<>> DiG [0-9.]\+ <<>>\|BIND.*named\|$ORIGIN\|$TTL\|IN\s\+SOA' + setf bindzone + elseif a:default != '' + exe 'setf ' . a:default + endif +endfunc + +" Blank +au BufNewFile,BufRead *.bl setf blank + +" Blkid cache file +au BufNewFile,BufRead /etc/blkid.tab,/etc/blkid.tab.old setf xml + +" C or lpc +au BufNewFile,BufRead *.c call s:FTlpc() + +func! s:FTlpc() + if exists("g:lpc_syntax_for_c") + let lnum = 1 + while lnum <= 12 + if getline(lnum) =~# '^\(//\|inherit\|private\|protected\|nosave\|string\|object\|mapping\|mixed\)' + setf lpc + return + endif + let lnum = lnum + 1 + endwhile + endif + setf c +endfunc + +" Calendar +au BufNewFile,BufRead calendar setf calendar +au BufNewFile,BufRead */.calendar/*, + \*/share/calendar/*/calendar.*,*/share/calendar/calendar.* + \ call s:StarSetf('calendar') + +" C# +au BufNewFile,BufRead *.cs setf cs + +" Cabal +au BufNewFile,BufRead *.cabal setf cabal + +" Cdrdao TOC +au BufNewFile,BufRead *.toc setf cdrtoc + +" Cdrdao config +au BufNewFile,BufRead etc/cdrdao.conf,etc/defaults/cdrdao,etc/default/cdrdao,~/.cdrdao setf cdrdaoconf + +" Cfengine +au BufNewFile,BufRead cfengine.conf setf cfengine + +" ChaiScript +au BufRead,BufNewFile *.chai setf chaiscript + +" Comshare Dimension Definition Language +au BufNewFile,BufRead *.cdl setf cdl + +" Conary Recipe +au BufNewFile,BufRead *.recipe setf conaryrecipe + +" Controllable Regex Mutilator +au BufNewFile,BufRead *.crm setf crm + +" Cyn++ +au BufNewFile,BufRead *.cyn setf cynpp + +" Cynlib +" .cc and .cpp files can be C++ or Cynlib. +au BufNewFile,BufRead *.cc + \ if exists("cynlib_syntax_for_cc")|setf cynlib|else|setf cpp|endif +au BufNewFile,BufRead *.cpp + \ if exists("cynlib_syntax_for_cpp")|setf cynlib|else|setf cpp|endif + +" C++ +au BufNewFile,BufRead *.cxx,*.c++,*.hh,*.hxx,*.hpp,*.ipp,*.moc,*.tcc,*.inl setf cpp +if has("fname_case") + au BufNewFile,BufRead *.C,*.H setf cpp +endif + +" .h files can be C, Ch C++, ObjC or ObjC++. +" Set c_syntax_for_h if you want C, ch_syntax_for_h if you want Ch. ObjC is +" detected automatically. +au BufNewFile,BufRead *.h call s:FTheader() + +func! s:FTheader() + if match(getline(1, min([line("$"), 200])), '^@\(interface\|end\|class\)') > -1 + setf objc + elseif exists("g:c_syntax_for_h") + setf c + elseif exists("g:ch_syntax_for_h") + setf ch + else + setf cpp + endif +endfunc + +" Ch (CHscript) +au BufNewFile,BufRead *.chf setf ch + +" TLH files are C++ headers generated by Visual C++'s #import from typelibs +au BufNewFile,BufRead *.tlh setf cpp + +" Cascading Style Sheets +au BufNewFile,BufRead *.css setf css + +" Century Term Command Scripts (*.cmd too) +au BufNewFile,BufRead *.con setf cterm + +" Changelog +au BufNewFile,BufRead changelog.Debian,changelog.dch,NEWS.Debian,NEWS.dch + \ setf debchangelog + +au BufNewFile,BufRead [cC]hange[lL]og + \ if getline(1) =~ '; urgency=' + \| setf debchangelog + \| else + \| setf changelog + \| endif + +au BufNewFile,BufRead NEWS + \ if getline(1) =~ '; urgency=' + \| setf debchangelog + \| endif + +" CHILL +au BufNewFile,BufRead *..ch setf chill + +" Changes for WEB and CWEB or CHILL +au BufNewFile,BufRead *.ch call s:FTchange() + +" This function checks if one of the first ten lines start with a '@'. In +" that case it is probably a change file. +" If the first line starts with # or ! it's probably a ch file. +" If a line has "main", "include", "//" ir "/*" it's probably ch. +" Otherwise CHILL is assumed. +func! s:FTchange() + let lnum = 1 + while lnum <= 10 + if getline(lnum)[0] == '@' + setf change + return + endif + if lnum == 1 && (getline(1)[0] == '#' || getline(1)[0] == '!') + setf ch + return + endif + if getline(lnum) =~ "MODULE" + setf chill + return + endif + if getline(lnum) =~ 'main\s*(\|#\s*include\|//' + setf ch + return + endif + let lnum = lnum + 1 + endwhile + setf chill +endfunc + +" ChordPro +au BufNewFile,BufRead *.chopro,*.crd,*.cho,*.crdpro,*.chordpro setf chordpro + +" Clean +au BufNewFile,BufRead *.dcl,*.icl setf clean + +" Clever +au BufNewFile,BufRead *.eni setf cl + +" Clever or dtd +au BufNewFile,BufRead *.ent call s:FTent() + +func! s:FTent() + " This function checks for valid cl syntax in the first five lines. + " Look for either an opening comment, '#', or a block start, '{". + " If not found, assume SGML. + let lnum = 1 + while lnum < 6 + let line = getline(lnum) + if line =~ '^\s*[#{]' + setf cl + return + elseif line !~ '^\s*$' + " Not a blank line, not a comment, and not a block start, + " so doesn't look like valid cl code. + break + endif + let lnum = lnum + 1 + endw + setf dtd +endfunc + +" Clipper (or FoxPro; could also be eviews) +au BufNewFile,BufRead *.prg + \ if exists("g:filetype_prg") | + \ exe "setf " . g:filetype_prg | + \ else | + \ setf clipper | + \ endif + +" Cmake +au BufNewFile,BufRead CMakeLists.txt,*.cmake,*.cmake.in setf cmake + +" Cmusrc +au BufNewFile,BufRead ~/.cmus/{autosave,rc,command-history,*.theme} setf cmusrc +au BufNewFile,BufRead */cmus/{rc,*.theme} setf cmusrc + +" Cobol +au BufNewFile,BufRead *.cbl,*.cob,*.lib setf cobol +" cobol or zope form controller python script? (heuristic) +au BufNewFile,BufRead *.cpy + \ if getline(1) =~ '^##' | + \ setf python | + \ else | + \ setf cobol | + \ endif + +" Coco/R +au BufNewFile,BufRead *.atg setf coco + +" Cold Fusion +au BufNewFile,BufRead *.cfm,*.cfi,*.cfc setf cf + +" Configure scripts +au BufNewFile,BufRead configure.in,configure.ac setf config + +" CUDA Cumpute Unified Device Architecture +au BufNewFile,BufRead *.cu setf cuda + +" WildPackets EtherPeek Decoder +au BufNewFile,BufRead *.dcd setf dcd + +" Enlightenment configuration files +au BufNewFile,BufRead *enlightenment/*.cfg setf c + +" Eterm +au BufNewFile,BufRead *Eterm/*.cfg setf eterm + +" Lynx config files +au BufNewFile,BufRead lynx.cfg setf lynx + +" Quake +au BufNewFile,BufRead *baseq[2-3]/*.cfg,*id1/*.cfg setf quake +au BufNewFile,BufRead *quake[1-3]/*.cfg setf quake + +" Quake C +au BufNewFile,BufRead *.qc setf c + +" Configure files +au BufNewFile,BufRead *.cfg setf cfg + +" Cucumber +au BufNewFile,BufRead *.feature setf cucumber + +" Communicating Sequential Processes +au BufNewFile,BufRead *.csp,*.fdr setf csp + +" CUPL logic description and simulation +au BufNewFile,BufRead *.pld setf cupl +au BufNewFile,BufRead *.si setf cuplsim + +" Debian Control +au BufNewFile,BufRead */debian/control setf debcontrol +au BufNewFile,BufRead control + \ if getline(1) =~ '^Source:' + \| setf debcontrol + \| endif + +" Debian Sources.list +au BufNewFile,BufRead /etc/apt/sources.list setf debsources + +" Deny hosts +au BufNewFile,BufRead denyhosts.conf setf denyhosts + +" ROCKLinux package description +au BufNewFile,BufRead *.desc setf desc + +" the D language or dtrace +au BufNewFile,BufRead *.d call s:DtraceCheck() + +func! s:DtraceCheck() + let lines = getline(1, min([line("$"), 100])) + if match(lines, '^#!\S\+dtrace\|#pragma\s\+D\s\+option\|:\S\{-}:\S\{-}:') > -1 + setf dtrace + else + setf d + endif +endfunc + +" Desktop files +au BufNewFile,BufRead *.desktop,.directory setf desktop + +" Dict config +au BufNewFile,BufRead dict.conf,.dictrc setf dictconf + +" Dictd config +au BufNewFile,BufRead dictd.conf setf dictdconf + +" Diff files +au BufNewFile,BufRead *.diff,*.rej,*.patch setf diff + +" Dircolors +au BufNewFile,BufRead .dir_colors,/etc/DIR_COLORS setf dircolors + +" Diva (with Skill) or InstallShield +au BufNewFile,BufRead *.rul + \ if getline(1).getline(2).getline(3).getline(4).getline(5).getline(6) =~? 'InstallShield' | + \ setf ishd | + \ else | + \ setf diva | + \ endif + +" DCL (Digital Command Language - vms) or DNS zone file +au BufNewFile,BufRead *.com call s:BindzoneCheck('dcl') + +" DOT +au BufNewFile,BufRead *.dot setf dot + +" Dylan - lid files +au BufNewFile,BufRead *.lid setf dylanlid + +" Dylan - intr files (melange) +au BufNewFile,BufRead *.intr setf dylanintr + +" Dylan +au BufNewFile,BufRead *.dylan setf dylan + +" Microsoft Module Definition +au BufNewFile,BufRead *.def setf def + +" Dracula +au BufNewFile,BufRead *.drac,*.drc,*lvs,*lpe setf dracula + +" Datascript +au BufNewFile,BufRead *.ds setf datascript + +" dsl +au BufNewFile,BufRead *.dsl setf dsl + +" DTD (Document Type Definition for XML) +au BufNewFile,BufRead *.dtd setf dtd + +" EDIF (*.edf,*.edif,*.edn,*.edo) +au BufNewFile,BufRead *.ed\(f\|if\|n\|o\) setf edif + +" Embedix Component Description +au BufNewFile,BufRead *.ecd setf ecd + +" Eiffel or Specman +au BufNewFile,BufRead *.e,*.E call s:FTe() + +" Elinks configuration +au BufNewFile,BufRead */etc/elinks.conf,*/.elinks/elinks.conf setf elinks + +func! s:FTe() + let n = 1 + while n < 100 && n < line("$") + if getline(n) =~ "^\\s*\\(<'\\|'>\\)\\s*$" + setf specman + return + endif + let n = n + 1 + endwhile + setf eiffel +endfunc + +" ERicsson LANGuage; Yaws is erlang too +au BufNewFile,BufRead *.erl,*.hrl,*.yaws setf erlang + +" Elm Filter Rules file +au BufNewFile,BufRead filter-rules setf elmfilt + +" ESMTP rc file +au BufNewFile,BufRead *esmtprc setf esmtprc + +" ESQL-C +au BufNewFile,BufRead *.ec,*.EC setf esqlc + +" Esterel +au BufNewFile,BufRead *.strl setf esterel + +" Essbase script +au BufNewFile,BufRead *.csc setf csc + +" Exim +au BufNewFile,BufRead exim.conf setf exim + +" Expect +au BufNewFile,BufRead *.exp setf expect + +" Exports +au BufNewFile,BufRead exports setf exports + +" Fantom +au BufNewFile,BufRead *.fan,*.fwt setf fan + +" Factor +au BufNewFile,BufRead *.factor setf factor + +" Fetchmail RC file +au BufNewFile,BufRead .fetchmailrc setf fetchmail + +" FlexWiki - disabled, because it has side effects when a .wiki file +" is not actually FlexWiki +"au BufNewFile,BufRead *.wiki setf flexwiki + +" Focus Executable +au BufNewFile,BufRead *.fex,*.focexec setf focexec + +" Focus Master file (but not for auto.master) +au BufNewFile,BufRead auto.master setf conf +au BufNewFile,BufRead *.mas,*.master setf master + +" Forth +au BufNewFile,BufRead *.fs,*.ft setf forth + +" Reva Forth +au BufNewFile,BufRead *.frt setf reva + +" Fortran +if has("fname_case") + au BufNewFile,BufRead *.F,*.FOR,*.FPP,*.FTN,*.F77,*.F90,*.F95,*.F03,*.F08 setf fortran +endif +au BufNewFile,BufRead *.f,*.for,*.fortran,*.fpp,*.ftn,*.f77,*.f90,*.f95,*.f03,*.f08 setf fortran + +" Framescript +au BufNewFile,BufRead *.fsl setf framescript + +" FStab +au BufNewFile,BufRead fstab,mtab setf fstab + +" GDB command files +au BufNewFile,BufRead .gdbinit setf gdb + +" GDMO +au BufNewFile,BufRead *.mo,*.gdmo setf gdmo + +" Gedcom +au BufNewFile,BufRead *.ged,lltxxxxx.txt setf gedcom + +" Git +autocmd BufNewFile,BufRead *.git/COMMIT_EDITMSG setf gitcommit +autocmd BufNewFile,BufRead *.git/config,.gitconfig,.gitmodules setf gitconfig +autocmd BufNewFile,BufRead git-rebase-todo setf gitrebase +autocmd BufNewFile,BufRead .msg.[0-9]* + \ if getline(1) =~ '^From.*# This line is ignored.$' | + \ setf gitsendemail | + \ endif +autocmd BufNewFile,BufRead *.git/** + \ if getline(1) =~ '^\x\{40\}\>\|^ref: ' | + \ setf git | + \ endif + +" Gkrellmrc +au BufNewFile,BufRead gkrellmrc,gkrellmrc_? setf gkrellmrc + +" GP scripts (2.0 and onward) +au BufNewFile,BufRead *.gp,.gprc setf gp + +" GPG +au BufNewFile,BufRead */.gnupg/options setf gpg +au BufNewFile,BufRead */.gnupg/gpg.conf setf gpg +au BufNewFile,BufRead /usr/**/gnupg/options.skel setf gpg + +" Gnuplot scripts +au BufNewFile,BufRead *.gpi setf gnuplot + +" GrADS scripts +au BufNewFile,BufRead *.gs setf grads + +" Gretl +au BufNewFile,BufRead *.gretl setf gretl + +" Groovy +au BufNewFile,BufRead *.groovy setf groovy + +" GNU Server Pages +au BufNewFile,BufRead *.gsp setf gsp + +" Group file +au BufNewFile,BufRead /etc/group,/etc/group-,/etc/group.edit,/etc/gshadow,/etc/gshadow-,/etc/gshadow.edit,/var/backups/group.bak,/var/backups/gshadow.bak setf group + +" GTK RC +au BufNewFile,BufRead .gtkrc,gtkrc setf gtkrc + +" Haml +au BufNewFile,BufRead *.haml setf haml + +" Hamster Classic | Playground files +au BufNewFile,BufRead *.hsc,*.hsm setf hamster + +" Haskell +au BufNewFile,BufRead *.hs,*.hs-boot setf haskell +au BufNewFile,BufRead *.lhs setf lhaskell +au BufNewFile,BufRead *.chs setf chaskell + +" Haste +au BufNewFile,BufRead *.ht setf haste +au BufNewFile,BufRead *.htpp setf hastepreproc + +" Hercules +au BufNewFile,BufRead *.vc,*.ev,*.rs,*.sum,*.errsum setf hercules + +" HEX (Intel) +au BufNewFile,BufRead *.hex,*.h32 setf hex + +" Tilde (must be before HTML) +au BufNewFile,BufRead *.t.html setf tilde + +" HTML (.shtml and .stm for server side) +au BufNewFile,BufRead *.html,*.htm,*.shtml,*.stm call s:FThtml() + +" Distinguish between HTML, XHTML and Django +func! s:FThtml() + let n = 1 + while n < 10 && n < line("$") + if getline(n) =~ '\' + setf htmldjango + return + endif + let n = n + 1 + endwhile + setf html +endfunc + +" HTML with Ruby - eRuby +au BufNewFile,BufRead *.erb,*.rhtml setf eruby + +" HTML with M4 +au BufNewFile,BufRead *.html.m4 setf htmlm4 + +" HTML Cheetah template +au BufNewFile,BufRead *.tmpl setf htmlcheetah + +" Host config +au BufNewFile,BufRead /etc/host.conf setf hostconf + +" Hosts access +au BufNewFile,BufRead /etc/hosts.allow,/etc/hosts.deny setf hostsaccess + +" Hyper Builder +au BufNewFile,BufRead *.hb setf hb + +" Icon +au BufNewFile,BufRead *.icn setf icon + +" IDL (Interface Description Language) +au BufNewFile,BufRead *.idl call s:FTidl() + +" Distinguish between standard IDL and MS-IDL +func! s:FTidl() + let n = 1 + while n < 50 && n < line("$") + if getline(n) =~ '^\s*import\s\+"\(unknwn\|objidl\)\.idl"' + setf msidl + return + endif + let n = n + 1 + endwhile + setf idl +endfunc + +" Microsoft IDL (Interface Description Language) Also *.idl +" MOF = WMI (Windows Management Instrumentation) Managed Object Format +au BufNewFile,BufRead *.odl,*.mof setf msidl + +" Icewm menu +au BufNewFile,BufRead */.icewm/menu setf icemenu + +" Indent profile (must come before IDL *.pro!) +au BufNewFile,BufRead .indent.pro setf indent +au BufNewFile,BufRead indent.pro call s:ProtoCheck('indent') + +" IDL (Interactive Data Language) +au BufNewFile,BufRead *.pro call s:ProtoCheck('idlang') + +" Distinguish between "default" and Cproto prototype file. */ +func! s:ProtoCheck(default) + " Cproto files have a comment in the first line and a function prototype in + " the second line, it always ends in ";". Indent files may also have + " comments, thus we can't match comments to see the difference. + if getline(2) =~ ';$' + setf cpp + else + exe 'setf ' . a:default + endif +endfunc + + +" Indent RC +au BufNewFile,BufRead indentrc setf indent + +" Inform +au BufNewFile,BufRead *.inf,*.INF setf inform + +" Initng +au BufNewFile,BufRead /etc/initng/**/*.i,*.ii setf initng + +" Ipfilter +au BufNewFile,BufRead ipf.conf,ipf6.conf,ipf.rules setf ipfilter + +" Informix 4GL (source - canonical, include file, I4GL+M4 preproc.) +au BufNewFile,BufRead *.4gl,*.4gh,*.m4gl setf fgl + +" .INI file for MSDOS +au BufNewFile,BufRead *.ini setf dosini + +" SysV Inittab +au BufNewFile,BufRead inittab setf inittab + +" Inno Setup +au BufNewFile,BufRead *.iss setf iss + +" JAL +au BufNewFile,BufRead *.jal,*.JAL setf jal + +" Jam +au BufNewFile,BufRead *.jpl,*.jpr setf jam + +" Java +au BufNewFile,BufRead *.java,*.jav setf java + +" JavaCC +au BufNewFile,BufRead *.jj,*.jjt setf javacc + +" JavaScript, ECMAScript +au BufNewFile,BufRead *.js,*.javascript,*.es,*.jsx setf javascript + +" Java Server Pages +au BufNewFile,BufRead *.jsp setf jsp + +" Java Properties resource file (note: doesn't catch font.properties.pl) +au BufNewFile,BufRead *.properties,*.properties_??,*.properties_??_?? setf jproperties +au BufNewFile,BufRead *.properties_??_??_* call s:StarSetf('jproperties') + +" Jess +au BufNewFile,BufRead *.clp setf jess + +" Jgraph +au BufNewFile,BufRead *.jgr setf jgraph + +" Kixtart +au BufNewFile,BufRead *.kix setf kix + +" Kimwitu[++] +au BufNewFile,BufRead *.k setf kwt + +" KDE script +au BufNewFile,BufRead *.ks setf kscript + +" Kconfig +au BufNewFile,BufRead Kconfig,Kconfig.debug setf kconfig + +" Lace (ISE) +au BufNewFile,BufRead *.ace,*.ACE setf lace + +" Latte +au BufNewFile,BufRead *.latte,*.lte setf latte + +" Limits +au BufNewFile,BufRead /etc/limits setf limits + +" LambdaProlog (*.mod too, see Modsim) +au BufNewFile,BufRead *.sig setf lprolog + +" LDAP LDIF +au BufNewFile,BufRead *.ldif setf ldif + +" Ld loader +au BufNewFile,BufRead *.ld setf ld + +" Lex +au BufNewFile,BufRead *.lex,*.l setf lex + +" Libao +au BufNewFile,BufRead /etc/libao.conf,*/.libao setf libao + +" Libsensors +au BufNewFile,BufRead /etc/sensors.conf setf sensors + +" LFTP +au BufNewFile,BufRead lftp.conf,.lftprc,*lftp/rc setf lftp + +" Lifelines (or Lex for C++!) +au BufNewFile,BufRead *.ll setf lifelines + +" Lilo: Linux loader +au BufNewFile,BufRead lilo.conf* call s:StarSetf('lilo') + +" Lisp (*.el = ELisp, *.cl = Common Lisp, *.jl = librep Lisp) +if has("fname_case") + au BufNewFile,BufRead *.lsp,*.lisp,*.el,*.cl,*.jl,*.L,.emacs,.sawfishrc setf lisp +else + au BufNewFile,BufRead *.lsp,*.lisp,*.el,*.cl,*.jl,.emacs,.sawfishrc setf lisp +endif + +" SBCL implementation of Common Lisp +au BufNewFile,BufRead sbclrc,.sbclrc setf lisp + +" Liquid +au BufNewFile,BufRead *.liquid setf liquid + +" Lite +au BufNewFile,BufRead *.lite,*.lt setf lite + +" LiteStep RC files +au BufNewFile,BufRead */LiteStep/*/*.rc setf litestep + +" Login access +au BufNewFile,BufRead /etc/login.access setf loginaccess + +" Login defs +au BufNewFile,BufRead /etc/login.defs setf logindefs + +" Logtalk +au BufNewFile,BufRead *.lgt setf logtalk + +" LOTOS +au BufNewFile,BufRead *.lot,*.lotos setf lotos + +" Lout (also: *.lt) +au BufNewFile,BufRead *.lou,*.lout setf lout + +" Lua +au BufNewFile,BufRead *.lua setf lua + +" Linden Scripting Language (Second Life) +au BufNewFile,BufRead *.lsl setf lsl + +" Lynx style file (or LotusScript!) +au BufNewFile,BufRead *.lss setf lss + +" M4 +au BufNewFile,BufRead *.m4 + \ if expand("") !~? 'html.m4$\|fvwm2rc' | setf m4 | endif + +" MaGic Point +au BufNewFile,BufRead *.mgp setf mgp + +" Mail (for Elm, trn, mutt, muttng, rn, slrn) +au BufNewFile,BufRead snd.\d\+,.letter,.letter.\d\+,.followup,.article,.article.\d\+,pico.\d\+,mutt{ng,}-*-\w\+,mutt[[:alnum:]_-]\{6\},ae\d\+.txt,/tmp/SLRN[0-9A-Z.]\+,*.eml setf mail + +" Mail aliases +au BufNewFile,BufRead /etc/mail/aliases,/etc/aliases setf mailaliases + +" Mailcap configuration file +au BufNewFile,BufRead .mailcap,mailcap setf mailcap + +" Makefile +au BufNewFile,BufRead *[mM]akefile,*.mk,*.mak,*.dsp setf make + +" MakeIndex +au BufNewFile,BufRead *.ist,*.mst setf ist + +" Manpage +au BufNewFile,BufRead *.man setf man + +" Man config +au BufNewFile,BufRead /etc/man.conf,man.config setf manconf + +" Maple V +au BufNewFile,BufRead *.mv,*.mpl,*.mws setf maple + +" Map (UMN mapserver config file) +au BufNewFile,BufRead *.map setf map + +" Markdown +au BufNewFile,BufRead *.markdown,*.mdown,*.mkd,*.mkdn,README.md setf markdown + +" Mason +au BufNewFile,BufRead *.mason,*.mhtml setf mason + +" Matlab or Objective C +au BufNewFile,BufRead *.m call s:FTm() + +func! s:FTm() + let n = 1 + while n < 10 + let line = getline(n) + if line =~ '^\s*\(#\s*\(include\|import\)\>\|/\*\|//\)' + setf objc + return + endif + if line =~ '^\s*%' + setf matlab + return + endif + if line =~ '^\s*(\*' + setf mma + return + endif + let n = n + 1 + endwhile + if exists("g:filetype_m") + exe "setf " . g:filetype_m + else + setf matlab + endif +endfunc + +" Mathematica notebook +au BufNewFile,BufRead *.nb setf mma + +" Maya Extension Language +au BufNewFile,BufRead *.mel setf mel + +" Mercurial config (looks like generic config file) +au BufNewFile,BufRead *.hgrc,*hgrc setf cfg + +" Messages +au BufNewFile,BufRead /var/log/messages,/var/log/messages.*[0-9] setf messages + +" Metafont +au BufNewFile,BufRead *.mf setf mf + +" MetaPost +au BufNewFile,BufRead *.mp setf mp + +" MGL +au BufNewFile,BufRead *.mgl setf mgl + +" MMIX or VMS makefile +au BufNewFile,BufRead *.mms call s:FTmms() + +" Symbian meta-makefile definition (MMP) +au BufNewFile,BufRead *.mmp setf mmp + +func! s:FTmms() + let n = 1 + while n < 10 + let line = getline(n) + if line =~ '^\s*\(%\|//\)' || line =~ '^\*' + setf mmix + return + endif + if line =~ '^\s*#' + setf make + return + endif + let n = n + 1 + endwhile + setf mmix +endfunc + + +" Modsim III (or LambdaProlog) +au BufNewFile,BufRead *.mod + \ if getline(1) =~ '\' | + \ setf lprolog | + \ else | + \ setf modsim3 | + \ endif + +" Modula 2 +au BufNewFile,BufRead *.m2,*.DEF,*.MOD,*.md,*.mi setf modula2 + +" Modula 3 (.m3, .i3, .mg, .ig) +au BufNewFile,BufRead *.[mi][3g] setf modula3 + +" Monk +au BufNewFile,BufRead *.isc,*.monk,*.ssc,*.tsc setf monk + +" MOO +au BufNewFile,BufRead *.moo setf moo + +" Modconf +au BufNewFile,BufRead /etc/modules.conf,/etc/conf.modules setf modconf +au BufNewFile,BufRead /etc/modutils/* + \ if executable(expand("")) != 1 + \| call s:StarSetf('modconf') + \|endif + +" Mplayer config +au BufNewFile,BufRead mplayer.conf,*/.mplayer/config setf mplayerconf + +" Moterola S record +au BufNewFile,BufRead *.s19,*.s28,*.s37 setf srec + +" Mrxvtrc +au BufNewFile,BufRead mrxvtrc,.mrxvtrc setf mrxvtrc + +" Msql +au BufNewFile,BufRead *.msql setf msql + +" Mysql +au BufNewFile,BufRead *.mysql setf mysql + +" M$ Resource files +au BufNewFile,BufRead *.rc setf rc + +" MuPAD source +au BufRead,BufNewFile *.mu setf mupad + +" Mush +au BufNewFile,BufRead *.mush setf mush + +" Mutt setup file (also for Muttng) +au BufNewFile,BufRead Mutt{ng,}rc setf muttrc + +" Nano +au BufNewFile,BufRead /etc/nanorc,.nanorc setf nanorc + +" Nastran input/DMAP +"au BufNewFile,BufRead *.dat setf nastran + +" Natural +au BufNewFile,BufRead *.NS[ACGLMNPS] setf natural + +" Netrc +au BufNewFile,BufRead .netrc setf netrc + +" Novell netware batch files +au BufNewFile,BufRead *.ncf setf ncf + +" Nroff/Troff (*.ms and *.t are checked below) +au BufNewFile,BufRead *.me + \ if expand("") != "read.me" && expand("") != "click.me" | + \ setf nroff | + \ endif +au BufNewFile,BufRead *.tr,*.nr,*.roff,*.tmac,*.mom setf nroff +au BufNewFile,BufRead *.[1-9] call s:FTnroff() + +" This function checks if one of the first five lines start with a dot. In +" that case it is probably an nroff file: 'filetype' is set and 1 is returned. +func! s:FTnroff() + if getline(1)[0] . getline(2)[0] . getline(3)[0] . getline(4)[0] . getline(5)[0] =~ '\.' + setf nroff + return 1 + endif + return 0 +endfunc + +" Nroff or Objective C++ +au BufNewFile,BufRead *.mm call s:FTmm() + +func! s:FTmm() + let n = 1 + while n < 10 + let line = getline(n) + if line =~ '^\s*\(#\s*\(include\|import\)\>\|/\*\)' + setf objcpp + return + endif + let n = n + 1 + endwhile + setf nroff +endfunc + +" Not Quite C +au BufNewFile,BufRead *.nqc setf nqc + +" NSIS +au BufNewFile,BufRead *.nsi setf nsis + +" OCAML +au BufNewFile,BufRead *.ml,*.mli,*.mll,*.mly setf ocaml + +" Occam +au BufNewFile,BufRead *.occ setf occam + +" Omnimark +au BufNewFile,BufRead *.xom,*.xin setf omnimark + +" OpenROAD +au BufNewFile,BufRead *.or setf openroad + +" OPL +au BufNewFile,BufRead *.[Oo][Pp][Ll] setf opl + +" Oracle config file +au BufNewFile,BufRead *.ora setf ora + +" Packet filter conf +au BufNewFile,BufRead pf.conf setf pf + +" Pam conf +au BufNewFile,BufRead /etc/pam.conf setf pamconf + +" PApp +au BufNewFile,BufRead *.papp,*.pxml,*.pxsl setf papp + +" Password file +au BufNewFile,BufRead /etc/passwd,/etc/passwd-,/etc/passwd.edit,/etc/shadow,/etc/shadow-,/var/backups/passwd.bak,/var/backups/shadow.bak setf passwd + +" Pascal (also *.p) +au BufNewFile,BufRead *.pas setf pascal + +" Delphi project file +au BufNewFile,BufRead *.dpr setf pascal + +" PDF +au BufNewFile,BufRead *.pdf setf pdf + +" Perl +if has("fname_case") + au BufNewFile,BufRead *.pl,*.PL call s:FTpl() +else + au BufNewFile,BufRead *.pl call s:FTpl() +endif +au BufNewFile,BufRead *.plx,*.al setf perl +au BufNewFile,BufRead *.p6,*.pm6 setf perl6 + +func! s:FTpl() + if exists("g:filetype_pl") + exe "setf " . g:filetype_pl + else + " recognize Prolog by specific text in the first non-empty line + " require a blank after the '%' because Perl uses "%list" and "%translate" + let l = getline(nextnonblank(1)) + if l =~ '\' || l =~ '^\s*\(%\+\(\s\|$\)\|/\*\)' || l =~ ':-' + setf prolog + else + setf perl + endif + endif +endfunc + +" Perl, XPM or XPM2 +au BufNewFile,BufRead *.pm + \ if getline(1) =~ "XPM2" | + \ setf xpm2 | + \ elseif getline(1) =~ "XPM" | + \ setf xpm | + \ else | + \ setf perl | + \ endif + +" Perl POD +au BufNewFile,BufRead *.pod setf pod + +" Php, php3, php4, etc. +" Also Phtml (was used for PHP 2 in the past) +" Also .ctp for Cake template file +au BufNewFile,BufRead *.php,*.php\d,*.phtml,*.ctp setf php + +" Pike +au BufNewFile,BufRead *.pike,*.lpc,*.ulpc,*.pmod setf pike + +" Pinfo config +au BufNewFile,BufRead */etc/pinforc,*/.pinforc setf pinfo + +" Palm Resource compiler +au BufNewFile,BufRead *.rcp setf pilrc + +" Pine config +au BufNewFile,BufRead .pinerc,pinerc,.pinercex,pinercex setf pine + +" PL/M (also: *.inp) +au BufNewFile,BufRead *.plm,*.p36,*.pac setf plm + +" PL/SQL +au BufNewFile,BufRead *.pls,*.plsql setf plsql + +" PLP +au BufNewFile,BufRead *.plp setf plp + +" PO and PO template (GNU gettext) +au BufNewFile,BufRead *.po,*.pot setf po + +" Postfix main config +au BufNewFile,BufRead main.cf setf pfmain + +" PostScript (+ font files, encapsulated PostScript, Adobe Illustrator) +au BufNewFile,BufRead *.ps,*.pfa,*.afm,*.eps,*.epsf,*.epsi,*.ai setf postscr + +" PostScript Printer Description +au BufNewFile,BufRead *.ppd setf ppd + +" Povray +au BufNewFile,BufRead *.pov setf pov + +" Povray configuration +au BufNewFile,BufRead .povrayrc setf povini + +" Povray, PHP or assembly +au BufNewFile,BufRead *.inc call s:FTinc() + +func! s:FTinc() + if exists("g:filetype_inc") + exe "setf " . g:filetype_inc + else + let lines = getline(1).getline(2).getline(3) + if lines =~? "perlscript" + setf aspperl + elseif lines =~ "<%" + setf aspvbs + elseif lines =~ "' + \ || line =~ '^\s*{' || line =~ '^\s*(\*' + setf pascal + return + elseif line !~ '^\s*$' || line =~ '^/\*' + " Not an empty line: Doesn't look like valid Pascal code. + " Or it looks like a Progress /* comment + break + endif + let lnum = lnum + 1 + endw + setf progress +endfunc + + +" Software Distributor Product Specification File (POSIX 1387.2-1995) +au BufNewFile,BufRead *.psf setf psf +au BufNewFile,BufRead INDEX,INFO + \ if getline(1) =~ '^\s*\(distribution\|installed_software\|root\|bundle\|product\)\s*$' | + \ setf psf | + \ endif + +" Prolog +au BufNewFile,BufRead *.pdb setf prolog + +" Promela +au BufNewFile,BufRead *.pml setf promela + +" Protocols +au BufNewFile,BufRead /etc/protocols setf protocols + +" Pyrex +au BufNewFile,BufRead *.pyx,*.pxd setf pyrex + +" Python +au BufNewFile,BufRead *.py,*.pyw setf python + +" Quixote (Python-based web framework) +au BufNewFile,BufRead *.ptl setf python + +" Radiance +au BufNewFile,BufRead *.rad,*.mat setf radiance + +" Ratpoison config/command files +au BufNewFile,BufRead .ratpoisonrc,ratpoisonrc setf ratpoison + +" RCS file +au BufNewFile,BufRead *\,v setf rcs + +" Readline +au BufNewFile,BufRead .inputrc,inputrc setf readline + +" Registry for MS-Windows +au BufNewFile,BufRead *.reg + \ if getline(1) =~? '^REGEDIT[0-9]*\s*$\|^Windows Registry Editor Version \d*\.\d*\s*$' | setf registry | endif + +" Renderman Interface Bytestream +au BufNewFile,BufRead *.rib setf rib + +" Rexx +au BufNewFile,BufRead *.rexx,*.rex,*.jrexx,*.rxj,*.orx setf rexx + +" R (Splus) +if has("fname_case") + au BufNewFile,BufRead *.s,*.S setf r +else + au BufNewFile,BufRead *.s setf r +endif + +" R Help file +if has("fname_case") + au BufNewFile,BufRead *.rd,*.Rd setf rhelp +else + au BufNewFile,BufRead *.rd setf rhelp +endif + +" R noweb file +if has("fname_case") + au BufNewFile,BufRead *.Rnw,*.rnw,*.Snw,*.snw setf rnoweb +else + au BufNewFile,BufRead *.rnw,*.snw setf rnoweb +endif + +" Rexx, Rebol or R +au BufNewFile,BufRead *.r,*.R call s:FTr() + +func! s:FTr() + let max = line("$") > 50 ? 50 : line("$") + + for n in range(1, max) + " Rebol is easy to recognize, check for that first + if getline(n) =~? '\' + setf rebol + return + endif + endfor + + for n in range(1, max) + " R has # comments + if getline(n) =~ '^\s*#' + setf r + return + endif + " Rexx has /* comments */ + if getline(n) =~ '^\s*/\*' + setf rexx + return + endif + endfor + + " Nothing recognized, assume Rexx + setf rexx +endfunc + +" Remind +au BufNewFile,BufRead .reminders* call s:StarSetf('remind') +au BufNewFile,BufRead *.remind,*.rem setf remind + +" Resolv.conf +au BufNewFile,BufRead resolv.conf setf resolv + +" Relax NG Compact +au BufNewFile,BufRead *.rnc setf rnc + +" RPL/2 +au BufNewFile,BufRead *.rpl setf rpl + +" Robots.txt +au BufNewFile,BufRead robots.txt setf robots + +" Rpcgen +au BufNewFile,BufRead *.x setf rpcgen + +" reStructuredText Documentation Format +au BufNewFile,BufRead *.rst setf rst + +" RTF +au BufNewFile,BufRead *.rtf setf rtf + +" Interactive Ruby shell +au BufNewFile,BufRead .irbrc,irbrc setf ruby + +" Ruby +au BufNewFile,BufRead *.rb,*.rbw,*.gem,*.gemspec setf ruby + +" Ruby on Rails +au BufNewFile,BufRead *.builder,*.rxml,*.rjs setf ruby + +" Rantfile and Rakefile is like Ruby +au BufNewFile,BufRead [rR]antfile,*.rant,[rR]akefile,*.rake setf ruby + +" S-lang (or shader language, or SmallLisp) +au BufNewFile,BufRead *.sl setf slang + +" Samba config +au BufNewFile,BufRead smb.conf setf samba + +" SAS script +au BufNewFile,BufRead *.sas setf sas + +" Sass +au BufNewFile,BufRead *.sass setf sass + +" Sather +au BufNewFile,BufRead *.sa setf sather + +" Scilab +au BufNewFile,BufRead *.sci,*.sce setf scilab + +" SCSS +au BufNewFile,BufRead *.scss setf scss + +" SD: Streaming Descriptors +au BufNewFile,BufRead *.sd setf sd + +" SDL +au BufNewFile,BufRead *.sdl,*.pr setf sdl + +" sed +au BufNewFile,BufRead *.sed setf sed + +" Sieve (RFC 3028) +au BufNewFile,BufRead *.siv setf sieve + +" Sendmail +au BufNewFile,BufRead sendmail.cf setf sm + +" Sendmail .mc files are actually m4. Could also be MS Message text file. +au BufNewFile,BufRead *.mc call s:McSetf() + +func! s:McSetf() + " Rely on the file to start with a comment. + " MS message text files use ';', Sendmail files use '#' or 'dnl' + for lnum in range(1, min([line("$"), 20])) + let line = getline(lnum) + if line =~ '^\s*\(#\|dnl\)' + setf m4 " Sendmail .mc file + return + elseif line =~ '^\s*;' + setf msmessages " MS Message text file + return + endif + endfor + setf m4 " Default: Sendmail .mc file +endfunc + +" Services +au BufNewFile,BufRead /etc/services setf services + +" Service Location config +au BufNewFile,BufRead /etc/slp.conf setf slpconf + +" Service Location registration +au BufNewFile,BufRead /etc/slp.reg setf slpreg + +" Service Location SPI +au BufNewFile,BufRead /etc/slp.spi setf slpspi + +" Setserial config +au BufNewFile,BufRead /etc/serial.conf setf setserial + +" SGML +au BufNewFile,BufRead *.sgm,*.sgml + \ if getline(1).getline(2).getline(3).getline(4).getline(5) =~? 'linuxdoc' | + \ setf sgmllnx | + \ elseif getline(1) =~ '") =~ g:ft_ignore_pat + return + endif + if a:name =~ '\' + " Some .sh scripts contain #!/bin/csh. + call SetFileTypeShell("csh") + return + elseif a:name =~ '\' + " Some .sh scripts contain #!/bin/tcsh. + call SetFileTypeShell("tcsh") + return + elseif a:name =~ '\' + let b:is_kornshell = 1 + if exists("b:is_bash") + unlet b:is_bash + endif + if exists("b:is_sh") + unlet b:is_sh + endif + elseif exists("g:bash_is_sh") || a:name =~ '\' || a:name =~ '\' + let b:is_bash = 1 + if exists("b:is_kornshell") + unlet b:is_kornshell + endif + if exists("b:is_sh") + unlet b:is_sh + endif + elseif a:name =~ '\' + let b:is_sh = 1 + if exists("b:is_kornshell") + unlet b:is_kornshell + endif + if exists("b:is_bash") + unlet b:is_bash + endif + endif + call SetFileTypeShell("sh") +endfunc + +" For shell-like file types, check for an "exec" command hidden in a comment, +" as used for Tcl. +" Also called from scripts.vim, thus can't be local to this script. +func! SetFileTypeShell(name) + if expand("") =~ g:ft_ignore_pat + return + endif + let l = 2 + while l < 20 && l < line("$") && getline(l) =~ '^\s*\(#\|$\)' + " Skip empty and comment lines. + let l = l + 1 + endwhile + if l < line("$") && getline(l) =~ '\s*exec\s' && getline(l - 1) =~ '^\s*#.*\\$' + " Found an "exec" line after a comment with continuation + let n = substitute(getline(l),'\s*exec\s\+\([^ ]*/\)\=', '', '') + if n =~ '\' | + \ setf xml | + \ else | + \ setf smil | + \ endif + +" SMIL or SNMP MIB file +au BufNewFile,BufRead *.smi + \ if getline(1) =~ '\' | + \ setf smil | + \ else | + \ setf mib | + \ endif + +" SMITH +au BufNewFile,BufRead *.smt,*.smith setf smith + +" Snobol4 and spitbol +au BufNewFile,BufRead *.sno,*.spt setf snobol4 + +" SNMP MIB files +au BufNewFile,BufRead *.mib,*.my setf mib + +" Snort Configuration +au BufNewFile,BufRead *.hog,snort.conf,vision.conf setf hog +au BufNewFile,BufRead *.rules call s:FTRules() + +let s:ft_rules_udev_rules_pattern = '^\s*\cudev_rules\s*=\s*"\([^"]\{-1,}\)/*".*' +func! s:FTRules() + let path = expand(':p') + if path =~ '^/etc/udev/\%(rules\.d/\)\=.*\.rules$' + setf udevrules + return + endif + if path =~ '^/etc/ufw/' + setf conf " Better than hog + return + endif + try + let config_lines = readfile('/etc/udev/udev.conf') + catch /^Vim\%((\a\+)\)\=:E484/ + setf hog + return + endtry + let dir = expand(':p:h') + for line in config_lines + if line =~ s:ft_rules_udev_rules_pattern + let udev_rules = substitute(line, s:ft_rules_udev_rules_pattern, '\1', "") + if dir == udev_rules + setf udevrules + endif + break + endif + endfor + setf hog +endfunc + + +" Spec (Linux RPM) +au BufNewFile,BufRead *.spec setf spec + +" Speedup (AspenTech plant simulator) +au BufNewFile,BufRead *.speedup,*.spdata,*.spd setf spup + +" Slice +au BufNewFile,BufRead *.ice setf slice + +" Spice +au BufNewFile,BufRead *.sp,*.spice setf spice + +" Spyce +au BufNewFile,BufRead *.spy,*.spi setf spyce + +" Squid +au BufNewFile,BufRead squid.conf setf squid + +" SQL for Oracle Designer +au BufNewFile,BufRead *.tyb,*.typ,*.tyc,*.pkb,*.pks setf sql + +" SQL +au BufNewFile,BufRead *.sql call s:SQL() + +func! s:SQL() + if exists("g:filetype_sql") + exe "setf " . g:filetype_sql + else + setf sql + endif +endfunc + +" SQLJ +au BufNewFile,BufRead *.sqlj setf sqlj + +" SQR +au BufNewFile,BufRead *.sqr,*.sqi setf sqr + +" OpenSSH configuration +au BufNewFile,BufRead ssh_config,*/.ssh/config setf sshconfig + +" OpenSSH server configuration +au BufNewFile,BufRead sshd_config setf sshdconfig + +" Stata +au BufNewFile,BufRead *.ado,*.class,*.do,*.imata,*.mata setf stata + +" SMCL +au BufNewFile,BufRead *.hlp,*.ihlp,*.smcl setf smcl + +" Stored Procedures +au BufNewFile,BufRead *.stp setf stp + +" Standard ML +au BufNewFile,BufRead *.sml setf sml + +" Sratus VOS command macro +au BufNewFile,BufRead *.cm setf voscm + +" Sysctl +au BufNewFile,BufRead /etc/sysctl.conf setf sysctl + +" Synopsys Design Constraints +au BufNewFile,BufRead *.sdc setf sdc + +" Sudoers +au BufNewFile,BufRead /etc/sudoers,sudoers.tmp setf sudoers + +" SVG (Scalable Vector Graphics) +au BufNewFile,BufRead *.svg setf svg + +" If the file has an extension of 't' and is in a directory 't' then it is +" almost certainly a Perl test file. +" If the first line starts with '#' and contains 'perl' it's probably a Perl +" file. +" (Slow test) If a file contains a 'use' statement then it is almost certainly +" a Perl file. +func! s:FTperl() + if expand("%:e") == 't' && expand("%:p:h:t") == 't' + setf perl + return 1 + endif + if getline(1)[0] == '#' && getline(1) =~ 'perl' + setf perl + return 1 + endif + if search('^use\s\s*\k', 'nc', 30) + setf perl + return 1 + endif + return 0 +endfunc + +" Tads (or Nroff or Perl test file) +au BufNewFile,BufRead *.t + \ if !s:FTnroff() && !s:FTperl() | setf tads | endif + +" Tags +au BufNewFile,BufRead tags setf tags + +" TAK +au BufNewFile,BufRead *.tak setf tak + +" Task +au BufRead,BufNewFile {pending,completed,undo}.data setf taskdata +au BufRead,BufNewFile *.task setf taskedit + +" Tcl (JACL too) +au BufNewFile,BufRead *.tcl,*.tk,*.itcl,*.itk,*.jacl setf tcl + +" TealInfo +au BufNewFile,BufRead *.tli setf tli + +" Telix Salt +au BufNewFile,BufRead *.slt setf tsalt + +" Terminfo +au BufNewFile,BufRead *.ti setf terminfo + +" TeX +au BufNewFile,BufRead *.latex,*.sty,*.dtx,*.ltx,*.bbl setf tex +au BufNewFile,BufRead *.tex call s:FTtex() + +" Choose context, plaintex, or tex (LaTeX) based on these rules: +" 1. Check the first line of the file for "%&". +" 2. Check the first 1000 non-comment lines for LaTeX or ConTeXt keywords. +" 3. Default to "latex" or to g:tex_flavor, can be set in user's vimrc. +func! s:FTtex() + let firstline = getline(1) + if firstline =~ '^%&\s*\a\+' + let format = tolower(matchstr(firstline, '\a\+')) + let format = substitute(format, 'pdf', '', '') + if format == 'tex' + let format = 'plain' + endif + else + " Default value, may be changed later: + let format = exists("g:tex_flavor") ? g:tex_flavor : 'plain' + " Save position, go to the top of the file, find first non-comment line. + let save_cursor = getpos('.') + call cursor(1,1) + let firstNC = search('^\s*[^[:space:]%]', 'c', 1000) + if firstNC " Check the next thousand lines for a LaTeX or ConTeXt keyword. + let lpat = 'documentclass\>\|usepackage\>\|begin{\|newcommand\>\|renewcommand\>' + let cpat = 'start\a\+\|setup\a\+\|usemodule\|enablemode\|enableregime\|setvariables\|useencoding\|usesymbols\|stelle\a\+\|verwende\a\+\|stel\a\+\|gebruik\a\+\|usa\a\+\|imposta\a\+\|regle\a\+\|utilisemodule\>' + let kwline = search('^\s*\\\%(' . lpat . '\)\|^\s*\\\(' . cpat . '\)', + \ 'cnp', firstNC + 1000) + if kwline == 1 " lpat matched + let format = 'latex' + elseif kwline == 2 " cpat matched + let format = 'context' + endif " If neither matched, keep default set above. + " let lline = search('^\s*\\\%(' . lpat . '\)', 'cn', firstNC + 1000) + " let cline = search('^\s*\\\%(' . cpat . '\)', 'cn', firstNC + 1000) + " if cline > 0 + " let format = 'context' + " endif + " if lline > 0 && (cline == 0 || cline > lline) + " let format = 'tex' + " endif + endif " firstNC + call setpos('.', save_cursor) + endif " firstline =~ '^%&\s*\a\+' + + " Translation from formats to file types. TODO: add AMSTeX, RevTex, others? + if format == 'plain' + setf plaintex + elseif format == 'context' + setf context + else " probably LaTeX + setf tex + endif + return +endfunc + +" ConTeXt +au BufNewFile,BufRead tex/context/*/*.tex,*.mkii,*.mkiv setf context + +" Texinfo +au BufNewFile,BufRead *.texinfo,*.texi,*.txi setf texinfo + +" TeX configuration +au BufNewFile,BufRead texmf.cnf setf texmf + +" Tidy config +au BufNewFile,BufRead .tidyrc,tidyrc setf tidy + +" TF mud client +au BufNewFile,BufRead *.tf,.tfrc,tfrc setf tf + +" TPP - Text Presentation Program +au BufNewFile,BufReadPost *.tpp setf tpp + +" Trustees +au BufNewFile,BufRead trustees.conf setf trustees + +" TSS - Geometry +au BufNewFile,BufReadPost *.tssgm setf tssgm + +" TSS - Optics +au BufNewFile,BufReadPost *.tssop setf tssop + +" TSS - Command Line (temporary) +au BufNewFile,BufReadPost *.tsscl setf tsscl + +" Motif UIT/UIL files +au BufNewFile,BufRead *.uit,*.uil setf uil + +" Udev conf +au BufNewFile,BufRead /etc/udev/udev.conf setf udevconf + +" Udev permissions +au BufNewFile,BufRead /etc/udev/permissions.d/*.permissions setf udevperm +" +" Udev symlinks config +au BufNewFile,BufRead /etc/udev/cdsymlinks.conf setf sh + +" UnrealScript +au BufNewFile,BufRead *.uc setf uc + +" Updatedb +au BufNewFile,BufRead /etc/updatedb.conf setf updatedb + +" Vera +au BufNewFile,BufRead *.vr,*.vri,*.vrh setf vera + +" Verilog HDL +au BufNewFile,BufRead *.v setf verilog + +" Verilog-AMS HDL +au BufNewFile,BufRead *.va,*.vams setf verilogams + +" VHDL +au BufNewFile,BufRead *.hdl,*.vhd,*.vhdl,*.vbe,*.vst setf vhdl +au BufNewFile,BufRead *.vhdl_[0-9]* call s:StarSetf('vhdl') + +" Vim script +au BufNewFile,BufRead *.vim,*.vba,.exrc,_exrc setf vim + +" Viminfo file +au BufNewFile,BufRead .viminfo,_viminfo setf viminfo + +" Virata Config Script File or Drupal module +au BufRead,BufNewFile *.hw,*.module,*.pkg + \ if getline(1) =~ '' | + \ let b:xf86c_xfree86_version = 3 | + \ endif | + \ setf xf86conf + +" Xorg config +au BufNewFile,BufRead xorg.conf,xorg.conf-4 let b:xf86c_xfree86_version = 4 | setf xf86conf + +" Xinetd conf +au BufNewFile,BufRead /etc/xinetd.conf setf xinetd + +" XS Perl extension interface language +au BufNewFile,BufRead *.xs setf xs + +" X resources file +au BufNewFile,BufRead .Xdefaults,.Xpdefaults,.Xresources,xdm-config,*.ad setf xdefaults + +" Xmath +au BufNewFile,BufRead *.msc,*.msf setf xmath +au BufNewFile,BufRead *.ms + \ if !s:FTnroff() | setf xmath | endif + +" XML specific variants: docbk and xbl +au BufNewFile,BufRead *.xml call s:FTxml() + +func! s:FTxml() + let n = 1 + while n < 100 && n < line("$") + let line = getline(n) + if line =~ '\)' && getline(n) !~ '^\s*#\s*include' + setf racc + return + endif + let n = n + 1 + endwhile + setf yacc +endfunc + + +" Yaml +au BufNewFile,BufRead *.yaml,*.yml setf yaml + +" Zope +" dtml (zope dynamic template markup language), pt (zope page template), +" cpt (zope form controller page template) +au BufNewFile,BufRead *.dtml,*.pt,*.cpt call s:FThtml() +" zsql (zope sql method) +au BufNewFile,BufRead *.zsql call s:SQL() + +" Z80 assembler asz80 +au BufNewFile,BufRead *.z8a setf z8a + +augroup END + + +" Source the user-specified filetype file, for backwards compatibility with +" Vim 5.x. +if exists("myfiletypefile") && filereadable(expand(myfiletypefile)) + execute "source " . myfiletypefile +endif + + +" Check for "*" after loading myfiletypefile, so that scripts.vim is only used +" when there are no matching file name extensions. +" Don't do this for compressed files. +augroup filetypedetect +au BufNewFile,BufRead * + \ if !did_filetype() && expand("") !~ g:ft_ignore_pat + \ | runtime! scripts.vim | endif +au StdinReadPost * if !did_filetype() | runtime! scripts.vim | endif + + +" Extra checks for when no filetype has been detected now. Mostly used for +" patterns that end in "*". E.g., "zsh*" matches "zsh.vim", but that's a Vim +" script file. +" Most of these should call s:StarSetf() to avoid names ending in .gz and the +" like are used. + +" More Apache files. +au BufNewFile,BufRead /etc/apache2/conf.*/*,/etc/apache2/sites-*/*,/etc/apache2/mods-*/* call s:StarSetf('apache') + +" Asterisk config file +au BufNewFile,BufRead *asterisk/*.conf* call s:StarSetf('asterisk') +au BufNewFile,BufRead *asterisk*/*voicemail.conf* call s:StarSetf('asteriskvm') + +" Bazaar version control +au BufNewFile,BufRead bzr_log.* setf bzr + +" BIND zone +au BufNewFile,BufRead */named/db.*,*/bind/db.* call s:StarSetf('bindzone') + +" Changelog +au BufNewFile,BufRead [cC]hange[lL]og* + \ if getline(1) =~ '; urgency=' + \| call s:StarSetf('debchangelog') + \|else + \| call s:StarSetf('changelog') + \|endif + +" Crontab +au BufNewFile,BufRead crontab,crontab.*,/etc/cron.d/* call s:StarSetf('crontab') + +" Debian Sources.list +au BufNewFile,BufRead /etc/apt/sources.list.d/* call s:StarSetf('debsources') + +" Dracula +au BufNewFile,BufRead drac.* call s:StarSetf('dracula') + +" Fvwm +au BufNewFile,BufRead */.fvwm/* call s:StarSetf('fvwm') +au BufNewFile,BufRead *fvwmrc*,*fvwm95*.hook + \ let b:fvwm_version = 1 | call s:StarSetf('fvwm') +au BufNewFile,BufRead *fvwm2rc* + \ if expand(":e") == "m4" + \| call s:StarSetf('fvwm2m4') + \|else + \| let b:fvwm_version = 2 | call s:StarSetf('fvwm') + \|endif + +" Gedcom +au BufNewFile,BufRead /tmp/lltmp* call s:StarSetf('gedcom') + +" GTK RC +au BufNewFile,BufRead .gtkrc*,gtkrc* call s:StarSetf('gtkrc') + +" Jam +au BufNewFile,BufRead Prl*.*,JAM*.* call s:StarSetf('jam') + +" Jargon +au! BufNewFile,BufRead *jarg* + \ if getline(1).getline(2).getline(3).getline(4).getline(5) =~? 'THIS IS THE JARGON FILE' + \| call s:StarSetf('jargon') + \|endif + +" Kconfig +au BufNewFile,BufRead Kconfig.* call s:StarSetf('kconfig') + +" Logcheck +au BufNewFile,BufRead /etc/logcheck/*.d*/* call s:StarSetf('logcheck') + +" Makefile +au BufNewFile,BufRead [mM]akefile* call s:StarSetf('make') + +" Ruby Makefile +au BufNewFile,BufRead [rR]akefile* call s:StarSetf('ruby') + +" Mail (also matches muttrc.vim, so this is below the other checks) +au BufNewFile,BufRead mutt[[:alnum:]._-]\{6\} setf mail + +" Modconf +au BufNewFile,BufRead /etc/modprobe.* call s:StarSetf('modconf') + +" Mutt setup file +au BufNewFile,BufRead .mutt{ng,}rc*,*/.mutt{ng,}/mutt{ng,}rc* call s:StarSetf('muttrc') +au BufNewFile,BufRead mutt{ng,}rc*,Mutt{ng,}rc* call s:StarSetf('muttrc') + +" Nroff macros +au BufNewFile,BufRead tmac.* call s:StarSetf('nroff') + +" Pam conf +au BufNewFile,BufRead /etc/pam.d/* call s:StarSetf('pamconf') + +" Printcap and Termcap +au BufNewFile,BufRead *printcap* + \ if !did_filetype() + \| let b:ptcap_type = "print" | call s:StarSetf('ptcap') + \|endif +au BufNewFile,BufRead *termcap* + \ if !did_filetype() + \| let b:ptcap_type = "term" | call s:StarSetf('ptcap') + \|endif + +" Vim script +au BufNewFile,BufRead *vimrc* call s:StarSetf('vim') + +" Subversion commit file +au BufNewFile,BufRead svn-commit*.tmp setf svn + +" X resources file +au BufNewFile,BufRead Xresources*,*/app-defaults/*,*/Xresources/* call s:StarSetf('xdefaults') + +" XFree86 config +au BufNewFile,BufRead XF86Config-4* + \ let b:xf86c_xfree86_version = 4 | call s:StarSetf('xf86conf') +au BufNewFile,BufRead XF86Config* + \ if getline(1) =~ '\' + \| let b:xf86c_xfree86_version = 3 + \|endif + \|call s:StarSetf('xf86conf') + +" X11 xmodmap +au BufNewFile,BufRead *xmodmap* call s:StarSetf('xmodmap') + +" Xinetd conf +au BufNewFile,BufRead /etc/xinetd.d/* call s:StarSetf('xinetd') + +" Z-Shell script +au BufNewFile,BufRead zsh*,zlog* call s:StarSetf('zsh') + + + +" Use the filetype detect plugins. They may overrule any of the previously +" detected filetypes. +runtime! ftdetect/*.vim + + +" Generic configuration file (check this last, it's just guessing!) +au BufNewFile,BufRead,StdinReadPost * + \ if !did_filetype() && expand("") !~ g:ft_ignore_pat + \ && (getline(1) =~ '^#' || getline(2) =~ '^#' || getline(3) =~ '^#' + \ || getline(4) =~ '^#' || getline(5) =~ '^#') | + \ setf conf | + \ endif + +augroup END + + +" If the GUI is already running, may still need to install the Syntax menu. +" Don't do it when the 'M' flag is included in 'guioptions'. +if has("menu") && has("gui_running") + \ && !exists("did_install_syntax_menu") && &guioptions !~# "M" + source :p:h/menu.vim +endif + +" Function called for testing all functions defined here. These are +" script-local, thus need to be executed here. +" Returns a string with error messages (hopefully empty). +func! TestFiletypeFuncs(testlist) + let output = '' + for f in a:testlist + try + exe f + catch + let output = output . "\n" . f . ": " . v:exception + endtry + endfor + return output +endfunc + +" Restore 'cpoptions' +let &cpo = s:cpo_save +unlet s:cpo_save diff -Naur vim73.orig/runtime/ftplugof.vim vim73/runtime/ftplugof.vim --- vim73.orig/runtime/ftplugof.vim 2010-05-15 11:03:57.000000000 +0000 +++ vim73/runtime/ftplugof.vim 2012-07-20 20:31:13.030974711 +0000 @@ -1,11 +1,13 @@ " Vim support file to switch off loading plugins for file types " " Maintainer: Bram Moolenaar -" Last Change: 2002 Apr 04 +" Last Change: 2011 Oct 20 if exists("did_load_ftplugin") unlet did_load_ftplugin endif -" Remove all autocommands in the filetypeplugin group -silent! au! filetypeplugin * +" Remove all autocommands in the filetypeplugin group, if any exist. +if exists("#filetypeplugin") + silent! au! filetypeplugin * +endif diff -Naur vim73.orig/src/GvimExt/Make_cyg.mak vim73/src/GvimExt/Make_cyg.mak --- vim73.orig/src/GvimExt/Make_cyg.mak 1970-01-01 00:00:00.000000000 +0000 +++ vim73/src/GvimExt/Make_cyg.mak 2012-07-20 20:31:12.867641259 +0000 @@ -0,0 +1,77 @@ +# Project: gvimext +# Generates gvimext.dll with gcc. +# To be used with Cygwin. +# +# Originally, the DLL base address was fixed: -Wl,--image-base=0x1C000000 +# Now it is allocated dymanically by the linker by evaluating all DLLs +# already loaded in memory. The binary image contains as well information +# for automatic pseudo-rebasing, if needed by the system. ALV 2004-02-29 + +# If cross-compiling set this to yes, else set it to no +CROSS = no +#CROSS = yes +# For the old MinGW 2.95 (the one you get e.g. with debian woody) +# set the following variable to yes and check if the executables are +# really named that way. +# If you have a newer MinGW or you are using cygwin set it to no and +# check also the executables +MINGWOLD = no + +# Link against the shared versions of libgcc/libstdc++ by default. Set +# STATIC_STDCPLUS to "yes" to link against static versions instead. +STATIC_STDCPLUS=no +#STATIC_STDCPLUS=yes + +# Note: -static-libstdc++ is not available until gcc 4.5.x. +LDFLAGS += -shared +ifeq (yes, $(STATIC_STDCPLUS)) +LDFLAGS += -static-libgcc -static-libstdc++ +endif + +ifeq ($(CROSS),yes) +DEL = rm +ifeq ($(MINGWOLD),yes) +CXXFLAGS := -O2 -mno-cygwin -fvtable-thunks +else +CXXFLAGS := -O2 -mno-cygwin +endif +else +CXXFLAGS := -O2 -mno-cygwin +ifneq (sh.exe, $(SHELL)) +DEL = rm +else +DEL = del +endif +endif +CXX := $(CROSS_COMPILE)g++ +WINDRES := $(CROSS_COMPILE)windres +WINDRES_CXX = $(CXX) +WINDRES_FLAGS = --preprocessor="$(WINDRES_CXX) -E -xc" -DRC_INVOKED +LIBS := -luuid +RES := gvimext.res +DEFFILE = gvimext_ming.def +OBJ := gvimext.o + +DLL := gvimext.dll + +.PHONY: all all-before all-after clean clean-custom + +all: all-before $(DLL) all-after + +$(DLL): $(OBJ) $(RES) $(DEFFILE) + $(CXX) $(LDFLAGS) $(CXXFLAGS) -s -o $@ \ + -Wl,--enable-auto-image-base \ + -Wl,--enable-auto-import \ + -Wl,--whole-archive \ + $^ \ + -Wl,--no-whole-archive \ + $(LIBS) + +gvimext.o: gvimext.cpp + $(CXX) $(CXXFLAGS) -DFEAT_GETTEXT -c $? -o $@ + +$(RES): gvimext_ming.rc + $(WINDRES) $(WINDRES_FLAGS) --input-format=rc --output-format=coff -DMING $? -o $@ + +clean: clean-custom + -$(DEL) $(OBJ) $(RES) $(DLL) diff -Naur vim73.orig/src/GvimExt/Make_ming.mak vim73/src/GvimExt/Make_ming.mak --- vim73.orig/src/GvimExt/Make_ming.mak 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/GvimExt/Make_ming.mak 2012-07-20 20:31:12.867641259 +0000 @@ -1,6 +1,6 @@ # Project: gvimext # Generates gvimext.dll with gcc. -# Can be used for Cygwin and MingW (MingW ignores -mno-cygwin) +# To be used with MingW. # # Originally, the DLL base address was fixed: -Wl,--image-base=0x1C000000 # Now it is allocated dymanically by the linker by evaluating all DLLs @@ -17,15 +17,26 @@ # check also the executables MINGWOLD = no +# Link against the shared versions of libgcc/libstdc++ by default. Set +# STATIC_STDCPLUS to "yes" to link against static versions instead. +STATIC_STDCPLUS=no +#STATIC_STDCPLUS=yes + +# Note: -static-libstdc++ is not available until gcc 4.5.x. +LDFLAGS += -shared +ifeq (yes, $(STATIC_STDCPLUS)) +LDFLAGS += -static-libgcc -static-libstdc++ +endif + ifeq ($(CROSS),yes) DEL = rm ifeq ($(MINGWOLD),yes) -CXXFLAGS := -O2 -mno-cygwin -fvtable-thunks +CXXFLAGS := -O2 -fvtable-thunks else -CXXFLAGS := -O2 -mno-cygwin +CXXFLAGS := -O2 endif else -CXXFLAGS := -O2 -mno-cygwin +CXXFLAGS := -O2 ifneq (sh.exe, $(SHELL)) DEL = rm else @@ -34,6 +45,8 @@ endif CXX := $(CROSS_COMPILE)g++ WINDRES := $(CROSS_COMPILE)windres +WINDRES_CXX = $(CXX) +WINDRES_FLAGS = --preprocessor="$(WINDRES_CXX) -E -xc" -DRC_INVOKED LIBS := -luuid RES := gvimext.res DEFFILE = gvimext_ming.def @@ -46,7 +59,7 @@ all: all-before $(DLL) all-after $(DLL): $(OBJ) $(RES) $(DEFFILE) - $(CXX) -shared $(CXXFLAGS) -s -o $@ \ + $(CXX) $(LDFLAGS) $(CXXFLAGS) -s -o $@ \ -Wl,--enable-auto-image-base \ -Wl,--enable-auto-import \ -Wl,--whole-archive \ @@ -58,8 +71,7 @@ $(CXX) $(CXXFLAGS) -DFEAT_GETTEXT -c $? -o $@ $(RES): gvimext_ming.rc - $(WINDRES) --input-format=rc --output-format=coff -DMING $? -o $@ + $(WINDRES) $(WINDRES_FLAGS) --input-format=rc --output-format=coff -DMING $? -o $@ clean: clean-custom -$(DEL) $(OBJ) $(RES) $(DLL) - diff -Naur vim73.orig/src/GvimExt/gvimext.cpp vim73/src/GvimExt/gvimext.cpp --- vim73.orig/src/GvimExt/gvimext.cpp 2010-07-10 17:21:34.000000000 +0000 +++ vim73/src/GvimExt/gvimext.cpp 2012-07-20 20:31:12.297640849 +0000 @@ -142,6 +142,7 @@ static int dyn_libintl_init(char *dir); static void dyn_libintl_end(void); +static wchar_t *oldenv = NULL; static HINSTANCE hLibintlDLL = 0; static char *(*dyn_libintl_gettext)(const char *) = null_libintl_gettext; static char *(*dyn_libintl_textdomain)(const char *) = null_libintl_textdomain; @@ -339,8 +340,10 @@ inc_cRefThisDLL() { #ifdef FEAT_GETTEXT - if (g_cRefThisDll == 0) + if (g_cRefThisDll == 0) { dyn_gettext_load(); + oldenv = GetEnvironmentStringsW(); + } #endif InterlockedIncrement((LPLONG)&g_cRefThisDll); } @@ -349,8 +352,13 @@ dec_cRefThisDLL() { #ifdef FEAT_GETTEXT - if (InterlockedDecrement((LPLONG)&g_cRefThisDll) == 0) + if (InterlockedDecrement((LPLONG)&g_cRefThisDll) == 0) { dyn_gettext_free(); + if (oldenv != NULL) { + FreeEnvironmentStringsW(oldenv); + oldenv = NULL; + } + } #else InterlockedDecrement((LPLONG)&g_cRefThisDll); #endif @@ -586,8 +594,23 @@ // Initialize m_cntOfHWnd to 0 m_cntOfHWnd = 0; - // Retrieve all the vim instances - EnumWindows(EnumWindowsProc, (LPARAM)this); + + HKEY keyhandle; + bool showExisting = true; + + // Check whether "Edit with existing Vim" entries are disabled. + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Vim\\Gvim", 0, + KEY_READ, &keyhandle) == ERROR_SUCCESS) + { + if (RegQueryValueEx(keyhandle, "DisableEditWithExisting", 0, NULL, + NULL, NULL) == ERROR_SUCCESS) + showExisting = false; + RegCloseKey(keyhandle); + } + + // Retrieve all the vim instances, unless disabled. + if (showExisting) + EnumWindows(EnumWindowsProc, (LPARAM)this); if (cbFiles > 1) { @@ -890,8 +913,8 @@ NULL, // Process handle not inheritable. NULL, // Thread handle not inheritable. FALSE, // Set handle inheritance to FALSE. - 0, // No creation flags. - NULL, // Use parent's environment block. + oldenv == NULL ? 0 : CREATE_UNICODE_ENVIRONMENT, + oldenv, // Use unmodified environment block. NULL, // Use parent's starting directory. &si, // Pointer to STARTUPINFO structure. &pi) // Pointer to PROCESS_INFORMATION structure. @@ -972,8 +995,8 @@ NULL, // Process handle not inheritable. NULL, // Thread handle not inheritable. FALSE, // Set handle inheritance to FALSE. - 0, // No creation flags. - NULL, // Use parent's environment block. + oldenv == NULL ? 0 : CREATE_UNICODE_ENVIRONMENT, + oldenv, // Use unmodified environment block. NULL, // Use parent's starting directory. &si, // Pointer to STARTUPINFO structure. &pi) // Pointer to PROCESS_INFORMATION structure. diff -Naur vim73.orig/src/GvimExt/gvimext.def vim73/src/GvimExt/gvimext.def --- vim73.orig/src/GvimExt/gvimext.def 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/GvimExt/gvimext.def 2012-07-20 20:31:11.500973609 +0000 @@ -1,7 +1,7 @@ ;gvimdef.def : Declares the module parameters for the DLL. LIBRARY gvimext -DESCRIPTION 'Vim Shell Extension' +; DESCRIPTION 'Vim Shell Extension' EXPORTS DllCanUnloadNow private diff -Naur vim73.orig/src/GvimExt/gvimext_ming.def vim73/src/GvimExt/gvimext_ming.def --- vim73.orig/src/GvimExt/gvimext_ming.def 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/GvimExt/gvimext_ming.def 2012-07-20 20:31:11.500973609 +0000 @@ -3,7 +3,7 @@ ;Hence this is the same file as gvimext.def with private removed LIBRARY gvimext -DESCRIPTION 'Vim Shell Extension build with MinGW' +; DESCRIPTION 'Vim Shell Extension build with MinGW' EXPORTS DllCanUnloadNow = DllCanUnloadNow@0 diff -Naur vim73.orig/src/INSTALL vim73/src/INSTALL --- vim73.orig/src/INSTALL 2010-06-26 04:04:51.000000000 +0000 +++ vim73/src/INSTALL 2012-07-20 20:31:10.884306499 +0000 @@ -6,9 +6,8 @@ Contents: 1. Generic 2. Unix -3. RISC OS -4. OS/2 (with EMX 0.9b) -5. Atari MiNT +3. OS/2 (with EMX 0.9b) +4. Atari MiNT See INSTALLami.txt for Amiga See INSTALLmac.txt for Macintosh @@ -174,25 +173,7 @@ ./configure --without-local-dir -3. RISC OS -============= - -Much file renaming is needed before you can compile anything. -You'll need UnixLib to link against, GCC and GNU make. - -I suggest you get the RISC OS binary distribution, which includes the -Templates file and the loader. - -Try here: http://www.ecs.soton.ac.uk/~tal197 - -Do - :help riscos - -within the editor for more information, or read the -../runtime/doc/os_risc.txt help file. - - -4. OS/2 +3. OS/2 ======= Summary: @@ -237,7 +218,7 @@ Check ../runtime/doc/os_os2.txt for additional info on running Vim. -5. Atari MiNT +4. Atari MiNT ============= [NOTE: this is quite old, it might not work anymore] diff -Naur vim73.orig/src/INSTALLpc.txt vim73/src/INSTALLpc.txt --- vim73.orig/src/INSTALLpc.txt 2010-05-24 12:58:06.000000000 +0000 +++ vim73/src/INSTALLpc.txt 2012-07-20 20:31:15.140976226 +0000 @@ -11,9 +11,9 @@ this, then you will get the default behavior as is documented, which should be fine for most people. -With the exception of the last two sections (Windows 3.1 and MS-DOS), -this document assumes that you are building Vim for Win32 -(Windows NT/2000/XP/2003/Vista and Windows 95/98/Me) +With the exception of two sections (Windows 3.1 and MS-DOS), this document +assumes that you are building Vim for Win32 or later. +(Windows 95/98/Me/NT/2000/XP/2003/Vista/7) Contents: @@ -27,9 +27,13 @@ 8. Windows 3.1 9. MS-DOS +10. Installing after building from sources + + The currently preferred method is using the free Visual C++ Toolkit 2008 -|msvc-2008-express|. If you need the executable to run on Windows 98 or ME, -use the 2003 one |msvc-2003-toolkit|. +|msvc-2008-express|, the produced binary runs on most MS-Windows systems. If +you need the executable to run on Windows 98 or ME, use the 2003 one +|msvc-2003-toolkit|. 1. Microsoft Visual C++ @@ -176,7 +180,7 @@ http://www.microsoft.com/express/vc/Default.aspx This includes the IDE and the debugger. -To set the environment execute the msvc2008.bat script. You can then build +To set the environment execute the msvc2010.bat script. You can then build Vim with Make_mvc.mak. @@ -235,6 +239,12 @@ found at http://www.upx.org/ +As of 2011, UPX still does not support compressing 64-bit EXE's; if you have +built a 64-bit vim then an alternative to UPX is 'MPRESS'. MPRESS can be found +at: + http://www.matcode.com/mpress.htm + + ADDITION: NLS support with MinGW (by Eduardo F. Amatria ) @@ -408,3 +418,59 @@ If you get all kinds of strange error messages when compiling, try adding changing the file format from "unix" to "dos". + + +10. Installing after building from sources +========================================== + +[provided by Michael Soyka] + +After you've built the Vim binaries as described above, you're ready to +install Vim on your system. However, if you've obtained the Vim sources +using Mercurial or by downloading them as a unix tar file, you must first +create a "vim73" directory. If you instead downloaded the sources as +zip files, you can skip this setup as the zip archives already have the +correct directory structure. + + A. Create a Vim "runtime" subdirectory named "vim73" + ----------------------------------------------------- + If you obtained your Vim sources as zip files, you can skip this step. + Otherwise, continue reading. + + Go to the directory that contains the Vim "src" and "runtime" + directories and create a new subdirectory named "vim73". + + Copy the "runtime" files into "vim73": + copy runtime\* vim73 + + B. Copy the new binaries into the "vim73" directory + ---------------------------------------------------- + Regardless of how you installed the Vim sources, you need to copy the + new binaries you created above into "vim73": + + copy src\*.exe vim73 + copy src\GvimExt\gvimext.dll vim73 + copy src\xxd\xxd.exe vim73 + + C. Move the "vim73" directory into the Vim installation subdirectory + --------------------------------------------------------------------- + Move the "vim73" subdirectory into the subdirectory where you want Vim + to be installed. Typically, this subdirectory will be named "vim". + If you already have a "vim73" subdirectory in "vim", delete it first + by running its unstal.exe program. + + D. Install Vim + --------------- + "cd" to your Vim installation subdirectory "vim\vim73" and run the + "install.exe" program. It will ask you a number of questions about + how you would like to have your Vim setup. Among these are: + - You can tell it to write a "_vimrc" file with your preferences in the + parent directory. + - It can also install an "Edit with Vim" entry in the Windows Explorer + popup menu. + - You can have it create batch files, so that you can run Vim from the + console or in a shell. You can select one of the directories in your + PATH or add the directory to PATH using the Windows Control Panel. + - Create entries for Vim on the desktop and in the Start menu. + +Happy Vimming! diff -Naur vim73.orig/src/Make_cyg.mak vim73/src/Make_cyg.mak --- vim73.orig/src/Make_cyg.mak 2010-08-02 19:09:22.000000000 +0000 +++ vim73/src/Make_cyg.mak 2012-07-20 20:31:17.854311501 +0000 @@ -1,6 +1,6 @@ # # Makefile for VIM on Win32, using Cygnus gcc -# Last updated by Dan Sharp. Last Change: 2010 Feb 24 +# Last updated by Dan Sharp. Last Change: 2012 Jun 30 # # Also read INSTALLpc.txt! # @@ -27,6 +27,7 @@ # MZSCHEME_VER define to version of MzScheme being used (209_000) # DYNAMIC_MZSCHEME no or yes: use yes to load the MzScheme DLLs dynamically (yes) # MZSCHEME_DLLS path to MzScheme DLLs (libmzgc and libmzsch), for "static" build. +# MZSCHEME_USE_RACKET define to use "racket" instead of "mzsch". # LUA define to path to Lua dir to get Lua support (not defined) # LUA_VER define to version of Lua being used (51) # DYNAMIC_LUA no or yes: use yes to load the Lua DLL dynamically (yes) @@ -47,7 +48,7 @@ # -L/lib/w32api to EXTRA_LIBS. # POSTSCRIPT no or yes: set to yes for PostScript printing (no) # FEATURES TINY, SMALL, NORMAL, BIG or HUGE (BIG) -# WINVER Lowest Win32 version to support. (0x0400) +# WINVER Lowest Win32 version to support. (0x0500) # CSCOPE no or yes: to include cscope interface support (yes) # OPTIMIZE SPACE, SPEED, or MAXSPEED: set optimization level (MAXSPEED) # NETBEANS no or yes: to include netbeans interface support (yes when GUI @@ -84,7 +85,7 @@ endif ifndef WINVER -WINVER = 0x0400 +WINVER = 0x0500 endif ifndef CSCOPE @@ -254,16 +255,22 @@ MZSCHEME_GENERATE_BASE=no endif +ifndef MZSCHEME_USE_RACKET +MZSCHEME_MAIN_LIB=mzsch +else +MZSCHEME_MAIN_LIB=racket +endif + ifeq (yes, $(DYNAMIC_MZSCHEME)) -DEFINES += -DDYNAMIC_MZSCHEME -DDYNAMIC_MZSCH_DLL=\"libmzsch$(MZSCHEME_VER).dll\" -DDYNAMIC_MZGC_DLL=\"libmzgc$(MZSCHEME_VER).dll\" +DEFINES += -DDYNAMIC_MZSCHEME -DDYNAMIC_MZSCH_DLL=\"lib$(MZSCHEME_MAIN_LIB)$(MZSCHEME_VER).dll\" -DDYNAMIC_MZGC_DLL=\"libmzgc$(MZSCHEME_VER).dll\" else ifndef MZSCHEME_DLLS MZSCHEME_DLLS = $(MZSCHEME) endif ifeq (yes,$(MZSCHEME_PRECISE_GC)) -MZSCHEME_LIB=-lmzsch$(MZSCHEME_VER) +MZSCHEME_LIB=-l$(MZSCHEME_MAIN_LIB)$(MZSCHEME_VER) else -MZSCHEME_LIB = -lmzsch$(MZSCHEME_VER) -lmzgc$(MZSCHEME_VER) +MZSCHEME_LIB = -l$(MZSCHEME_MAIN_LIB)$(MZSCHEME_VER) -lmzgc$(MZSCHEME_VER) endif EXTRA_LIBS += -L$(MZSCHEME_DLLS) -L$(MZSCHEME_DLLS)/lib $(MZSCHEME_LIB) endif @@ -529,7 +536,7 @@ $(MAKE) -C xxd -f Make_cyg.mak CC=$(CC) USEDLL=$(USEDLL) GvimExt/gvimext.dll: GvimExt/gvimext.cpp GvimExt/gvimext.rc GvimExt/gvimext.h - $(MAKE) -C GvimExt -f Make_ming.mak CROSS_COMPILE=$(CROSS_COMPILE) + $(MAKE) -C GvimExt -f Make_cyg.mak CROSS_COMPILE=$(CROSS_COMPILE) vimrun.exe: vimrun.c $(CC) $(CFLAGS) -o vimrun.exe vimrun.c $(LIBS) @@ -558,7 +565,7 @@ endif -$(DEL) pathdef.c $(MAKE) -C xxd -f Make_cyg.mak clean - $(MAKE) -C GvimExt -f Make_ming.mak clean + $(MAKE) -C GvimExt -f Make_cyg.mak clean distclean: clean -$(DEL) obj$(DIRSLASH)*.o diff -Naur vim73.orig/src/Make_ming.mak vim73/src/Make_ming.mak --- vim73.orig/src/Make_ming.mak 2010-08-02 19:09:43.000000000 +0000 +++ vim73/src/Make_ming.mak 2012-07-20 20:31:17.854311501 +0000 @@ -14,9 +14,11 @@ # it's just run out of memory or something. Run again, and it will continue # with 'xxd'. # -# "make upx" makes *compressed* versions of the GUI and console EXEs, using the -# excellent UPX compressor: +# "make upx" makes *compressed* versions of the 32 bit GUI and console EXEs, +# using the excellent UPX compressor: # http://upx.sourceforge.net/ +# "make mpress" uses the MPRESS compressor for 32- and 64-bit EXEs: +# http://www.matcode.com/mpress.htm # # Maintained by Ron Aaron # updated 2003 Jan 20 @@ -49,13 +51,21 @@ # set to yes to enable OLE support OLE=no # Set the default $(WINVER) to make it work with pre-Win2k -WINVER = 0x0400 +ifndef WINVER +WINVER = 0x0500 +endif # Set to yes to enable Cscope support CSCOPE=yes # Set to yes to enable Netbeans support NETBEANS=$(GUI) +# Link against the shared version of libstdc++ by default. Set +# STATIC_STDCPLUS to "yes" to link against static version instead. +ifndef STATIC_STDCPLUS +STATIC_STDCPLUS=no +endif + # If the user doesn't want gettext, undefine it. ifeq (no, $(GETTEXT)) GETTEXT= @@ -81,7 +91,7 @@ # If you are using gettext-0.10.35 from http://sourceforge.net/projects/gettext # or gettext-0.10.37 from http://sourceforge.net/projects/mingwrep/ -# uncomment the following, but I can't build a static versión with them, ?-(| +# uncomment the following, but I can't build a static version with them, ?-(| #GETTEXT=c:/gettext-0.10.37-20010430 #STATIC_GETTEXT=USE_STATIC_GETTEXT #DYNAMIC_GETTEXT=DYNAMIC_GETTEXT @@ -102,6 +112,13 @@ # on NT, it's here: PERLLIB=$(PERL)/lib PERLLIBS=$(PERLLIB)/Core +XSUBPPTRY=$(PERLLIB)/ExtUtils/xsubpp +XSUBPP_EXISTS=$(shell perl -e "print 1 unless -e '$(XSUBPPTRY)'") +ifeq "$(XSUBPP_EXISTS)" "" +XSUBPP=perl $(XSUBPPTRY) +else +XSUBPP=xsubpp +endif endif # uncomment 'LUA' if you want a Lua-enabled version @@ -141,11 +158,17 @@ MZSCHEME_GENERATE_BASE=no endif +ifndef MZSCHEME_USE_RACKET +MZSCHEME_MAIN_LIB=mzsch +else +MZSCHEME_MAIN_LIB=racket +endif + ifeq (no,$(DYNAMIC_MZSCHEME)) ifeq (yes,$(MZSCHEME_PRECISE_GC)) -MZSCHEME_LIB=-lmzsch$(MZSCHEME_VER) +MZSCHEME_LIB=-l$(MZSCHEME_MAIN_LIB)$(MZSCHEME_VER) else -MZSCHEME_LIB = -lmzsch$(MZSCHEME_VER) -lmzgc$(MZSCHEME_VER) +MZSCHEME_LIB = -l$(MZSCHEME_MAIN_LIB)$(MZSCHEME_VER) -lmzgc$(MZSCHEME_VER) endif # the modern MinGW can dynamically link to dlls directly. # point MZSCHEME_DLLS to where you put libmzschXXXXXXX.dll and libgcXXXXXXX.dll @@ -304,11 +327,13 @@ endif CC := $(CROSS_COMPILE)gcc WINDRES := $(CROSS_COMPILE)windres +WINDRES_CC = $(CC) #>>>>> end of choices ########################################################################### CFLAGS = -Iproto $(DEFINES) -pipe -w -march=$(ARCH) -Wall +WINDRES_FLAGS = --preprocessor="$(WINDRES_CC) -E -xc" -DRC_INVOKED ifdef GETTEXT DEFINES += -DHAVE_GETTEXT -DHAVE_LOCALE_H @@ -343,7 +368,7 @@ ifdef MZSCHEME CFLAGS += -I$(MZSCHEME)/include -DFEAT_MZSCHEME -DMZSCHEME_COLLECTS=\"$(MZSCHEME)/collects\" ifeq (yes, $(DYNAMIC_MZSCHEME)) -CFLAGS += -DDYNAMIC_MZSCHEME -DDYNAMIC_MZSCH_DLL=\"libmzsch$(MZSCHEME_VER).dll\" -DDYNAMIC_MZGC_DLL=\"libmzgc$(MZSCHEME_VER).dll\" +CFLAGS += -DDYNAMIC_MZSCHEME -DDYNAMIC_MZSCH_DLL=\"lib$(MZSCHEME_MAIN_LIB)$(MZSCHEME_VER).dll\" -DDYNAMIC_MZGC_DLL=\"libmzgc$(MZSCHEME_VER).dll\" endif endif @@ -571,8 +596,13 @@ endif ifeq (yes, $(OLE)) -LIB += -loleaut32 -lstdc++ +LIB += -loleaut32 OBJ += $(OUTDIR)/if_ole.o +ifeq (yes, $(STATIC_STDCPLUS)) +LIB += -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic +else +LIB += -lstdc++ +endif endif ifeq (yes, $(MBYTE)) @@ -614,8 +644,12 @@ upx gvim.exe upx vim.exe +mpress: exes + mpress gvim.exe + mpress vim.exe + xxd/xxd.exe: xxd/xxd.c - $(MAKE) -C xxd -f Make_cyg.mak CC=$(CC) + $(MAKE) -C xxd -f Make_ming.mak CC=$(CC) GvimExt/gvimext.dll: GvimExt/gvimext.cpp GvimExt/gvimext.rc GvimExt/gvimext.h $(MAKE) -C GvimExt -f Make_ming.mak CROSS=$(CROSS) CROSS_COMPILE=$(CROSS_COMPILE) @@ -633,7 +667,7 @@ -$(DEL) mzscheme_base.c endif $(MAKE) -C GvimExt -f Make_ming.mak clean - $(MAKE) -C xxd -f Make_cyg.mak clean + $(MAKE) -C xxd -f Make_ming.mak clean ########################################################################### INCL = vim.h feature.h os_win32.h os_dos.h ascii.h keymap.h term.h macros.h \ @@ -649,11 +683,9 @@ $(OUTDIR)/%.o : %.c $(INCL) $(CC) -c $(CFLAGS) $< -o $@ -$(OUTDIR)/vimres.res: vim.rc version.h gui_w32_rc.h - $(WINDRES) $(DEFINES) vim.rc $(OUTDIR)/vimres.res - -$(OUTDIR)/vimrc.o: $(OUTDIR)/vimres.res - $(WINDRES) $(OUTDIR)/vimres.res $(OUTDIR)/vimrc.o +$(OUTDIR)/vimrc.o: vim.rc version.h gui_w32_rc.h + $(WINDRES) $(WINDRES_FLAGS) $(DEFINES) \ + --input-format=rc --output-format=coff -i vim.rc -o $@ $(OUTDIR): $(MKDIR) $(OUTDIR) @@ -677,7 +709,7 @@ endif if_perl.c: if_perl.xs typemap - perl $(PERLLIB)/ExtUtils/xsubpp -prototypes -typemap \ + $(XSUBPP) -prototypes -typemap \ $(PERLLIB)/ExtUtils/typemap if_perl.xs > $@ $(OUTDIR)/netbeans.o: netbeans.c $(INCL) $(NBDEBUG_INCL) $(NBDEBUG_SRC) diff -Naur vim73.orig/src/Make_mvc.mak vim73/src/Make_mvc.mak --- vim73.orig/src/Make_mvc.mak 2010-07-18 19:24:20.000000000 +0000 +++ vim73/src/Make_mvc.mak 2012-07-20 20:31:14.987642782 +0000 @@ -380,9 +380,6 @@ !if "$(_NMAKE_VER)" == "10.00.30319.01" MSVCVER = 10.0 !endif -!if "$(_NMAKE_VER)" == "9.00.30729.01" -MSVCVER = 9.0 -!endif !endif # Abort bulding VIM if version of VC is unrecognised. @@ -412,8 +409,8 @@ CPUARG = !endif !else -# VC8/9 only allows specifying SSE architecture -!if "$(CPUNR)" == "pentium4" +# VC8/9/10 only allows specifying SSE architecture but only for 32bit +!if "$(ASSEMBLY_ARCHITECTURE)" == "x86" && "$(CPUNR)" == "pentium4" CPUARG = /arch:SSE2 !endif !endif @@ -619,7 +616,7 @@ -DDYNAMIC_TCL_VER=\"$(TCL_VER_LONG)\" TCL_OBJ = $(OUTDIR)\if_tcl.obj TCL_INC = /I "$(TCL)\Include" /I "$(TCL)" -TCL_LIB = $(TCL)\lib\tclstub$(TCL_VER).lib +TCL_LIB = "$(TCL)\lib\tclstub$(TCL_VER).lib" !else CFLAGS = $(CFLAGS) -DFEAT_TCL TCL_OBJ = $(OUTDIR)\if_tcl.obj @@ -705,12 +702,18 @@ MZSCHEME_VER = 205_000 !endif CFLAGS = $(CFLAGS) -DFEAT_MZSCHEME -I $(MZSCHEME)\include -!if EXIST("$(MZSCHEME)\collects\scheme\base.ss") -# for MzScheme 4.x we need to include byte code for basic Scheme stuff +!if EXIST("$(MZSCHEME)\collects\scheme\base.ss") \ + || EXIST("$(MZSCHEME)\collects\scheme\base.rkt") +# for MzScheme >= 4 we need to include byte code for basic Scheme stuff MZSCHEME_EXTRA_DEP = mzscheme_base.c CFLAGS = $(CFLAGS) -DINCLUDE_MZSCHEME_BASE !endif -!if EXIST("$(MZSCHEME)\lib\msvc\libmzsch$(MZSCHEME_VER).lib") \ +!if EXIST("$(MZSCHEME)\lib\msvc\libmzsch$(MZSCHEME_VER).lib") +MZSCHEME_MAIN_LIB=mzsch +!else +MZSCHEME_MAIN_LIB=racket +!endif +!if EXIST("$(MZSCHEME)\lib\msvc\lib$(MZSCHEME_MAIN_LIB)$(MZSCHEME_VER).lib") \ && !EXIST("$(MZSCHEME)\lib\msvc\libmzgc$(MZSCHEME_VER).lib") !message Building with Precise GC MZSCHEME_PRECISE_GC = yes @@ -722,7 +725,7 @@ !endif !message MzScheme DLLs will be loaded dynamically CFLAGS = $(CFLAGS) -DDYNAMIC_MZSCHEME \ - -DDYNAMIC_MZSCH_DLL=\"libmzsch$(MZSCHEME_VER).dll\" \ + -DDYNAMIC_MZSCH_DLL=\"lib$(MZSCHEME_MAIN_LIB)$(MZSCHEME_VER).dll\" \ -DDYNAMIC_MZGC_DLL=\"libmzgc$(MZSCHEME_VER).dll\" !else !if "$(MZSCHEME_DEBUG)" == "yes" @@ -730,13 +733,15 @@ !endif !if "$(MZSCHEME_PRECISE_GC)" == "yes" # Precise GC does not use separate dll -MZSCHEME_LIB = $(MZSCHEME)\lib\msvc\libmzsch$(MZSCHEME_VER).lib +MZSCHEME_LIB = $(MZSCHEME)\lib\msvc\lib$(MZSCHEME_MAIN_LIB)$(MZSCHEME_VER).lib !else MZSCHEME_LIB = $(MZSCHEME)\lib\msvc\libmzgc$(MZSCHEME_VER).lib \ - $(MZSCHEME)\lib\msvc\libmzsch$(MZSCHEME_VER).lib + $(MZSCHEME)\lib\msvc\lib$(MZSCHEME_MAIN_LIB)$(MZSCHEME_VER).lib !endif !endif MZSCHEME_OBJ = $(OUTDIR)\if_mzsch.obj +# increase stack size +MZSCHEME_LIB = $(MZSCHEME_LIB) /STACK:8388608 !endif # Perl interface @@ -782,6 +787,11 @@ PERL_INC = /I $(PERL_INCDIR) PERL_OBJ = $(OUTDIR)\if_perl.obj $(OUTDIR)\if_perlsfio.obj XSUBPP = $(PERL)\lib\ExtUtils\xsubpp +!if exist($(XSUBPP)) +XSUBPP = $(PERL_EXE) $(XSUBPP) +!else +XSUBPP = xsubpp +!endif XSUBPP_TYPEMAP = $(PERL)\lib\ExtUtils\typemap !endif @@ -1038,7 +1048,7 @@ $(CC) $(CFLAGS) $(LUA_INC) if_lua.c if_perl.c : if_perl.xs typemap - $(PERL_EXE) $(XSUBPP) -prototypes -typemap $(XSUBPP_TYPEMAP) \ + $(XSUBPP) -prototypes -typemap $(XSUBPP_TYPEMAP) \ -typemap typemap if_perl.xs > if_perl.c $(OUTDIR)/if_perl.obj: $(OUTDIR) if_perl.c $(INCL) @@ -1156,6 +1166,10 @@ E0_CFLAGS = $(CFLAGS:\=\\) E_CFLAGS = $(E0_CFLAGS:"=\") # ") stop the string +# $LINKARGS2 may contain backslashes and double quotes, escape them both. +E0_LINKARGS2 = $(LINKARGS2:\=\\) +E_LINKARGS2 = $(E0_LINKARGS2:"=\") +# ") stop the string $(PATHDEF_SRC): auto @echo creating $(PATHDEF_SRC) @@ -1164,7 +1178,7 @@ @echo char_u *default_vim_dir = (char_u *)"$(VIMRCLOC:\=\\)"; >> $(PATHDEF_SRC) @echo char_u *default_vimruntime_dir = (char_u *)"$(VIMRUNTIMEDIR:\=\\)"; >> $(PATHDEF_SRC) @echo char_u *all_cflags = (char_u *)"$(CC:\=\\) $(E_CFLAGS)"; >> $(PATHDEF_SRC) - @echo char_u *all_lflags = (char_u *)"$(link:\=\\) $(LINKARGS1:\=\\) $(LINKARGS2:\=\\)"; >> $(PATHDEF_SRC) + @echo char_u *all_lflags = (char_u *)"$(link:\=\\) $(LINKARGS1:\=\\) $(E_LINKARGS2)"; >> $(PATHDEF_SRC) @echo char_u *compiled_user = (char_u *)"$(USERNAME)"; >> $(PATHDEF_SRC) @echo char_u *compiled_sys = (char_u *)"$(USERDOMAIN)"; >> $(PATHDEF_SRC) diff -Naur vim73.orig/src/Make_ro.mak vim73/src/Make_ro.mak --- vim73.orig/src/Make_ro.mak 2010-05-15 11:04:08.000000000 +0000 +++ vim73/src/Make_ro.mak 1970-01-01 00:00:00.000000000 +0000 @@ -1,135 +0,0 @@ -# -# Makefile for Vim on RISC OS - Andy Wingate -# - -GCC = gcc -mthrowback -CFLAGS = -DRISCOS -DFEAT_GUI -CC = $(GCC) $(CFLAGS) -O2 -# -DUP_BC_PC_EXTERN for term.c needed as BC defined in termlib.c and term.c - -TERMFLAG = -DUP_BC_PC_EXTERN - -ASMFLAGS = -throwback -objasm -gcc - -OBJS = o.buffer o.charset o.diff o.digraph o.edit o.eval o.ex_cmds o.ex_cmds2 \ - o.ex_docmd o.ex_eval o.ex_getln o.fileio o.fold o.getchar \ - o.hardcopy o.hashtab o.main o.mark o.mbyte \ - o.memfile o.memline o.menu o.message o.misc1 o.misc2 o.move \ - o.normal o.ops o.option o.popupmnu o.quickfix o.regexp o.screen \ - o.search \ - o.spell o.syntax o.tag o.term o.termlib o.ui o.undo o.version \ - o.window o.os_riscos o.swis o.gui o.gui_riscos - -Vim: $(OBJS) - $(GCC) -o Vim $(OBJS) - -install: Vim - squeeze -v Vim @.!Vim.Vim - -clean: - create o.!fake! 0 - wipe o.* ~cf - remove Vim - -o.swis: s.swis - as $(ASMFLAGS) -o o.swis s.swis - -# Rules for object files - -o.%: c.% - $(CC) -c $< -o $@ - -o.buffer: c.buffer - -o.charset: c.charset - -o.digraph: c.digraph - -o.diff: c.diff - -o.edit: c.edit - -o.eval: c.eval - -o.ex_cmds: c.ex_cmds - -o.ex_cmds2: c.ex_cmds2 - -o.ex_docmd: c.ex_docmd - -o.ex_eval: c.ex_eval - -o.ex_getln: c.ex_getln - -o.fileio: c.fileio - -o.fold: c.fold - -o.getchar: c.getchar - -o.hardcopy: c.hardcopy - -o.hashtab: c.hashtab - -o.gui: c.gui - -o.gui_riscos: c.gui_riscos - -o.main: c.main - -o.mark: c.mark - -o.mbyte: c.mbyte - -o.memfile: c.memfile - -o.memline: c.memline - -o.menu: c.menu - -o.message: c.message - -o.misc1: c.misc1 - -o.misc2: c.misc2 - -o.move: c.move - -o.normal: c.normal - -o.ops: c.ops - -o.option: c.option - -o.os_riscos: c.os_riscos - -o.pty: c.pty - -o.popupmnu: c.popupmnu - -o.quickfix: c.quickfix - -o.regexp: c.regexp - -o.screen: c.screen - -o.search: c.search - -o.spell: c.spell - -o.syntax: c.syntax - -o.tag: c.tag - -o.term: c.term - $(CC) $(TERMFLAG) -c c.term -o o.term - -o.termlib: c.termlib - -o.ui: c.ui - -o.undo: c.undo - -o.version: c.version - -o.window: c.window diff -Naur vim73.orig/src/Makefile vim73/src/Makefile --- vim73.orig/src/Makefile 2010-08-15 12:56:15.000000000 +0000 +++ vim73/src/Makefile 2012-07-20 20:31:17.217644379 +0000 @@ -29,7 +29,7 @@ # - Uncomment the line "CONF_OPT_X = --without-x" if you have X11 but # want to disable using X11 libraries. This speeds up starting Vim, # but the window title will not be set and the X11 selection can not -# used. +# be used. # - Uncomment the line "CONF_OPT_XSMP = --disable-xsmp" if you have the # X11 Session Management Protocol (XSMP) library (libSM) but do not # want to use it. @@ -283,12 +283,13 @@ ######################## auto/config.mk ######################## {{{1 # At this position auto/config.mk is included. When starting from the -# distribution it is almost empty. After running auto/configure it contains -# settings that have been discovered for your system. Settings below this -# include override settings in auto/config.mk! - -# Note: if auto/config.mk is lost somehow (e.g., because configure was -# interrupted), create an empty auto/config.mk file and do "make config". +# toplevel Makefile it is almost empty. After running auto/configure it +# contains settings that have been discovered for your system. Settings below +# this include override settings in auto/config.mk! + +# Note: If make fails because auto/config.mk does not exist (it is not +# included in the repository), do: +# cp config.mk.dist auto/config.mk # (X) How to include auto/config.mk depends on the version of "make" you have, # if the current choice doesn't work, try the other one. @@ -388,6 +389,11 @@ #CONF_OPT_PLTHOME = --with-plthome=/usr/local/drscheme #CONF_OPT_PLTHOME = --with-plthome=/home/me/mz +# Uncomment the next line to fail if one of the requested language interfaces +# cannot be configured. Without this Vim will be build anyway, without +# the failing interfaces. +#CONF_OPT_FAIL = --enable-fail-if-missing + # PERL # Uncomment one of these when you want to include the Perl interface. # First one is for static linking, second one for dynamic loading. @@ -414,12 +420,16 @@ # However, this may still cause problems, such as "import termios" failing. # Build two separate versions of Vim in that case. #CONF_OPT_PYTHON = --enable-pythoninterp +#CONF_OPT_PYTHON = --enable-pythoninterp=dynamic #CONF_OPT_PYTHON3 = --enable-python3interp +#CONF_OPT_PYTHON3 = --enable-python3interp=dynamic # RUBY # Uncomment this when you want to include the Ruby interface. +# First one for static linking, second one for loading when used. # Note: you need the development package (e.g., ruby1.9.1-dev on Ubuntu). #CONF_OPT_RUBY = --enable-rubyinterp +#CONF_OPT_RUBY = --enable-rubyinterp=dynamic #CONF_OPT_RUBY = --enable-rubyinterp --with-ruby-command=ruby1.9.1 # TCL @@ -556,8 +566,8 @@ #CFLAGS = -g -O2 '-DSTARTUPTIME="vimstartup"' -fno-strength-reduce -Wall -Wmissing-prototypes # Use this with GCC to check for mistakes, unused arguments, etc. -#CFLAGS = -g -Wall -Wextra -Wmissing-prototypes -Wunreachable-code -D_FORTIFY_SOURCE=1 -DU_DEBUG -#CFLAGS = -g -O2 -Wall -Wextra -Wmissing-prototypes -D_FORTIFY_SOURCE=1 -DU_DEBUG +#CFLAGS = -g -Wall -Wextra -Wmissing-prototypes -Wunreachable-code -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 +#CFLAGS = -g -O2 -Wall -Wextra -Wmissing-prototypes -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -DU_DEBUG #PYTHON_CFLAGS_EXTRA = -Wno-missing-field-initializers #MZSCHEME_CFLAGS_EXTRA = -Wno-unreachable-code -Wno-unused-parameter @@ -589,8 +599,9 @@ # PROFILING - Uncomment the next two lines to do profiling with gcc and gprof. # Might not work with GUI or Perl. -# For unknown reasons adding "-lc" fixes a linking problem with GCC. That's -# probably a bug in the "-pg" implementation. +# For unknown reasons adding "-lc" fixes a linking problem with some versions +# of GCC. That's probably a bug in the "-pg" implementation. +# After running Vim see the profile result with: gmon vim gmon.out | vim - # Need to recompile everything after changing this: "make clean" "make". #PROFILE_CFLAGS = -pg -g -DWE_ARE_PROFILING #PROFILE_LIBS = -pg @@ -601,8 +612,8 @@ # Configuration is in the .ccmalloc or ~/.ccmalloc file. # Doesn't work very well, since memory linked to from global variables # (in libraries) is also marked as leaked memory. -#PROFILE_CFLAGS = -DEXITFREE -#PROFILE_LIBS = -lccmalloc +#LEAK_CFLAGS = -DEXITFREE +#LEAK_LIBS = -lccmalloc ##################################################### ### Specific systems, check if yours is listed! ### {{{ @@ -724,12 +735,6 @@ ### USL for Unix Systems Laboratories (SYSV 4.2) #EXTRA_DEFS = -DUSL -### RISCos on MIPS without X11 -#EXTRA_DEFS = -DMIPS - -### RISCos on MIPS with X11 -#EXTRA_LIBS = -lsun - ### (6) A/UX 3.1.1 with gcc (Jim Jagielski) #CC= gcc -D_POSIX_SOURCE #CFLAGS= -O2 @@ -870,6 +875,10 @@ #CFLAGS = -O -Qtarget=m88110compat #EXTRA_LIBS = -lgen +# The value of QUOTESED comes from auto/config.mk. +# Uncomment the next line to use the default value. +# QUOTESED = sed -e 's/[\\"]/\\&/g' -e 's/\\"/"/' -e 's/\\";$$/";/' + ##################### end of system specific lines ################### }}} ### Names of the programs and targets {{{1 @@ -1047,8 +1056,9 @@ INSTALL_DATA = cp INSTALL_DATA_R = cp -r -### Program to run on installed binary +### Program to run on installed binary. Use the second one to disable strip. #STRIP = strip +#STRIP = /bin/true ### Permissions for binaries {{{1 BINMOD = 755 @@ -1321,15 +1331,15 @@ .SUFFIXES: .c .o .pro PRE_DEFS = -Iproto $(DEFS) $(GUI_DEFS) $(GUI_IPATH) $(CPPFLAGS) $(EXTRA_IPATHS) -POST_DEFS = $(X_CFLAGS) $(MZSCHEME_CFLAGS) $(TCL_CFLAGS) $(RUBY_CFLAGS) $(EXTRA_DEFS) +POST_DEFS = $(X_CFLAGS) $(MZSCHEME_CFLAGS) $(TCL_CFLAGS) $(EXTRA_DEFS) -ALL_CFLAGS = $(PRE_DEFS) $(CFLAGS) $(PROFILE_CFLAGS) $(POST_DEFS) +ALL_CFLAGS = $(PRE_DEFS) $(CFLAGS) $(PROFILE_CFLAGS) $(LEAK_CFLAGS) $(POST_DEFS) # Exclude $CFLAGS for osdef.sh, for Mac 10.4 some flags don't work together # with "-E". OSDEF_CFLAGS = $(PRE_DEFS) $(POST_DEFS) -LINT_CFLAGS = -DLINT -I. $(PRE_DEFS) $(POST_DEFS) $(LUA_CFLAGS) $(PERL_CFLAGS) $(PYTHON_CFLAGS) -Dinline= -D__extension__= -Dalloca=alloca +LINT_CFLAGS = -DLINT -I. $(PRE_DEFS) $(POST_DEFS) $(RUBY_CFLAGS) $(LUA_CFLAGS) $(PERL_CFLAGS) $(PYTHON_CFLAGS) $(PYTHON3_CFLAGS) -Dinline= -D__extension__= -Dalloca=alloca LINT_EXTRA = -DUSE_SNIFF -DHANGUL_INPUT -D"__attribute__(x)=" @@ -1352,7 +1362,8 @@ $(PYTHON3_LIBS) \ $(TCL_LIBS) \ $(RUBY_LIBS) \ - $(PROFILE_LIBS) + $(PROFILE_LIBS) \ + $(LEAK_LIBS) # abbreviations DEST_BIN = $(DESTDIR)$(BINDIR) @@ -1474,8 +1485,15 @@ if_python.c if_python3.c if_tcl.c if_ruby.c if_sniff.c \ gui_beval.c workshop.c wsdebug.c integration.c netbeans.c +# Unittest files +MEMFILE_TEST_SRC = memfile_test.c +MEMFILE_TEST_TARGET = memfile_test$(EXEEXT) + +UNITTEST_SRC = $(MEMFILE_TEST_SRC) +UNITTEST_TARGETS = $(MEMFILE_TEST_TARGET) + # All sources, also the ones that are not configured -ALL_SRC = $(BASIC_SRC) $(ALL_GUI_SRC) $(EXTRA_SRC) +ALL_SRC = $(BASIC_SRC) $(ALL_GUI_SRC) $(UNITTEST_SRC) $(EXTRA_SRC) # Which files to check with lint. Select one of these three lines. ALL_SRC # checks more, but may not work well for checking a GUI that wasn't configured. @@ -1486,7 +1504,7 @@ #LINT_SRC = $(ALL_SRC) #LINT_SRC = $(BASIC_SRC) -OBJ = \ +OBJ_COMMON = \ objects/buffer.o \ objects/blowfish.o \ objects/charset.o \ @@ -1507,10 +1525,8 @@ $(HANGULIN_OBJ) \ objects/if_cscope.o \ objects/if_xcmdsrv.o \ - objects/main.o \ objects/mark.o \ - objects/memfile.o \ - objects/memline.o \ + objects/memline.o \ objects/menu.o \ objects/message.o \ objects/misc1.o \ @@ -1535,6 +1551,7 @@ objects/term.o \ objects/ui.o \ objects/undo.o \ + objects/version.o \ objects/window.o \ $(GUI_OBJ) \ $(LUA_OBJ) \ @@ -1549,6 +1566,13 @@ $(NETBEANS_OBJ) \ $(WSDEBUG_OBJ) +OBJ = $(OBJ_COMMON) \ + objects/main.o \ + objects/memfile.o + +MEMFILE_TEST_OBJ = $(OBJ_COMMON) \ + objects/memfile_test.o + PRO_AUTO = \ blowfish.pro \ buffer.pro \ @@ -1612,7 +1636,7 @@ RSRC_DIR = os_mac_rsrc PRO_MANUAL = os_amiga.pro os_msdos.pro os_win16.pro os_win32.pro \ - os_mswin.pro os_beos.pro os_vms.pro os_riscos.pro $(PERL_PRO) + os_mswin.pro os_beos.pro os_vms.pro $(PERL_PRO) # Default target is making the executable and tools all: $(VIMTARGET) $(TOOLS) languages $(GUI_BUNDLE) @@ -1633,7 +1657,8 @@ CC="$(CC)" CPPFLAGS="$(CPPFLAGS)" CFLAGS="$(CFLAGS)" \ LDFLAGS="$(LDFLAGS)" $(CONF_SHELL) srcdir="$(srcdir)" \ ./configure $(CONF_OPT_GUI) $(CONF_OPT_X) $(CONF_OPT_XSMP) \ - $(CONF_OPT_DARWIN) $(CONF_OPT_PERL) $(CONF_OPT_PYTHON) $(CONF_OPT_PYTHON3) \ + $(CONF_OPT_DARWIN) $(CONF_OPT_FAIL) \ + $(CONF_OPT_PERL) $(CONF_OPT_PYTHON) $(CONF_OPT_PYTHON3) \ $(CONF_OPT_TCL) $(CONF_OPT_RUBY) $(CONF_OPT_NLS) \ $(CONF_OPT_CSCOPE) $(CONF_OPT_MULTIBYTE) $(CONF_OPT_INPUT) \ $(CONF_OPT_OUTPUT) $(CONF_OPT_GPM) $(CONF_OPT_WORKSHOP) \ @@ -1694,11 +1719,12 @@ $(VIMTARGET): auto/config.mk objects $(OBJ) version.c version.h $(CCC) version.c -o objects/version.o @LINK="$(PURIFY) $(SHRPENV) $(CClink) $(ALL_LIB_DIRS) $(LDFLAGS) \ - -o $(VIMTARGET) $(OBJ) objects/version.o $(ALL_LIBS)" \ - MAKE="$(MAKE)" sh $(srcdir)/link.sh + -o $(VIMTARGET) $(OBJ) $(ALL_LIBS)" \ + MAKE="$(MAKE)" LINK_AS_NEEDED=$(LINK_AS_NEEDED) \ + sh $(srcdir)/link.sh xxd/xxd$(EXEEXT): xxd/xxd.c - cd xxd; CC="$(CC)" CFLAGS="$(CPPFLAGS) $(CFLAGS)" \ + cd xxd; CC="$(CC)" CFLAGS="$(CPPFLAGS) $(CFLAGS)" LDFLAGS="$(LDFLAGS)" \ $(MAKE) -f Makefile # Build the language specific files if they were unpacked. @@ -1818,6 +1844,15 @@ ln -s $(VIMTARGET) vim; \ fi cd testdir; $(MAKE) -f Makefile $(GUI_TESTTARGET) VIMPROG=../$(VIMTARGET) $(GUI_TESTARG) + $(MAKE) -f Makefile unittest + +unittesttargets: + $(MAKE) -f Makefile $(UNITTEST_TARGETS) + +unittest unittests: $(UNITTEST_TARGETS) + @for t in $(UNITTEST_TARGETS); do \ + ./$$t || exit 1; echo $$t passed; \ + done testclean: cd testdir; $(MAKE) -f Makefile clean @@ -1825,6 +1860,17 @@ cd $(PODIR); $(MAKE) checkclean; \ fi +# Unittests +# It's build just like Vim to satisfy all dependencies. +$(MEMFILE_TEST_TARGET): auto/config.mk objects $(MEMFILE_TEST_OBJ) + $(CCC) version.c -o objects/version.o + @LINK="$(PURIFY) $(SHRPENV) $(CClink) $(ALL_LIB_DIRS) $(LDFLAGS) \ + -o $(MEMFILE_TEST_TARGET) $(MEMFILE_TEST_OBJ) $(ALL_LIBS)" \ + MAKE="$(MAKE)" LINK_AS_NEEDED=$(LINK_AS_NEEDED) \ + sh $(srcdir)/link.sh + +# install targets + install: $(GUI_INSTALL) install_normal: installvim installtools $(INSTALL_LANGS) install-icons @@ -2258,6 +2304,7 @@ -rm -f *.o objects/* core $(VIMTARGET).core $(VIMTARGET) vim xxd/*.o -rm -f $(TOOLS) auto/osdef.h auto/pathdef.c auto/if_perl.c -rm -f conftest* *~ auto/link.sed + -rm -f $(UNITTEST_TARGETS) -rm -f runtime pixmaps -rm -rf $(APPDIR) -rm -rf mzscheme_base.c @@ -2291,6 +2338,7 @@ ../../testdir/vimrc.unix \ ../../testdir/*.in \ ../../testdir/*.vim \ + ../../testdir/test83-tags? \ ../../testdir/*.ok . # Link needed for doing "make install" in a shadow directory. @@ -2367,7 +2415,6 @@ auto/osdef.h: auto/config.h osdef.sh osdef1.h.in osdef2.h.in CC="$(CC) $(OSDEF_CFLAGS)" srcdir=$(srcdir) sh $(srcdir)/osdef.sh -QUOTESED = sed -e 's/[\\"]/\\&/g' -e 's/\\"/"/' -e 's/\\";$$/";/' auto/pathdef.c: Makefile auto/config.mk -@echo creating $@ -@echo '/* pathdef.c */' > $@ @@ -2532,7 +2579,7 @@ $(CCC) $(PYTHON3_CFLAGS) $(PYTHON3_CFLAGS_EXTRA) -o $@ if_python3.c objects/if_ruby.o: if_ruby.c - $(CCC) -o $@ if_ruby.c + $(CCC) $(RUBY_CFLAGS) -o $@ if_ruby.c objects/if_sniff.o: if_sniff.c $(CCC) -o $@ if_sniff.c @@ -2552,6 +2599,9 @@ objects/memfile.o: memfile.c $(CCC) -o $@ memfile.c +objects/memfile_test.o: memfile_test.c + $(CCC) -o $@ memfile_test.c + objects/memline.o: memline.c $(CCC) -o $@ memline.c @@ -2870,7 +2920,7 @@ objects/os_unix.o: os_unix.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h \ ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \ gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h globals.h farsi.h \ - arabic.h if_mzsch.h os_unixx.h + arabic.h os_unixx.h objects/pathdef.o: auto/pathdef.c vim.h auto/config.h feature.h os_unix.h \ auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \ regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h \ @@ -3009,6 +3059,10 @@ objects/pty.o: pty.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h ascii.h \ keymap.h term.h macros.h option.h structs.h regexp.h gui.h gui_beval.h \ proto/gui_beval.pro ex_cmds.h proto.h globals.h farsi.h arabic.h +objects/memfile_test.o: memfile_test.c main.c vim.h auto/config.h feature.h \ + os_unix.h auto/osdef.h ascii.h keymap.h term.h macros.h option.h \ + structs.h regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h \ + proto.h globals.h farsi.h arabic.h farsi.c arabic.c memfile.c objects/hangulin.o: hangulin.c vim.h auto/config.h feature.h os_unix.h \ auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \ regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h \ @@ -3020,7 +3074,7 @@ objects/if_mzsch.o: if_mzsch.c vim.h auto/config.h feature.h os_unix.h \ auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \ regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h \ - globals.h farsi.h arabic.h if_mzsch.h mzscheme_base.c + globals.h farsi.h arabic.h if_mzsch.h objects/if_perl.o: auto/if_perl.c vim.h auto/config.h feature.h os_unix.h \ auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \ regexp.h gui.h gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h \ @@ -3041,7 +3095,7 @@ ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \ gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h globals.h farsi.h \ arabic.h -objects/if_ruby.o: if_ruby.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h \ +objects/if_ruby.o: if_ruby.c auto/config.h vim.h feature.h os_unix.h auto/osdef.h \ ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \ gui_beval.h proto/gui_beval.pro ex_cmds.h proto.h globals.h farsi.h \ arabic.h version.h diff -Naur vim73.orig/src/VisVim/Commands.cpp vim73/src/VisVim/Commands.cpp --- vim73.orig/src/VisVim/Commands.cpp 2010-05-15 11:04:08.000000000 +0000 +++ vim73/src/VisVim/Commands.cpp 2012-07-20 20:31:12.320974199 +0000 @@ -549,7 +549,7 @@ if (g_bNewTabs) { sprintf(VimCmd, ":tab drop "); - s = VimCmd + 11; + s = VimCmd + 10; } else { @@ -557,8 +557,7 @@ s = VimCmd + 6; } sprintf(FileNameTmp, "%S", (char *)FileName); - for (p = FileNameTmp; *p != '\0' && s < FileNameTmp + MAX_OLE_STR - 4; - ++p) + for (p = FileNameTmp; *p != '\0' && s < VimCmd + MAX_OLE_STR - 4; ++p) if (*p == '\\') *s++ = '/'; else diff -Naur vim73.orig/src/arabic.c vim73/src/arabic.c --- vim73.orig/src/arabic.c 2010-05-15 11:04:09.000000000 +0000 +++ vim73/src/arabic.c 2012-07-20 20:31:16.377643778 +0000 @@ -1066,7 +1066,7 @@ if (curr_c != c && ccp != NULL) { - char_u buf[MB_MAXBYTES]; + char_u buf[MB_MAXBYTES + 1]; /* Update the first byte of the character. */ (*mb_char2bytes)(curr_c, buf); diff -Naur vim73.orig/src/ascii.h vim73/src/ascii.h --- vim73.orig/src/ascii.h 2010-05-15 11:04:07.000000000 +0000 +++ vim73/src/ascii.h 2012-07-20 20:31:13.754308564 +0000 @@ -123,7 +123,7 @@ #define DCS 0x90 /* Device Control String */ #define STERM 0x9c /* String Terminator */ -#define POUND '£' +#define POUND 0xB1 #define CTRL_F_STR "\056" #define CTRL_H_STR "\026" @@ -183,11 +183,6 @@ # define PATHSEP psepc # define PATHSEPSTR pseps #else -# ifdef RISCOS -# define PATHSEP '.' -# define PATHSEPSTR "." -# else -# define PATHSEP '/' -# define PATHSEPSTR "/" -# endif +# define PATHSEP '/' +# define PATHSEPSTR "/" #endif diff -Naur vim73.orig/src/auto/config.mk vim73/src/auto/config.mk --- vim73.orig/src/auto/config.mk 2010-08-15 13:02:25.000000000 +0000 +++ vim73/src/auto/config.mk 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -the first targets to make vim are: scratch config myself -srcdir = . -VIMNAME = vim -EXNAME = ex -VIEWNAME = view diff -Naur vim73.orig/src/auto/configure vim73/src/auto/configure --- vim73.orig/src/auto/configure 2010-08-13 14:17:15.000000000 +0000 +++ vim73/src/auto/configure 2012-07-20 20:31:17.054310930 +0000 @@ -593,6 +593,7 @@ ac_subst_vars='LTLIBOBJS LIBOBJS +LINK_AS_NEEDED DEPEND_CFLAGS_FILTER MAKEMO MSGFMT @@ -740,6 +741,7 @@ ac_subst_files='' ac_user_opts=' enable_option_checking +enable_fail_if_missing enable_darwin with_mac_arch with_developer_dir @@ -1417,6 +1419,8 @@ --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-fail-if-missing Fail if dependencies on additional features + specified on the command line are missing. --disable-darwin Disable Darwin (Mac OS X) support. --disable-selinux Don't check for SELinux support. --disable-xsmp Disable XSMP session management @@ -1427,7 +1431,7 @@ --enable-pythoninterp=OPTS Include Python interpreter. default=no OPTS=no/yes/dynamic --enable-python3interp=OPTS Include Python3 interpreter. default=no OPTS=no/yes/dynamic --enable-tclinterp Include Tcl interpreter. - --enable-rubyinterp Include Ruby interpreter. + --enable-rubyinterp=OPTS Include Ruby interpreter. default=no OPTS=no/yes/dynamic --enable-cscope Include cscope interface. --enable-workshop Include Sun Visual Workshop support. --disable-netbeans Disable NetBeans integration support. @@ -3948,6 +3952,19 @@ fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking --enable-fail-if-missing argument" >&5 +$as_echo_n "checking --enable-fail-if-missing argument... " >&6; } +# Check whether --enable-fail_if_missing was given. +if test "${enable_fail_if_missing+set}" = set; then : + enableval=$enable_fail_if_missing; fail_if_missing="yes" +else + fail_if_missing="no" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $fail_if_missing" >&5 +$as_echo "$fail_if_missing" >&6; } + if test -z "$CFLAGS"; then CFLAGS="-O" test "$GCC" = yes && CFLAGS="-O2 -fno-strength-reduce -Wall" @@ -4409,15 +4426,18 @@ echo "" echo "------------------------------------------" echo " On z/OS Unix, the environment variable" - echo " __CC_${ccn}MODE must be set to \"1\"!" + echo " _CC_${ccn}MODE must be set to \"1\"!" echo " Do:" echo " export _CC_${ccn}MODE=1" echo " and then call configure again." echo "------------------------------------------" exit 1 fi - CFLAGS="$CFLAGS -D_ALL_SOURCE -Wc,float\\(IEEE\\)"; - LDFLAGS="$LDFLAGS -Wl,EDIT=NO" + # Set CFLAGS for configure process. + # This will be reset later for config.mk. + # Use haltonmsg to force error for missing H files. + CFLAGS="$CFLAGS -D_ALL_SOURCE -Wc,float(ieee),haltonmsg(3296)"; + LDFLAGS="$LDFLAGS -Wl,EDIT=NO" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } ;; @@ -4726,6 +4746,9 @@ LUA_CFLAGS="-DDYNAMIC_LUA_DLL=\\\"liblua${vi_cv_version_lua}.so$LUA_SONAME\\\" $LUA_CFLAGS" fi fi + if test "$fail_if_missing" = "yes" -a -z "$LUA_SRC"; then + as_fn_error "could not configure lua" "$LINENO" 5 + fi @@ -4862,16 +4885,36 @@ else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if scheme.h can be found in /usr/include/plt/" >&5 -$as_echo_n "checking if scheme.h can be found in /usr/include/plt/... " >&6; } - if test -f /usr/include/plt/scheme.h; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if scheme.h can be found in $vi_cv_path_mzscheme_pfx/include/racket" >&5 +$as_echo_n "checking if scheme.h can be found in $vi_cv_path_mzscheme_pfx/include/racket... " >&6; } + if test -f $vi_cv_path_mzscheme_pfx/include/racket/scheme.h; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - SCHEME_INC=/usr/include/plt + SCHEME_INC=${vi_cv_path_mzscheme_pfx}/include/racket else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - vi_cv_path_mzscheme_pfx= + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if scheme.h can be found in /usr/include/plt/" >&5 +$as_echo_n "checking if scheme.h can be found in /usr/include/plt/... " >&6; } + if test -f /usr/include/plt/scheme.h; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SCHEME_INC=/usr/include/plt + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if scheme.h can be found in /usr/include/racket/" >&5 +$as_echo_n "checking if scheme.h can be found in /usr/include/racket/... " >&6; } + if test -f /usr/include/racket/scheme.h; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SCHEME_INC=/usr/include/racket + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + vi_cv_path_mzscheme_pfx= + fi + fi fi fi fi @@ -4883,12 +4926,22 @@ elif test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzscheme3m.a"; then MZSCHEME_LIBS="${vi_cv_path_mzscheme_pfx}/lib/libmzscheme3m.a" MZSCHEME_CFLAGS="-DMZ_PRECISE_GC" - elif test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a"; then + elif test -f "${vi_cv_path_mzscheme_pfx}/lib/libracket3m.a"; then + MZSCHEME_LIBS="${vi_cv_path_mzscheme_pfx}/lib/libracket3m.a" + MZSCHEME_CFLAGS="-DMZ_PRECISE_GC" + elif test -f "${vi_cv_path_mzscheme_pfx}/lib/libracket.a"; then + MZSCHEME_LIBS="${vi_cv_path_mzscheme_pfx}/lib/libracket.a ${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a" + elif test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzscheme.a"; then MZSCHEME_LIBS="${vi_cv_path_mzscheme_pfx}/lib/libmzscheme.a ${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a" else if test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzscheme3m.so"; then MZSCHEME_LIBS="-L${vi_cv_path_mzscheme_pfx}/lib -lmzscheme3m" MZSCHEME_CFLAGS="-DMZ_PRECISE_GC" + elif test -f "${vi_cv_path_mzscheme_pfx}/lib/libracket3m.so"; then + MZSCHEME_LIBS="-L${vi_cv_path_mzscheme_pfx}/lib -lracket3m" + MZSCHEME_CFLAGS="-DMZ_PRECISE_GC" + elif test -f "${vi_cv_path_mzscheme_pfx}/lib/libracket.so"; then + MZSCHEME_LIBS="-L${vi_cv_path_mzscheme_pfx}/lib -lracket -lmzgc" else MZSCHEME_LIBS="-L${vi_cv_path_mzscheme_pfx}/lib -lmzscheme -lmzgc" fi @@ -4901,10 +4954,20 @@ fi if test -d $vi_cv_path_mzscheme_pfx/lib/plt/collects; then SCHEME_COLLECTS=lib/plt/ + else + if test -d $vi_cv_path_mzscheme_pfx/lib/racket/collects; then + SCHEME_COLLECTS=lib/racket/ + fi fi if test -f "${vi_cv_path_mzscheme_pfx}/${SCHEME_COLLECTS}collects/scheme/base.ss" ; then - MZSCHEME_EXTRA="mzscheme_base.c" - MZSCHEME_CFLAGS="${MZSCHEME_CFLAGS} -DINCLUDE_MZSCHEME_BASE" + MZSCHEME_EXTRA="mzscheme_base.c" + else + if test -f "${vi_cv_path_mzscheme_pfx}/${SCHEME_COLLECTS}collects/scheme/base.rkt" ; then + MZSCHEME_EXTRA="mzscheme_base.c" + fi + fi + if test "X$MZSCHEME_EXTRA" != "X" ; then + MZSCHEME_CFLAGS="${MZSCHEME_CFLAGS} -DINCLUDE_MZSCHEME_BASE" MZSCHEME_MZC="${vi_cv_path_mzscheme_pfx}/bin/mzc" fi MZSCHEME_CFLAGS="${MZSCHEME_CFLAGS} -I${SCHEME_INC} \ @@ -5099,6 +5162,10 @@ PERL_CFLAGS="-DDYNAMIC_PERL_DLL=\\\"$libperl\\\" $PERL_CFLAGS" fi fi + + if test "$fail_if_missing" = "yes" -a "$perl_ok" != "yes"; then + as_fn_error "could not configure perl" "$LINENO" 5 + fi fi @@ -5285,9 +5352,9 @@ PYTHON_LIBS="${vi_cv_path_python_plibs}" if test "${vi_cv_path_python_pfx}" = "${vi_cv_path_python_epfx}"; then - PYTHON_CFLAGS="-I${vi_cv_path_python_pfx}/include/python${vi_cv_var_python_version}" + PYTHON_CFLAGS="-I${vi_cv_path_python_pfx}/include/python${vi_cv_var_python_version} -DPYTHON_HOME=\\\"${vi_cv_path_python_pfx}\\\"" else - PYTHON_CFLAGS="-I${vi_cv_path_python_pfx}/include/python${vi_cv_var_python_version} -I${vi_cv_path_python_epfx}/include/python${vi_cv_var_python_version}" + PYTHON_CFLAGS="-I${vi_cv_path_python_pfx}/include/python${vi_cv_var_python_version} -I${vi_cv_path_python_epfx}/include/python${vi_cv_var_python_version} -DPYTHON_HOME=\\\"${vi_cv_path_python_pfx}\\\"" fi PYTHON_SRC="if_python.c" if test "x$MACOSX" = "xyes"; then @@ -5298,7 +5365,7 @@ if test "${vi_cv_var_python_version}" = "1.4"; then PYTHON_OBJ="$PYTHON_OBJ objects/py_getpath.o" fi - PYTHON_GETPATH_CFLAGS="-DPYTHONPATH='\"${vi_cv_path_pythonpath}\"' -DPREFIX='\"${vi_cv_path_python_pfx}\"' -DEXEC_PREFIX='\"${vi_cv_path_python_epfx}\"'" + PYTHON_GETPATH_CFLAGS="-DPYTHONPATH='\"${vi_cv_path_pythonpath}\"' -DPREFIX='\"${vi_cv_path_python_pfx}\"' -DEXEC_PREFIX='\"${vi_cv_path_python_epfx}\"'" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if -pthread should be used" >&5 $as_echo_n "checking if -pthread should be used... " >&6; } @@ -5388,6 +5455,10 @@ $as_echo "too old" >&6; } fi fi + + if test "$fail_if_missing" = "yes" -a "$python_ok" != "yes"; then + as_fn_error "could not configure python" "$LINENO" 5 + fi fi @@ -5464,6 +5535,23 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $vi_cv_var_python3_version" >&5 $as_echo "$vi_cv_var_python3_version" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking Python's abiflags" >&5 +$as_echo_n "checking Python's abiflags... " >&6; } +if test "${vi_cv_var_python3_abiflags+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + + vi_cv_var_python3_abiflags= + if ${vi_cv_path_python3} -c \ + "import sys; sys.exit(${vi_cv_var_python3_version} < 3.2)" + then + vi_cv_var_python3_abiflags=`${vi_cv_path_python3} -c \ + "import sys; print(sys.abiflags)"` + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $vi_cv_var_python3_abiflags" >&5 +$as_echo "$vi_cv_var_python3_abiflags" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking Python's install prefix" >&5 $as_echo_n "checking Python's install prefix... " >&6; } if test "${vi_cv_path_python3_pfx+set}" = set; then : @@ -5514,9 +5602,13 @@ else vi_cv_path_python3_conf= + config_dir="config" + if test "${vi_cv_var_python3_abiflags}" != ""; then + config_dir="${config_dir}-${vi_cv_var_python3_version}${vi_cv_var_python3_abiflags}" + fi for path in "${vi_cv_path_python3_pfx}" "${vi_cv_path_python3_epfx}"; do for subdir in lib64 lib share; do - d="${path}/${subdir}/python${vi_cv_var_python3_version}/config" + d="${path}/${subdir}/python${vi_cv_var_python3_version}/${config_dir}" if test -d "$d" && test -f "$d/config.c"; then vi_cv_path_python3_conf="$d" fi @@ -5545,13 +5637,12 @@ @echo "python3_BASEMODLIBS='$(BASEMODLIBS)'" @echo "python3_LIBS='$(LIBS)'" @echo "python3_SYSLIBS='$(SYSLIBS)'" - @echo "python3_LINKFORSHARED='$(LINKFORSHARED)'" @echo "python3_INSTSONAME='$(INSTSONAME)'" eof eval "`cd ${PYTHON3_CONFDIR} && make -f "${tmp_mkf}" __ | sed '/ directory /d'`" rm -f -- "${tmp_mkf}" - vi_cv_path_python3_plibs="-L${PYTHON3_CONFDIR} -lpython${vi_cv_var_python3_version}" - vi_cv_path_python3_plibs="${vi_cv_path_python3_plibs} ${python3_BASEMODLIBS} ${python3_LIBS} ${python3_SYSLIBS} ${python3_LINKFORSHARED}" + vi_cv_path_python3_plibs="-L${PYTHON3_CONFDIR} -lpython${vi_cv_var_python3_version}${vi_cv_var_python3_abiflags}" + vi_cv_path_python3_plibs="${vi_cv_path_python3_plibs} ${python3_BASEMODLIBS} ${python3_LIBS} ${python3_SYSLIBS}" vi_cv_path_python3_plibs=`echo $vi_cv_path_python3_plibs | sed s/-ltermcap//` vi_cv_path_python3_plibs=`echo $vi_cv_path_python3_plibs | sed s/-lffi//` @@ -5560,9 +5651,9 @@ PYTHON3_LIBS="${vi_cv_path_python3_plibs}" if test "${vi_cv_path_python3_pfx}" = "${vi_cv_path_python3_epfx}"; then - PYTHON3_CFLAGS="-I${vi_cv_path_python3_pfx}/include/python${vi_cv_var_python3_version}" + PYTHON3_CFLAGS="-I${vi_cv_path_python3_pfx}/include/python${vi_cv_var_python3_version}${vi_cv_var_python3_abiflags} -DPYTHON3_HOME=L\\\"${vi_cv_path_python3_pfx}\\\"" else - PYTHON3_CFLAGS="-I${vi_cv_path_python3_pfx}/include/python${vi_cv_var_python3_version} -I${vi_cv_path_python3_epfx}/include/python${vi_cv_var_python3_version}" + PYTHON3_CFLAGS="-I${vi_cv_path_python3_pfx}/include/python${vi_cv_var_python3_version}${vi_cv_var_python3_abiflags} -I${vi_cv_path_python3_epfx}/include/python${vi_cv_var_python3_version}${vi_cv_var_python3_abiflags} -DPYTHON3_HOME=L\\\"${vi_cv_path_python3_pfx}\\\"" fi PYTHON3_SRC="if_python3.c" if test "x$MACOSX" = "xyes"; then @@ -5667,12 +5758,12 @@ $as_echo "#define DYNAMIC_PYTHON3 1" >>confdefs.h - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we can do without RTLD_GLOBAL" >&5 -$as_echo_n "checking whether we can do without RTLD_GLOBAL... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we can do without RTLD_GLOBAL for Python" >&5 +$as_echo_n "checking whether we can do without RTLD_GLOBAL for Python... " >&6; } cflags_save=$CFLAGS - CFLAGS="$CFLAGS $PYTHON3_CFLAGS" + CFLAGS="$CFLAGS $PYTHON_CFLAGS" ldflags_save=$LDFLAGS - LDFLAGS="$LDFLAGS -ldl" + LDFLAGS="-ldl $LDFLAGS" if test "$cross_compiling" = yes; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} @@ -5689,15 +5780,17 @@ * Only the first pyhton version used will be switched on. */ - int no_rtl_global_needed_for(char *python_instsoname) + int no_rtl_global_needed_for(char *python_instsoname, char *prefix) { int needed = 0; void* pylib = dlopen(python_instsoname, RTLD_LAZY); if (pylib != 0) { + void (*pfx)(char *home) = dlsym(pylib, "Py_SetPythonHome"); void (*init)(void) = dlsym(pylib, "Py_Initialize"); int (*simple)(char*) = dlsym(pylib, "PyRun_SimpleString"); void (*final)(void) = dlsym(pylib, "Py_Finalize"); + (*pfx)(prefix); (*init)(); needed = (*simple)("import termios") == -1; (*final)(); @@ -5709,7 +5802,7 @@ int main(int argc, char** argv) { int not_needed = 0; - if (no_rtl_global_needed_for("libpython2.7.so.1.0") && no_rtl_global_needed_for("libpython3.1.so.1.0")) + if (no_rtl_global_needed_for("${python_INSTSONAME}", "${vi_cv_path_python_pfx}")) not_needed = 1; return !not_needed; } @@ -5726,8 +5819,76 @@ conftest.$ac_objext conftest.beam conftest.$ac_ext fi + + CFLAGS=$cflags_save + LDFLAGS=$ldflags_save + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we can do without RTLD_GLOBAL for Python3" >&5 +$as_echo_n "checking whether we can do without RTLD_GLOBAL for Python3... " >&6; } + cflags_save=$CFLAGS + CFLAGS="$CFLAGS $PYTHON3_CFLAGS" + ldflags_save=$LDFLAGS + LDFLAGS="-ldl $LDFLAGS" + if test "$cross_compiling" = yes; then : + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "cannot run test program while cross compiling +See \`config.log' for more details." "$LINENO" 5; } +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include + /* If this program fails, then RTLD_GLOBAL is needed. + * RTLD_GLOBAL will be used and then it is not possible to + * have both python versions enabled in the same vim instance. + * Only the first pyhton version used will be switched on. + */ + + int no_rtl_global_needed_for(char *python_instsoname, wchar_t *prefix) + { + int needed = 0; + void* pylib = dlopen(python_instsoname, RTLD_LAZY); + if (pylib != 0) + { + void (*pfx)(wchar_t *home) = dlsym(pylib, "Py_SetPythonHome"); + void (*init)(void) = dlsym(pylib, "Py_Initialize"); + int (*simple)(char*) = dlsym(pylib, "PyRun_SimpleString"); + void (*final)(void) = dlsym(pylib, "Py_Finalize"); + (*pfx)(prefix); + (*init)(); + needed = (*simple)("import termios") == -1; + (*final)(); + dlclose(pylib); + } + return !needed; + } + + int main(int argc, char** argv) + { + int not_needed = 0; + if (no_rtl_global_needed_for("${python3_INSTSONAME}", L"${vi_cv_path_python3_pfx}")) + not_needed = 1; + return !not_needed; + } +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; };$as_echo "#define PY3_NO_RTLD_GLOBAL 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + CFLAGS=$cflags_save LDFLAGS=$ldflags_save + PYTHON_SRC="if_python.c" PYTHON_OBJ="objects/if_python.o" PYTHON_CFLAGS="$PYTHON_CFLAGS -DDYNAMIC_PYTHON_DLL=\\\"${python_INSTSONAME}\\\"" @@ -6085,6 +6246,9 @@ $as_echo "too old; need Tcl version 8.0 or later" >&6; } fi fi + if test "$fail_if_missing" = "yes" -a -z "$TCL_SRC"; then + as_fn_error "could not configure Tcl" "$LINENO" 5 + fi fi @@ -6103,20 +6267,20 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_rubyinterp" >&5 $as_echo "$enable_rubyinterp" >&6; } -if test "$enable_rubyinterp" = "yes"; then +if test "$enable_rubyinterp" = "yes" -o "$enable_rubyinterp" = "dynamic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking --with-ruby-command argument" >&5 $as_echo_n "checking --with-ruby-command argument... " >&6; } + # Check whether --with-ruby-command was given. if test "${with_ruby_command+set}" = set; then : - withval=$with_ruby_command; RUBY_CMD="$withval"; { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RUBY_CMD" >&5 + withval=$with_ruby_command; RUBY_CMD="$withval"; vi_cv_path_ruby="$withval"; { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RUBY_CMD" >&5 $as_echo "$RUBY_CMD" >&6; } else RUBY_CMD="ruby"; { $as_echo "$as_me:${as_lineno-$LINENO}: result: defaulting to $RUBY_CMD" >&5 $as_echo "defaulting to $RUBY_CMD" >&6; } fi - # Extract the first word of "$RUBY_CMD", so it can be a program name with args. set dummy $RUBY_CMD; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 @@ -6181,17 +6345,14 @@ RUBY_LIBS="$rubylibs" fi librubyarg=`$vi_cv_path_ruby -r rbconfig -e 'print Config.expand(Config::CONFIG["LIBRUBYARG"])'` - if test -f "$rubyhdrdir/$librubyarg"; then - librubyarg="$rubyhdrdir/$librubyarg" - else - rubylibdir=`$vi_cv_path_ruby -r rbconfig -e 'print Config.expand(Config::CONFIG["libdir"])'` - if test -f "$rubylibdir/$librubyarg"; then - librubyarg="$rubylibdir/$librubyarg" - elif test "$librubyarg" = "libruby.a"; then - librubyarg="-lruby" - else - librubyarg=`$vi_cv_path_ruby -r rbconfig -e "print '$librubyarg'.gsub(/-L\./, %'-L#{Config.expand(Config::CONFIG[\"libdir\"])}')"` - fi + librubya=`$vi_cv_path_ruby -r rbconfig -e 'print Config.expand(Config::CONFIG["LIBRUBY_A"])'` + rubylibdir=`$vi_cv_path_ruby -r rbconfig -e 'print Config.expand(Config::CONFIG["libdir"])'` + if test -f "$rubylibdir/$librubya"; then + librubyarg="$librubyarg" + RUBY_LIBS="$RUBY_LIBS -L$rubylibdir" + elif test "$librubyarg" = "libruby.a"; then + librubyarg="-lruby" + RUBY_LIBS="$RUBY_LIBS -L$rubylibdir" fi if test "X$librubyarg" != "X"; then @@ -6209,6 +6370,13 @@ RUBY_PRO="if_ruby.pro" $as_echo "#define FEAT_RUBY 1" >>confdefs.h + if test "$enable_rubyinterp" = "dynamic"; then + libruby=`$vi_cv_path_ruby -r rbconfig -e 'printf "lib%s.%s\n", Config::CONFIG["RUBY_SO_NAME"], Config::CONFIG["DLEXT"]'` + $as_echo "#define DYNAMIC_RUBY 1" >>confdefs.h + + RUBY_CFLAGS="-DDYNAMIC_RUBY_DLL=\\\"$libruby\\\" -DDYNAMIC_RUBY_VER=$rubyversion $RUBY_CFLAGS" + RUBY_LIBS= + fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found; disabling Ruby" >&5 $as_echo "not found; disabling Ruby" >&6; } @@ -6218,6 +6386,10 @@ $as_echo "too old; need Ruby version 1.6.0 or later" >&6; } fi fi + + if test "$fail_if_missing" = "yes" -a -z "$RUBY_OBJ"; then + as_fn_error "could not configure Ruby" "$LINENO" 5 + fi fi @@ -8528,8 +8700,13 @@ if test -z "$SKIP_MOTIF"; then cppflags_save=$CPPFLAGS CPPFLAGS="$CPPFLAGS $X_CFLAGS" - for ac_header in Xm/Xm.h Xm/XpmP.h Xm/JoinSideT.h Xm/TraitP.h Xm/Manager.h \ - Xm/UnhighlightT.h Xm/Notebook.h + if test "$zOSUnix" = "yes"; then + xmheader="Xm/Xm.h" + else + xmheader="Xm/Xm.h Xm/XpmP.h Xm/JoinSideT.h Xm/TraitP.h Xm/Manager.h + Xm/UnhighlightT.h Xm/Notebook.h" + fi + for ac_header in $xmheader do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" @@ -8544,7 +8721,7 @@ done - if test $ac_cv_header_Xm_XpmP_h = yes; then + if test "x$ac_cv_header_Xm_XpmP_h" = "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XpmAttributes_21 in Xm/XpmP.h" >&5 $as_echo_n "checking for XpmAttributes_21 in Xm/XpmP.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -9768,9 +9945,9 @@ else { $as_echo "$as_me:${as_lineno-$LINENO}: result: empty: automatic terminal library selection" >&5 $as_echo "empty: automatic terminal library selection" >&6; } - case "`uname -s 2>/dev/null`" in - OSF1|SCO_SV) tlibs="ncurses curses termlib termcap";; - *) tlibs="ncurses termlib termcap curses";; + case "`uname -s 2>/dev/null`" in + OSF1|SCO_SV) tlibs="tinfo ncurses curses termlib termcap";; + *) tlibs="tinfo ncurses termlib termcap curses";; esac for libname in $tlibs; do as_ac_Lib=`$as_echo "ac_cv_lib_${libname}''_tgetent" | $as_tr_sh` @@ -11159,7 +11336,47 @@ rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Solaris ACL support" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for acl_get in -lsec" >&5 +$as_echo_n "checking for acl_get in -lsec... " >&6; } +if test "${ac_cv_lib_sec_acl_get+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsec $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char acl_get (); +int +main () +{ +return acl_get (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_sec_acl_get=yes +else + ac_cv_lib_sec_acl_get=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sec_acl_get" >&5 +$as_echo "$ac_cv_lib_sec_acl_get" >&6; } +if test "x$ac_cv_lib_sec_acl_get" = x""yes; then : + LIBS="$LIBS -lsec"; $as_echo "#define HAVE_SOLARIS_ZFS_ACL 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Solaris ACL support" >&5 $as_echo_n "checking for Solaris ACL support... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -11186,6 +11403,8 @@ fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for AIX ACL support" >&5 $as_echo_n "checking for AIX ACL support... " >&6; } @@ -11642,7 +11861,8 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: checking uint32_t is 32 bits" >&5 $as_echo_n "checking uint32_t is 32 bits... " >&6; } if test "$cross_compiling" = yes; then : - as_fn_error "could not compile program using uint32_t." "$LINENO" 5 + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot check uint32_t when cross-compiling." >&5 +$as_echo "$as_me: WARNING: cannot check uint32_t when cross-compiling." >&2;} else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -11915,6 +12135,10 @@ test -f tags && mv tags tags.save if (eval ctags --version /dev/null | grep Exuberant) < /dev/null 1>&5 2>&1; then TAGPRG="ctags -I INIT+ --fields=+S" +elif (eval exctags --version /dev/null | grep Exuberant) < /dev/null 1>&5 2>&1; then + TAGPRG="exctags -I INIT+ --fields=+S" +elif (eval exuberant-ctags --version /dev/null | grep Exuberant) < /dev/null 1>&5 2>&1; then + TAGPRG="exuberant-ctags -I INIT+ --fields=+S" else TAGPRG="ctags" (eval etags /dev/null) < /dev/null 1>&5 2>&1 && TAGPRG="etags" @@ -12344,10 +12568,10 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need -D_FORTIFY_SOURCE=1" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need -D_FORTIFY_SOURCE=1" >&5 $as_echo_n "checking whether we need -D_FORTIFY_SOURCE=1... " >&6; } if test "$gccmajor" -gt "3"; then - CFLAGS=`echo "$CFLAGS" | sed -e 's/-Wp,-D_FORTIFY_SOURCE=.//g' -e 's/-D_FORTIFY_SOURCE=.//g' -e 's/$/ -D_FORTIFY_SOURCE=1/'` + CFLAGS=`echo "$CFLAGS" | sed -e 's/-Wp,-D_FORTIFY_SOURCE=.//g' -e 's/-D_FORTIFY_SOURCE=.//g' -e 's/$/ -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1/'` { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else @@ -12357,6 +12581,28 @@ fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker --as-needed support" >&5 +$as_echo_n "checking linker --as-needed support... " >&6; } +LINK_AS_NEEDED= +# Check if linker supports --as-needed and --no-as-needed options +if $CC -Wl,--help 2>/dev/null | grep as-needed > /dev/null; then + LDFLAGS="$LDFLAGS -Wl,--as-needed" + LINK_AS_NEEDED=yes +fi +if test "$LINK_AS_NEEDED" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# IBM z/OS reset CFLAGS for config.mk +if test "$zOSUnix" = "yes"; then + CFLAGS="-D_ALL_SOURCE -Wc,float\(ieee\),dll" +fi + ac_config_files="$ac_config_files auto/config.mk:config.mk.in" cat >confcache <<\_ACEOF diff -Naur vim73.orig/src/blowfish.c vim73/src/blowfish.c --- vim73.orig/src/blowfish.c 2010-07-14 14:45:39.000000000 +0000 +++ vim73/src/blowfish.c 2012-07-20 20:31:09.647638940 +0000 @@ -413,6 +413,7 @@ int salt_len; { int i, j, keypos = 0; + unsigned u; UINT32_T val, data_l, data_r; char_u *key; int keylen; @@ -432,8 +433,8 @@ } for (i = 0; i < keylen; i++) { - sscanf((char *)&key[i * 2], "%2x", &j); - key[i] = j; + sscanf((char *)&key[i * 2], "%2x", &u); + key[i] = u; } mch_memmove(sbx, sbi, 4 * 4 * 256); diff -Naur vim73.orig/src/buffer.c vim73/src/buffer.c --- vim73.orig/src/buffer.c 2010-08-13 09:14:35.000000000 +0000 +++ vim73/src/buffer.c 2012-07-20 20:31:18.240978445 +0000 @@ -57,13 +57,15 @@ #if defined(FEAT_SIGNS) static void insert_sign __ARGS((buf_T *buf, signlist_T *prev, signlist_T *next, int id, linenr_T lnum, int typenr)); -static void buf_delete_signs __ARGS((buf_T *buf)); #endif #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX) static char *msg_loclist = N_("[Location List]"); static char *msg_qflist = N_("[Quickfix List]"); #endif +#ifdef FEAT_AUTOCMD +static char *e_auabort = N_("E855: Autocommands caused command to abort"); +#endif /* * Open current buffer, that is: open the memfile and read the file into @@ -96,7 +98,7 @@ * There MUST be a memfile, otherwise we can't do anything * If we can't create one for the current buffer, take another buffer */ - close_buffer(NULL, curbuf, 0); + close_buffer(NULL, curbuf, 0, FALSE); for (curbuf = firstbuf; curbuf != NULL; curbuf = curbuf->b_next) if (curbuf->b_ml.ml_mfp != NULL) break; @@ -316,12 +318,17 @@ * get a new buffer very soon! * * The 'bufhidden' option can force freeing and deleting. + * + * When "abort_if_last" is TRUE then do not close the buffer if autocommands + * cause there to be only one window with this buffer. e.g. when ":quit" is + * supposed to close the window but autocommands close all other windows. */ void -close_buffer(win, buf, action) +close_buffer(win, buf, action, abort_if_last) win_T *win; /* if not NULL, set b_last_cursor */ buf_T *buf; int action; + int abort_if_last UNUSED; { #ifdef FEAT_AUTOCMD int is_curbuf; @@ -369,19 +376,35 @@ /* When the buffer is no longer in a window, trigger BufWinLeave */ if (buf->b_nwindows == 1) { + buf->b_closing = TRUE; apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname, FALSE, buf); - if (!buf_valid(buf)) /* autocommands may delete the buffer */ + if (!buf_valid(buf)) + { + /* Autocommands deleted the buffer. */ +aucmd_abort: + EMSG(_(e_auabort)); return; + } + buf->b_closing = FALSE; + if (abort_if_last && one_window()) + /* Autocommands made this the only window. */ + goto aucmd_abort; /* When the buffer becomes hidden, but is not unloaded, trigger * BufHidden */ if (!unload_buf) { + buf->b_closing = TRUE; apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname, FALSE, buf); - if (!buf_valid(buf)) /* autocmds may delete the buffer */ - return; + if (!buf_valid(buf)) + /* Autocommands deleted the buffer. */ + goto aucmd_abort; + buf->b_closing = FALSE; + if (abort_if_last && one_window()) + /* Autocommands made this the only window. */ + goto aucmd_abort; } # ifdef FEAT_EVAL if (aborting()) /* autocmds may abort script processing */ @@ -416,6 +439,14 @@ #endif buf_freeall(buf, (del_buf ? BFA_DEL : 0) + (wipe_buf ? BFA_WIPE : 0)); + if ( +#ifdef FEAT_WINDOWS + win_valid(win) && +#else + win != NULL && +#endif + win->w_buffer == buf) + win->w_buffer = NULL; /* make sure we don't use the buffer now */ #ifdef FEAT_AUTOCMD /* Autocommands may have deleted the buffer. */ @@ -527,6 +558,7 @@ #ifdef FEAT_AUTOCMD int is_curbuf = (buf == curbuf); + buf->b_closing = TRUE; apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, FALSE, buf); if (!buf_valid(buf)) /* autocommands may delete the buffer */ return; @@ -543,6 +575,7 @@ if (!buf_valid(buf)) /* autocommands may delete the buffer */ return; } + buf->b_closing = FALSE; # ifdef FEAT_EVAL if (aborting()) /* autocmds may abort script processing */ return; @@ -560,6 +593,11 @@ #ifdef FEAT_DIFF diff_buf_delete(buf); /* Can't use 'diff' for unloaded buffer. */ #endif +#ifdef FEAT_SYN_HL + /* Remove any ownsyntax, unless exiting. */ + if (firstwin != NULL && curwin->w_buffer == buf) + reset_synblock(curwin); +#endif #ifdef FEAT_FOLDING /* No folds in an empty buffer. */ @@ -639,6 +677,9 @@ { clear_wininfo(buf); /* including window-local options */ free_buf_options(buf, TRUE); +#ifdef FEAT_SPELL + ga_clear(&buf->b_s.b_langp); +#endif } #ifdef FEAT_EVAL vars_clear(&buf->b_vars.dv_hashtab); /* free all internal variables */ @@ -661,9 +702,6 @@ vim_free(buf->b_start_fenc); buf->b_start_fenc = NULL; #endif -#ifdef FEAT_SPELL - ga_clear(&buf->b_s.b_langp); -#endif } /* @@ -762,7 +800,7 @@ * open a new, empty buffer. */ swap_exists_action = SEA_NONE; /* don't want it again */ swap_exists_did_quit = TRUE; - close_buffer(curwin, curbuf, DOBUF_UNLOAD); + close_buffer(curwin, curbuf, DOBUF_UNLOAD, FALSE); if (!buf_valid(old_curbuf) || old_curbuf == curbuf) old_curbuf = buflist_new(NULL, NULL, 1L, BLN_CURBUF | BLN_LISTED); if (old_curbuf != NULL) @@ -1109,7 +1147,7 @@ * if the buffer still exists. */ if (buf != curbuf && buf_valid(buf) && buf->b_nwindows == 0) - close_buffer(NULL, buf, action); + close_buffer(NULL, buf, action, FALSE); return retval; } @@ -1120,6 +1158,9 @@ * a window with this buffer. */ while (buf == curbuf +# ifdef FEAT_AUTOCMD + && !(curwin->w_closing || curwin->w_buffer->b_closing) +# endif && (firstwin != lastwin || first_tabpage->tp_next != NULL)) win_close(curwin, FALSE); #endif @@ -1133,7 +1174,7 @@ close_windows(buf, FALSE); #endif if (buf != curbuf && buf_valid(buf) && buf->b_nwindows <= 0) - close_buffer(NULL, buf, action); + close_buffer(NULL, buf, action, FALSE); return OK; } @@ -1288,9 +1329,12 @@ /* Go to the other buffer. */ set_curbuf(buf, action); -#if defined(FEAT_LISTCMDS) && defined(FEAT_SCROLLBIND) +#if defined(FEAT_LISTCMDS) \ + && (defined(FEAT_SCROLLBIND) || defined(FEAT_CURSORBIND)) if (action == DOBUF_SPLIT) - curwin->w_p_scb = FALSE; /* reset 'scrollbind' */ + { + RESET_BINDING(curwin); /* reset 'scrollbind' and 'cursorbind' */ + } #endif #if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL) @@ -1343,6 +1387,10 @@ # endif #endif { +#ifdef FEAT_SYN_HL + if (prevbuf == curwin->w_buffer) + reset_synblock(curwin); +#endif #ifdef FEAT_WINDOWS if (unload) close_windows(prevbuf, FALSE); @@ -1353,22 +1401,34 @@ if (buf_valid(prevbuf)) #endif { +#ifdef FEAT_WINDOWS + win_T *previouswin = curwin; +#endif if (prevbuf == curbuf) u_sync(FALSE); close_buffer(prevbuf == curwin->w_buffer ? curwin : NULL, prevbuf, unload ? action : (action == DOBUF_GOTO && !P_HID(prevbuf) - && !bufIsChanged(prevbuf)) ? DOBUF_UNLOAD : 0); + && !bufIsChanged(prevbuf)) ? DOBUF_UNLOAD : 0, FALSE); +#ifdef FEAT_WINDOWS + if (curwin != previouswin && win_valid(previouswin)) + /* autocommands changed curwin, Grr! */ + curwin = previouswin; +#endif } } #ifdef FEAT_AUTOCMD /* An autocommand may have deleted "buf", already entered it (e.g., when - * it did ":bunload") or aborted the script processing! */ + * it did ":bunload") or aborted the script processing! + * If curwin->w_buffer is null, enter_buffer() will make it valid again */ + if ((buf_valid(buf) && buf != curbuf # ifdef FEAT_EVAL - if (buf_valid(buf) && buf != curbuf && !aborting()) -# else - if (buf_valid(buf) && buf != curbuf) + && !aborting() +# endif +# ifdef FEAT_WINDOWS + ) || curwin->w_buffer == NULL # endif + ) #endif enter_buffer(buf); } @@ -1392,10 +1452,6 @@ foldUpdateAll(curwin); /* update folds (later). */ #endif -#ifdef FEAT_SYN_HL - reset_synblock(curwin); - curwin->w_s = &(buf->b_s); -#endif /* Get the buffer in the current window. */ curwin->w_buffer = buf; curbuf = buf; @@ -1406,6 +1462,10 @@ diff_buf_add(curbuf); #endif +#ifdef FEAT_SYN_HL + curwin->w_s = &(buf->b_s); +#endif + /* Cursor on first line by default. */ curwin->w_cursor.lnum = 1; curwin->w_cursor.col = 0; @@ -1687,7 +1747,8 @@ buf->b_wininfo->wi_win = curwin; #ifdef FEAT_EVAL - init_var_dict(&buf->b_vars, &buf->b_bufvar); /* init b: variables */ + /* init b: variables */ + init_var_dict(&buf->b_vars, &buf->b_bufvar, VAR_SCOPE); #endif #ifdef FEAT_SYN_HL hash_init(&buf->b_s.b_keywtab); @@ -1805,9 +1866,6 @@ #ifdef FEAT_AUTOCMD clear_string_option(&buf->b_p_ft); #endif -#ifdef FEAT_OSFILETYPE - clear_string_option(&buf->b_p_oft); -#endif #ifdef FEAT_CINDENT clear_string_option(&buf->b_p_cink); clear_string_option(&buf->b_p_cino); @@ -1917,9 +1975,7 @@ tabpage_new(); else if (win_split(0, 0) == FAIL) /* Open in a new window */ return FAIL; -# ifdef FEAT_SCROLLBIND - curwin->w_p_scb = FALSE; -# endif + RESET_BINDING(curwin); } } #endif @@ -2526,6 +2582,9 @@ if (p_fdls >= 0) curwin->w_p_fdl = p_fdls; #endif +#ifdef FEAT_SYN_HL + check_colorcolumn(curwin); +#endif } /* @@ -2690,7 +2749,8 @@ vim_free(ffname); return FAIL; } - close_buffer(NULL, obuf, DOBUF_WIPE); /* delete from the list */ + /* delete from the list */ + close_buffer(NULL, obuf, DOBUF_WIPE, FALSE); } sfname = vim_strsave(sfname); if (ffname == NULL || sfname == NULL) @@ -3175,7 +3235,7 @@ /* format: "fname + (path) (1 of 2) - VIM" */ if (curbuf->b_fname == NULL) - STRCPY(buf, _("[No Name]")); + vim_strncpy(buf, (char_u *)_("[No Name]"), IOSIZE - 100); else { p = transstr(gettail(curbuf->b_fname)); @@ -3231,7 +3291,7 @@ if (serverName != NULL) { STRCAT(buf, " - "); - STRCAT(buf, serverName); + vim_strcat(buf, serverName, IOSIZE); } else #endif @@ -3240,9 +3300,8 @@ if (maxlen > 0) { /* make it shorter by removing a bit in the middle */ - len = vim_strsize(buf); - if (len > maxlen) - trunc_string(buf, buf, maxlen); + if (vim_strsize(buf) > maxlen) + trunc_string(buf, buf, maxlen, IOSIZE); } } } @@ -3363,7 +3422,8 @@ * or truncated if too long, fillchar is used for all whitespace. */ int -build_stl_str_hl(wp, out, outlen, fmt, use_sandbox, fillchar, maxwidth, hltab, tabtab) +build_stl_str_hl(wp, out, outlen, fmt, use_sandbox, fillchar, + maxwidth, hltab, tabtab) win_T *wp; char_u *out; /* buffer to write into != NameBuff */ size_t outlen; /* length of out[] */ @@ -3458,6 +3518,18 @@ prevchar_isitem = FALSE; for (s = usefmt; *s; ) { + if (curitem == STL_MAX_ITEM) + { + /* There are too many items. Add the error code to the statusline + * to give the user a hint about what went wrong. */ + if (p + 6 < out + outlen) + { + mch_memmove(p, " E541", (size_t)5); + p += 5; + } + break; + } + if (*s != NUL && *s != '%') prevchar_isflag = prevchar_isitem = FALSE; @@ -3473,6 +3545,8 @@ * Handle one '%' item. */ s++; + if (*s == NUL) /* ignore trailing % */ + break; if (*s == '%') { if (p + 1 >= out + outlen) @@ -4355,7 +4429,12 @@ { int i; win_T *wp, *wpnext; - char_u *opened; /* array of flags for which args are open */ + char_u *opened; /* Array of weight for which args are open: + * 0: not opened + * 1: opened in other tab + * 2: opened in curtab + * 3: opened in curtab and curwin + */ int opened_len; /* length of opened[] */ int use_firstwin = FALSE; /* use first window for arglist */ int split_ret = OK; @@ -4364,6 +4443,8 @@ buf_T *buf; tabpage_T *tpnext; int had_tab = cmdmod.tab; + win_T *old_curwin, *last_curwin; + tabpage_T *old_curtab, *last_curtab; win_T *new_curwin = NULL; tabpage_T *new_curtab = NULL; @@ -4380,6 +4461,15 @@ if (opened == NULL) return; + /* Autocommands may do anything to the argument list. Make sure it's not + * freed while we are working here by "locking" it. We still have to + * watch out for its size to be changed. */ + alist = curwin->w_alist; + ++alist->al_refcount; + + old_curwin = curwin; + old_curtab = curtab; + #ifdef FEAT_GUI need_mouse_correct = TRUE; #endif @@ -4392,7 +4482,7 @@ * When the ":tab" modifier was used do this for all tab pages. */ if (had_tab > 0) - goto_tabpage_tp(first_tabpage); + goto_tabpage_tp(first_tabpage, TRUE); for (;;) { tpnext = curtab->tp_next; @@ -4401,36 +4491,51 @@ wpnext = wp->w_next; buf = wp->w_buffer; if (buf->b_ffname == NULL - || buf->b_nwindows > 1 + || (!keep_tabs && buf->b_nwindows > 1) #ifdef FEAT_VERTSPLIT || wp->w_width != Columns #endif ) - i = ARGCOUNT; + i = opened_len; else { /* check if the buffer in this window is in the arglist */ - for (i = 0; i < ARGCOUNT; ++i) + for (i = 0; i < opened_len; ++i) { - if (ARGLIST[i].ae_fnum == buf->b_fnum - || fullpathcmp(alist_name(&ARGLIST[i]), - buf->b_ffname, TRUE) & FPC_SAME) + if (i < alist->al_ga.ga_len + && (AARGLIST(alist)[i].ae_fnum == buf->b_fnum + || fullpathcmp(alist_name(&AARGLIST(alist)[i]), + buf->b_ffname, TRUE) & FPC_SAME)) { - if (i < opened_len) + int weight = 1; + + if (old_curtab == curtab) + { + ++weight; + if (old_curwin == wp) + ++weight; + } + + if (weight > (int)opened[i]) { - opened[i] = TRUE; + opened[i] = (char_u)weight; if (i == 0) { + if (new_curwin != NULL) + new_curwin->w_arg_idx = opened_len; new_curwin = wp; new_curtab = curtab; } } - if (wp->w_alist != curwin->w_alist) + else if (keep_tabs) + i = opened_len; + + if (wp->w_alist != alist) { /* Use the current argument list for all windows * containing a file from it. */ alist_unlink(wp->w_alist); - wp->w_alist = curwin->w_alist; + wp->w_alist = alist; ++wp->w_alist->al_refcount; } break; @@ -4439,7 +4544,7 @@ } wp->w_arg_idx = i; - if (i == ARGCOUNT && !keep_tabs) /* close this window */ + if (i == opened_len && !keep_tabs)/* close this window */ { if (P_HID(buf) || forceit || buf->b_nwindows > 1 || !bufIsChanged(buf)) @@ -4461,7 +4566,8 @@ } #ifdef FEAT_WINDOWS /* don't close last window */ - if (firstwin == lastwin && first_tabpage->tp_next == NULL) + if (firstwin == lastwin + && (first_tabpage->tp_next == NULL || !had_tab)) #endif use_firstwin = TRUE; #ifdef FEAT_WINDOWS @@ -4488,27 +4594,23 @@ if (!valid_tabpage(tpnext)) tpnext = first_tabpage; /* start all over...*/ # endif - goto_tabpage_tp(tpnext); + goto_tabpage_tp(tpnext, TRUE); } /* * Open a window for files in the argument list that don't have one. * ARGCOUNT may change while doing this, because of autocommands. */ - if (count > ARGCOUNT || count <= 0) - count = ARGCOUNT; - - /* Autocommands may do anything to the argument list. Make sure it's not - * freed while we are working here by "locking" it. We still have to - * watch out for its size to be changed. */ - alist = curwin->w_alist; - ++alist->al_refcount; + if (count > opened_len || count <= 0) + count = opened_len; #ifdef FEAT_AUTOCMD /* Don't execute Win/Buf Enter/Leave autocommands here. */ ++autocmd_no_enter; ++autocmd_no_leave; #endif + last_curwin = curwin; + last_curtab = curtab; win_enter(lastwin, FALSE); #ifdef FEAT_WINDOWS /* ":drop all" should re-use an empty window to avoid "--remote-tab" @@ -4518,11 +4620,11 @@ use_firstwin = TRUE; #endif - for (i = 0; i < count && i < alist->al_ga.ga_len && !got_int; ++i) + for (i = 0; i < count && i < opened_len && !got_int; ++i) { if (alist == &global_alist && i == global_alist.al_ga.ga_len - 1) arg_had_last = TRUE; - if (i < opened_len && opened[i]) + if (opened[i] > 0) { /* Move the already present window to below the current window */ if (curwin->w_arg_idx != i) @@ -4531,7 +4633,13 @@ { if (wpnext->w_arg_idx == i) { - win_move_after(wpnext, curwin); + if (keep_tabs) + { + new_curwin = wpnext; + new_curtab = curtab; + } + else + win_move_after(wpnext, curwin); break; } } @@ -4586,9 +4694,17 @@ #ifdef FEAT_AUTOCMD --autocmd_no_enter; #endif + /* restore last referenced tabpage's curwin */ + if (last_curtab != new_curtab) + { + if (valid_tabpage(last_curtab)) + goto_tabpage_tp(last_curtab, TRUE); + if (win_valid(last_curwin)) + win_enter(last_curwin, FALSE); + } /* to window with first arg */ if (valid_tabpage(new_curtab)) - goto_tabpage_tp(new_curtab); + goto_tabpage_tp(new_curtab, TRUE); if (win_valid(new_curwin)) win_enter(new_curwin, FALSE); @@ -4640,7 +4756,7 @@ */ #ifdef FEAT_WINDOWS if (had_tab > 0) - goto_tabpage_tp(first_tabpage); + goto_tabpage_tp(first_tabpage, TRUE); for (;;) { #endif @@ -4658,7 +4774,11 @@ #ifdef FEAT_WINDOWS || (had_tab > 0 && wp != firstwin) #endif - ) && firstwin != lastwin) + ) && firstwin != lastwin +#ifdef FEAT_AUTOCMD + && !(wp->w_closing || wp->w_buffer->b_closing) +#endif + ) { win_close(wp, FALSE); #ifdef FEAT_AUTOCMD @@ -4676,7 +4796,7 @@ /* Without the ":tab" modifier only do the current tab page. */ if (had_tab == 0 || tpnext == NULL) break; - goto_tabpage_tp(tpnext); + goto_tabpage_tp(tpnext, TRUE); } #endif @@ -5417,7 +5537,7 @@ /* * Delete signs in buffer "buf". */ - static void + void buf_delete_signs(buf) buf_T *buf; { @@ -5465,7 +5585,7 @@ buf = firstbuf; else buf = rbuf; - while (buf != NULL) + while (buf != NULL && !got_int) { if (buf->b_signlist != NULL) { @@ -5473,7 +5593,7 @@ MSG_PUTS_ATTR(lbuf, hl_attr(HLF_D)); msg_putchar('\n'); } - for (p = buf->b_signlist; p != NULL; p = p->next) + for (p = buf->b_signlist; p != NULL && !got_int; p = p->next) { vim_snprintf(lbuf, BUFSIZ, _(" line=%ld id=%d name=%s"), (long)p->lnum, p->id, sign_typenr2name(p->typenr)); @@ -5606,7 +5726,7 @@ if (!aucmd) /* Don't trigger BufDelete autocommands here. */ block_autocmds(); #endif - close_buffer(NULL, buf, DOBUF_WIPE); + close_buffer(NULL, buf, DOBUF_WIPE, FALSE); #ifdef FEAT_AUTOCMD if (!aucmd) unblock_autocmds(); diff -Naur vim73.orig/src/charset.c vim73/src/charset.c --- vim73.orig/src/charset.c 2010-08-12 18:16:04.000000000 +0000 +++ vim73/src/charset.c 2012-07-20 20:31:16.277643707 +0000 @@ -463,41 +463,42 @@ if (enc_utf8) { int c = utf_ptr2char(STR_PTR(i)); - int ol = utf_ptr2len(STR_PTR(i)); + int olen = utf_ptr2len(STR_PTR(i)); int lc = utf_tolower(c); /* Only replace the character when it is not an invalid * sequence (ASCII character or more than one byte) and * utf_tolower() doesn't return the original character. */ - if ((c < 0x80 || ol > 1) && c != lc) + if ((c < 0x80 || olen > 1) && c != lc) { - int nl = utf_char2len(lc); + int nlen = utf_char2len(lc); /* If the byte length changes need to shift the following * characters forward or backward. */ - if (ol != nl) + if (olen != nlen) { - if (nl > ol) + if (nlen > olen) { - if (buf == NULL ? ga_grow(&ga, nl - ol + 1) == FAIL - : len + nl - ol >= buflen) + if (buf == NULL + ? ga_grow(&ga, nlen - olen + 1) == FAIL + : len + nlen - olen >= buflen) { /* out of memory, keep old char */ lc = c; - nl = ol; + nlen = olen; } } - if (ol != nl) + if (olen != nlen) { if (buf == NULL) { - STRMOVE(GA_PTR(i) + nl, GA_PTR(i) + ol); - ga.ga_len += nl - ol; + STRMOVE(GA_PTR(i) + nlen, GA_PTR(i) + olen); + ga.ga_len += nlen - olen; } else { - STRMOVE(buf + i + nl, buf + i + ol); - len += nl - ol; + STRMOVE(buf + i + nlen, buf + i + olen); + len += nlen - olen; } } } @@ -763,7 +764,7 @@ } /* - * Return the number of characters string "s" will take on the screen, + * Return the number of character cells string "s" will take on the screen, * counting TABs as two characters: "^I". */ int @@ -774,8 +775,8 @@ } /* - * Return the number of characters string "s[len]" will take on the screen, - * counting TABs as two characters: "^I". + * Return the number of character cells string "s[len]" will take on the + * screen, counting TABs as two characters: "^I". */ int vim_strnsize(s, len) @@ -1601,10 +1602,9 @@ #define LATIN1LOWER 'l' #define LATIN1UPPER 'U' -/* !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]%_'abcdefghijklmnopqrstuvwxyz{|}~ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ */ static char_u latin1flags[257] = " UUUUUUUUUUUUUUUUUUUUUUUUUU llllllllllllllllllllllllll UUUUUUUUUUUUUUUUUUUUUUU UUUUUUUllllllllllllllllllllllll llllllll"; -static char_u latin1upper[257] = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ÷ØÙÚÛÜÝÞÿ"; -static char_u latin1lower[257] = " !\"#$%&'()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿àáâãäåæçèéêëìíîïðñòóôõö×øùúûüýþßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"; +static char_u latin1upper[257] = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xf7\xd8\xd9\xda\xdb\xdc\xdd\xde\xff"; +static char_u latin1lower[257] = " !\"#$%&'()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xd7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"; int vim_islower(c) @@ -1829,7 +1829,7 @@ hex = 0; /* can't be octal */ break; } - if (ptr[n] > '0') + if (ptr[n] >= '0') hex = '0'; /* assume octal */ } } diff -Naur vim73.orig/src/config.h.in vim73/src/config.h.in --- vim73.orig/src/config.h.in 2010-08-13 13:45:27.000000000 +0000 +++ vim73/src/config.h.in 2012-07-20 20:31:14.604309173 +0000 @@ -346,9 +346,15 @@ /* Define if dynamic python does not require RTLD_GLOBAL */ #undef PY_NO_RTLD_GLOBAL +/* Define if dynamic python3 does not require RTLD_GLOBAL */ +#undef PY3_NO_RTLD_GLOBAL + /* Define if you want to include the Ruby interpreter. */ #undef FEAT_RUBY +/* Define for linking via dlopen() or LoadLibrary() */ +#undef DYNAMIC_RUBY + /* Define if you want to include the Tcl interpreter. */ #undef FEAT_TCL @@ -357,6 +363,7 @@ /* Define if you want to add support for ACL */ #undef HAVE_POSIX_ACL +#undef HAVE_SOLARIS_ZFS_ACL #undef HAVE_SOLARIS_ACL #undef HAVE_AIX_ACL diff -Naur vim73.orig/src/config.mk.in vim73/src/config.mk.in --- vim73.orig/src/config.mk.in 2010-07-17 15:28:51.000000000 +0000 +++ vim73/src/config.mk.in 2012-07-20 20:31:08.224304578 +0000 @@ -30,6 +30,7 @@ CPP = @CPP@ CPP_MM = @CPP_MM@ DEPEND_CFLAGS_FILTER = @DEPEND_CFLAGS_FILTER@ +LINK_AS_NEEDED = @LINK_AS_NEEDED@ X_CFLAGS = @X_CFLAGS@ X_LIBS_DIR = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ diff -Naur vim73.orig/src/configure.in vim73/src/configure.in --- vim73.orig/src/configure.in 2010-08-13 14:15:17.000000000 +0000 +++ vim73/src/configure.in 2012-07-20 20:31:17.044310922 +0000 @@ -28,6 +28,16 @@ AC_HEADER_STDC AC_HEADER_SYS_WAIT +dnl Check for the flag that fails if stuff are missing. + +AC_MSG_CHECKING(--enable-fail-if-missing argument) +AC_ARG_ENABLE(fail_if_missing, + [ --enable-fail-if-missing Fail if dependencies on additional features + specified on the command line are missing.], + [fail_if_missing="yes"], + [fail_if_missing="no"]) +AC_MSG_RESULT($fail_if_missing) + dnl Set default value for CFLAGS if none is defined or it's empty if test -z "$CFLAGS"; then CFLAGS="-O" @@ -319,15 +329,18 @@ echo "" echo "------------------------------------------" echo " On z/OS Unix, the environment variable" - echo " __CC_${ccn}MODE must be set to \"1\"!" + echo " _CC_${ccn}MODE must be set to \"1\"!" echo " Do:" echo " export _CC_${ccn}MODE=1" echo " and then call configure again." echo "------------------------------------------" exit 1 fi - CFLAGS="$CFLAGS -D_ALL_SOURCE -Wc,float\\(IEEE\\)"; - LDFLAGS="$LDFLAGS -Wl,EDIT=NO" + # Set CFLAGS for configure process. + # This will be reset later for config.mk. + # Use haltonmsg to force error for missing H files. + CFLAGS="$CFLAGS -D_ALL_SOURCE -Wc,float(ieee),haltonmsg(3296)"; + LDFLAGS="$LDFLAGS -Wl,EDIT=NO" AC_MSG_RESULT(yes) ;; *) zOSUnix="no"; @@ -491,6 +504,9 @@ LUA_CFLAGS="-DDYNAMIC_LUA_DLL=\\\"liblua${vi_cv_version_lua}.so$LUA_SONAME\\\" $LUA_CFLAGS" fi fi + if test "$fail_if_missing" = "yes" -a -z "$LUA_SRC"; then + AC_MSG_ERROR([could not configure lua]) + fi AC_SUBST(LUA_SRC) AC_SUBST(LUA_OBJ) AC_SUBST(LUA_PRO) @@ -568,13 +584,27 @@ SCHEME_INC=${vi_cv_path_mzscheme_pfx}/include/plt else AC_MSG_RESULT(no) - AC_MSG_CHECKING(if scheme.h can be found in /usr/include/plt/) - if test -f /usr/include/plt/scheme.h; then + AC_MSG_CHECKING(if scheme.h can be found in $vi_cv_path_mzscheme_pfx/include/racket) + if test -f $vi_cv_path_mzscheme_pfx/include/racket/scheme.h; then AC_MSG_RESULT(yes) - SCHEME_INC=/usr/include/plt + SCHEME_INC=${vi_cv_path_mzscheme_pfx}/include/racket else AC_MSG_RESULT(no) - vi_cv_path_mzscheme_pfx= + AC_MSG_CHECKING(if scheme.h can be found in /usr/include/plt/) + if test -f /usr/include/plt/scheme.h; then + AC_MSG_RESULT(yes) + SCHEME_INC=/usr/include/plt + else + AC_MSG_RESULT(no) + AC_MSG_CHECKING(if scheme.h can be found in /usr/include/racket/) + if test -f /usr/include/racket/scheme.h; then + AC_MSG_RESULT(yes) + SCHEME_INC=/usr/include/racket + else + AC_MSG_RESULT(no) + vi_cv_path_mzscheme_pfx= + fi + fi fi fi fi @@ -586,13 +616,23 @@ elif test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzscheme3m.a"; then MZSCHEME_LIBS="${vi_cv_path_mzscheme_pfx}/lib/libmzscheme3m.a" MZSCHEME_CFLAGS="-DMZ_PRECISE_GC" - elif test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a"; then + elif test -f "${vi_cv_path_mzscheme_pfx}/lib/libracket3m.a"; then + MZSCHEME_LIBS="${vi_cv_path_mzscheme_pfx}/lib/libracket3m.a" + MZSCHEME_CFLAGS="-DMZ_PRECISE_GC" + elif test -f "${vi_cv_path_mzscheme_pfx}/lib/libracket.a"; then + MZSCHEME_LIBS="${vi_cv_path_mzscheme_pfx}/lib/libracket.a ${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a" + elif test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzscheme.a"; then MZSCHEME_LIBS="${vi_cv_path_mzscheme_pfx}/lib/libmzscheme.a ${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a" else dnl Using shared objects if test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzscheme3m.so"; then MZSCHEME_LIBS="-L${vi_cv_path_mzscheme_pfx}/lib -lmzscheme3m" MZSCHEME_CFLAGS="-DMZ_PRECISE_GC" + elif test -f "${vi_cv_path_mzscheme_pfx}/lib/libracket3m.so"; then + MZSCHEME_LIBS="-L${vi_cv_path_mzscheme_pfx}/lib -lracket3m" + MZSCHEME_CFLAGS="-DMZ_PRECISE_GC" + elif test -f "${vi_cv_path_mzscheme_pfx}/lib/libracket.so"; then + MZSCHEME_LIBS="-L${vi_cv_path_mzscheme_pfx}/lib -lracket -lmzgc" else MZSCHEME_LIBS="-L${vi_cv_path_mzscheme_pfx}/lib -lmzscheme -lmzgc" fi @@ -607,10 +647,20 @@ fi if test -d $vi_cv_path_mzscheme_pfx/lib/plt/collects; then SCHEME_COLLECTS=lib/plt/ + else + if test -d $vi_cv_path_mzscheme_pfx/lib/racket/collects; then + SCHEME_COLLECTS=lib/racket/ + fi fi if test -f "${vi_cv_path_mzscheme_pfx}/${SCHEME_COLLECTS}collects/scheme/base.ss" ; then - dnl need to generate bytecode for MzScheme base MZSCHEME_EXTRA="mzscheme_base.c" + else + if test -f "${vi_cv_path_mzscheme_pfx}/${SCHEME_COLLECTS}collects/scheme/base.rkt" ; then + MZSCHEME_EXTRA="mzscheme_base.c" + fi + fi + if test "X$MZSCHEME_EXTRA" != "X" ; then + dnl need to generate bytecode for MzScheme base MZSCHEME_CFLAGS="${MZSCHEME_CFLAGS} -DINCLUDE_MZSCHEME_BASE" MZSCHEME_MZC="${vi_cv_path_mzscheme_pfx}/bin/mzc" fi @@ -747,6 +797,10 @@ PERL_CFLAGS="-DDYNAMIC_PERL_DLL=\\\"$libperl\\\" $PERL_CFLAGS" fi fi + + if test "$fail_if_missing" = "yes" -a "$perl_ok" != "yes"; then + AC_MSG_ERROR([could not configure perl]) + fi fi AC_SUBST(shrpenv) AC_SUBST(PERL_SRC) @@ -857,9 +911,9 @@ PYTHON_LIBS="${vi_cv_path_python_plibs}" if test "${vi_cv_path_python_pfx}" = "${vi_cv_path_python_epfx}"; then - PYTHON_CFLAGS="-I${vi_cv_path_python_pfx}/include/python${vi_cv_var_python_version}" + PYTHON_CFLAGS="-I${vi_cv_path_python_pfx}/include/python${vi_cv_var_python_version} -DPYTHON_HOME=\\\"${vi_cv_path_python_pfx}\\\"" else - PYTHON_CFLAGS="-I${vi_cv_path_python_pfx}/include/python${vi_cv_var_python_version} -I${vi_cv_path_python_epfx}/include/python${vi_cv_var_python_version}" + PYTHON_CFLAGS="-I${vi_cv_path_python_pfx}/include/python${vi_cv_var_python_version} -I${vi_cv_path_python_epfx}/include/python${vi_cv_var_python_version} -DPYTHON_HOME=\\\"${vi_cv_path_python_pfx}\\\"" fi PYTHON_SRC="if_python.c" dnl For Mac OSX 10.2 config.o is included in the Python library. @@ -871,7 +925,7 @@ if test "${vi_cv_var_python_version}" = "1.4"; then PYTHON_OBJ="$PYTHON_OBJ objects/py_getpath.o" fi - PYTHON_GETPATH_CFLAGS="-DPYTHONPATH='\"${vi_cv_path_pythonpath}\"' -DPREFIX='\"${vi_cv_path_python_pfx}\"' -DEXEC_PREFIX='\"${vi_cv_path_python_epfx}\"'" + PYTHON_GETPATH_CFLAGS="-DPYTHONPATH='\"${vi_cv_path_pythonpath}\"' -DPREFIX='\"${vi_cv_path_python_pfx}\"' -DEXEC_PREFIX='\"${vi_cv_path_python_epfx}\"'" dnl On FreeBSD linking with "-pthread" is required to use threads. dnl _THREAD_SAFE must be used for compiling then. @@ -932,6 +986,10 @@ AC_MSG_RESULT(too old) fi fi + + if test "$fail_if_missing" = "yes" -a "$python_ok" != "yes"; then + AC_MSG_ERROR([could not configure python]) + fi fi AC_SUBST(PYTHON_CONFDIR) @@ -958,6 +1016,17 @@ ${vi_cv_path_python3} -c 'import sys; print(sys.version[:3])'` ]]) + dnl -- get abiflags for python 3.2 or higher (PEP 3149) + AC_CACHE_CHECK(Python's abiflags,vi_cv_var_python3_abiflags, + [ + vi_cv_var_python3_abiflags= + if ${vi_cv_path_python3} -c \ + "import sys; sys.exit(${vi_cv_var_python3_version} < 3.2)" + then + vi_cv_var_python3_abiflags=`${vi_cv_path_python3} -c \ + "import sys; print(sys.abiflags)"` + fi ]) + dnl -- find where python3 thinks it was installed AC_CACHE_CHECK(Python's install prefix,vi_cv_path_python3_pfx, [ vi_cv_path_python3_pfx=` @@ -987,9 +1056,13 @@ AC_CACHE_CHECK(Python's configuration directory,vi_cv_path_python3_conf, [ vi_cv_path_python3_conf= + config_dir="config" + if test "${vi_cv_var_python3_abiflags}" != ""; then + config_dir="${config_dir}-${vi_cv_var_python3_version}${vi_cv_var_python3_abiflags}" + fi for path in "${vi_cv_path_python3_pfx}" "${vi_cv_path_python3_epfx}"; do for subdir in lib64 lib share; do - d="${path}/${subdir}/python${vi_cv_var_python3_version}/config" + d="${path}/${subdir}/python${vi_cv_var_python3_version}/${config_dir}" if test -d "$d" && test -f "$d/config.c"; then vi_cv_path_python3_conf="$d" fi @@ -1014,14 +1087,13 @@ @echo "python3_BASEMODLIBS='$(BASEMODLIBS)'" @echo "python3_LIBS='$(LIBS)'" @echo "python3_SYSLIBS='$(SYSLIBS)'" - @echo "python3_LINKFORSHARED='$(LINKFORSHARED)'" @echo "python3_INSTSONAME='$(INSTSONAME)'" eof dnl -- delete the lines from make about Entering/Leaving directory eval "`cd ${PYTHON3_CONFDIR} && make -f "${tmp_mkf}" __ | sed '/ directory /d'`" rm -f -- "${tmp_mkf}" - vi_cv_path_python3_plibs="-L${PYTHON3_CONFDIR} -lpython${vi_cv_var_python3_version}" - vi_cv_path_python3_plibs="${vi_cv_path_python3_plibs} ${python3_BASEMODLIBS} ${python3_LIBS} ${python3_SYSLIBS} ${python3_LINKFORSHARED}" + vi_cv_path_python3_plibs="-L${PYTHON3_CONFDIR} -lpython${vi_cv_var_python3_version}${vi_cv_var_python3_abiflags}" + vi_cv_path_python3_plibs="${vi_cv_path_python3_plibs} ${python3_BASEMODLIBS} ${python3_LIBS} ${python3_SYSLIBS}" dnl remove -ltermcap, it can conflict with an earlier -lncurses vi_cv_path_python3_plibs=`echo $vi_cv_path_python3_plibs | sed s/-ltermcap//` vi_cv_path_python3_plibs=`echo $vi_cv_path_python3_plibs | sed s/-lffi//` @@ -1029,9 +1101,9 @@ PYTHON3_LIBS="${vi_cv_path_python3_plibs}" if test "${vi_cv_path_python3_pfx}" = "${vi_cv_path_python3_epfx}"; then - PYTHON3_CFLAGS="-I${vi_cv_path_python3_pfx}/include/python${vi_cv_var_python3_version}" + PYTHON3_CFLAGS="-I${vi_cv_path_python3_pfx}/include/python${vi_cv_var_python3_version}${vi_cv_var_python3_abiflags} -DPYTHON3_HOME=L\\\"${vi_cv_path_python3_pfx}\\\"" else - PYTHON3_CFLAGS="-I${vi_cv_path_python3_pfx}/include/python${vi_cv_var_python3_version} -I${vi_cv_path_python3_epfx}/include/python${vi_cv_var_python3_version}" + PYTHON3_CFLAGS="-I${vi_cv_path_python3_pfx}/include/python${vi_cv_var_python3_version}${vi_cv_var_python3_abiflags} -I${vi_cv_path_python3_epfx}/include/python${vi_cv_var_python3_version}${vi_cv_var_python3_abiflags} -DPYTHON3_HOME=L\\\"${vi_cv_path_python3_pfx}\\\"" fi PYTHON3_SRC="if_python3.c" dnl For Mac OSX 10.2 config.o is included in the Python library. @@ -1109,11 +1181,12 @@ if test "$python_ok" = yes && test "$python3_ok" = yes; then AC_DEFINE(DYNAMIC_PYTHON) AC_DEFINE(DYNAMIC_PYTHON3) - AC_MSG_CHECKING(whether we can do without RTLD_GLOBAL) + AC_MSG_CHECKING(whether we can do without RTLD_GLOBAL for Python) cflags_save=$CFLAGS - CFLAGS="$CFLAGS $PYTHON3_CFLAGS" + CFLAGS="$CFLAGS $PYTHON_CFLAGS" ldflags_save=$LDFLAGS - LDFLAGS="$LDFLAGS -ldl" + dnl -ldl must go first to make this work on Archlinux (Roland Puntaier) + LDFLAGS="-ldl $LDFLAGS" AC_RUN_IFELSE([ #include /* If this program fails, then RTLD_GLOBAL is needed. @@ -1122,15 +1195,17 @@ * Only the first pyhton version used will be switched on. */ - int no_rtl_global_needed_for(char *python_instsoname) + int no_rtl_global_needed_for(char *python_instsoname, char *prefix) { int needed = 0; void* pylib = dlopen(python_instsoname, RTLD_LAZY); if (pylib != 0) { + void (*pfx)(char *home) = dlsym(pylib, "Py_SetPythonHome"); void (*init)(void) = dlsym(pylib, "Py_Initialize"); int (*simple)(char*) = dlsym(pylib, "PyRun_SimpleString"); void (*final)(void) = dlsym(pylib, "Py_Finalize"); + (*pfx)(prefix); (*init)(); needed = (*simple)("import termios") == -1; (*final)(); @@ -1142,13 +1217,61 @@ int main(int argc, char** argv) { int not_needed = 0; - if (no_rtl_global_needed_for("libpython2.7.so.1.0") && no_rtl_global_needed_for("libpython3.1.so.1.0")) + if (no_rtl_global_needed_for("${python_INSTSONAME}", "${vi_cv_path_python_pfx}")) not_needed = 1; return !not_needed; }], [AC_MSG_RESULT(yes);AC_DEFINE(PY_NO_RTLD_GLOBAL)], [AC_MSG_RESULT(no)]) + + CFLAGS=$cflags_save + LDFLAGS=$ldflags_save + + AC_MSG_CHECKING(whether we can do without RTLD_GLOBAL for Python3) + cflags_save=$CFLAGS + CFLAGS="$CFLAGS $PYTHON3_CFLAGS" + ldflags_save=$LDFLAGS + dnl -ldl must go first to make this work on Archlinux (Roland Puntaier) + LDFLAGS="-ldl $LDFLAGS" + AC_RUN_IFELSE([ + #include + #include + /* If this program fails, then RTLD_GLOBAL is needed. + * RTLD_GLOBAL will be used and then it is not possible to + * have both python versions enabled in the same vim instance. + * Only the first pyhton version used will be switched on. + */ + + int no_rtl_global_needed_for(char *python_instsoname, wchar_t *prefix) + { + int needed = 0; + void* pylib = dlopen(python_instsoname, RTLD_LAZY); + if (pylib != 0) + { + void (*pfx)(wchar_t *home) = dlsym(pylib, "Py_SetPythonHome"); + void (*init)(void) = dlsym(pylib, "Py_Initialize"); + int (*simple)(char*) = dlsym(pylib, "PyRun_SimpleString"); + void (*final)(void) = dlsym(pylib, "Py_Finalize"); + (*pfx)(prefix); + (*init)(); + needed = (*simple)("import termios") == -1; + (*final)(); + dlclose(pylib); + } + return !needed; + } + + int main(int argc, char** argv) + { + int not_needed = 0; + if (no_rtl_global_needed_for("${python3_INSTSONAME}", L"${vi_cv_path_python3_pfx}")) + not_needed = 1; + return !not_needed; + }], + [AC_MSG_RESULT(yes);AC_DEFINE(PY3_NO_RTLD_GLOBAL)], [AC_MSG_RESULT(no)]) + CFLAGS=$cflags_save LDFLAGS=$ldflags_save + PYTHON_SRC="if_python.c" PYTHON_OBJ="objects/if_python.o" PYTHON_CFLAGS="$PYTHON_CFLAGS -DDYNAMIC_PYTHON_DLL=\\\"${python_INSTSONAME}\\\"" @@ -1290,6 +1413,9 @@ AC_MSG_RESULT(too old; need Tcl version 8.0 or later) fi fi + if test "$fail_if_missing" = "yes" -a -z "$TCL_SRC"; then + AC_MSG_ERROR([could not configure Tcl]) + fi fi AC_SUBST(TCL_SRC) AC_SUBST(TCL_OBJ) @@ -1299,15 +1425,15 @@ AC_MSG_CHECKING(--enable-rubyinterp argument) AC_ARG_ENABLE(rubyinterp, - [ --enable-rubyinterp Include Ruby interpreter.], , + [ --enable-rubyinterp[=OPTS] Include Ruby interpreter. [default=no] [OPTS=no/yes/dynamic]], , [enable_rubyinterp="no"]) AC_MSG_RESULT($enable_rubyinterp) -if test "$enable_rubyinterp" = "yes"; then +if test "$enable_rubyinterp" = "yes" -o "$enable_rubyinterp" = "dynamic"; then AC_MSG_CHECKING(--with-ruby-command argument) + AC_SUBST(vi_cv_path_ruby) AC_ARG_WITH(ruby-command, [ --with-ruby-command=RUBY name of the Ruby command (default: ruby)], - RUBY_CMD="$withval"; AC_MSG_RESULT($RUBY_CMD), + RUBY_CMD="$withval"; vi_cv_path_ruby="$withval"; AC_MSG_RESULT($RUBY_CMD), RUBY_CMD="ruby"; AC_MSG_RESULT(defaulting to $RUBY_CMD)) - AC_SUBST(vi_cv_path_ruby) AC_PATH_PROG(vi_cv_path_ruby, $RUBY_CMD) if test "X$vi_cv_path_ruby" != "X"; then AC_MSG_CHECKING(Ruby version) @@ -1329,18 +1455,15 @@ RUBY_LIBS="$rubylibs" fi librubyarg=`$vi_cv_path_ruby -r rbconfig -e 'print Config.expand(Config::CONFIG[["LIBRUBYARG"]])'` - if test -f "$rubyhdrdir/$librubyarg"; then - librubyarg="$rubyhdrdir/$librubyarg" - else - rubylibdir=`$vi_cv_path_ruby -r rbconfig -e 'print Config.expand(Config::CONFIG[["libdir"]])'` - if test -f "$rubylibdir/$librubyarg"; then - librubyarg="$rubylibdir/$librubyarg" - elif test "$librubyarg" = "libruby.a"; then - dnl required on Mac OS 10.3 where libruby.a doesn't exist - librubyarg="-lruby" - else - librubyarg=`$vi_cv_path_ruby -r rbconfig -e "print '$librubyarg'.gsub(/-L\./, %'-L#{Config.expand(Config::CONFIG[\"libdir\"])}')"` - fi + librubya=`$vi_cv_path_ruby -r rbconfig -e 'print Config.expand(Config::CONFIG[["LIBRUBY_A"]])'` + rubylibdir=`$vi_cv_path_ruby -r rbconfig -e 'print Config.expand(Config::CONFIG[["libdir"]])'` + if test -f "$rubylibdir/$librubya"; then + librubyarg="$librubyarg" + RUBY_LIBS="$RUBY_LIBS -L$rubylibdir" + elif test "$librubyarg" = "libruby.a"; then + dnl required on Mac OS 10.3 where libruby.a doesn't exist + librubyarg="-lruby" + RUBY_LIBS="$RUBY_LIBS -L$rubylibdir" fi if test "X$librubyarg" != "X"; then @@ -1360,6 +1483,12 @@ RUBY_OBJ="objects/if_ruby.o" RUBY_PRO="if_ruby.pro" AC_DEFINE(FEAT_RUBY) + if test "$enable_rubyinterp" = "dynamic"; then + libruby=`$vi_cv_path_ruby -r rbconfig -e 'printf "lib%s.%s\n", Config::CONFIG[["RUBY_SO_NAME"]], Config::CONFIG[["DLEXT"]]'` + AC_DEFINE(DYNAMIC_RUBY) + RUBY_CFLAGS="-DDYNAMIC_RUBY_DLL=\\\"$libruby\\\" -DDYNAMIC_RUBY_VER=$rubyversion $RUBY_CFLAGS" + RUBY_LIBS= + fi else AC_MSG_RESULT(not found; disabling Ruby) fi @@ -1367,6 +1496,10 @@ AC_MSG_RESULT(too old; need Ruby version 1.6.0 or later) fi fi + + if test "$fail_if_missing" = "yes" -a -z "$RUBY_OBJ"; then + AC_MSG_ERROR([could not configure Ruby]) + fi fi AC_SUBST(RUBY_SRC) AC_SUBST(RUBY_OBJ) @@ -2248,10 +2381,15 @@ if test -z "$SKIP_MOTIF"; then cppflags_save=$CPPFLAGS CPPFLAGS="$CPPFLAGS $X_CFLAGS" - AC_CHECK_HEADERS(Xm/Xm.h Xm/XpmP.h Xm/JoinSideT.h Xm/TraitP.h Xm/Manager.h \ - Xm/UnhighlightT.h Xm/Notebook.h) + if test "$zOSUnix" = "yes"; then + xmheader="Xm/Xm.h" + else + xmheader="Xm/Xm.h Xm/XpmP.h Xm/JoinSideT.h Xm/TraitP.h Xm/Manager.h + Xm/UnhighlightT.h Xm/Notebook.h" + fi + AC_CHECK_HEADERS($xmheader) - if test $ac_cv_header_Xm_XpmP_h = yes; then + if test "x$ac_cv_header_Xm_XpmP_h" = "xyes"; then dnl Solaris uses XpmAttributes_21, very annoying. AC_MSG_CHECKING([for XpmAttributes_21 in Xm/XpmP.h]) AC_TRY_COMPILE([#include ], [XpmAttributes_21 attr;], @@ -2529,13 +2667,14 @@ AC_MSG_RESULT([empty: automatic terminal library selection]) dnl On HP-UX 10.10 termcap or termlib should be used instead of dnl curses, because curses is much slower. - dnl Newer versions of ncurses are preferred over anything. + dnl Newer versions of ncurses are preferred over anything, except + dnl when tinfo has been split off, it contains all we need. dnl Older versions of ncurses have bugs, get a new one! dnl Digital Unix (OSF1) should use curses (Ronald Schild). dnl On SCO Openserver should prefer termlib (Roger Cornelius). case "`uname -s 2>/dev/null`" in - OSF1|SCO_SV) tlibs="ncurses curses termlib termcap";; - *) tlibs="ncurses termlib termcap curses";; + OSF1|SCO_SV) tlibs="tinfo ncurses curses termlib termcap";; + *) tlibs="tinfo ncurses termlib termcap curses";; esac for libname in $tlibs; do AC_CHECK_LIB(${libname}, tgetent,,) @@ -2975,6 +3114,7 @@ dnl Link with -lposix1e for ACL stuff; if not found, try -lacl for SGI dnl when -lacl works, also try to use -lattr (required for Debian). +dnl On Solaris, use the acl_get/set functions in libsec, if present. AC_MSG_CHECKING(--disable-acl argument) AC_ARG_ENABLE(acl, [ --disable-acl Don't check for ACL support.], @@ -2997,6 +3137,7 @@ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_POSIX_ACL), AC_MSG_RESULT(no)) +AC_CHECK_LIB(sec, acl_get, [LIBS="$LIBS -lsec"; AC_DEFINE(HAVE_SOLARIS_ZFS_ACL)], AC_MSG_CHECKING(for Solaris ACL support) AC_TRY_LINK([ #ifdef HAVE_SYS_ACL_H @@ -3004,7 +3145,7 @@ #endif], [acl("foo", GETACLCNT, 0, NULL); ], AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SOLARIS_ACL), - AC_MSG_RESULT(no)) + AC_MSG_RESULT(no))) AC_MSG_CHECKING(for AIX ACL support) AC_TRY_LINK([ @@ -3180,7 +3321,7 @@ }], AC_MSG_RESULT(ok), AC_MSG_ERROR([WRONG! uint32_t not defined correctly.]), -AC_MSG_ERROR([could not compile program using uint32_t.])) +AC_MSG_WARN([cannot check uint32_t when cross-compiling.])) dnl Check for memmove() before bcopy(), makes memmove() be used when both are dnl present, fixes problem with incompatibility between Solaris 2.4 and 2.5. @@ -3280,7 +3421,7 @@ AC_CHECK_LIB(xpg4, _xpg4_setrunelocale, [LIBS="$LIBS -lxpg4"],,) dnl Check how we can run ctags. Default to "ctags" when nothing works. -dnl --version for Exuberant ctags (preferred) +dnl Use --version to detect Exuberant ctags (preferred) dnl Add --fields=+S to get function signatures for omni completion. dnl -t for typedefs (many ctags have this) dnl -s for static functions (Elvis ctags only?) @@ -3290,6 +3431,10 @@ test -f tags && mv tags tags.save if (eval ctags --version /dev/null | grep Exuberant) < /dev/null 1>&AC_FD_CC 2>&1; then TAGPRG="ctags -I INIT+ --fields=+S" +elif (eval exctags --version /dev/null | grep Exuberant) < /dev/null 1>&AC_FD_CC 2>&1; then + TAGPRG="exctags -I INIT+ --fields=+S" +elif (eval exuberant-ctags --version /dev/null | grep Exuberant) < /dev/null 1>&AC_FD_CC 2>&1; then + TAGPRG="exuberant-ctags -I INIT+ --fields=+S" else TAGPRG="ctags" (eval etags /dev/null) < /dev/null 1>&AC_FD_CC 2>&1 && TAGPRG="etags" @@ -3477,9 +3622,10 @@ dnl -D_FORTIFY_SOURCE=2 crashes Vim on strcpy(buf, "000") when buf is dnl declared as char x[1] but actually longer. Introduced in gcc 4.0. dnl Also remove duplicate _FORTIFY_SOURCE arguments. + dnl And undefine it first to avoid a warning. AC_MSG_CHECKING(whether we need -D_FORTIFY_SOURCE=1) if test "$gccmajor" -gt "3"; then - CFLAGS=`echo "$CFLAGS" | sed -e 's/-Wp,-D_FORTIFY_SOURCE=.//g' -e 's/-D_FORTIFY_SOURCE=.//g' -e 's/$/ -D_FORTIFY_SOURCE=1/'` + CFLAGS=`echo "$CFLAGS" | sed -e 's/-Wp,-D_FORTIFY_SOURCE=.//g' -e 's/-D_FORTIFY_SOURCE=.//g' -e 's/$/ -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1/'` AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) @@ -3487,6 +3633,28 @@ fi AC_SUBST(DEPEND_CFLAGS_FILTER) +dnl link.sh tries to avoid overlinking in a hackish way. +dnl At least GNU ld supports --as-needed which provides the same functionality +dnl at linker level. Let's use it. +AC_MSG_CHECKING(linker --as-needed support) +LINK_AS_NEEDED= +# Check if linker supports --as-needed and --no-as-needed options +if $CC -Wl,--help 2>/dev/null | grep as-needed > /dev/null; then + LDFLAGS="$LDFLAGS -Wl,--as-needed" + LINK_AS_NEEDED=yes +fi +if test "$LINK_AS_NEEDED" = yes; then + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) +fi +AC_SUBST(LINK_AS_NEEDED) + +# IBM z/OS reset CFLAGS for config.mk +if test "$zOSUnix" = "yes"; then + CFLAGS="-D_ALL_SOURCE -Wc,float\(ieee\),dll" +fi + dnl write output files AC_OUTPUT(auto/config.mk:config.mk.in) diff -Naur vim73.orig/src/dehqx.py vim73/src/dehqx.py --- vim73.orig/src/dehqx.py 2010-05-15 11:04:12.000000000 +0000 +++ vim73/src/dehqx.py 2012-07-20 20:31:17.260977744 +0000 @@ -1,7 +1,10 @@ # Python script to get both the data and resource fork from a BinHex encoded # file. -# Author: Taro Muraoka -# Last Change: 2003 Oct 25 +# Author: MURAOKA Taro +# Last Change: 2012 Jun 29 +# +# Copyright (C) 2003,12 MURAOKA Taro +# THIS FILE IS DISTRIBUTED UNDER THE VIM LICENSE. import sys import binhex diff -Naur vim73.orig/src/diff.c vim73/src/diff.c --- vim73.orig/src/diff.c 2010-07-31 13:35:21.000000000 +0000 +++ vim73/src/diff.c 2012-07-20 20:31:16.204310320 +0000 @@ -783,6 +783,15 @@ goto theend; } + /* :diffupdate! */ + if (eap != NULL && eap->forceit) + for (idx_new = idx_orig; idx_new < DB_COUNT; ++idx_new) + { + buf = curtab->tp_diffbuf[idx_new]; + if (buf_valid(buf)) + buf_check_timestamp(buf, FALSE); + } + /* Write the first buffer to a tempfile. */ buf = curtab->tp_diffbuf[idx_orig]; if (diff_write(buf, tmp_orig) == FAIL) @@ -1127,11 +1136,13 @@ # endif wp->w_p_diff = TRUE; + /* Use 'scrollbind' and 'cursorbind' when available */ +#ifdef FEAT_SCROLLBIND + wp->w_p_scb = TRUE; +#endif #ifdef FEAT_CURSORBIND - /* Use cursorbind if it's available */ wp->w_p_crb = TRUE; #endif - wp->w_p_scb = TRUE; wp->w_p_wrap = FALSE; # ifdef FEAT_FOLDING curwin = wp; @@ -1177,10 +1188,7 @@ { /* Set 'diff', 'scrollbind' off and 'wrap' on. */ wp->w_p_diff = FALSE; -#ifdef FEAT_CURSORBIND - wp->w_p_crb = FALSE; -#endif - wp->w_p_scb = FALSE; + RESET_BINDING(wp); wp->w_p_wrap = TRUE; #ifdef FEAT_FOLDING curwin = wp; diff -Naur vim73.orig/src/digraph.c vim73/src/digraph.c --- vim73.orig/src/digraph.c 2010-05-15 11:04:09.000000000 +0000 +++ vim73/src/digraph.c 2012-07-20 20:31:14.044308771 +0000 @@ -2080,13 +2080,13 @@ /* * Lookup the pair "char1", "char2" in the digraph tables. * If no match, return "char2". - * If "meta" is TRUE and "char1" is a space, return "char2" | 0x80. + * If "meta_char" is TRUE and "char1" is a space, return "char2" | 0x80. */ static int -getexactdigraph(char1, char2, meta) +getexactdigraph(char1, char2, meta_char) int char1; int char2; - int meta; + int meta_char; { int i; int retval = 0; @@ -2159,7 +2159,7 @@ if (retval == 0) /* digraph deleted or not found */ { - if (char1 == ' ' && meta) /* --> meta-char */ + if (char1 == ' ' && meta_char) /* --> meta-char */ return (char2 | 0x80); return char2; } @@ -2171,16 +2171,16 @@ * Allow for both char1-char2 and char2-char1 */ int -getdigraph(char1, char2, meta) +getdigraph(char1, char2, meta_char) int char1; int char2; - int meta; + int meta_char; { int retval; - if (((retval = getexactdigraph(char1, char2, meta)) == char2) + if (((retval = getexactdigraph(char1, char2, meta_char)) == char2) && (char1 != char2) - && ((retval = getexactdigraph(char2, char1, meta)) == char1)) + && ((retval = getexactdigraph(char2, char1, meta_char)) == char1)) return char2; return retval; } diff -Naur vim73.orig/src/edit.c vim73/src/edit.c --- vim73.orig/src/edit.c 2010-08-08 12:55:05.000000000 +0000 +++ vim73/src/edit.c 2012-07-20 20:31:18.157645052 +0000 @@ -58,6 +58,10 @@ }; static char e_hitend[] = N_("Hit end of paragraph"); +#ifdef FEAT_COMPL_FUNC +static char e_complwin[] = N_("E839: Completion function changed window"); +static char e_compldel[] = N_("E840: Completion function deleted text"); +#endif /* * Structure used to store one match for insert completion. @@ -131,6 +135,8 @@ static int compl_cont_mode = 0; static expand_T compl_xp; +static int compl_opt_refresh_always = FALSE; + 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)); @@ -149,16 +155,19 @@ static void ins_compl_free __ARGS((void)); static void ins_compl_clear __ARGS((void)); static int ins_compl_bs __ARGS((void)); +static int ins_compl_need_restart __ARGS((void)); static void ins_compl_new_leader __ARGS((void)); static void ins_compl_addleader __ARGS((int c)); -static int ins_compl_len __ARGS((void)); +static int ins_compl_len __ARGS((void)); static void ins_compl_restart __ARGS((void)); static void ins_compl_set_original_text __ARGS((char_u *str)); static void ins_compl_addfrommatch __ARGS((void)); static int ins_compl_prep __ARGS((int c)); +static void ins_compl_fixRedoBufForLeader __ARGS((char_u *ptr_arg)); static buf_T *ins_compl_next_buf __ARGS((buf_T *buf, int flag)); #if defined(FEAT_COMPL_FUNC) || defined(FEAT_EVAL) static void ins_compl_add_list __ARGS((list_T *list)); +static void ins_compl_add_dict __ARGS((dict_T *dict)); #endif static int ins_compl_get_exp __ARGS((pos_T *ini)); static void ins_compl_delete __ARGS((void)); @@ -244,12 +253,14 @@ #ifdef FEAT_DIGRAPHS static int ins_digraph __ARGS((void)); #endif -static int ins_copychar __ARGS((linenr_T lnum)); static int ins_ctrl_ey __ARGS((int tc)); #ifdef FEAT_SMARTINDENT static void ins_try_si __ARGS((int c)); #endif static colnr_T get_nolist_virtcol __ARGS((void)); +#ifdef FEAT_AUTOCMD +static char_u *do_insert_char_pre __ARGS((int c)); +#endif static colnr_T Insstart_textlen; /* length of line when insert started */ static colnr_T Insstart_blank_vcol; /* vcol for first inserted blank */ @@ -775,7 +786,20 @@ * completion: Add to "compl_leader". */ if (ins_compl_accept_char(c)) { - ins_compl_addleader(c); +#ifdef FEAT_AUTOCMD + /* Trigger InsertCharPre. */ + char_u *str = do_insert_char_pre(c); + char_u *p; + + if (str != NULL) + { + for (p = str; *p != NUL; mb_ptr_adv(p)) + ins_compl_addleader(PTR2CHAR(p)); + vim_free(str); + } + else +#endif + ins_compl_addleader(c); continue; } @@ -1377,10 +1401,42 @@ goto do_intr; #endif +normalchar: /* * Insert a nomal character. */ -normalchar: +#ifdef FEAT_AUTOCMD + if (!p_paste) + { + /* Trigger InsertCharPre. */ + char_u *str = do_insert_char_pre(c); + char_u *p; + + if (str != NULL) + { + if (*str != NUL && stop_arrow() != FAIL) + { + /* Insert the new value of v:char literally. */ + for (p = str; *p != NUL; mb_ptr_adv(p)) + { + c = PTR2CHAR(p); + if (c == CAR || c == K_KENTER || c == NL) + ins_eol(c); + else + ins_char(c); + } + AppendToRedobuffLit(str, -1); + } + vim_free(str); + c = NUL; + } + + /* If the new value is already inserted or an empty string + * then don't insert any character. */ + if (c == NUL) + break; + } +#endif #ifdef FEAT_SMARTINDENT /* Try to perform smart-indenting. */ ins_try_si(c); @@ -1398,13 +1454,16 @@ Insstart_blank_vcol = get_nolist_virtcol(); } - if (vim_iswordc(c) || !echeck_abbr( + /* Insert a normal character and check for abbreviations on a + * special character. Let CTRL-] expand abbreviations without + * inserting it. */ + if (vim_iswordc(c) || (!echeck_abbr( #ifdef FEAT_MBYTE /* Add ABBR_OFF for characters above 0x100, this is * what check_abbr() expects. */ (has_mbyte && c >= 0x100) ? (c + ABBR_OFF) : #endif - c)) + c) && c != Ctrl_RSB)) { insert_special(c, FALSE, FALSE); #ifdef FEAT_RIGHTLEFT @@ -1549,12 +1608,16 @@ ins_ctrl_v() { int c; + int did_putchar = FALSE; /* may need to redraw when no more chars available now */ ins_redraw(FALSE); if (redrawing() && !char_avail()) + { edit_putchar('^', TRUE); + did_putchar = TRUE; + } AppendToRedobuff((char_u *)CTRL_V_STR); /* CTRL-V */ #ifdef FEAT_CMDL_INFO @@ -1562,8 +1625,10 @@ #endif c = get_literal(); - edit_unputchar(); /* when line fits in 'columns' the '^' is at the start - of the next line and will not be redrawn */ + if (did_putchar) + /* when the line fits in 'columns' the '^' is at the start of the next + * line and will not removed by the redraw */ + edit_unputchar(); #ifdef FEAT_CMDL_INFO clear_showcmd(); #endif @@ -1583,11 +1648,7 @@ #define PC_STATUS_RIGHT 1 /* right halve of double-wide char */ #define PC_STATUS_LEFT 2 /* left halve of double-wide char */ #define PC_STATUS_SET 3 /* pc_bytes was filled */ -#ifdef FEAT_MBYTE static char_u pc_bytes[MB_MAXBYTES + 1]; /* saved bytes */ -#else -static char_u pc_bytes[2]; /* saved bytes */ -#endif static int pc_attr; static int pc_row; static int pc_col; @@ -1713,9 +1774,9 @@ static void undisplay_dollar() { - if (dollar_vcol) + if (dollar_vcol >= 0) { - dollar_vcol = 0; + dollar_vcol = -1; redrawWinline(curwin->w_cursor.lnum, FALSE); } } @@ -2133,7 +2194,7 @@ || c == Ctrl_I || c == Ctrl_D || c == Ctrl_P || c == Ctrl_N || c == Ctrl_T || c == Ctrl_V || c == Ctrl_Q || c == Ctrl_U || c == Ctrl_O - || c == Ctrl_S || c == 's'); + || c == Ctrl_S || c == Ctrl_K || c == 's'); case CTRL_X_SCROLL: return (c == Ctrl_Y || c == Ctrl_E); case CTRL_X_WHOLE_LINE: @@ -2658,6 +2719,7 @@ if (stop_arrow() == FAIL) return; + compl_direction = FORWARD; if (startcol > curwin->w_cursor.col) startcol = curwin->w_cursor.col; compl_col = startcol; @@ -3295,7 +3357,7 @@ /* Deleted more than what was used to find matches or didn't finish * finding all matches: need to look for matches all over again. */ if (curwin->w_cursor.col <= compl_col + compl_length - || compl_was_interrupted) + || ins_compl_need_restart()) ins_compl_restart(); vim_free(compl_leader); @@ -3309,6 +3371,20 @@ } /* + * Return TRUE when we need to find matches again, ins_compl_restart() is to + * be called. + */ + static int +ins_compl_need_restart() +{ + /* Return TRUE if we didn't complete finding matches or when the + * 'completefunc' returned "always" in the "refresh" dictionary item. */ + return compl_was_interrupted + || ((ctrl_x_mode == CTRL_X_FUNCTION || ctrl_x_mode == CTRL_X_OMNI) + && compl_opt_refresh_always); +} + +/* * Called after changing "compl_leader". * Show the popup menu with a different set of matches. * May also search for matches again if the previous search was interrupted. @@ -3391,20 +3467,32 @@ (*mb_char2bytes)(c, buf); buf[cc] = NUL; ins_char_bytes(buf, cc); + if (compl_opt_refresh_always) + AppendToRedobuff(buf); } else #endif + { ins_char(c); + if (compl_opt_refresh_always) + AppendCharToRedobuff(c); + } /* If we didn't complete finding matches we must search again. */ - if (compl_was_interrupted) + if (ins_compl_need_restart()) ins_compl_restart(); - vim_free(compl_leader); - compl_leader = vim_strnsave(ml_get_curline() + compl_col, + /* When 'always' is set, don't reset compl_leader. While completing, + * cursor doesn't point original position, changing compl_leader would + * break redo. */ + if (!compl_opt_refresh_always) + { + vim_free(compl_leader); + compl_leader = vim_strnsave(ml_get_curline() + compl_col, (int)(curwin->w_cursor.col - compl_col)); - if (compl_leader != NULL) - ins_compl_new_leader(); + if (compl_leader != NULL) + ins_compl_new_leader(); + } } /* @@ -3480,11 +3568,7 @@ return; } p += len; -#ifdef FEAT_MBYTE - c = mb_ptr2char(p); -#else - c = *p; -#endif + c = PTR2CHAR(p); ins_compl_addleader(c); } @@ -3653,9 +3737,6 @@ * memory that was used, and make sure we can redo the insert. */ if (compl_curr_match != NULL || compl_leader != NULL || c == Ctrl_E) { - char_u *p; - int temp = 0; - /* * If any of the original typed text has been changed, eg when * ignorecase is set, we must add back-spaces to the redo @@ -3666,25 +3747,9 @@ */ if (compl_curr_match != NULL && compl_used_match && c != Ctrl_E) ptr = compl_curr_match->cp_str; - else if (compl_leader != NULL) - ptr = compl_leader; else - ptr = compl_orig_text; - if (compl_orig_text != NULL) - { - p = compl_orig_text; - for (temp = 0; p[temp] != NUL && p[temp] == ptr[temp]; - ++temp) - ; -#ifdef FEAT_MBYTE - if (temp > 0) - temp -= (*mb_head_off)(compl_orig_text, p + temp); -#endif - for (p += temp; *p != NUL; mb_ptr_adv(p)) - AppendCharToRedobuff(K_BS); - } - if (ptr != NULL) - AppendToRedobuffLit(ptr + temp, -1); + ptr = NULL; + ins_compl_fixRedoBufForLeader(ptr); } #ifdef FEAT_CINDENT @@ -3759,6 +3824,11 @@ if (want_cindent && in_cinkeys(KEY_COMPLETE, ' ', inindent(0))) do_c_expr_indent(); #endif +#ifdef FEAT_AUTOCMD + /* Trigger the CompleteDone event to give scripts a chance to act + * upon the completion. */ + apply_autocmds(EVENT_COMPLETEDONE, NULL, NULL, FALSE, curbuf); +#endif } } @@ -3774,6 +3844,44 @@ } /* + * Fix the redo buffer for the completion leader replacing some of the typed + * text. This inserts backspaces and appends the changed text. + * "ptr" is the known leader text or NUL. + */ + static void +ins_compl_fixRedoBufForLeader(ptr_arg) + char_u *ptr_arg; +{ + int len; + char_u *p; + char_u *ptr = ptr_arg; + + if (ptr == NULL) + { + if (compl_leader != NULL) + ptr = compl_leader; + else + return; /* nothing to do */ + } + if (compl_orig_text != NULL) + { + p = compl_orig_text; + for (len = 0; p[len] != NUL && p[len] == ptr[len]; ++len) + ; +#ifdef FEAT_MBYTE + if (len > 0) + len -= (*mb_head_off)(p, p + len); +#endif + for (p += len; *p != NUL; mb_ptr_adv(p)) + AppendCharToRedobuff(K_BS); + } + else + len = 0; + if (ptr != NULL) + AppendToRedobuffLit(ptr + len, -1); +} + +/* * Loops through the list of windows, loaded-buffers or non-loaded-buffers * (depending on flag) starting from buf and looking for a non-scanned * buffer (other than curbuf). curbuf is special, if it is called with @@ -3829,10 +3937,14 @@ int type; /* CTRL_X_OMNI or CTRL_X_FUNCTION */ char_u *base; { - list_T *matchlist; + list_T *matchlist = NULL; + dict_T *matchdict = NULL; char_u *args[2]; char_u *funcname; pos_T pos; + win_T *curwin_save; + buf_T *curbuf_save; + typval_T rettv; funcname = (type == CTRL_X_FUNCTION) ? curbuf->b_p_cfu : curbuf->b_p_ofu; if (*funcname == NUL) @@ -3843,13 +3955,50 @@ args[1] = base; pos = curwin->w_cursor; - matchlist = call_func_retlist(funcname, 2, args, FALSE); + curwin_save = curwin; + curbuf_save = curbuf; + + /* Call a function, which returns a list or dict. */ + if (call_vim_function(funcname, 2, args, FALSE, &rettv) == OK) + { + switch (rettv.v_type) + { + case VAR_LIST: + matchlist = rettv.vval.v_list; + break; + case VAR_DICT: + matchdict = rettv.vval.v_dict; + break; + default: + /* TODO: Give error message? */ + clear_tv(&rettv); + break; + } + } + + if (curwin_save != curwin || curbuf_save != curbuf) + { + EMSG(_(e_complwin)); + goto theend; + } curwin->w_cursor = pos; /* restore the cursor position */ - if (matchlist == NULL) - return; + check_cursor(); + if (!equalpos(curwin->w_cursor, pos)) + { + EMSG(_(e_compldel)); + goto theend; + } + + if (matchlist != NULL) + ins_compl_add_list(matchlist); + else if (matchdict != NULL) + ins_compl_add_dict(matchdict); - ins_compl_add_list(matchlist); - list_unref(matchlist); +theend: + if (matchdict != NULL) + dict_unref(matchdict); + if (matchlist != NULL) + list_unref(matchlist); } #endif /* FEAT_COMPL_FUNC */ @@ -3876,6 +4025,33 @@ } /* + * Add completions from a dict. + */ + static void +ins_compl_add_dict(dict) + dict_T *dict; +{ + dictitem_T *di_refresh; + dictitem_T *di_words; + + /* Check for optional "refresh" item. */ + compl_opt_refresh_always = FALSE; + di_refresh = dict_find(dict, (char_u *)"refresh", 7); + if (di_refresh != NULL && di_refresh->di_tv.v_type == VAR_STRING) + { + char_u *v = di_refresh->di_tv.vval.v_string; + + if (v != NULL && STRCMP(v, (char_u *)"always") == 0) + compl_opt_refresh_always = TRUE; + } + + /* Add completions from a "words" list. */ + di_words = dict_find(dict, (char_u *)"words", 5); + if (di_words != NULL && di_words->di_tv.v_type == VAR_LIST) + ins_compl_add_list(di_words->di_tv.vval.v_list); +} + +/* * Add a match to the list of matches from a typeval_T. * If the given string is already in the list of completions, then return * NOTDONE, otherwise add it to the list and return OK. If there is an error, @@ -3889,6 +4065,7 @@ char_u *word; int icase = FALSE; int adup = FALSE; + int aempty = FALSE; char_u *(cptext[CPT_COUNT]); if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL) @@ -3906,13 +4083,15 @@ icase = get_dict_number(tv->vval.v_dict, (char_u *)"icase"); if (get_dict_string(tv->vval.v_dict, (char_u *)"dup", FALSE) != NULL) adup = get_dict_number(tv->vval.v_dict, (char_u *)"dup"); + if (get_dict_string(tv->vval.v_dict, (char_u *)"empty", FALSE) != NULL) + aempty = get_dict_number(tv->vval.v_dict, (char_u *)"empty"); } else { word = get_tv_string_chk(tv); vim_memset(cptext, 0, sizeof(cptext)); } - if (word == NULL || *word == NUL) + if (word == NULL || (!aempty && *word == NUL)) return FAIL; return ins_compl_add(word, -1, icase, NULL, cptext, dir, 0, adup); } @@ -4403,6 +4582,11 @@ int found_end = FALSE; int advance; + /* When user complete function return -1 for findstart which is next + * time of 'always', compl_shown_match become NULL. */ + if (compl_shown_match == NULL) + return -1; + if (compl_leader != NULL && (compl_shown_match->cp_flags & ORIGINAL_TEXT) == 0) { @@ -4994,6 +5178,8 @@ int col; char_u *funcname; pos_T pos; + win_T *curwin_save; + buf_T *curbuf_save; /* Call 'completefunc' or 'omnifunc' and get pattern length as a * string */ @@ -5009,8 +5195,40 @@ args[0] = (char_u *)"1"; args[1] = NULL; pos = curwin->w_cursor; + curwin_save = curwin; + curbuf_save = curbuf; col = call_func_retnr(funcname, 2, args, FALSE); + if (curwin_save != curwin || curbuf_save != curbuf) + { + EMSG(_(e_complwin)); + return FAIL; + } curwin->w_cursor = pos; /* restore the cursor position */ + check_cursor(); + if (!equalpos(curwin->w_cursor, pos)) + { + EMSG(_(e_compldel)); + return FAIL; + } + + /* Return value -2 means the user complete function wants to + * cancel the complete without an error. + * Return value -3 does the same as -2 and leaves CTRL-X mode.*/ + if (col == -2) + return FAIL; + if (col == -3) + { + ctrl_x_mode = 0; + edit_submode = NULL; + msg_clr_cmdline(); + return FAIL; + } + + /* + * Reset extended parameters of completion, when start new + * completion. + */ + compl_opt_refresh_always = FALSE; if (col < 0) col = curs_col; @@ -5089,6 +5307,10 @@ else edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode)); + /* If any of the original typed text has been changed we need to fix + * the redo buffer. */ + ins_compl_fixRedoBufForLeader(NULL); + /* Always add completion for the original text. */ vim_free(compl_orig_text); compl_orig_text = vim_strnsave(line + compl_col, compl_length); @@ -5249,7 +5471,7 @@ compl_curr_match->cp_number); edit_submode_extra = match_ref; edit_submode_highl = HLF_R; - if (dollar_vcol) + if (dollar_vcol >= 0) curs_columns(FALSE); } } @@ -5558,6 +5780,16 @@ # define WHITECHAR(cc) vim_iswhite(cc) #endif +/* + * "flags": INSCHAR_FORMAT - force formatting + * INSCHAR_CTRLV - char typed just after CTRL-V + * INSCHAR_NO_FEX - don't use 'formatexpr' + * + * NOTE: passes the flags value straight through to internal_format() which, + * beside INSCHAR_FORMAT (above), is also looking for these: + * INSCHAR_DO_COM - format comments + * INSCHAR_COM_LIST - format comments with num list or 2nd line indent + */ void insertchar(c, flags, second_indent) int c; /* character to insert or NUL */ @@ -5636,7 +5868,7 @@ * Need to remove existing (middle) comment leader and insert end * comment leader. First, check what comment leader we can find. */ - i = get_leader_len(line = ml_get_curline(), &p, FALSE); + i = get_leader_len(line = ml_get_curline(), &p, FALSE, TRUE); if (i > 0 && vim_strchr(p, COM_MIDDLE) != NULL) /* Just checking */ { /* Skip middle-comment string */ @@ -5691,6 +5923,8 @@ * Don't do this when 'cindent' or 'indentexpr' is set, because we might * need to re-indent at a ':', or any other character (but not what * 'paste' is set).. + * Don't do this when there an InsertCharPre autocommand is defined, + * because we need to fire the event for every character. */ #ifdef USE_ON_FLY_SCROLL dont_scroll = FALSE; /* allow scrolling here */ @@ -5708,6 +5942,9 @@ #ifdef FEAT_RIGHTLEFT && !p_ri #endif +#ifdef FEAT_AUTOCMD + && !has_insertcharpre() +#endif ) { #define INPUT_BUFLEN 100 @@ -5795,6 +6032,9 @@ /* * Format text at the current insert position. + * + * If the INSCHAR_COM_LIST flag is present, then the value of second_indent + * will be the comment leader length sent to open_line(). */ static void internal_format(textwidth, second_indent, flags, format_only, c) @@ -5869,7 +6109,7 @@ /* Don't break until after the comment leader */ if (do_comments) - leader_len = get_leader_len(ml_get_curline(), NULL, FALSE); + leader_len = get_leader_len(ml_get_curline(), NULL, FALSE, TRUE); else leader_len = 0; @@ -5902,6 +6142,7 @@ * Stop at first entered white when 'formatoptions' has 'v' */ while ((!fo_ins_blank && !has_format_option(FO_INS_VI)) + || (flags & INSCHAR_FORMAT) || curwin->w_cursor.lnum != Insstart.lnum || curwin->w_cursor.col >= Insstart.col) { @@ -6072,23 +6313,59 @@ + (fo_white_par ? OPENLINE_KEEPTRAIL : 0) #ifdef FEAT_COMMENTS + (do_comments ? OPENLINE_DO_COM : 0) + + ((flags & INSCHAR_COM_LIST) ? OPENLINE_COM_LIST : 0) #endif - , old_indent); - old_indent = 0; + , ((flags & INSCHAR_COM_LIST) ? second_indent : old_indent)); + if (!(flags & INSCHAR_COM_LIST)) + old_indent = 0; replace_offset = 0; if (first_line) { - if (second_indent < 0 && has_format_option(FO_Q_NUMBER)) - second_indent = get_number_indent(curwin->w_cursor.lnum -1); - if (second_indent >= 0) + if (!(flags & INSCHAR_COM_LIST)) { + /* + * This section is for auto-wrap of numeric lists. When not + * in insert mode (i.e. format_lines()), the INSCHAR_COM_LIST + * flag will be set and open_line() will handle it (as seen + * above). The code here (and in get_number_indent()) will + * recognize comments if needed... + */ + if (second_indent < 0 && has_format_option(FO_Q_NUMBER)) + second_indent = + get_number_indent(curwin->w_cursor.lnum - 1); + if (second_indent >= 0) + { #ifdef FEAT_VREPLACE - if (State & VREPLACE_FLAG) - change_indent(INDENT_SET, second_indent, FALSE, NUL, TRUE); - else + if (State & VREPLACE_FLAG) + change_indent(INDENT_SET, second_indent, + FALSE, NUL, TRUE); + else +#endif +#ifdef FEAT_COMMENTS + if (leader_len > 0 && second_indent - leader_len > 0) + { + int i; + int padding = second_indent - leader_len; + + /* We started at the first_line of a numbered list + * that has a comment. the open_line() function has + * inserted the proper comment leader and positioned + * the cursor at the end of the split line. Now we + * add the additional whitespace needed after the + * comment leader for the numbered list. */ + for (i = 0; i < padding; i++) + ins_str((char_u *)" "); + changed_bytes(curwin->w_cursor.lnum, leader_len); + } + else + { #endif - (void)set_indent(second_indent, SIN_CHANGED); + (void)set_indent(second_indent, SIN_CHANGED); +#ifdef FEAT_COMMENTS + } +#endif + } } first_line = FALSE; } @@ -6194,7 +6471,7 @@ /* With the 'c' flag in 'formatoptions' and 't' missing: only format * comments. */ if (has_format_option(FO_WRAP_COMS) && !has_format_option(FO_WRAP) - && get_leader_len(old, NULL, FALSE) == 0) + && get_leader_len(old, NULL, FALSE, TRUE) == 0) return; #endif @@ -6598,11 +6875,7 @@ char_u *s; vim_free(last_insert); -#ifdef FEAT_MBYTE last_insert = alloc(MB_MAXBYTES * 3 + 5); -#else - last_insert = alloc(6); -#endif if (last_insert != NULL) { s = last_insert; @@ -6640,7 +6913,7 @@ char_u *s; { #ifdef FEAT_MBYTE - char_u temp[MB_MAXBYTES]; + char_u temp[MB_MAXBYTES + 1]; int i; int len; @@ -7202,7 +7475,7 @@ int cc; { int n; - char_u buf[MB_MAXBYTES]; + char_u buf[MB_MAXBYTES + 1]; int i; int c; @@ -8352,7 +8625,7 @@ { temp = curwin->w_cursor.col; if (!can_bs(BS_EOL) /* only if "eol" included */ - || do_join(2, FALSE, TRUE) == FAIL) + || do_join(2, FALSE, TRUE, FALSE) == FAIL) vim_beep(); else curwin->w_cursor.col = temp; @@ -8533,7 +8806,7 @@ ptr[len - 1] = NUL; } - (void)do_join(2, FALSE, FALSE); + (void)do_join(2, FALSE, FALSE, FALSE); if (temp == NUL && gchar_cursor() != NUL) inc_cursor(); } @@ -8768,7 +9041,7 @@ * We can emulate the vi behaviour by pretending there is a dollar * displayed even when there isn't. * --pkv Sun Jan 19 01:56:40 EST 2003 */ - if (vim_strchr(p_cpo, CPO_BACKSPACE) != NULL && dollar_vcol == 0) + if (vim_strchr(p_cpo, CPO_BACKSPACE) != NULL && dollar_vcol == -1) dollar_vcol = curwin->w_virtcol; #ifdef FEAT_FOLDING @@ -9598,6 +9871,7 @@ { int c; int cc; + int did_putchar = FALSE; pc_status = PC_STATUS_UNSET; if (redrawing() && !char_avail()) @@ -9606,6 +9880,7 @@ ins_redraw(FALSE); edit_putchar('?', TRUE); + did_putchar = TRUE; #ifdef FEAT_CMDL_INFO add_to_showcmd_c(Ctrl_K); #endif @@ -9622,8 +9897,10 @@ c = plain_vgetc(); --no_mapping; --allow_keys; - edit_unputchar(); /* when line fits in 'columns' the '?' is at the start - of the next line and will not be redrawn */ + if (did_putchar) + /* when the line fits in 'columns' the '?' is at the start of the next + * line and will not be removed by the redraw */ + edit_unputchar(); if (IS_SPECIAL(c) || mod_mask) /* special key */ { @@ -9635,6 +9912,7 @@ } if (c != ESC) { + did_putchar = FALSE; if (redrawing() && !char_avail()) { /* may need to redraw when no more chars available now */ @@ -9642,11 +9920,9 @@ if (char2cells(c) == 1) { - /* first remove the '?', otherwise it's restored when typing - * an ESC next */ - edit_unputchar(); ins_redraw(FALSE); edit_putchar(c, TRUE); + did_putchar = TRUE; } #ifdef FEAT_CMDL_INFO add_to_showcmd_c(c); @@ -9657,8 +9933,10 @@ cc = plain_vgetc(); --no_mapping; --allow_keys; - edit_unputchar(); /* when line fits in 'columns' the '?' is at the - start of the next line and will not be redrawn */ + if (did_putchar) + /* when the line fits in 'columns' the '?' is at the start of the + * next line and will not be removed by a redraw */ + edit_unputchar(); if (cc != ESC) { AppendToRedobuff((char_u *)CTRL_V_STR); @@ -9680,7 +9958,7 @@ * Handle CTRL-E and CTRL-Y in Insert mode: copy char from other line. * Returns the char to be inserted, or NUL if none found. */ - static int + int ins_copychar(lnum) linenr_T lnum; { @@ -9870,3 +10148,52 @@ validate_virtcol(); return curwin->w_virtcol; } + +#ifdef FEAT_AUTOCMD +/* + * Handle the InsertCharPre autocommand. + * "c" is the character that was typed. + * Return a pointer to allocated memory with the replacement string. + * Return NULL to continue inserting "c". + */ + static char_u * +do_insert_char_pre(c) + int c; +{ + char_u *res; + char_u buf[MB_MAXBYTES + 1]; + + /* Return quickly when there is nothing to do. */ + if (!has_insertcharpre()) + return NULL; + +#ifdef FEAT_MBYTE + if (has_mbyte) + buf[(*mb_char2bytes)(c, buf)] = NUL; + else +#endif + { + buf[0] = c; + buf[1] = NUL; + } + + /* Lock the text to avoid weird things from happening. */ + ++textlock; + set_vim_var_string(VV_CHAR, buf, -1); /* set v:char */ + + res = NULL; + if (apply_autocmds(EVENT_INSERTCHARPRE, NULL, NULL, FALSE, curbuf)) + { + /* Get the value of v:char. It may be empty or more than one + * character. Only use it when changed, otherwise continue with the + * original character to avoid breaking autoindent. */ + if (STRCMP(buf, get_vim_var_str(VV_CHAR)) != 0) + res = vim_strsave(get_vim_var_str(VV_CHAR)); + } + + set_vim_var_string(VV_CHAR, NULL, -1); /* clear v:char */ + --textlock; + + return res; +} +#endif diff -Naur vim73.orig/src/eval.c vim73/src/eval.c --- vim73.orig/src/eval.c 2010-08-09 20:12:14.000000000 +0000 +++ vim73/src/eval.c 2012-07-20 20:31:18.337645181 +0000 @@ -10,9 +10,6 @@ /* * eval.c: Expression evaluation. */ -#if defined(MSDOS) || defined(WIN16) || defined(WIN32) || defined(_WIN64) -# include "vimio.h" /* for mch_open(), must be before vim.h */ -#endif #include "vim.h" @@ -355,13 +352,14 @@ {VV_NAME("swapname", VAR_STRING), VV_RO}, {VV_NAME("swapchoice", VAR_STRING), 0}, {VV_NAME("swapcommand", VAR_STRING), VV_RO}, - {VV_NAME("char", VAR_STRING), VV_RO}, + {VV_NAME("char", VAR_STRING), 0}, {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}, {VV_NAME("searchforward", VAR_NUMBER), 0}, {VV_NAME("oldfiles", VAR_LIST), 0}, + {VV_NAME("windowid", VAR_NUMBER), VV_RO}, }; /* shorthand */ @@ -382,9 +380,6 @@ static void prepare_vimvar __ARGS((int idx, typval_T *save_tv)); static void restore_vimvar __ARGS((int idx, typval_T *save_tv)); -#if defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL) -static int call_vim_function __ARGS((char_u *func, int argc, char_u **argv, int safe, typval_T *rettv)); -#endif 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)); @@ -429,31 +424,22 @@ static int get_lit_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate)); static int get_list_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate)); static int rettv_list_alloc __ARGS((typval_T *rettv)); -static listitem_T *listitem_alloc __ARGS((void)); static void listitem_free __ARGS((listitem_T *item)); -static void listitem_remove __ARGS((list_T *l, listitem_T *item)); static long list_len __ARGS((list_T *l)); -static int list_equal __ARGS((list_T *l1, list_T *l2, int ic)); -static int dict_equal __ARGS((dict_T *d1, dict_T *d2, int ic)); -static int tv_equal __ARGS((typval_T *tv1, typval_T *tv2, int ic)); -static listitem_T *list_find __ARGS((list_T *l, long n)); +static int list_equal __ARGS((list_T *l1, list_T *l2, int ic, int recursive)); +static int dict_equal __ARGS((dict_T *d1, dict_T *d2, int ic, int recursive)); +static int tv_equal __ARGS((typval_T *tv1, typval_T *tv2, int ic, int recursive)); static long list_find_nr __ARGS((list_T *l, long idx, int *errorp)); static long list_idx_of_item __ARGS((list_T *l, listitem_T *item)); -static void list_append __ARGS((list_T *l, listitem_T *item)); static int list_append_number __ARGS((list_T *l, varnumber_T n)); -static int list_insert_tv __ARGS((list_T *l, typval_T *tv, listitem_T *item)); static int list_extend __ARGS((list_T *l1, list_T *l2, listitem_T *bef)); static int list_concat __ARGS((list_T *l1, list_T *l2, typval_T *tv)); static list_T *list_copy __ARGS((list_T *orig, int deep, int copyID)); -static void list_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2)); static char_u *list2string __ARGS((typval_T *tv, int copyID)); +static int list_join_inner __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo_style, int copyID, garray_T *join_gap)); static int list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo, int copyID)); static int free_unref_items __ARGS((int copyID)); -static void set_ref_in_ht __ARGS((hashtab_T *ht, int copyID)); -static void set_ref_in_list __ARGS((list_T *l, int copyID)); -static void set_ref_in_item __ARGS((typval_T *tv, int copyID)); static int rettv_dict_alloc __ARGS((typval_T *rettv)); -static void dict_unref __ARGS((dict_T *d)); static void dict_free __ARGS((dict_T *d, int recurse)); static dictitem_T *dictitem_copy __ARGS((dictitem_T *org)); static void dictitem_remove __ARGS((dict_T *dict, dictitem_T *item)); @@ -480,6 +466,7 @@ static void f_acos __ARGS((typval_T *argvars, typval_T *rettv)); #endif static void f_add __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_and __ARGS((typval_T *argvars, typval_T *rettv)); static void f_append __ARGS((typval_T *argvars, typval_T *rettv)); static void f_argc __ARGS((typval_T *argvars, typval_T *rettv)); static void f_argidx __ARGS((typval_T *argvars, typval_T *rettv)); @@ -608,6 +595,7 @@ static void f_inputsave __ARGS((typval_T *argvars, typval_T *rettv)); static void f_inputsecret __ARGS((typval_T *argvars, typval_T *rettv)); static void f_insert __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_invert __ARGS((typval_T *argvars, typval_T *rettv)); static void f_isdirectory __ARGS((typval_T *argvars, typval_T *rettv)); static void f_islocked __ARGS((typval_T *argvars, typval_T *rettv)); static void f_items __ARGS((typval_T *argvars, typval_T *rettv)); @@ -625,6 +613,9 @@ static void f_log __ARGS((typval_T *argvars, typval_T *rettv)); static void f_log10 __ARGS((typval_T *argvars, typval_T *rettv)); #endif +#ifdef FEAT_LUA +static void f_luaeval __ARGS((typval_T *argvars, typval_T *rettv)); +#endif static void f_map __ARGS((typval_T *argvars, typval_T *rettv)); static void f_maparg __ARGS((typval_T *argvars, typval_T *rettv)); static void f_mapcheck __ARGS((typval_T *argvars, typval_T *rettv)); @@ -646,6 +637,7 @@ #endif static void f_nextnonblank __ARGS((typval_T *argvars, typval_T *rettv)); static void f_nr2char __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_or __ARGS((typval_T *argvars, typval_T *rettv)); static void f_pathshorten __ARGS((typval_T *argvars, typval_T *rettv)); #ifdef FEAT_FLOAT static void f_pow __ARGS((typval_T *argvars, typval_T *rettv)); @@ -653,6 +645,12 @@ static void f_prevnonblank __ARGS((typval_T *argvars, typval_T *rettv)); static void f_printf __ARGS((typval_T *argvars, typval_T *rettv)); static void f_pumvisible __ARGS((typval_T *argvars, typval_T *rettv)); +#ifdef FEAT_PYTHON3 +static void f_py3eval __ARGS((typval_T *argvars, typval_T *rettv)); +#endif +#ifdef FEAT_PYTHON +static void f_pyeval __ARGS((typval_T *argvars, typval_T *rettv)); +#endif static void f_range __ARGS((typval_T *argvars, typval_T *rettv)); static void f_readfile __ARGS((typval_T *argvars, typval_T *rettv)); static void f_reltime __ARGS((typval_T *argvars, typval_T *rettv)); @@ -757,6 +755,7 @@ static void f_winsaveview __ARGS((typval_T *argvars, typval_T *rettv)); static void f_winwidth __ARGS((typval_T *argvars, typval_T *rettv)); static void f_writefile __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_xor __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 dollar_lnum, int *fnum)); @@ -791,6 +790,8 @@ 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)); +static int var_check_func_name __ARGS((char_u *name, int new_var)); +static int valid_varname __ARGS((char_u *varname)); static int tv_check_lock __ARGS((int lock, char_u *name)); static int item_copy __ARGS((typval_T *from, typval_T *to, int deep, int copyID)); static char_u *find_option_end __ARGS((char_u **arg, int *opt_flags)); @@ -820,8 +821,6 @@ static char_u *autoload_name __ARGS((char_u *name)); static void cat_func_name __ARGS((char_u *buf, ufunc_T *fp)); static void func_free __ARGS((ufunc_T *fp)); -static void func_unref __ARGS((char_u *name)); -static void func_ref __ARGS((char_u *name)); static void call_user_func __ARGS((ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, linenr_T firstline, linenr_T lastline, dict_T *selfdict)); static int can_free_funccal __ARGS((funccall_T *fc, int copyID)) ; static void free_funccal __ARGS((funccall_T *fc, int free_val)); @@ -851,8 +850,9 @@ int i; struct vimvar *p; - init_var_dict(&globvardict, &globvars_var); - init_var_dict(&vimvardict, &vimvars_var); + init_var_dict(&globvardict, &globvars_var, VAR_DEF_SCOPE); + init_var_dict(&vimvardict, &vimvars_var, VAR_SCOPE); + vimvardict.dv_lock = VAR_FIXED; hash_init(&compat_hashtab); hash_init(&func_hashtab); @@ -875,10 +875,11 @@ hash_add(&compat_hashtab, p->vv_di.di_key); } set_vim_var_nr(VV_SEARCHFORWARD, 1L); + set_reg_var(0); /* default for v:register is not 0 but '"' */ #ifdef EBCDIC /* - * Sort the function table, to enable binary sort. + * Sort the function table, to enable binary search. */ sortFunctions(); #endif @@ -910,6 +911,7 @@ hash_clear(&compat_hashtab); free_scriptnames(); + free_locales(); /* global variables */ vars_clear(&globvarht); @@ -1355,7 +1357,11 @@ { ga_init2(&ga, (int)sizeof(char), 80); if (tv.vval.v_list != NULL) + { list_join(&ga, tv.vval.v_list, (char_u *)"\n", TRUE, 0); + if (tv.vval.v_list->lv_len > 0) + ga_append(&ga, NL); + } ga_append(&ga, NUL); retval = (char_u *)ga.ga_data; } @@ -1557,7 +1563,7 @@ * arguments are currently supported. * Returns OK or FAIL. */ - static int + int call_vim_function(func, argc, argv, safe, rettv) char_u *func; int argc; @@ -2325,7 +2331,7 @@ else if (endchars != NULL && vim_strchr(endchars, *skipwhite(arg)) == NULL) EMSG(_(e_letunexp)); - else + else if (!check_secure()) { c1 = name[len]; name[len] = NUL; @@ -2718,8 +2724,39 @@ lp->ll_list = NULL; lp->ll_dict = lp->ll_tv->vval.v_dict; lp->ll_di = dict_find(lp->ll_dict, key, len); + + /* When assigning to a scope dictionary check that a function and + * variable name is valid (only variable name unless it is l: or + * g: dictionary). Disallow overwriting a builtin function. */ + if (rettv != NULL && lp->ll_dict->dv_scope != 0) + { + int prevval; + int wrong; + + if (len != -1) + { + prevval = key[len]; + key[len] = NUL; + } + wrong = (lp->ll_dict->dv_scope == VAR_DEF_SCOPE + && rettv->v_type == VAR_FUNC + && var_check_func_name(key, lp->ll_di == NULL)) + || !valid_varname(key); + if (len != -1) + key[len] = prevval; + if (wrong) + return NULL; + } + if (lp->ll_di == NULL) { + /* Can't add "v:" variable. */ + if (lp->ll_dict == &vimvardict) + { + EMSG2(_(e_illvar), name); + return NULL; + } + /* Key does not exist in dict: may need to add it. */ if (*p == '[' || *p == '.' || unlet) { @@ -2739,6 +2776,10 @@ p = NULL; break; } + /* existing variable, need to check if it can be changed */ + else if (var_check_ro(lp->ll_di->di_flags, name)) + return NULL; + if (len == -1) clear_tv(&var1); lp->ll_tv = &lp->ll_di->di_tv; @@ -2770,6 +2811,8 @@ { if (lp->ll_range && !lp->ll_empty2) clear_tv(&var2); + if (!quiet) + EMSGN(_(e_listidx), lp->ll_n1); return NULL; } @@ -2787,7 +2830,11 @@ { ni = list_find(lp->ll_list, lp->ll_n2); if (ni == NULL) + { + if (!quiet) + EMSGN(_(e_listidx), lp->ll_n2); return NULL; + } lp->ll_n2 = list_idx_of_item(lp->ll_list, ni); } @@ -2795,7 +2842,11 @@ if (lp->ll_n1 < 0) lp->ll_n1 = list_idx_of_item(lp->ll_list, lp->ll_li); if (lp->ll_n2 < lp->ll_n1) + { + if (!quiet) + EMSGN(_(e_listidx), lp->ll_n2); return NULL; + } } lp->ll_tv = &lp->ll_li->li_tv; @@ -3337,6 +3388,18 @@ int failed = FALSE; funcdict_T fudi; + if (eap->skip) + { + /* trans_function_name() doesn't work well when skipping, use eval0() + * instead to skip to any following command, e.g. for: + * :if 0 | call dict.foo().bar() | endif */ + ++emsg_skip; + if (eval0(eap->arg, &rettv, &eap->nextcmd, FALSE) != FAIL) + clear_tv(&rettv); + --emsg_skip; + return; + } + tofree = trans_function_name(&arg, eap->skip, TFN_INT, &fudi); if (fudi.fd_newkey != NULL) { @@ -3386,6 +3449,9 @@ { curwin->w_cursor.lnum = lnum; curwin->w_cursor.col = 0; +#ifdef FEAT_VIRTUALEDIT + curwin->w_cursor.coladd = 0; +#endif } arg = startarg; if (get_func_tv(name, (int)STRLEN(name), &rettv, &arg, @@ -4349,7 +4415,8 @@ else { /* Compare two Lists for being equal or unequal. */ - n1 = list_equal(rettv->vval.v_list, var2.vval.v_list, ic); + n1 = list_equal(rettv->vval.v_list, var2.vval.v_list, + ic, FALSE); if (type == TYPE_NEQUAL) n1 = !n1; } @@ -4378,7 +4445,8 @@ else { /* Compare two Dictionaries for being equal or unequal. */ - n1 = dict_equal(rettv->vval.v_dict, var2.vval.v_dict, ic); + n1 = dict_equal(rettv->vval.v_dict, var2.vval.v_dict, + ic, FALSE); if (type == TYPE_NEQUAL) n1 = !n1; } @@ -5097,9 +5165,7 @@ else ret = OK; } - - if (alias != NULL) - vim_free(alias); + vim_free(alias); } *arg = skipwhite(*arg); @@ -5868,7 +5934,7 @@ /* * Allocate a list item. */ - static listitem_T * + listitem_T * listitem_alloc() { return (listitem_T *)alloc(sizeof(listitem_T)); @@ -5888,7 +5954,7 @@ /* * Remove a list item from a List and free it. Also clears the value. */ - static void + void listitem_remove(l, item) list_T *l; listitem_T *item; @@ -5913,10 +5979,11 @@ * Return TRUE when two lists have exactly the same values. */ static int -list_equal(l1, l2, ic) +list_equal(l1, l2, ic, recursive) list_T *l1; list_T *l2; int ic; /* ignore case for strings */ + int recursive; /* TRUE when used recursively */ { listitem_T *item1, *item2; @@ -5930,7 +5997,7 @@ for (item1 = l1->lv_first, item2 = l2->lv_first; item1 != NULL && item2 != NULL; item1 = item1->li_next, item2 = item2->li_next) - if (!tv_equal(&item1->li_tv, &item2->li_tv, ic)) + if (!tv_equal(&item1->li_tv, &item2->li_tv, ic, recursive)) return FALSE; return item1 == NULL && item2 == NULL; } @@ -5952,10 +6019,11 @@ * Return TRUE when two dictionaries have exactly the same key/values. */ static int -dict_equal(d1, d2, ic) +dict_equal(d1, d2, ic, recursive) dict_T *d1; dict_T *d2; int ic; /* ignore case for strings */ + int recursive; /* TRUE when used recursively */ { hashitem_T *hi; dictitem_T *item2; @@ -5976,7 +6044,7 @@ item2 = dict_find(d2, hi->hi_key, -1); if (item2 == NULL) return FALSE; - if (!tv_equal(&HI2DI(hi)->di_tv, &item2->di_tv, ic)) + if (!tv_equal(&HI2DI(hi)->di_tv, &item2->di_tv, ic, recursive)) return FALSE; --todo; } @@ -5984,41 +6052,54 @@ return TRUE; } +static int tv_equal_recurse_limit; + /* * Return TRUE if "tv1" and "tv2" have the same value. * Compares the items just like "==" would compare them, but strings and * numbers are different. Floats and numbers are also different. */ static int -tv_equal(tv1, tv2, ic) +tv_equal(tv1, tv2, ic, recursive) typval_T *tv1; typval_T *tv2; - int ic; /* ignore case */ + int ic; /* ignore case */ + int recursive; /* TRUE when used recursively */ { char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN]; char_u *s1, *s2; - static int recursive = 0; /* cach recursive loops */ + static int recursive_cnt = 0; /* catch recursive loops */ int r; if (tv1->v_type != tv2->v_type) return FALSE; + /* Catch lists and dicts that have an endless loop by limiting - * recursiveness to 1000. We guess they are equal then. */ - if (recursive >= 1000) + * recursiveness to a limit. We guess they are equal then. + * A fixed limit has the problem of still taking an awful long time. + * Reduce the limit every time running into it. That should work fine for + * deeply linked structures that are not recursively linked and catch + * recursiveness quickly. */ + if (!recursive) + tv_equal_recurse_limit = 1000; + if (recursive_cnt >= tv_equal_recurse_limit) + { + --tv_equal_recurse_limit; return TRUE; + } switch (tv1->v_type) { case VAR_LIST: - ++recursive; - r = list_equal(tv1->vval.v_list, tv2->vval.v_list, ic); - --recursive; + ++recursive_cnt; + r = list_equal(tv1->vval.v_list, tv2->vval.v_list, ic, TRUE); + --recursive_cnt; return r; case VAR_DICT: - ++recursive; - r = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic); - --recursive; + ++recursive_cnt; + r = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic, TRUE); + --recursive_cnt; return r; case VAR_FUNC: @@ -6049,7 +6130,7 @@ * A negative index is counted from the end; -1 is the last item. * Returns NULL when "n" is out of range. */ - static listitem_T * + listitem_T * list_find(l, n) list_T *l; long n; @@ -6191,7 +6272,7 @@ /* * Append item "item" to the end of list "l". */ - static void + void list_append(l, item) list_T *l; listitem_T *item; @@ -6304,7 +6385,7 @@ * If "item" is NULL append at the end. * Return FAIL when out of memory. */ - static int + int list_insert_tv(l, tv, item) list_T *l; typval_T *tv; @@ -6449,7 +6530,7 @@ * Remove items "item" to "item2" from list "l". * Does not free the listitem or the value! */ - static void + void list_remove(l, item, item2) list_T *l; listitem_T *item; @@ -6502,47 +6583,119 @@ return (char_u *)ga.ga_data; } -/* - * Join list "l" into a string in "*gap", using separator "sep". - * When "echo" is TRUE use String as echoed, otherwise as inside a List. - * Return FAIL or OK. - */ +typedef struct join_S { + char_u *s; + char_u *tofree; +} join_T; + static int -list_join(gap, l, sep, echo, copyID) - garray_T *gap; +list_join_inner(gap, l, sep, echo_style, copyID, join_gap) + garray_T *gap; /* to store the result in */ list_T *l; char_u *sep; - int echo; + int echo_style; int copyID; + garray_T *join_gap; /* to keep each list item string */ { + int i; + join_T *p; + int len; + int sumlen = 0; int first = TRUE; char_u *tofree; char_u numbuf[NUMBUFLEN]; listitem_T *item; char_u *s; + /* Stringify each item in the list. */ for (item = l->lv_first; item != NULL && !got_int; item = item->li_next) { - if (first) - first = FALSE; - else - ga_concat(gap, sep); - - if (echo) + if (echo_style) s = echo_string(&item->li_tv, &tofree, numbuf, copyID); else s = tv2string(&item->li_tv, &tofree, numbuf, copyID); - if (s != NULL) - ga_concat(gap, s); - vim_free(tofree); if (s == NULL) return FAIL; + + len = (int)STRLEN(s); + sumlen += len; + + ga_grow(join_gap, 1); + p = ((join_T *)join_gap->ga_data) + (join_gap->ga_len++); + if (tofree != NULL || s != numbuf) + { + p->s = s; + p->tofree = tofree; + } + else + { + p->s = vim_strnsave(s, len); + p->tofree = p->s; + } + line_breakcheck(); } + + /* Allocate result buffer with its total size, avoid re-allocation and + * multiple copy operations. Add 2 for a tailing ']' and NUL. */ + if (join_gap->ga_len >= 2) + sumlen += (int)STRLEN(sep) * (join_gap->ga_len - 1); + if (ga_grow(gap, sumlen + 2) == FAIL) + return FAIL; + + for (i = 0; i < join_gap->ga_len && !got_int; ++i) + { + if (first) + first = FALSE; + else + ga_concat(gap, sep); + p = ((join_T *)join_gap->ga_data) + i; + + if (p->s != NULL) + ga_concat(gap, p->s); + line_breakcheck(); + } + return OK; } /* + * Join list "l" into a string in "*gap", using separator "sep". + * When "echo_style" is TRUE use String as echoed, otherwise as inside a List. + * Return FAIL or OK. + */ + static int +list_join(gap, l, sep, echo_style, copyID) + garray_T *gap; + list_T *l; + char_u *sep; + int echo_style; + int copyID; +{ + garray_T join_ga; + int retval; + join_T *p; + int i; + + ga_init2(&join_ga, (int)sizeof(join_T), l->lv_len); + retval = list_join_inner(gap, l, sep, echo_style, copyID, &join_ga); + + /* Dispose each item in join_ga. */ + if (join_ga.ga_data != NULL) + { + p = (join_T *)join_ga.ga_data; + for (i = 0; i < join_ga.ga_len; ++i) + { + vim_free(p->tofree); + ++p; + } + ga_clear(&join_ga); + } + + return retval; +} + +/* * Garbage collection for lists and dictionaries. * * We use reference counts to be able to free most items right away when they @@ -6635,6 +6788,18 @@ /* v: vars */ set_ref_in_ht(&vimvarht, copyID); +#ifdef FEAT_LUA + set_ref_in_lua(copyID); +#endif + +#ifdef FEAT_PYTHON + set_ref_in_python(copyID); +#endif + +#ifdef FEAT_PYTHON3 + set_ref_in_python3(copyID); +#endif + /* * 2. Free lists and dictionaries that are not referenced. */ @@ -6720,7 +6885,7 @@ /* * Mark all lists and dicts referenced through hashtab "ht" with "copyID". */ - static void + void set_ref_in_ht(ht, copyID) hashtab_T *ht; int copyID; @@ -6740,7 +6905,7 @@ /* * Mark all lists and dicts referenced through list "l" with "copyID". */ - static void + void set_ref_in_list(l, copyID) list_T *l; int copyID; @@ -6754,7 +6919,7 @@ /* * Mark all lists and dicts referenced through typval "tv" with "copyID". */ - static void + void set_ref_in_item(tv, copyID) typval_T *tv; int copyID; @@ -6798,7 +6963,7 @@ d = (dict_T *)alloc(sizeof(dict_T)); if (d != NULL) { - /* Add the list to the list of dicts for garbage collection. */ + /* Add the dict to the list of dicts for garbage collection. */ if (first_dict != NULL) first_dict->dv_used_prev = d; d->dv_used_next = first_dict; @@ -6807,6 +6972,7 @@ hash_init(&d->dv_hashtab); d->dv_lock = 0; + d->dv_scope = 0; d->dv_refcount = 0; d->dv_copyID = 0; } @@ -6837,7 +7003,7 @@ * Unreference a Dictionary: decrement the reference count and free it when it * becomes zero. */ - static void + void dict_unref(d) dict_T *d; { @@ -7075,7 +7241,7 @@ } /* - * Add a list entry to dictionary "d". + * Add a list entry to dictionary "d". * Returns FAIL when out of memory and when key already exists. */ int @@ -7097,6 +7263,7 @@ dictitem_free(item); return FAIL; } + ++list->lv_refcount; return OK; } @@ -7649,6 +7816,7 @@ {"acos", 1, 1, f_acos}, /* WJMc */ #endif {"add", 2, 2, f_add}, + {"and", 2, 2, f_and}, {"append", 2, 2, f_append}, {"argc", 0, 0, f_argc}, {"argidx", 0, 0, f_argidx}, @@ -7708,7 +7876,7 @@ #ifdef FEAT_FLOAT {"exp", 1, 1, f_exp}, #endif - {"expand", 1, 2, f_expand}, + {"expand", 1, 3, f_expand}, {"extend", 2, 3, f_extend}, {"feedkeys", 1, 2, f_feedkeys}, {"file_readable", 1, 1, f_filereadable}, /* obsolete */ @@ -7759,7 +7927,7 @@ {"getwinposx", 0, 0, f_getwinposx}, {"getwinposy", 0, 0, f_getwinposy}, {"getwinvar", 2, 2, f_getwinvar}, - {"glob", 1, 2, f_glob}, + {"glob", 1, 3, f_glob}, {"globpath", 2, 3, f_globpath}, {"has", 1, 1, f_has}, {"has_key", 2, 2, f_has_key}, @@ -7784,6 +7952,7 @@ {"inputsave", 0, 0, f_inputsave}, {"inputsecret", 1, 2, f_inputsecret}, {"insert", 2, 3, f_insert}, + {"invert", 1, 1, f_invert}, {"isdirectory", 1, 1, f_isdirectory}, {"islocked", 1, 1, f_islocked}, {"items", 1, 1, f_items}, @@ -7801,8 +7970,11 @@ {"log", 1, 1, f_log}, {"log10", 1, 1, f_log10}, #endif +#ifdef FEAT_LUA + {"luaeval", 1, 2, f_luaeval}, +#endif {"map", 2, 2, f_map}, - {"maparg", 1, 3, f_maparg}, + {"maparg", 1, 4, f_maparg}, {"mapcheck", 1, 3, f_mapcheck}, {"match", 2, 4, f_match}, {"matchadd", 2, 4, f_matchadd}, @@ -7822,6 +7994,7 @@ #endif {"nextnonblank", 1, 1, f_nextnonblank}, {"nr2char", 1, 1, f_nr2char}, + {"or", 2, 2, f_or}, {"pathshorten", 1, 1, f_pathshorten}, #ifdef FEAT_FLOAT {"pow", 2, 2, f_pow}, @@ -7829,6 +8002,12 @@ {"prevnonblank", 1, 1, f_prevnonblank}, {"printf", 2, 19, f_printf}, {"pumvisible", 0, 0, f_pumvisible}, +#ifdef FEAT_PYTHON3 + {"py3eval", 1, 1, f_py3eval}, +#endif +#ifdef FEAT_PYTHON + {"pyeval", 1, 1, f_pyeval}, +#endif {"range", 1, 3, f_range}, {"readfile", 1, 3, f_readfile}, {"reltime", 0, 2, f_reltime}, @@ -7870,7 +8049,7 @@ {"sin", 1, 1, f_sin}, {"sinh", 1, 1, f_sinh}, #endif - {"sort", 1, 2, f_sort}, + {"sort", 1, 3, f_sort}, {"soundfold", 1, 1, f_soundfold}, {"spellbadword", 0, 1, f_spellbadword}, {"spellsuggest", 1, 3, f_spellsuggest}, @@ -7933,6 +8112,7 @@ {"winsaveview", 0, 0, f_winsaveview}, {"winwidth", 1, 1, f_winwidth}, {"writefile", 2, 3, f_writefile}, + {"xor", 2, 2, f_xor}, }; #if defined(FEAT_CMDL_COMPL) || defined(PROTO) @@ -8497,7 +8677,7 @@ if (argvars[0].v_type == VAR_LIST) { if ((l = argvars[0].vval.v_list) != NULL - && !tv_check_lock(l->lv_lock, (char_u *)"add()") + && !tv_check_lock(l->lv_lock, (char_u *)_("add() argument")) && list_append_tv(l, &argvars[1]) == OK) copy_tv(&argvars[0], rettv); } @@ -8506,6 +8686,18 @@ } /* + * "and(expr, expr)" function + */ + static void +f_and(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ + rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL) + & get_tv_number_chk(&argvars[1], NULL); +} + +/* * "append(lnum, string/list)" function */ static void @@ -8980,6 +9172,45 @@ #endif } + int +func_call(name, args, selfdict, rettv) + char_u *name; + typval_T *args; + dict_T *selfdict; + typval_T *rettv; +{ + listitem_T *item; + typval_T argv[MAX_FUNC_ARGS + 1]; + int argc = 0; + int dummy; + int r = 0; + + for (item = args->vval.v_list->lv_first; item != NULL; + item = item->li_next) + { + if (argc == MAX_FUNC_ARGS) + { + EMSG(_("E699: Too many arguments")); + break; + } + /* Make a copy of each argument. This is needed to be able to set + * v_lock to VAR_FIXED in the copy without changing the original list. + */ + copy_tv(&item->li_tv, &argv[argc++]); + } + + if (item == NULL) + r = call_func(name, (int)STRLEN(name), rettv, argc, argv, + curwin->w_cursor.lnum, curwin->w_cursor.lnum, + &dummy, TRUE, selfdict); + + /* Free the arguments. */ + while (argc > 0) + clear_tv(&argv[--argc]); + + return r; +} + /* * "call(func, arglist)" function */ @@ -8989,10 +9220,6 @@ typval_T *rettv; { char_u *func; - typval_T argv[MAX_FUNC_ARGS + 1]; - int argc = 0; - listitem_T *item; - int dummy; dict_T *selfdict = NULL; if (argvars[1].v_type != VAR_LIST) @@ -9020,28 +9247,7 @@ selfdict = argvars[2].vval.v_dict; } - for (item = argvars[1].vval.v_list->lv_first; item != NULL; - item = item->li_next) - { - if (argc == MAX_FUNC_ARGS) - { - EMSG(_("E699: Too many arguments")); - break; - } - /* Make a copy of each argument. This is needed to be able to set - * v_lock to VAR_FIXED in the copy without changing the original list. - */ - copy_tv(&item->li_tv, &argv[argc++]); - } - - if (item == NULL) - (void)call_func(func, (int)STRLEN(func), rettv, argc, argv, - curwin->w_cursor.lnum, curwin->w_cursor.lnum, - &dummy, TRUE, selfdict); - - /* Free the arguments. */ - while (argc > 0) - clear_tv(&argv[--argc]); + (void)func_call(func, &argvars[1], selfdict, rettv); } #ifdef FEAT_FLOAT @@ -9298,7 +9504,7 @@ if (!error) rettv->vval.v_number = do_dialog(type, NULL, message, buttons, - def, NULL); + def, NULL, FALSE); #endif } @@ -9389,7 +9595,7 @@ } for ( ; li != NULL; li = li->li_next) - if (tv_equal(&li->li_tv, &argvars[1], ic)) + if (tv_equal(&li->li_tv, &argvars[1], ic, FALSE)) ++n; } } @@ -9416,7 +9622,7 @@ if (!HASHITEM_EMPTY(hi)) { --todo; - if (tv_equal(&HI2DI(hi)->di_tv, &argvars[1], ic)) + if (tv_equal(&HI2DI(hi)->di_tv, &argvars[1], ic, FALSE)) ++n; } } @@ -9857,17 +10063,36 @@ char_u *s; int len; char_u *errormsg; - int flags = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND; + int options = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND; expand_T xpc; int error = FALSE; + char_u *result; rettv->v_type = VAR_STRING; + if (argvars[1].v_type != VAR_UNKNOWN + && argvars[2].v_type != VAR_UNKNOWN + && get_tv_number_chk(&argvars[2], &error) + && !error) + { + rettv->v_type = VAR_LIST; + rettv->vval.v_list = NULL; + } + s = get_tv_string(&argvars[0]); if (*s == '%' || *s == '#' || *s == '<') { ++emsg_off; - rettv->vval.v_string = eval_vars(s, s, &len, NULL, &errormsg, NULL); + result = eval_vars(s, s, &len, NULL, &errormsg, NULL); --emsg_off; + if (rettv->v_type == VAR_LIST) + { + if (rettv_list_alloc(rettv) != FAIL && result != NULL) + list_append_string(rettv->vval.v_list, result, -1); + else + vim_free(result); + } + else + rettv->vval.v_string = result; } else { @@ -9875,12 +10100,25 @@ * for 'wildignore' and don't put matches for 'suffixes' at the end. */ if (argvars[1].v_type != VAR_UNKNOWN && get_tv_number_chk(&argvars[1], &error)) - flags |= WILD_KEEP_ALL; + options |= WILD_KEEP_ALL; if (!error) { ExpandInit(&xpc); xpc.xp_context = EXPAND_FILES; - rettv->vval.v_string = ExpandOne(&xpc, s, NULL, flags, WILD_ALL); + if (p_wic) + options += WILD_ICASE; + if (rettv->v_type == VAR_STRING) + rettv->vval.v_string = ExpandOne(&xpc, s, NULL, + options, WILD_ALL); + else if (rettv_list_alloc(rettv) != FAIL) + { + int i; + + ExpandOne(&xpc, s, NULL, options, WILD_ALL_KEEP); + for (i = 0; i < xpc.xp_numfiles; i++) + list_append_string(rettv->vval.v_list, xpc.xp_files[i], -1); + ExpandCleanup(&xpc); + } } else rettv->vval.v_string = NULL; @@ -9896,6 +10134,8 @@ typval_T *argvars; typval_T *rettv; { + char *arg_errmsg = N_("extend() argument"); + if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST) { list_T *l1, *l2; @@ -9905,7 +10145,7 @@ l1 = argvars[0].vval.v_list; l2 = argvars[1].vval.v_list; - if (l1 != NULL && !tv_check_lock(l1->lv_lock, (char_u *)"extend()") + if (l1 != NULL && !tv_check_lock(l1->lv_lock, (char_u *)_(arg_errmsg)) && l2 != NULL) { if (argvars[2].v_type != VAR_UNKNOWN) @@ -9944,7 +10184,7 @@ d1 = argvars[0].vval.v_dict; d2 = argvars[1].vval.v_dict; - if (d1 != NULL && !tv_check_lock(d1->dv_lock, (char_u *)"extend()") + if (d1 != NULL && !tv_check_lock(d1->dv_lock, (char_u *)_(arg_errmsg)) && d2 != NULL) { /* Check the third argument. */ @@ -9976,6 +10216,19 @@ { --todo; di1 = dict_find(d1, hi2->hi_key, -1); + if (d1->dv_scope != 0) + { + /* Disallow replacing a builtin function in l: and g:. + * Check the key to be valid when adding to any + * scope. */ + if (d1->dv_scope == VAR_DEF_SCOPE + && HI2DI(hi2)->di_tv.v_type == VAR_FUNC + && var_check_func_name(hi2->hi_key, + di1 == NULL)) + break; + if (!valid_varname(hi2->hi_key)) + break; + } if (di1 == NULL) { di1 = dictitem_copy(HI2DI(hi2)); @@ -9987,7 +10240,7 @@ EMSG2(_("E737: Key already exists: %s"), hi2->hi_key); break; } - else if (*action == 'f') + else if (*action == 'f' && HI2DI(hi2) != di1) { clear_tv(&di1->di_tv); copy_tv(&HI2DI(hi2)->di_tv, &di1->di_tv); @@ -10186,20 +10439,22 @@ typval_T save_key; int rem; int todo; - char_u *ermsg = map ? (char_u *)"map()" : (char_u *)"filter()"; + char_u *ermsg = (char_u *)(map ? "map()" : "filter()"); + char *arg_errmsg = (map ? N_("map() argument") + : N_("filter() argument")); int save_did_emsg; int idx = 0; if (argvars[0].v_type == VAR_LIST) { if ((l = argvars[0].vval.v_list) == NULL - || (map && tv_check_lock(l->lv_lock, ermsg))) + || tv_check_lock(l->lv_lock, (char_u *)_(arg_errmsg))) return; } else if (argvars[0].v_type == VAR_DICT) { if ((d = argvars[0].vval.v_dict) == NULL - || (map && tv_check_lock(d->dv_lock, ermsg))) + || tv_check_lock(d->dv_lock, (char_u *)_(arg_errmsg))) return; } else @@ -10236,7 +10491,8 @@ { --todo; di = HI2DI(hi); - if (tv_check_lock(di->di_tv.v_lock, ermsg)) + if (tv_check_lock(di->di_tv.v_lock, + (char_u *)_(arg_errmsg))) break; vimvars[VV_KEY].vv_str = vim_strsave(di->di_key); if (filter_map_one(&di->di_tv, expr, map, &rem) == FAIL @@ -10255,7 +10511,7 @@ for (li = l->lv_first; li != NULL; li = nli) { - if (tv_check_lock(li->li_tv.v_lock, ermsg)) + if (tv_check_lock(li->li_tv.v_lock, (char_u *)_(arg_errmsg))) break; nli = li->li_next; vimvars[VV_KEY].vv_nr = idx; @@ -10839,6 +11095,11 @@ if (*varname == '&') /* buffer-local-option */ get_option_tv(&varname, rettv, TRUE); + else if (STRCMP(varname, "changedtick") == 0) + { + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = curbuf->b_changedtick; + } else { if (*varname == NUL) @@ -11039,18 +11300,22 @@ typval_T *argvars UNUSED; typval_T *rettv; { - char_u cwd[MAXPATHL]; + char_u *cwd; rettv->v_type = VAR_STRING; - if (mch_dirname(cwd, MAXPATHL) == FAIL) - rettv->vval.v_string = NULL; - else + rettv->vval.v_string = NULL; + cwd = alloc(MAXPATHL); + if (cwd != NULL) { - rettv->vval.v_string = vim_strsave(cwd); + if (mch_dirname(cwd, MAXPATHL) != FAIL) + { + rettv->vval.v_string = vim_strsave(cwd); #ifdef BACKSLASH_IN_FILENAME - if (rettv->vval.v_string != NULL) - slash_adjust(rettv->vval.v_string); + if (rettv->vval.v_string != NULL) + slash_adjust(rettv->vval.v_string); #endif + } + vim_free(cwd); } } @@ -11653,22 +11918,44 @@ typval_T *argvars; typval_T *rettv; { - int flags = WILD_SILENT|WILD_USE_NL; + int options = WILD_SILENT|WILD_USE_NL; expand_T xpc; int error = FALSE; /* When the optional second argument is non-zero, don't remove matches - * for 'wildignore' and don't put matches for 'suffixes' at the end. */ - if (argvars[1].v_type != VAR_UNKNOWN - && get_tv_number_chk(&argvars[1], &error)) - flags |= WILD_KEEP_ALL; + * for 'wildignore' and don't put matches for 'suffixes' at the end. */ rettv->v_type = VAR_STRING; + if (argvars[1].v_type != VAR_UNKNOWN) + { + if (get_tv_number_chk(&argvars[1], &error)) + options |= WILD_KEEP_ALL; + if (argvars[2].v_type != VAR_UNKNOWN + && get_tv_number_chk(&argvars[2], &error)) + { + rettv->v_type = VAR_LIST; + rettv->vval.v_list = NULL; + } + } if (!error) { ExpandInit(&xpc); xpc.xp_context = EXPAND_FILES; - rettv->vval.v_string = ExpandOne(&xpc, get_tv_string(&argvars[0]), - NULL, flags, WILD_ALL); + if (p_wic) + options += WILD_ICASE; + if (rettv->v_type == VAR_STRING) + rettv->vval.v_string = ExpandOne(&xpc, get_tv_string(&argvars[0]), + NULL, options, WILD_ALL); + else if (rettv_list_alloc(rettv) != FAIL) + { + int i; + + ExpandOne(&xpc, get_tv_string(&argvars[0]), + NULL, options, WILD_ALL_KEEP); + for (i = 0; i < xpc.xp_numfiles; i++) + list_append_string(rettv->vval.v_list, xpc.xp_files[i], -1); + + ExpandCleanup(&xpc); + } } else rettv->vval.v_string = NULL; @@ -11741,9 +12028,6 @@ #ifdef __QNX__ "qnx", #endif -#ifdef RISCOS - "riscos", -#endif #ifdef UNIX "unix", #endif @@ -11786,6 +12070,11 @@ "all_builtin_terms", # endif #endif +#if defined(FEAT_BROWSE) && (defined(USE_FILE_CHOOSER) \ + || defined(FEAT_GUI_W32) \ + || defined(FEAT_GUI_MOTIF)) + "browsefilter", +#endif #ifdef FEAT_BYTEOFF "byte_offset", #endif @@ -11856,7 +12145,7 @@ #ifdef FEAT_SEARCHPATH "file_in_path", #endif -#if defined(UNIX) && !defined(USE_SYSTEM) +#ifdef FEAT_FILTERPIPE "filterpipe", #endif #ifdef FEAT_FIND_ID @@ -12002,9 +12291,6 @@ #ifdef FEAT_OLE "ole", #endif -#ifdef FEAT_OSFILETYPE - "osfiletype", -#endif #ifdef FEAT_PATH_EXTRA "path_extra", #endif @@ -12116,6 +12402,9 @@ #ifdef FEAT_TOOLBAR "toolbar", #endif +#if defined(FEAT_CLIPBOARD) && defined(FEAT_X11) + "unnamedplus", +#endif #ifdef FEAT_USR_CMDS "user-commands", /* was accidentally included in 5.4 */ "user_commands", @@ -12159,6 +12448,9 @@ #ifdef FEAT_XFONTSET "xfontset", #endif +#ifdef FEAT_XPM_W32 + "xpm_w32", +#endif #ifdef USE_XSMP "xsmp", #endif @@ -12572,7 +12864,7 @@ } for ( ; item != NULL; item = item->li_next, ++idx) - if (tv_equal(&item->li_tv, &argvars[1], ic)) + if (tv_equal(&item->li_tv, &argvars[1], ic, FALSE)) { rettv->vval.v_number = idx; break; @@ -12648,6 +12940,7 @@ int xp_namelen; long argt; + /* input() with a third argument: completion */ rettv->vval.v_string = NULL; xp_name = get_tv_string_buf_chk(&argvars[2], buf); @@ -12666,6 +12959,11 @@ rettv->vval.v_string = getcmdline_prompt(inputsecret_flag ? NUL : '@', p, echo_attr, xp_type, xp_arg); + if (rettv->vval.v_string == NULL + && argvars[1].v_type != VAR_UNKNOWN + && argvars[2].v_type != VAR_UNKNOWN) + rettv->vval.v_string = vim_strsave(get_tv_string_buf( + &argvars[2], buf)); vim_free(xp_arg); @@ -12712,7 +13010,7 @@ IObuff[0] = NUL; if (message != NULL && defstr != NULL && do_dialog(VIM_QUESTION, NULL, message, - (char_u *)_("&OK\n&Cancel"), 1, IObuff) == 1) + (char_u *)_("&OK\n&Cancel"), 1, IObuff, FALSE) == 1) rettv->vval.v_string = vim_strsave(IObuff); else { @@ -12850,7 +13148,7 @@ if (argvars[0].v_type != VAR_LIST) EMSG2(_(e_listarg), "insert()"); else if ((l = argvars[0].vval.v_list) != NULL - && !tv_check_lock(l->lv_lock, (char_u *)"insert()")) + && !tv_check_lock(l->lv_lock, (char_u *)_("insert() argument"))) { if (argvars[2].v_type != VAR_UNKNOWN) before = get_tv_number_chk(&argvars[2], &error); @@ -12877,6 +13175,17 @@ } /* + * "invert(expr)" function + */ + static void +f_invert(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ + rettv->vval.v_number = ~get_tv_number_chk(&argvars[0], NULL); +} + +/* * "isdirectory()" function */ static void @@ -13290,8 +13599,10 @@ char_u *keys_buf = NULL; char_u *rhs; int mode; - garray_T ga; int abbr = FALSE; + int get_dict = FALSE; + mapblock_T *mp; + int buffer_local; /* return empty string for failure */ rettv->v_type = VAR_STRING; @@ -13305,7 +13616,11 @@ { which = get_tv_string_buf_chk(&argvars[1], buf); if (argvars[2].v_type != VAR_UNKNOWN) + { abbr = get_tv_number(&argvars[2]); + if (argvars[3].v_type != VAR_UNKNOWN) + get_dict = get_tv_number(&argvars[3]); + } } else which = (char_u *)""; @@ -13315,19 +13630,34 @@ mode = get_map_mode(&which, 0); keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE, FALSE); - rhs = check_map(keys, mode, exact, FALSE, abbr); + rhs = check_map(keys, mode, exact, FALSE, abbr, &mp, &buffer_local); vim_free(keys_buf); - if (rhs != NULL) - { - ga_init(&ga); - ga.ga_itemsize = 1; - ga.ga_growsize = 40; - while (*rhs != NUL) - ga_concat(&ga, str2special(&rhs, FALSE)); + if (!get_dict) + { + /* Return a string. */ + if (rhs != NULL) + rettv->vval.v_string = str2special_save(rhs, FALSE); + + } + else if (rettv_dict_alloc(rettv) != FAIL && rhs != NULL) + { + /* Return a dictionary. */ + char_u *lhs = str2special_save(mp->m_keys, TRUE); + char_u *mapmode = map_mode_to_chars(mp->m_mode); + dict_T *dict = rettv->vval.v_dict; + + dict_add_nr_str(dict, "lhs", 0L, lhs); + dict_add_nr_str(dict, "rhs", 0L, mp->m_orig_str); + dict_add_nr_str(dict, "noremap", mp->m_noremap ? 1L : 0L , NULL); + dict_add_nr_str(dict, "expr", mp->m_expr ? 1L : 0L, NULL); + dict_add_nr_str(dict, "silent", mp->m_silent ? 1L : 0L, NULL); + dict_add_nr_str(dict, "sid", (long)mp->m_script_ID, NULL); + dict_add_nr_str(dict, "buffer", (long)buffer_local, NULL); + dict_add_nr_str(dict, "mode", 0L, mapmode); - ga_append(&ga, NUL); - rettv->vval.v_string = (char_u *)ga.ga_data; + vim_free(lhs); + vim_free(mapmode); } } @@ -13367,6 +13697,23 @@ } #endif +#ifdef FEAT_LUA +/* + * "luaeval()" function + */ + static void +f_luaeval(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ + char_u *str; + char_u buf[NUMBUFLEN]; + + str = get_tv_string_buf(&argvars[0], buf); + do_luaeval(str, argvars + 1, rettv); +} +#endif + /* * "map()" function */ @@ -14006,6 +14353,18 @@ } /* + * "or(expr, expr)" function + */ + static void +f_or(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ + rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL) + | get_tv_number_chk(&argvars[1], NULL); +} + +/* * "pathshorten()" function */ static void @@ -14125,6 +14484,40 @@ #endif } +#ifdef FEAT_PYTHON3 +/* + * "py3eval()" function + */ + static void +f_py3eval(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ + char_u *str; + char_u buf[NUMBUFLEN]; + + str = get_tv_string_buf(&argvars[0], buf); + do_py3eval(str, rettv); +} +#endif + +#ifdef FEAT_PYTHON +/* + * "pyeval()" function + */ + static void +f_pyeval(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ + char_u *str; + char_u buf[NUMBUFLEN]; + + str = get_tv_string_buf(&argvars[0], buf); + do_pyeval(str, rettv); +} +#endif + /* * "range()" function */ @@ -14177,22 +14570,19 @@ typval_T *rettv; { int binary = FALSE; + int failed = FALSE; char_u *fname; FILE *fd; - listitem_T *li; -#define FREAD_SIZE 200 /* optimized for text lines */ - char_u buf[FREAD_SIZE]; - int readlen; /* size of last fread() */ - int buflen; /* nr of valid chars in buf[] */ - int filtd; /* how much in buf[] was NUL -> '\n' filtered */ - int tolist; /* first byte in buf[] still to be put in list */ - int chop; /* how many CR to chop off */ - char_u *prev = NULL; /* previously read bytes, if any */ - int prevlen = 0; /* length of "prev" if not NULL */ - char_u *s; - int len; - long maxline = MAXLNUM; - long cnt = 0; + char_u buf[(IOSIZE/256)*256]; /* rounded to avoid odd + 1 */ + int io_size = sizeof(buf); + int readlen; /* size of last fread() */ + char_u *prev = NULL; /* previously read bytes, if any */ + long prevlen = 0; /* length of data in prev */ + long prevsize = 0; /* size of prev buffer */ + long maxline = MAXLNUM; + long cnt = 0; + char_u *p; /* position in buf */ + char_u *start; /* start of current line */ if (argvars[1].v_type != VAR_UNKNOWN) { @@ -14214,49 +14604,61 @@ return; } - filtd = 0; while (cnt < maxline || maxline < 0) { - readlen = (int)fread(buf + filtd, 1, FREAD_SIZE - filtd, fd); - buflen = filtd + readlen; - tolist = 0; - for ( ; filtd < buflen || readlen <= 0; ++filtd) - { - if (buf[filtd] == '\n' || readlen <= 0) - { - /* Only when in binary mode add an empty list item when the - * last line ends in a '\n'. */ - if (!binary && readlen == 0 && filtd == 0) - break; + readlen = (int)fread(buf, 1, io_size, fd); - /* Found end-of-line or end-of-file: add a text line to the - * list. */ - chop = 0; - if (!binary) - while (filtd - chop - 1 >= tolist - && buf[filtd - chop - 1] == '\r') - ++chop; - len = filtd - tolist - chop; - if (prev == NULL) - s = vim_strnsave(buf + tolist, len); + /* This for loop processes what was read, but is also entered at end + * of file so that either: + * - an incomplete line gets written + * - a "binary" file gets an empty line at the end if it ends in a + * newline. */ + for (p = buf, start = buf; + p < buf + readlen || (readlen <= 0 && (prevlen > 0 || binary)); + ++p) + { + if (*p == '\n' || readlen <= 0) + { + listitem_T *li; + char_u *s = NULL; + long_u len = p - start; + + /* Finished a line. Remove CRs before NL. */ + if (readlen > 0 && !binary) + { + while (len > 0 && start[len - 1] == '\r') + --len; + /* removal may cross back to the "prev" string */ + if (len == 0) + while (prevlen > 0 && prev[prevlen - 1] == '\r') + --prevlen; + } + if (prevlen == 0) + s = vim_strnsave(start, (int)len); else { - s = alloc((unsigned)(prevlen + len + 1)); - if (s != NULL) + /* Change "prev" buffer to be the right size. This way + * the bytes are only copied once, and very long lines are + * allocated only once. */ + if ((s = vim_realloc(prev, prevlen + len + 1)) != NULL) { - mch_memmove(s, prev, prevlen); - vim_free(prev); - prev = NULL; - mch_memmove(s + prevlen, buf + tolist, len); + mch_memmove(s + prevlen, start, len); s[prevlen + len] = NUL; + prev = NULL; /* the list will own the string */ + prevlen = prevsize = 0; } } - tolist = filtd + 1; + if (s == NULL) + { + do_outofmem_msg((long_u) prevlen + len + 1); + failed = TRUE; + break; + } - li = listitem_alloc(); - if (li == NULL) + if ((li = listitem_alloc()) == NULL) { vim_free(s); + failed = TRUE; break; } li->li_tv.v_type = VAR_STRING; @@ -14264,71 +14666,111 @@ li->li_tv.vval.v_string = s; list_append(rettv->vval.v_list, li); - if (++cnt >= maxline && maxline >= 0) - break; - if (readlen <= 0) + start = p + 1; /* step over newline */ + if ((++cnt >= maxline && maxline >= 0) || readlen <= 0) break; } - else if (buf[filtd] == NUL) - buf[filtd] = '\n'; + else if (*p == NUL) + *p = '\n'; #ifdef FEAT_MBYTE - else if (buf[filtd] == 0xef - && enc_utf8 - && filtd + 2 < buflen - && !binary - && buf[filtd + 1] == 0xbb - && buf[filtd + 2] == 0xbf) - { - /* remove utf-8 byte order mark */ - mch_memmove(buf + filtd, buf + filtd + 3, buflen - filtd - 3); - --filtd; - buflen -= 3; + /* Check for utf8 "bom"; U+FEFF is encoded as EF BB BF. Do this + * when finding the BF and check the previous two bytes. */ + else if (*p == 0xbf && enc_utf8 && !binary) + { + /* Find the two bytes before the 0xbf. If p is at buf, or buf + * + 1, these may be in the "prev" string. */ + char_u back1 = p >= buf + 1 ? p[-1] + : prevlen >= 1 ? prev[prevlen - 1] : NUL; + char_u back2 = p >= buf + 2 ? p[-2] + : p == buf + 1 && prevlen >= 1 ? prev[prevlen - 1] + : prevlen >= 2 ? prev[prevlen - 2] : NUL; + + if (back2 == 0xef && back1 == 0xbb) + { + char_u *dest = p - 2; + + /* Usually a BOM is at the beginning of a file, and so at + * the beginning of a line; then we can just step over it. + */ + if (start == dest) + start = p + 1; + else + { + /* have to shuffle buf to close gap */ + int adjust_prevlen = 0; + + if (dest < buf) + { + adjust_prevlen = (int)(buf - dest); /* must be 1 or 2 */ + dest = buf; + } + if (readlen > p - buf + 1) + mch_memmove(dest, p + 1, readlen - (p - buf) - 1); + readlen -= 3 - adjust_prevlen; + prevlen -= adjust_prevlen; + p = dest - 1; + } + } } #endif - } - if (readlen <= 0) - break; + } /* for */ - if (tolist == 0) + if (failed || (cnt >= maxline && maxline >= 0) || readlen <= 0) + break; + if (start < p) { - /* "buf" is full, need to move text to an allocated buffer */ - if (prev == NULL) + /* There's part of a line in buf, store it in "prev". */ + if (p - start + prevlen >= prevsize) { - prev = vim_strnsave(buf, buflen); - prevlen = buflen; - } - else - { - s = alloc((unsigned)(prevlen + buflen)); - if (s != NULL) + /* need bigger "prev" buffer */ + char_u *newprev; + + /* A common use case is ordinary text files and "prev" gets a + * fragment of a line, so the first allocation is made + * small, to avoid repeatedly 'allocing' large and + * 'reallocing' small. */ + if (prevsize == 0) + prevsize = (long)(p - start); + else { - mch_memmove(s, prev, prevlen); - mch_memmove(s + prevlen, buf, buflen); - vim_free(prev); - prev = s; - prevlen += buflen; + long grow50pc = (prevsize * 3) / 2; + long growmin = (long)((p - start) * 2 + prevlen); + prevsize = grow50pc > growmin ? grow50pc : growmin; + } + newprev = prev == NULL ? alloc(prevsize) + : vim_realloc(prev, prevsize); + if (newprev == NULL) + { + do_outofmem_msg((long_u)prevsize); + failed = TRUE; + break; } + prev = newprev; } - filtd = 0; - } - else - { - mch_memmove(buf, buf + tolist, buflen - tolist); - filtd -= tolist; + /* Add the line part to end of "prev". */ + mch_memmove(prev + prevlen, start, p - start); + prevlen += (long)(p - start); } - } + } /* while */ /* * For a negative line count use only the lines at the end of the file, * free the rest. */ - if (maxline < 0) + if (!failed && maxline < 0) while (cnt > -maxline) { listitem_remove(rettv->vval.v_list, rettv->vval.v_list->lv_first); --cnt; } + if (failed) + { + list_free(rettv->vval.v_list, TRUE); + /* readfile doc says an empty list is returned on error */ + rettv->vval.v_list = list_alloc(); + } + vim_free(prev); fclose(fd); } @@ -14691,13 +15133,14 @@ char_u *key; dict_T *d; dictitem_T *di; + char *arg_errmsg = N_("remove() argument"); if (argvars[0].v_type == VAR_DICT) { if (argvars[2].v_type != VAR_UNKNOWN) EMSG2(_(e_toomanyarg), "remove()"); else if ((d = argvars[0].vval.v_dict) != NULL - && !tv_check_lock(d->dv_lock, (char_u *)"remove() argument")) + && !tv_check_lock(d->dv_lock, (char_u *)_(arg_errmsg))) { key = get_tv_string_chk(&argvars[1]); if (key != NULL) @@ -14717,7 +15160,7 @@ else if (argvars[0].v_type != VAR_LIST) EMSG2(_(e_listdictarg), "remove()"); else if ((l = argvars[0].vval.v_list) != NULL - && !tv_check_lock(l->lv_lock, (char_u *)"remove() argument")) + && !tv_check_lock(l->lv_lock, (char_u *)_(arg_errmsg))) { int error = FALSE; @@ -14847,6 +15290,9 @@ typval_T *rettv; { char_u *p; +#ifdef HAVE_READLINK + char_u *buf = NULL; +#endif p = get_tv_string(&argvars[0]); #ifdef FEAT_SHORTCUT @@ -14862,7 +15308,6 @@ #else # ifdef HAVE_READLINK { - char_u buf[MAXPATHL + 1]; char_u *cpy; int len; char_u *remain = NULL; @@ -14879,7 +15324,10 @@ len = STRLEN(p); if (len > 0 && after_pathsep(p, p + len)) + { has_trailing_pathsep = TRUE; + p[len - 1] = NUL; /* the trailing slash breaks readlink() */ + } q = getnextcomp(p); if (*q != NUL) @@ -14890,6 +15338,10 @@ q[-1] = NUL; } + buf = alloc(MAXPATHL + 1); + if (buf == NULL) + goto fail; + for (;;) { for (;;) @@ -15033,6 +15485,7 @@ #ifdef HAVE_READLINK fail: + vim_free(buf); #endif rettv->v_type = VAR_STRING; } @@ -15051,7 +15504,7 @@ if (argvars[0].v_type != VAR_LIST) EMSG2(_(e_listarg), "reverse()"); else if ((l = argvars[0].vval.v_list) != NULL - && !tv_check_lock(l->lv_lock, (char_u *)"reverse()")) + && !tv_check_lock(l->lv_lock, (char_u *)_("reverse() argument"))) { li = l->lv_last; l->lv_first = l->lv_last = NULL; @@ -16056,7 +16509,7 @@ if (tp != NULL && varname != NULL && varp != NULL) { save_curtab = curtab; - goto_tabpage_tp(tp); + goto_tabpage_tp(tp, TRUE); tabvarname = alloc((unsigned)STRLEN(varname) + 3); if (tabvarname != NULL) @@ -16069,7 +16522,7 @@ /* Restore current tabpage */ if (valid_tabpage(save_curtab)) - goto_tabpage_tp(save_curtab); + goto_tabpage_tp(save_curtab, TRUE); } } @@ -16133,7 +16586,7 @@ /* set curwin to be our win, temporarily */ save_curwin = curwin; save_curtab = curtab; - goto_tabpage_tp(tp); + goto_tabpage_tp(tp, TRUE); if (!win_valid(win)) return; curwin = win; @@ -16168,7 +16621,7 @@ /* Restore current tabpage and window, if still valid (autocomands can * make them invalid). */ if (valid_tabpage(save_curtab)) - goto_tabpage_tp(save_curtab); + goto_tabpage_tp(save_curtab, TRUE); if (win_valid(save_curwin)) { curwin = save_curwin; @@ -16256,6 +16709,7 @@ static int item_compare_ic; static char_u *item_compare_func; +static dict_T *item_compare_selfdict; static int item_compare_func_err; #define ITEM_COMPARE_FAIL 999 @@ -16315,7 +16769,8 @@ rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */ res = call_func(item_compare_func, (int)STRLEN(item_compare_func), - &rettv, 2, argv, 0L, 0L, &dummy, TRUE, NULL); + &rettv, 2, argv, 0L, 0L, &dummy, TRUE, + item_compare_selfdict); clear_tv(&argv[0]); clear_tv(&argv[1]); @@ -16348,7 +16803,8 @@ else { l = argvars[0].vval.v_list; - if (l == NULL || tv_check_lock(l->lv_lock, (char_u *)"sort()")) + if (l == NULL || tv_check_lock(l->lv_lock, + (char_u *)_("sort() argument"))) return; rettv->vval.v_list = l; rettv->v_type = VAR_LIST; @@ -16360,8 +16816,10 @@ item_compare_ic = FALSE; item_compare_func = NULL; + item_compare_selfdict = NULL; if (argvars[1].v_type != VAR_UNKNOWN) { + /* optional second argument: {func} */ if (argvars[1].v_type == VAR_FUNC) item_compare_func = argvars[1].vval.v_string; else @@ -16376,6 +16834,17 @@ else item_compare_func = get_tv_string(&argvars[1]); } + + if (argvars[2].v_type != VAR_UNKNOWN) + { + /* optional third argument: {dict} */ + if (argvars[2].v_type != VAR_DICT) + { + EMSG(_(e_dictreq)); + return; + } + item_compare_selfdict = argvars[2].vval.v_dict; + } } /* Make an array with each entry pointing to an item in the List. */ @@ -17512,18 +17981,22 @@ typval_T *argvars UNUSED; typval_T *rettv; { - char_u fname[MAXPATHL + 1]; + char_u *fname; tagname_T tn; int first; if (rettv_list_alloc(rettv) == FAIL) return; + fname = alloc(MAXPATHL); + if (fname == NULL) + return; for (first = TRUE; ; first = FALSE) if (get_tagfname(&tn, first, fname) == FAIL || list_append_string(rettv->vval.v_list, fname, -1) == FAIL) break; tagname_free(&tn); + vim_free(fname); } /* @@ -17711,7 +18184,7 @@ typval_T *argvars; typval_T *rettv; { - char_u *instr; + char_u *in_str; char_u *fromstr; char_u *tostr; char_u *p; @@ -17728,7 +18201,7 @@ char_u buf2[NUMBUFLEN]; garray_T ga; - instr = get_tv_string(&argvars[0]); + in_str = get_tv_string(&argvars[0]); fromstr = get_tv_string_buf_chk(&argvars[1], buf); tostr = get_tv_string_buf_chk(&argvars[2], buf2); @@ -17754,19 +18227,19 @@ } /* fromstr and tostr have to contain the same number of chars */ - while (*instr != NUL) + while (*in_str != NUL) { #ifdef FEAT_MBYTE if (has_mbyte) { - inlen = (*mb_ptr2len)(instr); - cpstr = instr; + inlen = (*mb_ptr2len)(in_str); + cpstr = in_str; cplen = inlen; idx = 0; for (p = fromstr; *p != NUL; p += fromlen) { fromlen = (*mb_ptr2len)(p); - if (fromlen == inlen && STRNCMP(instr, p, inlen) == 0) + if (fromlen == inlen && STRNCMP(in_str, p, inlen) == 0) { for (p = tostr; *p != NUL; p += tolen) { @@ -17785,11 +18258,11 @@ ++idx; } - if (first && cpstr == instr) + if (first && cpstr == in_str) { /* Check that fromstr and tostr have the same number of * (multi-byte) characters. Done only once when a character - * of instr doesn't appear in fromstr. */ + * of in_str doesn't appear in fromstr. */ first = FALSE; for (p = tostr; *p != NUL; p += tolen) { @@ -17804,18 +18277,18 @@ mch_memmove((char *)ga.ga_data + ga.ga_len, cpstr, (size_t)cplen); ga.ga_len += cplen; - instr += inlen; + in_str += inlen; } else #endif { /* When not using multi-byte chars we can do it faster. */ - p = vim_strchr(fromstr, *instr); + p = vim_strchr(fromstr, *in_str); if (p != NULL) ga_append(&ga, tostr[p - fromstr]); else - ga_append(&ga, *instr); - ++instr; + ga_append(&ga, *in_str); + ++in_str; } } @@ -17882,11 +18355,21 @@ rettv->v_type = VAR_STRING; #ifdef FEAT_PERSISTENT_UNDO { - char_u *ffname = FullName_save(get_tv_string(&argvars[0]), FALSE); + char_u *fname = get_tv_string(&argvars[0]); - if (ffname != NULL) - rettv->vval.v_string = u_get_undo_file_name(ffname, FALSE); - vim_free(ffname); + if (*fname == NUL) + { + /* If there is no file name there will be no undo file. */ + rettv->vval.v_string = NULL; + } + else + { + char_u *ffname = FullName_save(fname, FALSE); + + if (ffname != NULL) + rettv->vval.v_string = u_get_undo_file_name(ffname, FALSE); + vim_free(ffname); + } } #else rettv->vval.v_string = NULL; @@ -18118,9 +18601,11 @@ curwin->w_skipcol = get_dict_number(dict, (char_u *)"skipcol"); check_cursor(); - changed_cline_bef_curs(); - invalidate_botline(); - redraw_later(VALID); + win_new_height(curwin, curwin->w_height); +# ifdef FEAT_VERTSPLIT + win_new_width(curwin, W_WIDTH(curwin)); +# endif + changed_window_setting(); if (curwin->w_topline == 0) curwin->w_topline = 1; @@ -18258,6 +18743,19 @@ } /* + * "xor(expr, expr)" function + */ + static void +f_xor(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ + rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL) + ^ get_tv_number_chk(&argvars[1], NULL); +} + + +/* * Translate a String variable into a position. * Returns NULL when there is an error. */ @@ -18768,11 +19266,7 @@ set_vim_var_char(c) int c; { -#ifdef FEAT_MBYTE - char_u buf[MB_MAXBYTES]; -#else - char_u buf[2]; -#endif + char_u buf[MB_MAXBYTES + 1]; #ifdef FEAT_MBYTE if (has_mbyte) @@ -19453,9 +19947,14 @@ * worked find the variable again. Don't auto-load a script if it was * loaded already, otherwise it would be loaded every time when * checking if a function name is a Funcref variable. */ - if (ht == &globvarht && !writing - && script_autoload(varname, FALSE) && !aborting()) + if (ht == &globvarht && !writing) + { + /* Note: script_autoload() may make "hi" invalid. It must either + * be obtained again or not used. */ + if (!script_autoload(varname, FALSE) || aborting()) + return NULL; hi = hash_find(ht, varname); + } if (HASHITEM_EMPTY(hi)) return NULL; } @@ -19564,7 +20063,7 @@ { sv = SCRIPT_SV(ga_scripts.ga_len + 1) = (scriptvar_T *)alloc_clear(sizeof(scriptvar_T)); - init_var_dict(&sv->sv_dict, &sv->sv_var); + init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE); ++ga_scripts.ga_len; } } @@ -19575,11 +20074,14 @@ * point to it. */ void -init_var_dict(dict, dict_var) +init_var_dict(dict, dict_var, scope) dict_T *dict; dictitem_T *dict_var; + int scope; { hash_init(&dict->dv_hashtab); + dict->dv_lock = 0; + dict->dv_scope = scope; dict->dv_refcount = DO_NOT_FREE_CNT; dict->dv_copyID = 0; dict_var->di_tv.vval.v_dict = dict; @@ -19730,7 +20232,6 @@ dictitem_T *v; char_u *varname; hashtab_T *ht; - char_u *p; ht = find_var_ht(name, &varname); if (ht == NULL || *varname == NUL) @@ -19740,25 +20241,8 @@ } v = find_var_in_ht(ht, varname, TRUE); - if (tv->v_type == VAR_FUNC) - { - if (!(vim_strchr((char_u *)"wbs", name[0]) != NULL && name[1] == ':') - && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':') - ? name[2] : name[0])) - { - EMSG2(_("E704: Funcref variable name must start with a capital: %s"), name); - return; - } - /* Don't allow hiding a function. When "v" is not NULL we migth be - * assigning another function to the same var, the type is checked - * below. */ - if (v == NULL && function_exists(name)) - { - EMSG2(_("E705: Variable name conflicts with existing function: %s"), - name); - return; - } - } + if (tv->v_type == VAR_FUNC && var_check_func_name(name, v == NULL)) + return; if (v != NULL) { @@ -19824,13 +20308,8 @@ } /* Make sure the variable name is valid. */ - for (p = varname; *p != NUL; ++p) - if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p)) - && *p != AUTOLOAD_CHAR) - { - EMSG2(_(e_illvar), varname); - return; - } + if (!valid_varname(varname)) + return; v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T) + STRLEN(varname))); @@ -19895,6 +20374,55 @@ } /* + * Check if a funcref is assigned to a valid variable name. + * Return TRUE and give an error if not. + */ + static int +var_check_func_name(name, new_var) + char_u *name; /* points to start of variable name */ + int new_var; /* TRUE when creating the variable */ +{ + if (!(vim_strchr((char_u *)"wbs", name[0]) != NULL && name[1] == ':') + && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':') + ? name[2] : name[0])) + { + EMSG2(_("E704: Funcref variable name must start with a capital: %s"), + name); + return TRUE; + } + /* Don't allow hiding a function. When "v" is not NULL we might be + * assigning another function to the same var, the type is checked + * below. */ + if (new_var && function_exists(name)) + { + EMSG2(_("E705: Variable name conflicts with existing function: %s"), + name); + return TRUE; + } + return FALSE; +} + +/* + * Check if a variable name is valid. + * Return FALSE and give an error if not. + */ + static int +valid_varname(varname) + char_u *varname; +{ + char_u *p; + + for (p = varname; *p != NUL; ++p) + if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p)) + && *p != AUTOLOAD_CHAR) + { + EMSG2(_(e_illvar), varname); + return FALSE; + } + return TRUE; +} + +/* * Return TRUE if typeval "tv" is set to be locked (immutable). * Also give an error message, using "name". */ @@ -20099,7 +20627,13 @@ /* Call msg_start() after eval1(), evaluating the expression * may cause a message to appear. */ if (eap->cmdidx == CMD_echo) + { + /* Mark the saved text as finishing the line, so that what + * follows is displayed on a new line when scrolling back + * at the more prompt. */ + msg_sb_eol(); msg_start(); + } } else if (eap->cmdidx == CMD_echo) msg_puts_attr((char_u *)" ", echo_attr); @@ -20302,6 +20836,7 @@ exarg_T *eap; { char_u *theline; + int i; int j; int c; int saved_did_emsg; @@ -20548,6 +21083,15 @@ arg = vim_strsave(arg); if (arg == NULL) goto erret; + + /* Check for duplicate argument name. */ + for (i = 0; i < newargs.ga_len; ++i) + if (STRCMP(((char_u **)(newargs.ga_data))[i], arg) == 0) + { + EMSG2(_("E853: Duplicate argument name: %s"), arg); + goto erret; + } + ((char_u **)(newargs.ga_data))[newargs.ga_len] = arg; *p = c; newargs.ga_len++; @@ -20623,7 +21167,8 @@ nesting = 0; for (;;) { - msg_scroll = TRUE; + if (KeyTyped) + msg_scroll = TRUE; need_wait_return = FALSE; sourcing_lnum_off = sourcing_lnum; @@ -20726,6 +21271,8 @@ && (!ASCII_ISALPHA(p[2]) || p[2] == 'r')) || (p[0] == 't' && p[1] == 'c' && (!ASCII_ISALPHA(p[2]) || p[2] == 'l')) + || (p[0] == 'l' && p[1] == 'u' && p[2] == 'a' + && !ASCII_ISALPHA(p[3])) || (p[0] == 'r' && p[1] == 'u' && p[2] == 'b' && (!ASCII_ISALPHA(p[3]) || p[3] == 'y')) || (p[0] == 'm' && p[1] == 'z' @@ -21562,6 +22109,9 @@ ++hi; fp = HI2UF(hi); + if (fp->uf_flags & FC_DICT) + return (char_u *)""; /* don't show dict functions */ + if (STRLEN(fp->uf_name) + 4 >= IOSIZE) return fp->uf_name; /* prevents overflow */ @@ -21689,7 +22239,7 @@ * Unreference a Function: decrement the reference count and free it when it * becomes zero. Only for numbered functions. */ - static void + void func_unref(name) char_u *name; { @@ -21713,7 +22263,7 @@ /* * Count a reference to a Function. */ - static void + void func_ref(name) char_u *name; { @@ -21792,7 +22342,7 @@ /* * Init l: variables. */ - init_var_dict(&fc->l_vars, &fc->l_vars_var); + init_var_dict(&fc->l_vars, &fc->l_vars_var, VAR_DEF_SCOPE); if (selfdict != NULL) { /* Set l:self to "selfdict". Use "name" to avoid a warning from @@ -21813,7 +22363,7 @@ * Set a:0 to "argcount". * Set a:000 to a list with room for the "..." arguments. */ - init_var_dict(&fc->l_avars, &fc->l_avars_var); + init_var_dict(&fc->l_avars, &fc->l_avars_var, VAR_SCOPE); add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "0", (varnumber_T)(argcount - fp->uf_args.ga_len)); /* Use "name" to avoid a warning from some compiler that checks the @@ -21921,8 +22471,12 @@ s = tv2string(&argvars[i], &tofree, numbuf2, 0); if (s != NULL) { - trunc_string(s, buf, MSG_BUF_CLEN); - msg_puts(buf); + if (vim_strsize(s) > MSG_BUF_CLEN) + { + trunc_string(s, buf, MSG_BUF_CLEN, MSG_BUF_LEN); + s = buf; + } + msg_puts(s); vim_free(tofree); } } @@ -22010,8 +22564,12 @@ 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); + if (vim_strsize(s) > MSG_BUF_CLEN) + { + trunc_string(s, buf, MSG_BUF_CLEN, MSG_BUF_LEN); + s = buf; + } + smsg((char_u *)_("%s returning %s"), sourcing_name, s); vim_free(tofree); } } @@ -22519,18 +23077,21 @@ if (tab != NULL) { *tab++ = '\0'; /* isolate the variable name */ - if (*tab == 'S') /* string var */ - type = VAR_STRING; + switch (*tab) + { + case 'S': type = VAR_STRING; break; #ifdef FEAT_FLOAT - else if (*tab == 'F') - type = VAR_FLOAT; + case 'F': type = VAR_FLOAT; break; #endif + case 'D': type = VAR_DICT; break; + case 'L': type = VAR_LIST; break; + } tab = vim_strchr(tab, '\t'); if (tab != NULL) { tv.v_type = type; - if (type == VAR_STRING) + if (type == VAR_STRING || type == VAR_DICT || type == VAR_LIST) tv.vval.v_string = viminfo_readstring(virp, (int)(tab - virp->vir_line + 1), TRUE); #ifdef FEAT_FLOAT @@ -22539,9 +23100,28 @@ #endif else tv.vval.v_number = atol((char *)tab + 1); + if (type == VAR_DICT || type == VAR_LIST) + { + typval_T *etv = eval_expr(tv.vval.v_string, NULL); + + if (etv == NULL) + /* Failed to parse back the dict or list, use it as a + * string. */ + tv.v_type = VAR_STRING; + else + { + vim_free(tv.vval.v_string); + tv = *etv; + vim_free(etv); + } + } + set_var(virp->vir_line + 1, &tv, FALSE); - if (type == VAR_STRING) + + if (tv.v_type == VAR_STRING) vim_free(tv.vval.v_string); + else if (tv.v_type == VAR_DICT || tv.v_type == VAR_LIST) + clear_tv(&tv); } } } @@ -22583,8 +23163,10 @@ case VAR_STRING: s = "STR"; break; case VAR_NUMBER: s = "NUM"; break; #ifdef FEAT_FLOAT - case VAR_FLOAT: s = "FLO"; break; + case VAR_FLOAT: s = "FLO"; break; #endif + case VAR_DICT: s = "DIC"; break; + case VAR_LIST: s = "LIS"; break; default: continue; } fprintf(fp, "!%s\t%s\t", this_var->di_key, s); @@ -22656,7 +23238,7 @@ f = -f; sign = '-'; } - if ((fprintf(fd, "let %s = %c&%f", + if ((fprintf(fd, "let %s = %c%f", this_var->di_key, sign, f) < 0) || put_eol(fd) == FAIL) return FAIL; @@ -23019,6 +23601,7 @@ int c; int has_fullname = 0; #ifdef WIN3264 + char_u *fname_start = *fnamep; int has_shortname = 0; #endif @@ -23072,6 +23655,27 @@ return -1; } +#ifdef WIN3264 +# if _WIN32_WINNT >= 0x0500 + if (vim_strchr(*fnamep, '~') != NULL) + { + /* Expand 8.3 filename to full path. Needed to make sure the same + * file does not have two different names. + * Note: problem does not occur if _WIN32_WINNT < 0x0500. */ + p = alloc(_MAX_PATH + 1); + if (p != NULL) + { + if (GetLongPathName(*fnamep, p, MAXPATHL)) + { + vim_free(*bufp); + *bufp = *fnamep = p; + } + else + vim_free(p); + } + } +# endif +#endif /* Append a path separator to a directory. */ if (mch_isdir(*fnamep)) { @@ -23193,24 +23797,25 @@ } #ifdef WIN3264 - /* Check shortname after we have done 'heads' and before we do 'tails' + /* + * Handle ":8" after we have done 'heads' and before we do 'tails'. */ if (has_shortname) { - pbuf = NULL; - /* Copy the string if it is shortened by :h */ - if (*fnamelen < (int)STRLEN(*fnamep)) + /* Copy the string if it is shortened by :h and when it wasn't copied + * yet, because we are going to change it in place. Avoids changing + * the buffer name for "%:8". */ + if (*fnamelen < (int)STRLEN(*fnamep) || *fnamep == fname_start) { p = vim_strnsave(*fnamep, *fnamelen); - if (p == 0) + if (p == NULL) return -1; vim_free(*bufp); *bufp = *fnamep = p; } /* Split into two implementations - makes it easier. First is where - * there isn't a full name already, second is where there is. - */ + * there isn't a full name already, second is where there is. */ if (!has_fullname && !vim_isAbsName(*fnamep)) { if (shortpath_for_partial(fnamep, bufp, fnamelen) == FAIL) @@ -23218,18 +23823,16 @@ } else { - int l; + int l = *fnamelen; - /* Simple case, already have the full-name + /* Simple case, already have the full-name. * Nearly always shorter, so try first time. */ - l = *fnamelen; if (get_short_pathname(fnamep, bufp, &l) == FAIL) return -1; if (l == 0) { - /* Couldn't find the filename.. search the paths. - */ + /* Couldn't find the filename, search the paths. */ l = *fnamelen; if (shortpath_for_invalid_fname(fnamep, bufp, &l) == FAIL) return -1; diff -Naur vim73.orig/src/ex_cmds.c vim73/src/ex_cmds.c --- vim73.orig/src/ex_cmds.c 2010-08-13 09:14:35.000000000 +0000 +++ vim73/src/ex_cmds.c 2012-07-20 20:31:18.014311616 +0000 @@ -11,10 +11,6 @@ * ex_cmds.c: some functions for command line commands */ -#if defined(MSDOS) || defined(WIN16) || defined(WIN32) || defined(_WIN64) -# include "vimio.h" /* for mch_open(), must be before vim.h */ -#endif - #include "vim.h" #include "version.h" @@ -29,7 +25,6 @@ static int read_viminfo_up_to_marks __ARGS((vir_T *virp, int forceit, int writing)); #endif -static int check_overwrite __ARGS((exarg_T *eap, buf_T *buf, char_u *fname, char_u *ffname, int other)); static int check_readonly __ARGS((int *forceit, buf_T *buf)); #ifdef FEAT_AUTOCMD static void delbuf_msg __ARGS((char_u *name)); @@ -323,7 +318,8 @@ /* When sorting numbers "start_col_nr" is the number, not the column * number. */ if (sort_nr) - result = l1.start_col_nr - l2.start_col_nr; + result = l1.start_col_nr == l2.start_col_nr ? 0 + : l1.start_col_nr > l2.start_col_nr ? 1 : -1; else { /* We need to copy one line into "sortbuf1", because there is no @@ -482,7 +478,7 @@ * of the match, by temporarily terminating the string there */ s2 = s + end_col; c = *s2; - (*s2) = 0; + *s2 = NUL; /* Sorting on number: Store the number itself. */ p = s + start_col; if (sort_hex) @@ -491,9 +487,13 @@ s = skiptodigit(p); if (s > p && s[-1] == '-') --s; /* include preceding negative sign */ - vim_str2nr(s, NULL, NULL, sort_oct, sort_hex, - &nrs[lnum - eap->line1].start_col_nr, NULL); - (*s2) = c; + if (*s == NUL) + /* empty line should sort before any number */ + nrs[lnum - eap->line1].start_col_nr = -MAXLNUM; + else + vim_str2nr(s, NULL, NULL, sort_oct, sort_hex, + &nrs[lnum - eap->line1].start_col_nr, NULL); + *s2 = c; } else { @@ -819,7 +819,13 @@ curwin->w_cursor.lnum = dest + (line2 - line1) + 1; if (line1 < dest) - changed_lines(line1, 0, dest + num_lines + 1, 0L); + { + dest += num_lines + 1; + last_line = curbuf->b_ml.ml_line_count; + if (dest > last_line + 1) + dest = last_line + 1; + changed_lines(line1, 0, dest, 0L); + } else changed_lines(dest + 1, 0, line1 + num_lines, 0L); @@ -898,9 +904,6 @@ * Handle the ":!cmd" command. Also for ":r !cmd" and ":w !cmd" * Bangs in the argument are replaced with the previously entered command. * Remember the argument. - * - * RISCOS: Bangs only replaced when followed by a space, since many - * pathnames contain one. */ void do_bang(addr_count, eap, forceit, do_in, do_out) @@ -979,11 +982,7 @@ trailarg = NULL; while (*p) { - if (*p == '!' -#ifdef RISCOS - && (p[1] == ' ' || p[1] == NUL) -#endif - ) + if (*p == '!') { if (p > newcmd && p[-1] == '\\') STRMOVE(p - 1, p); @@ -1113,7 +1112,7 @@ if (do_out) shell_flags |= SHELL_DOOUT; -#if !defined(USE_SYSTEM) && defined(UNIX) +#ifdef FEAT_FILTERPIPE if (!do_in && do_out && !p_stmp) { /* Use a pipe to fetch stdout of the command, do not use a temp file. */ @@ -1577,14 +1576,8 @@ if (p != NULL) *p = NUL; } -# ifdef RISCOS - STRCAT(buf, " { < "); /* Use RISC OS notation for input. */ - STRCAT(buf, itmp); - STRCAT(buf, " } "); -# else STRCAT(buf, " <"); /* " < " causes problems on Amiga */ STRCAT(buf, itmp); -# endif if (*p_shq == NUL) { p = vim_strchr(cmd, '|'); @@ -1633,16 +1626,9 @@ else vim_snprintf((char *)end, (size_t)(buflen - (end - buf)), #ifdef FEAT_QUICKFIX -# ifndef RISCOS - opt != p_sp ? " %s%s" : -# endif " %s %s", #else -# ifndef RISCOS " %s%s", /* " > %s" causes problems on Amiga */ -# else - " %s %s", /* But is needed for 'shellpipe' and RISC OS */ -# endif #endif (char *)opt, (char *)fname); } @@ -1843,11 +1829,7 @@ #ifdef VMS (char_u *)"-tmp", #else -# ifdef RISCOS - (char_u *)"/tmp", -# else (char_u *)".tmp", -# endif #endif FALSE); if (tempname == NULL) /* out of memory */ @@ -2700,6 +2682,10 @@ TRUE); do_modelines(0); } + + /* Autocommands may have changed buffer names, esp. when + * 'autochdir' is set. */ + fname = curbuf->b_sfname; #endif } @@ -2735,7 +2721,7 @@ * May set eap->forceit if a dialog says it's OK to overwrite. * Return OK if it's OK, FAIL if it is not. */ - static int + int check_overwrite(eap, buf, fname, ffname, other) exarg_T *eap; buf_T *buf; @@ -2772,7 +2758,7 @@ #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) if (p_confirm || cmdmod.confirm) { - char_u buff[IOSIZE]; + char_u buff[DIALOG_MSG_SIZE]; dialog_msg(buff, _("Overwrite existing file \"%s\"?"), fname); if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2) != VIM_YES) @@ -2790,7 +2776,7 @@ /* For ":w! filename" check that no swap file exists for "filename". */ if (other && !emsg_silent) { - char_u dir[MAXPATHL]; + char_u *dir; char_u *p; int r; char_u *swapname; @@ -2801,20 +2787,29 @@ * Use 'shortname' of the current buffer, since there is no buffer * for the written file. */ if (*p_dir == NUL) + { + dir = alloc(5); + if (dir == NULL) + return FAIL; STRCPY(dir, "."); + } else { + dir = alloc(MAXPATHL); + if (dir == NULL) + return FAIL; p = p_dir; copy_option_part(&p, dir, MAXPATHL, ","); } swapname = makeswapname(fname, ffname, curbuf, dir); + vim_free(dir); r = vim_fexists(swapname); if (r) { #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) if (p_confirm || cmdmod.confirm) { - char_u buff[IOSIZE]; + char_u buff[DIALOG_MSG_SIZE]; dialog_msg(buff, _("Swap file \"%s\" exists, overwrite anyway?"), @@ -2964,7 +2959,7 @@ #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) if ((p_confirm || cmdmod.confirm) && buf->b_fname != NULL) { - char_u buff[IOSIZE]; + char_u buff[DIALOG_MSG_SIZE]; if (buf->b_p_ro) dialog_msg(buff, _("'readonly' option is set for \"%s\".\nDo you wish to write anyway?"), @@ -3391,9 +3386,16 @@ /* close the link to the current buffer */ u_sync(FALSE); close_buffer(oldwin, curbuf, - (flags & ECMD_HIDE) ? 0 : DOBUF_UNLOAD); + (flags & ECMD_HIDE) ? 0 : DOBUF_UNLOAD, FALSE); #ifdef FEAT_AUTOCMD + /* Autocommands may open a new window and leave oldwin open + * which leads to crashes since the above call sets + * oldwin->w_buffer to NULL. */ + if (curwin != oldwin && oldwin != aucmd_win + && win_valid(oldwin) && oldwin->w_buffer == NULL) + win_close(oldwin, FALSE); + # ifdef FEAT_EVAL if (aborting()) /* autocmds may abort script processing */ { @@ -3418,7 +3420,7 @@ * and re-attach to buffer, perhaps. */ if (curwin->w_s == &(curwin->w_buffer->b_s)) - curwin->w_s = &(buf->b_s); + curwin->w_s = &(buf->b_s); #endif curwin->w_buffer = buf; curbuf = buf; @@ -3498,9 +3500,7 @@ curbuf->b_p_bin = FALSE; /* reset 'bin' before reading file */ curwin->w_p_nu = 0; /* no line numbers */ curwin->w_p_rnu = 0; /* no relative line numbers */ -#ifdef FEAT_SCROLLBIND - curwin->w_p_scb = FALSE; /* no scroll binding */ -#endif + RESET_BINDING(curwin); /* no scroll or cursor binding */ #ifdef FEAT_ARABIC curwin->w_p_arab = FALSE; /* no arabic mode */ #endif @@ -3631,10 +3631,6 @@ */ check_arg_idx(curwin); -#ifdef FEAT_SYN_HL - reset_synblock(curwin); /* remove any ownsyntax */ -#endif - #ifdef FEAT_AUTOCMD if (!auto_buf) #endif @@ -4109,8 +4105,8 @@ switch (*kind) { case '-': - start = lnum - bigness * (linenr_T)(x - kind); - end = start + bigness; + start = lnum - bigness * (linenr_T)(x - kind) + 1; + end = start + bigness - 1; curs = end; break; @@ -4637,7 +4633,15 @@ * for a match in this line again. */ skip_match = TRUE; else - ++matchcol; /* search for a match at next column */ + { + /* search for a match at next column */ +#ifdef FEAT_MBYTE + if (has_mbyte) + matchcol += mb_ptr2len(sub_firstline + matchcol); + else +#endif + ++matchcol; + } goto skip; } @@ -5146,10 +5150,13 @@ if (!global_busy) { - if (endcolumn) - coladvance((colnr_T)MAXCOL); - else - beginline(BL_WHITE | BL_FIX); + if (!do_ask) /* when interactive leave cursor on the match */ + { + if (endcolumn) + coladvance((colnr_T)MAXCOL); + else + beginline(BL_WHITE | BL_FIX); + } if (!do_sub_msg(do_count) && do_ask) MSG(""); } @@ -5353,8 +5360,9 @@ global_exe(cmd) char_u *cmd; { - linenr_T old_lcount; /* b_ml.ml_line_count before the command */ - linenr_T lnum; /* line number according to old situation */ + linenr_T old_lcount; /* b_ml.ml_line_count before the command */ + buf_T *old_buf = curbuf; /* remember what buffer we started in */ + linenr_T lnum; /* line number according to old situation */ /* * Set current position only once for a global command. @@ -5398,8 +5406,10 @@ msg_didout = FALSE; /* If substitutes done, report number of substitutes, otherwise report - * number of extra or deleted lines. */ - if (!do_sub_msg(FALSE)) + * number of extra or deleted lines. + * Don't report extra or deleted lines in the edge case where the buffer + * we are in after execution is different from the buffer we started in. */ + if (!do_sub_msg(FALSE) && curbuf == old_buf) msgmore(curbuf->b_ml.ml_line_count - old_lcount); } @@ -5409,7 +5419,7 @@ vir_T *virp; int force; { - if (old_sub != NULL && force) + if (force) vim_free(old_sub); if (force || old_sub == NULL) old_sub = viminfo_readstring(virp, 1, TRUE); @@ -5471,9 +5481,8 @@ return FALSE; curwin->w_p_pvw = TRUE; curwin->w_p_wfh = TRUE; -# ifdef FEAT_SCROLLBIND - curwin->w_p_scb = FALSE; /* don't take over 'scrollbind' */ -# endif + RESET_BINDING(curwin); /* don't take over 'scrollbind' + and 'cursorbind' */ # ifdef FEAT_DIFF curwin->w_p_diff = FALSE; /* no 'diff' */ # endif @@ -5514,6 +5523,9 @@ int len; char_u *lang; #endif +#ifdef FEAT_FOLDING + int old_KeyTyped = KeyTyped; +#endif if (eap != NULL) { @@ -5533,7 +5545,7 @@ } arg = eap->arg; - if (eap->forceit && *arg == NUL) + if (eap->forceit && *arg == NUL && !curbuf->b_help) { EMSG(_("E478: Don't panic!")); return; @@ -5677,6 +5689,12 @@ if (!p_im) restart_edit = 0; /* don't want insert mode in help file */ +#ifdef FEAT_FOLDING + /* Restore KeyTyped, setting 'filetype=help' may reset it. + * It is needed for do_tag top open folds under the cursor. */ + KeyTyped = old_KeyTyped; +#endif + if (tag != NULL) do_tag(tag, DT_HELP, 1, FALSE, TRUE); @@ -5946,6 +5964,29 @@ break; } *d = NUL; + + if (*IObuff == '`') + { + if (d > IObuff + 2 && d[-1] == '`') + { + /* remove the backticks from `command` */ + mch_memmove(IObuff, IObuff + 1, STRLEN(IObuff)); + d[-2] = NUL; + } + else if (d > IObuff + 3 && d[-2] == '`' && d[-1] == ',') + { + /* remove the backticks and comma from `command`, */ + mch_memmove(IObuff, IObuff + 1, STRLEN(IObuff)); + d[-3] = NUL; + } + else if (d > IObuff + 4 && d[-3] == '`' + && d[-2] == '\\' && d[-1] == '.') + { + /* remove the backticks and dot from `command`\. */ + mch_memmove(IObuff, IObuff + 1, STRLEN(IObuff)); + d[-4] = NUL; + } + } } } @@ -5979,6 +6020,7 @@ char_u *line; int in_example = FALSE; int len; + char_u *fname; char_u *p; char_u *rt; int mustfree; @@ -6025,124 +6067,187 @@ } /* - * In the "help.txt" file, add the locally added help files. - * This uses the very first line in the help file. + * In the "help.txt" and "help.abx" file, add the locally added help + * files. This uses the very first line in the help file. */ - if (fnamecmp(gettail(curbuf->b_fname), "help.txt") == 0) + fname = gettail(curbuf->b_fname); + if (fnamecmp(fname, "help.txt") == 0 +#ifdef FEAT_MULTI_LANG + || (fnamencmp(fname, "help.", 5) == 0 + && ASCII_ISALPHA(fname[5]) + && ASCII_ISALPHA(fname[6]) + && TOLOWER_ASC(fname[7]) == 'x' + && fname[8] == NUL) +#endif + ) { for (lnum = 1; lnum < curbuf->b_ml.ml_line_count; ++lnum) { line = ml_get_buf(curbuf, lnum, FALSE); - if (strstr((char *)line, "*local-additions*") != NULL) - { - /* Go through all directories in 'runtimepath', skipping - * $VIMRUNTIME. */ - p = p_rtp; - while (*p != NUL) - { - copy_option_part(&p, NameBuff, MAXPATHL, ","); - mustfree = FALSE; - rt = vim_getenv((char_u *)"VIMRUNTIME", &mustfree); - if (fullpathcmp(rt, NameBuff, FALSE) != FPC_SAME) - { - int fcount; - char_u **fnames; - FILE *fd; - char_u *s; - int fi; + if (strstr((char *)line, "*local-additions*") == NULL) + continue; + + /* Go through all directories in 'runtimepath', skipping + * $VIMRUNTIME. */ + p = p_rtp; + while (*p != NUL) + { + copy_option_part(&p, NameBuff, MAXPATHL, ","); + mustfree = FALSE; + rt = vim_getenv((char_u *)"VIMRUNTIME", &mustfree); + if (fullpathcmp(rt, NameBuff, FALSE) != FPC_SAME) + { + int fcount; + char_u **fnames; + FILE *fd; + char_u *s; + int fi; #ifdef FEAT_MBYTE - vimconv_T vc; - char_u *cp; + vimconv_T vc; + char_u *cp; #endif - /* Find all "doc/ *.txt" files in this directory. */ - add_pathsep(NameBuff); - STRCAT(NameBuff, "doc/*.txt"); - if (gen_expand_wildcards(1, &NameBuff, &fcount, - &fnames, EW_FILE|EW_SILENT) == OK - && fcount > 0) + /* Find all "doc/ *.txt" files in this directory. */ + add_pathsep(NameBuff); +#ifdef FEAT_MULTI_LANG + STRCAT(NameBuff, "doc/*.??[tx]"); +#else + STRCAT(NameBuff, "doc/*.txt"); +#endif + if (gen_expand_wildcards(1, &NameBuff, &fcount, + &fnames, EW_FILE|EW_SILENT) == OK + && fcount > 0) + { +#ifdef FEAT_MULTI_LANG + int i1; + int i2; + char_u *f1; + char_u *f2; + char_u *t1; + char_u *e1; + char_u *e2; + + /* If foo.abx is found use it instead of foo.txt in + * the same directory. */ + for (i1 = 0; i1 < fcount; ++i1) { - for (fi = 0; fi < fcount; ++fi) + for (i2 = 0; i2 < fcount; ++i2) { - fd = mch_fopen((char *)fnames[fi], "r"); - if (fd != NULL) + if (i1 == i2) + continue; + if (fnames[i1] == NULL || fnames[i2] == NULL) + continue; + f1 = fnames[i1]; + f2 = fnames[i2]; + t1 = gettail(f1); + if (fnamencmp(f1, f2, t1 - f1) != 0) + continue; + e1 = vim_strrchr(t1, '.'); + e2 = vim_strrchr(gettail(f2), '.'); + if (e1 == NUL || e2 == NUL) + continue; + if (fnamecmp(e1, ".txt") != 0 + && fnamecmp(e1, fname + 4) != 0) { - vim_fgets(IObuff, IOSIZE, fd); - if (IObuff[0] == '*' - && (s = vim_strchr(IObuff + 1, '*')) - != NULL) - { -#ifdef FEAT_MBYTE - int this_utf = MAYBE; + /* Not .txt and not .abx, remove it. */ + vim_free(fnames[i1]); + fnames[i1] = NULL; + continue; + } + if (fnamencmp(f1, f2, e1 - f1) != 0) + continue; + if (fnamecmp(e1, ".txt") == 0 + && fnamecmp(e2, fname + 4) == 0) + { + /* use .abx instead of .txt */ + vim_free(fnames[i1]); + fnames[i1] = NULL; + } + } + } #endif - /* Change tag definition to a - * reference and remove /. */ - IObuff[0] = '|'; - *s = '|'; - while (*s != NUL) - { - if (*s == '\r' || *s == '\n') - *s = NUL; + for (fi = 0; fi < fcount; ++fi) + { + if (fnames[fi] == NULL) + continue; + fd = mch_fopen((char *)fnames[fi], "r"); + if (fd != NULL) + { + vim_fgets(IObuff, IOSIZE, fd); + if (IObuff[0] == '*' + && (s = vim_strchr(IObuff + 1, '*')) + != NULL) + { #ifdef FEAT_MBYTE - /* The text is utf-8 when a byte - * above 127 is found and no - * illegal byte sequence is found. - */ - if (*s >= 0x80 && this_utf != FALSE) - { - int l; - - this_utf = TRUE; - l = utf_ptr2len(s); - if (l == 1) - this_utf = FALSE; - s += l - 1; - } + int this_utf = MAYBE; #endif - ++s; - } + /* Change tag definition to a + * reference and remove /. */ + IObuff[0] = '|'; + *s = '|'; + while (*s != NUL) + { + if (*s == '\r' || *s == '\n') + *s = NUL; #ifdef FEAT_MBYTE - /* The help file is latin1 or utf-8; - * conversion to the current - * 'encoding' may be required. */ - vc.vc_type = CONV_NONE; - convert_setup(&vc, (char_u *)( - this_utf == TRUE ? "utf-8" - : "latin1"), p_enc); - if (vc.vc_type == CONV_NONE) - /* No conversion needed. */ - cp = IObuff; - else + /* The text is utf-8 when a byte + * above 127 is found and no + * illegal byte sequence is found. + */ + if (*s >= 0x80 && this_utf != FALSE) { - /* Do the conversion. If it fails - * use the unconverted text. */ - cp = string_convert(&vc, IObuff, - NULL); - if (cp == NULL) - cp = IObuff; + int l; + + this_utf = TRUE; + l = utf_ptr2len(s); + if (l == 1) + this_utf = FALSE; + s += l - 1; } - convert_setup(&vc, NULL, NULL); +#endif + ++s; + } +#ifdef FEAT_MBYTE + /* The help file is latin1 or utf-8; + * conversion to the current + * 'encoding' may be required. */ + vc.vc_type = CONV_NONE; + convert_setup(&vc, (char_u *)( + this_utf == TRUE ? "utf-8" + : "latin1"), p_enc); + if (vc.vc_type == CONV_NONE) + /* No conversion needed. */ + cp = IObuff; + else + { + /* Do the conversion. If it fails + * use the unconverted text. */ + cp = string_convert(&vc, IObuff, + NULL); + if (cp == NULL) + cp = IObuff; + } + convert_setup(&vc, NULL, NULL); - ml_append(lnum, cp, (colnr_T)0, FALSE); - if (cp != IObuff) - vim_free(cp); + ml_append(lnum, cp, (colnr_T)0, FALSE); + if (cp != IObuff) + vim_free(cp); #else - ml_append(lnum, IObuff, (colnr_T)0, - FALSE); + ml_append(lnum, IObuff, (colnr_T)0, + FALSE); #endif - ++lnum; - } - fclose(fd); + ++lnum; } + fclose(fd); } - FreeWild(fcount, fnames); } + FreeWild(fcount, fnames); } - if (mustfree) - vim_free(rt); } - break; + if (mustfree) + vim_free(rt); } + break; } } } @@ -6430,7 +6535,10 @@ p1 = vim_strchr(IObuff, '*'); /* find first '*' */ while (p1 != NULL) { - p2 = vim_strchr(p1 + 1, '*'); /* find second '*' */ + /* Use vim_strbyte() instead of vim_strchr() so that when + * 'encoding' is dbcs it still works, don't find '*' in the + * second byte. */ + p2 = vim_strbyte(p1 + 1, '*'); /* find second '*' */ if (p2 != NULL && p2 > p1 + 1) /* skip "*" and "**" */ { for (s = p1 + 1; s < p2; ++s) @@ -6559,8 +6667,7 @@ struct sign { sign_T *sn_next; /* next sign in list */ - int sn_typenr; /* type number of sign (negative if not equal - to name) */ + int sn_typenr; /* type number of sign */ char_u *sn_name; /* name of sign */ char_u *sn_icon; /* name of pixmap */ #ifdef FEAT_SIGN_ICONS @@ -6572,7 +6679,7 @@ }; static sign_T *first_sign = NULL; -static int last_sign_typenr = MAX_TYPENR; /* is decremented */ +static int next_sign_typenr = 1; static int sign_cmd_idx __ARGS((char_u *begin_cmd, char_u *end_cmd)); static void sign_list_defined __ARGS((sign_T *sp)); @@ -6647,16 +6754,21 @@ if (idx == SIGNCMD_LIST && *arg == NUL) { /* ":sign list": list all defined signs */ - for (sp = first_sign; sp != NULL; sp = sp->sn_next) + for (sp = first_sign; sp != NULL && !got_int; sp = sp->sn_next) sign_list_defined(sp); } else if (*arg == NUL) EMSG(_("E156: Missing sign name")); else { + /* Isolate the sign name. If it's a number skip leading zeroes, + * so that "099" and "99" are the same sign. But keep "0". */ p = skiptowhite(arg); if (*p != NUL) *p++ = NUL; + while (arg[0] == '0' && arg[1] != NUL) + ++arg; + sp_prev = NULL; for (sp = first_sign; sp != NULL; sp = sp->sn_next) { @@ -6669,46 +6781,52 @@ /* ":sign define {name} ...": define a sign */ if (sp == NULL) { + sign_T *lp; + int start = next_sign_typenr; + /* Allocate a new sign. */ sp = (sign_T *)alloc_clear((unsigned)sizeof(sign_T)); if (sp == NULL) return; - if (sp_prev == NULL) - first_sign = sp; - else - sp_prev->sn_next = sp; - sp->sn_name = vim_strnsave(arg, (int)(p - arg)); - /* If the name is a number use that for the typenr, - * otherwise use a negative number. */ - if (VIM_ISDIGIT(*arg)) - sp->sn_typenr = atoi((char *)arg); - else + /* Check that next_sign_typenr is not already being used. + * This only happens after wrapping around. Hopefully + * another one got deleted and we can use its number. */ + for (lp = first_sign; lp != NULL; ) { - sign_T *lp; - int start = last_sign_typenr; - - for (lp = first_sign; lp != NULL; lp = lp->sn_next) + if (lp->sn_typenr == next_sign_typenr) { - if (lp->sn_typenr == last_sign_typenr) + ++next_sign_typenr; + if (next_sign_typenr == MAX_TYPENR) + next_sign_typenr = 1; + if (next_sign_typenr == start) { - --last_sign_typenr; - if (last_sign_typenr == 0) - last_sign_typenr = MAX_TYPENR; - if (last_sign_typenr == start) - { - EMSG(_("E612: Too many signs defined")); - return; - } - lp = first_sign; - continue; + vim_free(sp); + EMSG(_("E612: Too many signs defined")); + return; } + lp = first_sign; /* start all over */ + continue; } + lp = lp->sn_next; + } + + sp->sn_typenr = next_sign_typenr; + if (++next_sign_typenr == MAX_TYPENR) + next_sign_typenr = 1; /* wrap around */ - sp->sn_typenr = last_sign_typenr--; - if (last_sign_typenr == 0) - last_sign_typenr = MAX_TYPENR; /* wrap around */ + sp->sn_name = vim_strsave(arg); + if (sp->sn_name == NULL) /* out of memory */ + { + vim_free(sp); + return; } + + /* add the new sign to the list of signs */ + if (sp_prev == NULL) + first_sign = sp; + else + sp_prev->sn_next = sp; } /* set values for a defined sign. */ @@ -6879,6 +6997,16 @@ lnum = atoi((char *)arg); arg = skiptowhite(arg); } + else if (STRNCMP(arg, "*", 1) == 0 && idx == SIGNCMD_UNPLACE) + { + if (id != -1) + { + EMSG(_(e_invarg)); + return; + } + id = -2; + arg = skiptowhite(arg + 1); + } else if (STRNCMP(arg, "name=", 5) == 0) { arg += 5; @@ -6886,6 +7014,8 @@ arg = skiptowhite(arg); if (*arg != NUL) *arg++ = NUL; + while (sign_name[0] == '0' && sign_name[1] != NUL) + ++sign_name; } else if (STRNCMP(arg, "file=", 5) == 0) { @@ -6913,7 +7043,7 @@ { EMSG2(_("E158: Invalid buffer name: %s"), arg); } - else if (id <= 0) + else if (id <= 0 && !(idx == SIGNCMD_UNPLACE && id == -2)) { if (lnum >= 0 || sign_name != NULL) EMSG(_(e_invarg)); @@ -6954,11 +7084,17 @@ } else if (idx == SIGNCMD_UNPLACE) { - /* ":sign unplace {id} file={fname}" */ if (lnum >= 0 || sign_name != NULL) EMSG(_(e_invarg)); + else if (id == -2) + { + /* ":sign unplace * file={fname}" */ + redraw_buf_later(buf, NOT_VALID); + buf_delete_signs(buf); + } else { + /* ":sign unplace {id} file={fname}" */ lnum = buf_delsign(buf, id); update_debug_sign(buf, lnum); } diff -Naur vim73.orig/src/ex_cmds.h vim73/src/ex_cmds.h --- vim73.orig/src/ex_cmds.h 2010-07-21 13:48:02.000000000 +0000 +++ vim73/src/ex_cmds.h 2012-07-20 20:31:17.920978216 +0000 @@ -102,7 +102,7 @@ EX(CMD_aboveleft, "aboveleft", ex_wrongmodifier, NEEDARG|EXTRA|NOTRLCOM), EX(CMD_all, "all", ex_all, - RANGE|NOTADR|COUNT|TRLBAR), + BANG|RANGE|NOTADR|COUNT|TRLBAR), EX(CMD_amenu, "amenu", ex_menu, RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN), EX(CMD_anoremenu, "anoremenu", ex_menu, @@ -304,7 +304,7 @@ EX(CMD_display, "display", ex_display, EXTRA|NOTRLCOM|TRLBAR|SBOXOK|CMDWIN), EX(CMD_diffupdate, "diffupdate", ex_diffupdate, - TRLBAR), + BANG|TRLBAR), EX(CMD_diffget, "diffget", ex_diffgetput, RANGE|EXTRA|TRLBAR|MODIFY), EX(CMD_diffoff, "diffoff", ex_diffoff, @@ -788,7 +788,7 @@ EX(CMD_rubyfile, "rubyfile", ex_rubyfile, RANGE|FILE1|NEEDARG|CMDWIN), EX(CMD_rundo, "rundo", ex_rundo, - NEEDARG|EXTRA|XFILE), + NEEDARG|FILE1), EX(CMD_rviminfo, "rviminfo", ex_viminfo, BANG|FILE1|TRLBAR|CMDWIN), EX(CMD_substitute, "substitute", do_sub, @@ -798,7 +798,7 @@ EX(CMD_sargument, "sargument", ex_argument, BANG|RANGE|NOTADR|COUNT|EXTRA|EDITCMD|ARGOPT|TRLBAR), EX(CMD_sall, "sall", ex_all, - RANGE|NOTADR|COUNT|TRLBAR), + BANG|RANGE|NOTADR|COUNT|TRLBAR), EX(CMD_sandbox, "sandbox", ex_wrongmodifier, NEEDARG|EXTRA|NOTRLCOM), EX(CMD_saveas, "saveas", ex_write, @@ -944,7 +944,7 @@ EX(CMD_tabfirst, "tabfirst", ex_tabnext, TRLBAR), EX(CMD_tabmove, "tabmove", ex_tabmove, - RANGE|NOTADR|ZEROR|COUNT|TRLBAR|ZEROR), + RANGE|NOTADR|ZEROR|EXTRA|NOSPC|TRLBAR), EX(CMD_tablast, "tablast", ex_tabnext, TRLBAR), EX(CMD_tabnext, "tabnext", ex_tabnext, @@ -1078,7 +1078,7 @@ EX(CMD_wsverb, "wsverb", ex_wsverb, EXTRA|NOTADR|NEEDARG), EX(CMD_wundo, "wundo", ex_wundo, - BANG|NEEDARG|EXTRA|XFILE), + BANG|NEEDARG|FILE1), EX(CMD_wviminfo, "wviminfo", ex_viminfo, BANG|FILE1|TRLBAR|CMDWIN), EX(CMD_xit, "xit", ex_exit, diff -Naur vim73.orig/src/ex_cmds2.c vim73/src/ex_cmds2.c --- vim73.orig/src/ex_cmds2.c 2010-07-27 19:43:38.000000000 +0000 +++ vim73/src/ex_cmds2.c 2012-07-20 20:31:17.370977822 +0000 @@ -11,10 +11,6 @@ * ex_cmds2.c: some more functions for command line commands */ -#if defined(MSDOS) || defined(WIN16) || defined(WIN32) || defined(_WIN64) -# include "vimio.h" /* for mch_open(), must be before vim.h */ -#endif - #include "vim.h" #include "version.h" @@ -504,18 +500,10 @@ /* Expand the file name in the same way as do_source(). This means * doing it twice, so that $DIR/file gets expanded when $DIR is * "~/dir". */ -#ifdef RISCOS - q = mch_munge_fname(p); -#else q = expand_env_save(p); -#endif if (q == NULL) return FAIL; -#ifdef RISCOS - p = mch_munge_fname(q); -#else p = expand_env_save(q); -#endif vim_free(q); if (p == NULL) return FAIL; @@ -608,10 +596,15 @@ garray_T *gap; gap = &dbg_breakp; -#ifdef FEAT_PROFILE if (eap->cmdidx == CMD_profdel) + { +#ifdef FEAT_PROFILE gap = &prof_ga; +#else + ex_ni(eap); + return; #endif + } if (vim_isdigit(*eap->arg)) { @@ -694,10 +687,12 @@ for (i = 0; i < dbg_breakp.ga_len; ++i) { bp = &BREAKP(i); + if (bp->dbg_type == DBG_FILE) + home_replace(NULL, bp->dbg_name, NameBuff, MAXPATHL, TRUE); smsg((char_u *)_("%3d %s %s line %ld"), bp->dbg_nr, bp->dbg_type == DBG_FUNC ? "func" : "file", - bp->dbg_name, + bp->dbg_type == DBG_FUNC ? bp->dbg_name : NameBuff, (long)bp->dbg_lnum); } } @@ -1119,7 +1114,7 @@ static enum { PEXP_SUBCMD, /* expand :profile sub-commands */ - PEXP_FUNC, /* expand :profile func {funcname} */ + PEXP_FUNC /* expand :profile func {funcname} */ } pexpand_what; static char *pexpand_cmds[] = { @@ -1488,7 +1483,7 @@ #endif /* - * Ask the user what to do when abondoning a changed buffer. + * Ask the user what to do when abandoning a changed buffer. * Must check 'write' option first! */ void @@ -1496,9 +1491,10 @@ buf_T *buf; int checkall; /* may abandon all changed buffers */ { - char_u buff[IOSIZE]; + char_u buff[DIALOG_MSG_SIZE]; int ret; buf_T *buf2; + exarg_T ea; dialog_msg(buff, _("Save changes to \"%s\"?"), (buf->b_fname != NULL) ? @@ -1508,13 +1504,19 @@ else ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1); + /* Init ea pseudo-structure, this is needed for the check_overwrite() + * function. */ + ea.append = ea.forceit = FALSE; + if (ret == VIM_YES) { #ifdef FEAT_BROWSE /* May get file name, when there is none */ browse_save_fname(buf); #endif - if (buf->b_fname != NULL) /* didn't hit Cancel */ + if (buf->b_fname != NULL && check_overwrite(&ea, buf, + buf->b_fname, buf->b_ffname, FALSE) == OK) + /* didn't hit Cancel */ (void)buf_write_all(buf, FALSE); } else if (ret == VIM_NO) @@ -1542,7 +1544,9 @@ /* May get file name, when there is none */ browse_save_fname(buf2); #endif - if (buf2->b_fname != NULL) /* didn't hit Cancel */ + if (buf2->b_fname != NULL && check_overwrite(&ea, buf2, + buf2->b_fname, buf2->b_ffname, FALSE) == OK) + /* didn't hit Cancel */ (void)buf_write_all(buf2, FALSE); #ifdef FEAT_AUTOCMD /* an autocommand may have deleted the buffer */ @@ -1579,6 +1583,26 @@ || forceit); } +static void add_bufnum __ARGS((int *bufnrs, int *bufnump, int nr)); + +/* + * Add a buffer number to "bufnrs", unless it's already there. + */ + static void +add_bufnum(bufnrs, bufnump, nr) + int *bufnrs; + int *bufnump; + int nr; +{ + int i; + + for (i = 0; i < *bufnump; ++i) + if (bufnrs[i] == nr) + return; + bufnrs[*bufnump] = nr; + *bufnump = *bufnump + 1; +} + /* * Return TRUE if any buffer was changed and cannot be abandoned. * That changed buffer becomes the current buffer. @@ -1587,32 +1611,64 @@ check_changed_any(hidden) int hidden; /* Only check hidden buffers */ { + int ret = FALSE; buf_T *buf; int save; + int i; + int bufnum = 0; + int bufcount = 0; + int *bufnrs; #ifdef FEAT_WINDOWS + tabpage_T *tp; win_T *wp; #endif - for (;;) + for (buf = firstbuf; buf != NULL; buf = buf->b_next) + ++bufcount; + + if (bufcount == 0) + return FALSE; + + bufnrs = (int *)alloc(sizeof(int) * bufcount); + if (bufnrs == NULL) + return FALSE; + + /* curbuf */ + bufnrs[bufnum++] = curbuf->b_fnum; +#ifdef FEAT_WINDOWS + /* buf in curtab */ + FOR_ALL_WINDOWS(wp) + if (wp->w_buffer != curbuf) + add_bufnum(bufnrs, &bufnum, wp->w_buffer->b_fnum); + + /* buf in other tab */ + for (tp = first_tabpage; tp != NULL; tp = tp->tp_next) + if (tp != curtab) + for (wp = tp->tp_firstwin; wp != NULL; wp = wp->w_next) + add_bufnum(bufnrs, &bufnum, wp->w_buffer->b_fnum); +#endif + /* any other buf */ + for (buf = firstbuf; buf != NULL; buf = buf->b_next) + add_bufnum(bufnrs, &bufnum, buf->b_fnum); + + for (i = 0; i < bufnum; ++i) { - /* check curbuf first: if it was changed we can't abandon it */ - if (!hidden && curbufIsChanged()) - buf = curbuf; - else + buf = buflist_findnr(bufnrs[i]); + if (buf == NULL) + continue; + if ((!hidden || buf->b_nwindows == 0) && bufIsChanged(buf)) { - for (buf = firstbuf; buf != NULL; buf = buf->b_next) - if ((!hidden || buf->b_nwindows == 0) && bufIsChanged(buf)) - break; + /* Try auto-writing the buffer. If this fails but the buffer no + * longer exists it's not changed, that's OK. */ + if (check_changed(buf, p_awa, TRUE, FALSE, TRUE) && buf_valid(buf)) + break; /* didn't save - still changes */ } - if (buf == NULL) /* No buffers changed */ - return FALSE; - - /* Try auto-writing the buffer. If this fails but the buffer no - * longer exists it's not changed, that's OK. */ - if (check_changed(buf, p_awa, TRUE, FALSE, TRUE) && buf_valid(buf)) - break; /* didn't save - still changes */ } + if (i >= bufnum) + goto theend; + + ret = TRUE; exiting = FALSE; #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) /* @@ -1645,24 +1701,29 @@ #ifdef FEAT_WINDOWS /* Try to find a window that contains the buffer. */ if (buf != curbuf) - for (wp = firstwin; wp != NULL; wp = wp->w_next) + FOR_ALL_TAB_WINDOWS(tp, wp) if (wp->w_buffer == buf) { - win_goto(wp); + goto_tabpage_win(tp, wp); # ifdef FEAT_AUTOCMD /* Paranoia: did autocms wipe out the buffer with changes? */ if (!buf_valid(buf)) - return TRUE; + { + goto theend; + } # endif - break; + goto buf_found; } +buf_found: #endif /* Open the changed buffer in the current window. */ if (buf != curbuf) set_curbuf(buf, DOBUF_GOTO); - return TRUE; +theend: + vim_free(bufnrs); + return ret; } /* @@ -1789,22 +1850,28 @@ #if defined(FEAT_QUICKFIX) || defined(FEAT_SYN_HL) || defined(PROTO) /* * Parse a list of arguments (file names), expand them and return in - * "fnames[fcountp]". + * "fnames[fcountp]". When "wig" is TRUE, removes files matching 'wildignore'. * Return FAIL or OK. */ int -get_arglist_exp(str, fcountp, fnamesp) +get_arglist_exp(str, fcountp, fnamesp, wig) char_u *str; int *fcountp; char_u ***fnamesp; + int wig; { garray_T ga; int i; if (get_arglist(&ga, str) == FAIL) return FAIL; - i = gen_expand_wildcards(ga.ga_len, (char_u **)ga.ga_data, - fcountp, fnamesp, EW_FILE|EW_NOTFOUND); + if (wig == TRUE) + i = expand_wildcards(ga.ga_len, (char_u **)ga.ga_data, + fcountp, fnamesp, EW_FILE|EW_NOTFOUND); + else + i = gen_expand_wildcards(ga.ga_len, (char_u **)ga.ga_data, + fcountp, fnamesp, EW_FILE|EW_NOTFOUND); + ga_clear(&ga); return i; } @@ -1949,7 +2016,7 @@ } /* - * Return TRUE if window "win" is editing then file at the current argument + * Return TRUE if window "win" is editing the file at the current argument * index. */ static int @@ -2165,9 +2232,7 @@ { if (win_split(0, 0) == FAIL) return; -# ifdef FEAT_SCROLLBIND - curwin->w_p_scb = FALSE; -# endif + RESET_BINDING(curwin); } else #endif @@ -2422,7 +2487,7 @@ /* go to window "tp" */ if (!valid_tabpage(tp)) break; - goto_tabpage_tp(tp); + goto_tabpage_tp(tp, TRUE); tp = tp->tp_next; } #endif @@ -2946,11 +3011,7 @@ proftime_T wait_start; #endif -#ifdef RISCOS - p = mch_munge_fname(fname); -#else p = expand_env_save(fname); -#endif if (p == NULL) return retval; fname_exp = fix_fname(p); @@ -3286,7 +3347,11 @@ for (i = 1; i <= script_items.ga_len && !got_int; ++i) if (SCRIPT_ITEM(i).sn_name != NULL) - smsg((char_u *)"%3d: %s", i, SCRIPT_ITEM(i).sn_name); + { + home_replace(NULL, SCRIPT_ITEM(i).sn_name, + NameBuff, MAXPATHL, TRUE); + smsg((char_u *)"%3d: %s", i, NameBuff); + } } # if defined(BACKSLASH_IN_FILENAME) || defined(PROTO) @@ -3412,7 +3477,7 @@ { struct source_cookie *sp = (struct source_cookie *)cookie; char_u *line; - char_u *p, *s; + char_u *p; #ifdef FEAT_EVAL /* If breakpoints have been added/deleted need to check for it. */ @@ -3451,28 +3516,49 @@ { /* compensate for the one line read-ahead */ --sourcing_lnum; - for (;;) - { - sp->nextline = get_one_sourceline(sp); - if (sp->nextline == NULL) - break; - p = skipwhite(sp->nextline); - if (*p != '\\') - break; - s = alloc((unsigned)(STRLEN(line) + STRLEN(p))); - if (s == NULL) /* out of memory */ - break; - STRCPY(s, line); - STRCAT(s, p + 1); + + /* Get the next line and concatenate it when it starts with a + * backslash. We always need to read the next line, keep it in + * sp->nextline. */ + sp->nextline = get_one_sourceline(sp); + if (sp->nextline != NULL && *(p = skipwhite(sp->nextline)) == '\\') + { + garray_T ga; + + ga_init2(&ga, (int)sizeof(char_u), 400); + ga_concat(&ga, line); + ga_concat(&ga, p + 1); + for (;;) + { + vim_free(sp->nextline); + sp->nextline = get_one_sourceline(sp); + if (sp->nextline == NULL) + break; + p = skipwhite(sp->nextline); + if (*p != '\\') + break; + /* Adjust the growsize to the current length to speed up + * concatenating many lines. */ + if (ga.ga_len > 400) + { + if (ga.ga_len > 8000) + ga.ga_growsize = 8000; + else + ga.ga_growsize = ga.ga_len; + } + ga_concat(&ga, p + 1); + } + ga_append(&ga, NUL); vim_free(line); - line = s; - vim_free(sp->nextline); + line = ga.ga_data; } } #ifdef FEAT_MBYTE if (line != NULL && sp->conv.vc_type != CONV_NONE) { + char_u *s; + /* Convert the encoding of the script line. */ s = string_convert(&sp->conv, line, NULL); if (s != NULL) @@ -4166,11 +4252,90 @@ /* Set v:lang, v:lc_time and v:ctype to the final result. */ set_lang_var(); # endif +# ifdef FEAT_TITLE + maketitle(); +# endif } } } # if defined(FEAT_CMDL_COMPL) || defined(PROTO) + +static char_u **locales = NULL; /* Array of all available locales */ +static int did_init_locales = FALSE; + +static void init_locales __ARGS((void)); +static char_u **find_locales __ARGS((void)); + +/* + * Lazy initialization of all available locales. + */ + static void +init_locales() +{ + if (!did_init_locales) + { + did_init_locales = TRUE; + locales = find_locales(); + } +} + +/* Return an array of strings for all available locales + NULL for the + * last element. Return NULL in case of error. */ + static char_u ** +find_locales() +{ + garray_T locales_ga; + char_u *loc; + + /* Find all available locales by running command "locale -a". If this + * doesn't work we won't have completion. */ + char_u *locale_a = get_cmd_output((char_u *)"locale -a", + NULL, SHELL_SILENT); + if (locale_a == NULL) + return NULL; + ga_init2(&locales_ga, sizeof(char_u *), 20); + + /* Transform locale_a string where each locale is separated by "\n" + * into an array of locale strings. */ + loc = (char_u *)strtok((char *)locale_a, "\n"); + + while (loc != NULL) + { + if (ga_grow(&locales_ga, 1) == FAIL) + break; + loc = vim_strsave(loc); + if (loc == NULL) + break; + + ((char_u **)locales_ga.ga_data)[locales_ga.ga_len++] = loc; + loc = (char_u *)strtok(NULL, "\n"); + } + vim_free(locale_a); + if (ga_grow(&locales_ga, 1) == FAIL) + { + ga_clear(&locales_ga); + return NULL; + } + ((char_u **)locales_ga.ga_data)[locales_ga.ga_len] = NULL; + return (char_u **)locales_ga.ga_data; +} + +# if defined(EXITFREE) || defined(PROTO) + void +free_locales() +{ + int i; + if (locales != NULL) + { + for (i = 0; locales[i] != NULL; i++) + vim_free(locales[i]); + vim_free(locales); + locales = NULL; + } +} +# endif + /* * Function given to ExpandGeneric() to obtain the possible arguments of the * ":language" command. @@ -4186,7 +4351,25 @@ return (char_u *)"ctype"; if (idx == 2) return (char_u *)"time"; - return NULL; + + init_locales(); + if (locales == NULL) + return NULL; + return locales[idx - 3]; +} + +/* + * Function given to ExpandGeneric() to obtain the available locales. + */ + char_u * +get_locales(xp, idx) + expand_T *xp UNUSED; + int idx; +{ + init_locales(); + if (locales == NULL) + return NULL; + return locales[idx]; } # endif diff -Naur vim73.orig/src/ex_docmd.c vim73/src/ex_docmd.c --- vim73.orig/src/ex_docmd.c 2010-08-07 14:59:47.000000000 +0000 +++ vim73/src/ex_docmd.c 2012-07-20 20:31:18.217645094 +0000 @@ -61,6 +61,7 @@ static char_u *do_one_cmd __ARGS((char_u **, int, char_u *(*fgetline)(int, void *, int), void *cookie)); static int if_level = 0; /* depth in :if */ #endif +static void append_command __ARGS((char_u *cmd)); static char_u *find_command __ARGS((exarg_T *eap, int *full)); static void ex_abbreviate __ARGS((exarg_T *eap)); @@ -370,11 +371,9 @@ # define ex_endif ex_ni # define ex_else ex_ni # define ex_while ex_ni -# define ex_for ex_ni # define ex_continue ex_ni # define ex_break ex_ni # define ex_endwhile ex_ni -# define ex_endfor ex_ni # define ex_throw ex_ni # define ex_try ex_ni # define ex_catch ex_ni @@ -733,7 +732,7 @@ * do_cmdline(): execute one Ex command line * * 1. Execute "cmdline" when it is not NULL. - * If "cmdline" is NULL, or more lines are needed, getline() is used. + * If "cmdline" is NULL, or more lines are needed, fgetline() is used. * 2. Split up in parts separated with '|'. * * This function can be called recursively! @@ -741,7 +740,7 @@ * flags: * DOCMD_VERBOSE - The command will be included in the error message. * DOCMD_NOWAIT - Don't call wait_return() and friends. - * DOCMD_REPEAT - Repeat execution until getline() returns NULL. + * DOCMD_REPEAT - Repeat execution until fgetline() returns NULL. * DOCMD_KEYTYPED - Don't reset KeyTyped. * DOCMD_EXCRESET - Reset the exception environment (used for debugging). * DOCMD_KEEPLINE - Store first typed line (for repeating with "."). @@ -749,15 +748,15 @@ * return FAIL if cmdline could not be executed, OK otherwise */ int -do_cmdline(cmdline, getline, cookie, flags) +do_cmdline(cmdline, fgetline, cookie, flags) char_u *cmdline; - char_u *(*getline) __ARGS((int, void *, int)); - void *cookie; /* argument for getline() */ + char_u *(*fgetline) __ARGS((int, void *, int)); + void *cookie; /* argument for fgetline() */ int flags; { char_u *next_cmdline; /* next cmd to execute */ char_u *cmdline_copy = NULL; /* copy of cmd line */ - int used_getline = FALSE; /* used "getline" to obtain command */ + int used_getline = FALSE; /* used "fgetline" to obtain command */ static int recursive = 0; /* recursive depth */ int msg_didout_before_start = 0; int count = 0; /* line number count */ @@ -775,14 +774,14 @@ struct msglist **saved_msg_list = NULL; struct msglist *private_msg_list; - /* "getline" and "cookie" passed to do_one_cmd() */ + /* "fgetline" and "cookie" passed to do_one_cmd() */ char_u *(*cmd_getline) __ARGS((int, void *, int)); void *cmd_cookie; struct loop_cookie cmd_loop_cookie; void *real_cookie; int getline_is_func; #else -# define cmd_getline getline +# define cmd_getline fgetline # define cmd_cookie cookie #endif static int call_depth = 0; /* recursiveness */ @@ -822,10 +821,10 @@ cstack.cs_lflags = 0; ga_init2(&lines_ga, (int)sizeof(wcmd_T), 10); - real_cookie = getline_cookie(getline, cookie); + real_cookie = getline_cookie(fgetline, cookie); /* Inside a function use a higher nesting level. */ - getline_is_func = getline_equal(getline, cookie, get_func_line); + getline_is_func = getline_equal(fgetline, cookie, get_func_line); if (getline_is_func && ex_nesting_level == func_level(real_cookie)) ++ex_nesting_level; @@ -837,7 +836,7 @@ breakpoint = func_breakpoint(real_cookie); dbg_tick = func_dbg_tick(real_cookie); } - else if (getline_equal(getline, cookie, getsourceline)) + else if (getline_equal(fgetline, cookie, getsourceline)) { fname = sourcing_name; breakpoint = source_breakpoint(real_cookie); @@ -881,7 +880,8 @@ * KeyTyped is only set when calling vgetc(). Reset it here when not * calling vgetc() (sourced command lines). */ - if (!(flags & DOCMD_KEYTYPED) && !getline_equal(getline, cookie, getexline)) + if (!(flags & DOCMD_KEYTYPED) + && !getline_equal(fgetline, cookie, getexline)) KeyTyped = FALSE; /* @@ -894,7 +894,7 @@ do { #ifdef FEAT_EVAL - getline_is_func = getline_equal(getline, cookie, get_func_line); + getline_is_func = getline_equal(fgetline, cookie, get_func_line); #endif /* stop skipping cmds for an error msg after all endif/while/for */ @@ -909,7 +909,7 @@ /* * 1. If repeating a line in a loop, get a line from lines_ga. - * 2. If no line given: Get an allocated line with getline(). + * 2. If no line given: Get an allocated line with fgetline(). * 3. If a line is given: Make a copy, so we can mess with it. */ @@ -938,12 +938,12 @@ } #ifdef FEAT_PROFILE else if (do_profiling == PROF_YES - && getline_equal(getline, cookie, getsourceline)) + && getline_equal(fgetline, cookie, getsourceline)) script_line_end(); #endif /* Check if a sourced file hit a ":finish" command. */ - if (source_finished(getline, cookie)) + if (source_finished(fgetline, cookie)) { retval = FAIL; break; @@ -954,7 +954,7 @@ && *dbg_tick != debug_tick) { *breakpoint = dbg_find_breakpoint( - getline_equal(getline, cookie, getsourceline), + getline_equal(fgetline, cookie, getsourceline), fname, sourcing_lnum); *dbg_tick = debug_tick; } @@ -969,7 +969,7 @@ dbg_breakpoint(fname, sourcing_lnum); /* Find next breakpoint. */ *breakpoint = dbg_find_breakpoint( - getline_equal(getline, cookie, getsourceline), + getline_equal(fgetline, cookie, getsourceline), fname, sourcing_lnum); *dbg_tick = debug_tick; } @@ -978,7 +978,7 @@ { if (getline_is_func) func_line_start(real_cookie); - else if (getline_equal(getline, cookie, getsourceline)) + else if (getline_equal(fgetline, cookie, getsourceline)) script_line_start(); } # endif @@ -987,7 +987,7 @@ if (cstack.cs_looplevel > 0) { /* Inside a while/for loop we need to store the lines and use them - * again. Pass a different "getline" function to do_one_cmd() + * again. Pass a different "fgetline" function to do_one_cmd() * below, so that it stores lines in or reads them from * "lines_ga". Makes it possible to define a function inside a * while/for loop. */ @@ -995,27 +995,27 @@ cmd_cookie = (void *)&cmd_loop_cookie; cmd_loop_cookie.lines_gap = &lines_ga; cmd_loop_cookie.current_line = current_line; - cmd_loop_cookie.getline = getline; + cmd_loop_cookie.getline = fgetline; cmd_loop_cookie.cookie = cookie; cmd_loop_cookie.repeating = (current_line < lines_ga.ga_len); } else { - cmd_getline = getline; + cmd_getline = fgetline; cmd_cookie = cookie; } #endif - /* 2. If no line given, get an allocated line with getline(). */ + /* 2. If no line given, get an allocated line with fgetline(). */ if (next_cmdline == NULL) { /* * Need to set msg_didout for the first line after an ":if", * otherwise the ":if" will be overwritten. */ - if (count == 1 && getline_equal(getline, cookie, getexline)) + if (count == 1 && getline_equal(fgetline, cookie, getexline)) msg_didout = TRUE; - if (getline == NULL || (next_cmdline = getline(':', cookie, + if (fgetline == NULL || (next_cmdline = fgetline(':', cookie, #ifdef FEAT_EVAL cstack.cs_idx < 0 ? 0 : (cstack.cs_idx + 1) * 2 #else @@ -1142,7 +1142,7 @@ * If the command was typed, remember it for the ':' register. * Do this AFTER executing the command to make :@: work. */ - if (getline_equal(getline, cookie, getexline) + if (getline_equal(fgetline, cookie, getexline) && new_last_cmdline != NULL) { vim_free(last_cmdline); @@ -1163,7 +1163,7 @@ #ifdef FEAT_EVAL /* reset did_emsg for a function that is not aborted by an error */ if (did_emsg && !force_abort - && getline_equal(getline, cookie, get_func_line) + && getline_equal(fgetline, cookie, get_func_line) && !func_has_abort(real_cookie)) did_emsg = FALSE; @@ -1202,7 +1202,7 @@ if (breakpoint != NULL) { *breakpoint = dbg_find_breakpoint( - getline_equal(getline, cookie, getsourceline), + getline_equal(fgetline, cookie, getsourceline), fname, ((wcmd_T *)lines_ga.ga_data)[current_line].lnum-1); *dbg_tick = debug_tick; @@ -1296,8 +1296,8 @@ #endif ) && !(did_emsg && used_getline - && (getline_equal(getline, cookie, getexmodeline) - || getline_equal(getline, cookie, getexline))) + && (getline_equal(fgetline, cookie, getexmodeline) + || getline_equal(fgetline, cookie, getexline))) && (next_cmdline != NULL #ifdef FEAT_EVAL || cstack.cs_idx >= 0 @@ -1316,9 +1316,9 @@ * unclosed conditional. */ if (!got_int && !did_throw - && ((getline_equal(getline, cookie, getsourceline) - && !source_finished(getline, cookie)) - || (getline_equal(getline, cookie, get_func_line) + && ((getline_equal(fgetline, cookie, getsourceline) + && !source_finished(fgetline, cookie)) + || (getline_equal(fgetline, cookie, get_func_line) && !func_has_ended(real_cookie)))) { if (cstack.cs_flags[cstack.cs_idx] & CSF_TRY) @@ -1354,7 +1354,7 @@ /* If a missing ":endtry", ":endwhile", ":endfor", or ":endif" or a memory * lack was reported above and the error message is to be converted to an * exception, do this now after rewinding the cstack. */ - do_errthrow(&cstack, getline_equal(getline, cookie, get_func_line) + do_errthrow(&cstack, getline_equal(fgetline, cookie, get_func_line) ? (char_u *)"endfunction" : (char_u *)NULL); if (trylevel == 0) @@ -1449,9 +1449,9 @@ */ if (did_throw) need_rethrow = TRUE; - if ((getline_equal(getline, cookie, getsourceline) + if ((getline_equal(fgetline, cookie, getsourceline) && ex_nesting_level > source_level(real_cookie)) - || (getline_equal(getline, cookie, get_func_line) + || (getline_equal(fgetline, cookie, get_func_line) && ex_nesting_level > func_level(real_cookie) + 1)) { if (!did_throw) @@ -1460,16 +1460,16 @@ else { /* When leaving a function, reduce nesting level. */ - if (getline_equal(getline, cookie, get_func_line)) + if (getline_equal(fgetline, cookie, get_func_line)) --ex_nesting_level; /* * Go to debug mode when returning from a function in which we are * single-stepping. */ - if ((getline_equal(getline, cookie, getsourceline) - || getline_equal(getline, cookie, get_func_line)) + if ((getline_equal(fgetline, cookie, getsourceline) + || getline_equal(fgetline, cookie, get_func_line)) && ex_nesting_level + 1 <= debug_break_level) - do_debug(getline_equal(getline, cookie, getsourceline) + do_debug(getline_equal(fgetline, cookie, getsourceline) ? (char_u *)_("End of sourced file") : (char_u *)_("End of function")); } @@ -2135,10 +2135,7 @@ { STRCPY(IObuff, _("E492: Not an editor command")); if (!sourcing) - { - STRCAT(IObuff, ": "); - STRNCAT(IObuff, *cmdlinep, 40); - } + append_command(*cmdlinep); errormsg = IObuff; } goto doend; @@ -2423,25 +2420,39 @@ if ( (ea.argt & REGSTR) && *ea.arg != NUL #ifdef FEAT_USR_CMDS - && valid_yank_reg(*ea.arg, (ea.cmdidx != CMD_put - && USER_CMDIDX(ea.cmdidx))) /* Do not allow register = for user commands */ && (!USER_CMDIDX(ea.cmdidx) || *ea.arg != '=') -#else - && valid_yank_reg(*ea.arg, ea.cmdidx != CMD_put) #endif && !((ea.argt & COUNT) && VIM_ISDIGIT(*ea.arg))) { - ea.regname = *ea.arg++; -#ifdef FEAT_EVAL - /* for '=' register: accept the rest of the line as an expression */ - if (ea.arg[-1] == '=' && ea.arg[0] != NUL) +#ifndef FEAT_CLIPBOARD + /* check these explicitly for a more specific error message */ + if (*ea.arg == '*' || *ea.arg == '+') { - set_expr_line(vim_strsave(ea.arg)); - ea.arg += STRLEN(ea.arg); + errormsg = (char_u *)_(e_invalidreg); + goto doend; } #endif - ea.arg = skipwhite(ea.arg); + if ( +#ifdef FEAT_USR_CMDS + valid_yank_reg(*ea.arg, (ea.cmdidx != CMD_put + && USER_CMDIDX(ea.cmdidx))) +#else + valid_yank_reg(*ea.arg, ea.cmdidx != CMD_put) +#endif + ) + { + ea.regname = *ea.arg++; +#ifdef FEAT_EVAL + /* for '=' register: accept the rest of the line as an expression */ + if (ea.arg[-1] == '=' && ea.arg[0] != NUL) + { + set_expr_line(vim_strsave(ea.arg)); + ea.arg += STRLEN(ea.arg); + } +#endif + ea.arg = skipwhite(ea.arg); + } } /* @@ -2580,6 +2591,7 @@ case CMD_unlet: case CMD_verbose: case CMD_vertical: + case CMD_wincmd: break; default: goto doend; @@ -2692,8 +2704,7 @@ STRCPY(IObuff, errormsg); errormsg = IObuff; } - STRCAT(errormsg, ": "); - STRNCAT(errormsg, *cmdlinep, IOSIZE - STRLEN(IObuff) - 1); + append_command(*cmdlinep); } emsg(errormsg); } @@ -2781,6 +2792,42 @@ } /* + * Append "cmd" to the error message in IObuff. + * Takes care of limiting the length and handling 0xa0, which would be + * invisible otherwise. + */ + static void +append_command(cmd) + char_u *cmd; +{ + char_u *s = cmd; + char_u *d; + + STRCAT(IObuff, ": "); + d = IObuff + STRLEN(IObuff); + while (*s != NUL && d - IObuff < IOSIZE - 7) + { + if ( +#ifdef FEAT_MBYTE + enc_utf8 ? (s[0] == 0xc2 && s[1] == 0xa0) : +#endif + *s == 0xa0) + { + s += +#ifdef FEAT_MBYTE + enc_utf8 ? 2 : +#endif + 1; + STRCPY(d, ""); + d += 4; + } + else + MB_COPY_CHAR(s, d); + } + *d = NUL; +} + +/* * Find an Ex command by its name, either built-in or user. * Start of the name can be found at eap->cmd. * Returns pointer to char after the command name. @@ -2871,8 +2918,10 @@ } #ifdef FEAT_USR_CMDS - /* Look for a user defined command as a last resort */ - if (eap->cmdidx == CMD_SIZE && *eap->cmd >= 'A' && *eap->cmd <= 'Z') + /* Look for a user defined command as a last resort. Let ":Print" be + * overruled by a user defined command. */ + if ((eap->cmdidx == CMD_SIZE || eap->cmdidx == CMD_Print) + && *eap->cmd >= 'A' && *eap->cmd <= 'Z') { /* User defined commands may contain digits. */ while (ASCII_ISALNUM(*p)) @@ -3465,7 +3514,8 @@ case CMD_find: case CMD_sfind: case CMD_tabfind: - xp->xp_context = EXPAND_FILES_IN_PATH; + if (xp->xp_context == EXPAND_FILES) + xp->xp_context = EXPAND_FILES_IN_PATH; break; case CMD_cd: case CMD_chdir: @@ -3843,13 +3893,24 @@ #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \ && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE)) case CMD_language: - if (*skiptowhite(arg) == NUL) + p = skiptowhite(arg); + if (*p == NUL) { xp->xp_context = EXPAND_LANGUAGE; xp->xp_pattern = arg; } else - xp->xp_context = EXPAND_NOTHING; + { + if ( STRNCMP(arg, "messages", p - arg) == 0 + || STRNCMP(arg, "ctype", p - arg) == 0 + || STRNCMP(arg, "time", p - arg) == 0) + { + xp->xp_context = EXPAND_LOCALES; + xp->xp_pattern = skipwhite(p); + } + else + xp->xp_context = EXPAND_NOTHING; + } break; #endif #if defined(FEAT_PROFILE) @@ -3859,8 +3920,16 @@ #endif case CMD_behave: xp->xp_context = EXPAND_BEHAVE; + xp->xp_pattern = arg; break; +#if defined(FEAT_CMDHIST) + case CMD_history: + xp->xp_context = EXPAND_HISTORY; + xp->xp_pattern = arg; + break; +#endif + #endif /* FEAT_CMDL_COMPL */ default: @@ -4520,12 +4589,14 @@ else /* n == 2 */ { expand_T xpc; + int options = WILD_LIST_NOTFOUND|WILD_ADD_SLASH; ExpandInit(&xpc); xpc.xp_context = EXPAND_FILES; + if (p_wic) + options += WILD_ICASE; p = ExpandOne(&xpc, eap->arg, NULL, - WILD_LIST_NOTFOUND|WILD_ADD_SLASH, - WILD_EXPAND_FREE); + options, WILD_EXPAND_FREE); if (p == NULL) return FAIL; } @@ -4777,12 +4848,10 @@ #ifdef FEAT_MBYTE else if (STRNCMP(arg, "enc", 3) == 0) { - arg += 3; - pp = &eap->force_enc; - } - else if (STRNCMP(arg, "encoding", 8) == 0) - { - arg += 8; + if (STRNCMP(arg, "encoding", 8) == 0) + arg += 8; + else + arg += 3; pp = &eap->force_enc; } else if (STRNCMP(arg, "bad", 3) == 0) @@ -4894,7 +4963,7 @@ map_clear(eap->cmd, eap->arg, TRUE, TRUE); } -#ifdef FEAT_AUTOCMD +#if defined(FEAT_AUTOCMD) || defined(PROTO) static void ex_autocmd(eap) exarg_T *eap; @@ -4921,8 +4990,12 @@ ex_doautocmd(eap) exarg_T *eap; { - (void)do_doautocmd(eap->arg, TRUE); - do_modelines(0); + char_u *arg = eap->arg; + int call_do_modelines = check_nomodeline(&arg); + + (void)do_doautocmd(arg, TRUE); + if (call_do_modelines) /* Only when there is no . */ + do_modelines(0); } #endif @@ -5087,12 +5160,14 @@ #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) if ((p_confirm || cmdmod.confirm) && curbuf->b_fname != NULL) { - char_u buff[IOSIZE]; + char_u buff[DIALOG_MSG_SIZE]; if (n == 1) - STRCPY(buff, _("1 more file to edit. Quit anyway?")); + vim_strncpy(buff, + (char_u *)_("1 more file to edit. Quit anyway?"), + DIALOG_MSG_SIZE - 1); else - vim_snprintf((char *)buff, IOSIZE, + vim_snprintf((char *)buff, DIALOG_MSG_SIZE, _("%d more files to edit. Quit anyway?"), n); if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 1) == VIM_YES) return OK; @@ -5262,8 +5337,11 @@ } command_complete[] = { {EXPAND_AUGROUP, "augroup"}, + {EXPAND_BEHAVE, "behave"}, {EXPAND_BUFFERS, "buffer"}, + {EXPAND_COLORS, "color"}, {EXPAND_COMMANDS, "command"}, + {EXPAND_COMPILER, "compiler"}, #if defined(FEAT_CSCOPE) {EXPAND_CSCOPE, "cscope"}, #endif @@ -5276,10 +5354,18 @@ {EXPAND_EVENTS, "event"}, {EXPAND_EXPRESSION, "expression"}, {EXPAND_FILES, "file"}, + {EXPAND_FILES_IN_PATH, "file_in_path"}, {EXPAND_FILETYPE, "filetype"}, {EXPAND_FUNCTIONS, "function"}, {EXPAND_HELP, "help"}, {EXPAND_HIGHLIGHT, "highlight"}, +#if defined(FEAT_CMDHIST) + {EXPAND_HISTORY, "history"}, +#endif +#if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \ + && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE)) + {EXPAND_LOCALES, "locale"}, +#endif {EXPAND_MAPPINGS, "mapping"}, {EXPAND_MENUS, "menu"}, {EXPAND_OWNSYNTAX, "syntax"}, @@ -5587,6 +5673,7 @@ int compl = EXPAND_NOTHING; char_u *compl_arg = NULL; int has_attr = (eap->arg[0] == '-'); + int name_len; p = eap->arg; @@ -5612,6 +5699,7 @@ return; } end = p; + name_len = (int)(end - name); /* If there is nothing after the name, and no attributes were specified, * we are listing commands @@ -5626,6 +5714,13 @@ EMSG(_("E183: User defined commands must start with an uppercase letter")); return; } + else if ((name_len == 1 && *name == 'X') + || (name_len <= 4 + && STRNCMP(name, "Next", name_len > 4 ? 4 : name_len) == 0)) + { + EMSG(_("E841: Reserved name, cannot be used for user defined command")); + return; + } else uc_add_command(name, end - name, p, argt, def, flags, compl, compl_arg, eap->forceit); @@ -5750,8 +5845,14 @@ } else { +#ifdef FEAT_MBYTE + int charlen = (*mb_ptr2len)(p); + len += charlen; + p += charlen; +#else ++len; ++p; +#endif } } @@ -5794,7 +5895,7 @@ } else { - *q++ = *p++; + MB_COPY_CHAR(p, q); } } *q++ = '"'; @@ -5888,7 +5989,14 @@ result = STRLEN(eap->arg) + 2; for (p = eap->arg; *p; ++p) { - if (*p == '\\' || *p == '"') +#ifdef FEAT_MBYTE + if (enc_dbcs != 0 && (*mb_ptr2len)(p) == 2) + /* DBCS can contain \ in a trail byte, skip the + * double-byte character. */ + ++p; + else +#endif + if (*p == '\\' || *p == '"') ++result; } @@ -5897,7 +6005,14 @@ *buf++ = '"'; for (p = eap->arg; *p; ++p) { - if (*p == '\\' || *p == '"') +#ifdef FEAT_MBYTE + if (enc_dbcs != 0 && (*mb_ptr2len)(p) == 2) + /* DBCS can contain \ in a trail byte, copy the + * double-byte character to avoid escaping. */ + *buf++ = *p++; + else +#endif + if (*p == '\\' || *p == '"') *buf++ = '\\'; *buf++ = *p; } @@ -6039,15 +6154,17 @@ end = vim_strchr(start + 1, '>'); if (buf != NULL) { - ksp = vim_strchr(p, K_SPECIAL); - if (ksp != NULL && (start == NULL || ksp < start || end == NULL) + for (ksp = p; *ksp != NUL && *ksp != K_SPECIAL; ++ksp) + ; + if (*ksp == K_SPECIAL + && (start == NULL || ksp < start || end == NULL) && ((ksp[1] == KS_SPECIAL && ksp[2] == KE_FILLER) # ifdef FEAT_GUI || (ksp[1] == KS_EXTRA && ksp[2] == (int)KE_CSI) # endif )) { - /* K_SPECIAL han been put in the buffer as K_SPECIAL + /* K_SPECIAL has been put in the buffer as K_SPECIAL * KS_SPECIAL KE_FILLER, like for mappings, but * do_cmdline() doesn't handle that, so convert it back. * Also change K_SPECIAL KS_EXTRA KE_CSI into CSI. */ @@ -6347,7 +6464,10 @@ return; } #ifdef FEAT_AUTOCMD - if (curbuf_locked()) + apply_autocmds(EVENT_QUITPRE, NULL, NULL, FALSE, curbuf); + /* Refuse to quick when locked or when the buffer in the last window is + * being closed (can only happen in autocommands). */ + if (curbuf_locked() || (curbuf->b_nwindows == 1 && curbuf->b_closing)) return; #endif @@ -6439,7 +6559,7 @@ { # ifdef FEAT_CMDWIN if (cmdwin_type != 0) - cmdwin_result = K_IGNORE; + cmdwin_result = Ctrl_C; else # endif if (!text_locked() @@ -6897,9 +7017,7 @@ # ifdef FEAT_WINDOWS if (win_split(0, 0) == FAIL) return; -# ifdef FEAT_SCROLLBIND - curwin->w_p_scb = FALSE; -# endif + RESET_BINDING(curwin); /* When splitting the window, create a new alist. Otherwise the * existing one is overwritten. */ @@ -7026,7 +7144,7 @@ old_arg_count = GARGCOUNT; if (expand_wildcards(old_arg_count, old_arg_files, &new_arg_file_count, &new_arg_files, - EW_FILE|EW_NOTFOUND|EW_ADDSLASH) == OK + EW_FILE|EW_NOTFOUND|EW_ADDSLASH|EW_NOERROR) == OK && new_arg_file_count > 0) { alist_set(&global_alist, new_arg_file_count, new_arg_files, @@ -7299,7 +7417,9 @@ || cmdmod.browse # endif ) - curwin->w_p_scb = FALSE; + { + RESET_BINDING(curwin); + } else do_check_scrollbind(FALSE); # endif @@ -7364,7 +7484,42 @@ ex_tabmove(eap) exarg_T *eap; { - tabpage_move(eap->addr_count == 0 ? 9999 : (int)eap->line2); + int tab_number = 9999; + + if (eap->arg && *eap->arg != NUL) + { + char_u *p = eap->arg; + int relative = 0; /* argument +N/-N means: move N places to the + * right/left relative to the current position. */ + + if (*eap->arg == '-') + { + relative = -1; + p = eap->arg + 1; + } + else if (*eap->arg == '+') + { + relative = 1; + p = eap->arg + 1; + } + else + p = eap->arg; + + if (p == skipdigits(p)) + { + /* No numbers as argument. */ + eap->errmsg = e_invarg; + return; + } + + tab_number = getdigits(&p); + if (relative != 0) + tab_number = tab_number * relative + tabpage_index(curtab) - 1;; + } + else if (eap->addr_count != 0) + tab_number = eap->line2; + + tabpage_move(tab_number); } /* @@ -8122,6 +8277,12 @@ { ui_delay(msec - done > 1000L ? 1000L : msec - done, TRUE); ui_breakcheck(); +#ifdef FEAT_NETBEANS_INTG + /* Process the netbeans messages that may have been received in the + * call to ui_breakcheck() when the GUI is in use. This may occur when + * running a test case. */ + netbeans_parse_messages(); +#endif } } @@ -8193,7 +8354,7 @@ p = skipwhite(p); if (*p != NUL && *p != '"' && eap->nextcmd == NULL) EMSG(_(e_invarg)); - else + else if (!eap->skip) { /* Pass flags on for ":vertical wincmd ]". */ postponed_split_flags = cmdmod.split; @@ -8428,7 +8589,7 @@ } ++eap->line2; } - (void)do_join(eap->line2 - eap->line1 + 1, !eap->forceit, TRUE); + (void)do_join(eap->line2 - eap->line1 + 1, !eap->forceit, TRUE, TRUE); beginline(BL_WHITE | BL_FIX); ex_may_print(eap); } @@ -8907,35 +9068,42 @@ failed = TRUE; if (eap->cmdidx == CMD_mksession) { - char_u dirnow[MAXPATHL]; /* current directory */ + char_u *dirnow; /* current directory */ - /* - * Change to session file's dir. - */ - if (mch_dirname(dirnow, MAXPATHL) == FAIL - || mch_chdir((char *)dirnow) != 0) - *dirnow = NUL; - if (*dirnow != NUL && (ssop_flags & SSOP_SESDIR)) - { - if (vim_chdirfile(fname) == OK) - shorten_fnames(TRUE); - } - else if (*dirnow != NUL - && (ssop_flags & SSOP_CURDIR) && globaldir != NULL) + dirnow = alloc(MAXPATHL); + if (dirnow == NULL) + failed = TRUE; + else { - if (mch_chdir((char *)globaldir) == 0) - shorten_fnames(TRUE); - } + /* + * Change to session file's dir. + */ + if (mch_dirname(dirnow, MAXPATHL) == FAIL + || mch_chdir((char *)dirnow) != 0) + *dirnow = NUL; + if (*dirnow != NUL && (ssop_flags & SSOP_SESDIR)) + { + if (vim_chdirfile(fname) == OK) + shorten_fnames(TRUE); + } + else if (*dirnow != NUL + && (ssop_flags & SSOP_CURDIR) && globaldir != NULL) + { + if (mch_chdir((char *)globaldir) == 0) + shorten_fnames(TRUE); + } - failed |= (makeopens(fd, dirnow) == FAIL); + failed |= (makeopens(fd, dirnow) == FAIL); - /* restore original dir */ - if (*dirnow != NUL && ((ssop_flags & SSOP_SESDIR) + /* restore original dir */ + if (*dirnow != NUL && ((ssop_flags & SSOP_SESDIR) || ((ssop_flags & SSOP_CURDIR) && globaldir != NULL))) - { - if (mch_chdir((char *)dirnow) != 0) - EMSG(_(e_prev_dir)); - shorten_fnames(TRUE); + { + if (mch_chdir((char *)dirnow) != 0) + EMSG(_(e_prev_dir)); + shorten_fnames(TRUE); + } + vim_free(dirnow); } } else @@ -8966,10 +9134,15 @@ else if (eap->cmdidx == CMD_mksession) { /* successful session write - set this_session var */ - char_u tbuf[MAXPATHL]; + char_u *tbuf; - if (vim_FullName(fname, tbuf, MAXPATHL, FALSE) == OK) - set_vim_var_string(VV_THIS_SESSION, tbuf, -1); + tbuf = alloc(MAXPATHL); + if (tbuf != NULL) + { + if (vim_FullName(fname, tbuf, MAXPATHL, FALSE) == OK) + set_vim_var_string(VV_THIS_SESSION, tbuf, -1); + vim_free(tbuf); + } } #endif #ifdef MKSESSION_NL @@ -9295,7 +9468,7 @@ && !got_int) { update_topline_cursor(); - normal_cmd(&oa, FALSE); /* execute a Normal mode cmd */ + normal_cmd(&oa, TRUE); /* execute a Normal mode cmd */ } } #endif @@ -9393,7 +9566,7 @@ ex_ptag(eap) exarg_T *eap; { - g_do_tagpreview = p_pvh; + g_do_tagpreview = p_pvh; /* will be reset to 0 in ex_tag_cmd() */ ex_tag_cmd(eap, cmdnames[eap->cmdidx].cmd_name + 1); } @@ -9525,17 +9698,23 @@ #define SPEC_CFILE 4 "", /* ":so" file name */ #define SPEC_SFILE 5 + "", /* ":so" file line number */ +#define SPEC_SLNUM 6 #ifdef FEAT_AUTOCMD "", /* autocommand file name */ -# define SPEC_AFILE 6 +# define SPEC_AFILE 7 "", /* autocommand buffer number */ -# define SPEC_ABUF 7 +# define SPEC_ABUF 8 "", /* autocommand match name */ -# define SPEC_AMATCH 8 +# define SPEC_AMATCH 9 #endif #ifdef FEAT_CLIENTSERVER "" -# define SPEC_CLIENT 9 +# ifdef FEAT_AUTOCMD +# define SPEC_CLIENT 10 +# else +# define SPEC_CLIENT 7 +# endif #endif }; @@ -9560,6 +9739,7 @@ * '' to WORD under the cursor * '' to path name under the cursor * '' to sourced file name + * '' to sourced file line number * '' to file name for autocommand * '' to buffer number for autocommand * '' to matching name for autocommand @@ -9591,10 +9771,7 @@ #ifdef FEAT_MODIFY_FNAME int skip_mod = FALSE; #endif - -#if defined(FEAT_AUTOCMD) || defined(FEAT_CLIENTSERVER) char_u strbuf[30]; -#endif *errormsg = NULL; if (escaped != NULL) @@ -9653,14 +9830,7 @@ valid = 0; /* Must have ":p:h" to be valid */ } else -#ifdef RISCOS - /* Always use the full path for RISC OS if possible. */ - result = curbuf->b_ffname; - if (result == NULL) - result = curbuf->b_fname; -#else result = curbuf->b_fname; -#endif break; case SPEC_HASH: /* '#' or "#99": alternate file */ @@ -9783,6 +9953,15 @@ return NULL; } break; + case SPEC_SLNUM: /* line in file for ":so" command */ + if (sourcing_name == NULL || sourcing_lnum == 0) + { + *errormsg = (char_u *)_("E842: no line number to use for \"\""); + return NULL; + } + sprintf((char *)strbuf, "%ld", (long)sourcing_lnum); + result = strbuf; + break; #if defined(FEAT_CLIENTSERVER) case SPEC_CLIENT: /* Source of last submitted input */ sprintf((char *)strbuf, PRINTF_HEX_LONG_U, @@ -9796,11 +9975,7 @@ if (src[*usedlen] == '<') /* remove the file name extension */ { ++*usedlen; -#ifdef RISCOS - if ((s = vim_strrchr(result, '/')) != NULL && s >= gettail(result)) -#else if ((s = vim_strrchr(result, '.')) != NULL && s >= gettail(result)) -#endif resultlen = (int)(s - result); } #ifdef FEAT_MODIFY_FNAME @@ -10645,7 +10820,7 @@ unsigned *flagp; { int i; - char_u buf[MAXPATHL]; + char_u *buf = NULL; char_u *s; if (gap->ga_len == 0) @@ -10660,11 +10835,19 @@ { if (fullname) { - (void)vim_FullName(s, buf, MAXPATHL, FALSE); - s = buf; + buf = alloc(MAXPATHL); + if (buf != NULL) + { + (void)vim_FullName(s, buf, MAXPATHL, FALSE); + s = buf; + } } if (fputs(" ", fd) < 0 || ses_put_fname(fd, s, flagp) == FAIL) + { + vim_free(buf); return FAIL; + } + vim_free(buf); } } return put_eol(fd); @@ -10707,7 +10890,7 @@ * Write a file name to the session file. * Takes care of the "slash" option in 'sessionoptions' and escapes special * characters. - * Returns FAIL if writing fails. + * Returns FAIL if writing fails or out of memory. */ static int ses_put_fname(fd, name, flagp) @@ -10716,49 +10899,32 @@ unsigned *flagp; { char_u *sname; + char_u *p; int retval = OK; - int c; sname = home_replace_save(NULL, name); - if (sname != NULL) - name = sname; - while (*name != NUL) - { -#ifdef FEAT_MBYTE - { - int l; + if (sname == NULL) + return FAIL; - if (has_mbyte && (l = (*mb_ptr2len)(name)) > 1) - { - /* copy a multibyte char */ - while (--l >= 0) - { - if (putc(*name, fd) != *name) - retval = FAIL; - ++name; - } - continue; - } - } -#endif - c = *name++; - if (c == '\\' && (*flagp & SSOP_SLASH)) - /* change a backslash to a forward slash */ - c = '/'; - else if ((vim_strchr(escape_chars, c) != NULL -#ifdef BACKSLASH_IN_FILENAME - && c != '\\' -#endif - ) || c == '#' || c == '%') - { - /* escape a special character with a backslash */ - if (putc('\\', fd) != '\\') - retval = FAIL; - } - if (putc(c, fd) != c) - retval = FAIL; + if (*flagp & SSOP_SLASH) + { + /* change all backslashes to forward slashes */ + for (p = sname; *p != NUL; mb_ptr_adv(p)) + if (*p == '\\') + *p = '/'; } + + /* escapse special characters */ + p = vim_strsave_fnameescape(sname, FALSE); vim_free(sname); + if (p == NULL) + return FAIL; + + /* write the result */ + if (fputs((char *)p, fd) < 0) + retval = FAIL; + + vim_free(p); return retval; } @@ -10826,8 +10992,7 @@ else if (vim_ispathsep(*p)) { *s++ = '='; -#if defined(BACKSLASH_IN_FILENAME) || defined(AMIGA) || defined(RISCOS) \ - || defined(VMS) +#if defined(BACKSLASH_IN_FILENAME) || defined(AMIGA) || defined(VMS) if (*p == ':') *s++ = '-'; else @@ -10910,7 +11075,7 @@ #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) || defined(PROTO) /* - * Make a dialog message in "buff[IOSIZE]". + * Make a dialog message in "buff[DIALOG_MSG_SIZE]". * "format" must contain "%s". */ void @@ -10921,7 +11086,7 @@ { if (fname == NULL) fname = (char_u *)_("Untitled"); - vim_snprintf((char *)buff, IOSIZE, format, fname); + vim_snprintf((char *)buff, DIALOG_MSG_SIZE, format, fname); } #endif diff -Naur vim73.orig/src/ex_getln.c vim73/src/ex_getln.c --- vim73.orig/src/ex_getln.c 2010-08-14 15:25:45.000000000 +0000 +++ vim73/src/ex_getln.c 2012-07-20 20:31:17.557644623 +0000 @@ -25,7 +25,7 @@ int cmdlen; /* number of chars in command line */ int cmdpos; /* current cursor position */ int cmdspos; /* cursor column on screen */ - int cmdfirstc; /* ':', '/', '?', '=' or NUL */ + int cmdfirstc; /* ':', '/', '?', '=', '>' or NUL */ int cmdindent; /* number of spaces before cmdline */ char_u *cmdprompt; /* message in front of cmdline */ int cmdattr; /* attributes for prompt */ @@ -67,7 +67,7 @@ static int hist_char2type __ARGS((int c)); -static int in_history __ARGS((int, char_u *, int)); +static int in_history __ARGS((int, char_u *, int, int)); # ifdef FEAT_EVAL static int calc_hist_idx __ARGS((int histype, int num)); # endif @@ -110,7 +110,10 @@ static int expand_showtail __ARGS((expand_T *xp)); #ifdef FEAT_CMDL_COMPL static int expand_shellcmd __ARGS((char_u *filepat, int *num_file, char_u ***file, int flagsarg)); -static int ExpandRTDir __ARGS((char_u *pat, int *num_file, char_u ***file, char *dirname)); +static int ExpandRTDir __ARGS((char_u *pat, int *num_file, char_u ***file, char *dirname[])); +# ifdef FEAT_CMDHIST +static char_u *get_history_arg __ARGS((expand_T *xp, int idx)); +# endif # if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL) static int ExpandUserDefined __ARGS((expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file)); static int ExpandUserList __ARGS((expand_T *xp, int *num_file, char_u ***file)); @@ -121,6 +124,14 @@ static int ex_window __ARGS((void)); #endif +#if defined(FEAT_CMDL_COMPL) || defined(PROTO) +static int +#ifdef __BORLANDC__ +_RTLENTRYF +#endif +sort_func_compare __ARGS((const void *s1, const void *s2)); +#endif + /* * getcmdline() - accept a command line starting with firstc. * @@ -637,7 +648,11 @@ } else if (ccline.cmdpos > i) cmdline_del(i); + + /* Now complete in the new directory. Set KeyTyped in case the + * Up key came from a mapping. */ c = p_wc; + KeyTyped = TRUE; } } @@ -688,28 +703,35 @@ p = get_expr_line(); --textlock; restore_cmdline(&save_ccline); - len = (int)STRLEN(p); - if (p != NULL && realloc_cmdbuff(len + 1) == OK) + if (p != NULL) { - ccline.cmdlen = len; - STRCPY(ccline.cmdbuff, p); - vim_free(p); - - /* Restore the cursor or use the position set with - * set_cmdline_pos(). */ - if (new_cmdpos > ccline.cmdlen) - ccline.cmdpos = ccline.cmdlen; - else - ccline.cmdpos = new_cmdpos; - - KeyTyped = FALSE; /* Don't do p_wc completion. */ - redrawcmd(); - goto cmdline_changed; + len = (int)STRLEN(p); + if (realloc_cmdbuff(len + 1) == OK) + { + ccline.cmdlen = len; + STRCPY(ccline.cmdbuff, p); + vim_free(p); + + /* Restore the cursor or use the position set with + * set_cmdline_pos(). */ + if (new_cmdpos > ccline.cmdlen) + ccline.cmdpos = ccline.cmdlen; + else + ccline.cmdpos = new_cmdpos; + + KeyTyped = FALSE; /* Don't do p_wc completion. */ + redrawcmd(); + goto cmdline_changed; + } } } beep_flush(); - c = ESC; + got_int = FALSE; /* don't abandon the command line */ + did_emsg = FALSE; + emsg_on_display = FALSE; + redrawcmd(); + goto cmdline_not_changed; } #endif else @@ -1833,8 +1855,11 @@ # endif ) /* Always redraw the whole command line to fix shaping and - * right-left typing. Not efficient, but it works. */ - redrawcmd(); + * right-left typing. Not efficient, but it works. + * Do it only when there are no characters left to read + * to avoid useless intermediate redraws. */ + if (vpeekc() == NUL) + redrawcmd(); #endif } @@ -1962,8 +1987,12 @@ # endif s = getcmdline(firstc, 1L, 0); restore_cmdline(&save_ccline); - /* Restore msg_col, the prompt from input() may have changed it. */ - msg_col = msg_col_save; + /* Restore msg_col, the prompt from input() may have changed it. + * But only if called recursively and the commandline is therefore being + * restored to an old one; if not, the input() prompt stays on the screen, + * so we need its modified msg_col left intact. */ + if (ccline.cmdbuff != NULL) + msg_col = msg_col_save; return s; } @@ -2342,15 +2371,31 @@ windgoto(msg_row, msg_col); pend = (char_u *)(line_ga.ga_data) + line_ga.ga_len; - /* we are done when a NL is entered, but not when it comes after a - * backslash */ - if (line_ga.ga_len > 0 && pend[-1] == '\n' - && (line_ga.ga_len <= 1 || pend[-2] != '\\')) - { - --line_ga.ga_len; - --pend; - *pend = NUL; - break; + /* We are done when a NL is entered, but not when it comes after an + * odd number of backslashes, that results in a NUL. */ + if (line_ga.ga_len > 0 && pend[-1] == '\n') + { + int bcount = 0; + + while (line_ga.ga_len - 2 >= bcount && pend[-2 - bcount] == '\\') + ++bcount; + + if (bcount > 0) + { + /* Halve the number of backslashes: "\NL" -> "NUL", "\\NL" -> + * "\NL", etc. */ + line_ga.ga_len -= (bcount + 1) / 2; + pend -= (bcount + 1) / 2; + pend[-1] = '\n'; + } + + if ((bcount & 1) == 0) + { + --line_ga.ga_len; + --pend; + *pend = NUL; + break; + } } } @@ -2719,6 +2764,11 @@ msg_no_more = TRUE; if (ccline.cmdlen == ccline.cmdpos) msg_putchar(' '); +#ifdef FEAT_MBYTE + else if (has_mbyte) + draw_cmdline(ccline.cmdpos, + (*mb_ptr2len)(ccline.cmdbuff + ccline.cmdpos)); +#endif else draw_cmdline(ccline.cmdpos, 1); msg_no_more = FALSE; @@ -2843,6 +2893,7 @@ { msg_no_more = TRUE; i = cmdline_row; + cursorcmd(); draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos); /* Avoid clearing the rest of the line too often. */ if (cmdline_row != i || ccline.overstrike) @@ -3023,7 +3074,7 @@ int len; /* Locate start of last word in the cmd buffer. */ - for (w = ccline.cmdbuff + ccline.cmdlen; w > ccline.cmdbuff; ) + for (w = ccline.cmdbuff + ccline.cmdpos; w > ccline.cmdbuff; ) { #ifdef FEAT_MBYTE if (has_mbyte) @@ -3041,7 +3092,7 @@ --w; } } - len = (int)((ccline.cmdbuff + ccline.cmdlen) - w); + len = (int)((ccline.cmdbuff + ccline.cmdpos) - w); if (p_ic ? STRNICMP(w, arg, len) == 0 : STRNCMP(w, arg, len) == 0) p += len; } @@ -3082,7 +3133,8 @@ else #endif c = *s++; - if (cv == Ctrl_V || c == ESC || c == Ctrl_C || c == CAR || c == NL + if (cv == Ctrl_V || c == ESC || c == Ctrl_C + || c == CAR || c == NL || c == Ctrl_L #ifdef UNIX || c == intr_char #endif @@ -3258,6 +3310,24 @@ return check_abbr(c, ccline.cmdbuff, ccline.cmdpos, 0); } +#if defined(FEAT_CMDL_COMPL) || defined(PROTO) + static int +#ifdef __BORLANDC__ +_RTLENTRYF +#endif +sort_func_compare(s1, s2) + const void *s1; + const void *s2; +{ + char_u *p1 = *(char_u **)s1; + char_u *p2 = *(char_u **)s2; + + if (*p1 != '<' && *p2 == '<') return -1; + if (*p1 == '<' && *p2 != '<') return 1; + return STRCMP(p1, p2); +} +#endif + /* * Return FAIL if this is not an appropriate context in which to do * completion of anything, return OK if it is (even if there are no matches). @@ -3316,10 +3386,14 @@ p2 = NULL; else { + int use_options = options | + WILD_HOME_REPLACE|WILD_ADD_SLASH|WILD_SILENT|WILD_ESCAPE; + + if (p_wic) + use_options += WILD_ICASE; p2 = ExpandOne(xp, p1, vim_strnsave(&ccline.cmdbuff[i], xp->xp_pattern_len), - WILD_HOME_REPLACE|WILD_ADD_SLASH|WILD_SILENT|WILD_ESCAPE - |options, type); + use_options, type); vim_free(p1); /* longest match: make sure it is not shorter, happens with :help */ if (p2 != NULL && type == WILD_LONGEST) @@ -3396,6 +3470,7 @@ * mode = WILD_PREV: use previous match in multiple match, wrap to first * mode = WILD_ALL: return all matches concatenated * mode = WILD_LONGEST: return longest matched part + * mode = WILD_ALL_KEEP: get all matches, keep matches * * options = WILD_LIST_NOTFOUND: list entries without a match * options = WILD_HOME_REPLACE: do home_replace() for buffer names @@ -3405,6 +3480,7 @@ * options = WILD_KEEP_ALL: don't remove 'wildignore' entries * options = WILD_SILENT: don't print warning messages * options = WILD_ESCAPE: put backslash before special chars + * options = WILD_ICASE: ignore case for files * * The variables xp->xp_context and xp->xp_backslash must have been set! */ @@ -3518,7 +3594,8 @@ /* * Check for matching suffixes in file names. */ - if (mode != WILD_ALL && mode != WILD_LONGEST) + if (mode != WILD_ALL && mode != WILD_ALL_KEEP + && mode != WILD_LONGEST) { if (xp->xp_numfiles) non_suf_match = xp->xp_numfiles; @@ -3674,6 +3751,7 @@ if (options & WILD_ESCAPE) { if (xp->xp_context == EXPAND_FILES + || xp->xp_context == EXPAND_FILES_IN_PATH || xp->xp_context == EXPAND_SHELLCMD || xp->xp_context == EXPAND_BUFFERS || xp->xp_context == EXPAND_DIRECTORIES) @@ -4338,6 +4416,7 @@ char_u ***matches; /* return: array of pointers to matches */ { char_u *file_str = NULL; + int options = WILD_ADD_SLASH|WILD_SILENT; if (xp->xp_context == EXPAND_UNSUCCESSFUL) { @@ -4356,9 +4435,11 @@ if (file_str == NULL) return EXPAND_UNSUCCESSFUL; + if (p_wic) + options += WILD_ICASE; + /* find all files that match the description */ - if (ExpandFromContext(xp, file_str, matchcount, matches, - WILD_ADD_SLASH|WILD_SILENT) == FAIL) + if (ExpandFromContext(xp, file_str, matchcount, matches, options) == FAIL) { *matchcount = 0; *matches = NULL; @@ -4410,7 +4491,7 @@ char_u *pat; int *num_file; char_u ***file; - int options; + int options; /* EW_ flags */ { #ifdef FEAT_CMDL_COMPL regmatch_T regmatch; @@ -4464,6 +4545,9 @@ flags |= (EW_FILE | EW_PATH); else flags = (flags | EW_DIR) & ~EW_FILE; + if (options & WILD_ICASE) + flags |= EW_ICASE; + /* Expand wildcards, supporting %:h and the like. */ ret = expand_wildcards_eval(&pat, num_file, file, flags); if (free_pat) @@ -4501,13 +4585,25 @@ || xp->xp_context == EXPAND_TAGS_LISTFILES) return expand_tags(xp->xp_context == EXPAND_TAGS, pat, num_file, file); if (xp->xp_context == EXPAND_COLORS) - return ExpandRTDir(pat, num_file, file, "colors"); + { + char *directories[] = {"colors", NULL}; + return ExpandRTDir(pat, num_file, file, directories); + } if (xp->xp_context == EXPAND_COMPILER) - return ExpandRTDir(pat, num_file, file, "compiler"); + { + char *directories[] = {"compiler", NULL}; + return ExpandRTDir(pat, num_file, file, directories); + } if (xp->xp_context == EXPAND_OWNSYNTAX) - return ExpandRTDir(pat, num_file, file, "syntax"); + { + char *directories[] = {"syntax", NULL}; + return ExpandRTDir(pat, num_file, file, directories); + } if (xp->xp_context == EXPAND_FILETYPE) - return ExpandRTDir(pat, num_file, file, "{syntax,indent,ftplugin}"); + { + char *directories[] = {"syntax", "indent", "ftplugin", NULL}; + return ExpandRTDir(pat, num_file, file, directories); + } # if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL) if (xp->xp_context == EXPAND_USER_LIST) return ExpandUserList(xp, num_file, file); @@ -4536,48 +4632,53 @@ int context; char_u *((*func)__ARGS((expand_T *, int))); int ic; + int escaped; } tab[] = { - {EXPAND_COMMANDS, get_command_name, FALSE}, - {EXPAND_BEHAVE, get_behave_arg, TRUE}, + {EXPAND_COMMANDS, get_command_name, FALSE, TRUE}, + {EXPAND_BEHAVE, get_behave_arg, TRUE, TRUE}, +#ifdef FEAT_CMDHIST + {EXPAND_HISTORY, get_history_arg, TRUE, TRUE}, +#endif #ifdef FEAT_USR_CMDS - {EXPAND_USER_COMMANDS, get_user_commands, FALSE}, - {EXPAND_USER_CMD_FLAGS, get_user_cmd_flags, FALSE}, - {EXPAND_USER_NARGS, get_user_cmd_nargs, FALSE}, - {EXPAND_USER_COMPLETE, get_user_cmd_complete, FALSE}, + {EXPAND_USER_COMMANDS, get_user_commands, FALSE, TRUE}, + {EXPAND_USER_CMD_FLAGS, get_user_cmd_flags, FALSE, TRUE}, + {EXPAND_USER_NARGS, get_user_cmd_nargs, FALSE, TRUE}, + {EXPAND_USER_COMPLETE, get_user_cmd_complete, FALSE, TRUE}, #endif #ifdef FEAT_EVAL - {EXPAND_USER_VARS, get_user_var_name, FALSE}, - {EXPAND_FUNCTIONS, get_function_name, FALSE}, - {EXPAND_USER_FUNC, get_user_func_name, FALSE}, - {EXPAND_EXPRESSION, get_expr_name, FALSE}, + {EXPAND_USER_VARS, get_user_var_name, FALSE, TRUE}, + {EXPAND_FUNCTIONS, get_function_name, FALSE, TRUE}, + {EXPAND_USER_FUNC, get_user_func_name, FALSE, TRUE}, + {EXPAND_EXPRESSION, get_expr_name, FALSE, TRUE}, #endif #ifdef FEAT_MENU - {EXPAND_MENUS, get_menu_name, FALSE}, - {EXPAND_MENUNAMES, get_menu_names, FALSE}, + {EXPAND_MENUS, get_menu_name, FALSE, TRUE}, + {EXPAND_MENUNAMES, get_menu_names, FALSE, TRUE}, #endif #ifdef FEAT_SYN_HL - {EXPAND_SYNTAX, get_syntax_name, TRUE}, + {EXPAND_SYNTAX, get_syntax_name, TRUE, TRUE}, #endif - {EXPAND_HIGHLIGHT, get_highlight_name, TRUE}, + {EXPAND_HIGHLIGHT, get_highlight_name, TRUE, TRUE}, #ifdef FEAT_AUTOCMD - {EXPAND_EVENTS, get_event_name, TRUE}, - {EXPAND_AUGROUP, get_augroup_name, TRUE}, + {EXPAND_EVENTS, get_event_name, TRUE, TRUE}, + {EXPAND_AUGROUP, get_augroup_name, TRUE, TRUE}, #endif #ifdef FEAT_CSCOPE - {EXPAND_CSCOPE, get_cscope_name, TRUE}, + {EXPAND_CSCOPE, get_cscope_name, TRUE, TRUE}, #endif #ifdef FEAT_SIGNS - {EXPAND_SIGN, get_sign_name, TRUE}, + {EXPAND_SIGN, get_sign_name, TRUE, TRUE}, #endif #ifdef FEAT_PROFILE - {EXPAND_PROFILE, get_profile_name, TRUE}, + {EXPAND_PROFILE, get_profile_name, TRUE, TRUE}, #endif #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \ && (defined(FEAT_GETTEXT) || defined(FEAT_MBYTE)) - {EXPAND_LANGUAGE, get_lang_arg, TRUE}, + {EXPAND_LANGUAGE, get_lang_arg, TRUE, FALSE}, + {EXPAND_LOCALES, get_locales, TRUE, FALSE}, #endif - {EXPAND_ENV_VARS, get_env_name, TRUE}, + {EXPAND_ENV_VARS, get_env_name, TRUE, TRUE}, }; int i; @@ -4591,7 +4692,8 @@ { if (tab[i].ic) regmatch.rm_ic = TRUE; - ret = ExpandGeneric(xp, ®match, num_file, file, tab[i].func); + ret = ExpandGeneric(xp, ®match, num_file, file, + tab[i].func, tab[i].escaped); break; } } @@ -4613,13 +4715,14 @@ * Returns OK when no problems encountered, FAIL for error (out of memory). */ int -ExpandGeneric(xp, regmatch, num_file, file, func) +ExpandGeneric(xp, regmatch, num_file, file, func, escaped) expand_T *xp; regmatch_T *regmatch; int *num_file; char_u ***file; char_u *((*func)__ARGS((expand_T *, int))); /* returns a string from the list */ + int escaped; { int i; int count = 0; @@ -4644,7 +4747,10 @@ { if (round) { - str = vim_strsave_escaped(str, (char_u *)" \t\\."); + if (escaped) + str = vim_strsave_escaped(str, (char_u *)" \t\\."); + else + str = vim_strsave(str); (*file)[count] = str; #ifdef FEAT_MENU if (func == get_menu_names && str != NULL) @@ -4676,7 +4782,16 @@ /* Sort the results. Keep menu's in the specified order. */ if (xp->xp_context != EXPAND_MENUNAMES && xp->xp_context != EXPAND_MENUS) - sort_strings(*file, *num_file); + { + if (xp->xp_context == EXPAND_EXPRESSION + || xp->xp_context == EXPAND_FUNCTIONS + || xp->xp_context == EXPAND_USER_FUNC) + /* functions should be sorted to the end. */ + qsort((void *)*file, (size_t)*num_file, sizeof(char_u *), + sort_func_compare); + else + sort_strings(*file, *num_file); + } #ifdef FEAT_CMDL_COMPL /* Reset the variables used for special highlight names expansion, so that @@ -4728,7 +4843,11 @@ || (pat[1] == '.' && vim_ispathsep(pat[2]))))) path = (char_u *)"."; else + { path = vim_getenv((char_u *)"PATH", &mustfree); + if (path == NULL) + path = (char_u *)""; + } /* * Go over all directories in $PATH. Expand matches in that directory and @@ -4949,57 +5068,68 @@ /* * Expand color scheme, compiler or filetype names: * 'runtimepath'/{dirnames}/{pat}.vim - * dirnames may contain one directory (ex: "colorscheme") or can be a glob - * expression matching multiple directories (ex: "{syntax,ftplugin,indent}"). + * "dirnames" is an array with one or more directory names. */ static int ExpandRTDir(pat, num_file, file, dirnames) char_u *pat; int *num_file; char_u ***file; - char *dirnames; + char *dirnames[]; { - char_u *all; + char_u *matches; char_u *s; char_u *e; garray_T ga; + int i; + int pat_len; *num_file = 0; *file = NULL; - s = alloc((unsigned)(STRLEN(pat) + STRLEN(dirnames) + 7)); - if (s == NULL) - return FAIL; - sprintf((char *)s, "%s/%s*.vim", dirnames, pat); - all = globpath(p_rtp, s, 0); - vim_free(s); - if (all == NULL) - return FAIL; + pat_len = (int)STRLEN(pat); + ga_init2(&ga, (int)sizeof(char *), 10); - ga_init2(&ga, (int)sizeof(char *), 3); - for (s = all; *s != NUL; s = e) + for (i = 0; dirnames[i] != NULL; ++i) { - e = vim_strchr(s, '\n'); - if (e == NULL) - e = s + STRLEN(s); - if (ga_grow(&ga, 1) == FAIL) - break; - if (e - 4 > s && STRNICMP(e - 4, ".vim", 4) == 0) + s = alloc((unsigned)(STRLEN(dirnames[i]) + pat_len + 7)); + if (s == NULL) { - for (s = e - 4; s > all; mb_ptr_back(all, s)) - if (*s == '\n' || vim_ispathsep(*s)) - break; - ++s; - ((char_u **)ga.ga_data)[ga.ga_len] = + ga_clear_strings(&ga); + return FAIL; + } + sprintf((char *)s, "%s/%s*.vim", dirnames[i], pat); + matches = globpath(p_rtp, s, 0); + vim_free(s); + if (matches == NULL) + continue; + + for (s = matches; *s != NUL; s = e) + { + e = vim_strchr(s, '\n'); + if (e == NULL) + e = s + STRLEN(s); + if (ga_grow(&ga, 1) == FAIL) + break; + if (e - 4 > s && STRNICMP(e - 4, ".vim", 4) == 0) + { + for (s = e - 4; s > matches; mb_ptr_back(matches, s)) + if (*s == '\n' || vim_ispathsep(*s)) + break; + ++s; + ((char_u **)ga.ga_data)[ga.ga_len] = vim_strnsave(s, (int)(e - s - 4)); - ++ga.ga_len; + ++ga.ga_len; + } + if (*e != NUL) + ++e; } - if (*e != NUL) - ++e; + vim_free(matches); } - vim_free(all); + if (ga.ga_len == 0) + return FAIL; /* Sort and remove duplicates which can happen when specifying multiple - * directories in dirnames such as "{syntax,ftplugin,indent}". */ + * directories in dirnames. */ remove_duplicates(&ga); *file = ga.ga_data; @@ -5127,6 +5257,34 @@ NULL }; +#if defined(FEAT_CMDL_COMPL) || defined(PROTO) +/* + * Function given to ExpandGeneric() to obtain the possible first + * arguments of the ":history command. + */ + static char_u * +get_history_arg(xp, idx) + expand_T *xp UNUSED; + int idx; +{ + static char_u compl[2] = { NUL, NUL }; + char *short_names = ":=@>?/"; + int short_names_count = (int)STRLEN(short_names); + int history_name_count = sizeof(history_names) / sizeof(char *) - 1; + + if (idx < short_names_count) + { + compl[0] = (char_u)short_names[idx]; + return compl; + } + if (idx < short_names_count + history_name_count) + return (char_u *)history_names[idx - short_names_count]; + if (idx == short_names_count + history_name_count) + return (char_u *)"all"; + return NULL; +} +#endif + /* * init_history() - Initialize the command line history. * Also used to re-allocate the history when the size changes. @@ -5220,13 +5378,15 @@ * If 'move_to_front' is TRUE, matching entry is moved to end of history. */ static int -in_history(type, str, move_to_front) +in_history(type, str, move_to_front, sep) int type; char_u *str; int move_to_front; /* Move the entry to the front if it exists */ + int sep; { int i; int last_i = -1; + char_u *p; if (hisidx[type] < 0) return FALSE; @@ -5235,7 +5395,12 @@ { if (history[type][i].hisstr == NULL) return FALSE; - if (STRCMP(str, history[type][i].hisstr) == 0) + + /* For search history, check that the separator character matches as + * well. */ + p = history[type][i].hisstr; + if (STRCMP(str, p) == 0 + && (type != HIST_SEARCH || sep == p[STRLEN(p) + 1])) { if (!move_to_front) return TRUE; @@ -5329,7 +5494,7 @@ } last_maptick = -1; } - if (!in_history(histype, new_entry, TRUE)) + if (!in_history(histype, new_entry, TRUE, sep)) { if (++hisidx[histype] == hislen) hisidx[histype] = 0; @@ -5803,7 +5968,7 @@ hist[i].hisnum); if (vim_strsize(hist[i].hisstr) > (int)Columns - 10) trunc_string(hist[i].hisstr, IObuff + STRLEN(IObuff), - (int)Columns - 10); + (int)Columns - 10, IOSIZE - (int)STRLEN(IObuff)); else STRCAT(IObuff, hist[i].hisstr); msg_outtrans(IObuff); @@ -5907,8 +6072,10 @@ val = viminfo_readstring(virp, 1, TRUE); if (val != NULL && *val != NUL) { + int sep = (*val == ' ' ? NUL : *val); + if (!in_history(type, val + (type == HIST_SEARCH), - viminfo_add_at_front)) + viminfo_add_at_front, sep)) { /* Need to re-allocate to append the separator byte. */ len = STRLEN(val); @@ -5920,7 +6087,7 @@ /* Search entry: Move the separator from the first * column to after the NUL. */ mch_memmove(p, val + 1, (size_t)len); - p[len] = (*val == ' ' ? NUL : *val); + p[len] = sep; } else { @@ -6147,9 +6314,7 @@ curwin->w_p_rl = cmdmsg_rl; cmdmsg_rl = FALSE; # endif -# ifdef FEAT_SCROLLBIND - curwin->w_p_scb = FALSE; -# endif + RESET_BINDING(curwin); # ifdef FEAT_AUTOCMD /* Do execute autocommands for setting the filetype (load syntax). */ @@ -6287,6 +6452,12 @@ ccline.cmdbuff = vim_strsave((char_u *)"qa"); cmdwin_result = CAR; } + else if (cmdwin_result == Ctrl_C) + { + /* :q or :close, don't execute any command + * and don't modify the cmd window. */ + ccline.cmdbuff = NULL; + } else ccline.cmdbuff = vim_strsave(ml_get_curline()); if (ccline.cmdbuff == NULL) @@ -6317,7 +6488,7 @@ /* win_close() may have already wiped the buffer when 'bh' is * set to 'wipe' */ if (buf_valid(bp)) - close_buffer(NULL, bp, DOBUF_WIPE); + close_buffer(NULL, bp, DOBUF_WIPE, FALSE); /* Restore window sizes. */ win_size_restore(&winsizes); diff -Naur vim73.orig/src/farsi.c vim73/src/farsi.c --- vim73.orig/src/farsi.c 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/farsi.c 2012-07-20 20:31:18.224311766 +0000 @@ -1813,7 +1813,7 @@ ptr[i] = toF_leading(ptr[i]); ++i; - while(canF_Rjoin(ptr[i]) && (i < llen)) + while (canF_Rjoin(ptr[i]) && i < llen) { ptr[i] = toF_Rjoin(ptr[i]); if (F_isterm(ptr[i]) || !F_isalpha(ptr[i])) diff -Naur vim73.orig/src/feature.h vim73/src/feature.h --- vim73.orig/src/feature.h 2010-07-27 19:45:42.000000000 +0000 +++ vim73/src/feature.h 2012-07-20 20:31:15.827643384 +0000 @@ -506,15 +506,6 @@ #endif /* - * +osfiletype filetype checking in autocommand patterns. - * Only on systems that support filetypes (RISC OS). - */ -#if 0 -# define FEAT_OSFILETYPE -# define DFLT_OFT "Text" -#endif - -/* * +viminfo reading/writing the viminfo file. Takes about 8Kbyte * of code. * VIMINFO_FILE Location of user .viminfo file (should start with $). @@ -1062,6 +1053,9 @@ # ifdef FEAT_BIG # define FEAT_MOUSE_DEC # endif +# ifdef FEAT_BIG +# define FEAT_MOUSE_URXVT +# endif # if defined(FEAT_NORMAL) && (defined(MSDOS) || defined(WIN3264)) # define DOS_MOUSE # endif @@ -1077,13 +1071,23 @@ #if defined(FEAT_NORMAL) && defined(HAVE_SYSMOUSE) # define FEAT_SYSMOUSE #endif + +/* urxvt is a small variation of mouse_xterm, and shares its code */ +#if defined(FEAT_MOUSE_URXVT) && !defined(FEAT_MOUSE_XTERM) +# define FEAT_MOUSE_XTERM +#endif + /* Define FEAT_MOUSE when any of the above is defined or FEAT_GUI. */ #if !defined(FEAT_MOUSE_TTY) \ && (defined(FEAT_MOUSE_XTERM) \ - || defined(FEAT_MOUSE_NET) || defined(FEAT_MOUSE_DEC) \ - || defined(DOS_MOUSE) || defined(FEAT_MOUSE_GPM) \ - || defined(FEAT_MOUSE_JSB) || defined(FEAT_MOUSE_PTERM) \ - || defined(FEAT_SYSMOUSE)) + || defined(FEAT_MOUSE_NET) \ + || defined(FEAT_MOUSE_DEC) \ + || defined(DOS_MOUSE) \ + || defined(FEAT_MOUSE_GPM) \ + || defined(FEAT_MOUSE_JSB) \ + || defined(FEAT_MOUSE_PTERM) \ + || defined(FEAT_SYSMOUSE) \ + || defined(FEAT_MOUSE_URXVT)) # define FEAT_MOUSE_TTY /* include non-GUI mouse support */ #endif #if !defined(FEAT_MOUSE) && (defined(FEAT_MOUSE_TTY) || defined(FEAT_GUI)) @@ -1312,3 +1316,11 @@ #ifdef FEAT_NORMAL # define FEAT_PERSISTENT_UNDO #endif + +/* + * +filterpipe + */ +#if (defined(UNIX) && !defined(USE_SYSTEM)) \ + || (defined(WIN3264) && defined(FEAT_GUI_W32)) +# define FEAT_FILTERPIPE +#endif diff -Naur vim73.orig/src/fileio.c vim73/src/fileio.c --- vim73.orig/src/fileio.c 2010-08-14 12:20:54.000000000 +0000 +++ vim73/src/fileio.c 2012-07-20 20:31:18.164311724 +0000 @@ -11,14 +11,6 @@ * fileio.c: read from and write to a file */ -#if defined(MSDOS) || defined(WIN16) || defined(WIN32) || defined(_WIN64) -# include "vimio.h" /* for lseek(), must be before vim.h */ -#endif - -#if defined __EMX__ -# include "vimio.h" /* for mktemp(), CJW 1997-12-03 */ -#endif - #include "vim.h" #if defined(__TANDEM) || defined(__MINT__) @@ -258,6 +250,7 @@ #ifdef FEAT_CRYPT char_u *cryptkey = NULL; int did_ask_for_key = FALSE; + int crypt_method_used; #endif #ifdef FEAT_PERSISTENT_UNDO context_sha256_T sha_ctx; @@ -325,7 +318,7 @@ int using_b_fname; #endif - write_no_eol_lnum = 0; /* in case it was set by the previous read */ + curbuf->b_no_eol_lnum = 0; /* in case it was set by the previous read */ /* * If there is no file name yet, use the one for the read file. @@ -511,18 +504,11 @@ if (newfile && !read_stdin && !read_buffer) { - /* Remember time of file. - * For RISCOS, also remember the filetype. - */ + /* Remember time of file. */ if (mch_stat((char *)fname, &st) >= 0) { buf_store_time(curbuf, &st, fname); curbuf->b_mtime_read = curbuf->b_mtime; - -#if defined(RISCOS) && defined(FEAT_OSFILETYPE) - /* Read the filetype into the buffer local filetype option. */ - mch_read_filetype(fname); -#endif #ifdef UNIX /* * Use the protection bits of the original file for the swap file. @@ -564,7 +550,6 @@ /* * for UNIX: check readonly with perm and mch_access() - * for RISCOS: same as Unix, otherwise file gets re-datestamped! * for MSDOS and Amiga: check readonly by trying to open the file for writing */ file_readonly = FALSE; @@ -918,7 +903,7 @@ { /* Read the first line (and a bit more). Immediately rewind to * the start of the file. If the read() fails "len" is -1. */ - len = vim_read(fd, firstline, 80); + len = read_eintr(fd, firstline, 80); lseek(fd, (off_t)0L, SEEK_SET); for (p = firstline; p < firstline + len; ++p) if (*p >= 0x80) @@ -1373,7 +1358,7 @@ /* * Read bytes from the file. */ - size = vim_read(fd, ptr, size); + size = read_eintr(fd, ptr, size); } if (size <= 0) @@ -2297,6 +2282,7 @@ save_file_ff(curbuf); /* remember the current file format */ #ifdef FEAT_CRYPT + crypt_method_used = use_crypt_method; if (cryptkey != NULL) { crypt_pop_state(); @@ -2491,7 +2477,10 @@ #ifdef FEAT_CRYPT if (cryptkey != NULL) { - STRCAT(IObuff, _("[crypted]")); + if (crypt_method_used == 1) + STRCAT(IObuff, _("[blowfish]")); + else + STRCAT(IObuff, _("[crypted]")); c = TRUE; } #endif @@ -2607,10 +2596,11 @@ /* * Trick: We remember if the last line of the read didn't have - * an eol for when writing it again. This is required for + * an eol even when 'binary' is off, for when writing it again with + * 'binary' on. This is required for * ":autocmd FileReadPost *.gz set bin|'[,']!gunzip" to work. */ - write_no_eol_lnum = read_no_eol_lnum; + curbuf->b_no_eol_lnum = read_no_eol_lnum; /* When reloading a buffer put the cursor at the first line that is * different. */ @@ -2658,10 +2648,10 @@ FALSE, NULL, eap); if (msg_scrolled == n) msg_scroll = m; -#ifdef FEAT_EVAL +# ifdef FEAT_EVAL if (aborting()) /* autocmds may abort script processing */ return FAIL; -#endif +# endif } #endif @@ -3202,6 +3192,9 @@ int write_undo_file = FALSE; context_sha256_T sha_ctx; #endif +#ifdef FEAT_CRYPT + int crypt_method_used; +#endif if (fname == NULL || *fname == NUL) /* safety check */ return FAIL; @@ -3345,8 +3338,22 @@ } else if (reset_changed && whole) { - if (!(did_cmd = apply_autocmds_exarg(EVENT_BUFWRITECMD, - sfname, sfname, FALSE, curbuf, eap))) + int was_changed = curbufIsChanged(); + + did_cmd = apply_autocmds_exarg(EVENT_BUFWRITECMD, + sfname, sfname, FALSE, curbuf, eap); + if (did_cmd) + { + if (was_changed && !curbufIsChanged()) + { + /* Written everything correctly and BufWriteCmd has reset + * 'modified': Correct the undo information so that an + * undo now sets 'modified'. */ + u_unchanged(curbuf); + u_update_save_nr(curbuf); + } + } + else { #ifdef FEAT_QUICKFIX if (overwriting && bt_nofile(curbuf)) @@ -3799,13 +3806,7 @@ /* make sure we have a valid backup extension to use */ if (*p_bex == NUL) - { -#ifdef RISCOS - backup_ext = (char_u *)"/bak"; -#else backup_ext = (char_u *)".bak"; -#endif - } else backup_ext = p_bex; @@ -4000,7 +4001,7 @@ #ifdef HAS_BW_FLAGS write_info.bw_flags = FIO_NOCONVERT; #endif - while ((write_info.bw_len = vim_read(fd, copybuf, + while ((write_info.bw_len = read_eintr(fd, copybuf, BUFSIZE)) > 0) { if (buf_write_bytes(&write_info) == FAIL) @@ -4568,7 +4569,7 @@ if (end == 0 || (lnum == end && write_bin - && (lnum == write_no_eol_lnum + && (lnum == buf->b_no_eol_lnum || (lnum == buf->b_ml.ml_line_count && !buf->b_p_eol)))) { ++lnum; /* written the line, count it */ @@ -4719,11 +4720,6 @@ #endif if (perm >= 0) /* set perm. of new file same as old file */ (void)mch_setperm(wfname, perm); -#ifdef RISCOS - if (!append && !filtering) - /* Set the filetype after writing the file. */ - mch_set_filetype(wfname, buf->b_p_oft); -#endif #ifdef HAVE_ACL /* Probably need to set the ACL before changing the user (can't set the * ACL on a file the user doesn't own). */ @@ -4731,6 +4727,7 @@ mch_set_acl(wfname, acl); #endif #ifdef FEAT_CRYPT + crypt_method_used = use_crypt_method; if (wb_flags & FIO_ENCRYPTED) crypt_pop_state(); #endif @@ -4813,7 +4810,7 @@ #ifdef HAS_BW_FLAGS write_info.bw_flags = FIO_NOCONVERT; #endif - while ((write_info.bw_len = vim_read(fd, smallbuf, + while ((write_info.bw_len = read_eintr(fd, smallbuf, SMBUFSIZE)) > 0) if (buf_write_bytes(&write_info) == FAIL) break; @@ -4885,7 +4882,10 @@ #ifdef FEAT_CRYPT if (wb_flags & FIO_ENCRYPTED) { - STRCAT(IObuff, _("[crypted]")); + if (crypt_method_used == 1) + STRCAT(IObuff, _("[blowfish]")); + else + STRCAT(IObuff, _("[crypted]")); c = TRUE; } #endif @@ -5094,7 +5094,7 @@ { aco_save_T aco; - write_no_eol_lnum = 0; /* in case it was set by the previous read */ + curbuf->b_no_eol_lnum = 0; /* in case it was set by the previous read */ /* * Apply POST autocommands. @@ -5330,7 +5330,7 @@ /* * Call write() to write a number of bytes to the file. - * Also handles encryption and 'encoding' conversion. + * Handles encryption and 'encoding' conversion. * * Return FAIL for failure, OK otherwise. */ @@ -5702,16 +5702,8 @@ crypt_encode(buf, len, buf); #endif - /* Repeat the write(), it may be interrupted by a signal. */ - while (len > 0) - { - wlen = vim_write(ip->bw_fd, buf, len); - if (wlen <= 0) /* error! */ - return FAIL; - len -= wlen; - buf += wlen; - } - return OK; + wlen = write_eintr(ip->bw_fd, buf, len); + return (wlen < len) ? FAIL : OK; } #ifdef FEAT_MBYTE @@ -6024,15 +6016,19 @@ shorten_fname1(full_path) char_u *full_path; { - char_u dirname[MAXPATHL]; + char_u *dirname; char_u *p = full_path; + dirname = alloc(MAXPATHL); + if (dirname == NULL) + return full_path; if (mch_dirname(dirname, MAXPATHL) == OK) { p = shorten_fname(full_path, dirname); if (p == NULL || *p == NUL) p = full_path; } + vim_free(dirname); return p; } #endif @@ -6259,19 +6255,17 @@ */ for (ptr = retval + fnamelen; ptr > retval; mb_ptr_back(retval, ptr)) { -#ifndef RISCOS if (*ext == '.' -# ifdef USE_LONG_FNAME +#ifdef USE_LONG_FNAME && (!USE_LONG_FNAME || shortname) -# else -# ifndef SHORT_FNAME +#else +# ifndef SHORT_FNAME && shortname -# endif # endif +#endif ) if (*ptr == '.') /* replace '.' by '_' */ *ptr = '_'; -#endif if (vim_ispathsep(*ptr)) { ++ptr; @@ -6306,23 +6300,14 @@ if (fname == NULL || *fname == NUL || vim_ispathsep(fname[STRLEN(fname) - 1])) { -#ifdef RISCOS - if (*ext == '/') -#else if (*ext == '.') -#endif *s++ = '_'; } /* * If the extension starts with '.', truncate the base name at 8 * characters */ -#ifdef RISCOS - /* We normally use '/', but swap files are '_' */ - else if (*ext == '/' || *ext == '_') -#else else if (*ext == '.') -#endif { if ((size_t)(s - ptr) > (size_t)8) { @@ -6334,13 +6319,8 @@ * If the extension doesn't start with '.', and the file name * doesn't have an extension yet, append a '.' */ -#ifdef RISCOS - else if ((e = vim_strchr(ptr, '/')) == NULL) - *s++ = '/'; -#else else if ((e = vim_strchr(ptr, '.')) == NULL) *s++ = '.'; -#endif /* * If the extension doesn't start with '.', and there already is an * extension, it may need to be truncated @@ -6368,23 +6348,14 @@ /* * Prepend the dot. */ - if (prepend_dot && !shortname && *(e = gettail(retval)) != -#ifdef RISCOS - '/' -#else - '.' -#endif + if (prepend_dot && !shortname && *(e = gettail(retval)) != '.' #ifdef USE_LONG_FNAME && USE_LONG_FNAME #endif ) { STRMOVE(e + 1, e); -#ifdef RISCOS - *e = '/'; -#else *e = '.'; -#endif } #endif @@ -6552,6 +6523,21 @@ use_tmp_file = TRUE; } #endif +#ifdef WIN3264 + { + BY_HANDLE_FILE_INFORMATION info1, info2; + + /* It's possible for the source and destination to be the same file. + * In that case go through a temp file name. This makes rename("foo", + * "./foo") a no-op (in a complicated way). */ + if (win32_fileinfo(from, &info1) == FILEINFO_OK + && win32_fileinfo(to, &info2) == FILEINFO_OK + && info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber + && info1.nFileIndexHigh == info2.nFileIndexHigh + && info1.nFileIndexLow == info2.nFileIndexLow) + use_tmp_file = TRUE; + } +#endif #if defined(UNIX) || defined(CASE_INSENSITIVE_FILENAME) if (use_tmp_file) @@ -6662,8 +6648,8 @@ return -1; } - while ((n = vim_read(fd_in, buffer, BUFSIZE)) > 0) - if (vim_write(fd_out, buffer, n) != n) + while ((n = read_eintr(fd_in, buffer, BUFSIZE)) > 0) + if (write_eintr(fd_out, buffer, n) != n) { errmsg = _("E208: Error writing to \"%s\""); break; @@ -7024,7 +7010,7 @@ STRCAT(tbuf, mesg2); } if (do_dialog(VIM_WARNING, (char_u *)_("Warning"), tbuf, - (char_u *)_("&OK\n&Load File"), 1, NULL) == 2) + (char_u *)_("&OK\n&Load File"), 1, NULL, TRUE) == 2) reload = TRUE; } else @@ -7272,8 +7258,8 @@ write_lnum_adjust(offset) linenr_T offset; { - if (write_no_eol_lnum != 0) /* only if there is a missing eol */ - write_no_eol_lnum += offset; + if (curbuf->b_no_eol_lnum != 0) /* only if there is a missing eol */ + curbuf->b_no_eol_lnum += offset; } #if defined(TEMPDIRNAMES) || defined(PROTO) @@ -7475,7 +7461,10 @@ STRCPY(itmp, ""); if (GetTempPath(_MAX_PATH, szTempFile) == 0) - szTempFile[0] = NUL; /* GetTempPath() failed, use current dir */ + { + szTempFile[0] = '.'; /* GetTempPath() failed, use current dir */ + szTempFile[1] = NUL; + } strcpy(buf4, "VIM"); buf4[2] = extra_char; /* make it "VIa", "VIb", etc. */ if (GetTempFileName(szTempFile, buf4, 0, itmp) == 0) @@ -7496,8 +7485,11 @@ # else /* WIN3264 */ # ifdef USE_TMPNAM + char_u *p; + /* tmpnam() will make its own name */ - if (*tmpnam((char *)itmp) == NUL) + p = tmpnam((char *)itmp); + if (p == NULL || *p == NUL) return NULL; # else char_u *p; @@ -7651,6 +7643,7 @@ {"CmdwinEnter", EVENT_CMDWINENTER}, {"CmdwinLeave", EVENT_CMDWINLEAVE}, {"ColorScheme", EVENT_COLORSCHEME}, + {"CompleteDone", EVENT_COMPLETEDONE}, {"CursorHold", EVENT_CURSORHOLD}, {"CursorHoldI", EVENT_CURSORHOLDI}, {"CursorMoved", EVENT_CURSORMOVED}, @@ -7682,9 +7675,11 @@ {"InsertChange", EVENT_INSERTCHANGE}, {"InsertEnter", EVENT_INSERTENTER}, {"InsertLeave", EVENT_INSERTLEAVE}, + {"InsertCharPre", EVENT_INSERTCHARPRE}, {"MenuPopup", EVENT_MENUPOPUP}, {"QuickFixCmdPost", EVENT_QUICKFIXCMDPOST}, {"QuickFixCmdPre", EVENT_QUICKFIXCMDPRE}, + {"QuitPre", EVENT_QUITPRE}, {"RemoteReply", EVENT_REMOTEREPLY}, {"SessionLoadPost", EVENT_SESSIONLOADPOST}, {"ShellCmdPost", EVENT_SHELLCMDPOST}, @@ -8744,6 +8739,8 @@ int retval; aco_save_T aco; buf_T *buf; + char_u *arg = eap->arg; + int call_do_modelines = check_nomodeline(&arg); /* * This is a bit tricky: For some commands curwin->w_buffer needs to be @@ -8760,11 +8757,15 @@ aucmd_prepbuf(&aco, buf); /* execute the autocommands for this buffer */ - retval = do_doautocmd(eap->arg, FALSE); + retval = do_doautocmd(arg, FALSE); - /* Execute the modeline settings, but don't set window-local - * options if we are using the current window for another buffer. */ - do_modelines(curwin == aucmd_win ? OPT_NOWIN : 0); + if (call_do_modelines) + { + /* Execute the modeline settings, but don't set window-local + * options if we are using the current window for another + * buffer. */ + do_modelines(curwin == aucmd_win ? OPT_NOWIN : 0); + } /* restore the current window */ aucmd_restbuf(&aco); @@ -8779,6 +8780,23 @@ } /* + * Check *argp for . When it is present return FALSE, otherwise + * return TRUE and advance *argp to after it. + * Thus return TRUE when do_modelines() should be called. + */ + int +check_nomodeline(argp) + char_u **argp; +{ + if (STRNCMP(*argp, "", 12) == 0) + { + *argp = skipwhite(*argp + 12); + return FALSE; + } + return TRUE; +} + +/* * Prepare for executing autocommands for (hidden) buffer "buf". * Search for a visible window containing the current buffer. If there isn't * one then use "aucmd_win". @@ -8901,12 +8919,13 @@ if (wp == aucmd_win) { if (tp != curtab) - goto_tabpage_tp(tp); + goto_tabpage_tp(tp, TRUE); win_goto(aucmd_win); - break; + goto win_found; } } } +win_found: /* Remove the window and frame from the tree of frames. */ (void)winframe_remove(curwin, &dummy, NULL); @@ -8965,6 +8984,10 @@ && buf_valid(aco->new_curbuf) && aco->new_curbuf->b_ml.ml_mfp != NULL) { +# if defined(FEAT_SYN_HL) || defined(FEAT_SPELL) + if (curwin->w_s == &curbuf->b_s) + curwin->w_s = &aco->new_curbuf->b_s; +# endif --curbuf->b_nwindows; curbuf = aco->new_curbuf; curwin->w_buffer = curbuf; @@ -9063,7 +9086,10 @@ { int state; - if (!did_cursorhold && has_cursorhold() && !Recording + if (!did_cursorhold + && has_cursorhold() + && !Recording + && typebuf.tb_len == 0 #ifdef FEAT_INS_EXPAND && !ins_compl_active() #endif @@ -9094,6 +9120,15 @@ return (first_autopat[(int)EVENT_CURSORMOVEDI] != NULL); } +/* + * Return TRUE when there is an InsertCharPre autocommand defined. + */ + int +has_insertcharpre() +{ + return (first_autopat[(int)EVENT_INSERTCHARPRE] != NULL); +} + static int apply_autocmds_group(event, fname, fname_io, force, group, buf, eap) event_T event; @@ -9954,6 +9989,8 @@ if ((c == ';' || c == '>') && match == FALSE) { *pattern = NUL; /* Terminate the string */ + /* TODO: match with 'filetype' of buffer that "fname" comes + * from. */ match = mch_check_filetype(fname, type_start); *pattern = c; /* Restore the terminator */ type_start = pattern + 1; @@ -10181,19 +10218,11 @@ ++p; break; case '.': -#ifdef RISCOS - if (allow_dirs != NULL) - *allow_dirs = TRUE; - /* FALLTHROUGH */ -#endif case '~': reg_pat[i++] = '\\'; reg_pat[i++] = *p; break; case '?': -#ifdef RISCOS - case '#': -#endif reg_pat[i++] = '.'; break; case '\\': @@ -10304,3 +10333,55 @@ } return reg_pat; } + +#if defined(EINTR) || defined(PROTO) +/* + * Version of read() that retries when interrupted by EINTR (possibly + * by a SIGWINCH). + */ + long +read_eintr(fd, buf, bufsize) + int fd; + void *buf; + size_t bufsize; +{ + long ret; + + for (;;) + { + ret = vim_read(fd, buf, bufsize); + if (ret >= 0 || errno != EINTR) + break; + } + return ret; +} + +/* + * Version of write() that retries when interrupted by EINTR (possibly + * by a SIGWINCH). + */ + long +write_eintr(fd, buf, bufsize) + int fd; + void *buf; + size_t bufsize; +{ + long ret = 0; + long wlen; + + /* Repeat the write() so long it didn't fail, other than being interrupted + * by a signal. */ + while (ret < (long)bufsize) + { + wlen = vim_write(fd, (char *)buf + ret, bufsize - ret); + if (wlen < 0) + { + if (errno != EINTR) + break; + } + else + ret += wlen; + } + return ret; +} +#endif diff -Naur vim73.orig/src/fold.c vim73/src/fold.c --- vim73.orig/src/fold.c 2010-06-22 04:20:24.000000000 +0000 +++ vim73/src/fold.c 2012-07-20 20:31:15.170976247 +0000 @@ -1033,10 +1033,10 @@ * Init the fold info in a new window. */ void -foldInitWin(newwin) - win_T *newwin; +foldInitWin(new_win) + win_T *new_win; { - ga_init2(&newwin->w_folds, (int)sizeof(fold_T), 10); + ga_init2(&new_win->w_folds, (int)sizeof(fold_T), 10); } /* find_wl_entry() {{{2 */ @@ -1469,11 +1469,14 @@ } else { - /* move nested folds one level up, to overwrite the fold that is + /* Move nested folds one level up, to overwrite the fold that is * deleted. */ moved = fp->fd_nested.ga_len; if (ga_grow(gap, (int)(moved - 1)) == OK) { + /* Get "fp" again, the array may have been reallocated. */ + fp = (fold_T *)gap->ga_data + idx; + /* adjust fd_top and fd_flags for the moved folds */ nfp = (fold_T *)fp->fd_nested.ga_data; for (i = 0; i < moved; ++i) @@ -1486,9 +1489,9 @@ } /* move the existing folds down to make room */ - if (idx < gap->ga_len) + if (idx + 1 < gap->ga_len) mch_memmove(fp + moved, fp + 1, - sizeof(fold_T) * (gap->ga_len - idx)); + sizeof(fold_T) * (gap->ga_len - (idx + 1))); /* move the contained folds one level up */ mch_memmove(fp, nfp, (size_t)(sizeof(fold_T) * moved)); vim_free(nfp); @@ -3289,7 +3292,8 @@ /* put_folds() {{{2 */ #if defined(FEAT_SESSION) || defined(PROTO) static int put_folds_recurse __ARGS((FILE *fd, garray_T *gap, linenr_T off)); -static int put_foldopen_recurse __ARGS((FILE *fd, garray_T *gap, linenr_T off)); +static int put_foldopen_recurse __ARGS((FILE *fd, win_T *wp, garray_T *gap, linenr_T off)); +static int put_fold_open_close __ARGS((FILE *fd, fold_T *fp, linenr_T off)); /* * Write commands to "fd" to restore the manual folds in window "wp". @@ -3309,7 +3313,7 @@ /* If some folds are manually opened/closed, need to restore that. */ if (wp->w_fold_manual) - return put_foldopen_recurse(fd, &wp->w_folds, (linenr_T)0); + return put_foldopen_recurse(fd, wp, &wp->w_folds, (linenr_T)0); return OK; } @@ -3349,12 +3353,14 @@ * Returns FAIL when writing failed. */ static int -put_foldopen_recurse(fd, gap, off) +put_foldopen_recurse(fd, wp, gap, off) FILE *fd; + win_T *wp; garray_T *gap; linenr_T off; { int i; + int level; fold_T *fp; fp = (fold_T *)gap->ga_data; @@ -3364,27 +3370,60 @@ { if (fp->fd_nested.ga_len > 0) { - /* open/close nested folds while this fold is open */ + /* open nested folds while this fold is open */ if (fprintf(fd, "%ld", fp->fd_top + off) < 0 || put_eol(fd) == FAIL || put_line(fd, "normal zo") == FAIL) return FAIL; - if (put_foldopen_recurse(fd, &fp->fd_nested, off + fp->fd_top) + if (put_foldopen_recurse(fd, wp, &fp->fd_nested, + off + fp->fd_top) == FAIL) return FAIL; + /* close the parent when needed */ + if (fp->fd_flags == FD_CLOSED) + { + if (put_fold_open_close(fd, fp, off) == FAIL) + return FAIL; + } + } + else + { + /* Open or close the leaf according to the window foldlevel. + * Do not close a leaf that is already closed, as it will close + * the parent. */ + level = foldLevelWin(wp, off + fp->fd_top); + if ((fp->fd_flags == FD_CLOSED && wp->w_p_fdl >= level) + || (fp->fd_flags != FD_CLOSED && wp->w_p_fdl < level)) + if (put_fold_open_close(fd, fp, off) == FAIL) + return FAIL; } - if (fprintf(fd, "%ld", fp->fd_top + off) < 0 - || put_eol(fd) == FAIL - || fprintf(fd, "normal z%c", - fp->fd_flags == FD_CLOSED ? 'c' : 'o') < 0 - || put_eol(fd) == FAIL) - return FAIL; } ++fp; } return OK; } + +/* put_fold_open_close() {{{2 */ +/* + * Write the open or close command to "fd". + * Returns FAIL when writing failed. + */ + static int +put_fold_open_close(fd, fp, off) + FILE *fd; + fold_T *fp; + linenr_T off; +{ + if (fprintf(fd, "%ld", fp->fd_top + off) < 0 + || put_eol(fd) == FAIL + || fprintf(fd, "normal z%c", + fp->fd_flags == FD_CLOSED ? 'c' : 'o') < 0 + || put_eol(fd) == FAIL) + return FAIL; + + return OK; +} #endif /* FEAT_SESSION */ /* }}}1 */ diff -Naur vim73.orig/src/getchar.c vim73/src/getchar.c --- vim73.orig/src/getchar.c 2010-08-08 13:00:33.000000000 +0000 +++ vim73/src/getchar.c 2012-07-20 20:31:16.570977250 +0000 @@ -418,12 +418,12 @@ /* * Remove the contents of the stuff buffer and the mapped characters in the - * typeahead buffer (used in case of an error). If 'typeahead' is true, + * typeahead buffer (used in case of an error). If "flush_typeahead" is true, * flush all typeahead characters (used when interrupted by a CTRL-C). */ void -flush_buffers(typeahead) - int typeahead; +flush_buffers(flush_typeahead) + int flush_typeahead; { init_typebuf(); @@ -431,7 +431,7 @@ while (read_stuff(TRUE) != NUL) ; - if (typeahead) /* remove all typeahead */ + if (flush_typeahead) /* remove all typeahead */ { /* * We have to get all characters, because we may delete the first part @@ -470,6 +470,24 @@ } } +/* + * Discard the contents of the redo buffer and restore the previous redo + * buffer. + */ + void +CancelRedo() +{ + if (!block_redo) + { + free_buff(&redobuff); + redobuff = old_redobuff; + old_redobuff.bh_first.b_next = NULL; + start_stuff(); + while (read_stuff(TRUE) != NUL) + ; + } +} + #if defined(FEAT_AUTOCMD) || defined(FEAT_EVAL) || defined(PROTO) /* * Save redobuff and old_redobuff to save_redobuff and save_old_redobuff. @@ -635,11 +653,14 @@ /* * Stuff "s" into the stuff buffer, leaving special key codes unmodified and * escaping other K_SPECIAL and CSI bytes. + * Change CR, LF and ESC into a space. */ void stuffReadbuffSpec(s) char_u *s; { + int c; + while (*s != NUL) { if (*s == K_SPECIAL && s[1] != NUL && s[2] != NUL) @@ -649,11 +670,16 @@ s += 3; } else + { #ifdef FEAT_MBYTE - stuffcharReadbuff(mb_ptr2char_adv(&s)); + c = mb_ptr2char_adv(&s); #else - stuffcharReadbuff(*s++); + c = *s++; #endif + if (c == CAR || c == NL || c == ESC) + c = ' '; + stuffcharReadbuff(c); + } } } #endif @@ -683,9 +709,9 @@ * Read a character from the redo buffer. Translates K_SPECIAL, CSI and * multibyte characters. * The redo buffer is left as it is. - * if init is TRUE, prepare for redo, return FAIL if nothing to redo, OK - * otherwise - * if old is TRUE, use old_redobuff instead of redobuff + * If init is TRUE, prepare for redo, return FAIL if nothing to redo, OK + * otherwise. + * If old is TRUE, use old_redobuff instead of redobuff. */ static int read_redo(init, old_redo) @@ -697,7 +723,7 @@ int c; #ifdef FEAT_MBYTE int n; - char_u buf[MB_MAXBYTES]; + char_u buf[MB_MAXBYTES + 1]; int i; #endif @@ -1046,7 +1072,7 @@ int c; { #ifdef FEAT_MBYTE - char_u buf[MB_MAXBYTES]; + char_u buf[MB_MAXBYTES + 1]; #else char_u buf[4]; #endif @@ -1506,9 +1532,6 @@ } } -#define KL_PART_KEY -1 /* keylen value for incomplete key-code */ -#define KL_PART_MAP -2 /* keylen value for incomplete mapping */ - /* * Get the next input character. * Can return a special key or a multi-byte character. @@ -1524,7 +1547,7 @@ int c, c2; #ifdef FEAT_MBYTE int n; - char_u buf[MB_MAXBYTES]; + char_u buf[MB_MAXBYTES + 1]; int i; #endif @@ -2171,7 +2194,7 @@ if (!timedout) { /* break at a partly match */ - keylen = KL_PART_MAP; + keylen = KEYLEN_PART_MAP; break; } } @@ -2192,7 +2215,7 @@ /* If no partly match found, use the longest full * match. */ - if (keylen != KL_PART_MAP) + if (keylen != KEYLEN_PART_MAP) { mp = mp_match; keylen = mp_match_len; @@ -2230,7 +2253,7 @@ } /* Need more chars for partly match. */ if (mlen == typebuf.tb_len) - keylen = KL_PART_KEY; + keylen = KEYLEN_PART_KEY; else if (max_mlen < mlen) /* no match, may have to check for termcode at * next character */ @@ -2238,7 +2261,7 @@ } if ((mp == NULL || max_mlen >= mp_match_len) - && keylen != KL_PART_MAP) + && keylen != KEYLEN_PART_MAP) { int save_keylen = keylen; @@ -2259,13 +2282,14 @@ typebuf.tb_off] == RM_YES)) && !timedout) { - keylen = check_termcode(max_mlen + 1, NULL, 0); + keylen = check_termcode(max_mlen + 1, + NULL, 0, NULL); /* If no termcode matched but 'pastetoggle' * matched partially it's like an incomplete key * sequence. */ - if (keylen == 0 && save_keylen == KL_PART_KEY) - keylen = KL_PART_KEY; + if (keylen == 0 && save_keylen == KEYLEN_PART_KEY) + keylen = KEYLEN_PART_KEY; /* * When getting a partial match, but the last @@ -2302,7 +2326,7 @@ continue; } if (*s == NUL) /* need more characters */ - keylen = KL_PART_KEY; + keylen = KEYLEN_PART_KEY; } if (keylen >= 0) #endif @@ -2339,7 +2363,8 @@ if (keylen > 0) /* full matching terminal code */ { #if defined(FEAT_GUI) && defined(FEAT_MENU) - if (typebuf.tb_buf[typebuf.tb_off] == K_SPECIAL + if (typebuf.tb_len >= 2 + && typebuf.tb_buf[typebuf.tb_off] == K_SPECIAL && typebuf.tb_buf[typebuf.tb_off + 1] == KS_MENU) { @@ -2381,7 +2406,7 @@ /* Partial match: get some more characters. When a * matching mapping was found use that one. */ if (mp == NULL || keylen < 0) - keylen = KL_PART_KEY; + keylen = KEYLEN_PART_KEY; else keylen = mp_match_len; } @@ -2454,27 +2479,18 @@ /* * Handle ":map ": evaluate the {rhs} as an - * expression. Save and restore the typeahead so that - * getchar() can be used. Also save and restore the - * command line for "normal :". + * expression. Also save and restore the command line + * for "normal :". */ if (mp->m_expr) { - tasave_T tabuf; int save_vgetc_busy = vgetc_busy; - save_typeahead(&tabuf); - if (tabuf.typebuf_valid) - { - vgetc_busy = 0; - save_m_keys = vim_strsave(mp->m_keys); - save_m_str = vim_strsave(mp->m_str); - s = eval_map_expr(save_m_str, NUL); - vgetc_busy = save_vgetc_busy; - } - else - s = NULL; - restore_typeahead(&tabuf); + vgetc_busy = 0; + save_m_keys = vim_strsave(mp->m_keys); + save_m_str = vim_strsave(mp->m_str); + s = eval_map_expr(save_m_str, NUL); + vgetc_busy = save_vgetc_busy; } else #endif @@ -2553,7 +2569,8 @@ #endif && typebuf.tb_maplen == 0 && (State & INSERT) - && (p_timeout || (keylen == KL_PART_KEY && p_ttimeout)) + && (p_timeout + || (keylen == KEYLEN_PART_KEY && p_ttimeout)) && (c = inchar(typebuf.tb_buf + typebuf.tb_off + typebuf.tb_len, 3, 25L, typebuf.tb_change_cnt)) == 0) @@ -2711,8 +2728,11 @@ * are still available. But when those available characters * are part of a mapping, and we are going to do a blocking * wait here. Need to update the screen to display the - * changed text so far. */ - if ((State & INSERT) && advance && must_redraw != 0) + * changed text so far. Also for when 'lazyredraw' is set and + * redrawing was postponed because there was something in the + * input buffer (e.g., termresponse). */ + if (((State & INSERT) != 0 || p_lz) && (State & CMDLINE) == 0 + && advance && must_redraw != 0 && !need_wait_return) { update_screen(0); setcursor(); /* put cursor back where it belongs */ @@ -2783,9 +2803,9 @@ ? 0 : ((typebuf.tb_len == 0 || !(p_timeout || (p_ttimeout - && keylen == KL_PART_KEY))) + && keylen == KEYLEN_PART_KEY))) ? -1L - : ((keylen == KL_PART_KEY && p_ttm >= 0) + : ((keylen == KEYLEN_PART_KEY && p_ttm >= 0) ? p_ttm : p_tm)), typebuf.tb_change_cnt); @@ -2799,7 +2819,8 @@ edit_unputchar(); if (State & CMDLINE) unputcmdline(); - setcursor(); /* put cursor back where it belongs */ + else + setcursor(); /* put cursor back where it belongs */ } if (c < 0) @@ -3168,6 +3189,7 @@ int expr = FALSE; #endif int noremap; + char_u *orig_rhs; keys = arg; map_table = maphash; @@ -3251,9 +3273,9 @@ validate_maphash(); /* - * find end of keys and skip CTRL-Vs (and backslashes) in it + * Find end of keys and skip CTRL-Vs (and backslashes) in it. * Accept backslash like CTRL-V when 'cpoptions' does not contain 'B'. - * with :unmap white space is included in the keys, no argument possible + * with :unmap white space is included in the keys, no argument possible. */ p = keys; do_backslash = (vim_strchr(p_cpo, CPO_BSLASH) == NULL); @@ -3266,6 +3288,7 @@ } if (*p != NUL) *p++ = NUL; + p = skipwhite(p); rhs = p; hasarg = (*rhs != NUL); @@ -3288,6 +3311,7 @@ */ if (haskey) keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE, special); + orig_rhs = rhs; if (hasarg) { if (STRICMP(rhs, "") == 0) /* "" means nothing */ @@ -3298,7 +3322,7 @@ #ifdef FEAT_FKMAP /* - * when in right-to-left mode and alternate keymap option set, + * When in right-to-left mode and alternate keymap option set, * reverse the character flow in the rhs in Farsi. */ if (p_altkeymap && curwin->w_p_rl) @@ -3556,6 +3580,8 @@ } vim_free(mp->m_str); mp->m_str = newstr; + vim_free(mp->m_orig_str); + mp->m_orig_str = vim_strsave(orig_rhs); mp->m_noremap = noremap; mp->m_silent = silent; mp->m_mode = mode; @@ -3633,10 +3659,12 @@ mp->m_keys = vim_strsave(keys); mp->m_str = vim_strsave(rhs); + mp->m_orig_str = vim_strsave(orig_rhs); if (mp->m_keys == NULL || mp->m_str == NULL) { vim_free(mp->m_keys); vim_free(mp->m_str); + vim_free(mp->m_orig_str); vim_free(mp); retval = 4; /* no mem */ goto theend; @@ -3682,6 +3710,7 @@ mp = *mpp; vim_free(mp->m_keys); vim_free(mp->m_str); + vim_free(mp->m_orig_str); *mpp = mp->m_next; vim_free(mp); } @@ -3851,12 +3880,57 @@ } } +/* + * Return characters to represent the map mode in an allocated string. + * Returns NULL when out of memory. + */ + char_u * +map_mode_to_chars(mode) + int mode; +{ + garray_T mapmode; + + ga_init2(&mapmode, 1, 7); + + if ((mode & (INSERT + CMDLINE)) == INSERT + CMDLINE) + ga_append(&mapmode, '!'); /* :map! */ + else if (mode & INSERT) + ga_append(&mapmode, 'i'); /* :imap */ + else if (mode & LANGMAP) + ga_append(&mapmode, 'l'); /* :lmap */ + else if (mode & CMDLINE) + ga_append(&mapmode, 'c'); /* :cmap */ + else if ((mode & (NORMAL + VISUAL + SELECTMODE + OP_PENDING)) + == NORMAL + VISUAL + SELECTMODE + OP_PENDING) + ga_append(&mapmode, ' '); /* :map */ + else + { + if (mode & NORMAL) + ga_append(&mapmode, 'n'); /* :nmap */ + if (mode & OP_PENDING) + ga_append(&mapmode, 'o'); /* :omap */ + if ((mode & (VISUAL + SELECTMODE)) == VISUAL + SELECTMODE) + ga_append(&mapmode, 'v'); /* :vmap */ + else + { + if (mode & VISUAL) + ga_append(&mapmode, 'x'); /* :xmap */ + if (mode & SELECTMODE) + ga_append(&mapmode, 's'); /* :smap */ + } + } + + ga_append(&mapmode, NUL); + return (char_u *)mapmode.ga_data; +} + static void showmap(mp, local) mapblock_T *mp; int local; /* TRUE for buffer-local map */ { - int len = 1; + int len = 1; + char_u *mapchars; if (msg_didout || msg_silent != 0) { @@ -3864,49 +3938,15 @@ if (got_int) /* 'q' typed at MORE prompt */ return; } - if ((mp->m_mode & (INSERT + CMDLINE)) == INSERT + CMDLINE) - msg_putchar('!'); /* :map! */ - else if (mp->m_mode & INSERT) - msg_putchar('i'); /* :imap */ - else if (mp->m_mode & LANGMAP) - msg_putchar('l'); /* :lmap */ - else if (mp->m_mode & CMDLINE) - msg_putchar('c'); /* :cmap */ - else if ((mp->m_mode & (NORMAL + VISUAL + SELECTMODE + OP_PENDING)) - == NORMAL + VISUAL + SELECTMODE + OP_PENDING) - msg_putchar(' '); /* :map */ - else + + mapchars = map_mode_to_chars(mp->m_mode); + if (mapchars != NULL) { - len = 0; - if (mp->m_mode & NORMAL) - { - msg_putchar('n'); /* :nmap */ - ++len; - } - if (mp->m_mode & OP_PENDING) - { - msg_putchar('o'); /* :omap */ - ++len; - } - if ((mp->m_mode & (VISUAL + SELECTMODE)) == VISUAL + SELECTMODE) - { - msg_putchar('v'); /* :vmap */ - ++len; - } - else - { - if (mp->m_mode & VISUAL) - { - msg_putchar('x'); /* :xmap */ - ++len; - } - if (mp->m_mode & SELECTMODE) - { - msg_putchar('s'); /* :smap */ - ++len; - } - } + msg_puts(mapchars); + len = (int)STRLEN(mapchars); + vim_free(mapchars); } + while (++len <= 3) msg_putchar(' '); @@ -3931,12 +3971,21 @@ msg_putchar(' '); /* Use FALSE below if we only want things like to show up as such on - * the rhs, and not M-x etc, TRUE gets both -- webb - */ + * the rhs, and not M-x etc, TRUE gets both -- webb */ if (*mp->m_str == NUL) msg_puts_attr((char_u *)"", hl_attr(HLF_8)); else - msg_outtrans_special(mp->m_str, FALSE); + { + /* Remove escaping of CSI, because "m_str" is in a format to be used + * as typeahead. */ + char_u *s = vim_strsave(mp->m_str); + if (s != NULL) + { + vim_unescape_csi(s); + msg_outtrans_special(s, FALSE); + vim_free(s); + } + } #ifdef FEAT_EVAL if (p_verbose > 0) last_set_msg(mp->m_script_ID); @@ -4287,11 +4336,7 @@ int scol; /* starting column of the abbr. */ int j; char_u *s; -#ifdef FEAT_MBYTE char_u tb[MB_MAXBYTES + 4]; -#else - char_u tb[4]; -#endif mapblock_T *mp; #ifdef FEAT_LOCALMAP mapblock_T *mp2; @@ -4304,8 +4349,9 @@ if (typebuf.tb_no_abbr_cnt) /* abbrev. are not recursive */ return FALSE; - if ((KeyNoremap & (RM_NONE|RM_SCRIPT)) != 0) - /* no remapping implies no abbreviation */ + + /* no remapping implies no abbreviation, except for CTRL-] */ + if ((KeyNoremap & (RM_NONE|RM_SCRIPT)) != 0 && c != Ctrl_RSB) return FALSE; /* @@ -4478,12 +4524,25 @@ { char_u *res; char_u *p; + char_u *expr; char_u *save_cmd; pos_T save_cursor; + int save_msg_col; + int save_msg_row; + + /* Remove escaping of CSI, because "str" is in a format to be used as + * typeahead. */ + expr = vim_strsave(str); + if (expr == NULL) + return NULL; + vim_unescape_csi(expr); save_cmd = save_cmdline_alloc(); if (save_cmd == NULL) + { + vim_free(expr); return NULL; + } /* Forbid changing text or using ":normal" to avoid most of the bad side * effects. Also restore the cursor position. */ @@ -4493,16 +4552,23 @@ #endif set_vim_var_char(c); /* set v:char to the typed character */ save_cursor = curwin->w_cursor; - p = eval_to_string(str, NULL, FALSE); + save_msg_col = msg_col; + save_msg_row = msg_row; + p = eval_to_string(expr, NULL, FALSE); --textlock; #ifdef FEAT_EX_EXTRA --ex_normal_lock; #endif curwin->w_cursor = save_cursor; + msg_col = save_msg_col; + msg_row = save_msg_row; restore_cmdline_alloc(save_cmd); + vim_free(expr); + if (p == NULL) return NULL; + /* Escape CSI in the result to be able to use the string as typeahead. */ res = vim_strsave_escape_csi(p); vim_free(p); @@ -4995,19 +5061,21 @@ sourcing_name = save_name; } -#ifdef FEAT_EVAL +#if defined(FEAT_EVAL) || defined(PROTO) /* - * Check the string "keys" against the lhs of all mappings - * Return pointer to rhs of mapping (mapblock->m_str) - * NULL otherwise + * Check the string "keys" against the lhs of all mappings. + * Return pointer to rhs of mapping (mapblock->m_str). + * NULL when no mapping found. */ char_u * -check_map(keys, mode, exact, ign_mod, abbr) +check_map(keys, mode, exact, ign_mod, abbr, mp_ptr, local_ptr) char_u *keys; int mode; int exact; /* require exact match */ int ign_mod; /* ignore preceding modifier */ int abbr; /* do abbreviations */ + mapblock_T **mp_ptr; /* return: pointer to mapblock or NULL */ + int *local_ptr; /* return: buffer-local mapping or NULL */ { int hash; int len, minlen; @@ -5062,7 +5130,17 @@ minlen = mp->m_keylen - 3; } if (STRNCMP(s, keys, minlen) == 0) + { + if (mp_ptr != NULL) + *mp_ptr = mp; + if (local_ptr != NULL) +#ifdef FEAT_LOCALMAP + *local_ptr = local; +#else + *local_ptr = 0; +#endif return mp->m_str; + } } } } diff -Naur vim73.orig/src/globals.h vim73/src/globals.h --- vim73.orig/src/globals.h 2010-07-23 19:20:45.000000000 +0000 +++ vim73/src/globals.h 2012-07-20 20:31:18.067644988 +0000 @@ -113,9 +113,9 @@ * When '$' is included in 'cpoptions' option set: * When a change command is given that deletes only part of a line, a dollar * is put at the end of the changed text. dollar_vcol is set to the virtual - * column of this '$'. + * column of this '$'. -1 is used to indicate no $ is being displayed. */ -EXTERN colnr_T dollar_vcol INIT(= 0); +EXTERN colnr_T dollar_vcol INIT(= -1); #ifdef FEAT_INS_EXPAND /* @@ -510,9 +510,15 @@ EXTERN VimClipboard clip_plus; /* CLIPBOARD selection in X11 */ # else # define clip_plus clip_star /* there is only one clipboard */ +# define ONE_CLIPBOARD # endif -EXTERN int clip_unnamed INIT(= FALSE); -EXTERN int clip_autoselect INIT(= FALSE); + +# define CLIP_UNNAMED 1 +# define CLIP_UNNAMED_PLUS 2 +EXTERN int clip_unnamed INIT(= 0); /* above two values or'ed */ + +EXTERN int clip_autoselect_star INIT(= FALSE); +EXTERN int clip_autoselect_plus INIT(= FALSE); EXTERN int clip_autoselectml INIT(= FALSE); EXTERN int clip_html INIT(= FALSE); EXTERN regprog_T *clip_exclude_prog INIT(= NULL); @@ -530,6 +536,10 @@ EXTERN win_T *prevwin INIT(= NULL); /* previous window */ # define W_NEXT(wp) ((wp)->w_next) # define FOR_ALL_WINDOWS(wp) for (wp = firstwin; wp != NULL; wp = wp->w_next) +/* + * When using this macro "break" only breaks out of the inner loop. Use "goto" + * to break out of the tabpage loop. + */ # define FOR_ALL_TAB_WINDOWS(tp, wp) \ for ((tp) = first_tabpage; (tp) != NULL; (tp) = (tp)->tp_next) \ for ((wp) = ((tp) == curtab) \ @@ -728,9 +738,9 @@ #endif EXTERN pos_T saved_cursor /* w_cursor before formatting text. */ -# ifdef DO_INIT +#ifdef DO_INIT = INIT_POS_T(0, 0, 0) -# endif +#endif ; /* @@ -798,9 +808,9 @@ # endif EXTERN int has_mbyte INIT(= 0); /* any multi-byte encoding */ -#if defined(WIN3264) && defined(FEAT_MBYTE) +# if defined(WIN3264) && defined(FEAT_MBYTE) EXTERN int wide_WindowProc INIT(= FALSE); /* use wide WindowProc() */ -#endif +# endif /* * To speed up BYTELEN() we fill a table with the byte lengths whenever @@ -1052,10 +1062,6 @@ ; #endif -EXTERN linenr_T write_no_eol_lnum INIT(= 0); /* non-zero lnum when last line - of next binary write should - not have an end-of-line */ - #ifdef FEAT_WINDOWS EXTERN int postponed_split INIT(= 0); /* for CTRL-W CTRL-] command */ EXTERN int postponed_split_flags INIT(= 0); /* args for win_split() */ @@ -1094,8 +1100,8 @@ EXTERN int save_p_ls INIT(= -1); /* Save 'laststatus' setting */ EXTERN int save_p_wmh INIT(= -1); /* Save 'winminheight' setting */ EXTERN int wild_menu_showing INIT(= 0); -#define WM_SHOWN 1 /* wildmenu showing */ -#define WM_SCROLLED 2 /* wildmenu showing with scroll */ +# define WM_SHOWN 1 /* wildmenu showing */ +# define WM_SCROLLED 2 /* wildmenu showing with scroll */ #endif #ifdef MSWIN @@ -1305,9 +1311,9 @@ EXTERN Atom commProperty INIT(= None); EXTERN char_u *serverDelayedStartName INIT(= NULL); # else -# ifdef PROTO +# ifdef PROTO typedef int HWND; -# endif +# endif EXTERN HWND clientWindow INIT(= 0); # endif #endif @@ -1512,7 +1518,7 @@ EXTERN char_u e_sandbox[] INIT(= N_("E48: Not allowed in sandbox")); #endif EXTERN char_u e_secure[] INIT(= N_("E523: Not allowed here")); -#if defined(AMIGA) || defined(MACOS) || defined(MSWIN) || defined(RISCOS) \ +#if defined(AMIGA) || defined(MACOS) || defined(MSWIN) \ || defined(UNIX) || defined(VMS) || defined(OS2) EXTERN char_u e_screenmode[] INIT(= N_("E359: Screen mode setting not supported")); #endif @@ -1560,6 +1566,9 @@ (defined(FEAT_INS_EXPAND) && defined(FEAT_COMPL_FUNC)) EXTERN char_u e_notset[] INIT(= N_("E764: Option '%s' is not set")); #endif +#ifndef FEAT_CLIPBOARD +EXTERN char_u e_invalidreg[] INIT(= N_("E850: Invalid register name")); +#endif #ifdef MACOS_X_UNIX EXTERN short disallow_gui INIT(= FALSE); diff -Naur vim73.orig/src/gui.c vim73/src/gui.c --- vim73.orig/src/gui.c 2010-08-08 13:01:18.000000000 +0000 +++ vim73/src/gui.c 2012-07-20 20:31:18.074311659 +0000 @@ -37,6 +37,24 @@ static void gui_set_bg_color __ARGS((char_u *name)); static win_T *xy2win __ARGS((int x, int y)); +#if defined(UNIX) && !defined(__BEOS__) && !defined(MACOS_X) \ + && !defined(__APPLE__) +# define MAY_FORK +static void gui_do_fork __ARGS((void)); + +static int gui_read_child_pipe __ARGS((int fd)); + +/* Return values for gui_read_child_pipe */ +enum { + GUI_CHILD_IO_ERROR, + GUI_CHILD_OK, + GUI_CHILD_FAILED +}; + +#endif /* MAY_FORK */ + +static void gui_attempt_start __ARGS((void)); + static int can_update_cursor = TRUE; /* can display the cursor */ /* @@ -59,42 +77,53 @@ gui_start() { char_u *old_term; -#if defined(UNIX) && !defined(__BEOS__) && !defined(MACOS_X) -# define MAY_FORK - int dofork = TRUE; -#endif static int recursive = 0; old_term = vim_strsave(T_NAME); - /* - * Set_termname() will call gui_init() to start the GUI. - * Set the "starting" flag, to indicate that the GUI will start. - * - * We don't want to open the GUI shell until after we've read .gvimrc, - * otherwise we don't know what font we will use, and hence we don't know - * what size the shell should be. So if there are errors in the .gvimrc - * file, they will have to go to the terminal: Set full_screen to FALSE. - * full_screen will be set to TRUE again by a successful termcapinit(). - */ settmode(TMODE_COOK); /* stop RAW mode */ if (full_screen) cursor_on(); /* needed for ":gui" in .vimrc */ - gui.starting = TRUE; full_screen = FALSE; -#ifdef MAY_FORK - if (!gui.dofork || vim_strchr(p_go, GO_FORG) || recursive) - dofork = FALSE; -#endif ++recursive; - termcapinit((char_u *)"builtin_gui"); - gui.starting = recursive - 1; +#ifdef MAY_FORK + /* + * Quit the current process and continue in the child. + * Makes "gvim file" disconnect from the shell it was started in. + * Don't do this when Vim was started with "-f" or the 'f' flag is present + * in 'guioptions'. + */ + if (gui.dofork && !vim_strchr(p_go, GO_FORG) && recursive <= 1) + { + gui_do_fork(); + } + else +#endif + { +#ifdef FEAT_GUI_GTK + /* If there is 'f' in 'guioptions' and specify -g argument, + * gui_mch_init_check() was not called yet. */ + if (gui_mch_init_check() != OK) + exit(1); +#endif + gui_attempt_start(); + } if (!gui.in_use) /* failed to start GUI */ { - termcapinit(old_term); /* back to old term settings */ + /* Back to old term settings + * + * FIXME: If we got here because a child process failed and flagged to + * the parent to resume, and X11 is enabled with FEAT_TITLE, this will + * hit an X11 I/O error and do a longjmp(), leaving recursive + * permanently set to 1. This is probably not as big a problem as it + * sounds, because gui_mch_init() in both gui_x11.c and gui_gtk_x11.c + * return "OK" unconditionally, so it would be very difficult to + * actually hit this case. + */ + termcapinit(old_term); settmode(TMODE_RAW); /* restart RAW mode */ #ifdef FEAT_TITLE set_title_defaults(); /* set 'title' and 'icon' again */ @@ -103,101 +132,223 @@ vim_free(old_term); +#ifdef FEAT_AUTOCMD + /* If the GUI started successfully, trigger the GUIEnter event, otherwise + * the GUIFailed event. */ + gui_mch_update(); + apply_autocmds(gui.in_use ? EVENT_GUIENTER : EVENT_GUIFAILED, + NULL, NULL, FALSE, curbuf); +#endif + --recursive; +} + +/* + * Set_termname() will call gui_init() to start the GUI. + * Set the "starting" flag, to indicate that the GUI will start. + * + * We don't want to open the GUI shell until after we've read .gvimrc, + * otherwise we don't know what font we will use, and hence we don't know + * what size the shell should be. So if there are errors in the .gvimrc + * file, they will have to go to the terminal: Set full_screen to FALSE. + * full_screen will be set to TRUE again by a successful termcapinit(). + */ + static void +gui_attempt_start() +{ + static int recursive = 0; + + ++recursive; + gui.starting = TRUE; + +#ifdef FEAT_GUI_GTK + gui.event_time = GDK_CURRENT_TIME; +#endif + + termcapinit((char_u *)"builtin_gui"); + gui.starting = recursive - 1; + #if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_X11) if (gui.in_use) + { +# ifdef FEAT_EVAL + Window x11_window; + Display *x11_display; + + if (gui_get_x11_windis(&x11_window, &x11_display) == OK) + set_vim_var_nr(VV_WINDOWID, (long)x11_window); +# endif + /* Display error messages in a dialog now. */ display_errors(); + } #endif + --recursive; +} -#if defined(MAY_FORK) && !defined(__QNXNTO__) - /* - * Quit the current process and continue in the child. - * Makes "gvim file" disconnect from the shell it was started in. - * Don't do this when Vim was started with "-f" or the 'f' flag is present - * in 'guioptions'. - */ - if (gui.in_use && dofork) +#ifdef MAY_FORK + +/* for waitpid() */ +# if defined(HAVE_SYS_WAIT_H) || defined(HAVE_UNION_WAIT) +# include +# endif + +/* + * Create a new process, by forking. In the child, start the GUI, and in + * the parent, exit. + * + * If something goes wrong, this will return with gui.in_use still set + * to FALSE, in which case the caller should continue execution without + * the GUI. + * + * If the child fails to start the GUI, then the child will exit and the + * parent will return. If the child succeeds, then the parent will exit + * and the child will return. + */ + static void +gui_do_fork() +{ +#ifdef __QNXNTO__ + procmgr_daemon(0, PROCMGR_DAEMON_KEEPUMASK | PROCMGR_DAEMON_NOCHDIR | + PROCMGR_DAEMON_NOCLOSE | PROCMGR_DAEMON_NODEVNULL); + gui_attempt_start(); + return; +#else + int pipefd[2]; /* pipe between parent and child */ + int pipe_error; + int status; + int exit_status; + pid_t pid = -1; + + /* Setup a pipe between the child and the parent, so that the parent + * knows when the child has done the setsid() call and is allowed to + * exit. */ + pipe_error = (pipe(pipefd) < 0); + pid = fork(); + if (pid < 0) /* Fork error */ { - int pipefd[2]; /* pipe between parent and child */ - int pipe_error; - char dummy; - pid_t pid = -1; - - /* Setup a pipe between the child and the parent, so that the parent - * knows when the child has done the setsid() call and is allowed to - * exit. */ - pipe_error = (pipe(pipefd) < 0); - pid = fork(); - if (pid > 0) /* Parent */ - { - /* Give the child some time to do the setsid(), otherwise the - * exit() may kill the child too (when starting gvim from inside a - * gvim). */ - if (pipe_error) - ui_delay(300L, TRUE); - else + EMSG(_("E851: Failed to create a new process for the GUI")); + return; + } + else if (pid > 0) /* Parent */ + { + /* Give the child some time to do the setsid(), otherwise the + * exit() may kill the child too (when starting gvim from inside a + * gvim). */ + if (!pipe_error) + { + /* The read returns when the child closes the pipe (or when + * the child dies for some reason). */ + close(pipefd[1]); + status = gui_read_child_pipe(pipefd[0]); + if (status == GUI_CHILD_FAILED) + { + /* The child failed to start the GUI, so the caller must + * continue. There may be more error information written + * to stderr by the child. */ +# ifdef __NeXT__ + wait4(pid, &exit_status, 0, (struct rusage *)0); +# else + waitpid(pid, &exit_status, 0); +# endif + EMSG(_("E852: The child process failed to start the GUI")); + return; + } + else if (status == GUI_CHILD_IO_ERROR) { - /* The read returns when the child closes the pipe (or when - * the child dies for some reason). */ - close(pipefd[1]); - ignored = (int)read(pipefd[0], &dummy, (size_t)1); - close(pipefd[0]); + pipe_error = TRUE; } + /* else GUI_CHILD_OK: parent exit */ + } - /* When swapping screens we may need to go to the next line, e.g., - * after a hit-enter prompt and using ":gui". */ - if (newline_on_exit) - mch_errmsg("\r\n"); + if (pipe_error) + ui_delay(300L, TRUE); - /* - * The parent must skip the normal exit() processing, the child - * will do it. For example, GTK messes up signals when exiting. - */ - _exit(0); - } + /* When swapping screens we may need to go to the next line, e.g., + * after a hit-enter prompt and using ":gui". */ + if (newline_on_exit) + mch_errmsg("\r\n"); -# if defined(HAVE_SETSID) || defined(HAVE_SETPGID) /* - * Change our process group. On some systems/shells a CTRL-C in the - * shell where Vim was started would otherwise kill gvim! + * The parent must skip the normal exit() processing, the child + * will do it. For example, GTK messes up signals when exiting. */ - if (pid == 0) /* child */ + _exit(0); + } + /* Child */ + +#ifdef FEAT_GUI_GTK + /* Call gtk_init_check() here after fork(). See gui_init_check(). */ + if (gui_mch_init_check() != OK) + exit(1); +#endif + +# if defined(HAVE_SETSID) || defined(HAVE_SETPGID) + /* + * Change our process group. On some systems/shells a CTRL-C in the + * shell where Vim was started would otherwise kill gvim! + */ # if defined(HAVE_SETSID) - (void)setsid(); + (void)setsid(); # else - (void)setpgid(0, 0); + (void)setpgid(0, 0); # endif # endif - if (!pipe_error) - { - close(pipefd[0]); - close(pipefd[1]); - } + if (!pipe_error) + close(pipefd[0]); # if defined(FEAT_GUI_GNOME) && defined(FEAT_SESSION) - /* Tell the session manager our new PID */ - gui_mch_forked(); + /* Tell the session manager our new PID */ + gui_mch_forked(); # endif + + /* Try to start the GUI */ + gui_attempt_start(); + + /* Notify the parent */ + if (!pipe_error) + { + if (gui.in_use) + write_eintr(pipefd[1], "ok", 3); + else + write_eintr(pipefd[1], "fail", 5); + close(pipefd[1]); } -#else -# if defined(__QNXNTO__) - if (gui.in_use && dofork) - procmgr_daemon(0, PROCMGR_DAEMON_KEEPUMASK | PROCMGR_DAEMON_NOCHDIR | - PROCMGR_DAEMON_NOCLOSE | PROCMGR_DAEMON_NODEVNULL); -# endif -#endif -#ifdef FEAT_AUTOCMD - /* If the GUI started successfully, trigger the GUIEnter event, otherwise - * the GUIFailed event. */ - gui_mch_update(); - apply_autocmds(gui.in_use ? EVENT_GUIENTER : EVENT_GUIFAILED, - NULL, NULL, FALSE, curbuf); + /* If we failed to start the GUI, exit now. */ + if (!gui.in_use) + exit(1); #endif +} - --recursive; +/* + * Read from a pipe assumed to be connected to the child process (this + * function is called from the parent). + * Return GUI_CHILD_OK if the child successfully started the GUI, + * GUY_CHILD_FAILED if the child failed, or GUI_CHILD_IO_ERROR if there was + * some other error. + * + * The file descriptor will be closed before the function returns. + */ + static int +gui_read_child_pipe(int fd) +{ + long bytes_read; +#define READ_BUFFER_SIZE 10 + char buffer[READ_BUFFER_SIZE]; + + bytes_read = read_eintr(fd, buffer, READ_BUFFER_SIZE - 1); +#undef READ_BUFFER_SIZE + close(fd); + if (bytes_read < 0) + return GUI_CHILD_IO_ERROR; + buffer[bytes_read] = NUL; + if (strcmp(buffer, "ok") == 0) + return GUI_CHILD_OK; + return GUI_CHILD_FAILED; } +#endif /* MAY_FORK */ + /* * Call this when vim starts up, whether or not the GUI is started */ @@ -291,7 +442,17 @@ #ifdef ALWAYS_USE_GUI result = OK; #else +# ifdef FEAT_GUI_GTK + /* + * Note: Don't call gtk_init_check() before fork, it will be called after + * the fork. When calling it before fork, it make vim hang for a while. + * See gui_do_fork(). + * Use a simpler check if the GUI window can probably be opened. + */ + result = gui.dofork ? gui_mch_early_init_check() : gui_mch_init_check(); +# else result = gui_mch_init_check(); +# endif #endif return result; } @@ -1392,7 +1553,7 @@ if (!gui.shell_created) return; -#ifdef MSWIN +#if defined(MSWIN) || defined(FEAT_GUI_GTK) /* If not setting to a user specified size and maximized, calculate the * number of characters that fit in the maximized window. */ if (!mustset && gui_mch_maximized()) @@ -2146,7 +2307,7 @@ if (highlight_mask & (HL_INVERSE | HL_STANDOUT)) { -#if defined(AMIGA) || defined(RISCOS) +#if defined(AMIGA) gui_mch_set_colors(bg_color, fg_color); #else gui_mch_set_fg_color(bg_color); @@ -2155,7 +2316,7 @@ } else { -#if defined(AMIGA) || defined(RISCOS) +#if defined(AMIGA) gui_mch_set_colors(fg_color, bg_color); #else gui_mch_set_fg_color(fg_color); @@ -2183,7 +2344,7 @@ if (back != 0 && ((draw_flags & DRAW_BOLD) || (highlight_mask & HL_ITALIC))) return FAIL; -#if defined(RISCOS) || defined(FEAT_GUI_GTK) +#if defined(FEAT_GUI_GTK) /* If there's no italic font, then fake it. * For GTK2, we don't need a different font for italic style. */ if (hl_mask_todo & HL_ITALIC) @@ -2352,7 +2513,7 @@ if (draw_sign) /* Draw the sign on top of the spaces. */ gui_mch_drawsign(gui.row, col, gui.highlight_mask); -# if defined(FEAT_NETBEANS_INTG) && (defined(FEAT_GUI_MOTIF) \ +# if defined(FEAT_NETBEANS_INTG) && (defined(FEAT_GUI_X11) \ || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_W32)) if (multi_sign) netbeans_draw_multisign_indicator(gui.row); @@ -2975,26 +3136,11 @@ did_clip = TRUE; } /* Allow the left button to start the selection */ - else if (button == -# ifdef RISCOS - /* Only start a drag on a drag event. Otherwise - * we don't get a release event. */ - MOUSE_DRAG -# else - MOUSE_LEFT -# endif - ) - { - clip_start_selection(X_2_COL(x), Y_2_ROW(y), repeated_click); - did_clip = TRUE; - } -# ifdef RISCOS else if (button == MOUSE_LEFT) { - clip_clear_selection(); + clip_start_selection(X_2_COL(x), Y_2_ROW(y), repeated_click); did_clip = TRUE; } -# endif /* Always allow pasting */ if (button != MOUSE_MIDDLE) @@ -3008,7 +3154,7 @@ } if (clip_star.state != SELECT_CLEARED && !did_clip) - clip_clear_selection(); + clip_clear_selection(&clip_star); #endif /* Don't put events in the input queue now. */ @@ -4893,7 +5039,7 @@ if (STRLEN(p) > 2000) STRCPY(p + 2000 - 14, "...(truncated)"); (void)do_dialog(VIM_ERROR, (char_u *)_("Error"), - p, (char_u *)_("&Ok"), 1, NULL); + p, (char_u *)_("&Ok"), 1, NULL, FALSE); break; } ga_clear(&error_ga); diff -Naur vim73.orig/src/gui.h vim73/src/gui.h --- vim73.orig/src/gui.h 2010-07-17 19:40:58.000000000 +0000 +++ vim73/src/gui.h 2012-07-20 20:31:11.674307068 +0000 @@ -52,10 +52,6 @@ # include */ #endif -#ifdef RISCOS -# include "gui_riscos.h" -#endif - #ifdef FEAT_GUI_PHOTON # include # include @@ -151,7 +147,7 @@ #define DRAW_BOLD 0x02 /* draw bold text */ #define DRAW_UNDERL 0x04 /* draw underline text */ #define DRAW_UNDERC 0x08 /* draw undercurl text */ -#if defined(RISCOS) || defined(FEAT_GUI_GTK) +#if defined(FEAT_GUI_GTK) # define DRAW_ITALIC 0x10 /* draw italic text */ #endif #define DRAW_CURSOR 0x20 /* drawing block cursor (win32) */ @@ -219,9 +215,6 @@ #ifdef FEAT_GUI_MAC ControlHandle id; /* A handle to the scrollbar */ #endif -#ifdef RISCOS - int id; /* Window handle of scrollbar window */ -#endif #ifdef FEAT_GUI_PHOTON PtWidget_t *id; #endif @@ -408,6 +401,8 @@ GtkAccelGroup *accel_group; GtkWidget *filedlg; /* file selection dialog */ char_u *browse_fname; /* file name from filedlg */ + + guint32 event_time; #endif /* FEAT_GUI_GTK */ #if defined(FEAT_GUI_TABLINE) \ @@ -450,14 +445,6 @@ int visibility; /* Is window partially/fully obscured? */ #endif -#ifdef RISCOS - int window_handle; - char_u *window_title; - int window_title_size; - int fg_colour; /* in 0xBBGGRR format */ - int bg_colour; -#endif - #ifdef FEAT_GUI_PHOTON PtWidget_t *vimWindow; /* PtWindow */ PtWidget_t *vimTextArea; /* PtRaw */ diff -Naur vim73.orig/src/gui_athena.c vim73/src/gui_athena.c --- vim73.orig/src/gui_athena.c 2010-08-08 13:01:39.000000000 +0000 +++ vim73/src/gui_athena.c 2012-07-20 20:31:09.277638673 +0000 @@ -2117,13 +2117,14 @@ } int -gui_mch_dialog(type, title, message, buttons, dfltbutton, textfield) +gui_mch_dialog(type, title, message, buttons, dfltbutton, textfield, ex_cmd) int type UNUSED; char_u *title; char_u *message; char_u *buttons; int dfltbutton UNUSED; char_u *textfield; + int ex_cmd UNUSED; { char_u *buts; char_u *p, *next; diff -Naur vim73.orig/src/gui_gtk.c vim73/src/gui_gtk.c --- vim73.orig/src/gui_gtk.c 2010-07-20 11:15:22.000000000 +0000 +++ vim73/src/gui_gtk.c 2012-07-20 20:31:17.964311580 +0000 @@ -90,6 +90,13 @@ static void entry_activate_cb(GtkWidget *widget, gpointer data); static void entry_changed_cb(GtkWidget *entry, GtkWidget *dialog); static void find_replace_cb(GtkWidget *widget, gpointer data); +#if defined(FEAT_BROWSE) || defined(PROTO) +static void recent_func_log_func( + const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer user_data); +#endif #if defined(FEAT_TOOLBAR) /* @@ -772,9 +779,6 @@ /* * Implementation of the file selector related stuff */ -#if GTK_CHECK_VERSION(2,4,0) -# define USE_FILE_CHOOSER -#endif #ifndef USE_FILE_CHOOSER static void @@ -833,12 +837,15 @@ char_u *dflt, char_u *ext UNUSED, char_u *initdir, - char_u *filter UNUSED) + char_u *filter) { #ifdef USE_FILE_CHOOSER GtkWidget *fc; #endif char_u dirbuf[MAXPATHL]; + guint log_handler; + const gchar *domain = "Gtk"; + GtkFileFilter *gfilter; title = CONVERT_TO_UTF8(title); @@ -853,6 +860,11 @@ /* If our pointer is currently hidden, then we should show it. */ gui_mch_mousehide(FALSE); + /* Hack: The GTK file dialog warns when it can't access a new file, this + * makes it shut up. http://bugzilla.gnome.org/show_bug.cgi?id=664587 */ + log_handler = g_log_set_handler(domain, G_LOG_LEVEL_WARNING, + recent_func_log_func, NULL); + #ifdef USE_FILE_CHOOSER /* We create the dialog each time, so that the button text can be "Open" * or "Save" according to the action. */ @@ -865,6 +877,45 @@ NULL); gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fc), (const gchar *)dirbuf); + + if (filter != NULL && *filter != NUL) + { + int i = 0; + char_u *patt; + char_u *p = filter; + + gfilter = gtk_file_filter_new(); + patt = alloc(STRLEN(filter)); + while (p != NULL && *p != NUL) + { + if (*p == '\n' || *p == ';' || *p == '\t') + { + STRNCPY(patt, filter, i); + patt[i] = '\0'; + if (*p == '\t') + gtk_file_filter_set_name(gfilter, (gchar *)patt); + else + { + gtk_file_filter_add_pattern(gfilter, (gchar *)patt); + if (*p == '\n') + { + gtk_file_chooser_add_filter((GtkFileChooser *)fc, + gfilter); + if (*(p + 1) != NUL) + gfilter = gtk_file_filter_new(); + } + } + filter = ++p; + i = 0; + } + else + { + p++; + i++; + } + } + vim_free(patt); + } if (saving && dflt != NULL && *dflt != NUL) gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(fc), (char *)dflt); @@ -916,6 +967,7 @@ gtk_widget_show(gui.filedlg); gtk_main(); #endif + g_log_remove_handler(domain, log_handler); CONVERT_TO_UTF8_FREE(title); if (gui.browse_fname == NULL) @@ -1268,7 +1320,8 @@ char_u *message, /* message text */ char_u *buttons, /* names of buttons */ int def_but, /* default button */ - char_u *textfield) /* text for textfield or NULL */ + char_u *textfield, /* text for textfield or NULL */ + int ex_cmd UNUSED) { GtkWidget *dialog; GtkWidget *entry = NULL; @@ -1287,6 +1340,9 @@ entry = gtk_entry_new(); gtk_widget_show(entry); + /* Make Enter work like pressing OK. */ + gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE); + text = CONVERT_TO_UTF8(textfield); gtk_entry_set_text(GTK_ENTRY(entry), (const char *)text); CONVERT_TO_UTF8_FREE(text); @@ -1387,7 +1443,7 @@ gtk_menu_popup(GTK_MENU(menu->submenu_id), NULL, NULL, (GtkMenuPositionFunc)NULL, NULL, - 3U, (guint32)GDK_CURRENT_TIME); + 3U, gui.event_time); } /* Ugly global variable to pass "mouse_pos" flag from gui_make_popup() to @@ -1795,7 +1851,6 @@ char_u *repl_text; gboolean direction_down; SharedFindReplace *sfr; - int rc; flags = (int)(long)data; /* avoid a lint warning here */ @@ -1821,7 +1876,7 @@ repl_text = CONVERT_FROM_UTF8(repl_text); find_text = CONVERT_FROM_UTF8(find_text); - rc = gui_do_findrepl(flags, find_text, repl_text, direction_down); + gui_do_findrepl(flags, find_text, repl_text, direction_down); CONVERT_FROM_UTF8_FREE(repl_text); CONVERT_FROM_UTF8_FREE(find_text); } @@ -1879,3 +1934,15 @@ * backwards compatibility anyway. */ do_cmdline_cmd((char_u *)"emenu ToolBar.FindHelp"); } + +#if defined(FEAT_BROWSE) || defined(PROTO) + static void +recent_func_log_func(const gchar *log_domain UNUSED, + GLogLevelFlags log_level UNUSED, + const gchar *message UNUSED, + gpointer user_data UNUSED) +{ + /* We just want to suppress the warnings. */ + /* http://bugzilla.gnome.org/show_bug.cgi?id=664587 */ +} +#endif diff -Naur vim73.orig/src/gui_gtk_x11.c vim73/src/gui_gtk_x11.c --- vim73.orig/src/gui_gtk_x11.c 2010-08-15 11:52:15.000000000 +0000 +++ vim73/src/gui_gtk_x11.c 2012-07-20 20:31:16.157643621 +0000 @@ -86,7 +86,6 @@ #ifdef HAVE_X11_SUNKEYSYM_H # include -static guint32 clipboard_event_time = CurrentTime; #endif /* @@ -933,7 +932,7 @@ guint state; char_u *s, *d; - clipboard_event_time = event->time; + gui.event_time = event->time; key_sym = event->keyval; state = event->state; @@ -1128,7 +1127,7 @@ GdkEventKey *event, gpointer data UNUSED) { - clipboard_event_time = event->time; + gui.event_time = event->time; /* * GTK+ 2 input methods may do fancy stuff on key release events too. * With the default IM for instance, you can enter any UCS code point @@ -1172,7 +1171,7 @@ char_u *tmpbuf = NULL; guchar *tmpbuf_utf8 = NULL; int len; - int motion_type; + int motion_type = MAUTO; if (data->selection == clip_plus.gtk_sel_atom) cbd = &clip_plus; @@ -1181,7 +1180,6 @@ text = (char_u *)data->data; len = data->length; - motion_type = MCHAR; if (text == NULL || len <= 0) { @@ -1416,7 +1414,29 @@ } /* - * Check if the GUI can be started. Called before gvimrc is sourced. + * Check if the GUI can be started. Called before gvimrc is sourced and + * before fork(). + * Return OK or FAIL. + */ + int +gui_mch_early_init_check(void) +{ + char_u *p; + + /* Guess that when $DISPLAY isn't set the GUI can't start. */ + p = mch_getenv((char_u *)"DISPLAY"); + if (p == NULL || *p == NUL) + { + gui.dying = TRUE; + EMSG(_((char *)e_opendisp)); + return FAIL; + } + return OK; +} + +/* + * Check if the GUI can be started. Called before gvimrc is sourced but after + * fork(). * Return OK or FAIL. */ int @@ -1622,7 +1642,7 @@ int x, y; int_u vim_modifiers; - clipboard_event_time = event->time; + gui.event_time = event->time; /* Make sure we have focus now we've been selected */ if (gtk_socket_id != 0 && !GTK_WIDGET_HAS_FOCUS(widget)) @@ -1733,7 +1753,7 @@ int x, y; int_u vim_modifiers; - clipboard_event_time = event->time; + gui.event_time = event->time; /* Remove any motion "machine gun" timers used for automatic further extension of allocation areas if outside of the applications window @@ -3052,7 +3072,7 @@ for (i = 0; i < (int)N_SELECTION_TARGETS; ++i) { - /* OpenOffice tries to use TARGET_HTML and fails when it doesn't + /* OpenOffice tries to use TARGET_HTML and fails when we don't * return something, instead of trying another target. Therefore only * offer TARGET_HTML when it works. */ if (!clip_html && selection_targets[i].info == TARGET_HTML) @@ -3083,7 +3103,7 @@ for (i = 0; i < (int)N_DND_TARGETS; ++i) { - if (!clip_html && selection_targets[i].info == TARGET_HTML) + if (!clip_html && dnd_targets[i].info == TARGET_HTML) n_targets--; else targets[j++] = dnd_targets[i]; @@ -3093,7 +3113,7 @@ gtk_drag_dest_set(gui.drawarea, GTK_DEST_DEFAULT_ALL, targets, n_targets, - GDK_ACTION_COPY); + GDK_ACTION_COPY | GDK_ACTION_MOVE); } /* @@ -3902,6 +3922,21 @@ } /* + * Called when the font changed while the window is maximized. Compute the + * new Rows and Columns. This is like resizing the window. + */ + void +gui_mch_newfont() +{ + int w, h; + + gtk_window_get_size(GTK_WINDOW(gui.mainwin), &w, &h); + w -= get_menu_tool_width(); + h -= get_menu_tool_height(); + gui_resize_shell(w, h); +} + +/* * Set the windows size. */ void @@ -4411,14 +4446,9 @@ if (gui_mch_maximized()) { - int w, h; - /* Update lines and columns in accordance with the new font, keep the * window maximized. */ - gtk_window_get_size(GTK_WINDOW(gui.mainwin), &w, &h); - w -= get_menu_tool_width(); - h -= get_menu_tool_height(); - gui_resize_shell(w, h); + gui_mch_newfont(); } else { @@ -5419,7 +5449,7 @@ } #if defined(FEAT_NETBEANS_INTG) - /* Process the queued netbeans messages. */ + /* Process any queued netbeans messages. */ netbeans_parse_messages(); #endif @@ -5654,7 +5684,7 @@ int success; success = gtk_selection_owner_set(gui.drawarea, cbd->gtk_sel_atom, - clipboard_event_time); + gui.event_time); gui_mch_update(); return (success) ? OK : FAIL; } diff -Naur vim73.orig/src/gui_mac.c vim73/src/gui_mac.c --- vim73.orig/src/gui_mac.c 2010-08-14 19:39:54.000000000 +0000 +++ vim73/src/gui_mac.c 2012-07-20 20:31:13.584308441 +0000 @@ -1480,7 +1480,7 @@ * * Returns the index inside the menu wher */ - short /* Shoulde we return MenuItemIndex? */ + short /* Should we return MenuItemIndex? */ gui_mac_get_menu_item_index(vimmenu_T *pMenu) { short index; @@ -1823,7 +1823,7 @@ p.h += gui.scrollbar_width; if (gui.which_scrollbars[SBAR_RIGHT]) p.h += gui.scrollbar_width; - /* ideal height is as heigh as we can get */ + /* ideal height is as high as we can get */ p.v = 15 * 1024; thePart = IsWindowInStandardState(whichWindow, &p, &r) @@ -1840,7 +1840,7 @@ p.v -= gui.scrollbar_height; p.v -= p.v % gui.char_height; p.v += 2 * gui.border_width; - if (gui.which_scrollbars[SBAR_BOTTOM]); + if (gui.which_scrollbars[SBAR_BOTTOM]) p.v += gui.scrollbar_height; ZoomWindowIdeal(whichWindow, thePart, &p); @@ -3216,7 +3216,7 @@ { /* TODO: * This proc is called when Normal is set to a value - * so what msut be done? I don't know + * so what must be done? I don't know */ } @@ -3303,7 +3303,6 @@ *x = bounds.left; *y = bounds.top; return OK; - return FAIL; } /* @@ -4481,7 +4480,7 @@ * event arrives. No need to check for input_buf_full because we are * returning as soon as it contains a single char. */ - /* TODO: reduce wtime accordinly??? */ + /* TODO: reduce wtime accordingly??? */ if (wtime > -1) sleeppyTick = 60 * wtime / 1000; else @@ -4671,7 +4670,7 @@ if (flavor) type = **textOfClip; else - type = (strchr(*textOfClip, '\r') != NULL) ? MLINE : MCHAR; + type = MAUTO; tempclip = lalloc(scrapSize + 1, TRUE); mch_memmove(tempclip, *textOfClip + flavor, scrapSize); @@ -5583,7 +5582,8 @@ char_u *message, char_u *buttons, int dfltbutton, - char_u *textfield) + char_u *textfield, + int ex_cmd) { Handle buttonDITL; Handle iconDITL; @@ -5723,13 +5723,13 @@ iconDITL = GetResource('DITL', 131); switch (type) { - case VIM_GENERIC: useIcon = kNoteIcon; - case VIM_ERROR: useIcon = kStopIcon; - case VIM_WARNING: useIcon = kCautionIcon; - case VIM_INFO: useIcon = kNoteIcon; - case VIM_QUESTION: useIcon = kNoteIcon; - default: useIcon = kStopIcon; - }; + case VIM_GENERIC: + case VIM_INFO: + case VIM_QUESTION: useIcon = kNoteIcon; break; + case VIM_WARNING: useIcon = kCautionIcon; break; + case VIM_ERROR: useIcon = kStopIcon; break; + default: useIcon = kStopIcon; + } AppendDITL(theDialog, iconDITL, overlayDITL); ReleaseResource(iconDITL); GetDialogItem(theDialog, iconItm.idx, &itemType, &itemHandle, &box); @@ -5892,7 +5892,7 @@ return itemHit; /* - * Usefull thing which could be used + * Useful thing which could be used * SetDialogTimeout(): Auto click a button after timeout * SetDialogTracksCursor() : Get the I-beam cursor over input box * MoveDialogItem(): Probably better than SetDialogItem @@ -6100,7 +6100,7 @@ #endif /* - * Transfered from os_mac.c for MacOS X using os_unix.c prep work + * Transferred from os_mac.c for MacOS X using os_unix.c prep work */ int @@ -6543,7 +6543,7 @@ static ControlRef dataBrowser = NULL; // when the tabline is hidden, vim doesn't call update_tabline(). When -// the tabline is shown again, show_tabline() is called before upate_tabline(), +// the tabline is shown again, show_tabline() is called before update_tabline(), // and because of this, the tab labels and vims internal tabs are out of sync // for a very short time. to prevent inconsistent state, we store the labels // of the tabs, not pointers to the tabs (which are invalid for a short time). diff -Naur vim73.orig/src/gui_motif.c vim73/src/gui_motif.c --- vim73.orig/src/gui_motif.c 2010-08-08 13:04:15.000000000 +0000 +++ vim73/src/gui_motif.c 2012-07-20 20:31:09.287638679 +0000 @@ -2549,13 +2549,14 @@ #endif int -gui_mch_dialog(type, title, message, button_names, dfltbutton, textfield) +gui_mch_dialog(type, title, message, button_names, dfltbutton, textfield, ex_cmd) int type UNUSED; char_u *title; char_u *message; char_u *button_names; int dfltbutton; char_u *textfield; /* buffer of size IOSIZE */ + int ex_cmd UNUSED; { char_u *buts; char_u *p, *next; diff -Naur vim73.orig/src/gui_photon.c vim73/src/gui_photon.c --- vim73.orig/src/gui_photon.c 2010-05-15 11:04:08.000000000 +0000 +++ vim73/src/gui_photon.c 2012-07-20 20:31:12.694307802 +0000 @@ -32,9 +32,9 @@ #endif #define ARRAY_LENGTH(a) (sizeof(a) / sizeof(a[0])) -#define RGB(r,g,b) PgRGB(r,g,b) +#define RGB(r, g, b) PgRGB(r, g, b) -#define EVENT_BUFFER_SIZE sizeof( PhEvent_t ) + 1000 +#define EVENT_BUFFER_SIZE sizeof(PhEvent_t) + 1000 /* Some defines for gui_mch_mousehide() */ #define MOUSE_HIDE TRUE @@ -206,53 +206,53 @@ static PtCallbackF_t gui_ph_handle_menu_unrealized; #ifdef USE_PANEL_GROUP -static void gui_ph_get_panelgroup_margins( short*, short*, short*, short* ); +static void gui_ph_get_panelgroup_margins(short*, short*, short*, short*); #endif #ifdef FEAT_TOOLBAR -static PhImage_t *gui_ph_toolbar_find_icon( vimmenu_T *menu ); +static PhImage_t *gui_ph_toolbar_find_icon(vimmenu_T *menu); #endif -static void gui_ph_draw_start( void ); -static void gui_ph_draw_end( void ); +static void gui_ph_draw_start(void); +static void gui_ph_draw_end(void); /* Set the text for the balloon */ -static PtWidget_t * gui_ph_show_tooltip( PtWidget_t *window, +static PtWidget_t * gui_ph_show_tooltip(PtWidget_t *window, PtWidget_t *widget, int position, char *text, char *font, PgColor_t fill_color, - PgColor_t text_color ); + PgColor_t text_color); /****************************************************************************/ -static PtWidget_t * gui_ph_show_tooltip( PtWidget_t *window, +static PtWidget_t * gui_ph_show_tooltip(PtWidget_t *window, PtWidget_t *widget, int position, char *text, char *font, PgColor_t fill_color, - PgColor_t text_color ) + PgColor_t text_color) { PtArg_t arg; vimmenu_T *menu; char_u *tooltip; - PtSetArg( &arg, Pt_ARG_POINTER, &menu, 0 ); - PtGetResources( widget, 1, &arg ); + PtSetArg(&arg, Pt_ARG_POINTER, &menu, 0); + PtGetResources(widget, 1, &arg); /* Override the text and position */ tooltip = text; - if( menu != NULL ) + if (menu != NULL) { int index = MENU_INDEX_TIP; - if( menu->strings[ index ] != NULL ) + if (menu->strings[ index ] != NULL) tooltip = menu->strings[ index ]; } - return( PtInflateBalloon( + return PtInflateBalloon( window, widget, /* Don't put the balloon at the bottom, @@ -261,25 +261,25 @@ tooltip, font, fill_color, - text_color ) ); + text_color); } static void -gui_ph_resize_container( void ) +gui_ph_resize_container(void) { PhArea_t area; - PtWidgetArea( gui.vimWindow, &area ); - PtWidgetPos ( gui.vimContainer, &area.pos ); + PtWidgetArea(gui.vimWindow, &area); + PtWidgetPos (gui.vimContainer, &area.pos); - PtSetResource( gui.vimContainer, Pt_ARG_AREA, &area, 0 ); + PtSetResource(gui.vimContainer, Pt_ARG_AREA, &area, 0); } static int gui_ph_handle_menu_resize( PtWidget_t *widget, void *other, - PtCallbackInfo_t *info ) + PtCallbackInfo_t *info) { PtContainerCallback_t *sizes = info->cbdata; PtWidget_t *container; @@ -291,7 +291,7 @@ /* Because vim treats the toolbar and menubar separately, * and here they're lumped together into a PtToolbarGroup, * we only need either menu_height or toolbar_height set at once */ - if( gui.menu_is_active ) + if (gui.menu_is_active) { gui.menu_height = height; gui.toolbar_height = 0; @@ -310,16 +310,16 @@ container = gui.vimContainer; #endif - PtSetResource( container, Pt_ARG_POS, &below_menu, 0 ); + PtSetResource(container, Pt_ARG_POS, &below_menu, 0); gui_ph_resize_container(); #ifdef USE_PANEL_GROUP gui_ph_get_panelgroup_margins( &pg_margin_top, &pg_margin_bottom, - &pg_margin_left, &pg_margin_right ); + &pg_margin_left, &pg_margin_right); #endif - return( Pt_CONTINUE ); + return Pt_CONTINUE; } /* @@ -330,23 +330,23 @@ gui_ph_handle_timer_cursor( PtWidget_t *widget, void *data, - PtCallbackInfo_t *info ) + PtCallbackInfo_t *info) { - if( blink_state == BLINK_ON ) + if (blink_state == BLINK_ON) { gui_undraw_cursor(); blink_state = BLINK_OFF; - PtSetResource( gui_ph_timer_cursor, Pt_ARG_TIMER_INITIAL, - blink_offtime, 0 ); + PtSetResource(gui_ph_timer_cursor, Pt_ARG_TIMER_INITIAL, + blink_offtime, 0); } else { gui_update_cursor(TRUE, FALSE); blink_state = BLINK_ON; - PtSetResource( gui_ph_timer_cursor, Pt_ARG_TIMER_INITIAL, - blink_ontime, 0 ); + PtSetResource(gui_ph_timer_cursor, Pt_ARG_TIMER_INITIAL, + blink_ontime, 0); } - return( Pt_CONTINUE ); + return Pt_CONTINUE; } static int @@ -354,25 +354,25 @@ { is_timeout = TRUE; - return( Pt_CONTINUE ); + return Pt_CONTINUE; } static int -gui_ph_handle_window_cb( PtWidget_t *widget, void *data, PtCallbackInfo_t *info ) +gui_ph_handle_window_cb(PtWidget_t *widget, void *data, PtCallbackInfo_t *info) { PhWindowEvent_t *we = info->cbdata; ushort_t *width, *height; - switch( we->event_f ) { + switch (we->event_f) { case Ph_WM_CLOSE: gui_shell_closed(); break; case Ph_WM_FOCUS: /* Just in case it's hidden and needs to be shown */ - gui_mch_mousehide( MOUSE_SHOW ); + gui_mch_mousehide(MOUSE_SHOW); - if( we->event_state == Ph_WM_EVSTATE_FOCUS ) + if (we->event_state == Ph_WM_EVSTATE_FOCUS) { gui_focus_change(TRUE); gui_mch_start_blink(); @@ -385,28 +385,28 @@ break; case Ph_WM_RESIZE: - PtGetResource( gui.vimWindow, Pt_ARG_WIDTH, &width, 0 ); - PtGetResource( gui.vimWindow, Pt_ARG_HEIGHT, &height, 0 ); + PtGetResource(gui.vimWindow, Pt_ARG_WIDTH, &width, 0); + PtGetResource(gui.vimWindow, Pt_ARG_HEIGHT, &height, 0); #ifdef USE_PANEL_GROUP width -= (pg_margin_left + pg_margin_right); height -= (pg_margin_top + pg_margin_bottom); #endif - gui_resize_shell( *width, *height ); - gui_set_shellsize( FALSE, FALSE, RESIZE_BOTH ); + gui_resize_shell(*width, *height); + gui_set_shellsize(FALSE, FALSE, RESIZE_BOTH); is_ignore_draw = FALSE; - PtEndFlux( gui.vimContainer ); - PtContainerRelease( gui.vimContainer ); + PtEndFlux(gui.vimContainer); + PtContainerRelease(gui.vimContainer); break; default: break; } - return( Pt_CONTINUE ); + return Pt_CONTINUE; } static int -gui_ph_handle_scrollbar( PtWidget_t *widget, void *data, PtCallbackInfo_t *info ) +gui_ph_handle_scrollbar(PtWidget_t *widget, void *data, PtCallbackInfo_t *info) { PtScrollbarCallback_t *scroll; scrollbar_T *sb; @@ -415,10 +415,10 @@ scroll = info->cbdata; sb = (scrollbar_T *) data; - if( sb != NULL ) + if (sb != NULL) { value = scroll->position; - switch( scroll->action ) + switch (scroll->action) { case Pt_SCROLL_DRAGGED: dragging = TRUE; @@ -426,107 +426,107 @@ case Pt_SCROLL_SET: /* FIXME: return straight away here? */ - return( Pt_CONTINUE ); + return Pt_CONTINUE; break; } gui_drag_scrollbar(sb, value, dragging); } - return( Pt_CONTINUE ); + return Pt_CONTINUE; } static int -gui_ph_handle_keyboard( PtWidget_t *widget, void *data, PtCallbackInfo_t *info ) +gui_ph_handle_keyboard(PtWidget_t *widget, void *data, PtCallbackInfo_t *info) { PhKeyEvent_t *key; unsigned char string[6]; int len, i; int ch, modifiers; - key = PhGetData( info->event ); + key = PhGetData(info->event); ch = modifiers = len = 0; - if( p_mh ) - gui_mch_mousehide( MOUSE_HIDE ); + if (p_mh) + gui_mch_mousehide(MOUSE_HIDE); /* We're a good lil photon program, aren't we? yes we are, yeess wee arrr */ - if( key->key_flags & Pk_KF_Compose ) + if (key->key_flags & Pk_KF_Compose) { - return( Pt_CONTINUE ); + return Pt_CONTINUE; } - if( (key->key_flags & Pk_KF_Cap_Valid) && - PkIsKeyDown( key->key_flags ) ) + if ((key->key_flags & Pk_KF_Cap_Valid) && + PkIsKeyDown(key->key_flags)) { #ifdef FEAT_MENU /* * Only show the menu if the Alt key is down, and the Shift & Ctrl * keys aren't down, as well as the other conditions */ - if( ( ( key->key_mods & Pk_KM_Alt ) && - !( key->key_mods & Pk_KM_Shift ) && - !( key->key_mods & Pk_KM_Ctrl ) ) && + if (((key->key_mods & Pk_KM_Alt) && + !(key->key_mods & Pk_KM_Shift) && + !(key->key_mods & Pk_KM_Ctrl)) && gui.menu_is_active && - ( *p_wak == 'y' || - ( *p_wak == 'm' && - gui_is_menu_shortcut( key->key_cap ) ) ) ) + (*p_wak == 'y' || + (*p_wak == 'm' && + gui_is_menu_shortcut(key->key_cap)))) { /* Fallthrough and let photon look for the hotkey */ - return( Pt_CONTINUE ); + return Pt_CONTINUE; } #endif - for( i = 0; special_keys[i].key_sym != 0; i++ ) + for (i = 0; special_keys[i].key_sym != 0; i++) { - if( special_keys[i].key_sym == key->key_cap ) + if (special_keys[i].key_sym == key->key_cap) { len = 0; - if( special_keys[i].vim_code1 == NUL ) + if (special_keys[i].vim_code1 == NUL) ch = special_keys[i].vim_code0; else { /* Detect if a keypad number key has been pressed * and change the key if Num Lock is on */ - if( key->key_cap >= Pk_KP_Enter && key->key_cap <= Pk_KP_9 - && ( key->key_mods & Pk_KM_Num_Lock ) ) + if (key->key_cap >= Pk_KP_Enter && key->key_cap <= Pk_KP_9 + && (key->key_mods & Pk_KM_Num_Lock)) { /* FIXME: For now, just map the key to a ascii value * (see ) */ ch = key->key_cap - 0xf080; } else - ch = TO_SPECIAL( special_keys[i].vim_code0, - special_keys[i].vim_code1 ); + ch = TO_SPECIAL(special_keys[i].vim_code0, + special_keys[i].vim_code1); } break; } } - if( key->key_mods & Pk_KM_Ctrl ) + if (key->key_mods & Pk_KM_Ctrl) modifiers |= MOD_MASK_CTRL; - if( key->key_mods & Pk_KM_Alt ) + if (key->key_mods & Pk_KM_Alt) modifiers |= MOD_MASK_ALT; - if( key->key_mods & Pk_KM_Shift ) + if (key->key_mods & Pk_KM_Shift) modifiers |= MOD_MASK_SHIFT; /* Is this not a special key? */ - if( special_keys[i].key_sym == 0 ) + if (special_keys[i].key_sym == 0) { - ch = PhTo8859_1( key ); - if( ch == -1 + ch = PhTo8859_1(key); + if (ch == -1 #ifdef FEAT_MBYTE - || ( enc_utf8 && ch > 127 ) + || (enc_utf8 && ch > 127) #endif ) { #ifdef FEAT_MBYTE - len = PhKeyToMb( string, key ); - if( len > 0 ) + len = PhKeyToMb(string, key); + if (len > 0) { static char buf[6]; int src_taken, dst_made; - if( enc_utf8 != TRUE ) + if (enc_utf8 != TRUE) { PxTranslateFromUTF( charset_translate, @@ -535,70 +535,70 @@ &src_taken, buf, 6, - &dst_made ); + &dst_made); - add_to_input_buf( buf, dst_made ); + add_to_input_buf(buf, dst_made); } else { - add_to_input_buf( string, len ); + add_to_input_buf(string, len); } - return( Pt_CONSUME ); + return Pt_CONSUME; } len = 0; #endif ch = key->key_cap; - if( ch < 0xff ) + if (ch < 0xff) { /* FIXME: is this the right thing to do? */ - if( modifiers & MOD_MASK_CTRL ) + if (modifiers & MOD_MASK_CTRL) { modifiers &= ~MOD_MASK_CTRL; - if( ( ch >= 'a' && ch <= 'z' ) || + if ((ch >= 'a' && ch <= 'z') || ch == '[' || ch == ']' || - ch == '\\' ) - ch = Ctrl_chr( ch ); - else if( ch == '2' ) + ch == '\\') + ch = Ctrl_chr(ch); + else if (ch == '2') ch = NUL; - else if( ch == '6' ) + else if (ch == '6') ch = 0x1e; - else if( ch == '-' ) + else if (ch == '-') ch = 0x1f; else modifiers |= MOD_MASK_CTRL; } - if( modifiers & MOD_MASK_ALT ) + if (modifiers & MOD_MASK_ALT) { - ch = Meta( ch ); + ch = Meta(ch); modifiers &= ~MOD_MASK_ALT; } } else { - return( Pt_CONTINUE ); + return Pt_CONTINUE; } } else modifiers &= ~MOD_MASK_SHIFT; } - ch = simplify_key( ch, &modifiers ); - if( modifiers ) + ch = simplify_key(ch, &modifiers); + if (modifiers) { string[ len++ ] = CSI; string[ len++ ] = KS_MODIFIER; string[ len++ ] = modifiers; } - if( IS_SPECIAL( ch ) ) + if (IS_SPECIAL(ch)) { string[ len++ ] = CSI; - string[ len++ ] = K_SECOND( ch ); - string[ len++ ] = K_THIRD( ch ); + string[ len++ ] = K_SECOND(ch); + string[ len++ ] = K_THIRD(ch); } else { @@ -619,28 +619,28 @@ string[ len++ ] = KE_CSI; } - if( len > 0 ) + if (len > 0) { - add_to_input_buf( string, len ); - return( Pt_CONSUME ); + add_to_input_buf(string, len); + return Pt_CONSUME; } } - return( Pt_CONTINUE ); + return Pt_CONTINUE; } static int -gui_ph_handle_mouse( PtWidget_t *widget, void *data, PtCallbackInfo_t *info ) +gui_ph_handle_mouse(PtWidget_t *widget, void *data, PtCallbackInfo_t *info) { PhPointerEvent_t *pointer; PhRect_t *pos; int button = 0, repeated_click, modifiers = 0x0; short mouse_x, mouse_y; - pointer = PhGetData( info->event ); - pos = PhGetRects( info->event ); + pointer = PhGetData(info->event); + pos = PhGetRects(info->event); - gui_mch_mousehide( MOUSE_SHOW ); + gui_mch_mousehide(MOUSE_SHOW); /* * Coordinates need to be relative to the base window, @@ -649,27 +649,27 @@ mouse_x = pos->ul.x + gui.border_width; mouse_y = pos->ul.y + gui.border_width; - if( info->event->type == Ph_EV_PTR_MOTION_NOBUTTON ) + if (info->event->type == Ph_EV_PTR_MOTION_NOBUTTON) { - gui_mouse_moved( mouse_x, mouse_y ); - return( Pt_CONTINUE ); + gui_mouse_moved(mouse_x, mouse_y); + return Pt_CONTINUE; } - if( pointer->key_mods & Pk_KM_Shift ) + if (pointer->key_mods & Pk_KM_Shift) modifiers |= MOUSE_SHIFT; - if( pointer->key_mods & Pk_KM_Ctrl ) + if (pointer->key_mods & Pk_KM_Ctrl) modifiers |= MOUSE_CTRL; - if( pointer->key_mods & Pk_KM_Alt ) + if (pointer->key_mods & Pk_KM_Alt) modifiers |= MOUSE_ALT; /* * FIXME More than one button may be involved, but for * now just deal with one */ - if( pointer->buttons & Ph_BUTTON_SELECT ) + if (pointer->buttons & Ph_BUTTON_SELECT) button = MOUSE_LEFT; - if( pointer->buttons & Ph_BUTTON_MENU ) + if (pointer->buttons & Ph_BUTTON_MENU) { button = MOUSE_RIGHT; /* Need the absolute coordinates for the popup menu */ @@ -677,65 +677,65 @@ abs_mouse.y = pointer->pos.y; } - if( pointer->buttons & Ph_BUTTON_ADJUST ) + if (pointer->buttons & Ph_BUTTON_ADJUST) button = MOUSE_MIDDLE; /* Catch a real release (not phantom or other releases */ - if( info->event->type == Ph_EV_BUT_RELEASE ) + if (info->event->type == Ph_EV_BUT_RELEASE) button = MOUSE_RELEASE; - if( info->event->type & Ph_EV_PTR_MOTION_BUTTON ) + if (info->event->type & Ph_EV_PTR_MOTION_BUTTON) button = MOUSE_DRAG; #if 0 /* Vim doesn't use button repeats */ - if( info->event->type & Ph_EV_BUT_REPEAT ) + if (info->event->type & Ph_EV_BUT_REPEAT) button = MOUSE_DRAG; #endif /* Don't do anything if it is one of the phantom mouse release events */ - if( ( button != MOUSE_RELEASE ) || - ( info->event->subtype == Ph_EV_RELEASE_REAL ) ) + if ((button != MOUSE_RELEASE) || + (info->event->subtype == Ph_EV_RELEASE_REAL)) { repeated_click = (pointer->click_count >= 2) ? TRUE : FALSE; - gui_send_mouse_event( button , mouse_x, mouse_y, repeated_click, modifiers ); + gui_send_mouse_event(button , mouse_x, mouse_y, repeated_click, modifiers); } - return( Pt_CONTINUE ); + return Pt_CONTINUE; } /* Handle a focus change of the PtRaw widget */ static int -gui_ph_handle_focus( PtWidget_t *widget, void *data, PtCallbackInfo_t *info ) +gui_ph_handle_focus(PtWidget_t *widget, void *data, PtCallbackInfo_t *info) { - if( info->reason == Pt_CB_LOST_FOCUS ) + if (info->reason == Pt_CB_LOST_FOCUS) { - PtRemoveEventHandler( gui.vimTextArea, Ph_EV_PTR_MOTION_NOBUTTON, - gui_ph_handle_mouse, NULL ); + PtRemoveEventHandler(gui.vimTextArea, Ph_EV_PTR_MOTION_NOBUTTON, + gui_ph_handle_mouse, NULL); - gui_mch_mousehide( MOUSE_SHOW ); + gui_mch_mousehide(MOUSE_SHOW); } else { - PtAddEventHandler( gui.vimTextArea, Ph_EV_PTR_MOTION_NOBUTTON, - gui_ph_handle_mouse, NULL ); + PtAddEventHandler(gui.vimTextArea, Ph_EV_PTR_MOTION_NOBUTTON, + gui_ph_handle_mouse, NULL); } - return( Pt_CONTINUE ); + return Pt_CONTINUE; } static void -gui_ph_handle_raw_draw( PtWidget_t *widget, PhTile_t *damage ) +gui_ph_handle_raw_draw(PtWidget_t *widget, PhTile_t *damage) { PhRect_t *r; PhPoint_t offset; PhPoint_t translation; - if( is_ignore_draw == TRUE ) + if (is_ignore_draw == TRUE) return; - PtSuperClassDraw( PtBasic, widget, damage ); - PgGetTranslation( &translation ); + PtSuperClassDraw(PtBasic, widget, damage); + PgGetTranslation(&translation); PgClearTranslation(); #if 0 @@ -750,21 +750,21 @@ out_flush(); #endif - PtWidgetOffset( widget, &offset ); - PhTranslatePoint( &offset, PtWidgetPos( gui.vimTextArea, NULL ) ); + PtWidgetOffset(widget, &offset); + PhTranslatePoint(&offset, PtWidgetPos(gui.vimTextArea, NULL)); #if 1 /* Redraw individual damage regions */ - if( damage->next != NULL ) + if (damage->next != NULL) damage = damage->next; - while( damage != NULL ) + while (damage != NULL) { r = &damage->rect; gui_redraw( r->ul.x - offset.x, r->ul.y - offset.y, r->lr.x - r->ul.x + 1, - r->lr.y - r->ul.y + 1 ); + r->lr.y - r->ul.y + 1); damage = damage->next; } #else @@ -773,39 +773,39 @@ gui_redraw( r->ul.x - offset.x, r->ul.y - offset.y, r->lr.x - r->ul.x + 1, - r->lr.y - r->ul.y + 1 ); + r->lr.y - r->ul.y + 1); #endif - PgSetTranslation( &translation, 0 ); + PgSetTranslation(&translation, 0); } static int gui_ph_handle_pulldown_menu( PtWidget_t *widget, void *data, - PtCallbackInfo_t *info ) + PtCallbackInfo_t *info) { - if( data != NULL ) + if (data != NULL) { vimmenu_T *menu = (vimmenu_T *) data; - PtPositionMenu( menu->submenu_id, NULL ); - PtRealizeWidget( menu->submenu_id ); + PtPositionMenu(menu->submenu_id, NULL); + PtRealizeWidget(menu->submenu_id); } - return( Pt_CONTINUE ); + return Pt_CONTINUE; } /* This is used for pulldown/popup menus and also toolbar buttons */ static int -gui_ph_handle_menu( PtWidget_t *widget, void *data, PtCallbackInfo_t *info ) +gui_ph_handle_menu(PtWidget_t *widget, void *data, PtCallbackInfo_t *info) { - if( data != NULL ) + if (data != NULL) { vimmenu_T *menu = (vimmenu_T *) data; - gui_menu_cb( menu ); + gui_menu_cb(menu); } - return( Pt_CONTINUE ); + return Pt_CONTINUE; } /* Stop focus from disappearing into the menubar... */ @@ -813,20 +813,20 @@ gui_ph_handle_menu_unrealized( PtWidget_t *widget, void *data, - PtCallbackInfo_t *info ) + PtCallbackInfo_t *info) { - PtGiveFocus( gui.vimTextArea, NULL ); - return( Pt_CONTINUE ); + PtGiveFocus(gui.vimTextArea, NULL); + return Pt_CONTINUE; } static int gui_ph_handle_window_open( PtWidget_t *widget, void *data, - PtCallbackInfo_t *info ) + PtCallbackInfo_t *info) { - gui_set_shellsize( FALSE, TRUE, RESIZE_BOTH ); - return( Pt_CONTINUE ); + gui_set_shellsize(FALSE, TRUE, RESIZE_BOTH); + return Pt_CONTINUE; } /****************************************************************************/ @@ -836,74 +836,74 @@ /* TODO: Set a clipping rect? */ static void -gui_ph_draw_start( void ) +gui_ph_draw_start(void) { PhGC_t *gc; gc = PgGetGC(); - PgSetRegion( PtWidgetRid( PtFindDisjoint( gui.vimTextArea ) ) ); - PgClearClippingsCx( gc ); - PgClearTranslationCx( gc ); + PgSetRegion(PtWidgetRid(PtFindDisjoint(gui.vimTextArea))); + PgClearClippingsCx(gc); + PgClearTranslationCx(gc); - PtWidgetOffset( gui.vimTextArea, &gui_ph_raw_offset ); - PhTranslatePoint( &gui_ph_raw_offset, PtWidgetPos( gui.vimTextArea, NULL ) ); + PtWidgetOffset(gui.vimTextArea, &gui_ph_raw_offset); + PhTranslatePoint(&gui_ph_raw_offset, PtWidgetPos(gui.vimTextArea, NULL)); - PgSetTranslation( &gui_ph_raw_offset, Pg_RELATIVE ); + PgSetTranslation(&gui_ph_raw_offset, Pg_RELATIVE); } static void -gui_ph_draw_end( void ) +gui_ph_draw_end(void) { gui_ph_raw_offset.x = -gui_ph_raw_offset.x; gui_ph_raw_offset.y = -gui_ph_raw_offset.y; - PgSetTranslation( &gui_ph_raw_offset, Pg_RELATIVE ); + PgSetTranslation(&gui_ph_raw_offset, Pg_RELATIVE); } #ifdef USE_PANEL_GROUP static vimmenu_T * -gui_ph_find_buffer_item( char_u *name ) +gui_ph_find_buffer_item(char_u *name) { vimmenu_T *top_level = root_menu; vimmenu_T *items = NULL; - while( top_level != NULL && - ( STRCMP( top_level->dname, "Buffers" ) != 0 ) ) + while (top_level != NULL && + (STRCMP(top_level->dname, "Buffers") != 0)) top_level = top_level->next; - if( top_level != NULL ) + if (top_level != NULL) { items = top_level->children; - while( items != NULL && - ( STRCMP( items->dname, name ) != 0 ) ) + while (items != NULL && + (STRCMP(items->dname, name) != 0)) items = items->next; } - return( items ); + return items; } static void -gui_ph_pg_set_buffer_num( int_u buf_num ) +gui_ph_pg_set_buffer_num(int_u buf_num) { int i; char search[16]; char *mark; - if( gui.vimTextArea == NULL || buf_num == 0 ) + if (gui.vimTextArea == NULL || buf_num == 0) return; search[0] = '('; - ultoa( buf_num, &search[1], 10 ); - STRCAT( search, ")" ); + ultoa(buf_num, &search[1], 10); + STRCAT(search, ")"); - for( i = 0; i < num_panels; i++ ) + for (i = 0; i < num_panels; i++) { /* find the last "(" in the panel title and see if the buffer * number in the title matches the one we're looking for */ - mark = STRRCHR( panel_titles[ i ], '(' ); - if( mark != NULL && STRCMP( mark, search ) == 0 ) + mark = STRRCHR(panel_titles[ i ], '('); + if (mark != NULL && STRCMP(mark, search) == 0) { - PtSetResource( gui.vimPanelGroup, Pt_ARG_PG_CURRENT_INDEX, - i, 0 ); + PtSetResource(gui.vimPanelGroup, Pt_ARG_PG_CURRENT_INDEX, + i, 0); } } } @@ -912,22 +912,22 @@ gui_ph_handle_pg_change( PtWidget_t *widget, void *data, - PtCallbackInfo_t *info ) + PtCallbackInfo_t *info) { vimmenu_T *menu; PtPanelGroupCallback_t *panel; - if( info->event != NULL ) + if (info->event != NULL) { panel = info->cbdata; - if( panel->new_panel != NULL ) + if (panel->new_panel != NULL) { - menu = gui_ph_find_buffer_item( panel->new_panel ); - if( menu ) - gui_menu_cb( menu ); + menu = gui_ph_find_buffer_item(panel->new_panel); + if (menu) + gui_menu_cb(menu); } } - return( Pt_CONTINUE ); + return Pt_CONTINUE; } static void @@ -935,17 +935,17 @@ short *top, short *bottom, short *left, - short *right ) + short *right) { unsigned short abs_raw_x, abs_raw_y, abs_panel_x, abs_panel_y; const unsigned short *margin_top, *margin_bottom; const unsigned short *margin_left, *margin_right; - PtGetAbsPosition( gui.vimTextArea, &abs_raw_x, &abs_raw_y ); - PtGetAbsPosition( gui.vimPanelGroup, &abs_panel_x, &abs_panel_y ); + PtGetAbsPosition(gui.vimTextArea, &abs_raw_x, &abs_raw_y); + PtGetAbsPosition(gui.vimPanelGroup, &abs_panel_x, &abs_panel_y); - PtGetResource( gui.vimPanelGroup, Pt_ARG_MARGIN_RIGHT, &margin_right, 0 ); - PtGetResource( gui.vimPanelGroup, Pt_ARG_MARGIN_BOTTOM, &margin_bottom, 0 ); + PtGetResource(gui.vimPanelGroup, Pt_ARG_MARGIN_RIGHT, &margin_right, 0); + PtGetResource(gui.vimPanelGroup, Pt_ARG_MARGIN_BOTTOM, &margin_bottom, 0); abs_raw_x -= abs_panel_x; abs_raw_y -= abs_panel_y; @@ -959,85 +959,85 @@ /* Used for the tabs for PtPanelGroup */ static int -gui_ph_is_buffer_item( vimmenu_T *menu, vimmenu_T *parent ) +gui_ph_is_buffer_item(vimmenu_T *menu, vimmenu_T *parent) { char *mark; - if( STRCMP( parent->dname, "Buffers" ) == 0 ) + if (STRCMP(parent->dname, "Buffers") == 0) { /* Look for '(' digits ')' */ - mark = vim_strchr( menu->dname, '(' ); - if( mark != NULL ) + mark = vim_strchr(menu->dname, '('); + if (mark != NULL) { mark++; - while( isdigit( *mark ) ) + while (isdigit(*mark)) mark++; - if( *mark == ')' ) - return( TRUE); + if (*mark == ')') + return TRUE; } } - return( FALSE ); + return FALSE; } static void -gui_ph_pg_add_buffer(char *name ) +gui_ph_pg_add_buffer(char *name) { char **new_titles = NULL; - new_titles = (char **) alloc( ( num_panels + 1 ) * sizeof( char ** ) ); - if( new_titles != NULL ) + new_titles = (char **) alloc((num_panels + 1) * sizeof(char **)); + if (new_titles != NULL) { - if( num_panels > 0 ) - memcpy( new_titles, panel_titles, num_panels * sizeof( char ** ) ); + if (num_panels > 0) + memcpy(new_titles, panel_titles, num_panels * sizeof(char **)); new_titles[ num_panels++ ] = name; - PtSetResource( gui.vimPanelGroup, Pt_ARG_PG_PANEL_TITLES, new_titles, - num_panels ); + PtSetResource(gui.vimPanelGroup, Pt_ARG_PG_PANEL_TITLES, new_titles, + num_panels); - vim_free( panel_titles ); + vim_free(panel_titles); panel_titles = new_titles; } } static void -gui_ph_pg_remove_buffer( char *name ) +gui_ph_pg_remove_buffer(char *name) { int i; char **new_titles = NULL; /* If there is only 1 panel, we just use the temporary place holder */ - if( num_panels > 1 ) + if (num_panels > 1) { - new_titles = (char **) alloc( ( num_panels - 1 ) * sizeof( char ** ) ); - if( new_titles != NULL ) + new_titles = (char **) alloc((num_panels - 1) * sizeof(char **)); + if (new_titles != NULL) { char **s = new_titles; /* Copy all the titles except the one we're removing */ - for( i = 0; i < num_panels; i++ ) + for (i = 0; i < num_panels; i++) { - if( STRCMP( panel_titles[ i ], name ) != 0 ) + if (STRCMP(panel_titles[ i ], name) != 0) { *s++ = panel_titles[ i ]; } } num_panels--; - PtSetResource( gui.vimPanelGroup, Pt_ARG_PG_PANEL_TITLES, new_titles, - num_panels ); + PtSetResource(gui.vimPanelGroup, Pt_ARG_PG_PANEL_TITLES, new_titles, + num_panels); - vim_free( panel_titles ); + vim_free(panel_titles); panel_titles = new_titles; } } else { num_panels--; - PtSetResource( gui.vimPanelGroup, Pt_ARG_PG_PANEL_TITLES, &empty_title, - 1 ); + PtSetResource(gui.vimPanelGroup, Pt_ARG_PG_PANEL_TITLES, &empty_title, + 1); - vim_free( panel_titles ); + vim_free(panel_titles); panel_titles = NULL; } } @@ -1047,38 +1047,38 @@ gui_ph_handle_buffer_remove( PtWidget_t *widget, void *data, - PtCallbackInfo_t *info ) + PtCallbackInfo_t *info) { vimmenu_T *menu; - if( data != NULL ) + if (data != NULL) { menu = (vimmenu_T *) data; - gui_ph_pg_remove_buffer( menu->dname ); + gui_ph_pg_remove_buffer(menu->dname); } - return( Pt_CONTINUE ); + return Pt_CONTINUE; } #endif static int -gui_ph_pane_resize( PtWidget_t *widget, void *data, PtCallbackInfo_t *info ) +gui_ph_pane_resize(PtWidget_t *widget, void *data, PtCallbackInfo_t *info) { - if( PtWidgetIsRealized( widget ) ) + if (PtWidgetIsRealized(widget)) { is_ignore_draw = TRUE; - PtStartFlux( gui.vimContainer ); - PtContainerHold( gui.vimContainer ); + PtStartFlux(gui.vimContainer); + PtContainerHold(gui.vimContainer); } - return( Pt_CONTINUE ); + return Pt_CONTINUE; } /****************************************************************************/ #ifdef FEAT_MBYTE void -gui_ph_encoding_changed( int new_encoding ) +gui_ph_encoding_changed(int new_encoding) { /* Default encoding is latin1 */ char *charset = "latin1"; @@ -1094,13 +1094,13 @@ { DBCS_CHS, "gb" } }; - for( i = 0; i < ARRAY_LENGTH( charsets ); i++ ) + for (i = 0; i < ARRAY_LENGTH(charsets); i++) { - if( new_encoding == charsets[ i ].encoding ) + if (new_encoding == charsets[ i ].encoding) charset = charsets[ i ].name; } - charset_translate = PxTranslateSet( charset_translate, charset ); + charset_translate = PxTranslateSet(charset_translate, charset); } #endif @@ -1112,7 +1112,7 @@ int *argc; char **argv; { - PtInit( NULL ); + PtInit(NULL); } int @@ -1124,90 +1124,90 @@ PhDim_t window_size = {100, 100}; /* Arbitrary values */ PhPoint_t pos = {0, 0}; - gui.event_buffer = (PhEvent_t *) alloc( EVENT_BUFFER_SIZE ); - if( gui.event_buffer == NULL ) - return( FAIL ); + gui.event_buffer = (PhEvent_t *) alloc(EVENT_BUFFER_SIZE); + if (gui.event_buffer == NULL) + return FAIL; /* Get a translation so we can convert from ISO Latin-1 to UTF */ - charset_translate = PxTranslateSet( NULL, "latin1" ); + charset_translate = PxTranslateSet(NULL, "latin1"); /* The +2 is for the 1 pixel dark line on each side */ gui.border_offset = gui.border_width = GUI_PH_MARGIN + 2; /* Handle close events ourselves */ - PtSetArg( &args[ n++ ], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE, Ph_WM_CLOSE ); - PtSetArg( &args[ n++ ], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_TRUE, - Ph_WM_CLOSE | Ph_WM_RESIZE | Ph_WM_FOCUS ); - PtSetArg( &args[ n++ ], Pt_ARG_DIM, &window_size, 0 ); - gui.vimWindow = PtCreateWidget( PtWindow, NULL, n, args ); - if( gui.vimWindow == NULL ) - return( FAIL ); - - PtAddCallback( gui.vimWindow, Pt_CB_WINDOW, gui_ph_handle_window_cb, NULL ); - PtAddCallback( gui.vimWindow, Pt_CB_WINDOW_OPENING, - gui_ph_handle_window_open, NULL ); + PtSetArg(&args[ n++ ], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE, Ph_WM_CLOSE); + PtSetArg(&args[ n++ ], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_TRUE, + Ph_WM_CLOSE | Ph_WM_RESIZE | Ph_WM_FOCUS); + PtSetArg(&args[ n++ ], Pt_ARG_DIM, &window_size, 0); + gui.vimWindow = PtCreateWidget(PtWindow, NULL, n, args); + if (gui.vimWindow == NULL) + return FAIL; + + PtAddCallback(gui.vimWindow, Pt_CB_WINDOW, gui_ph_handle_window_cb, NULL); + PtAddCallback(gui.vimWindow, Pt_CB_WINDOW_OPENING, + gui_ph_handle_window_open, NULL); n = 0; - PtSetArg( &args[ n++ ], Pt_ARG_ANCHOR_FLAGS, Pt_ANCHOR_ALL, Pt_IS_ANCHORED ); - PtSetArg( &args[ n++ ], Pt_ARG_DIM, &window_size, 0 ); - PtSetArg( &args[ n++ ], Pt_ARG_POS, &pos, 0 ); + PtSetArg(&args[ n++ ], Pt_ARG_ANCHOR_FLAGS, Pt_ANCHOR_ALL, Pt_IS_ANCHORED); + PtSetArg(&args[ n++ ], Pt_ARG_DIM, &window_size, 0); + PtSetArg(&args[ n++ ], Pt_ARG_POS, &pos, 0); #ifdef USE_PANEL_GROUP /* Put in a temprary place holder title */ - PtSetArg( &args[ n++ ], Pt_ARG_PG_PANEL_TITLES, &empty_title, 1 ); + PtSetArg(&args[ n++ ], Pt_ARG_PG_PANEL_TITLES, &empty_title, 1); - gui.vimPanelGroup = PtCreateWidget( PtPanelGroup, gui.vimWindow, n, args ); - if( gui.vimPanelGroup == NULL ) - return( FAIL ); + gui.vimPanelGroup = PtCreateWidget(PtPanelGroup, gui.vimWindow, n, args); + if (gui.vimPanelGroup == NULL) + return FAIL; - PtAddCallback( gui.vimPanelGroup, Pt_CB_PG_PANEL_SWITCHING, - gui_ph_handle_pg_change, NULL ); + PtAddCallback(gui.vimPanelGroup, Pt_CB_PG_PANEL_SWITCHING, + gui_ph_handle_pg_change, NULL); #else /* Turn off all edge decorations */ - PtSetArg( &args[ n++ ], Pt_ARG_BASIC_FLAGS, Pt_FALSE, Pt_ALL ); - PtSetArg( &args[ n++ ], Pt_ARG_BEVEL_WIDTH, 0, 0 ); - PtSetArg( &args[ n++ ], Pt_ARG_MARGIN_WIDTH, 0, 0 ); - PtSetArg( &args[ n++ ], Pt_ARG_MARGIN_HEIGHT, 0, 0 ); - PtSetArg( &args[ n++ ], Pt_ARG_CONTAINER_FLAGS, Pt_TRUE, Pt_AUTO_EXTENT ); - - gui.vimContainer = PtCreateWidget( PtPane, gui.vimWindow, n, args ); - if( gui.vimContainer == NULL ) - return( FAIL ); + PtSetArg(&args[ n++ ], Pt_ARG_BASIC_FLAGS, Pt_FALSE, Pt_ALL); + PtSetArg(&args[ n++ ], Pt_ARG_BEVEL_WIDTH, 0, 0); + PtSetArg(&args[ n++ ], Pt_ARG_MARGIN_WIDTH, 0, 0); + PtSetArg(&args[ n++ ], Pt_ARG_MARGIN_HEIGHT, 0, 0); + PtSetArg(&args[ n++ ], Pt_ARG_CONTAINER_FLAGS, Pt_TRUE, Pt_AUTO_EXTENT); + + gui.vimContainer = PtCreateWidget(PtPane, gui.vimWindow, n, args); + if (gui.vimContainer == NULL) + return FAIL; - PtAddCallback( gui.vimContainer, Pt_CB_RESIZE, gui_ph_pane_resize, NULL ); + PtAddCallback(gui.vimContainer, Pt_CB_RESIZE, gui_ph_pane_resize, NULL); #endif /* Size for the text area is set in gui_mch_set_text_area_pos */ n = 0; - PtSetArg( &args[ n++ ], Pt_ARG_RAW_DRAW_F, gui_ph_handle_raw_draw, 1 ); - PtSetArg( &args[ n++ ], Pt_ARG_BEVEL_WIDTH, GUI_PH_MARGIN, 0 ); + PtSetArg(&args[ n++ ], Pt_ARG_RAW_DRAW_F, gui_ph_handle_raw_draw, 1); + PtSetArg(&args[ n++ ], Pt_ARG_BEVEL_WIDTH, GUI_PH_MARGIN, 0); /* * Using focus render also causes the whole widget to be redrawn * whenever it changes focus, which is very annoying :p */ - PtSetArg( &args[ n++ ], Pt_ARG_FLAGS, Pt_TRUE, - Pt_GETS_FOCUS | Pt_HIGHLIGHTED ); + PtSetArg(&args[ n++ ], Pt_ARG_FLAGS, Pt_TRUE, + Pt_GETS_FOCUS | Pt_HIGHLIGHTED); #ifndef FEAT_MOUSESHAPE - PtSetArg( &args[ n++ ], Pt_ARG_CURSOR_TYPE, GUI_PH_MOUSE_TYPE, 0 ); - PtSetArg( &args[ n++ ], Pt_ARG_CURSOR_COLOR, gui_ph_mouse_color, 0 ); + PtSetArg(&args[ n++ ], Pt_ARG_CURSOR_TYPE, GUI_PH_MOUSE_TYPE, 0); + PtSetArg(&args[ n++ ], Pt_ARG_CURSOR_COLOR, gui_ph_mouse_color, 0); #endif - gui.vimTextArea = PtCreateWidget( PtRaw, Pt_DFLT_PARENT, n, args ); - if( gui.vimTextArea == NULL) - return( FAIL ); + gui.vimTextArea = PtCreateWidget(PtRaw, Pt_DFLT_PARENT, n, args); + if (gui.vimTextArea == NULL) + return FAIL; /* TODO: use PtAddEventHandlers instead? */ /* Not using Ph_EV_BUT_REPEAT because vim wouldn't use it anyway */ - PtAddEventHandler( gui.vimTextArea, + PtAddEventHandler(gui.vimTextArea, Ph_EV_BUT_PRESS | Ph_EV_BUT_RELEASE | Ph_EV_PTR_MOTION_BUTTON, - gui_ph_handle_mouse, NULL ); - PtAddEventHandler( gui.vimTextArea, Ph_EV_KEY, - gui_ph_handle_keyboard, NULL ); - PtAddCallback( gui.vimTextArea, Pt_CB_GOT_FOCUS, - gui_ph_handle_focus, NULL ); - PtAddCallback( gui.vimTextArea, Pt_CB_LOST_FOCUS, - gui_ph_handle_focus, NULL ); + gui_ph_handle_mouse, NULL); + PtAddEventHandler(gui.vimTextArea, Ph_EV_KEY, + gui_ph_handle_keyboard, NULL); + PtAddCallback(gui.vimTextArea, Pt_CB_GOT_FOCUS, + gui_ph_handle_focus, NULL); + PtAddCallback(gui.vimTextArea, Pt_CB_LOST_FOCUS, + gui_ph_handle_focus, NULL); /* * Now that the text area widget has been created, set up the colours, @@ -1218,62 +1218,62 @@ * Create the two timers, not as accurate as using the kernel timer * functions, but good enough */ - gui_ph_timer_cursor = PtCreateWidget( PtTimer, gui.vimWindow, 0, NULL ); - if( gui_ph_timer_cursor == NULL ) - return( FAIL ); - - gui_ph_timer_timeout = PtCreateWidget( PtTimer, gui.vimWindow, 0, NULL ); - if( gui_ph_timer_timeout == NULL ) - return( FAIL ); + gui_ph_timer_cursor = PtCreateWidget(PtTimer, gui.vimWindow, 0, NULL); + if (gui_ph_timer_cursor == NULL) + return FAIL; + + gui_ph_timer_timeout = PtCreateWidget(PtTimer, gui.vimWindow, 0, NULL); + if (gui_ph_timer_timeout == NULL) + return FAIL; - PtAddCallback( gui_ph_timer_cursor, Pt_CB_TIMER_ACTIVATE, + PtAddCallback(gui_ph_timer_cursor, Pt_CB_TIMER_ACTIVATE, gui_ph_handle_timer_cursor, NULL); - PtAddCallback( gui_ph_timer_timeout, Pt_CB_TIMER_ACTIVATE, + PtAddCallback(gui_ph_timer_timeout, Pt_CB_TIMER_ACTIVATE, gui_ph_handle_timer_timeout, NULL); #ifdef FEAT_MENU n = 0; - PtSetArg( &args[ n++ ], Pt_ARG_WIDTH, window_size.w, 0 ); - PtSetArg( &args[ n++ ], Pt_ARG_ANCHOR_FLAGS, Pt_ANCHOR_LEFT_RIGHT, - Pt_IS_ANCHORED ); - gui.vimToolBarGroup = PtCreateWidget( PtToolbarGroup, gui.vimWindow, - n, args ); - if( gui.vimToolBarGroup == NULL ) - return( FAIL ); + PtSetArg(&args[ n++ ], Pt_ARG_WIDTH, window_size.w, 0); + PtSetArg(&args[ n++ ], Pt_ARG_ANCHOR_FLAGS, Pt_ANCHOR_LEFT_RIGHT, + Pt_IS_ANCHORED); + gui.vimToolBarGroup = PtCreateWidget(PtToolbarGroup, gui.vimWindow, + n, args); + if (gui.vimToolBarGroup == NULL) + return FAIL; - PtAddCallback( gui.vimToolBarGroup, Pt_CB_RESIZE, - gui_ph_handle_menu_resize, NULL ); + PtAddCallback(gui.vimToolBarGroup, Pt_CB_RESIZE, + gui_ph_handle_menu_resize, NULL); n = 0; flags = 0; - PtSetArg( &args[ n++ ], Pt_ARG_WIDTH, window_size.w, 0 ); - if( ! vim_strchr( p_go, GO_MENUS ) ) + PtSetArg(&args[ n++ ], Pt_ARG_WIDTH, window_size.w, 0); + if (! vim_strchr(p_go, GO_MENUS)) { flags |= Pt_DELAY_REALIZE; - PtSetArg( &args[ n++ ], Pt_ARG_FLAGS, Pt_TRUE, flags ); + PtSetArg(&args[ n++ ], Pt_ARG_FLAGS, Pt_TRUE, flags); } - gui.vimMenuBar = PtCreateWidget( PtMenuBar, gui.vimToolBarGroup, n, args ); - if( gui.vimMenuBar == NULL ) - return( FAIL ); + gui.vimMenuBar = PtCreateWidget(PtMenuBar, gui.vimToolBarGroup, n, args); + if (gui.vimMenuBar == NULL) + return FAIL; # ifdef FEAT_TOOLBAR n = 0; - PtSetArg( &args[ n++ ], Pt_ARG_ANCHOR_FLAGS, - Pt_ANCHOR_LEFT_RIGHT |Pt_TOP_ANCHORED_TOP, Pt_IS_ANCHORED ); - PtSetArg( &args[ n++ ], Pt_ARG_RESIZE_FLAGS, Pt_TRUE, - Pt_RESIZE_Y_AS_REQUIRED ); - PtSetArg( &args[ n++ ], Pt_ARG_WIDTH, window_size.w, 0 ); + PtSetArg(&args[ n++ ], Pt_ARG_ANCHOR_FLAGS, + Pt_ANCHOR_LEFT_RIGHT |Pt_TOP_ANCHORED_TOP, Pt_IS_ANCHORED); + PtSetArg(&args[ n++ ], Pt_ARG_RESIZE_FLAGS, Pt_TRUE, + Pt_RESIZE_Y_AS_REQUIRED); + PtSetArg(&args[ n++ ], Pt_ARG_WIDTH, window_size.w, 0); flags = Pt_GETS_FOCUS; - if( ! vim_strchr( p_go, GO_TOOLBAR ) ) + if (! vim_strchr(p_go, GO_TOOLBAR)) flags |= Pt_DELAY_REALIZE; - PtSetArg( &args[ n++ ], Pt_ARG_FLAGS, Pt_DELAY_REALIZE, flags ); + PtSetArg(&args[ n++ ], Pt_ARG_FLAGS, Pt_DELAY_REALIZE, flags); - gui.vimToolBar = PtCreateWidget( PtToolbar, gui.vimToolBarGroup, n, args ); - if( gui.vimToolBar == NULL ) - return( FAIL ); + gui.vimToolBar = PtCreateWidget(PtToolbar, gui.vimToolBarGroup, n, args); + if (gui.vimToolBar == NULL) + return FAIL; /* * Size for the toolbar is fetched in gui_mch_show_toolbar, after @@ -1284,13 +1284,13 @@ #endif - return( OK ); + return OK; } int gui_mch_init_check(void) { - return( (is_photon_available == TRUE) ? OK : FAIL ); + return (is_photon_available == TRUE) ? OK : FAIL; } int @@ -1310,20 +1310,20 @@ if (gui_win_x != -1 && gui_win_y != -1) gui_mch_set_winpos(gui_win_x, gui_win_y); - return( (PtRealizeWidget( gui.vimWindow ) == 0) ? OK : FAIL ); + return (PtRealizeWidget(gui.vimWindow) == 0) ? OK : FAIL; } void gui_mch_exit(int rc) { - PtDestroyWidget( gui.vimWindow ); + PtDestroyWidget(gui.vimWindow); - PxTranslateSet( charset_translate, NULL ); + PxTranslateSet(charset_translate, NULL); - vim_free( gui.event_buffer ); + vim_free(gui.event_buffer); #ifdef USE_PANEL_GROUPS - vim_free( panel_titles ); + vim_free(panel_titles); #endif } @@ -1333,10 +1333,10 @@ /* When no events are available, photon will call this function, working is * set to FALSE, and the gui_mch_update loop will exit. */ static int -exit_gui_mch_update( void *data ) +exit_gui_mch_update(void *data) { *(int *)data = FALSE; - return( Pt_END ); + return Pt_END; } void @@ -1344,8 +1344,8 @@ { int working = TRUE; - PtAppAddWorkProc( NULL, exit_gui_mch_update, &working ); - while( ( working == TRUE ) && !vim_is_input_buf_full()) + PtAppAddWorkProc(NULL, exit_gui_mch_update, &working); + while ((working == TRUE) && !vim_is_input_buf_full()) { PtProcessEvent(); } @@ -1356,23 +1356,23 @@ { is_timeout = FALSE; - if( wtime > 0 ) - PtSetResource( gui_ph_timer_timeout, Pt_ARG_TIMER_INITIAL, wtime, 0 ); + if (wtime > 0) + PtSetResource(gui_ph_timer_timeout, Pt_ARG_TIMER_INITIAL, wtime, 0); - while( 1 ) + while (1) { PtProcessEvent(); - if( input_available() ) + if (input_available()) { - PtSetResource( gui_ph_timer_timeout, Pt_ARG_TIMER_INITIAL, 0, 0 ); - return( OK ); + PtSetResource(gui_ph_timer_timeout, Pt_ARG_TIMER_INITIAL, 0, 0); + return OK; } - else if( is_timeout == TRUE ) - return( FAIL ); + else if (is_timeout == TRUE) + return FAIL; } } -#if defined( FEAT_BROWSE ) || defined( PROTO ) +#if defined(FEAT_BROWSE) || defined(PROTO) /* * Put up a file requester. * Returns the selected name in allocated memory, or NULL for Cancel. @@ -1398,12 +1398,12 @@ char_u *open_text = NULL; flags = 0; - memset( &file, 0, sizeof( file ) ); + memset(&file, 0, sizeof(file)); - default_path = alloc( MAXPATHL + 1 + NAME_MAX + 1 ); - if( default_path != NULL ) + default_path = alloc(MAXPATHL + 1 + NAME_MAX + 1); + if (default_path != NULL) { - if( saving == TRUE ) + if (saving == TRUE) { /* Don't need Pt_FSR_CONFIRM_EXISTING, vim will ask anyway */ flags |= Pt_FSR_NO_FCHECK; @@ -1411,23 +1411,23 @@ } /* combine the directory and filename into a single path */ - if( initdir == NULL || *initdir == NUL ) + if (initdir == NULL || *initdir == NUL) { - mch_dirname( default_path, MAXPATHL ); + mch_dirname(default_path, MAXPATHL); initdir = default_path; } else { - STRCPY( default_path, initdir ); + STRCPY(default_path, initdir); initdir = default_path; } - if( default_name != NULL ) + if (default_name != NULL) { - if( default_path[ STRLEN( default_path ) - 1 ] != '/' ) - STRCAT( default_path, "/" ); + if (default_path[ STRLEN(default_path) - 1 ] != '/') + STRCAT(default_path, "/"); - STRCAT( default_path, default_name ); + STRCAT(default_path, default_name); } /* TODO: add a filter? */ @@ -1441,58 +1441,58 @@ NULL, NULL, &file, - flags ); + flags); - vim_free( default_path ); + vim_free(default_path); - if( file.ret == Pt_FSDIALOG_BTN1 ) - return( vim_strsave( file.path ) ); + if (file.ret == Pt_FSDIALOG_BTN1) + return vim_strsave(file.path); } - return( NULL ); + return NULL; } #endif -#if defined( FEAT_GUI_DIALOG ) || defined( PROTO ) +#if defined(FEAT_GUI_DIALOG) || defined(PROTO) static PtWidget_t *gui_ph_dialog_text = NULL; static int -gui_ph_dialog_close( int button, void *data ) +gui_ph_dialog_close(int button, void *data) { PtModalCtrl_t *modal_ctrl = data; char_u *dialog_text, *vim_text; - if( gui_ph_dialog_text != NULL ) + if (gui_ph_dialog_text != NULL) { - PtGetResource( gui_ph_dialog_text, Pt_ARG_TEXT_STRING, &dialog_text, 0 ); - PtGetResource( gui_ph_dialog_text, Pt_ARG_POINTER, &vim_text, 0 ); - STRNCPY( vim_text, dialog_text, IOSIZE - 1 ); + PtGetResource(gui_ph_dialog_text, Pt_ARG_TEXT_STRING, &dialog_text, 0); + PtGetResource(gui_ph_dialog_text, Pt_ARG_POINTER, &vim_text, 0); + STRNCPY(vim_text, dialog_text, IOSIZE - 1); } - PtModalUnblock( modal_ctrl, (void *) button ); + PtModalUnblock(modal_ctrl, (void *) button); - return( Pt_TRUE ); + return Pt_TRUE; } static int -gui_ph_dialog_text_enter( PtWidget_t *widget, void *data, PtCallbackInfo_t *info ) +gui_ph_dialog_text_enter(PtWidget_t *widget, void *data, PtCallbackInfo_t *info) { - if( info->reason_subtype == Pt_EDIT_ACTIVATE ) - gui_ph_dialog_close( 1, data ); - return( Pt_CONTINUE ); + if (info->reason_subtype == Pt_EDIT_ACTIVATE) + gui_ph_dialog_close(1, data); + return Pt_CONTINUE; } static int -gui_ph_dialog_esc( PtWidget_t *widget, void *data, PtCallbackInfo_t *info ) +gui_ph_dialog_esc(PtWidget_t *widget, void *data, PtCallbackInfo_t *info) { PhKeyEvent_t *key; - key = PhGetData( info->event ); - if( ( key->key_flags & Pk_KF_Cap_Valid ) && ( key->key_cap == Pk_Escape ) ) + key = PhGetData(info->event); + if ((key->key_flags & Pk_KF_Cap_Valid) && (key->key_cap == Pk_Escape)) { - gui_ph_dialog_close( 0, data ); - return( Pt_CONSUME ); + gui_ph_dialog_close(0, data); + return Pt_CONSUME; } - return( Pt_PROCESS ); + return Pt_PROCESS; } int @@ -1502,7 +1502,8 @@ char_u *message, char_u *buttons, int default_button, - char_u *textfield) + char_u *textfield, + int ex_cmd) { char_u *str; char_u **button_array; @@ -1517,40 +1518,40 @@ button_count = len = i = 0; - if( buttons == NULL || *buttons == NUL ) - return( -1 ); + if (buttons == NULL || *buttons == NUL) + return -1; /* There is one less separator than buttons, so bump up the button count */ button_count = 1; /* Count string length and number of seperators */ - for( str = buttons; *str; str++ ) + for (str = buttons; *str; str++) { len++; - if( *str == DLG_BUTTON_SEP ) + if (*str == DLG_BUTTON_SEP) button_count++; } - if ( title == NULL ) + if (title == NULL) title = "Vim"; - buttons_copy = alloc( len + 1 ); - button_array = (char_u **) alloc( button_count * sizeof( char_u * ) ); - if( buttons_copy != NULL && button_array != NULL ) + buttons_copy = alloc(len + 1); + button_array = (char_u **) alloc(button_count * sizeof(char_u *)); + if (buttons_copy != NULL && button_array != NULL) { - STRCPY( buttons_copy, buttons ); + STRCPY(buttons_copy, buttons); /* * Convert DLG_BUTTON_SEP into NUL's and fill in * button_array with the pointer to each NUL terminated string */ str = buttons_copy; - for( i = 0; i < button_count; i++ ) + for (i = 0; i < button_count; i++) { button_array[ i ] = str; - for( ; *str; str++ ) + for (; *str; str++) { - if( *str == DLG_BUTTON_SEP ) + if (*str == DLG_BUTTON_SEP) { *str++ = NUL; break; @@ -1564,7 +1565,7 @@ NULL, message, NULL, button_count, (const char **) button_array, NULL, - default_button, 0, Pt_MODAL ); + default_button, 0, Pt_MODAL); #else /* Writing the dialog ourselves lets us add extra features, like * trapping the escape key and returning 0 to vim */ @@ -1575,32 +1576,32 @@ PtModalCtrl_t modal_ctrl; PtDialogInfo_t di; - memset( &di, 0, sizeof( di ) ); - memset( &modal_ctrl, 0, sizeof( modal_ctrl ) ); + memset(&di, 0, sizeof(di)); + memset(&modal_ctrl, 0, sizeof(modal_ctrl)); n = 0; - PtSetArg( &args[n++], Pt_ARG_GROUP_ROWS_COLS, 0, 0 ); - PtSetArg( &args[n++], Pt_ARG_WIDTH, 350, 0 ); - PtSetArg( &args[n++], Pt_ARG_GROUP_ORIENTATION, - Pt_GROUP_VERTICAL, 0 ); - PtSetArg( &args[n++], Pt_ARG_GROUP_FLAGS, - Pt_TRUE, Pt_GROUP_NO_KEYS | Pt_GROUP_STRETCH_HORIZONTAL ); - PtSetArg( &args[n++], Pt_ARG_CONTAINER_FLAGS, Pt_FALSE, Pt_TRUE ); - pane = PtCreateWidget( PtGroup, NULL, n, args ); + PtSetArg(&args[n++], Pt_ARG_GROUP_ROWS_COLS, 0, 0); + PtSetArg(&args[n++], Pt_ARG_WIDTH, 350, 0); + PtSetArg(&args[n++], Pt_ARG_GROUP_ORIENTATION, + Pt_GROUP_VERTICAL, 0); + PtSetArg(&args[n++], Pt_ARG_GROUP_FLAGS, + Pt_TRUE, Pt_GROUP_NO_KEYS | Pt_GROUP_STRETCH_HORIZONTAL); + PtSetArg(&args[n++], Pt_ARG_CONTAINER_FLAGS, Pt_FALSE, Pt_TRUE); + pane = PtCreateWidget(PtGroup, NULL, n, args); n = 0; - PtSetArg( &args[n++], Pt_ARG_TEXT_STRING, message, 0 ); - PtCreateWidget( PtLabel, pane, n, args ); + PtSetArg(&args[n++], Pt_ARG_TEXT_STRING, message, 0); + PtCreateWidget(PtLabel, pane, n, args); - if( textfield != NULL ) + if (textfield != NULL) { n = 0; - PtSetArg( &args[n++], Pt_ARG_MAX_LENGTH, IOSIZE - 1, 0 ); - PtSetArg( &args[n++], Pt_ARG_TEXT_STRING, textfield, 0 ); - PtSetArg( &args[n++], Pt_ARG_POINTER, textfield, 0 ); - gui_ph_dialog_text = PtCreateWidget( PtText, pane, n, args ); - PtAddCallback( gui_ph_dialog_text, Pt_CB_ACTIVATE, - gui_ph_dialog_text_enter, &modal_ctrl ); + PtSetArg(&args[n++], Pt_ARG_MAX_LENGTH, IOSIZE - 1, 0); + PtSetArg(&args[n++], Pt_ARG_TEXT_STRING, textfield, 0); + PtSetArg(&args[n++], Pt_ARG_POINTER, textfield, 0); + gui_ph_dialog_text = PtCreateWidget(PtText, pane, n, args); + PtAddCallback(gui_ph_dialog_text, Pt_CB_ACTIVATE, + gui_ph_dialog_text_enter, &modal_ctrl); } di.parent = gui.vimWindow; @@ -1615,28 +1616,28 @@ di.callback = gui_ph_dialog_close; di.data = &modal_ctrl; - dialog = PtCreateDialog( &di ); - PtAddFilterCallback( dialog, Ph_EV_KEY, - gui_ph_dialog_esc, &modal_ctrl ); + dialog = PtCreateDialog(&di); + PtAddFilterCallback(dialog, Ph_EV_KEY, + gui_ph_dialog_esc, &modal_ctrl); - if( gui_ph_dialog_text != NULL ) - PtGiveFocus( gui_ph_dialog_text, NULL ); + if (gui_ph_dialog_text != NULL) + PtGiveFocus(gui_ph_dialog_text, NULL); /* Open dialog, block the vim window and wait for the dialog to close */ - PtRealizeWidget( dialog ); - PtMakeModal( dialog, Ph_CURSOR_NOINPUT, Ph_CURSOR_DEFAULT_COLOR ); - dialog_result = (int) PtModalBlock( &modal_ctrl, 0 ); + PtRealizeWidget(dialog); + PtMakeModal(dialog, Ph_CURSOR_NOINPUT, Ph_CURSOR_DEFAULT_COLOR); + dialog_result = (int) PtModalBlock(&modal_ctrl, 0); - PtDestroyWidget( dialog ); + PtDestroyWidget(dialog); gui_ph_dialog_text = NULL; } #endif } - vim_free( button_array ); - vim_free( buttons_copy ); + vim_free(button_array); + vim_free(buttons_copy); - return( dialog_result ); + return dialog_result; } #endif /****************************************************************************/ @@ -1647,12 +1648,12 @@ { PhPoint_t *pos; - pos = PtWidgetPos( gui.vimWindow, NULL ); + pos = PtWidgetPos(gui.vimWindow, NULL); *x = pos->x; *y = pos->y; - return( OK ); + return OK; } void @@ -1660,7 +1661,7 @@ { PhPoint_t pos = { x, y }; - PtSetResource( gui.vimWindow, Pt_ARG_POS, &pos, 0 ); + PtSetResource(gui.vimWindow, Pt_ARG_POS, &pos, 0); } void @@ -1676,10 +1677,10 @@ window_size.h += pg_margin_top + pg_margin_bottom; #endif - PtSetResource( gui.vimWindow, Pt_ARG_MINIMUM_DIM, &min_size, 0 ); - PtSetResource( gui.vimWindow, Pt_ARG_DIM, &window_size, 0 ); + PtSetResource(gui.vimWindow, Pt_ARG_MINIMUM_DIM, &min_size, 0); + PtSetResource(gui.vimWindow, Pt_ARG_DIM, &window_size, 0); - if( ! PtWidgetIsRealized( gui.vimWindow ) ) + if (! PtWidgetIsRealized(gui.vimWindow)) gui_ph_resize_container(); } @@ -1692,8 +1693,8 @@ { PhRect_t console; - PhWindowQueryVisible( Ph_QUERY_WORKSPACE, 0, - PhInputGroup( NULL ), &console ); + PhWindowQueryVisible(Ph_QUERY_WORKSPACE, 0, + PhInputGroup(NULL), &console); *screen_w = console.lr.x - console.ul.x + 1; *screen_h = console.lr.y - console.ul.y + 1; @@ -1704,11 +1705,11 @@ { PhWindowEvent_t event; - memset( &event, 0, sizeof (event) ); + memset(&event, 0, sizeof (event)); event.event_f = Ph_WM_HIDE; event.event_state = Ph_WM_EVSTATE_HIDE; - event.rid = PtWidgetRid( gui.vimWindow ); - PtForwardWindowEvent( &event ); + event.rid = PtWidgetRid(gui.vimWindow); + PtForwardWindowEvent(&event); } #if defined(FEAT_EVAL) || defined(PROTO) @@ -1720,11 +1721,11 @@ { PhWindowEvent_t event; - memset( &event, 0, sizeof (event) ); + memset(&event, 0, sizeof (event)); event.event_f = Ph_WM_TOFRONT; event.event_state = Ph_WM_EVSTATE_FFRONT; - event.rid = PtWidgetRid( gui.vimWindow ); - PtForwardWindowEvent( &event ); + event.rid = PtWidgetRid(gui.vimWindow); + PtForwardWindowEvent(&event); } #endif @@ -1732,9 +1733,9 @@ gui_mch_settitle(char_u *title, char_u *icon) { #ifdef USE_PANEL_GROUP - gui_ph_pg_set_buffer_num( curwin->w_buffer->b_fnum ); + gui_ph_pg_set_buffer_num(curwin->w_buffer->b_fnum); #endif - PtSetResource( gui.vimWindow, Pt_ARG_WINDOW_TITLE, title, 0 ); + PtSetResource(gui.vimWindow, Pt_ARG_WINDOW_TITLE, title, 0); /* Not sure what to do with the icon text, set balloon text somehow? */ } @@ -1747,10 +1748,10 @@ int n = 0; PtArg_t args[3]; - PtSetArg( &args[ n++ ], Pt_ARG_MAXIMUM, max, 0 ); - PtSetArg( &args[ n++ ], Pt_ARG_SLIDER_SIZE, size, 0 ); - PtSetArg( &args[ n++ ], Pt_ARG_GAUGE_VALUE, val, 0 ); - PtSetResources( sb->id, n, args ); + PtSetArg(&args[ n++ ], Pt_ARG_MAXIMUM, max, 0); + PtSetArg(&args[ n++ ], Pt_ARG_SLIDER_SIZE, size, 0); + PtSetArg(&args[ n++ ], Pt_ARG_GAUGE_VALUE, val, 0); + PtSetResources(sb->id, n, args); } void @@ -1758,7 +1759,7 @@ { PhArea_t area = {{ x, y }, { w, h }}; - PtSetResource( sb->id, Pt_ARG_AREA, &area, 0 ); + PtSetResource(sb->id, Pt_ARG_AREA, &area, 0); } void @@ -1774,12 +1775,12 @@ * * Also, don't let the scrollbar get focus */ - PtSetArg( &args[ n++ ], Pt_ARG_FLAGS, Pt_DELAY_REALIZE, - Pt_DELAY_REALIZE | Pt_GETS_FOCUS ); - PtSetArg( &args[ n++ ], Pt_ARG_SCROLLBAR_FLAGS, Pt_SCROLLBAR_SHOW_ARROWS, 0); + PtSetArg(&args[ n++ ], Pt_ARG_FLAGS, Pt_DELAY_REALIZE, + Pt_DELAY_REALIZE | Pt_GETS_FOCUS); + PtSetArg(&args[ n++ ], Pt_ARG_SCROLLBAR_FLAGS, Pt_SCROLLBAR_SHOW_ARROWS, 0); #if 0 /* Don't need this anchoring for the scrollbars */ - if( orient == SBAR_HORIZ ) + if (orient == SBAR_HORIZ) { anchor_flags = Pt_BOTTOM_ANCHORED_BOTTOM | Pt_LEFT_ANCHORED_LEFT | Pt_RIGHT_ANCHORED_RIGHT; @@ -1787,40 +1788,40 @@ else { anchor_flags = Pt_BOTTOM_ANCHORED_BOTTOM | Pt_TOP_ANCHORED_TOP; - if( sb->wp != NULL ) + if (sb->wp != NULL) { - if( sb == &sb->wp->w_scrollbars[ SBAR_LEFT ] ) + if (sb == &sb->wp->w_scrollbars[ SBAR_LEFT ]) anchor_flags |= Pt_LEFT_ANCHORED_LEFT; else anchor_flags |= Pt_RIGHT_ANCHORED_RIGHT; } } - PtSetArg( &args[ n++ ], Pt_ARG_ANCHOR_FLAGS, anchor_flags, Pt_IS_ANCHORED ); + PtSetArg(&args[ n++ ], Pt_ARG_ANCHOR_FLAGS, anchor_flags, Pt_IS_ANCHORED); #endif - PtSetArg( &args[ n++ ], Pt_ARG_ORIENTATION, - (orient == SBAR_HORIZ) ? Pt_HORIZONTAL : Pt_VERTICAL, 0 ); + PtSetArg(&args[ n++ ], Pt_ARG_ORIENTATION, + (orient == SBAR_HORIZ) ? Pt_HORIZONTAL : Pt_VERTICAL, 0); #ifdef USE_PANEL_GROUP - sb->id = PtCreateWidget( PtScrollbar, gui.vimPanelGroup, n, args ); + sb->id = PtCreateWidget(PtScrollbar, gui.vimPanelGroup, n, args); #else - sb->id = PtCreateWidget( PtScrollbar, gui.vimContainer, n, args ); + sb->id = PtCreateWidget(PtScrollbar, gui.vimContainer, n, args); #endif - PtAddCallback( sb->id, Pt_CB_SCROLLBAR_MOVE, gui_ph_handle_scrollbar, sb ); + PtAddCallback(sb->id, Pt_CB_SCROLLBAR_MOVE, gui_ph_handle_scrollbar, sb); } void gui_mch_enable_scrollbar(scrollbar_T *sb, int flag) { - if( flag != 0 ) - PtRealizeWidget( sb->id ); + if (flag != 0) + PtRealizeWidget(sb->id); else - PtUnrealizeWidget( sb->id ); + PtUnrealizeWidget(sb->id); } void gui_mch_destroy_scrollbar(scrollbar_T *sb) { - PtDestroyWidget( sb->id ); + PtDestroyWidget(sb->id); sb->id = NULL; } @@ -1865,8 +1866,8 @@ return; if (shape == MSHAPE_HIDE || gui.pointer_hidden) - PtSetResource( gui.vimTextArea, Pt_ARG_CURSOR_TYPE, Ph_CURSOR_NONE, - 0 ); + PtSetResource(gui.vimTextArea, Pt_ARG_CURSOR_TYPE, Ph_CURSOR_NONE, + 0); else { if (shape >= MSHAPE_NUMBERED) @@ -1874,7 +1875,7 @@ else id = mshape_ids[shape]; - PtSetResource( gui.vimTextArea, Pt_ARG_CURSOR_TYPE, id, 0 ); + PtSetResource(gui.vimTextArea, Pt_ARG_CURSOR_TYPE, id, 0); } if (shape != MSHAPE_HIDE) last_shape = shape; @@ -1884,19 +1885,19 @@ void gui_mch_mousehide(int hide) { - if( gui.pointer_hidden != hide ) + if (gui.pointer_hidden != hide) { gui.pointer_hidden = hide; #ifdef FEAT_MOUSESHAPE - if( hide ) - PtSetResource( gui.vimTextArea, Pt_ARG_CURSOR_TYPE, - Ph_CURSOR_NONE, 0 ); + if (hide) + PtSetResource(gui.vimTextArea, Pt_ARG_CURSOR_TYPE, + Ph_CURSOR_NONE, 0); else - mch_set_mouse_shape( last_shape ); + mch_set_mouse_shape(last_shape); #else - PtSetResource( gui.vimTextArea, Pt_ARG_CURSOR_TYPE, - ( hide == MOUSE_SHOW ) ? GUI_PH_MOUSE_TYPE : Ph_CURSOR_NONE, - 0 ); + PtSetResource(gui.vimTextArea, Pt_ARG_CURSOR_TYPE, + (hide == MOUSE_SHOW) ? GUI_PH_MOUSE_TYPE : Ph_CURSOR_NONE, + 0); #endif } } @@ -1909,8 +1910,8 @@ /* FIXME: does this return the correct position, * with respect to the border? */ - PhQueryCursor( PhInputGroup( NULL ), &info ); - PtGetAbsPosition( gui.vimTextArea , &ix, &iy ); + PhQueryCursor(PhInputGroup(NULL), &info); + PtGetAbsPosition(gui.vimTextArea , &ix, &iy); *x = info.pos.x - ix; *y = info.pos.y - iy; @@ -1921,9 +1922,9 @@ { short abs_x, abs_y; - PtGetAbsPosition( gui.vimTextArea, &abs_x, &abs_y ); + PtGetAbsPosition(gui.vimTextArea, &abs_x, &abs_y); /* Add the border offset? */ - PhMoveCursorAbs( PhInputGroup( NULL ), abs_x + x, abs_y + y ); + PhMoveCursorAbs(PhInputGroup(NULL), abs_x + x, abs_y + y); } /****************************************************************************/ @@ -1951,34 +1952,34 @@ color_diff = gui_get_lightness(gui_ph_mouse_color) - gui_get_lightness(gui.back_pixel); - if( abs( color_diff ) < 64 ) + if (abs(color_diff) < 64) { short r, g, b; /* not a great algorithm... */ - r = PgRedValue( gui_ph_mouse_color ) ^ 255; - g = PgGreenValue( gui_ph_mouse_color ) ^ 255; - b = PgBlueValue( gui_ph_mouse_color ) ^ 255; + r = PgRedValue(gui_ph_mouse_color) ^ 255; + g = PgGreenValue(gui_ph_mouse_color) ^ 255; + b = PgBlueValue(gui_ph_mouse_color) ^ 255; #ifndef FEAT_MOUSESHAPE - gui_ph_mouse_color = PgRGB( r, g, b ); - PtSetResource( gui.vimTextArea, Pt_ARG_CURSOR_COLOR, - gui_ph_mouse_color, 0 ); + gui_ph_mouse_color = PgRGB(r, g, b); + PtSetResource(gui.vimTextArea, Pt_ARG_CURSOR_COLOR, + gui_ph_mouse_color, 0); #endif } #endif - PtSetResource( gui.vimTextArea, Pt_ARG_FILL_COLOR, gui.back_pixel, 0 ); + PtSetResource(gui.vimTextArea, Pt_ARG_FILL_COLOR, gui.back_pixel, 0); } static int hex_digit(int c) { if (VIM_ISDIGIT(c)) - return( c - '0' ); + return c - '0'; c = TOLOWER_ASC(c); if (c >= 'a' && c <= 'f') - return( c - 'a' + 10 ); - return( -1000 ); + return c - 'a' + 10; + return -1000; } @@ -2006,8 +2007,8 @@ static GuiColourTable table[] = { {"Black", RGB(0x00, 0x00, 0x00)}, - {"DarkGray", RGB(0x80, 0x80, 0x80)}, - {"DarkGrey", RGB(0x80, 0x80, 0x80)}, + {"DarkGray", RGB(0xA9, 0xA9, 0xA9)}, + {"DarkGrey", RGB(0xA9, 0xA9, 0xA9)}, {"Gray", RGB(0xC0, 0xC0, 0xC0)}, {"Grey", RGB(0xC0, 0xC0, 0xC0)}, {"LightGray", RGB(0xD3, 0xD3, 0xD3)}, @@ -2036,19 +2037,19 @@ {"LightRed", RGB(0xFF, 0xA0, 0xA0)}, {"DarkBlue", RGB(0x00, 0x00, 0x80)}, {"Blue", RGB(0x00, 0x00, 0xFF)}, - {"LightBlue", RGB(0xA0, 0xA0, 0xFF)}, + {"LightBlue", RGB(0xAD, 0xD8, 0xE6)}, {"DarkGreen", RGB(0x00, 0x80, 0x00)}, {"Green", RGB(0x00, 0xFF, 0x00)}, - {"LightGreen", RGB(0xA0, 0xFF, 0xA0)}, + {"LightGreen", RGB(0x90, 0xEE, 0x90)}, {"DarkCyan", RGB(0x00, 0x80, 0x80)}, {"Cyan", RGB(0x00, 0xFF, 0xFF)}, - {"LightCyan", RGB(0xA0, 0xFF, 0xFF)}, + {"LightCyan", RGB(0xE0, 0xFF, 0xFF)}, {"DarkMagenta", RGB(0x80, 0x00, 0x80)}, {"Magenta", RGB(0xFF, 0x00, 0xFF)}, {"LightMagenta", RGB(0xFF, 0xA0, 0xFF)}, {"Brown", RGB(0x80, 0x40, 0x40)}, {"Yellow", RGB(0xFF, 0xFF, 0x00)}, - {"LightYellow", RGB(0xFF, 0xFF, 0xA0)}, + {"LightYellow", RGB(0xFF, 0xFF, 0xE0)}, {"SeaGreen", RGB(0x2E, 0x8B, 0x57)}, {"Orange", RGB(0xFF, 0xA5, 0x00)}, {"Purple", RGB(0xA0, 0x20, 0xF0)}, @@ -2057,20 +2058,20 @@ }; /* is name #rrggbb format? */ - if( name[0] == '#' && STRLEN( name ) == 7 ) + if (name[0] == '#' && STRLEN(name) == 7) { - r = hex_digit( name[1] ) * 16 + hex_digit( name[2] ); - g = hex_digit( name[3] ) * 16 + hex_digit( name[4] ); - b = hex_digit( name[5] ) * 16 + hex_digit( name[6] ); - if( r < 0 || g < 0 || b < 0 ) + r = hex_digit(name[1]) * 16 + hex_digit(name[2]); + g = hex_digit(name[3]) * 16 + hex_digit(name[4]); + b = hex_digit(name[5]) * 16 + hex_digit(name[6]); + if (r < 0 || g < 0 || b < 0) return INVALCOLOR; - return( RGB( r, g, b ) ); + return RGB(r, g, b); } - for( i = 0; i < ARRAY_LENGTH( table ); i++ ) + for (i = 0; i < ARRAY_LENGTH(table); i++) { - if( STRICMP( name, table[i].name ) == 0 ) - return( table[i].colour ); + if (STRICMP(name, table[i].name) == 0) + return table[i].colour; } /* @@ -2114,7 +2115,7 @@ if (STRICMP(color, name) == 0) { fclose(fd); - return( (guicolor_T) RGB(r,g,b) ); + return (guicolor_T)RGB(r, g, b); } } @@ -2128,13 +2129,13 @@ void gui_mch_set_fg_color(guicolor_T color) { - PgSetTextColor( color ); + PgSetTextColor(color); } void gui_mch_set_bg_color(guicolor_T color) { - PgSetFillColor( color ); + PgSetFillColor(color); } void @@ -2147,21 +2148,21 @@ { PhRect_t rect; - rect.ul.x = FILL_X( col ); - rect.ul.y = FILL_Y( row ); + rect.ul.x = FILL_X(col); + rect.ul.y = FILL_Y(row); /* FIXME: This has an off by one pixel problem */ rect.lr.x = rect.ul.x + nc * gui.char_width; rect.lr.y = rect.ul.y + nr * gui.char_height; - if( nc > 0 ) + if (nc > 0) rect.lr.x -= 1; - if( nr > 0 ) + if (nr > 0) rect.lr.y -= 1; DRAW_START; - PgSetDrawMode( Pg_DrawModeDSTINVERT ); - PgDrawRect( &rect, Pg_DRAW_FILL ); - PgSetDrawMode( Pg_DrawModeSRCCOPY ); + PgSetDrawMode(Pg_DrawModeDSTINVERT); + PgDrawRect(&rect, Pg_DRAW_FILL); + PgSetDrawMode(Pg_DrawModeSRCCOPY); DRAW_END; } @@ -2169,13 +2170,13 @@ gui_mch_clear_block(int row1, int col1, int row2, int col2) { PhRect_t block = { - { FILL_X( col1 ), FILL_Y( row1 ) }, - { FILL_X( col2 + 1 ) - 1, FILL_Y( row2 + 1 ) - 1} + { FILL_X(col1), FILL_Y(row1) }, + { FILL_X(col2 + 1) - 1, FILL_Y(row2 + 1) - 1} }; DRAW_START; - gui_mch_set_bg_color( gui.back_pixel ); - PgDrawRect( &block, Pg_DRAW_FILL ); + gui_mch_set_bg_color(gui.back_pixel); + PgDrawRect(&block, Pg_DRAW_FILL); DRAW_END; } @@ -2188,12 +2189,12 @@ Rows * gui.char_height + gui.border_width - 1 } }; - if( is_ignore_draw == TRUE ) + if (is_ignore_draw == TRUE) return; DRAW_START; - gui_mch_set_bg_color( gui.back_pixel ); - PgDrawRect( &text_rect, Pg_DRAW_FILL ); + gui_mch_set_bg_color(gui.back_pixel); + PgDrawRect(&text_rect, Pg_DRAW_FILL); DRAW_END; } @@ -2203,28 +2204,28 @@ PhRect_t rect; PhPoint_t delta; - rect.ul.x = FILL_X( gui.scroll_region_left ); - rect.ul.y = FILL_Y( row + num_lines ); + rect.ul.x = FILL_X(gui.scroll_region_left); + rect.ul.y = FILL_Y(row + num_lines); - rect.lr.x = FILL_X( gui.scroll_region_right + 1 ) - 1; - rect.lr.y = FILL_Y( gui.scroll_region_bot + 1) - 1; + rect.lr.x = FILL_X(gui.scroll_region_right + 1) - 1; + rect.lr.y = FILL_Y(gui.scroll_region_bot + 1) - 1; - PtWidgetOffset( gui.vimTextArea, &gui_ph_raw_offset ); - PhTranslatePoint( &gui_ph_raw_offset, PtWidgetPos(gui.vimTextArea, NULL)); - PhTranslateRect( &rect, &gui_ph_raw_offset ); + PtWidgetOffset(gui.vimTextArea, &gui_ph_raw_offset); + PhTranslatePoint(&gui_ph_raw_offset, PtWidgetPos(gui.vimTextArea, NULL)); + PhTranslateRect(&rect, &gui_ph_raw_offset); delta.x = 0; delta.y = -num_lines * gui.char_height; PgFlush(); - PhBlit( PtWidgetRid( PtFindDisjoint( gui.vimTextArea ) ), &rect, &delta ); + PhBlit(PtWidgetRid(PtFindDisjoint(gui.vimTextArea)), &rect, &delta); gui_clear_block( gui.scroll_region_bot - num_lines + 1, gui.scroll_region_left, gui.scroll_region_bot, - gui.scroll_region_right ); + gui.scroll_region_right); } void @@ -2233,25 +2234,25 @@ PhRect_t rect; PhPoint_t delta; - rect.ul.x = FILL_X( gui.scroll_region_left ); - rect.ul.y = FILL_Y( row ); + rect.ul.x = FILL_X(gui.scroll_region_left); + rect.ul.y = FILL_Y(row); - rect.lr.x = FILL_X( gui.scroll_region_right + 1 ) - 1; - rect.lr.y = FILL_Y( gui.scroll_region_bot - num_lines + 1 ) - 1; + rect.lr.x = FILL_X(gui.scroll_region_right + 1) - 1; + rect.lr.y = FILL_Y(gui.scroll_region_bot - num_lines + 1) - 1; - PtWidgetOffset( gui.vimTextArea, &gui_ph_raw_offset ); - PhTranslatePoint( &gui_ph_raw_offset, PtWidgetPos( gui.vimTextArea, NULL ) ); - PhTranslateRect( &rect, &gui_ph_raw_offset ); + PtWidgetOffset(gui.vimTextArea, &gui_ph_raw_offset); + PhTranslatePoint(&gui_ph_raw_offset, PtWidgetPos(gui.vimTextArea, NULL)); + PhTranslateRect(&rect, &gui_ph_raw_offset); delta.x = 0; delta.y = num_lines * gui.char_height; PgFlush(); - PhBlit( PtWidgetRid( PtFindDisjoint( gui.vimTextArea ) ) , &rect, &delta ); + PhBlit(PtWidgetRid(PtFindDisjoint(gui.vimTextArea)) , &rect, &delta); - gui_clear_block( row, gui.scroll_region_left, - row + num_lines - 1, gui.scroll_region_right ); + gui_clear_block(row, gui.scroll_region_left, + row + num_lines - 1, gui.scroll_region_right); } void @@ -2260,37 +2261,37 @@ static char *utf8_buffer = NULL; static int utf8_len = 0; - PhPoint_t pos = { TEXT_X( col ), TEXT_Y( row ) }; + PhPoint_t pos = { TEXT_X(col), TEXT_Y(row) }; PhRect_t rect; - if( is_ignore_draw == TRUE ) + if (is_ignore_draw == TRUE) return; DRAW_START; - if( !( flags & DRAW_TRANSP ) ) + if (!(flags & DRAW_TRANSP)) { PgDrawIRect( - FILL_X( col ), FILL_Y( row ), - FILL_X( col + len ) - 1, FILL_Y( row + 1 ) - 1, - Pg_DRAW_FILL ); + FILL_X(col), FILL_Y(row), + FILL_X(col + len) - 1, FILL_Y(row + 1) - 1, + Pg_DRAW_FILL); } - if( flags & DRAW_UNDERL ) - PgSetUnderline( gui.norm_pixel, Pg_TRANSPARENT, 0 ); + if (flags & DRAW_UNDERL) + PgSetUnderline(gui.norm_pixel, Pg_TRANSPARENT, 0); - if( charset_translate != NULL + if (charset_translate != NULL #ifdef FEAT_MBYTE && enc_utf8 == 0 #endif - ) + ) { int src_taken, dst_made; /* Use a static buffer to avoid large amounts of de/allocations */ - if( utf8_len < len ) + if (utf8_len < len) { - utf8_buffer = realloc( utf8_buffer, len * MB_LEN_MAX ); + utf8_buffer = realloc(utf8_buffer, len * MB_LEN_MAX); utf8_len = len; } @@ -2301,36 +2302,36 @@ &src_taken, utf8_buffer, utf8_len, - &dst_made ); + &dst_made); s = utf8_buffer; len = dst_made; } - PgDrawText( s, len, &pos, 0 ); + PgDrawText(s, len, &pos, 0); - if( flags & DRAW_BOLD ) + if (flags & DRAW_BOLD) { /* FIXME: try and only calculate these values once... */ - rect.ul.x = FILL_X( col ) + 1; - rect.ul.y = FILL_Y( row ); - rect.lr.x = FILL_X( col + len ) - 1; - rect.lr.y = FILL_Y( row + 1) - 1; - /* PgSetUserClip( NULL ) causes the scrollbar to not redraw... */ + rect.ul.x = FILL_X(col) + 1; + rect.ul.y = FILL_Y(row); + rect.lr.x = FILL_X(col + len) - 1; + rect.lr.y = FILL_Y(row + 1) - 1; + /* PgSetUserClip(NULL) causes the scrollbar to not redraw... */ #if 0 pos.x++; - PgSetUserClip( &rect ); - PgDrawText( s, len, &pos, 0 ); - PgSetUserClip( NULL ); + PgSetUserClip(&rect); + PgDrawText(s, len, &pos, 0); + PgSetUserClip(NULL); #else - rect.lr.y -= ( p_linespace + 1 ) / 2; + rect.lr.y -= (p_linespace + 1) / 2; /* XXX: DrawTextArea doesn't work with phditto */ - PgDrawTextArea( s, len, &rect, Pg_TEXT_BOTTOM ); + PgDrawTextArea(s, len, &rect, Pg_TEXT_BOTTOM); #endif } - if( flags & DRAW_UNDERL ) - PgSetUnderline( Pg_TRANSPARENT, Pg_TRANSPARENT, 0 ); + if (flags & DRAW_UNDERL) + PgSetUnderline(Pg_TRANSPARENT, Pg_TRANSPARENT, 0); DRAW_END; } @@ -2345,14 +2346,14 @@ /* FIXME: Double width characters */ - r.ul.x = FILL_X( gui.col ); - r.ul.y = FILL_Y( gui.row ); + r.ul.x = FILL_X(gui.col); + r.ul.y = FILL_Y(gui.row); r.lr.x = r.ul.x + gui.char_width - 1; r.lr.y = r.ul.y + gui.char_height - 1; DRAW_START; - PgSetStrokeColor( color ); - PgDrawRect( &r, Pg_DRAW_STROKE ); + PgSetStrokeColor(color); + PgDrawRect(&r, Pg_DRAW_STROKE); DRAW_END; } @@ -2361,14 +2362,14 @@ { PhRect_t r; - r.ul.x = FILL_X( gui.col ); - r.ul.y = FILL_Y( gui.row ) + gui.char_height - h; + r.ul.x = FILL_X(gui.col); + r.ul.y = FILL_Y(gui.row) + gui.char_height - h; r.lr.x = r.ul.x + w - 1; r.lr.y = r.ul.y + h - 1; DRAW_START; - gui_mch_set_bg_color( color ); - PgDrawRect( &r, Pg_DRAW_FILL ); + gui_mch_set_bg_color(color); + PgDrawRect(&r, Pg_DRAW_FILL); DRAW_END; } @@ -2384,10 +2385,10 @@ gui_mch_start_blink(void) { /* Only turn on the timer on if none of the times are zero */ - if( blink_waittime && blink_ontime && blink_offtime && gui.in_focus) + if (blink_waittime && blink_ontime && blink_offtime && gui.in_focus) { - PtSetResource( gui_ph_timer_cursor, Pt_ARG_TIMER_INITIAL, - blink_waittime, 0 ); + PtSetResource(gui_ph_timer_cursor, Pt_ARG_TIMER_INITIAL, + blink_waittime, 0); blink_state = BLINK_ON; gui_update_cursor(TRUE, FALSE); } @@ -2396,9 +2397,9 @@ void gui_mch_stop_blink(void) { - PtSetResource( gui_ph_timer_cursor, Pt_ARG_TIMER_INITIAL, 0, 0 ); + PtSetResource(gui_ph_timer_cursor, Pt_ARG_TIMER_INITIAL, 0, 0); - if( blink_state == BLINK_OFF ) + if (blink_state == BLINK_OFF) gui_update_cursor(TRUE, FALSE); blink_state = BLINK_NONE; @@ -2416,15 +2417,15 @@ void gui_mch_flash(int msec) { - PgSetFillXORColor( Pg_BLACK, Pg_WHITE ); - PgSetDrawMode( Pg_DRAWMODE_XOR ); + PgSetFillXORColor(Pg_BLACK, Pg_WHITE); + PgSetDrawMode(Pg_DRAWMODE_XOR); gui_mch_clear_all(); gui_mch_flush(); - ui_delay( (long) msec, TRUE ); + ui_delay((long) msec, TRUE); gui_mch_clear_all(); - PgSetDrawMode( Pg_DRAWMODE_OPAQUE ); + PgSetDrawMode(Pg_DRAWMODE_OPAQUE); gui_mch_flush(); } @@ -2439,7 +2440,7 @@ { PhArea_t area = {{x, y}, {w, h}}; - PtSetResource( gui.vimTextArea, Pt_ARG_AREA, &area, 0 ); + PtSetResource(gui.vimTextArea, Pt_ARG_AREA, &area, 0); } int @@ -2450,8 +2451,8 @@ for (i = 0; special_keys[i].key_sym != 0; i++) if (name[0] == special_keys[i].vim_code0 && name[1] == special_keys[i].vim_code1) - return( OK ); - return( FAIL ); + return OK; + return FAIL; } /****************************************************************************/ @@ -2495,23 +2496,23 @@ }; static PhImage_t * -gui_ph_toolbar_load_icon( char_u *iconfile ) +gui_ph_toolbar_load_icon(char_u *iconfile) { static PhImage_t external_icon; PhImage_t *temp_phi = NULL; - temp_phi = PxLoadImage( iconfile, NULL ); - if( temp_phi != NULL ) + temp_phi = PxLoadImage(iconfile, NULL); + if (temp_phi != NULL) { /* The label widget will free the image/palette/etc. for us when * it's destroyed */ temp_phi->flags |= Ph_RELEASE_IMAGE_ALL; - memcpy( &external_icon, temp_phi, sizeof( external_icon ) ); - free( temp_phi ); + memcpy(&external_icon, temp_phi, sizeof(external_icon)); + free(temp_phi); temp_phi = &external_icon; } - return( temp_phi ); + return temp_phi; } /* @@ -2522,45 +2523,45 @@ * PhImage_t are copied, and the original PhImage_t aren't needed anymore). */ static PhImage_t * -gui_ph_toolbar_find_icon( vimmenu_T *menu ) +gui_ph_toolbar_find_icon(vimmenu_T *menu) { char_u full_pathname[ MAXPATHL + 1 ]; PhImage_t *icon = NULL; - if( menu->icon_builtin == FALSE ) + if (menu->icon_builtin == FALSE) { - if( menu->iconfile != NULL ) + if (menu->iconfile != NULL) /* TODO: use gui_find_iconfile() */ - icon = gui_ph_toolbar_load_icon( menu->iconfile ); + icon = gui_ph_toolbar_load_icon(menu->iconfile); /* TODO: Restrict loading to just .png? Search for any format? */ - if( ( icon == NULL ) && - ( ( gui_find_bitmap( menu->name, full_pathname, "gif" ) == OK ) || - ( gui_find_bitmap( menu->name, full_pathname, "png" ) == OK ) ) ) - icon = gui_ph_toolbar_load_icon( full_pathname ); + if ((icon == NULL) && + ((gui_find_bitmap(menu->name, full_pathname, "gif") == OK) || + (gui_find_bitmap(menu->name, full_pathname, "png") == OK))) + icon = gui_ph_toolbar_load_icon(full_pathname); - if( icon != NULL ) - return( icon ); + if (icon != NULL) + return icon; } - if( menu->iconidx >= 0 && - ( menu->iconidx < ARRAY_LENGTH( gui_ph_toolbar_images ) ) ) + if (menu->iconidx >= 0 && + (menu->iconidx < ARRAY_LENGTH(gui_ph_toolbar_images))) { - return( gui_ph_toolbar_images[ menu->iconidx ] ); + return gui_ph_toolbar_images[menu->iconidx]; } - return( NULL ); + return NULL; } #endif -#if defined( FEAT_MENU ) || defined( PROTO ) +#if defined(FEAT_MENU) || defined(PROTO) void gui_mch_enable_menu(int flag) { - if( flag != 0 ) - PtRealizeWidget( gui.vimMenuBar ); + if (flag != 0) + PtRealizeWidget(gui.vimMenuBar); else - PtUnrealizeWidget( gui.vimMenuBar ); + PtUnrealizeWidget(gui.vimMenuBar); } void @@ -2571,30 +2572,30 @@ /* Change the position of a menu button in the parent */ static void -gui_ph_position_menu( PtWidget_t *widget, int priority ) +gui_ph_position_menu(PtWidget_t *widget, int priority) { PtWidget_t *traverse; vimmenu_T *menu; - traverse = PtWidgetChildBack( PtWidgetParent( widget ) ); + traverse = PtWidgetChildBack(PtWidgetParent(widget)); /* Iterate through the list of widgets in traverse, until * we find the position we want to insert our widget into */ /* TODO: traverse from front to back, possible speedup? */ - while( traverse != NULL ) + while (traverse != NULL) { - PtGetResource( traverse, Pt_ARG_POINTER, &menu, 0 ); + PtGetResource(traverse, Pt_ARG_POINTER, &menu, 0); - if( menu != NULL && + if (menu != NULL && priority < menu->priority && - widget != traverse ) + widget != traverse) { /* Insert the widget before the current traverse widget */ - PtWidgetInsert( widget, traverse, 1 ); + PtWidgetInsert(widget, traverse, 1); return; } - traverse = PtWidgetBrotherInFront( traverse ); + traverse = PtWidgetBrotherInFront(traverse); } } @@ -2610,11 +2611,11 @@ menu->submenu_id = menu->id = NULL; - if( menu_is_menubar( menu->name ) ) + if (menu_is_menubar(menu->name)) { - accel_key = vim_strchr( menu->name, '&' ); - if( accel_key != NULL ) + accel_key = vim_strchr(menu->name, '&'); + if (accel_key != NULL) { mnemonic_str[0] = accel_key[1]; mnemonic_str[1] = NUL; @@ -2622,51 +2623,51 @@ /* Create the menu button */ n = 0; - PtSetArg( &args[ n++ ], Pt_ARG_TEXT_STRING, menu->dname, 0 ); - PtSetArg( &args[ n++ ], Pt_ARG_ACCEL_TEXT, menu->actext, 0 ); - if( accel_key != NULL ) - PtSetArg( &args[ n++ ], Pt_ARG_ACCEL_KEY, mnemonic_str, 0 ); - PtSetArg( &args[ n++ ], Pt_ARG_POINTER, menu, 0 ); + PtSetArg(&args[ n++ ], Pt_ARG_TEXT_STRING, menu->dname, 0); + PtSetArg(&args[ n++ ], Pt_ARG_ACCEL_TEXT, menu->actext, 0); + if (accel_key != NULL) + PtSetArg(&args[ n++ ], Pt_ARG_ACCEL_KEY, mnemonic_str, 0); + PtSetArg(&args[ n++ ], Pt_ARG_POINTER, menu, 0); - if( parent != NULL ) - PtSetArg( &args[ n++ ], Pt_ARG_BUTTON_TYPE, Pt_MENU_RIGHT, 0 ); + if (parent != NULL) + PtSetArg(&args[ n++ ], Pt_ARG_BUTTON_TYPE, Pt_MENU_RIGHT, 0); - menu->id = PtCreateWidget( PtMenuButton, + menu->id = PtCreateWidget(PtMenuButton, (parent == NULL) ? gui.vimMenuBar : parent->submenu_id, - n, args ); + n, args); - PtAddCallback( menu->id, Pt_CB_ARM, gui_ph_handle_pulldown_menu, menu ); + PtAddCallback(menu->id, Pt_CB_ARM, gui_ph_handle_pulldown_menu, menu); /* Create the actual menu */ n = 0; - if( parent != NULL ) - PtSetArg( &args[ n++ ], Pt_ARG_MENU_FLAGS, Pt_TRUE, Pt_MENU_CHILD ); + if (parent != NULL) + PtSetArg(&args[ n++ ], Pt_ARG_MENU_FLAGS, Pt_TRUE, Pt_MENU_CHILD); - menu->submenu_id = PtCreateWidget( PtMenu, menu->id, n, args ); + menu->submenu_id = PtCreateWidget(PtMenu, menu->id, n, args); - if( parent == NULL ) + if (parent == NULL) { - PtAddCallback( menu->submenu_id, Pt_CB_UNREALIZED, - gui_ph_handle_menu_unrealized, menu ); + PtAddCallback(menu->submenu_id, Pt_CB_UNREALIZED, + gui_ph_handle_menu_unrealized, menu); - if( menu->mnemonic != 0 ) + if (menu->mnemonic != 0) { - PtAddHotkeyHandler( gui.vimWindow, tolower( menu->mnemonic ), - Pk_KM_Alt, 0, menu, gui_ph_handle_pulldown_menu ); + PtAddHotkeyHandler(gui.vimWindow, tolower(menu->mnemonic), + Pk_KM_Alt, 0, menu, gui_ph_handle_pulldown_menu); } } - gui_ph_position_menu( menu->id, menu->priority ); + gui_ph_position_menu(menu->id, menu->priority); /* Redraw menubar here instead of gui_mch_draw_menubar */ - if( gui.menu_is_active ) - PtRealizeWidget( menu->id ); + if (gui.menu_is_active) + PtRealizeWidget(menu->id); } - else if( menu_is_popup( menu->name ) ) + else if (menu_is_popup(menu->name)) { - menu->submenu_id = PtCreateWidget( PtMenu, gui.vimWindow, 0, NULL ); - PtAddCallback( menu->submenu_id, Pt_CB_UNREALIZED, - gui_ph_handle_menu_unrealized, menu ); + menu->submenu_id = PtCreateWidget(PtMenu, gui.vimWindow, 0, NULL); + PtAddCallback(menu->submenu_id, Pt_CB_UNREALIZED, + gui_ph_handle_menu_unrealized, menu); } } @@ -2680,104 +2681,104 @@ PtArg_t args[13]; n = 0; - PtSetArg( &args[ n++ ], Pt_ARG_POINTER, menu, 0 ); + PtSetArg(&args[ n++ ], Pt_ARG_POINTER, menu, 0); #ifdef FEAT_TOOLBAR - if( menu_is_toolbar( parent->name ) ) + if (menu_is_toolbar(parent->name)) { - if( menu_is_separator( menu->name ) ) + if (menu_is_separator(menu->name)) { - PtSetArg( &args[ n++ ], Pt_ARG_SEP_FLAGS, - Pt_SEP_VERTICAL, Pt_SEP_ORIENTATION ); - PtSetArg( &args[ n++ ], Pt_ARG_SEP_TYPE, Pt_ETCHED_IN, 0 ); - PtSetArg( &args[ n++ ], Pt_ARG_ANCHOR_FLAGS, - Pt_TRUE, Pt_ANCHOR_TOP_BOTTOM ); - PtSetArg( &args[ n++ ], Pt_ARG_WIDTH, 2, 0 ); - menu->id = PtCreateWidget( PtSeparator, gui.vimToolBar, n, args ); + PtSetArg(&args[ n++ ], Pt_ARG_SEP_FLAGS, + Pt_SEP_VERTICAL, Pt_SEP_ORIENTATION); + PtSetArg(&args[ n++ ], Pt_ARG_SEP_TYPE, Pt_ETCHED_IN, 0); + PtSetArg(&args[ n++ ], Pt_ARG_ANCHOR_FLAGS, + Pt_TRUE, Pt_ANCHOR_TOP_BOTTOM); + PtSetArg(&args[ n++ ], Pt_ARG_WIDTH, 2, 0); + menu->id = PtCreateWidget(PtSeparator, gui.vimToolBar, n, args); } else { - if( strstr( (const char *) p_toolbar, "text" ) != NULL ) + if (strstr((const char *) p_toolbar, "text") != NULL) { - PtSetArg( &args[ n++ ], Pt_ARG_BALLOON_POSITION, - Pt_BALLOON_BOTTOM, 0 ); - PtSetArg( &args[ n++ ], Pt_ARG_TEXT_STRING, menu->dname, 0 ); - PtSetArg( &args[ n++ ], Pt_ARG_TEXT_FONT, "TextFont08", 0 ); + PtSetArg(&args[ n++ ], Pt_ARG_BALLOON_POSITION, + Pt_BALLOON_BOTTOM, 0); + PtSetArg(&args[ n++ ], Pt_ARG_TEXT_STRING, menu->dname, 0); + PtSetArg(&args[ n++ ], Pt_ARG_TEXT_FONT, "TextFont08", 0); } - if( ( strstr( (const char *) p_toolbar, "icons" ) != NULL ) && - ( gui_ph_toolbar_images != NULL ) ) + if ((strstr((const char *) p_toolbar, "icons") != NULL) && + (gui_ph_toolbar_images != NULL)) { - PtSetArg( &args[ n++ ], Pt_ARG_LABEL_IMAGE, - gui_ph_toolbar_find_icon( menu ), 0 ); - PtSetArg( &args[ n++ ], Pt_ARG_LABEL_TYPE, Pt_TEXT_IMAGE, 0 ); - PtSetArg( &args[ n++ ], Pt_ARG_TEXT_IMAGE_SPACING, 0, 0 ); + PtSetArg(&args[ n++ ], Pt_ARG_LABEL_IMAGE, + gui_ph_toolbar_find_icon(menu), 0); + PtSetArg(&args[ n++ ], Pt_ARG_LABEL_TYPE, Pt_TEXT_IMAGE, 0); + PtSetArg(&args[ n++ ], Pt_ARG_TEXT_IMAGE_SPACING, 0, 0); } - if( strstr( (const char *) p_toolbar, "tooltips" ) != NULL ) + if (strstr((const char *) p_toolbar, "tooltips") != NULL) { - PtSetArg( &args[ n++ ], Pt_ARG_LABEL_BALLOON, - gui_ph_show_tooltip, 0 ); - PtSetArg( &args[ n++ ], Pt_ARG_LABEL_FLAGS, - Pt_TRUE, Pt_SHOW_BALLOON ); + PtSetArg(&args[ n++ ], Pt_ARG_LABEL_BALLOON, + gui_ph_show_tooltip, 0); + PtSetArg(&args[ n++ ], Pt_ARG_LABEL_FLAGS, + Pt_TRUE, Pt_SHOW_BALLOON); } - PtSetArg( &args[ n++ ], Pt_ARG_MARGIN_HEIGHT, 1, 0 ); - PtSetArg( &args[ n++ ], Pt_ARG_MARGIN_WIDTH, 1, 0 ); - PtSetArg( &args[ n++ ], Pt_ARG_FLAGS, Pt_FALSE, - Pt_HIGHLIGHTED | Pt_GETS_FOCUS ); - PtSetArg( &args[ n++ ], Pt_ARG_FILL_COLOR, Pg_TRANSPARENT, 0 ); - menu->id = PtCreateWidget( PtButton, gui.vimToolBar, n, args ); + PtSetArg(&args[ n++ ], Pt_ARG_MARGIN_HEIGHT, 1, 0); + PtSetArg(&args[ n++ ], Pt_ARG_MARGIN_WIDTH, 1, 0); + PtSetArg(&args[ n++ ], Pt_ARG_FLAGS, Pt_FALSE, + Pt_HIGHLIGHTED | Pt_GETS_FOCUS); + PtSetArg(&args[ n++ ], Pt_ARG_FILL_COLOR, Pg_TRANSPARENT, 0); + menu->id = PtCreateWidget(PtButton, gui.vimToolBar, n, args); - PtAddCallback( menu->id, Pt_CB_ACTIVATE, gui_ph_handle_menu, menu ); + PtAddCallback(menu->id, Pt_CB_ACTIVATE, gui_ph_handle_menu, menu); } /* Update toolbar if it's open */ - if( PtWidgetIsRealized( gui.vimToolBar ) ) - PtRealizeWidget( menu->id ); + if (PtWidgetIsRealized(gui.vimToolBar)) + PtRealizeWidget(menu->id); } else #endif - if( menu_is_separator( menu->name ) ) + if (menu_is_separator(menu->name)) { - menu->id = PtCreateWidget( PtSeparator, parent->submenu_id, n, args ); + menu->id = PtCreateWidget(PtSeparator, parent->submenu_id, n, args); } else { - accel_key = vim_strchr( menu->name, '&' ); - if( accel_key != NULL ) + accel_key = vim_strchr(menu->name, '&'); + if (accel_key != NULL) { mnemonic_str[0] = accel_key[1]; mnemonic_str[1] = NUL; } - PtSetArg( &args[ n++ ], Pt_ARG_TEXT_STRING, menu->dname, 0 ); - if( accel_key != NULL ) - PtSetArg( &args[ n++ ], Pt_ARG_ACCEL_KEY, mnemonic_str, - 0 ); + PtSetArg(&args[ n++ ], Pt_ARG_TEXT_STRING, menu->dname, 0); + if (accel_key != NULL) + PtSetArg(&args[ n++ ], Pt_ARG_ACCEL_KEY, mnemonic_str, + 0); - PtSetArg( &args[ n++ ], Pt_ARG_ACCEL_TEXT, menu->actext, 0 ); + PtSetArg(&args[ n++ ], Pt_ARG_ACCEL_TEXT, menu->actext, 0); - menu->id = PtCreateWidget( PtMenuButton, parent->submenu_id, n, args ); + menu->id = PtCreateWidget(PtMenuButton, parent->submenu_id, n, args); - PtAddCallback( menu->id, Pt_CB_ACTIVATE, gui_ph_handle_menu, menu ); + PtAddCallback(menu->id, Pt_CB_ACTIVATE, gui_ph_handle_menu, menu); #ifdef USE_PANEL_GROUP - if( gui_ph_is_buffer_item( menu, parent ) == TRUE ) + if (gui_ph_is_buffer_item(menu, parent) == TRUE) { - PtAddCallback( menu->id, Pt_CB_DESTROYED, - gui_ph_handle_buffer_remove, menu ); - gui_ph_pg_add_buffer( menu->dname ); + PtAddCallback(menu->id, Pt_CB_DESTROYED, + gui_ph_handle_buffer_remove, menu); + gui_ph_pg_add_buffer(menu->dname); } #endif } - gui_ph_position_menu( menu->id, menu->priority ); + gui_ph_position_menu(menu->id, menu->priority); } void gui_mch_destroy_menu(vimmenu_T *menu) { - if( menu->submenu_id != NULL ) - PtDestroyWidget( menu->submenu_id ); - if( menu->id != NULL ) - PtDestroyWidget( menu->id ); + if (menu->submenu_id != NULL) + PtDestroyWidget(menu->submenu_id); + if (menu->id != NULL) + PtDestroyWidget(menu->id); menu->submenu_id = NULL; menu->id = NULL; @@ -2788,12 +2789,12 @@ { long flags, mask, fields; - if( menu->id == NULL ) + if (menu->id == NULL) return; - flags = PtWidgetFlags( menu->id ); - if( PtWidgetIsClass( menu->id, PtMenuButton ) && - PtWidgetIsClass( PtWidgetParent( menu->id ), PtMenu ) ) + flags = PtWidgetFlags(menu->id); + if (PtWidgetIsClass(menu->id, PtMenuButton) && + PtWidgetIsClass(PtWidgetParent(menu->id), PtMenu)) { fields = Pt_FALSE; mask = Pt_SELECTABLE | Pt_HIGHLIGHTED; @@ -2804,11 +2805,11 @@ mask = Pt_BLOCKED | Pt_GHOST; } - if( ! grey ) + if (! grey) fields = ~fields; - PtSetResource( menu->id, Pt_ARG_FLAGS, fields, - mask ); + PtSetResource(menu->id, Pt_ARG_FLAGS, fields, + mask); } void @@ -2829,8 +2830,8 @@ void gui_mch_show_popupmenu(vimmenu_T *menu) { - PtSetResource( menu->submenu_id, Pt_ARG_POS, &abs_mouse, 0 ); - PtRealizeWidget( menu->submenu_id ); + PtSetResource(menu->submenu_id, Pt_ARG_POS, &abs_mouse, 0); + PtRealizeWidget(menu->submenu_id); } void @@ -2841,14 +2842,14 @@ #endif -#if defined( FEAT_TOOLBAR ) || defined( PROTO ) +#if defined(FEAT_TOOLBAR) || defined(PROTO) void gui_mch_show_toolbar(int showit) { - if( showit ) - PtRealizeWidget( gui.vimToolBar ); + if (showit) + PtRealizeWidget(gui.vimToolBar); else - PtUnrealizeWidget( gui.vimToolBar ); + PtUnrealizeWidget(gui.vimToolBar); } #endif @@ -2869,36 +2870,36 @@ FontQueryInfo info; int_u style; - font_tag = alloc( MAX_FONT_TAG ); - if( font_tag != NULL ) + font_tag = alloc(MAX_FONT_TAG); + if (font_tag != NULL) { - if( PfGenerateFontName( font_name, font_flags, font_size, - font_tag ) != NULL ) + if (PfGenerateFontName(font_name, font_flags, font_size, + font_tag) != NULL) { /* Enforce some limits on the font used */ style = PHFONT_INFO_FIXED; - if( enforce & PF_STYLE_BOLD ) + if (enforce & PF_STYLE_BOLD) style |= PHFONT_INFO_BOLD; - if( enforce & PF_STYLE_ANTIALIAS ) + if (enforce & PF_STYLE_ANTIALIAS) style |= PHFONT_INFO_ALIAS; - if( enforce & PF_STYLE_ITALIC ) + if (enforce & PF_STYLE_ITALIC) style |= PHFONT_INFO_ITALIC; - PfQueryFontInfo( font_tag, &info ); + PfQueryFontInfo(font_tag, &info); - if( info.size == 0 ) + if (info.size == 0) font_size = 0; /* Make sure font size matches, and that the font style * at least has the bits we're checking for */ - if( font_size == info.size && - style == (info.style & style) ) - return( (GuiFont) font_tag ); + if (font_size == info.size && + style == (info.style & style)) + return (GuiFont)font_tag; } - vim_free( font_tag ); + vim_free(font_tag); } - return( NULL ); + return NULL; } /* @@ -2918,34 +2919,34 @@ char_u *vim_font, char_u **font_name, int_u *font_flags, - int_u *font_size ) + int_u *font_size) { char_u *mark; int_u name_len, size; - mark = vim_strchr( vim_font, ':' ); - if( mark == NULL ) - name_len = STRLEN( vim_font ); + mark = vim_strchr(vim_font, ':'); + if (mark == NULL) + name_len = STRLEN(vim_font); else - name_len = (int_u) ( mark - vim_font ); + name_len = (int_u) (mark - vim_font); - *font_name = vim_strnsave( vim_font, name_len ); - if( *font_name != NULL ) + *font_name = vim_strnsave(vim_font, name_len); + if (*font_name != NULL) { - if( mark != NULL ) + if (mark != NULL) { - while( *mark != NUL && *mark++ == ':') + while (*mark != NUL && *mark++ == ':') { - switch( tolower( *mark++ ) ) + switch (tolower(*mark++)) { case 'a': *font_flags |= PF_STYLE_ANTIALIAS; break; case 'b': *font_flags |= PF_STYLE_BOLD; break; case 'i': *font_flags |= PF_STYLE_ITALIC; break; case 's': - size = getdigits( &mark ); + size = getdigits(&mark); /* Restrict the size to some vague limits */ - if( size < 1 || size > 100 ) + if (size < 1 || size > 100) size = 8; *font_size = size; @@ -2956,9 +2957,9 @@ } } } - return( TRUE ); + return TRUE; } - return( FALSE ); + return FALSE; } int @@ -2972,60 +2973,60 @@ FontQueryInfo info; PhRect_t extent; - if( vim_font_name == NULL ) + if (vim_font_name == NULL) { /* Default font */ vim_font_name = "PC Terminal"; } - if( STRCMP( vim_font_name, "*" ) == 0 ) + if (STRCMP(vim_font_name, "*") == 0) { - font_tag = PtFontSelection( gui.vimWindow, NULL, NULL, - "pcterm12", -1, PHFONT_FIXED, NULL ); + font_tag = PtFontSelection(gui.vimWindow, NULL, NULL, + "pcterm12", -1, PHFONT_FIXED, NULL); - if( font_tag == NULL ) - return( FAIL ); + if (font_tag == NULL) + return FAIL; - gui_mch_free_font( gui.norm_font ); + gui_mch_free_font(gui.norm_font); gui.norm_font = font_tag; - PfQueryFontInfo( font_tag, &info ); - font_name = vim_strsave( info.font ); + PfQueryFontInfo(font_tag, &info); + font_name = vim_strsave(info.font); } else { - if( gui_ph_parse_font_name( vim_font_name, &font_name, &font_flags, - &font_size ) == FALSE ) - return( FAIL ); + if (gui_ph_parse_font_name(vim_font_name, &font_name, &font_flags, + &font_size) == FALSE) + return FAIL; - font_tag = gui_ph_get_font( font_name, font_flags, font_size, 0 ); - if( font_tag == NULL ) + font_tag = gui_ph_get_font(font_name, font_flags, font_size, 0); + if (font_tag == NULL) { - vim_free( font_name ); - return( FAIL ); + vim_free(font_name); + return FAIL; } - gui_mch_free_font( gui.norm_font ); + gui_mch_free_font(gui.norm_font); gui.norm_font = font_tag; } - gui_mch_free_font( gui.bold_font ); - gui.bold_font = gui_ph_get_font( font_name, font_flags | PF_STYLE_BOLD, - font_size, PF_STYLE_BOLD ); - - gui_mch_free_font( gui.ital_font ); - gui.ital_font = gui_ph_get_font( font_name, font_flags | PF_STYLE_ITALIC, - font_size, PF_STYLE_ITALIC ); + gui_mch_free_font(gui.bold_font); + gui.bold_font = gui_ph_get_font(font_name, font_flags | PF_STYLE_BOLD, + font_size, PF_STYLE_BOLD); + + gui_mch_free_font(gui.ital_font); + gui.ital_font = gui_ph_get_font(font_name, font_flags | PF_STYLE_ITALIC, + font_size, PF_STYLE_ITALIC); /* This extent was brought to you by the letter 'g' */ - PfExtentText( &extent, NULL, font_tag, "g", 1 ); + PfExtentText(&extent, NULL, font_tag, "g", 1); gui.char_width = extent.lr.x - extent.ul.x + 1; gui.char_height = (- extent.ul.y) + extent.lr.y + 1; gui.char_ascent = - extent.ul.y; - vim_free( font_name ); - return( OK ); + vim_free(font_name); + return OK; } /* @@ -3036,12 +3037,12 @@ { FontQueryInfo info; - PfQueryFontInfo( gui.norm_font, &info ); + PfQueryFontInfo(gui.norm_font, &info); gui.char_height = - info.ascender + info.descender + p_linespace; gui.char_ascent = - info.ascender + p_linespace / 2; - return( OK ); + return OK; } GuiFont @@ -3052,20 +3053,20 @@ int_u font_size = 12; int_u font_flags = 0; - if( gui_ph_parse_font_name( vim_font_name, &font_name, &font_flags, - &font_size ) != FALSE ) + if (gui_ph_parse_font_name(vim_font_name, &font_name, &font_flags, + &font_size) != FALSE) { - font_tag = gui_ph_get_font( font_name, font_flags, font_size, -1 ); - vim_free( font_name ); + font_tag = gui_ph_get_font(font_name, font_flags, font_size, -1); + vim_free(font_name); - if( font_tag != NULL ) - return( (GuiFont) font_tag ); + if (font_tag != NULL) + return (GuiFont)font_tag; } - if( report_error ) - EMSG2(e_font, vim_font_name ); + if (report_error) + EMSG2(e_font, vim_font_name); - return( FAIL ); + return FAIL; } #if defined(FEAT_EVAL) || defined(PROTO) @@ -3087,12 +3088,12 @@ void gui_mch_set_font(GuiFont font) { - PgSetFont( font ); + PgSetFont(font); } void gui_mch_free_font(GuiFont font) { - vim_free( font ); + vim_free(font); } diff -Naur vim73.orig/src/gui_riscos.c vim73/src/gui_riscos.c --- vim73.orig/src/gui_riscos.c 2010-05-15 11:04:09.000000000 +0000 +++ vim73/src/gui_riscos.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,3558 +0,0 @@ -/* vi:set ts=8 sts=4 sw=4: - * - * VIM - Vi IMproved by Bram Moolenaar - * - * Do ":help uganda" in Vim to read copying and usage conditions. - * Do ":help credits" in Vim to see a list of people who contributed. - * See README.txt for an overview of the Vim source code. - */ - -#include "vim.h" -#include - -/* - * gui_riscos.c - * - * Thomas Leonard - * Updated by Andy Wingate - */ - -extern int time_of_last_poll; - -int task_handle = 0; /* Zero means we are not yet a Wimp task */ -int child_handle = 0; /* Task handle of our child process (zero if none). */ -int *wimp_menu = (int *) -1; /* Pointer to a Wimp menu structure (or -1) */ -int save_window = -1; /* Save As window handle */ - -int *redraw_block = NULL; /* NULL means not in a redraw loop. */ -int ro_return_early = FALSE; /* Break out of gui_mch_wait_for_chars() */ - -int leaf_ref = 0; /* Wimp message number - send via Wimp$Scrap */ -char_u *leaf_name = NULL; /* Leaf name from DataSave */ - -int default_columns = 120; /* These values are used if the --rows and --columns */ -int default_rows = 32; /* options aren't used on startup. */ - -#define DRAG_FALSE 0 -#define DRAG_SELECTION 1 -#define DRAG_RESIZE_WINDOW 2 -int ro_dragging = DRAG_FALSE; -int drag_button; -int drag_modifiers; -int drag_x_offset; -int drag_y_offset; - -int nested_wimp = FALSE; /* Bool - can we use the new wimp? */ - -int changed_mode = FALSE; -int x_eigen_factor; -int y_eigen_factor; - -/* If ro_current_font is non-zero then use the outline font with that handle, - * otherwise, if zap_redraw is TRUE then use ZapRedraw, otherwise use the - * system font. - * - * If zap_redraw is TRUE then zap_file[] contains valid Zap font file - * pointers (or NULLs). - */ -int ro_current_font = 0; /* 0 is system font, or ZapRedraw */ -int font_x_offset = 0; /* Where to position each char in its box */ -int font_y_offset = 0; - -int zap_redraw = FALSE; -int double_height = FALSE; /* Plot each line twice? */ - -#define grgb(r,g,b) ((b<<16) + (g<<8) + (r)) -#define UNUSED_COLOUR (gui.back_pixel) - -#define RO_LOAD_CLIPBOARD -2 /* Internal handle for DataSave message. */ - -/* Changes by John Kortink, 22-23 July 1998 - * - * Stuff to make redraw a lot faster. Almost all of it is right here below, - * elsewhere changes are marked with 'JK230798'. Apart from a small change in - * 'gui.c' all changes are limited to this file, 'gui_riscos.c'. The change in - * 'gui.c' is to make Vim stop being 'smart' not redrawing characters that are - * 'already there' (i.e. from the previous line, by coincidence). This caused a - * lot more calls to the redraw code, which we want to avoid because a few nice - * big strings at a time is a lot faster than a truckload of small ones. ('Dear - * Bram ...'). - */ - -/* The ZapRedraw structure */ - -static struct -{ - int r_flags; - int r_minx; - int r_miny; - int r_maxx; - int r_maxy; - int r_screen; - int r_bpl; - int r_bpp; - int r_charw; - int r_charh; - char *r_caddr; - int r_cbpl; - int r_cbpc; - int r_linesp; - int r_data; - int r_scrollx; - int r_scrolly; - int *r_palette; - int r_for; - int r_bac; - char *r_workarea; - int r_magx; - int r_magy; - int r_xsize; - int r_ysize; - int r_mode; -} -zap_redraw_block; - -/* Other globals */ - -static int zap_redraw_initialised = FALSE; -static int zap_redraw_update_colours; -static int zap_redraw_colours[2]; -static int zap_redraw_palette[16]; - -/* Holds the current Zap font file(s). - * The font is recreated from this block on a mode change. - * When using zap, element ZAP_NORMAL is always valid, but - * the others can be NULL. - */ - -#define ZAP_NORMAL 0 -#define ZAP_BOLD 1 -#define ZAP_ITALIC 2 -#define ZAP_BITALIC 3 -#define ZAP_STYLES 4 - -/* Zap font file format data */ -static char *zap_file[ZAP_STYLES] = {NULL, NULL, NULL, NULL}; - -/* r_caddr format for current mode */ -static char *zap_caddr[ZAP_STYLES] = {NULL, NULL, NULL, NULL}; - -static void ro_remove_menu(int *menu); - -/* - * Initialise all the ZapRedraw stuff. - * Call this when changing font and after each mode change. - * zap_redraw_bitmap must contain a valid Zap font file (possibly - * created from the system font). - * - * Return FAIL to revert to system font (if we can't use ZapRedraw). - */ - int -ro_zap_redraw_initialise() -{ - int bytes_per_bitmap_char; - int first, last; - int i; - - /* Can't have initialisers for struct members :-(, ok, this way then ... */ - if (!zap_redraw_initialised) - { - zap_redraw_block.r_workarea = NULL; - zap_redraw_initialised = TRUE; - } - - /* We redraw in DSA mode */ - zap_redraw_block.r_flags = 0x0; - - /* Let ZapRedraw get the screen address for us */ - zap_redraw_block.r_screen = 0; - - /* Read the font width and height from the font file header. - * Assume that all styles are the same size. - * ZAP_NORMAL is always present. - */ - zap_redraw_block.r_charw = ((int *) zap_file[ZAP_NORMAL])[2]; - zap_redraw_block.r_charh = ((int *) zap_file[ZAP_NORMAL])[3]; - - /* We have no linespacing */ - zap_redraw_block.r_linesp = 0; - - /* Fix foreground = colour 1 */ - zap_redraw_block.r_for = 1; - - /* Fix background = colour 0 */ - zap_redraw_block.r_bac = 0; - - /* Colour mask buffer */ - zap_redraw_block.r_palette = zap_redraw_palette; - - /* Allocate local workspace (for the few calls following here) */ - if (zap_redraw_block.r_workarea != NULL) - free(zap_redraw_block.r_workarea); - zap_redraw_block.r_workarea = (char*) malloc(128); - if (!zap_redraw_block.r_workarea) - return FAIL; /* Out of memory */ - - /* Fill in VDU variables */ - if (xswi(ZapRedraw_ReadVduVars, 0, &zap_redraw_block) & v_flag) - return FAIL; /* Can't find ZapRedraw module - use VDU instead */ - - /* Determine cbpl and cbpc */ - swi(ZapRedraw_CachedCharSize, zap_redraw_block.r_bpp, 0, - zap_redraw_block.r_charw, zap_redraw_block.r_charh); - zap_redraw_block.r_cbpl = r2; - zap_redraw_block.r_cbpc = r3; - - /* Allocate general workspace (for the calls outside) */ - if (zap_redraw_block.r_workarea != NULL) - free(zap_redraw_block.r_workarea); - zap_redraw_block.r_workarea = (char*) malloc(128 + zap_redraw_block.r_cbpl); - if (!zap_redraw_block.r_workarea) - return FAIL; /* Out of memory */ - - /* Now convert the 1 bpp character data ready for the current mode */ - - bytes_per_bitmap_char = (zap_redraw_block.r_charw * zap_redraw_block.r_charh + 7) / 8; - - /* Convert the fonts from 1bpp to a format suitable for the - * current mode. - */ - for (i = 0; i < ZAP_STYLES; i++) - { - first = ((int *) zap_file[i])[4]; - last = ((int *) zap_file[i])[5]; - - if (last > 255) - last = 255; /* Don't convert cursors (overwrites memory!) */ - - /* Allocate the font cache */ - vim_free(zap_caddr[i]); - if (zap_file[i]) - zap_caddr[i] = (char*) malloc(zap_redraw_block.r_cbpc * 256); - else - zap_caddr[i] = NULL; /* No file for this style */ - - if (zap_caddr[i]) - { - zap_redraw_block.r_caddr = zap_caddr[i]; - - swi(ZapRedraw_ConvertBitmap, 0, &zap_redraw_block, - first, last, /* Range of characters to convert */ - zap_file[i] + 0x20 /* Addr of first char provided by font */ - - first * bytes_per_bitmap_char); - } - } - - if (!zap_caddr[ZAP_NORMAL]) - { - zap_redraw = FALSE; /* Out of memory */ - return FAIL; - } - - /* Next time we need them, we have to update the colour masks */ - zap_redraw_update_colours = TRUE; - - return OK; -} - -/* - * Redraw a string at OS coordinates (top-left, x inclusive, y exclusive). - * Graphics clip window is window[0..3] as in R1+28..40 of Wimp_RedrawWindow. - * Returns (possibly modified) flags. - */ - int -ro_zap_redraw_draw_string(x, y, string, length, flags, clip) - int x; - int y; - char *string; - int length; - int flags; /* DRAW_TRANSP, DRAW_BOLD, DRAW_UNDERL, DRAW_ITALIC */ - int *clip; -{ - char redraw_data[1024]; - int clip_minx; - int clip_miny; - int clip_maxx; - int clip_maxy; - int os_xshift = zap_redraw_block.r_magx; - int os_yshift = zap_redraw_block.r_magy; - - if (flags & DRAW_TRANSP) - return flags; /* We don't do transparent plotting yet. */ - - if (flags & DRAW_BOLD) - { - if (flags & DRAW_ITALIC && zap_caddr[ZAP_BITALIC]) - zap_redraw_block.r_caddr = zap_caddr[ZAP_BITALIC]; - else - zap_redraw_block.r_caddr = zap_caddr[ZAP_BOLD]; - } - else - { - if (flags & DRAW_ITALIC) - zap_redraw_block.r_caddr = zap_caddr[ZAP_ITALIC]; - else - zap_redraw_block.r_caddr = zap_caddr[ZAP_NORMAL]; - } - if (!zap_redraw_block.r_caddr) - { - zap_redraw_block.r_caddr = zap_caddr[ZAP_NORMAL]; - flags |= DRAW_UNDERL; /* Style missing - we can always underline */ - } - - /* Set the vertical scaling flag */ - if (double_height) - zap_redraw_block.r_flags = 1 << 1; - else - zap_redraw_block.r_flags = 0; - - /* Update the colour masks (if needed) */ - if (zap_redraw_update_colours) - { - swi(ZapRedraw_CreatePalette, 2, - &zap_redraw_block, - zap_redraw_colours, - zap_redraw_block.r_palette, 2); - zap_redraw_update_colours = FALSE; - } - - /* Target rectangle in ZapRedraw rectangle coordinates (pixels, Y-min/max reversed !!!) */ - zap_redraw_block.r_minx = x >> os_xshift; /* inclusive */ - zap_redraw_block.r_miny = zap_redraw_block.r_ysize - (y >> os_yshift); /* inclusive */ - zap_redraw_block.r_maxx = (x + length * gui.char_width) >> os_xshift; /* exclusive */ - zap_redraw_block.r_maxy = zap_redraw_block.r_ysize - ((y - gui.char_height) >> os_yshift); - /* exclusive */ - - /* Clip rectangle in ZapRedraw rectangle coordinates (pixels, Y-min/max reversed !!!) */ - clip_minx = clip[0] >> os_xshift; /* inclusive */ - clip_miny = zap_redraw_block.r_ysize - (clip[3] >> os_yshift); /* inclusive */ - clip_maxx = clip[2] >> os_xshift; /* exclusive */ - clip_maxy = zap_redraw_block.r_ysize - (clip[1] >> os_yshift); /* exclusive */ - - /* Clip target rectangle against the current graphics window */ - if (zap_redraw_block.r_minx < clip_minx) - { - zap_redraw_block.r_scrollx = clip_minx - zap_redraw_block.r_minx; - zap_redraw_block.r_minx = clip_minx; - } - else - zap_redraw_block.r_scrollx = 0; - if (zap_redraw_block.r_miny < clip_miny) - { - zap_redraw_block.r_scrolly = clip_miny - zap_redraw_block.r_miny; - zap_redraw_block.r_miny = clip_miny; - } - else - zap_redraw_block.r_scrolly = 0; - if (zap_redraw_block.r_maxx > clip_maxx) - zap_redraw_block.r_maxx = clip_maxx; - if (zap_redraw_block.r_maxy > clip_maxy) - zap_redraw_block.r_maxy = clip_maxy; - - /* Fill in the character data structure */ - if (length > (sizeof(redraw_data) - 2 * 4 - 2)) - length = sizeof(redraw_data) - 2 * 4 - 2; - ((int*) redraw_data)[0] = 2 * 4; - ((int*) redraw_data)[1] = 0; - strncpy(redraw_data + 2 * 4, string, length); - redraw_data[2 * 4 + length + 0] = '\0'; - redraw_data[2 * 4 + length + 1] = '\x2'; - zap_redraw_block.r_data = (int) redraw_data; - - /* Perform the draw */ - swi(ZapRedraw_RedrawArea, 0, &zap_redraw_block); - - return flags; -} - -/* - * Okay that was it from me, back to Thomas ... - */ - -/* - * Parse the GUI related command-line arguments. Any arguments used are - * deleted from argv, and *argc is decremented accordingly. This is called - * when vim is started, whether or not the GUI has been started. - */ - void -gui_mch_prepare(int *argc, char **argv) -{ - int arg = 1; - - while (arg < *argc - 1) - { - if (strcmp(argv[arg], "--rows") == 0 || strcmp(argv[arg], "--columns") == 0) - { - int value; - - value = atoi(argv[arg + 1]); - - if (argv[arg][2] == 'r') - default_rows = value; - else - default_columns = value; - - /* Delete argument from argv[]. (hope this is read/write!) */ - - *argc -= 2; - if (*argc > arg) - mch_memmove(&argv[arg], &argv[arg + 2], (*argc - arg) - * sizeof(char *)); - } - else - arg++; - } -} - -/* Fatal error on initialisation - report it and die. */ - void -ro_die(error) - char_u *error; /* RISC OS error block */ -{ - swi(Wimp_ReportError, error, 5, "GVim"); - exit(EXIT_FAILURE); -} - -/* Find the sizes of the window tools: - * - * Create a test window. - * Find inner and outer sizes. - * Find the difference. - * Delete window. - * - * While we're here, find the eigen values too. - */ - void -ro_measure_tools() -{ - int block[10]; - int vdu[] = { 4, 5, -1}; - int test_window[] = - { - -100, -100, /* Visible area : min X,Y */ - -50, -50, /* max X,Y */ - 0, 0, /* Scroll offsets */ - -1, /* Window in front */ - 0xd0800150, /* Window flags */ - 0xff070207, /* Colours */ - 0x000c0103, /* More colours */ - 0, -0x4000, /* Workarea extent */ - 0x4000, 0, /* max X,Y */ - 0x00000000, /* No title */ - 0 << 12, /* No workarea button type */ - 1, /* Wimp sprite area */ - 0x00010001, /* Minimum width, height */ - 0, 0, 0, /* Title data (none) */ - 0 /* No icons */ - }; - int inner_max_x, inner_min_y; - - swi(Wimp_CreateWindow, 0, test_window); - - block[0] = r0; - /* Open the window (and read state). - * GetWindowOutline needs it too if the wimp isn't nested. - */ - swi(Wimp_OpenWindow, 0, block); - inner_max_x = block[3]; - inner_min_y = block[2]; - - swi(Wimp_GetWindowOutline, 0, block); - - gui.scrollbar_width = block[3] - inner_max_x; - gui.scrollbar_height = inner_min_y - block[2]; - - swi(Wimp_DeleteWindow, 0, block); - - /* Read the size of one pixel. */ - swi(OS_ReadVduVariables, vdu, vdu); - x_eigen_factor = vdu[0]; - y_eigen_factor = vdu[1]; -} - -/* Load a template from the current templates file. - * Create the window and return its handle. - */ - int -ro_load_template(str_name, title, title_size) - char_u *str_name; /* Identifier of window in file (max 12 chars) */ - char_u **title; /* If not NULL then return pointer to title here */ - int *title_size; /* If not NULL then return the title length here */ -{ - int *window; - char *data; - int name[4]; - - strcpy( (char *) name, str_name); - - /* Find how big we must make the buffers */ - - if (xswi(Wimp_LoadTemplate, 0, 0, 0, 0, -1, name, 0) & v_flag) - ro_die( (char *) r0); - - window = malloc(r1); /* Don't print text messages from alloc() */ - data = malloc(r2); - if (window == NULL || data == NULL) - ro_die("\0\0\0\0Out of memory - Can't load templates"); - - /* Load the template into the buffers */ - - swi(Wimp_LoadTemplate, 0, - window, /* Temp block */ - data, /* Icon data */ - data + r2 + 1, /* End of icon data */ - -1, /* No fonts */ - name, 0); /* First match */ - if (r6 == 0) - ro_die("\0\0\0\0Can't find window in Templates file"); - - /* Create the window */ - - if (xswi(Wimp_CreateWindow, 0, window) & v_flag) - ro_die( (char *) r0); - - if (title) - *title = (char_u *) window[18]; - if (title_size) - *title_size = window[20]; - - free(window); /* Free temp block */ - return r0; /* Return the window handle */ -} - -/* - * Check if the GUI can be started. Called before gvimrc is sourced. - * Return OK or FAIL. - */ - int -gui_mch_init_check() -{ - return OK; /* TODO: GUI can always be started? */ -} - -/* - * Initialise the RISC OS GUI. - * Create all the windows. - * Returns OK for success, FAIL when the GUI can't be started. - */ - int -gui_mch_init() -{ - int messages[] = { - 1, 2, 3, 4, /* DataSave, DataSaveAck, DataLoad, DataLoadAck */ - 8, /* PreQuit */ - 0xf, /* ClaimEntity (for clipboard) */ - 0x10, /* DataRequest (for clipboard) */ - 0x400c1, /* Mode change */ - 0x400c3, /* TaskCloseDown */ - 0x400c9, /* MenusDeleted */ - 0x808c1, /* TW_Output */ - 0x808c2, /* TW_Ego */ - 0x808c3, /* TW_Morio */ - 0x808c4, /* TW_Morite */ - 0}; /* End-of-list. */ - - - /* There may have been some errors reported in the - * command window before we get here. Wait if so. - */ - swi(Wimp_ReadSysInfo, 3); - if (r0 == 0) - swi(Wimp_CommandWindow, 0); /* Window opened - close with prompt */ - - if (xswi(Wimp_Initialise, 310, 0x4b534154, "GVim", messages) & v_flag) - return FAIL; - nested_wimp = r0 >= 397; - task_handle = r1; - - /* Load the templates. */ - - if (xswi(Wimp_OpenTemplate, 0, "Vim:Templates") & v_flag) - ro_die( (char *) r0); - - gui.window_handle = ro_load_template("editor", - &gui.window_title, - &gui.window_title_size); - - save_window = ro_load_template("save", NULL, NULL); - - swi(Wimp_CloseTemplate); - - /* Set default foreground and background colours. */ - - gui.norm_pixel = gui.def_norm_pixel; - gui.back_pixel = gui.def_back_pixel; - - /* Get the colours from the "Normal" and "Menu" group (set in syntax.c or - * in a vimrc file) */ - - set_normal_colors(); - - /* - * Check that none of the colors are the same as the background color - */ - - gui_check_colors(); - - /* Get the colours for the highlight groups (gui_check_colors() might have - * changed them) */ - - highlight_gui_started(); /* re-init colours and fonts */ - - /* Set geometry based on values read on initialisation. */ - - gui.num_cols = Columns = default_columns; - gui.num_rows = Rows = default_rows; - - /* Get some information about our environment. */ - - ro_measure_tools(); - - return OK; -} - -/* - * Called when the foreground or background colour has been changed. - */ - void -gui_mch_new_colors() -{ -} - -/* - * Open the GUI window which was created by a call to gui_mch_init(). - */ - int -gui_mch_open(void) -{ - int block[10]; - - block[0] = gui.window_handle; - swi(Wimp_GetWindowState, 0, block); - block[7] = -1; /* Open at the top of the stack */ - swi(Wimp_OpenWindow, 0, block); - - /* Give the new window the input focus */ - swi(Wimp_SetCaretPosition, gui.window_handle, -1, 0, 0, -1, -1); - - if (gui_win_x != -1 && gui_win_y != -1) - gui_mch_set_winpos(gui_win_x, gui_win_y); - - return OK; -} - - void -gui_mch_exit(int rc) -{ - int block[64]; - - /* Close window. Stops us from getting troublesome events - * if we take a while to die. - */ - block[0] = gui.window_handle; - swi(Wimp_CloseWindow, 0, block); - - if (child_handle) - { - /* We still have a sub-task running - kill it */ - block[0] = 20; - block[3] = 0; - block[4] = 0; /* Quit */ - if ((xswi(Wimp_SendMessage, 17, block, child_handle) & v_flag) == 0) - { - /* Idle until child dies. */ - while (child_handle) - { - process_event(wimp_poll(1, block), block); - } - } - } - - exit(rc); -} - -/* - * Get the position of the top left corner of the window. - */ - int -gui_mch_get_winpos(int *x, int *y) -{ - /* TODO */ - return FAIL; -} - -/* - * Set the position of the top left corner of the window to the given - * coordinates. - */ - void -gui_mch_set_winpos(int x, int y) -{ - /* TODO */ -} - - void -gui_mch_set_shellsize(width, height, min_width, min_height, base_width, base_height, direction) - int width; /* In OS units */ - int height; - int min_width; /* Smallest permissible window size (ignored) */ - int min_height; - int base_width; /* Space for scroll bars, etc */ - int base_height; - int direction; -{ - int s_width, s_height; - int block[] = { - gui.window_handle, - 0, - -height + 1, - width, - 1}; - - gui_mch_get_screen_dimensions(&s_width, &s_height); - s_width -= base_width; - s_height -= base_height; /* Underestimate - ignores titlebar */ - - swi(Wimp_GetWindowState, 0, block); - block[3] = block[1] + width; - block[2] = block[4] - height; - if (block[3] > s_width) - { - block[3] = s_width; - block[1] = block[3] - width; - } - if (block[2] < gui.scrollbar_height) - { - block[2] = gui.scrollbar_height; - block[4] = block[2] + height; - } - swi(Wimp_OpenWindow, 0, block); - swi(Wimp_ForceRedraw, gui.window_handle, 0, -height, width, 0); -} - - void -gui_mch_get_screen_dimensions(int *screen_w, int *screen_h) -{ - int block[] = {4, 5, 11, 12, -1}; - - swi(OS_ReadVduVariables, block, block); - *screen_w = (block[2] + 1) << block[0]; - *screen_h = (block[3] + 1) << block[1]; -} - -/* Take a font name with options and return a font handle, or - * zero for failure. - * Replace extension with 'Bold' or 'Italic' depending on modifiers. - */ - int -ro_get_font(fullname, weight) - char_u *fullname; - int weight; /* Initial weights: - * BIT MEANING - * 0 bold - * 1 italic - */ -{ - char_u *arg; - char_u font[41]; - int width = -1; - int height = -1; - int name_len; - int i; - char_u c; - - for (i = 0; i < 39;) - { - c = fullname[i]; - if (c == ':' || c == NUL || c == '.') - break; - font[i++] = c; - } - - /* find the first modifier, NULL if none */ - arg = strchr(fullname + i, ':'); - - while (arg) - { - switch (*++arg) - { - case 'h': - height = strtol(arg + 1, (char **) &arg, 10); - break; - case 'w': - width = strtol(arg + 1, (char **) &arg, 10); - break; - case 'b': - weight |= 1; - break; - case 'i': - weight |= 2; - break; - default: - return 0; - } - arg = strchr(arg, ':'); - } - - if ((weight & 1) && i < 35) - { - /* Bold goes instead of given suffix */ - strncpy(font + i, ".Bold", 5); - i += 5; - } - else - { - /* Copy rest of name unless we are using Bold */ - while (i < 39) - { - c = fullname[i]; - if (c == ':' || c == NUL) - break; - font[i++] = c; - } - } - if ((weight & 2) && i < 32) - { - strncpy(font + i, ".Oblique", 8); - i += 8; - } - - font[i] = 0; - - if (height < 1 && width < 1) - height = width = 10; /* Default to 10pt */ - else if (height < 1) - height = width; - else if (width < 1) - width = height; - - if (xswi(Font_FindFont, 0, font, width << 4, height << 4, 0, 0) & v_flag) - return NOFONT; /* Can't find font */ - - return r0; -} - -/* Load a file into allocated memory and check it is valid. - * Return a pointer to the allocated block on success. - */ - char * -zap_load_file(name, style) - char_u *name; /* Name of directory containing styles */ - char_u *style; /* Name of style within directory */ -{ - char_u fname[256]; - char_u *file; - - if (strlen(name) + strlen(style) > 254) - return NULL; /* Names too long */ - - sprintf(fname, "%s.%s", name, style); - - /* Load the named font in 1bpp format. */ - if (xswi(OS_File, 13, fname, 0, 0, "VimFonts:") & v_flag || r0 != 1) - return NULL; /* Error reading file info, or not a file */ - - /* Allocate enough memory to load the whole file */ - file = (char *) alloc(r4); - if (!file) - return NULL; /* Out of memory */ - - if (xswi(OS_File, 12, fname, file, 0, "VimFonts:") & v_flag) - return NULL; /* Unable to load file */ - - if (strncmp(file, "ZapFont\015", 8) == 0) - return file; /* Loaded OK! */ - - vim_free(file); - return NULL; /* Not a valid font file */ -} - -/* Load and convert the named font. - * If name is NULL or a null string then convert the system font. - * Return OK on success; FAIL and we revert to using the VDU drivers. - * - * 'name' is the name of a directory. - * Tries to load 'name.0', 'name.B', 'name.I' and 'name.IB'. - */ - int -zap_load_font(name) - char_u *name; -{ - int i; - - /* Free the existing font files, if any */ - for (i = 0; i < ZAP_STYLES; i++) - { - vim_free(zap_file[i]); - zap_file[i] = NULL; - } - - if (name && *name == '!') - { - name++; - double_height = TRUE; - } - else - double_height = FALSE; - - if (name && *name) - { - zap_file[ZAP_NORMAL] = zap_load_file(name, "0"); - if (!zap_file[ZAP_NORMAL]) - return FAIL; /* Can't load the 'normal' style - error */ - - zap_file[ZAP_BOLD] = zap_load_file(name, "B"); - zap_file[ZAP_ITALIC] = zap_load_file(name, "I"); - zap_file[ZAP_BITALIC] = zap_load_file(name, "IB"); - } - else - { - int *header; - char workarea[16]; - char *old_wa; - - /* Allocate memory for system font (8 x 8 x 256 bits, plus header) */ - header = (int *) alloc(0x20 + 8 * 256); - if (header == NULL) - return FAIL; - zap_file[ZAP_NORMAL] = (char *) header; - - /* Store details about the system font */ - header[2] = 8; /* Width */ - header[3] = 8; /* Height */ - header[4] = 0; /* First char */ - header[5] = 255; /* Last char */ - header[6] = header[7] = 0; /* Reserved */ - - /* Get system font bitmap */ - old_wa = zap_redraw_block.r_workarea; - zap_redraw_block.r_workarea = workarea; - swi(ZapRedraw_ReadSystemChars, zap_file[ZAP_NORMAL] + 0x20, &zap_redraw_block); - zap_redraw_block.r_workarea = old_wa; - } - - return ro_zap_redraw_initialise(); -} - -/* - * Initialise vim to use the font with the given name. - * Return FAIL if the font could not be loaded, OK otherwise. - */ - int -gui_mch_init_font(char_u *font_name, int fontset) -{ - int new_handle = 0; /* Use the system font by default */ - - if (font_name[0] == '!') - { - /* Select a ZapRedraw font */ - if (zap_load_font(font_name + 1)) - zap_redraw = TRUE; - else - { - EMSG2(_("E610: Can't load Zap font '%s'"), font_name); - font_name = "System"; /* Error - use system font */ - zap_redraw = FALSE; - } - } - else - { - zap_redraw = FALSE; - - if (font_name) - { - /* Extract any extra details about the font */ - new_handle = ro_get_font(font_name, 0); - if (!new_handle) - return FAIL; - } - else - font_name = "System"; - } - - /* Free the previous font, if any */ - gui_mch_free_font(gui.norm_font); - gui.norm_font = new_handle; - gui.char_ascent = 0; - - if (new_handle) - { - /* Read details about the chosen font */ - swi(Font_ReadInfo, new_handle); - - gui.char_width = r3 - r1; - gui.char_height = r4 - r2; - - font_x_offset = -r1; /* Where to position each char in its box */ - font_y_offset = -r4; - - /* Try to load other fonts for bold, italic, and bold-italic */ - gui_mch_free_font(gui.bold_font); - gui.bold_font = ro_get_font(font_name, 1); - gui_mch_free_font(gui.ital_font); - gui.ital_font = ro_get_font(font_name, 2); - gui_mch_free_font(gui.boldital_font); - gui.boldital_font = ro_get_font(font_name, 3); - } - else - { - /* Use the system font or ZapRedraw. */ - if (zap_redraw) - { - gui.char_width = zap_redraw_block.r_charw << zap_redraw_block.r_magx; - gui.char_height = zap_redraw_block.r_charh << zap_redraw_block.r_magy; - if (double_height) - gui.char_height <<= 1; - } - else - { - gui.char_width = 16; - gui.char_height = 32; - } - - gui_mch_free_font(gui.bold_font); - gui.bold_font = 0; - gui_mch_free_font(gui.ital_font); - gui.ital_font = 0; - gui_mch_free_font(gui.boldital_font); - gui.boldital_font = 0; - } - hl_set_font_name(font_name); - - must_redraw = CLEAR; - return OK; -} - -/* - * Adjust gui.char_height (after 'linespace' was changed). - */ - int -gui_mch_adjust_charheight() -{ - return FAIL; -} - -/* - * Get a font structure for highlighting. - */ - GuiFont -gui_mch_get_font(name, giveErrorIfMissing) - char_u *name; - int giveErrorIfMissing; -{ - int handle; - - if (!name) - return NOFONT; /* System font if no name */ - - handle = ro_get_font(name, 0); - if (!handle) - { - if (giveErrorIfMissing) - EMSG2(_("E611: Can't use font %s"), name); - return NOFONT; - } - - return handle; -} - -#if defined(FEAT_EVAL) || defined(PROTO) -/* - * Return the name of font "font" in allocated memory. - * Don't know how to get the actual name, thus use the provided name. - */ - char_u * -gui_mch_get_fontname(font, name) - GuiFont font; - char_u *name; -{ - if (name == NULL) - return NULL; - return vim_strsave(name); -} -#endif - -/* - * Set the current text font. - */ - void -gui_mch_set_font(GuiFont font) -{ - ro_current_font = font; - - if (font) - { - /* Not the system font or ZapRedraw font - select it */ - swi(Font_SetFont, font); - } -} - -/* - * If a font is not going to be used, free its structure. - */ - void -gui_mch_free_font(GuiFont font) -{ - if (font) - swi(Font_LoseFont, font); -} - -/* - * Return the Pixel value (colour) for the given colour name. - * Return INVALCOLOR for error. - * NB: I've changed Green for now, since it looked really sick - */ - guicolor_T -gui_mch_get_color(char_u *name) -{ - int i; - struct colour - { - char_u *name; - guicolor_T value; - } colours[] = - { - { "Red", grgb(255, 0, 0) }, - { "LightRed", grgb(255, 0, 0) }, - { "DarkRed", grgb(139, 0, 0) }, - - { "Green", grgb(50, 200, 50) }, - { "LightGreen", grgb(144, 238, 144) }, - { "DarkGreen", grgb(0, 100, 0) }, - { "SeaGreen", grgb(46, 139, 87) }, - - { "Blue", grgb(0, 0, 255) }, - { "LightBlue", grgb(173, 216, 230) }, - { "DarkBlue", grgb(0, 0, 139) }, - { "SlateBlue", grgb(160, 90, 205) }, - - { "Cyan", grgb(0, 255, 255) }, - { "LightCyan", grgb(224, 255, 255) }, - { "DarkCyan", grgb(0, 139, 139) }, - - { "Magenta", grgb(255, 0, 255) }, - { "LightMagenta", grgb(255, 224, 255) }, - { "DarkMagenta", grgb(139, 0, 139) }, - - { "Yellow", grgb(255, 255, 0) }, - { "LightYellow", grgb(255, 255, 224) }, - { "DarkYellow", grgb(139, 139, 0) }, - { "Brown", grgb(165, 42, 42) }, - - { "Gray", grgb(190, 190, 190) }, - { "Grey", grgb(190, 190, 190) }, - { "LightGray", grgb(211, 211, 211) }, - { "LightGrey", grgb(211, 211, 211) }, - { "DarkGray", grgb(169, 169, 169) }, - { "DarkGrey", grgb(169, 169, 169) }, - { "Gray10", grgb(26, 26, 26) }, - { "Grey10", grgb(26, 26, 26) }, - { "Gray20", grgb(51, 51, 51) }, - { "Grey20", grgb(51, 51, 51) }, - { "Gray30", grgb(77, 77, 77) }, - { "Grey30", grgb(77, 77, 77) }, - { "Gray40", grgb(102, 102, 102) }, - { "Grey40", grgb(102, 102, 102) }, - { "Gray50", grgb(127, 127, 127) }, - { "Grey50", grgb(127, 127, 127) }, - { "Gray60", grgb(153, 153, 153) }, - { "Grey60", grgb(153, 153, 153) }, - { "Gray70", grgb(179, 179, 179) }, - { "Grey70", grgb(179, 179, 179) }, - { "Gray80", grgb(204, 204, 204) }, - { "Grey80", grgb(204, 204, 204) }, - { "Gray90", grgb(229, 229, 229) }, - { "Grey90", grgb(229, 229, 229) }, - - { "Black", grgb(0, 0, 0) }, - { "White", grgb(255, 255, 255) }, - - { "Orange", grgb(255, 165, 0) }, - { "Purple", grgb(160, 32, 240) }, - { "Violet", grgb(238, 130, 238) }, - {NULL, 0} - }; - - if (name[0] == '#') - { - char *end; - int c; - - c = strtol(name + 1, &end, 16); - return (guicolor_T) ((c >> 16) & 0xff) | (c & 0xff00) | ((c & 0xff) << 16); - } - - for (i = 0; colours[i].name != NULL; i++) - { - if (STRICMP(name, colours[i].name) == 0) - return colours[i].value; - } - if (strnicmp(name, "grey", 4) == 0 || strnicmp(name, "gray", 4) == 0) - { - int level = (255 * atoi(name + 4)) / 100; - return (guicolor_T) grgb(level, level, level); - } - return INVALCOLOR; -} - -/* - * Set the current text colours. - * If we are using fonts then set the antialiasing colours too. - */ - void -gui_mch_set_colors(guicolor_T fg, guicolor_T bg) -{ - zap_redraw_colours[0] = bg << 8; /* JK230798, register new background colour */ - zap_redraw_colours[1] = fg << 8; /* JK230798, register new foreground colour */ - zap_redraw_update_colours = TRUE; /* JK230798, need update of colour masks */ - - swi(ColourTrans_ReturnGCOL, fg << 8); - gui.fg_colour = r0; - swi(ColourTrans_ReturnGCOL, bg << 8); - gui.bg_colour = r0; - - if (ro_current_font) - swi(ColourTrans_SetFontColours, 0, bg << 8, fg << 8, 14); -} - - void -ro_draw_string(x, y, s, len, flags, clip) - int x; /* Top-left coord to plot at (x incl, y excl) */ - int y; /* (screen coords) */ - char_u *s; /* String to plot */ - int len; /* Length of string */ - int flags; /* DRAW_TRANSP, DRAW_BOLD, DRAW_UNDERL */ - int* clip; /* JK230798, added clip window */ -{ - if (ro_current_font) - { - int fx; - int flen = len; /* Preserve for underline */ - - /* Use the Font manager to paint the string. - * Must do one char at a time to get monospacing. - */ - - if (flags & DRAW_ITALIC && !gui.ital_font) - flags |= DRAW_UNDERL; /* No italic - underline instead */ - - if ((flags & DRAW_TRANSP) == 0) - { - swi(ColourTrans_SetColour, gui.bg_colour, 0, 0, 0, 0); - swi(OS_Plot, 4, x, y - gui.char_height); - swi(OS_Plot, 96 + 5, x + len * gui.char_width - 1, y - 1); - } - - fx = x + font_x_offset; - while (flen--) - { - swi(Font_Paint, 0, s++, 0x90, fx, y + font_y_offset, 0, 0, 1); - fx += gui.char_width; - } - } - else - { - if (zap_redraw) - { - /* Using fast Zap redraw. */ - flags = ro_zap_redraw_draw_string(x, y, s, len, flags, clip); - } - else - { - /* Using the system font */ - if (flags & DRAW_ITALIC) - flags |= DRAW_UNDERL; - - if ((flags & DRAW_TRANSP) == 0) - { - swi(ColourTrans_SetColour, gui.bg_colour, 0, 0, 0, 0); - swi(OS_Plot, 4, x, y - gui.char_height); - swi(OS_Plot, 96 + 5, x + len * gui.char_width - 1, y - 1); - } - swi(OS_Plot, 4, /* Move the drawing cursor */ - x, - y - 1); - swi(ColourTrans_SetColour, gui.fg_colour, 0, 0, 0, 0); - swi(OS_WriteN, s, len); - - if (flags & DRAW_BOLD) - { - swi(OS_Plot, 4, x + (1 << x_eigen_factor), y - 1); - swi(OS_WriteN, s, len); - } - } - } - - if (flags & DRAW_UNDERL) - { - if (ro_current_font || zap_redraw) - swi(ColourTrans_SetColour, gui.fg_colour, 0, 0, 0, 0); - /* Underlined is the same with all plotting methods */ - swi(OS_Plot, 4, x, y - gui.char_height); - swi(OS_Plot, 1, gui.char_width * len, 0); - } -} - - void -gui_mch_draw_string(int row, int col, char_u *s, int len, int flags) -{ - int x, y; /* Workarea x,y */ - x = col * gui.char_width; - y = -row * gui.char_height; - - if (redraw_block) - { - ro_draw_string(x + redraw_block[1], y + redraw_block[4], - s, len, flags, &redraw_block[7]); /* JK230798, added clip window */ - } - else - { - int block[44]; - block[0] = gui.window_handle; - block[1] = x; - block[2] = y - gui.char_height; - block[3] = (col + len) * gui.char_width; - block[4] = y; - swi(Wimp_UpdateWindow, 0, block); - while (r0) - { - ro_draw_string(x + block[1], y + block[4], - s, len, flags, &block[7]); /* JK230798, added clip window */ - swi(Wimp_GetRectangle, 0, block); - } - } -} - -/* - * Return OK if the key with the termcap name "name" is supported. - */ - int -gui_mch_haskey(char_u *name) -{ - return FAIL; -} - - void -gui_mch_beep(void) -{ - swi(OS_WriteI + 7); -} - -/* - * Visual bell. - */ - void -gui_mch_flash(int msec) -{ - /* TODO */ -} - - -/* - * Plot a solid rectangle using the given plot action and colour. - * Coordinates are inclusive and window-relative. - */ - void -plot_rectangle(plot, colour, minx, miny, maxx, maxy) - int plot; /* OS_Plot action */ - int colour; - int minx; - int miny; - int maxx; - int maxy; -{ - if (redraw_block) - { - swi(ColourTrans_SetColour, colour, 0, 0, 0, 0); - swi(OS_Plot, 4, minx + redraw_block[1], miny + redraw_block[4]); - swi(OS_Plot, plot, maxx + redraw_block[1], maxy + redraw_block[4]); - } - else - { - int block[44]; - block[0] = gui.window_handle; - block[1] = minx; - block[2] = miny; - block[3] = maxx + 1; - block[4] = maxy + 1; - swi(Wimp_UpdateWindow, 0, block); - while (r0) - { - swi(ColourTrans_SetColour, colour, 0, 0, 0, 0); - swi(OS_Plot, 4, minx + block[1], miny + block[4]); - swi(OS_Plot, plot, maxx + block[1], maxy + block[4]); - swi(Wimp_GetRectangle, 0, block); - } - } -} - -/* - * Invert a rectangle from row r, column c, for nr rows and nc columns. - */ - void -gui_mch_invert_rectangle(int r, int c, int nr, int nc) -{ - plot_rectangle(96 + 6, 0, FILL_X(c), -FILL_Y(r + nr), FILL_X(c + nc), -FILL_Y(r)); -} - -/* - * Iconify the GUI window. - */ - void -gui_mch_iconify(void) -{ -} - -#if defined(FEAT_EVAL) || defined(PROTO) -/* - * Bring the Vim window to the foreground. - */ - void -gui_mch_set_foreground() -{ - /* TODO */ -} -#endif - -/* Draw a hollow rectangle relative to the current - * graphics cursor position, with the given width - * and height. Start position is top-left. - */ - void -draw_hollow(w, h) - int w; - int h; -{ - swi(OS_Plot, 1, w - 1, 0); - swi(OS_Plot, 1, 0, 1 - h); - swi(OS_Plot, 1, 1 - w, 0); - swi(OS_Plot, 1, 0, h - 1); -} - -/* - * Draw a cursor without focus. - */ - void -gui_mch_draw_hollow_cursor(guicolor_T colour) -{ - int x = FILL_X(gui.cursor_col); /* Window relative, top-left */ - int y = -FILL_Y(gui.cursor_row); - if (redraw_block == NULL) - { - int block[11]; - - block[0] = gui.window_handle; - block[1] = x; - block[2] = y - gui.char_height; - block[3] = x + gui.char_width; - block[4] = y; - swi(Wimp_UpdateWindow, 0, block); - while (r0) - { - swi(ColourTrans_SetGCOL, colour << 8, 0, 0, 0, 0); - - swi(OS_Plot, 4, x + block[1], y + block[4] - 1); - draw_hollow(gui.char_width, gui.char_height); - - swi(Wimp_GetRectangle, 0, block); - } - } - else - { - swi(ColourTrans_SetGCOL, colour << 8, 0, 0, 0, 0); - - swi(OS_Plot, 4, x + redraw_block[1], y + redraw_block[4] - 1); - draw_hollow(gui.char_width, gui.char_height); - } -} - -/* - * Draw part of a cursor, "w" pixels wide, and "h" pixels high, using - * color "color". - */ - void -gui_mch_draw_part_cursor(w, h, colour) - int w; - int h; - guicolor_T colour; -{ - int x = FILL_X(gui.cursor_col); - int y = -FILL_Y(gui.cursor_row); - swi(ColourTrans_ReturnGCOL, colour << 8); - plot_rectangle(96 + 5, r0, x, y - h, x + w - 1, y - 1); -} - -/* - * Catch up with any queued events. This may put keyboard input into the - * input buffer, call resize call-backs, trigger timers etc. - * If there is nothing in the event queue(& no timers pending), then we return - * immediately (well, after a Wimp_Poll). - */ - void -gui_mch_update(void) -{ - int block[64]; - int reason; - - swi(OS_ReadMonotonicTime); - if ((r0 - time_of_last_poll) < 50) - return; /* Don't return too often */ - - reason = wimp_poll(0, block); - if (reason) - process_event(reason, block); - ro_return_early = FALSE; /* We're returning anyway. */ -} - - void -redraw_window(block) - int *block; -{ - int x, y; /* Vim workarea coords */ - int width, height; - int blank_col; - - swi(ColourTrans_ReturnGCOL, UNUSED_COLOUR << 8, 0, 0, 1<<7, 0); - blank_col = r0; - - swi(Wimp_RedrawWindow, 0, block); - redraw_block = block; - while (r0) - { - x = block[7] - block[1]; - y = block[4] - block[10]; - width = block[9] - block[7]; - height = block[10] - block[8]; - - if (height + y > Rows * gui.char_height) - { - /* Blank everything off the bottom. */ - plot_rectangle(96 + 5, blank_col, - 0, block[8] - block[4], - block[9] - block[1], -FILL_Y(Rows) - 1); - height = Rows * gui.char_height; - } - if (width + x> Columns * gui.char_width) - { - /* Blank everything off to the right. */ - plot_rectangle(96 + 5, blank_col, - FILL_X(Columns), block[8] - block[4], - block[9] - block[1], 0); - width = Columns * gui.char_width; - } - gui_redraw(x , y, width, height); - swi(Wimp_GetRectangle, 0, block); - } - redraw_block = NULL; -} - -/* Check if we have modified data. - * If we do then ack the message to stop the shutdown. - * Otherwise, ignore the message. - */ - void -ro_prequit(block) - int *block; -{ - if (!ro_ok_to_quit()) - { - /* Not OK to quit - stop shutdown */ - block[3] = block[2]; - swi(Wimp_SendMessage, 19, block, block[1]); - } - /* Do nothing. We may get a Message_Quit later. */ -} - -/* If there is unsaved data then ask the user if they mind losing it. - * Return TRUE if we can quit without saving, FALSE to halt the - * shutdown. - */ - int -ro_ok_to_quit() -{ - int old_confirm = cmdmod.confirm; - - cmdmod.confirm = FALSE; /* Use our own, single tasking, box */ - - if (check_changed_any(FALSE)) - { - swi(Wimp_ReportError, - "\0\0\0\0Vim contains unsaved data - quit anyway?", - 0x17, - "Vim"); - cmdmod.confirm = old_confirm; - if (r1 != 1) - return FALSE; - } - cmdmod.confirm = old_confirm; - return TRUE; -} - -/* Quit without checking for unsaved data. */ - void -ro_quit() -{ - exiting = TRUE; - getout(0); - - exiting = FALSE; /* probably can't get here */ - setcursor(); /* position cursor */ - out_flush(); -} - -/* Insent the given vim special code into the input buffer */ - void -ro_press(a, b, modifier) - char a; - char b; - int modifier; /* % 0000 0000 */ -{ - char_u buf[6]; - int vim_mod; - int key; - - - /* Convert RISC OS modifier to Vim modifier. */ - vim_mod = ((modifier & 0x10) ? MOD_MASK_SHIFT : 0) - | ((modifier & 0x20) ? MOD_MASK_CTRL : 0); - key = simplify_key(TERMCAP2KEY(a, b), &vim_mod); - - buf[3] = CSI; - buf[4] = KEY2TERMCAP0(key); - buf[5] = KEY2TERMCAP1(key); - if (vim_mod) - { - buf[0] = CSI; - buf[1] = KS_MODIFIER; - buf[2] = vim_mod; - add_to_input_buf(buf, 6); - } - else - add_to_input_buf(buf + 3, 3); -} - -/* Take a wimp key code and insert the vim equivalent - * into vim's input buffer. - * CTRL-C also sets got_int. - */ - void -ro_insert_key(code) - char_u *code; /* Wimp_ProcessKey code (4 bytes) */ -{ - char a = code[0]; - char b = code[1]; - int base, modifier; - - if (a == 3 && ctrl_c_interrupts) - got_int = TRUE; - - /* Is it a normal key? */ - if (a > 31 && a < 127) - { - add_to_input_buf(code, 1); - return; - } - - /* We should pass any unrecognised keys on, but - * for now just pass on F12 combinations. - */ - switch (b) - { - case 0: - /* Home and Delete are the only special cases */ - switch (a) - { - case 0x1e: - ro_press('k','h', 0); /* Home */ - return; - case 0x7f: - ro_press('k','D', 0); /* Delete */ - return; - case CSI: - { - /* Turn CSI into K_CSI. Untested! */ - char_u string[3] = {CSI, KS_EXTRA, KE_CSI}; - - add_to_input_buf(string, 3); - return; - } - default: - add_to_input_buf(code, 1); - return; - } - case 1: - if ((a & 0xcf) == 0xcc) - { - /* F12 pressed - pass it on (quick hack) */ - swi(Wimp_ProcessKey, a | 0x100); - return; - } - base = a & 0xcf; - modifier = a & 0x30; - switch (base) - { - case 0x8a: /* Tab */ - add_to_input_buf("\011", 1); - return; - case 0x8b: /* Copy (End) */ - return ro_press('@', '7', modifier); - case 0x8c: /* Left */ - return ro_press('k', 'l', modifier); - case 0x8d: /* Right */ - return ro_press('k', 'r', modifier); - case 0x8e: /* Down */ - if (modifier & 0x10) - return ro_press('k', 'N', modifier ^ 0x10); - else - return ro_press('k', 'd', modifier); - case 0x8f: /* Up */ - if (modifier & 0x10) - return ro_press('k', 'P', modifier ^ 0x10); - else - return ro_press('k', 'u', modifier); - case 0xca: /* F10 */ - return ro_press('k', ';', modifier); - case 0xcb: /* F11 */ - return ro_press('F', '1', modifier); - case 0xcd: /* Insert */ - return ro_press('k', 'I', modifier); - default: - if (base > 0x80 && base < 0x18a) - { - /* One of the other function keys */ - return ro_press('k', '0' + (base & 15), modifier); - } - } - } -} - -/* Process a mouse event. */ - void -ro_mouse(block) - int *block; -{ - int x, y, button, vim_button; - int modifiers = 0; - int min_x, min_y; /* Visible area of editor window */ - int max_x, max_y; - - if (block[3] != gui.window_handle || ro_dragging) - return; /* Not our window or ignoring clicks*/ - - x = block[0]; /* Click position - screen coords */ - y = block[1]; - button = block[2]; - - block[0] = gui.window_handle; - swi(Wimp_GetWindowState, 0, block); - min_x = block[1]; - min_y = block[2]; - max_x = block[3]; - max_y = block[4]; - - if (block[3] - x < gui.scrollbar_width) - { - /* Click in that blank area under the scrollbars */ - - if (button & 0x444) - { - int front_block[10]; - /* Dragging with Select - bring window to front first */ - front_block[0] = gui.window_handle; - swi(Wimp_GetWindowState, 0, front_block); - front_block[7] = -1; - ro_open_main(front_block); - } - - block[0] = gui.window_handle; - block[1] = 7; /* Drag point */ - block[2] = block[4] = 0; /* Coords of point. */ - block[3] = block[5] = 0; - drag_x_offset = max_x - x; - drag_y_offset = min_y - y; - - /* Parent box. */ - block[6] = min_x + - gui.scrollbar_width * 2 + - MIN_COLUMNS * gui.char_width; - block[7] = 0; - gui_mch_get_screen_dimensions(&block[8], &block[9]); - block[9] = max_y - - 4 * gui.char_height - - gui.scrollbar_height; - - swi(Wimp_DragBox, 0, block); - ro_dragging = DRAG_RESIZE_WINDOW; - drag_button = vim_button; - drag_modifiers = modifiers; - return; - } - - if (button & 0x111) - vim_button = MOUSE_RIGHT; - else if (button & 0x222) - vim_button = MOUSE_MIDDLE; - else - vim_button = MOUSE_LEFT; - - swi(OS_Byte, 121, 0x80); - if (r1 == 0xff) - modifiers |= MOUSE_SHIFT; - swi(OS_Byte, 121, 0x81); - if (r1 == 0xff) - modifiers |= MOUSE_CTRL; - swi(OS_Byte, 121, 0x82); - if (r1 == 0xff) - modifiers |= MOUSE_ALT; - - if (button == 2) - { - /* Menu click: - * If shift was pressed then do the paste action. - * If not, then open the pop-up menu. - */ - modifiers ^= MOUSE_SHIFT; - if (modifiers && MOUSE_SHIFT) - { - vimmenu_T main; - /* Shift was NOT pressed - show menu */ - main.dname = (char_u *) "Vim"; - main.children = root_menu; - gui_mch_show_popupmenu(&main); - return; - } - } - - /* Gain the input focus */ - swi(Wimp_SetCaretPosition, gui.window_handle, -1, 0, 0, -1, -1); - - if (button & 0xf0) - { - /* Drag operation: - * - * Tell the Wimp to start a drag. - * Monitor null events. - */ - block[1] = 7; /* Drag a point. */ - block[2] = block[4] = x; /* Coords of point. */ - block[3] = block[5] = y; - block[6] = 0; /* Coords of bounding box. */ - block[7] = 0; - gui_mch_get_screen_dimensions(&block[8], &block[9]); - - drag_x_offset = drag_y_offset = 0; - - swi(Wimp_DragBox, 0, block); - ro_dragging = DRAG_SELECTION; - drag_button = vim_button; - drag_modifiers = modifiers; - - vim_button |= MOUSE_DRAG; - } - - gui_send_mouse_event( - vim_button, - x - min_x, - max_y - y, - button & 0xf ? TRUE : FALSE, /* dclick */ - modifiers); -} - - void -ro_continue_drag(block) - int *block; /* Just used as scrap. */ -{ - int x, y; - - /* Get screen coords of pointer. */ - swi(Wimp_GetPointerInfo, 0, block); - x = block[0] + drag_x_offset; - y = block[1] + drag_y_offset; - - block[0] = gui.window_handle; - swi(Wimp_GetWindowState, 0, block); - - if (ro_dragging == DRAG_RESIZE_WINDOW) - { - /* Resizeing the main window. */ - block[2] = y; - block[3] = x; - ro_open_main(block); - } - else - { - /* Selecting some text. */ - gui_send_mouse_event( - drag_button | MOUSE_DRAG, /* Always report the same button */ - x - block[1], - block[4] - y, - FALSE, /* Not a double click. */ - drag_modifiers); - } -} - -/* User has released all mouse buttons, marking the end of a drag. */ - void -ro_drag_finished(block) - int *block; -{ - int x; - int y; - int width, height; - - /* I don't trust the box returned by Wimp_Poll; look at the pointer - * ourselves. - */ - swi(Wimp_GetPointerInfo, 0, block); - x = block[0] + drag_x_offset; - y = block[1] + drag_y_offset; - - if (ro_dragging == DRAG_RESIZE_WINDOW) - { - block[0] = gui.window_handle; - swi(Wimp_GetWindowState, 0, block); - block[2] = y; - block[3] = x; - ro_open_main(block); - - width = (block[3] - block[1]); - height = (block[4] - block[2]); - - swi(Wimp_ForceRedraw, gui.window_handle, 0, -height, width, 0); - gui_resize_shell(width, height); - } - else - { - block[0] = gui.window_handle; - swi(Wimp_GetWindowState, 0, block); - gui_send_mouse_event( - MOUSE_RELEASE, - x - block[1], - block[4] - y, - FALSE, /* not a double click */ - drag_modifiers); - } - ro_dragging = DRAG_FALSE; -} - -/* Load the file/pathname given in block into a [new] buffer. - * - * Modifier Action - * - * None :confirm e - * Ctrl :sp - * Shift - * - * Insert into typebuf, at the start. - * If loading from !Scrap then use saved leafname instead, and - * delete the scrap file. Also, ignore shift key. - * - * NB: Doesn't send DataLoadAck (other app might delete temp file?). - */ - void -ro_dataload(block) - int *block; -{ - char_u new_path[MAXPATHL]; - char_u *path = ((char_u *) block) + 44; - int scrap = FALSE; - - if (block[3] == leaf_ref && leaf_name) - scrap = TRUE; - - switch (get_real_state() & 0xff) - { - case INSERT: - case CMDLINE: - case CMDLINE+LANGMAP: - /* For insert mode we can only insert the pathname (currently) - * Make sure Shift is pressed. - */ - swi(OS_Byte, 121, 0x80); /* Is Shift pressed? */ - if (r1 == 0xff) - { - ins_typebuf(" ", REMAP_NONE, 0, TRUE, FALSE); - ins_typebuf(path, REMAP_NONE, 0, TRUE, FALSE); - ro_return_early = TRUE; /* Return even though nothing was typed. */ - } - else - swi(Wimp_ReportError, - "\0\0\0\0Sorry, you can only load text in normal mode", 5, "Vim"); - break; - - case NORMAL: - ro_return_early = TRUE; /* Return even though nothing was typed. */ - - if (scrap) /* Remove . Later. */ - ins_typebuf(":!~remove \r", REMAP_NONE, 0, TRUE, FALSE); - - /* Insert {:sp ,:confirm e }[+f\ ] */ - ins_typebuf("\r", REMAP_NONE, 0, TRUE, FALSE); - ins_typebuf(path, REMAP_NONE, 0, TRUE, FALSE); - ins_typebuf(" ", REMAP_NONE, 0, TRUE, FALSE); - - if (scrap) - { - /* Loading via !Scrap - change pathname to stored leafname */ - ins_typebuf(leaf_name, REMAP_NONE, 0, TRUE, FALSE); - ins_typebuf(" +f\\ ", REMAP_NONE, 0, TRUE, FALSE); - leaf_ref = 0; - vim_free(leaf_name); - leaf_name = NULL; - } - - swi(OS_Byte, 121, 0x81); /* Is Ctrl pressed? */ - if (r1 == 0xff) - /* Yes, split window */ - ins_typebuf(":sp", REMAP_NONE, 0, TRUE, FALSE); - else - ins_typebuf(":confirm e", REMAP_NONE, 0, TRUE, FALSE); - break; - - default: - swi(Wimp_ReportError, "\0\0\0\0You can only load text in normal mode.", 5, "Vim"); - } - /* Send DataSaveAck so other program doesn't think we died - * and delete . - */ - block[3] = block[2]; - block[4] = 4; - swi(Wimp_SendMessage, 17, block, block[1]); -} - - void -ro_datasave(block) - int *block; -{ - char_u *path = ((char_u *) block) + 44; - - /* Preserve the name given so we can use it, not */ - if (leaf_name) - vim_free(leaf_name); - leaf_name = vim_strsave(path); - - block[9] = -1; /* File is unsafe. */ - strcpy(path, ""); - block[0] = 60; - block[3] = block[2]; - block[4] = 2; - swi(Wimp_SendMessage, 17, block, block[1]); - - leaf_ref = block[2]; -} - - void -ro_message(block) - int *block; -{ - char_u *buffer; - long_u len; - - if (block[1] == task_handle) - return; /* Don't talk to ourself! */ - switch (block[4]) - { - case 0: /* Quit. */ - if (block[4] == 0) - ro_quit(); - break; - case 1: /* DataSave */ - ro_datasave(block); - break; - case 2: /* DataSaveAck. */ - if (clip_convert_selection(&buffer, &len, &clip_star) == -1) - return; - - /* Save the clipboard contents to a file. */ - swi(OS_File, 10, ((char_u *) block) + 44, 0xfff, 0, buffer, buffer + len); - - /* Ack with DataLoad message. */ - block[3] = block[2]; - block[4] = 3; - block[9] = len; - swi(Wimp_SendMessage, 17, block, block[1]); - - vim_free(buffer); - break; - case 3: /* DataLoad */ - ro_dataload(block); - break; - case 8: /* PreQuit */ - ro_prequit(block); - break; - case 0xf: /* Lose clipboard. */ - if (block[5] & 4) - { - clip_free_selection(&clip_star); - clip_star.owned = FALSE; - } - break; - case 0x10: /* DataRequest (clip_star) */ - if (clip_star.owned) - { - int rows; - - /* Tell other program that we have the clipboard. */ - block[0] = 52; - block[3] = block[2]; /* Copy myref to yourref. */ - block[4] = 1; /* DataSave message. */ - /* Create an estimate for the size (larger or same as true - * value) */ - rows = clip_star.end.lnum - clip_star.start.lnum; - if (rows < 0) - rows = -rows; - block[9] = (rows + 1) * Columns + 1; /* Add one for possible - final newline. */ - block[10] = 0xfff; /* Clipboard is text. */ - strcpy( ((char_u *) block) + 44, "VimClip"); - swi(Wimp_SendMessage, 17, block, block[1]); - } - break; - case 0x400c1: /* Mode change */ - changed_mode = TRUE; /* Flag - update on next OpenWindow */ - if (zap_redraw) - { - /* JK230798, re-initialise ZapRedraw stuff */ - if (ro_zap_redraw_initialise() == FAIL) - zap_redraw = FALSE; - } - break; - case 0x400c3: /* TaskCloseDown */ - if (block[1] == child_handle) - child_handle = 0; - break; - } -} - -/* - * Converts a scrollbar's window handle into a scrollbar pointer. - * NULL on failure. - */ - scrollbar_T * -ro_find_sbar(id) - int id; -{ - win_T *wp; - - if (gui.bottom_sbar.id == id) - return &gui.bottom_sbar; - FOR_ALL_WINDOWS(wp) - { - if (wp->w_scrollbars[SBAR_LEFT].id == id) - return &wp->w_scrollbars[SBAR_LEFT]; - if (wp->w_scrollbars[SBAR_RIGHT].id == id) - return &wp->w_scrollbars[SBAR_RIGHT]; - } - return NULL; -} - - void -scroll_to(line, sb) - int sb; /* Scrollbar number */ - int line; -{ - char_u code[8]; - - /* Don't put events in the input queue now. */ - if (hold_gui_events) - return; - - /* Send a scroll event: - * - * A scrollbar event is CSI (NOT K_SPECIAL), KS_VER_SCROLLBAR, - * KE_FILLER followed by: - * one byte representing the scrollbar number, and then four bytes - * representing a long_u which is the new value of the scrollbar. - */ - code[0] = CSI; - code[1] = KS_VER_SCROLLBAR; - code[2] = KE_FILLER; - code[3] = sb; - code[4] = line >> 24; - code[5] = line >> 16; - code[6] = line >> 8; - code[7] = line; - add_to_input_buf(code, 8); -} - - void -h_scroll_to(col) - int col; -{ - char_u code[8]; - - /* Don't put events in the input queue now. */ - if (hold_gui_events) - return; - - /* Send a scroll event: - * - * A scrollbar event is CSI (NOT K_SPECIAL) - * - * A horizontal scrollbar event is K_SPECIAL, KS_HOR_SCROLLBAR, - * KE_FILLER followed by four bytes representing a long_u which is the - * new value of the scrollbar. - */ - code[0] = CSI; - code[1] = KS_HOR_SCROLLBAR; - code[2] = KE_FILLER; - code[4] = col >> 24; - code[5] = col >> 16; - code[6] = col >> 8; - code[7] = col; - add_to_input_buf(code, 8); -} - - void -ro_scroll(block) - int *block; -{ - scrollbar_T *sb; - int offset; - win_T *wp; - - /* Block is ready for Wimp_OpenWindow, and also contains: - * - * +32 = scroll X direction (-2 .. +2) - * +36 = scroll Y direction (-2 .. +2) - */ - - sb = ro_find_sbar(block[0]); - if (!sb) - return; /* Window not found (error). */ - - wp = sb-> wp; - - if (wp == NULL) - { - /* Horizontal bar. */ - offset = block[8]; - if (offset == -2) - offset = (block[1] - block[3]) / gui.char_width; - else if (offset == 2) - offset = (block[3] - block[1]) / gui.char_width; - - block[5] += offset * gui.char_width; - - gui_drag_scrollbar(sb, block[5] / gui.char_width, FALSE); - - swi(Wimp_OpenWindow, 0, block); - } - else - { - offset = -block[9]; - if (offset == -2) - offset = -(wp -> w_height - 1); - else if (offset == 2) - offset = wp -> w_height - 1; - - /* Possibly we should reposition the scrollbar? - * Vim seems to update the bar anyway... - */ - gui_drag_scrollbar(sb, offset - (block[6] / gui.char_height), FALSE); - } -} - -/* Move a window by a given offset. Used to simulate the function of the - * nested wimp. - */ - void -ro_move_child(window, x, y, pos_wanted, pos_got) - int window; - int x,y; /* offset to move by */ - int pos_wanted, pos_got; -{ - int block[10]; - - block[0] = window; - swi(Wimp_GetWindowState, 0, block); - block[1] += x; - block[2] += y; - block[3] += x; - block[4] += y; - if (pos_wanted == -1) - block[7] = -1; - else if (pos_wanted == -2) - block[7] = pos_got; - swi(Wimp_OpenWindow, 0, block); -} - -/* Open the main window. Also updates scrollbars if we are not - * using the nested Wimp. - * If we have just changed mode then re-read all values. - */ - void -ro_open_main(block) - int *block; -{ - int toggle_size; - - /* Find out if the user clicked on the toggle size icon. */ - block[20] = block[0]; - swi(Wimp_GetWindowState, 0, block + 20); - toggle_size = block[28] & (1 << 19); - - if (nested_wimp) - { - swi(Wimp_OpenWindow, 0, block); - } - else - { - int old[10]; - int x_offset, y_offset; /* Move children same as parent. */ - int pos_wanted, pos_got; - int left_bar = gui.which_scrollbars[SBAR_LEFT]; - int right_bar = gui.which_scrollbars[SBAR_RIGHT]; - win_T *wp; - - /* Three cases to think about: - * 1) Move to top. Open each window at the top. - * 2) Same stack position. Open each with same position. - * 3) Open at bottom. Open children with parent's new position. - */ - - old[0] = block[0]; - swi(Wimp_GetWindowState, 0, old); - pos_wanted = block[7]; - swi(Wimp_OpenWindow, 0, block); - /* Block updated by OpenWindow? I don't think so! */ - swi(Wimp_GetWindowState, 0, block); - pos_got = block[7]; - - x_offset = block[1] - old[1]; - y_offset = block[4] - old[4]; - if (x_offset || y_offset || pos_wanted == -1 || pos_wanted == -2) - { - /* If parent has moved, re-open all the child windows. */ - FOR_ALL_WINDOWS(wp) - { - /* Reopen scrollbars for this window. */ - if (left_bar) - ro_move_child(wp -> w_scrollbars[SBAR_LEFT].id, - x_offset, y_offset, - pos_wanted, pos_got); - if (right_bar) - ro_move_child(wp -> w_scrollbars[SBAR_RIGHT].id, - x_offset, y_offset, - pos_wanted, pos_got); - } - } - } - if (changed_mode || toggle_size) - { - int width, height; - - if (changed_mode) - ro_measure_tools(); - block[0] = gui.window_handle; - swi(Wimp_GetWindowState, 0, block); - - width = block[3] - block[1]; - height = block[4] - block[2]; - swi(Wimp_ForceRedraw, gui.window_handle, 0, -height, width, 0); - gui_resize_shell(width, height); - changed_mode = FALSE; - } -} - - void -ro_open_window(block) - int *block; -{ - int pos; - scrollbar_T *sb; - - if (block[0] == gui.window_handle) - ro_open_main(block); - else - { - swi(Wimp_OpenWindow, 0, block); - if (block[0] != gui.window_handle) - { - sb = ro_find_sbar(block[0]); - if (sb) - { - if (sb-> wp != NULL) - gui_drag_scrollbar(sb, -block[6] / gui.char_height, FALSE); - else - gui_drag_scrollbar(sb, block[5] / gui.char_width, FALSE); - } - } - } -} - - void -ro_menu_selection(block) - int *block; -{ - int *item = wimp_menu + 7; - vimmenu_T *menu; - /* wimp_menu points to a wimp menu structure */ - - for (;;) - { - while (block[0]--) - item += 6; - if (block[1] == -1) - break; - item = ((int *) item[1]) + 7; - block++; - } - /* item points to the wimp menu item structure chosen */ - menu = (vimmenu_T *) item[5]; - - swi(Wimp_GetPointerInfo, 0, block); - if (block[2] == 1) - /* Adjust used - keep menu open */ - swi(Wimp_CreateMenu, 0, wimp_menu); - - if (menu-> cb) - menu-> cb(menu); -} - - void -ro_open_parent() -{ - int head; - char_u *i = curbuf-> b_ffname; - char_u buffer[256]; - - head = 0; - for (; *i; i++) - { - if (*i == '.') - head = i - curbuf-> b_ffname; - } - - /* Append head chars to buffer */ - if (head < 240 && curbuf-> b_ffname && head) - { - strcpy(buffer, "%filer_opendir "); - strncpy(buffer + 15, curbuf-> b_ffname, head); - buffer[15 + head] = '\0'; - swi(OS_CLI, buffer); - } -} - - void -process_event(event, block) - int event; - int *block; -{ - switch (event) - { - case 0: /* Nothing - update drag state. */ - if (ro_dragging) - ro_continue_drag(block); - break; - case 1: /* Redraw window. */ - redraw_window(block); - break; - case 2: /* Open window. */ - ro_open_window(block); - break; - case 3: /* Close window. */ - swi(Wimp_GetPointerInfo, 0, block + 1); - if (block[3] == 1) - ro_open_parent(); - else - if (ro_ok_to_quit()) - ro_quit(); - break; - case 6: /* Mouse click. */ - ro_mouse(block); - break; - case 7: /* Finished drag. */ - ro_drag_finished(block); - break; - case 8: /* Key pressed. */ - ro_insert_key((char_u *) &block[6]); - break; - case 9: - ro_menu_selection(block); - break; - case 10: /* Scroll request. */ - ro_scroll(block); - break; - case 11: /* Lose caret. */ - if (block[0] == gui.window_handle) - gui_focus_change(FALSE); - break; - case 12: /* Gain caret. */ - if (block[0] == gui.window_handle) - gui_focus_change(TRUE); - break; - case 17: /* User message. */ - case 18: /* User message recorded. */ - ro_message(block); - break; - } -} - -/* - * GUI input routine called by gui_wait_for_chars(). Waits for a character - * from the keyboard. - * wtime == -1 Wait forever. - * wtime == 0 This should never happen. - * wtime > 0 Wait wtime milliseconds for a character. - * Returns OK if a character was found to be available within the given time, - * or FAIL otherwise. - */ - int -gui_mch_wait_for_chars(long wtime) -{ - int block[64]; - int reason; - int start_time = -1; - int ctime = wtime / 10; /* delay in cs */ - - if (wtime != -1) - { - swi(OS_ReadMonotonicTime); - start_time = r0; - } - - for (;;) - { - if (ro_dragging) - reason = wimp_poll(0, block); /* Always return immediately */ - else if (wtime == -1) - reason = wimp_poll(1, block); - else - reason = wimp_pollidle(0, block, start_time + ctime); - - process_event(reason, block); - - if (input_available() || ro_return_early) - { - ro_return_early = FALSE; - return OK; /* There is something to process (key / menu event) */ - } - - if (wtime != -1) - { - swi(OS_ReadMonotonicTime); - if (r0 - start_time > ctime) - return FAIL; /* We've been waiting too long - return failure */ - } - } -} - -/* Flush any output to the screen */ - void -gui_mch_flush(void) -{ -} - -/* - * Clear a rectangular region of the screen from text pos(row1, col1) to - * (row2, col2) inclusive. - */ - void -gui_mch_clear_block(int row1, int col1, int row2, int col2) -{ - swi(ColourTrans_ReturnGCOL, gui.back_pixel << 8, 0, 0, 1<<7, 0); - plot_rectangle(96 + 5, r0, - FILL_X(col1), -FILL_Y(row2 + 1), - FILL_X(col2 + 1), -FILL_Y(row1)); -} - - void -gui_mch_clear_all(void) -{ - if (redraw_block) - { - swi(ColourTrans_SetGCOL, gui.back_pixel << 8, 0, 0, 1<<7, 0); - swi(OS_WriteI + 16); - } - else - { - int block[44]; - block[0] = gui.window_handle; - block[1] = 0; - block[2] = -gui.num_rows * gui.char_height; - block[3] = gui.num_cols * gui.char_width; - block[4] = 0; - swi(Wimp_UpdateWindow, 0, block); - while (r0) - { - swi(ColourTrans_SetGCOL, gui.back_pixel << 8, 0, 0, 1<<7, 0); - swi(OS_WriteI + 16); - swi(Wimp_GetRectangle, 0, block); - } - } -} - -/* - * Delete the given number of lines from the given row, scrolling up any - * text further down within the scroll region. - */ - void -gui_mch_delete_lines(int row, int num_lines) -{ - int top_from = -row - num_lines; - int bot_from = -gui.scroll_region_bot - 1; - int bot_to = bot_from + num_lines; - - swi(ColourTrans_SetGCOL, gui.back_pixel << 8, 0, 0, 0x80, 0); - - /* Changed without checking! */ - swi(Wimp_BlockCopy, gui.window_handle, - gui.scroll_region_left * gui.char_width, - bot_from * gui.char_height, - (gui.scroll_region_right - gui.scroll_region_left - + 1) * gui.char_width, - top_from * gui.char_height, - - gui.scroll_region_left * gui.char_width, - bot_to * gui.char_height); - - gui_clear_block(gui.scroll_region_bot - num_lines + 1, - gui.scroll_region_left, - gui.scroll_region_bot, gui.scroll_region_right); -} - -/* - * Insert the given number of lines before the given row, scrolling down any - * following text within the scroll region. - */ - void -gui_mch_insert_lines(int row, int num_lines) -{ - int top_from = -row; - int bot_to = -gui.scroll_region_bot - 1; - int bot_from = bot_to + num_lines; - - swi(ColourTrans_SetGCOL, gui.back_pixel << 8, 0, 0, 0x80, 0); - - swi(Wimp_BlockCopy, gui.window_handle, - gui.scroll_region_left * gui.char_width, - bot_from * gui.char_height, - (gui.scroll_region_right - gui.scroll_region_left - + 1) * gui.char_width, - top_from * gui.char_height, - - gui.scroll_region_left * gui.char_width, - bot_to * gui.char_height); - - gui_clear_block(row, gui.scroll_region_left, - row + num_lines - 1, gui.scroll_region_right); -} - -/* Put selection in clipboard buffer. - * Should we become the new owner? - */ - void -clip_mch_request_selection(VimClipboard *cbd) -{ - int block[64]; /* Will be used in Wimp_Poll. */ - int reason; - char_u *buffer; - long_u length; - - block[0] = 48; /* Size of block. */ - block[3] = 0; /* Orinial message. */ - block[4] = 0x10; /* Data request. */ - block[5] = gui.window_handle; - block[6] = RO_LOAD_CLIPBOARD; /* Internal handle. */ - block[7] = block[8] = 0; /* (x,y) not used. */ - block[9] = 4; - block[10] = 0xfff; /* We want text files if possible, I think. */ - block[11] = -1; /* End of list. */ - swi(Wimp_SendMessage, 17, block, 0); /* Broadcast request. */ - - /* OK, we've sent the request. Poll until we get a null poll (failure) or - * we load the clipboard. - * If we receive a DataSave event with icon handle = -2 then put it on the - * clipboard. RISC OS should ensure that key events will not be delivered - * until the clipboard operation completes (unless the owner starts idling - * - we can't wait forever!). - */ - for (;;) - { - reason = wimp_poll(0, block); - if (reason == 0) - return; /* Failed to get clipboard. */ - if ((reason == 17 || reason == 18) && - block[4] == 1 && block[6] == RO_LOAD_CLIPBOARD) - break; /* Got it - stop waiting. */ - process_event(reason, block); - if (ro_return_early) - return; - } - /* Tell owner to save data in . */ - block[0] = 60; - block[3] = block[2]; /* Copy myref -> yourref */ - block[4] = 2; /* DataSaveAck. */ - block[9] = -1; /* Data is unsafe. */ - strcpy( ((char_u *) block) + 44, ""); - swi(Wimp_SendMessage, 17, block, block[1]); - - /* Wait again for reply. */ - for (;;) - { - reason = wimp_poll(0, block); - if (reason == 0) - return; /* Other program has given up! */ - if ((reason == 17 || reason == 18) && block[4] == 3 && block[6] == RO_LOAD_CLIPBOARD) - break; /* Clipboard data saved to */ - process_event(reason, block); - if (ro_return_early) - return; - } - - /* contains clipboard - load it. */ - if (xswi(OS_File, 17, "") & v_flag) - return; /* Error! */ - if (r0 != 1 && r0 != 3) - return; - length = r4; - - buffer = lalloc(length, TRUE); /* Claim memory (and report errors). */ - if (buffer == NULL) - return; - - if (xswi(OS_File, 16, "", buffer, 0) & v_flag) - return; - - clip_yank_selection(MCHAR, buffer, length, cbd); - - vim_free(buffer); - - swi(OS_FSControl, 27, "", 0, 0); /* Delete temp file. */ - - block[4] = 4; /* Send DataLoadAck. */ - block[3] = block[2]; /* Copy myref -> yourref. */ - swi(Wimp_SendMessage, 17, block, block[1]); -} - -/* Not sure what this means under RISC OS. */ - void -clip_mch_lose_selection(VimClipboard *cbd) -{ -} - -/* Tell everyone that we now own the clipboard. - * Return OK if our claim is accepted (always, under RISC OS) - */ - int -clip_mch_own_selection(VimClipboard *cbd) -{ - int block[6]; - block[0] = 24; /* Length of block. */ - block[3] = 0; /* Original message. */ - block[4] = 0xf; /* ClaimEntity. */ - block[5] = 0x4; /* Claim clipboard only. */ - swi(Wimp_SendMessage, 17, block, 0); - return OK; -} - -/* - * Send the current selection to the clipboard. Do nothing for X because we - * will fill in the selection only when requested by another app. Sounds good - * for RISC OS too. - */ - void -clip_mch_set_selection(VimClipboard *cbd) -{ - clip_get_selection(cbd); -} - -/* - * Make a menu either grey or not grey. - */ - void -gui_mch_menu_grey(vimmenu_T *menu, int grey) -{ - menu-> greyed_out = grey; -} - -/* - * Make menu item hidden or not hidden - */ - void -gui_mch_menu_hidden(vimmenu_T *menu, int hidden) -{ - menu-> hidden = hidden; -} - -/* - * This is called after setting all the menus to grey/hidden or not. - */ - void -gui_mch_draw_menubar(void) -{ - swi(Wimp_CreateMenu, 0, -1); - if (wimp_menu != (int *) -1) - { - ro_remove_menu(wimp_menu); - wimp_menu = (int *) -1; - } -} - -/* Add or remove a scrollbar. Note that this is only called when - * the scrollbar state is changing. - * The scroll bar window has already been created. - * We can't do anything except remove the scroll bar - * until we know what size to use. - */ - void -gui_mch_enable_scrollbar(sb, flag) - scrollbar_T *sb; - int flag; -{ - if (!flag) - swi(Wimp_CloseWindow, 0, & (sb->id) ); - return; -} - - void -gui_mch_set_blinking(long waittime, long on, long off) -{ -} - -/* - * Stop the cursor blinking. Show the cursor if it wasn't shown. - */ - void -gui_mch_stop_blink(void) -{ -} - -/* - * Start the cursor blinking. If it was already blinking, this restarts the - * waiting time and shows the cursor. - */ - void -gui_mch_start_blink(void) -{ -} - -/* - * Return the RGB value of a pixel as a long. - */ - long_u -gui_mch_get_rgb(guicolor_T pixel) -{ - return (long_u)pixel; -} - - void -gui_mch_set_text_area_pos(int x, int y, int w, int h) -{ -} - - void -gui_mch_enable_menu(int flag) -{ -} - - void -gui_mch_set_menu_pos(int x, int y, int w, int h) -{ -} - - void -gui_mch_add_menu(vimmenu_T *menu, int idx) -{ -} - - void -gui_mch_add_menu_item(vimmenu_T *menu, int idx) -{ -} - - void -gui_mch_new_menu_colors(void) -{ -} - - void -gui_mch_destroy_menu(vimmenu_T *menu) -{ -} - -/* Size of buffer has changed. - * Add one to max since gui.c subtracts one more than it should! - */ - void -gui_mch_set_scrollbar_thumb(sb, val, size, max) - scrollbar_T *sb; - long val; - long size; - long max; -{ - int block[10], width, height; - - width = (max + 1) * gui.char_width; - height = (max + 1 + W_STATUS_HEIGHT(sb->wp)) * gui.char_height; - - block[0] = block[3] = 0; - block[1] = -height + (1 << y_eigen_factor); - block[2] = width; - - swi(Wimp_SetExtent, sb -> id, block); - - block[0] = sb -> id; - swi(Wimp_GetWindowState, 0, block); - block[5] = val * gui.char_width; - block[6] = -val * gui.char_height; - swi(Wimp_OpenWindow, 0, block, 0x4b534154, - gui.window_handle, /* Parent window handle. */ - (CHILD_FIX_TO_RIGHT << CHILD_LEFT ) | - (CHILD_FIX_TO_RIGHT << CHILD_RIGHT ) | - (CHILD_FIX_TO_BOTTOM << CHILD_TOP ) | - (CHILD_FIX_TO_BOTTOM << CHILD_BOTTOM) | - (CHILD_SELF_SCROLL << CHILD_SCROLL_X) | - (CHILD_SELF_SCROLL << CHILD_SCROLL_Y) - ); -} - -/* Set the position of the scrollbar within the editor - * window. Note that, for vertical scrollbars, x and w - * are ignored. For horizontal bars y and h are ignored. - */ - void -gui_mch_set_scrollbar_pos(sb, x, y, w, h) - scrollbar_T *sb; - int x; /* Horizontal sb position */ - int y; /* Top of scroll bar */ - int w; /* Width */ - int h; /* Height */ -{ - int block[24]; - int px1, py1; /* Parent window min coords */ - int px2, py2; /* Parent window max coords */ - - /* Find where the parent window is. */ - block[0] = gui.window_handle; - swi(Wimp_GetWindowState, 0, block); - px1 = block[1]; - py1 = block[2]; - px2 = block[3]; - py2 = block[4]; - - block[0] = sb -> id; - - /* Find out how big the scroll window is at the moment. */ - swi(Wimp_GetWindowInfo, 0, ((char_u *)block) + 1); - - if (block[13] < w || block[12] > -h) - { - /* Current window is too small! */ - if (block[12] > -h) - block[12] = -h; - if (block[13] < w) - block[13] = w; - swi(Wimp_SetExtent, block[0], block + 11); - } - - /* This works better on the nested_wimp. */ - if (sb-> wp) - { - /* This is a vertical scrollbar. */ - block[1] = block[3] = px2 - gui.scrollbar_width + (1 << x_eigen_factor); - block[2] = 1 + py2 - (y + h) + (1 << y_eigen_factor); - block[4] = 1 + py2 - y; - } - else - { - /* This is a horizontal scrollbar. */ - block[2] = block[4] = py1 + gui.scrollbar_height; - block[1] = px1; - block[3] = px2 - gui.scrollbar_width; - } - - block[5] = 0; - block[6] = 0; - block[7] = -1; - - swi(Wimp_OpenWindow, 0, block, 0x4b534154, - gui.window_handle, /* Parent window handle. */ - (CHILD_FIX_TO_RIGHT << CHILD_LEFT ) | - (CHILD_FIX_TO_RIGHT << CHILD_RIGHT ) | - (CHILD_FIX_TO_BOTTOM << CHILD_TOP ) | - (CHILD_FIX_TO_BOTTOM << CHILD_BOTTOM) | - (CHILD_SELF_SCROLL << CHILD_SCROLL_X) | - (CHILD_SELF_SCROLL << CHILD_SCROLL_Y) - ); -} - -/* Create a window with no workarea to place inside editor window. - * (what happens without the nested wimp?) - * Data for scrollbar is invalid. - */ - void -gui_mch_create_scrollbar(sb, orient) - scrollbar_T *sb; - int orient; /* orient is SBAR_HORIZ or SBAR_VERT */ -{ - int bar[] = - { - 0, 0, /* Visible area : min X,Y */ - 100, 100, /* max X,Y */ - 0, 0, /* Scroll offsets */ - -1, /* Window in front */ - 0x80800150 | (orient == SBAR_HORIZ ? (1 << 30) : (1 << 28)), - 0xff070207, /* Colours */ - 0x000c0103, /* More colours */ - 0, -0x4000, /* Workarea extent */ - 0x4000, 0, /* max X,Y */ - 0x00000000, /* No title */ - 0 << 12, /* No workarea button type */ - 1, /* Wimp sprite area */ - 0x00010001, /* Minimum width, height */ - 0, 0, 0, /* Title data (none) */ - 0 /* No icons */ - }; - swi(Wimp_CreateWindow, 0, bar); - sb -> id = r0; -} - -#if defined(FEAT_WINDOWS) || defined(PROTO) - void -gui_mch_destroy_scrollbar(scrollbar_T *sb) -{ - swi(Wimp_DeleteWindow, 0, & (sb->id)); - sb -> id = -1; -} -#endif - - void -gui_mch_set_scrollbar_colors(scrollbar_T *sb) -{ - /* Always use default RO colour scheme. */ -} - -/* - * Get current mouse coordinates in text window. - * Note: (0,0) is the bottom left corner, positive y is UP. - */ - void -gui_mch_getmouse(x, y) - int *x; - int *y; -{ - int left; - int top; - int block[10]; - - block[0] = gui.window_handle; - swi(Wimp_GetWindowState, 0, block); - left = block[1]; - top = block[4]; - - swi(Wimp_GetPointerInfo, 0, block); - *x = block[0] - left; - *y = top - block[1]; -} - -/* MouseTo(x, y) */ - void -gui_mch_setmouse(x, y) - int x; - int y; -{ -} - - void -gui_mch_toggle_tearoffs(enable) - int enable; -{ - /* no tearoff menus */ -} - -/* Redraw a window's title. - * For the nested wimp we use the new 'redraw-title-bar' reason code. - * For older wimps we mark the area of the screen where the title bar - * is as invalid. - */ - void -ro_redraw_title(window) - int window; -{ - if (nested_wimp) - { - swi(Wimp_ForceRedraw, window, 0x4b534154, 3); - } - else - { - int block[10]; - int miny; - - block[0] = window; - swi(Wimp_GetWindowState, 0, block); - miny = block[4]; - swi(Wimp_GetWindowOutline, 0, block); - swi(Wimp_ForceRedraw, -1, - block[1], miny, - block[3], block[4]); - } -} - -/* Turn a vimmenu_T structure into a wimp menu structure. - * -1 if resulting menu is empty. - * Only the children and dname items in the root menu are used. - */ - int * -ro_build_menu(menu) - vimmenu_T *menu; -{ - int *wimp_menu; - int width = 4; - int w; - int size = 28; - vimmenu_T *item; - int *wimp_item; - - /* Find out how big the menu is so we can allocate memory for it */ - for (item = menu-> children; item; item = item-> next) - { - if (item-> hidden == FALSE && !menu_is_separator(item->name)) - size += 24; - } - - if (size <= 28) - return (int *) -1; /* No children - shouldn't happen */ - - wimp_menu = (int *) alloc(size); - - wimp_menu[0] = (int) menu-> dname; - wimp_menu[1] = -1; - wimp_menu[2] = 0; - wimp_menu[3] = 0x00070207; - wimp_menu[5] = 44; - wimp_menu[6] = 0; - - wimp_item = wimp_menu + 7; - - for (item = menu-> children; item; item = item-> next) - { - if (menu_is_separator(item-> name)) - { - /* This menu entry is actually a separator. If it is not the first - * menu entry then mark the previous menu item as needing a dotted - * line after it. - */ - if (wimp_item > wimp_menu + 7) - wimp_item[-6] |= 0x2; - } - else if (item-> hidden == FALSE) - { - wimp_item[0] = 0; - wimp_item[1] = item-> children ? (int) ro_build_menu(item) : -1; - wimp_item[2] = 0x07009131 | (item-> greyed_out << 22); - wimp_item[3] = (int) item-> dname; - wimp_item[4] = -1; - wimp_item[5] = (int) item; /* Stuff the menu address in this unused space */ - - w = strlen(item-> dname) + 1; - if (w > width) - width = w; - wimp_item += 6; - } - } - - wimp_menu[4] = (width + 2) * 16; - wimp_menu[7] |= 0x100; /* Menu title is indirected */ - wimp_item[-6] |= 0x080; /* Last entry in menu */ - return wimp_menu; -} - - static void -ro_remove_menu(menu) - int *menu; -{ - int *item = menu + 7; - - if (menu == NULL || menu == (int *) -1) - return; - - for (;;) - { - if (item[1] != -1) - ro_remove_menu((int *) item[1]); /* Remove sub-menu */ - if (item[0] & 0x80) - break; /* This was the last entry */ - item += 6; - } - vim_free(menu); -} - - void -gui_mch_show_popupmenu(menu) - vimmenu_T *menu; -{ - int block[10]; - - /* Remove the existing menu, if any */ - if (wimp_menu != (int *) -1) - { - swi(Wimp_CreateMenu, 0, -1); - ro_remove_menu(wimp_menu); - wimp_menu = (int *) -1; - } - - wimp_menu = ro_build_menu(menu); - if (wimp_menu != (int *) -1) - { - swi(Wimp_GetPointerInfo, 0, block); - swi(Wimp_CreateMenu, 0, wimp_menu, block[0] - 64, block[1] + 64); - } -} - -/* Run a command using the TaskWindow module. - * If SHELL_FILTER is set then output is not echoed to the screen, - * If it is not set, then \r is not sent to the output file. - */ - int -gui_mch_call_shell(cmd, options) - char_u *cmd; - int options; /* SHELL_FILTER if called by do_filter() */ - /* SHELL_COOKED if term needs cooked mode */ -{ - char_u task_cmd[256]; /* Contains *TaskWindow command. */ - int block[64]; - int reason; - char_u *out; - char_u c; - int old_msg_col; - char_u *out_redir; - int length; - FILE *out_file = NULL; - - out_redir = strstr(cmd, " > "); - if (out_redir == NULL) - length = strlen(cmd); /* No redirection. */ - else - { - length = out_redir - cmd; - out_file = fopen(out_redir + 3, "wb"); - if (out_file == NULL) - smsg("WARNING : Can't open file %s for writing\n", out_redir + 3); - } - - if (length > 180) - { - if (out_file) - fclose(out_file); - return FAIL; /* Command too long. */ - } - - strcpy(task_cmd, "TaskWindow \""); - strncpy(task_cmd + 12, cmd, length); - sprintf(task_cmd + 12 + length, - "\" -task &%08x -ctrl -quit -name \"Vim command\"", - task_handle); - - if (options & SHELL_COOKED) - settmode(TMODE_COOK); - - if (xswi(Wimp_StartTask, task_cmd) & v_flag) - { - /* Failed to even start a new task (out of memory?) */ - settmode(TMODE_RAW); - if (out_file) - fclose(out_file); - return FAIL; - } - - /* Wait for the child process to initialise. */ - child_handle = 0; - while (!child_handle) - { - reason = wimp_poll(0, block); - if ((reason == 17 || reason == 18) && block[4] == 0x808c2) - child_handle = block[1]; - else - process_event(reason, block); - } - - /* Block until finished */ - while (child_handle) - { - reason = wimp_poll(1, block); - if (reason == 3 || (reason == 8 && block[6] == 3)) - { - /* Close window request or CTRL-C - kill child task. */ - block[0] = 20; - block[3] = 0; - block[4] = 0x808c4; /* Morite */ - swi(Wimp_SendMessage, 17, block, child_handle); - MSG_PUTS(_("\nSending message to terminate child process.\n")); - continue; - } - else if (reason == 8) - { - block[0] = 28; - block[3] = 0; - block[4] = 0x808c0; /* Input */ - block[5] = 1; - /* Block[6] is OK as it is! */ - swi(Wimp_SendMessage, 17, block, child_handle); - continue; - } - else if (reason == 17 || reason == 18) - { - if (block[4] == 0x808c1) - { - /* Ack message. */ - block[3] = block[2]; - swi(Wimp_SendMessage, 19, block, block[1]); - out = (char_u *)block + 24; - old_msg_col = msg_col; - while (block[5]--) - { - c = *out++; - if (out_file && (c != '\r' || (options & SHELL_FILTER))) - fputc(c, out_file); - if ((options & SHELL_FILTER) == 0) - { - if (c == 127) - msg_puts("\b \b"); - else if (c > 31) - msg_putchar(c); - else if (c == 10) - { - lines_left = 8; /* Don't do More prompt! */ - msg_putchar(10); - } - } - } - /* Flush output to the screen. */ - windgoto(msg_row, msg_col); - out_flush(); - continue; - } - } - process_event(reason, block); - } - msg_putchar('\n'); - settmode(TMODE_RAW); - if (out_file) - fclose(out_file); - return OK; -} - -/* Like strsave(), but stops at any control char */ - char_u * -wimp_strsave(str) - char *str; -{ - int strlen = 0; - char_u *retval; - while (str[strlen] > 31) - strlen++; - retval = alloc(strlen + 1); - if (retval) - { - memcpy(retval, str, strlen); - retval[strlen] = '\0'; - } - return retval; -} - -/* If we are saving then pop up a standard RISC OS save box. - * Otherwise, open a directory viewer on the given directory (and return NULL) - * The string we return will be freed later. - */ - char_u * -gui_mch_browse(saving, title, dflt, ext, initdir, filter) - int saving; /* write action */ - char_u *title; /* title for the window */ - char_u *dflt; /* default file name */ - char_u *ext; /* extension added */ - char_u *initdir; /* initial directory, NULL for current dir */ - char_u *filter; /* file name filter */ -{ - char command[256]; - int length; - - if (saving) - { - int block[64]; - int reason; - int done_save = FALSE; - char_u *retval = NULL; - char_u *sprname; - char_u *fname; - int dragging_icon = FALSE; - int filetype; - - if (!dflt) - dflt = "TextFile"; - - block[0] = save_window; - block[1] = 0; - swi(Wimp_GetIconState, 0, block); - sprname = ((char_u *) block[7]); - block[1] = 1; - swi(Wimp_GetIconState, 0, block); - fname = ((char *) block[7]); - strncpy(fname, dflt, 255); - - if (xswi(OS_FSControl, 31, curbuf->b_p_oft) & v_flag) - { - filetype = 0xfff; - strcpy(sprname + 5, "xxx"); - } - else - { - filetype = r2; - sprintf(sprname + 5, "%03x", filetype); - } - - /* Open the save box */ - - swi(Wimp_GetPointerInfo, 0, block); - swi(Wimp_CreateMenu, 0, save_window, block[0] - 64, block[1] + 64); - swi(Wimp_SetCaretPosition, save_window, 1, 0, 0, -1, -1); - - while (!done_save) - { - reason = wimp_poll(1, block); - switch (reason) - { - case 1: - redraw_window(block); - break; - case 2: - if (block[0] == save_window) - swi(Wimp_OpenWindow, 0, block); - else - ro_open_window(block); - break; - case 3: - done_save = TRUE; - break; - case 6: - if (block[3] != save_window) - done_save = TRUE; - else - { - int drag_box[4]; - int min_x, max_y; - - switch (block[4]) - { - case 0: /* Start drag */ - block[0] = save_window; - swi(Wimp_GetWindowState, 0, block); - min_x = block[1]; - max_y = block[4]; - block[1] = 0; - swi(Wimp_GetIconState, 0, block); - drag_box[0] = block[2] + min_x; - drag_box[1] = block[3] + max_y; - drag_box[2] = block[4] + min_x; - drag_box[3] = block[5] + max_y; - - swi(DragASprite_Start, - 0x45, - 1, - sprname, - drag_box); - dragging_icon = TRUE; - break; - case 2: /* OK */ - retval = wimp_strsave(fname); - done_save = TRUE; - break; - case 3: /* Cancel */ - done_save = TRUE; - break; - } - } - break; - case 7: - if (dragging_icon) - { - int len = 0; - - dragging_icon = FALSE; - swi(Wimp_GetPointerInfo, 0, block); - block[5] = block[3]; - block[6] = block[4]; - block[7] = block[0]; - block[8] = block[1]; - block[9] = 0; /* Don't know the size */ - block[10] = filetype; - - while (fname[len] > 31) - { - if (fname[len] == '.') - { - fname += len + 1; - len = 0; - } - else - len++; - } - if (len > 211) - len = 211; - - memcpy(((char_u *) block) + 44, fname, len); - ((char_u *)block)[44 + len] = '\0'; - - block[0] = (len + 48) & 0xfc; - block[3] = 0; - block[4] = 1; /* DataSave */ - - swi(Wimp_SendMessage, 17, block, block[5], block[6]); - } - else - ro_drag_finished(block); - break; - case 8: - if (block[6] == 13) - { - retval = wimp_strsave(fname); - done_save = TRUE; - } - else if (block[6] == 0x1b) - done_save = TRUE; - else - swi(Wimp_ProcessKey, block[6]); - break; - case 17: - case 18: - if (block[4] == 2 && block[9] != -1) - { - /* DataSaveAck from dragging icon. */ - retval = wimp_strsave(((char_u *) block) + 44); - done_save = TRUE; - } - else if (block[4] == 0x400c9) - { - /* MenusDeleted */ - done_save = TRUE; - } - else - ro_message(block); - break; - } - } - block[0] = save_window; - swi(Wimp_CloseWindow, 0, block); - swi(Wimp_GetCaretPosition, 0, block); - if (block[0] == -1) - swi(Wimp_SetCaretPosition, gui.window_handle, -1, 0, 0, -1, -1); - - return retval; - } - else if (initdir) - { - /* Open a directory viewer */ - length = strlen(initdir); - - if (length > 240) - return NULL; /* Path too long! */ - - length = sprintf(command, "Filer_OpenDir %s", initdir); - while (command[length - 1] == '.') - length--; - command[length] = '\0'; - swi(OS_CLI, command); - } - return NULL; -} diff -Naur vim73.orig/src/gui_riscos.h vim73/src/gui_riscos.h --- vim73.orig/src/gui_riscos.h 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/gui_riscos.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -/* vi:set ts=8 sts=4 sw=4: - * - * VIM - Vi IMproved by Bram Moolenaar - * - * Do ":help uganda" in Vim to read copying and usage conditions. - * Do ":help credits" in Vim to see a list of people who contributed. - */ - -#define FEAT_BROWSE - -#define TASK 0x4b534154 - -/* Nested wimp flags: */ -#define CHILD_FIX_TO_WORKAREA 0 -#define CHILD_FIX_TO_LEFT 1 -#define CHILD_FIX_TO_BOTTOM 1 -#define CHILD_FIX_TO_RIGHT 2 -#define CHILD_FIX_TO_TOP 2 - -#define CHILD_SELF_SCROLL 0 -#define CHILD_PARENT_SCROLL 1 - -#define CHILD_LEFT 16 -#define CHILD_BOTTOM 18 -#define CHILD_RIGHT 20 -#define CHILD_TOP 22 -#define CHILD_SCROLL_X 24 -#define CHILD_SCROLL_Y 26 - -int wimp_poll(int mask, int *block); -int wimp_poll_idle(int mask, int *block, int end_time); -void ro_open_main(int *block); diff -Naur vim73.orig/src/gui_w16.c vim73/src/gui_w16.c --- vim73.orig/src/gui_w16.c 2010-07-18 13:03:38.000000000 +0000 +++ vim73/src/gui_w16.c 2012-07-20 20:31:14.477642416 +0000 @@ -21,6 +21,12 @@ * */ +/* Win16 doesn't use the "W" methods. */ +#define pDispatchMessage DispatchMessage +#define pGetMessage GetMessage +#define pIsDialogMessage IsDialogMessage +#define pPeekMessage PeekMessage + /* * Include the common stuff for MS-Windows GUI. */ @@ -1098,7 +1104,8 @@ char_u *message, char_u *buttons, int dfltbutton, - char_u *textfield) + char_u *textfield, + int ex_cmd) { FARPROC dp; LPWORD p, pnumitems; diff -Naur vim73.orig/src/gui_w32.c vim73/src/gui_w32.c --- vim73.orig/src/gui_w32.c 2010-08-08 13:05:26.000000000 +0000 +++ vim73/src/gui_w32.c 2012-07-20 20:31:13.890975327 +0000 @@ -289,13 +289,13 @@ #ifdef FEAT_MENU static UINT s_menu_id = 100; +#endif /* * Use the system font for dialogs and tear-off menus. Remove this line to * use DLG_FONT_NAME. */ -# define USE_SYSMENU_FONT -#endif +#define USE_SYSMENU_FONT #define VIM_NAME "vim" #define VIM_CLASS "Vim" @@ -798,7 +798,7 @@ if (pt.y < rect.top) { show_tabline_popup_menu(); - return 0; + return 0L; } } return MyWindowProc(hwnd, uMsg, wParam, lParam); @@ -828,7 +828,10 @@ case WM_ENDSESSION: if (wParam) /* system only really goes down when wParam is TRUE */ + { _OnEndSession(); + return 0L; + } break; case WM_CHAR: @@ -866,7 +869,7 @@ * are received, mouse pointer remains hidden. */ return MyWindowProc(hwnd, uMsg, wParam, lParam); #else - return 0; + return 0L; #endif case WM_SIZING: /* HANDLE_MSG doesn't seem to handle this one */ @@ -874,7 +877,7 @@ case WM_MOUSEWHEEL: _OnMouseWheel(hwnd, HIWORD(wParam)); - break; + return 0L; /* Notification for change in SystemParametersInfo() */ case WM_SETTINGCHANGE: @@ -987,13 +990,19 @@ case TCN_SELCHANGE: if (gui_mch_showing_tabline() && ((LPNMHDR)lParam)->hwndFrom == s_tabhwnd) + { send_tabline_event(TabCtrl_GetCurSel(s_tabhwnd) + 1); + return 0L; + } break; case NM_RCLICK: if (gui_mch_showing_tabline() && ((LPNMHDR)lParam)->hwndFrom == s_tabhwnd) + { show_tabline_popup_menu(); + return 0L; + } break; # endif default: @@ -1037,6 +1046,7 @@ out_flush(); did_menu_tip = TRUE; } + return 0L; } break; #endif @@ -1079,18 +1089,19 @@ case WM_IME_NOTIFY: if (!_OnImeNotify(hwnd, (DWORD)wParam, (DWORD)lParam)) return MyWindowProc(hwnd, uMsg, wParam, lParam); - break; + return 1L; + case WM_IME_COMPOSITION: if (!_OnImeComposition(hwnd, wParam, lParam)) return MyWindowProc(hwnd, uMsg, wParam, lParam); - break; + return 1L; #endif default: if (uMsg == msh_msgmousewheel && msh_msgmousewheel != 0) { /* handle MSH_MOUSEWHEEL messages for Intellimouse */ _OnMouseWheel(hwnd, HIWORD(wParam)); - break; + return 0L; } #ifdef MSWIN_FIND_REPLACE else if (uMsg == s_findrep_msg && s_findrep_msg != 0) @@ -1101,7 +1112,7 @@ return MyWindowProc(hwnd, uMsg, wParam, lParam); } - return 1; + return DefWindowProc(hwnd, uMsg, wParam, lParam); } /* @@ -1260,7 +1271,7 @@ /* try and load the user32.dll library and get the entry points for * multi-monitor-support. */ - if ((user32_lib = LoadLibrary("User32.dll")) != NULL) + if ((user32_lib = vimLoadLib("User32.dll")) != NULL) { pMonitorFromWindow = (TMonitorFromWindow)GetProcAddress(user32_lib, "MonitorFromWindow"); @@ -1270,6 +1281,25 @@ pGetMonitorInfo = (TGetMonitorInfo)GetProcAddress(user32_lib, "GetMonitorInfoA"); } + +#ifdef FEAT_MBYTE + /* If the OS is Windows NT, use wide functions; + * this enables common dialogs input unicode from IME. */ + if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT) + { + pDispatchMessage = DispatchMessageW; + pGetMessage = GetMessageW; + pIsDialogMessage = IsDialogMessageW; + pPeekMessage = PeekMessageW; + } + else + { + pDispatchMessage = DispatchMessageA; + pGetMessage = GetMessageA; + pIsDialogMessage = IsDialogMessageA; + pPeekMessage = PeekMessageA; + } +#endif } /* @@ -1379,7 +1409,8 @@ s_hwnd = CreateWindowEx( WS_EX_MDICHILD, szVimWndClass, "Vim MSWindows GUI", - WS_OVERLAPPEDWINDOW | WS_CHILD | WS_CLIPSIBLINGS | 0xC000, + WS_OVERLAPPEDWINDOW | WS_CHILD + | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | 0xC000, gui_win_x == -1 ? CW_USEDEFAULT : gui_win_x, gui_win_y == -1 ? CW_USEDEFAULT : gui_win_y, 100, /* Any value will do */ @@ -1410,7 +1441,8 @@ * titlebar, it will be reparented below. */ s_hwnd = CreateWindow( szVimWndClass, "Vim MSWindows GUI", - win_socket_id == 0 ? WS_OVERLAPPEDWINDOW : WS_POPUP, + (win_socket_id == 0 ? WS_OVERLAPPEDWINDOW : WS_POPUP) + | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, gui_win_x == -1 ? CW_USEDEFAULT : gui_win_x, gui_win_y == -1 ? CW_USEDEFAULT : gui_win_y, 100, /* Any value will do */ @@ -1573,6 +1605,15 @@ # endif #endif +#ifdef FEAT_EVAL +# if _MSC_VER < 1400 +/* HandleToLong() only exists in compilers that can do 64 bit builds */ +# define HandleToLong(h) ((long)(h)) +# endif + /* set the v:windowid variable */ + set_vim_var_nr(VV_WINDOWID, HandleToLong(s_hwnd)); +#endif + theend: /* Display any pending error messages */ display_errors(); @@ -1620,9 +1661,7 @@ { RECT workarea_rect; int win_width, win_height; - int win_xpos, win_ypos; WINDOWPLACEMENT wndpl; - int workarea_left; /* Try to keep window completely on screen. */ /* Get position of the screen work area. This is the part that is not @@ -1644,9 +1683,6 @@ GetWindowPlacement(s_hwnd, &wndpl); } - win_xpos = wndpl.rcNormalPosition.left; - win_ypos = wndpl.rcNormalPosition.top; - /* compute the size of the outside of the window */ win_width = width + GetSystemMetrics(SM_CXFRAME) * 2; win_height = height + GetSystemMetrics(SM_CYFRAME) * 2 @@ -1656,36 +1692,32 @@ #endif ; - /* There is an inconsistency when using two monitors and Vim is on the - * second (right) one: win_xpos will be the offset from the workarea of - * the left monitor. While with one monitor it's the offset from the - * workarea (including a possible taskbar on the left). Detect the second - * monitor by checking for the left offset to be quite big. */ - if (workarea_rect.left > 300) - workarea_left = 0; - else - workarea_left = workarea_rect.left; + /* The following should take care of keeping Vim on the same monitor, no + * matter if the secondary monitor is left or right of the primary + * monitor. */ + wndpl.rcNormalPosition.right = wndpl.rcNormalPosition.left + win_width; + wndpl.rcNormalPosition.bottom = wndpl.rcNormalPosition.top + win_height; - /* If the window is going off the screen, move it on to the screen. - * win_xpos and win_ypos are relative to the workarea. */ + /* If the window is going off the screen, move it on to the screen. */ if ((direction & RESIZE_HOR) - && workarea_left + win_xpos + win_width > workarea_rect.right) - win_xpos = workarea_rect.right - win_width - workarea_left; + && wndpl.rcNormalPosition.right > workarea_rect.right) + OffsetRect(&wndpl.rcNormalPosition, + workarea_rect.right - wndpl.rcNormalPosition.right, 0); - if ((direction & RESIZE_HOR) && win_xpos < 0) - win_xpos = 0; + if ((direction & RESIZE_HOR) + && wndpl.rcNormalPosition.left < workarea_rect.left) + OffsetRect(&wndpl.rcNormalPosition, + workarea_rect.left - wndpl.rcNormalPosition.left, 0); if ((direction & RESIZE_VERT) - && workarea_rect.top + win_ypos + win_height > workarea_rect.bottom) - win_ypos = workarea_rect.bottom - win_height - workarea_rect.top; + && wndpl.rcNormalPosition.bottom > workarea_rect.bottom) + OffsetRect(&wndpl.rcNormalPosition, + 0, workarea_rect.bottom - wndpl.rcNormalPosition.bottom); - if ((direction & RESIZE_VERT) && win_ypos < 0) - win_ypos = 0; - - wndpl.rcNormalPosition.left = win_xpos; - wndpl.rcNormalPosition.right = win_xpos + win_width; - wndpl.rcNormalPosition.top = win_ypos; - wndpl.rcNormalPosition.bottom = win_ypos + win_height; + if ((direction & RESIZE_VERT) + && wndpl.rcNormalPosition.top < workarea_rect.top) + OffsetRect(&wndpl.rcNormalPosition, + 0, workarea_rect.top - wndpl.rcNormalPosition.top); /* set window position - we should use SetWindowPlacement rather than * SetWindowPos as the MSDN docs say the coord systems returned by @@ -3000,7 +3032,8 @@ char_u *message, char_u *buttons, int dfltbutton, - char_u *textfield) + char_u *textfield, + int ex_cmd) { WORD *p, *pdlgtemplate, *pnumitems; DWORD *dwp; @@ -4188,7 +4221,7 @@ static void dyn_imm_load(void) { - hLibImm = LoadLibrary("imm32.dll"); + hLibImm = vimLoadLib("imm32.dll"); if (hLibImm == NULL) return; diff -Naur vim73.orig/src/gui_w48.c vim73/src/gui_w48.c --- vim73.orig/src/gui_w48.c 2010-07-27 19:46:04.000000000 +0000 +++ vim73/src/gui_w48.c 2012-07-20 20:31:14.280975607 +0000 @@ -328,6 +328,10 @@ static LRESULT _OnImeNotify(HWND hWnd, DWORD dwCommand, DWORD dwData); #endif +#if defined(FEAT_MBYTE) && defined(WIN3264) +static char_u *convert_filter(char_u *s); +#endif + #ifdef DEBUG_PRINT_ERROR /* * Print out the last Windows error message @@ -390,7 +394,7 @@ KillTimer(NULL, idEvent); /* Eat spurious WM_TIMER messages */ - while (PeekMessage(&msg, hwnd, WM_TIMER, WM_TIMER, PM_REMOVE)) + while (pPeekMessage(&msg, hwnd, WM_TIMER, WM_TIMER, PM_REMOVE)) ; if (blink_state == BLINK_ON) @@ -418,7 +422,7 @@ { KillTimer(NULL, blink_timer); /* Eat spurious WM_TIMER messages */ - while (PeekMessage(&msg, s_hwnd, WM_TIMER, WM_TIMER, PM_REMOVE)) + while (pPeekMessage(&msg, s_hwnd, WM_TIMER, WM_TIMER, PM_REMOVE)) ; blink_timer = 0; } @@ -476,7 +480,7 @@ s_timed_out = TRUE; /* Eat spurious WM_TIMER messages */ - while (PeekMessage(&msg, hwnd, WM_TIMER, WM_TIMER, PM_REMOVE)) + while (pPeekMessage(&msg, hwnd, WM_TIMER, WM_TIMER, PM_REMOVE)) ; if (idEvent == s_wait_timer) s_wait_timer = 0; @@ -1411,12 +1415,12 @@ static guicolor_tTable table[] = { {"Black", RGB(0x00, 0x00, 0x00)}, - {"DarkGray", RGB(0x80, 0x80, 0x80)}, - {"DarkGrey", RGB(0x80, 0x80, 0x80)}, + {"DarkGray", RGB(0xA9, 0xA9, 0xA9)}, + {"DarkGrey", RGB(0xA9, 0xA9, 0xA9)}, {"Gray", RGB(0xC0, 0xC0, 0xC0)}, {"Grey", RGB(0xC0, 0xC0, 0xC0)}, - {"LightGray", RGB(0xE0, 0xE0, 0xE0)}, - {"LightGrey", RGB(0xE0, 0xE0, 0xE0)}, + {"LightGray", RGB(0xD3, 0xD3, 0xD3)}, + {"LightGrey", RGB(0xD3, 0xD3, 0xD3)}, {"Gray10", RGB(0x1A, 0x1A, 0x1A)}, {"Grey10", RGB(0x1A, 0x1A, 0x1A)}, {"Gray20", RGB(0x33, 0x33, 0x33)}, @@ -1441,19 +1445,19 @@ {"LightRed", RGB(0xFF, 0xA0, 0xA0)}, {"DarkBlue", RGB(0x00, 0x00, 0x80)}, {"Blue", RGB(0x00, 0x00, 0xFF)}, - {"LightBlue", RGB(0xA0, 0xA0, 0xFF)}, + {"LightBlue", RGB(0xAD, 0xD8, 0xE6)}, {"DarkGreen", RGB(0x00, 0x80, 0x00)}, {"Green", RGB(0x00, 0xFF, 0x00)}, - {"LightGreen", RGB(0xA0, 0xFF, 0xA0)}, + {"LightGreen", RGB(0x90, 0xEE, 0x90)}, {"DarkCyan", RGB(0x00, 0x80, 0x80)}, {"Cyan", RGB(0x00, 0xFF, 0xFF)}, - {"LightCyan", RGB(0xA0, 0xFF, 0xFF)}, + {"LightCyan", RGB(0xE0, 0xFF, 0xFF)}, {"DarkMagenta", RGB(0x80, 0x00, 0x80)}, {"Magenta", RGB(0xFF, 0x00, 0xFF)}, {"LightMagenta", RGB(0xFF, 0xA0, 0xFF)}, {"Brown", RGB(0x80, 0x40, 0x40)}, {"Yellow", RGB(0xFF, 0xFF, 0x00)}, - {"LightYellow", RGB(0xFF, 0xFF, 0xA0)}, + {"LightYellow", RGB(0xFF, 0xFF, 0xE0)}, {"DarkYellow", RGB(0xBB, 0xBB, 0x00)}, {"SeaGreen", RGB(0x2E, 0x8B, 0x57)}, {"Orange", RGB(0xFF, 0xA5, 0x00)}, @@ -1707,7 +1711,7 @@ static char_u k10[] = {K_SPECIAL, 'k', ';', 0}; #endif - GetMessage(&msg, NULL, 0, 0); + pGetMessage(&msg, NULL, 0, 0); #ifdef FEAT_OLE /* Look after OLE Automation commands */ @@ -1718,7 +1722,7 @@ { /* Message can't be ours, forward it. Fixes problem with Ultramon * 3.0.4 */ - DispatchMessage(&msg); + pDispatchMessage(&msg); } else { @@ -1749,14 +1753,14 @@ if (msg.message == WM_USER) { MyTranslateMessage(&msg); - DispatchMessage(&msg); + pDispatchMessage(&msg); return; } #endif #ifdef MSWIN_FIND_REPLACE /* Don't process messages used by the dialog */ - if (s_findrep_hwnd != NULL && IsDialogMessage(s_findrep_hwnd, &msg)) + if (s_findrep_hwnd != NULL && pIsDialogMessage(s_findrep_hwnd, &msg)) { HandleMouseHide(msg.message, msg.lParam); return; @@ -1810,7 +1814,8 @@ * mapped we want to use the mapping instead. */ if (vk == VK_F10 && gui.menu_is_active - && check_map(k10, State, FALSE, TRUE, FALSE) == NULL) + && check_map(k10, State, FALSE, TRUE, FALSE, + NULL, NULL) == NULL) break; #endif if (GetKeyState(VK_SHIFT) & 0x8000) @@ -1924,9 +1929,10 @@ /* Check for : Default effect is to select the menu. When is * mapped we need to stop it here to avoid strange effects (e.g., for the * key-up event) */ - if (vk != VK_F10 || check_map(k10, State, FALSE, TRUE, FALSE) == NULL) + if (vk != VK_F10 || check_map(k10, State, FALSE, TRUE, FALSE, + NULL, NULL) == NULL) #endif - DispatchMessage(&msg); + pDispatchMessage(&msg); } /* @@ -1941,7 +1947,7 @@ MSG msg; if (!s_busy_processing) - while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) + while (pPeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) && !vim_is_input_buf_full()) process_message(); } @@ -2017,7 +2023,7 @@ KillTimer(NULL, s_wait_timer); /* Eat spurious WM_TIMER messages */ - while (PeekMessage(&msg, s_hwnd, WM_TIMER, WM_TIMER, PM_REMOVE)) + while (pPeekMessage(&msg, s_hwnd, WM_TIMER, WM_TIMER, PM_REMOVE)) ; s_wait_timer = 0; } @@ -3273,28 +3279,21 @@ # if defined(FEAT_MBYTE) && defined(WIN3264) /* - * Wide version of convert_filter(). Keep in sync! + * Wide version of convert_filter(). */ static WCHAR * convert_filterW(char_u *s) { - WCHAR *res; - unsigned s_len = (unsigned)STRLEN(s); - unsigned i; + char_u *tmp; + int len; + WCHAR *res; - res = (WCHAR *)alloc((s_len + 3) * sizeof(WCHAR)); - if (res != NULL) - { - for (i = 0; i < s_len; ++i) - if (s[i] == '\t' || s[i] == '\n') - res[i] = '\0'; - else - res[i] = s[i]; - res[s_len] = NUL; - /* Add two extra NULs to make sure it's properly terminated. */ - res[s_len + 1] = NUL; - res[s_len + 2] = NUL; - } + tmp = convert_filter(s); + if (tmp == NULL) + return NULL; + len = (int)STRLEN(s) + 3; + res = enc_to_utf16(tmp, &len); + vim_free(tmp); return res; } diff -Naur vim73.orig/src/gui_x11.c vim73/src/gui_x11.c --- vim73.orig/src/gui_x11.c 2010-08-08 13:05:45.000000000 +0000 +++ vim73/src/gui_x11.c 2012-07-20 20:31:08.337637993 +0000 @@ -2895,6 +2895,11 @@ focus = gui.in_focus; } +#if defined(FEAT_NETBEANS_INTG) + /* Process any queued netbeans messages. */ + netbeans_parse_messages(); +#endif + /* * Don't use gui_mch_update() because then we will spin-lock until a * char arrives, instead we use XtAppProcessEvent() to hang until an diff -Naur vim73.orig/src/gui_xmdlg.c vim73/src/gui_xmdlg.c --- vim73.orig/src/gui_xmdlg.c 2010-06-26 03:53:50.000000000 +0000 +++ vim73/src/gui_xmdlg.c 2012-07-20 20:31:09.267638665 +0000 @@ -688,7 +688,7 @@ do_dialog(VIM_ERROR, (char_u *)_("Error"), (char_u *)_("Invalid font specification"), - (char_u *)_("&Dismiss"), 1, NULL); + (char_u *)_("&Dismiss"), 1, NULL, FALSE); return True; } @@ -807,7 +807,7 @@ do_dialog(VIM_ERROR, (char_u *)_("Error"), (char_u *)_("Invalid font specification"), - (char_u *)_("&Dismiss"), 1, NULL); + (char_u *)_("&Dismiss"), 1, NULL, FALSE); XFreeFontNames(name); } else diff -Naur vim73.orig/src/gui_xmebw.c vim73/src/gui_xmebw.c --- vim73.orig/src/gui_xmebw.c 2010-07-14 14:48:14.000000000 +0000 +++ vim73/src/gui_xmebw.c 2012-07-20 20:31:17.487644573 +0000 @@ -375,11 +375,8 @@ XGetGeometry(dpy, pix, &root, &x, &y, &width, &height, &border, &depth); - if (eb->enhancedbutton.label_location == (int)XmTOP - || eb->enhancedbutton.label_location == (int)XmBOTTOM) - shift = eb->primitive.shadow_thickness / 2; - else - shift = eb->primitive.shadow_thickness / 2; + /* TODO: does the shift depend on label_location somehow? */ + shift = eb->primitive.shadow_thickness / 2; if (shift < 1) shift = 1; diff -Naur vim73.orig/src/hardcopy.c vim73/src/hardcopy.c --- vim73.orig/src/hardcopy.c 2010-07-31 14:10:59.000000000 +0000 +++ vim73/src/hardcopy.c 2012-07-20 20:31:10.217639350 +0000 @@ -1759,18 +1759,25 @@ char *name; struct prt_ps_resource_S *resource; { - char_u buffer[MAXPATHL + 1]; + char_u *buffer; + int retval; - STRCPY(resource->name, name); + buffer = alloc(MAXPATHL + 1); + if (buffer == NULL) + return FALSE; + + vim_strncpy(resource->name, (char_u *)name, 63); /* Look for named resource file in runtimepath */ STRCPY(buffer, "print"); add_pathsep(buffer); - STRCAT(buffer, name); - STRCAT(buffer, ".ps"); + vim_strcat(buffer, (char_u *)name, MAXPATHL); + vim_strcat(buffer, (char_u *)".ps", MAXPATHL); resource->filename[0] = NUL; - return (do_in_runtimepath(buffer, FALSE, prt_resource_name, + retval = (do_in_runtimepath(buffer, FALSE, prt_resource_name, resource->filename) && resource->filename[0] != NUL); + vim_free(buffer); + return retval; } /* PS CR and LF characters have platform independent values */ @@ -2848,15 +2855,33 @@ double right; double top; double bottom; - struct prt_ps_resource_S res_prolog; - struct prt_ps_resource_S res_encoding; + struct prt_ps_resource_S *res_prolog; + struct prt_ps_resource_S *res_encoding; char buffer[256]; char_u *p_encoding; char_u *p; #ifdef FEAT_MBYTE - struct prt_ps_resource_S res_cidfont; - struct prt_ps_resource_S res_cmap; + struct prt_ps_resource_S *res_cidfont; + struct prt_ps_resource_S *res_cmap; #endif + int retval = FALSE; + + res_prolog = (struct prt_ps_resource_S *) + alloc(sizeof(struct prt_ps_resource_S)); + res_encoding = (struct prt_ps_resource_S *) + alloc(sizeof(struct prt_ps_resource_S)); +#ifdef FEAT_MBYTE + res_cidfont = (struct prt_ps_resource_S *) + alloc(sizeof(struct prt_ps_resource_S)); + res_cmap = (struct prt_ps_resource_S *) + alloc(sizeof(struct prt_ps_resource_S)); +#endif + if (res_prolog == NULL || res_encoding == NULL +#ifdef FEAT_MBYTE + || res_cidfont == NULL || res_cmap == NULL +#endif + ) + goto theend; /* * PS DSC Header comments - no PS code! @@ -2932,27 +2957,27 @@ #endif /* Search for external resources VIM supplies */ - if (!prt_find_resource("prolog", &res_prolog)) + if (!prt_find_resource("prolog", res_prolog)) { EMSG(_("E456: Can't find PostScript resource file \"prolog.ps\"")); return FALSE; } - if (!prt_open_resource(&res_prolog)) + if (!prt_open_resource(res_prolog)) return FALSE; - if (!prt_check_resource(&res_prolog, PRT_PROLOG_VERSION)) + if (!prt_check_resource(res_prolog, PRT_PROLOG_VERSION)) return FALSE; #ifdef FEAT_MBYTE if (prt_out_mbyte) { /* Look for required version of multi-byte printing procset */ - if (!prt_find_resource("cidfont", &res_cidfont)) + if (!prt_find_resource("cidfont", res_cidfont)) { EMSG(_("E456: Can't find PostScript resource file \"cidfont.ps\"")); return FALSE; } - if (!prt_open_resource(&res_cidfont)) + if (!prt_open_resource(res_cidfont)) return FALSE; - if (!prt_check_resource(&res_cidfont, PRT_CID_PROLOG_VERSION)) + if (!prt_check_resource(res_cidfont, PRT_CID_PROLOG_VERSION)) return FALSE; } #endif @@ -2968,7 +2993,7 @@ #endif p_encoding = enc_skip(p_penc); if (*p_encoding == NUL - || !prt_find_resource((char *)p_encoding, &res_encoding)) + || !prt_find_resource((char *)p_encoding, res_encoding)) { /* 'printencoding' not set or not supported - find alternate */ #ifdef FEAT_MBYTE @@ -2977,13 +3002,13 @@ p_encoding = enc_skip(p_enc); props = enc_canon_props(p_encoding); if (!(props & ENC_8BIT) - || !prt_find_resource((char *)p_encoding, &res_encoding)) + || !prt_find_resource((char *)p_encoding, res_encoding)) /* 8-bit 'encoding' is not supported */ #endif { /* Use latin1 as default printing encoding */ p_encoding = (char_u *)"latin1"; - if (!prt_find_resource((char *)p_encoding, &res_encoding)) + if (!prt_find_resource((char *)p_encoding, res_encoding)) { EMSG2(_("E456: Can't find PostScript resource file \"%s.ps\""), p_encoding); @@ -2991,7 +3016,7 @@ } } } - if (!prt_open_resource(&res_encoding)) + if (!prt_open_resource(res_encoding)) return FALSE; /* For the moment there are no checks on encoding resource files to * perform */ @@ -3005,13 +3030,13 @@ if (prt_use_courier) { /* Include ASCII range encoding vector */ - if (!prt_find_resource(prt_ascii_encoding, &res_encoding)) + if (!prt_find_resource(prt_ascii_encoding, res_encoding)) { EMSG2(_("E456: Can't find PostScript resource file \"%s.ps\""), prt_ascii_encoding); return FALSE; } - if (!prt_open_resource(&res_encoding)) + if (!prt_open_resource(res_encoding)) return FALSE; /* For the moment there are no checks on encoding resource files to * perform */ @@ -3034,44 +3059,44 @@ if (prt_out_mbyte && prt_custom_cmap) { /* Find user supplied CMap */ - if (!prt_find_resource(prt_cmap, &res_cmap)) + if (!prt_find_resource(prt_cmap, res_cmap)) { EMSG2(_("E456: Can't find PostScript resource file \"%s.ps\""), prt_cmap); return FALSE; } - if (!prt_open_resource(&res_cmap)) + if (!prt_open_resource(res_cmap)) return FALSE; } #endif /* List resources supplied */ - STRCPY(buffer, res_prolog.title); + STRCPY(buffer, res_prolog->title); STRCAT(buffer, " "); - STRCAT(buffer, res_prolog.version); + STRCAT(buffer, res_prolog->version); prt_dsc_resources("DocumentSuppliedResources", "procset", buffer); #ifdef FEAT_MBYTE if (prt_out_mbyte) { - STRCPY(buffer, res_cidfont.title); + STRCPY(buffer, res_cidfont->title); STRCAT(buffer, " "); - STRCAT(buffer, res_cidfont.version); + STRCAT(buffer, res_cidfont->version); prt_dsc_resources(NULL, "procset", buffer); if (prt_custom_cmap) { - STRCPY(buffer, res_cmap.title); + STRCPY(buffer, res_cmap->title); STRCAT(buffer, " "); - STRCAT(buffer, res_cmap.version); + STRCAT(buffer, res_cmap->version); prt_dsc_resources(NULL, "cmap", buffer); } } if (!prt_out_mbyte || prt_use_courier) #endif { - STRCPY(buffer, res_encoding.title); + STRCPY(buffer, res_encoding->title); STRCAT(buffer, " "); - STRCAT(buffer, res_encoding.version); + STRCAT(buffer, res_encoding->version); prt_dsc_resources(NULL, "encoding", buffer); } prt_dsc_requirements(prt_duplex, prt_tumble, prt_collate, @@ -3114,15 +3139,15 @@ prt_dsc_noarg("BeginProlog"); /* Add required procsets - NOTE: order is important! */ - if (!prt_add_resource(&res_prolog)) + if (!prt_add_resource(res_prolog)) return FALSE; #ifdef FEAT_MBYTE if (prt_out_mbyte) { /* Add CID font procset, and any user supplied CMap */ - if (!prt_add_resource(&res_cidfont)) + if (!prt_add_resource(res_cidfont)) return FALSE; - if (prt_custom_cmap && !prt_add_resource(&res_cmap)) + if (prt_custom_cmap && !prt_add_resource(res_cmap)) return FALSE; } #endif @@ -3132,7 +3157,7 @@ #endif /* There will be only one Roman font encoding to be included in the PS * file. */ - if (!prt_add_resource(&res_encoding)) + if (!prt_add_resource(res_encoding)) return FALSE; prt_dsc_noarg("EndProlog"); @@ -3248,7 +3273,17 @@ prt_dsc_noarg("EndSetup"); /* Fail if any problems writing out to the PS file */ - return !prt_file_error; + retval = !prt_file_error; + +theend: + vim_free(res_prolog); + vim_free(res_encoding); +#ifdef FEAT_MBYTE + vim_free(res_cidfont); + vim_free(res_cmap); +#endif + + return retval; } void diff -Naur vim73.orig/src/if_cscope.c vim73/src/if_cscope.c --- vim73.orig/src/if_cscope.c 2010-07-25 14:32:31.000000000 +0000 +++ vim73/src/if_cscope.c 2012-07-20 20:31:11.340973493 +0000 @@ -13,16 +13,10 @@ #if defined(FEAT_CSCOPE) || defined(PROTO) -#include -#include -#include #include #include #if defined(UNIX) # include -#else - /* not UNIX, must be WIN32 */ -# include "vimio.h" #endif #include "if_cscope.h" @@ -1274,9 +1268,7 @@ { win_split(postponed_split > 0 ? postponed_split : 0, postponed_split_flags); -# ifdef FEAT_SCROLLBIND - curwin->w_p_scb = FALSE; -# endif + RESET_BINDING(curwin); postponed_split = 0; } # endif @@ -1353,7 +1345,7 @@ " g: Find this definition\n" " i: Find files #including this file\n" " s: Find this C symbol\n" - " t: Find assignments to\n")); + " t: Find this text string\n")); cmdp++; } @@ -1420,17 +1412,15 @@ { short i, j; #ifndef UNIX - HANDLE hFile; BY_HANDLE_FILE_INFORMATION bhfi; - vim_memset(&bhfi, 0, sizeof(bhfi)); /* On windows 9x GetFileInformationByHandle doesn't work, so skip it */ if (!mch_windows95()) { - hFile = CreateFile(fname, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) + switch (win32_fileinfo(fname, &bhfi)) { + case FILEINFO_ENC_FAIL: /* enc_to_utf16() failed */ + case FILEINFO_READ_FAIL: /* CreateFile() failed */ if (p_csverbose) { char *cant_msg = _("E625: cannot open cscope database: %s"); @@ -1446,15 +1436,12 @@ (void)EMSG2(cant_msg, fname); } return -1; - } - if (!GetFileInformationByHandle(hFile, &bhfi)) - { - CloseHandle(hFile); + + case FILEINFO_INFO_FAIL: /* GetFileInformationByHandle() failed */ if (p_csverbose) (void)EMSG(_("E626: cannot get cscope database information")); return -1; } - CloseHandle(hFile); } #endif @@ -1664,7 +1651,7 @@ /* * PRIVATE: cs_make_vim_style_matches * - * convert the cscope output into into a ctags style entry (as might be found + * convert the cscope output into a ctags style entry (as might be found * in a ctags tags file). there's one catch though: cscope doesn't tell you * the type of the tag you are looking for. for example, in Darren Hiebert's * ctags (the one that comes with vim), #define's use a line number to find the @@ -2484,42 +2471,61 @@ */ static char * cs_resolve_file(i, name) - int i; + int i; char *name; { - char *fullname; - int len; + char *fullname; + int len; + char_u *csdir = NULL; /* - * ppath is freed when we destroy the cscope connection. - * fullname is freed after cs_make_vim_style_matches, after it's been - * copied into the tag buffer used by vim + * Ppath is freed when we destroy the cscope connection. + * Fullname is freed after cs_make_vim_style_matches, after it's been + * copied into the tag buffer used by Vim. */ len = (int)(strlen(name) + 2); if (csinfo[i].ppath != NULL) len += (int)strlen(csinfo[i].ppath); + else if (p_csre && csinfo[i].fname != NULL) + { + /* If 'cscoperelative' is set and ppath is not set, use cscope.out + * path in path resolution. */ + csdir = alloc(MAXPATHL); + if (csdir != NULL) + { + vim_strncpy(csdir, (char_u *)csinfo[i].fname, + gettail((char_u *)csinfo[i].fname) - 1 - (char_u *)csinfo[i].fname); + len += (int)STRLEN(csdir); + } + } if ((fullname = (char *)alloc(len)) == NULL) return NULL; - /* - * note/example: this won't work if the cscope output already starts + /* Note/example: this won't work if the cscope output already starts * "../.." and the prefix path is also "../..". if something like this - * happens, you are screwed up and need to fix how you're using cscope. - */ - if (csinfo[i].ppath != NULL && - (strncmp(name, csinfo[i].ppath, strlen(csinfo[i].ppath)) != 0) && - (name[0] != '/') + * happens, you are screwed up and need to fix how you're using cscope. */ + if (csinfo[i].ppath != NULL + && (strncmp(name, csinfo[i].ppath, strlen(csinfo[i].ppath)) != 0) + && (name[0] != '/') #ifdef WIN32 - && name[0] != '\\' && name[1] != ':' + && name[0] != '\\' && name[1] != ':' #endif - ) + ) (void)sprintf(fullname, "%s/%s", csinfo[i].ppath, name); + else if (csdir != NULL && csinfo[i].fname != NULL && STRLEN(csdir) > 0) + { + /* Check for csdir to be non empty to avoid empty path concatenated to + * cscope output. TODO: avoid the unnecessary alloc/free of fullname. */ + vim_free(fullname); + fullname = (char *)concat_fnames(csdir, (char_u *)name, TRUE); + } else (void)sprintf(fullname, "%s", name); + vim_free(csdir); return fullname; -} /* cs_resolve_file */ +} /* diff -Naur vim73.orig/src/if_lua.c vim73/src/if_lua.c --- vim73.orig/src/if_lua.c 2010-08-12 20:12:04.000000000 +0000 +++ vim73/src/if_lua.c 2012-07-20 20:31:17.324311122 +0000 @@ -1,4 +1,4 @@ -/* vi:set ts=8 sts=4 sw=4: +/* vi:set ts=8 sts=4 sw=4 noet: * * VIM - Vi IMproved by Bram Moolenaar * @@ -9,12 +9,11 @@ * See README.txt for an overview of the Vim source code. */ -#include -#include +#include "vim.h" + #include #include #include -#include "vim.h" /* Only do the following when the feature is enabled. Needed for "make * depend". */ @@ -22,15 +21,33 @@ #define LUAVIM_CHUNKNAME "vim chunk" #define LUAVIM_NAME "vim" +#define LUAVIM_EVALNAME "luaeval" +#define LUAVIM_EVALHEADER "local _A=select(1,...) return " typedef buf_T *luaV_Buffer; typedef win_T *luaV_Window; +typedef dict_T *luaV_Dict; +typedef list_T *luaV_List; typedef void (*msgfunc_T)(char_u *); +static const char LUAVIM_DICT[] = "dict"; +static const char LUAVIM_LIST[] = "list"; static const char LUAVIM_BUFFER[] = "buffer"; static const char LUAVIM_WINDOW[] = "window"; static const char LUAVIM_FREE[] = "luaV_free"; +static const char LUAVIM_LUAEVAL[] = "luaV_luaeval"; +static const char LUAVIM_SETREF[] = "luaV_setref"; +/* most functions are closures with a cache table as first upvalue; + * get/setudata manage references to vim userdata in cache table through + * object pointers (light userdata) */ +#define luaV_getudata(L, v) \ + lua_pushlightuserdata((L), (void *) (v)); \ + lua_rawget((L), lua_upvalueindex(1)) +#define luaV_setudata(L, v) \ + lua_pushlightuserdata((L), (void *) (v)); \ + lua_pushvalue((L), -2); \ + lua_rawset((L), lua_upvalueindex(1)) #define luaV_getfield(L, s) \ lua_pushlightuserdata((L), (void *)(s)); \ lua_rawget((L), LUA_REGISTRYINDEX) @@ -39,6 +56,15 @@ #define luaV_msg(L) luaV_msgfunc((L), (msgfunc_T) msg) #define luaV_emsg(L) luaV_msgfunc((L), (msgfunc_T) emsg) +static luaV_List *luaV_pushlist (lua_State *L, list_T *lis); +static luaV_Dict *luaV_pushdict (lua_State *L, dict_T *dic); + +#if LUA_VERSION_NUM <= 501 +#define luaV_openlib(L, l, n) luaL_openlib(L, NULL, l, n) +#define luaL_typeerror luaL_typerror +#else +#define luaV_openlib luaL_setfuncs +#endif #ifdef DYNAMIC_LUA @@ -49,38 +75,61 @@ # define symbol_from_dll dlsym # define close_dll dlclose #else -# define load_dll LoadLibrary +# define load_dll vimLoadLib # define symbol_from_dll GetProcAddress # define close_dll FreeLibrary #endif /* lauxlib */ +#if LUA_VERSION_NUM <= 501 #define luaL_register dll_luaL_register +#define luaL_prepbuffer dll_luaL_prepbuffer +#define luaL_openlib dll_luaL_openlib #define luaL_typerror dll_luaL_typerror +#define luaL_loadfile dll_luaL_loadfile +#define luaL_loadbuffer dll_luaL_loadbuffer +#else +#define luaL_prepbuffsize dll_luaL_prepbuffsize +#define luaL_setfuncs dll_luaL_setfuncs +#define luaL_loadfilex dll_luaL_loadfilex +#define luaL_loadbufferx dll_luaL_loadbufferx +#define luaL_argerror dll_luaL_argerror +#endif +#define luaL_checkany dll_luaL_checkany #define luaL_checklstring dll_luaL_checklstring #define luaL_checkinteger dll_luaL_checkinteger #define luaL_optinteger dll_luaL_optinteger #define luaL_checktype dll_luaL_checktype #define luaL_error dll_luaL_error -#define luaL_loadfile dll_luaL_loadfile -#define luaL_loadbuffer dll_luaL_loadbuffer #define luaL_newstate dll_luaL_newstate #define luaL_buffinit dll_luaL_buffinit -#define luaL_prepbuffer dll_luaL_prepbuffer #define luaL_addlstring dll_luaL_addlstring #define luaL_pushresult dll_luaL_pushresult /* lua */ +#if LUA_VERSION_NUM <= 501 +#define lua_tonumber dll_lua_tonumber +#define lua_tointeger dll_lua_tointeger +#define lua_call dll_lua_call +#define lua_pcall dll_lua_pcall +#else +#define lua_tonumberx dll_lua_tonumberx +#define lua_tointegerx dll_lua_tointegerx +#define lua_callk dll_lua_callk +#define lua_pcallk dll_lua_pcallk +#define lua_getglobal dll_lua_getglobal +#define lua_setglobal dll_lua_setglobal +#endif +#define lua_typename dll_lua_typename #define lua_close dll_lua_close #define lua_gettop dll_lua_gettop #define lua_settop dll_lua_settop #define lua_pushvalue dll_lua_pushvalue #define lua_replace dll_lua_replace +#define lua_remove dll_lua_remove #define lua_isnumber dll_lua_isnumber #define lua_isstring dll_lua_isstring #define lua_type dll_lua_type #define lua_rawequal dll_lua_rawequal -#define lua_tonumber dll_lua_tonumber -#define lua_tointeger dll_lua_tointeger #define lua_toboolean dll_lua_toboolean #define lua_tolstring dll_lua_tolstring #define lua_touserdata dll_lua_touserdata @@ -95,6 +144,7 @@ #define lua_pushlightuserdata dll_lua_pushlightuserdata #define lua_getfield dll_lua_getfield #define lua_rawget dll_lua_rawget +#define lua_rawgeti dll_lua_rawgeti #define lua_createtable dll_lua_createtable #define lua_newuserdata dll_lua_newuserdata #define lua_getmetatable dll_lua_getmetatable @@ -102,8 +152,7 @@ #define lua_rawset dll_lua_rawset #define lua_rawseti dll_lua_rawseti #define lua_setmetatable dll_lua_setmetatable -#define lua_call dll_lua_call -#define lua_pcall dll_lua_pcall +#define lua_next dll_lua_next /* libs */ #define luaopen_base dll_luaopen_base #define luaopen_table dll_luaopen_table @@ -116,32 +165,57 @@ #define luaL_openlibs dll_luaL_openlibs /* lauxlib */ +#if LUA_VERSION_NUM <= 501 void (*dll_luaL_register) (lua_State *L, const char *libname, const luaL_Reg *l); +char *(*dll_luaL_prepbuffer) (luaL_Buffer *B); +void (*dll_luaL_openlib) (lua_State *L, const char *libname, const luaL_Reg *l, int nup); int (*dll_luaL_typerror) (lua_State *L, int narg, const char *tname); +int (*dll_luaL_loadfile) (lua_State *L, const char *filename); +int (*dll_luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, const char *name); +#else +char *(*dll_luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); +void (*dll_luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); +int (*dll_luaL_loadfilex) (lua_State *L, const char *filename, const char *mode); +int (*dll_luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode); +int (*dll_luaL_argerror) (lua_State *L, int numarg, const char *extramsg); +#endif +void (*dll_luaL_checkany) (lua_State *L, int narg); const char *(*dll_luaL_checklstring) (lua_State *L, int numArg, size_t *l); lua_Integer (*dll_luaL_checkinteger) (lua_State *L, int numArg); lua_Integer (*dll_luaL_optinteger) (lua_State *L, int nArg, lua_Integer def); void (*dll_luaL_checktype) (lua_State *L, int narg, int t); int (*dll_luaL_error) (lua_State *L, const char *fmt, ...); -int (*dll_luaL_loadfile) (lua_State *L, const char *filename); -int (*dll_luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, const char *name); lua_State *(*dll_luaL_newstate) (void); void (*dll_luaL_buffinit) (lua_State *L, luaL_Buffer *B); -char *(*dll_luaL_prepbuffer) (luaL_Buffer *B); void (*dll_luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); void (*dll_luaL_pushresult) (luaL_Buffer *B); /* lua */ +#if LUA_VERSION_NUM <= 501 +lua_Number (*dll_lua_tonumber) (lua_State *L, int idx); +lua_Integer (*dll_lua_tointeger) (lua_State *L, int idx); +void (*dll_lua_call) (lua_State *L, int nargs, int nresults); +int (*dll_lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); +#else +lua_Number (*dll_lua_tonumberx) (lua_State *L, int idx, int *isnum); +lua_Integer (*dll_lua_tointegerx) (lua_State *L, int idx, int *isnum); +void (*dll_lua_callk) (lua_State *L, int nargs, int nresults, int ctx, + lua_CFunction k); +int (*dll_lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, + int ctx, lua_CFunction k); +void (*dll_lua_getglobal) (lua_State *L, const char *var); +void (*dll_lua_setglobal) (lua_State *L, const char *var); +#endif +const char *(*dll_lua_typename) (lua_State *L, int tp); void (*dll_lua_close) (lua_State *L); int (*dll_lua_gettop) (lua_State *L); void (*dll_lua_settop) (lua_State *L, int idx); void (*dll_lua_pushvalue) (lua_State *L, int idx); void (*dll_lua_replace) (lua_State *L, int idx); +void (*dll_lua_remove) (lua_State *L, int idx); int (*dll_lua_isnumber) (lua_State *L, int idx); int (*dll_lua_isstring) (lua_State *L, int idx); int (*dll_lua_type) (lua_State *L, int idx); int (*dll_lua_rawequal) (lua_State *L, int idx1, int idx2); -lua_Number (*dll_lua_tonumber) (lua_State *L, int idx); -lua_Integer (*dll_lua_tointeger) (lua_State *L, int idx); int (*dll_lua_toboolean) (lua_State *L, int idx); const char *(*dll_lua_tolstring) (lua_State *L, int idx, size_t *len); void *(*dll_lua_touserdata) (lua_State *L, int idx); @@ -156,6 +230,7 @@ void (*dll_lua_pushlightuserdata) (lua_State *L, void *p); void (*dll_lua_getfield) (lua_State *L, int idx, const char *k); void (*dll_lua_rawget) (lua_State *L, int idx); +void (*dll_lua_rawgeti) (lua_State *L, int idx, int n); void (*dll_lua_createtable) (lua_State *L, int narr, int nrec); void *(*dll_lua_newuserdata) (lua_State *L, size_t sz); int (*dll_lua_getmetatable) (lua_State *L, int objindex); @@ -163,8 +238,7 @@ void (*dll_lua_rawset) (lua_State *L, int idx); void (*dll_lua_rawseti) (lua_State *L, int idx, int n); int (*dll_lua_setmetatable) (lua_State *L, int objindex); -void (*dll_lua_call) (lua_State *L, int nargs, int nresults); -int (*dll_lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); +int (*dll_lua_next) (lua_State *L, int idx); /* libs */ int (*dll_luaopen_base) (lua_State *L); int (*dll_luaopen_table) (lua_State *L); @@ -184,32 +258,55 @@ static const luaV_Reg luaV_dll[] = { /* lauxlib */ +#if LUA_VERSION_NUM <= 501 {"luaL_register", (luaV_function) &dll_luaL_register}, + {"luaL_prepbuffer", (luaV_function) &dll_luaL_prepbuffer}, + {"luaL_openlib", (luaV_function) &dll_luaL_openlib}, {"luaL_typerror", (luaV_function) &dll_luaL_typerror}, + {"luaL_loadfile", (luaV_function) &dll_luaL_loadfile}, + {"luaL_loadbuffer", (luaV_function) &dll_luaL_loadbuffer}, +#else + {"luaL_prepbuffsize", (luaV_function) &dll_luaL_prepbuffsize}, + {"luaL_setfuncs", (luaV_function) &dll_luaL_setfuncs}, + {"luaL_loadfilex", (luaV_function) &dll_luaL_loadfilex}, + {"luaL_loadbufferx", (luaV_function) &dll_luaL_loadbufferx}, + {"luaL_argerror", (luaV_function) &dll_luaL_argerror}, +#endif + {"luaL_checkany", (luaV_function) &dll_luaL_checkany}, {"luaL_checklstring", (luaV_function) &dll_luaL_checklstring}, {"luaL_checkinteger", (luaV_function) &dll_luaL_checkinteger}, {"luaL_optinteger", (luaV_function) &dll_luaL_optinteger}, {"luaL_checktype", (luaV_function) &dll_luaL_checktype}, {"luaL_error", (luaV_function) &dll_luaL_error}, - {"luaL_loadfile", (luaV_function) &dll_luaL_loadfile}, - {"luaL_loadbuffer", (luaV_function) &dll_luaL_loadbuffer}, {"luaL_newstate", (luaV_function) &dll_luaL_newstate}, {"luaL_buffinit", (luaV_function) &dll_luaL_buffinit}, - {"luaL_prepbuffer", (luaV_function) &dll_luaL_prepbuffer}, {"luaL_addlstring", (luaV_function) &dll_luaL_addlstring}, {"luaL_pushresult", (luaV_function) &dll_luaL_pushresult}, /* lua */ +#if LUA_VERSION_NUM <= 501 + {"lua_tonumber", (luaV_function) &dll_lua_tonumber}, + {"lua_tointeger", (luaV_function) &dll_lua_tointeger}, + {"lua_call", (luaV_function) &dll_lua_call}, + {"lua_pcall", (luaV_function) &dll_lua_pcall}, +#else + {"lua_tonumberx", (luaV_function) &dll_lua_tonumberx}, + {"lua_tointegerx", (luaV_function) &dll_lua_tointegerx}, + {"lua_callk", (luaV_function) &dll_lua_callk}, + {"lua_pcallk", (luaV_function) &dll_lua_pcallk}, + {"lua_getglobal", (luaV_function) &dll_lua_getglobal}, + {"lua_setglobal", (luaV_function) &dll_lua_setglobal}, +#endif + {"lua_typename", (luaV_function) &dll_lua_typename}, {"lua_close", (luaV_function) &dll_lua_close}, {"lua_gettop", (luaV_function) &dll_lua_gettop}, {"lua_settop", (luaV_function) &dll_lua_settop}, {"lua_pushvalue", (luaV_function) &dll_lua_pushvalue}, {"lua_replace", (luaV_function) &dll_lua_replace}, + {"lua_remove", (luaV_function) &dll_lua_remove}, {"lua_isnumber", (luaV_function) &dll_lua_isnumber}, {"lua_isstring", (luaV_function) &dll_lua_isstring}, {"lua_type", (luaV_function) &dll_lua_type}, {"lua_rawequal", (luaV_function) &dll_lua_rawequal}, - {"lua_tonumber", (luaV_function) &dll_lua_tonumber}, - {"lua_tointeger", (luaV_function) &dll_lua_tointeger}, {"lua_toboolean", (luaV_function) &dll_lua_toboolean}, {"lua_tolstring", (luaV_function) &dll_lua_tolstring}, {"lua_touserdata", (luaV_function) &dll_lua_touserdata}, @@ -224,6 +321,7 @@ {"lua_pushlightuserdata", (luaV_function) &dll_lua_pushlightuserdata}, {"lua_getfield", (luaV_function) &dll_lua_getfield}, {"lua_rawget", (luaV_function) &dll_lua_rawget}, + {"lua_rawgeti", (luaV_function) &dll_lua_rawgeti}, {"lua_createtable", (luaV_function) &dll_lua_createtable}, {"lua_newuserdata", (luaV_function) &dll_lua_newuserdata}, {"lua_getmetatable", (luaV_function) &dll_lua_getmetatable}, @@ -231,8 +329,7 @@ {"lua_rawset", (luaV_function) &dll_lua_rawset}, {"lua_rawseti", (luaV_function) &dll_lua_rawseti}, {"lua_setmetatable", (luaV_function) &dll_lua_setmetatable}, - {"lua_call", (luaV_function) &dll_lua_call}, - {"lua_pcall", (luaV_function) &dll_lua_pcall}, + {"lua_next", (luaV_function) &dll_lua_next}, /* libs */ {"luaopen_base", (luaV_function) &dll_luaopen_base}, {"luaopen_table", (luaV_function) &dll_luaopen_table}, @@ -292,6 +389,16 @@ #endif /* DYNAMIC_LUA */ +#if LUA_VERSION_NUM > 501 + static int +luaL_typeerror (lua_State *L, int narg, const char *tname) +{ + const char *msg = lua_pushfstring(L, "%s expected, got %s", + tname, luaL_typename(L, narg)); + return luaL_argerror(L, narg, msg); +} +#endif + /* ======= Internal ======= */ @@ -325,17 +432,35 @@ } static void * +luaV_checkcache(lua_State *L, void *p) +{ + luaV_getudata(L, p); + if (lua_isnil(L, -1)) luaL_error(L, "invalid object"); + lua_pop(L, 1); + return p; +} + +#define luaV_unbox(L,luatyp,ud) (*((luatyp *) lua_touserdata((L),(ud)))) + +#define luaV_checkvalid(L,luatyp,ud) \ + luaV_checkcache((L), (void *) luaV_unbox((L),luatyp,(ud))) + + static void * luaV_checkudata(lua_State *L, int ud, const char *tname) { void *p = luaV_toudata(L, ud, tname); - if (p == NULL) luaL_typerror(L, ud, tname); + if (p == NULL) luaL_typeerror(L, ud, tname); return p; } static void luaV_pushtypval(lua_State *L, typval_T *tv) { - if (tv == NULL) luaL_error(L, "null type"); + if (tv == NULL) + { + lua_pushnil(L); + return; + } switch (tv->v_type) { case VAR_STRING: @@ -349,68 +474,70 @@ lua_pushnumber(L, (lua_Number) tv->vval.v_float); break; #endif - case VAR_LIST: { - list_T *l = tv->vval.v_list; + case VAR_LIST: + luaV_pushlist(L, tv->vval.v_list); + break; + case VAR_DICT: + luaV_pushdict(L, tv->vval.v_dict); + break; + default: + lua_pushnil(L); + } +} - if (l != NULL) +/* converts lua value at 'pos' to typval 'tv' */ + static void +luaV_totypval (lua_State *L, int pos, typval_T *tv) +{ + switch(lua_type(L, pos)) { + case LUA_TBOOLEAN: + tv->v_type = VAR_NUMBER; + tv->vval.v_number = (varnumber_T) lua_toboolean(L, pos); + break; + case LUA_TSTRING: + tv->v_type = VAR_STRING; + tv->vval.v_string = vim_strsave((char_u *) lua_tostring(L, pos)); + break; + case LUA_TNUMBER: +#ifdef FEAT_FLOAT + tv->v_type = VAR_FLOAT; + tv->vval.v_float = (float_T) lua_tonumber(L, pos); +#else + tv->v_type = VAR_NUMBER; + tv->vval.v_number = (varnumber_T) lua_tointeger(L, pos); +#endif + break; + case LUA_TUSERDATA: { + void *p = lua_touserdata(L, pos); + if (lua_getmetatable(L, pos)) /* has metatable? */ { - /* check cache */ - lua_pushlightuserdata(L, (void *) l); - lua_rawget(L, LUA_ENVIRONINDEX); - if (lua_isnil(L, -1)) /* not interned? */ + /* check list */ + luaV_getfield(L, LUAVIM_LIST); + if (lua_rawequal(L, -1, -2)) { - listitem_T *li; - int n = 0; - lua_pop(L, 1); /* nil */ - lua_newtable(L); - lua_pushlightuserdata(L, (void *) l); - lua_pushvalue(L, -2); - lua_rawset(L, LUA_ENVIRONINDEX); - for (li = l->lv_first; li != NULL; li = li->li_next) - { - luaV_pushtypval(L, &li->li_tv); - lua_rawseti(L, -2, ++n); - } + tv->v_type = VAR_LIST; + tv->vval.v_list = *((luaV_List *) p); + ++tv->vval.v_list->lv_refcount; + lua_pop(L, 2); /* MTs */ + return; } - } - else lua_pushnil(L); - break; - } - case VAR_DICT: { - dict_T *d = tv->vval.v_dict; - - if (d != NULL) - { - /* check cache */ - lua_pushlightuserdata(L, (void *) d); - lua_rawget(L, LUA_ENVIRONINDEX); - if (lua_isnil(L, -1)) /* not interned? */ + /* check dict */ + luaV_getfield(L, LUAVIM_DICT); + if (lua_rawequal(L, -1, -3)) { - hashtab_T *ht = &d->dv_hashtab; - hashitem_T *hi; - int n = ht->ht_used; /* remaining items */ - lua_pop(L, 1); /* nil */ - lua_newtable(L); - lua_pushlightuserdata(L, (void *) d); - lua_pushvalue(L, -2); - lua_rawset(L, LUA_ENVIRONINDEX); - for (hi = ht->ht_array; n > 0; hi++) - { - if (!HASHITEM_EMPTY(hi)) - { - dictitem_T *di = dict_lookup(hi); - luaV_pushtypval(L, &di->di_tv); - lua_setfield(L, -2, (char *) hi->hi_key); - n--; - } - } + tv->v_type = VAR_DICT; + tv->vval.v_dict = *((luaV_Dict *) p); + ++tv->vval.v_dict->dv_refcount; + lua_pop(L, 3); /* MTs */ + return; } + lua_pop(L, 3); /* MTs */ } - else lua_pushnil(L); break; } default: - luaL_error(L, "invalid type"); + tv->v_type = VAR_NUMBER; + tv->vval.v_number = 0; } } @@ -479,89 +606,372 @@ lua_pop(L, 2); /* original and modified strings */ } +#define luaV_newtype(typ,tname,luatyp,luatname) \ + static luatyp * \ + luaV_new##tname (lua_State *L, typ *obj) \ + { \ + luatyp *o = (luatyp *) lua_newuserdata(L, sizeof(luatyp)); \ + *o = obj; \ + luaV_setudata(L, obj); /* cache[obj] = udata */ \ + luaV_getfield(L, luatname); \ + lua_setmetatable(L, -2); \ + return o; \ + } + +#define luaV_pushtype(typ,tname,luatyp) \ + static luatyp * \ + luaV_push##tname (lua_State *L, typ *obj) \ + { \ + luatyp *o = NULL; \ + if (obj == NULL) \ + lua_pushnil(L); \ + else { \ + luaV_getudata(L, obj); \ + if (lua_isnil(L, -1)) /* not interned? */ \ + { \ + lua_pop(L, 1); \ + o = luaV_new##tname(L, obj); \ + } \ + else \ + o = (luatyp *) lua_touserdata(L, -1); \ + } \ + return o; \ + } + +#define luaV_type_tostring(tname,luatname) \ + static int \ + luaV_##tname##_tostring (lua_State *L) \ + { \ + lua_pushfstring(L, "%s: %p", luatname, lua_touserdata(L, 1)); \ + return 1; \ + } + +/* ======= List type ======= */ + + static luaV_List * +luaV_newlist (lua_State *L, list_T *lis) +{ + luaV_List *l = (luaV_List *) lua_newuserdata(L, sizeof(luaV_List)); + *l = lis; + lis->lv_refcount++; /* reference in Lua */ + luaV_setudata(L, lis); /* cache[lis] = udata */ + luaV_getfield(L, LUAVIM_LIST); + lua_setmetatable(L, -2); + return l; +} + +luaV_pushtype(list_T, list, luaV_List) +luaV_type_tostring(list, LUAVIM_LIST) -/* ======= Buffer type ======= */ + static int +luaV_list_gc (lua_State *L) +{ + list_unref(luaV_unbox(L, luaV_List, 1)); + return 0; +} - static luaV_Buffer * -luaV_newbuffer(lua_State *L, buf_T *buf) + static int +luaV_list_len (lua_State *L) { - luaV_Buffer *b = (luaV_Buffer *) lua_newuserdata(L, sizeof(luaV_Buffer)); - *b = buf; - lua_pushlightuserdata(L, (void *) buf); - lua_pushvalue(L, -2); - lua_rawset(L, LUA_ENVIRONINDEX); /* env[buf] = udata */ - /* to avoid GC, store as key in env */ - lua_pushvalue(L, -1); - lua_pushboolean(L, 1); - lua_rawset(L, LUA_ENVIRONINDEX); /* env[udata] = true */ - /* set metatable */ - luaV_getfield(L, LUAVIM_BUFFER); - lua_setmetatable(L, -2); - return b; + list_T *l = luaV_unbox(L, luaV_List, 1); + lua_pushinteger(L, (l == NULL) ? 0 : (int) l->lv_len); + return 1; } - static luaV_Buffer * -luaV_pushbuffer (lua_State *L, buf_T *buf) + static int +luaV_list_iter (lua_State *L) { - luaV_Buffer *b = NULL; - if (buf == NULL) - lua_pushnil(L); - else { - lua_pushlightuserdata(L, (void *) buf); - lua_rawget(L, LUA_ENVIRONINDEX); - if (lua_isnil(L, -1)) /* not interned? */ + listitem_T *li = (listitem_T *) lua_touserdata(L, lua_upvalueindex(2)); + if (li == NULL) return 0; + luaV_pushtypval(L, &li->li_tv); + lua_pushlightuserdata(L, (void *) li->li_next); + lua_replace(L, lua_upvalueindex(2)); + return 1; +} + + static int +luaV_list_call (lua_State *L) +{ + list_T *l = luaV_unbox(L, luaV_List, 1); + lua_pushvalue(L, lua_upvalueindex(1)); /* pass cache table along */ + lua_pushlightuserdata(L, (void *) l->lv_first); + lua_pushcclosure(L, luaV_list_iter, 2); + return 1; +} + + static int +luaV_list_index (lua_State *L) +{ + list_T *l = luaV_unbox(L, luaV_List, 1); + if (lua_isnumber(L, 2)) /* list item? */ + { + listitem_T *li = list_find(l, (long) luaL_checkinteger(L, 2)); + if (li == NULL) + lua_pushnil(L); + else + luaV_pushtypval(L, &li->li_tv); + } + else if (lua_isstring(L, 2)) /* method? */ + { + const char *s = lua_tostring(L, 2); + if (strncmp(s, "add", 3) == 0 + || strncmp(s, "insert", 6) == 0 + || strncmp(s, "extend", 6) == 0) { - lua_pop(L, 1); - b = luaV_newbuffer(L, buf); + lua_getmetatable(L, 1); + lua_getfield(L, -1, s); } else - b = (luaV_Buffer *) lua_touserdata(L, -1); + lua_pushnil(L); + } + else + lua_pushnil(L); + return 1; +} + + static int +luaV_list_newindex (lua_State *L) +{ + list_T *l = luaV_unbox(L, luaV_List, 1); + long n = (long) luaL_checkinteger(L, 2); + listitem_T *li; + if (l->lv_lock) + luaL_error(L, "list is locked"); + li = list_find(l, n); + if (li == NULL) return 0; + if (lua_isnil(L, 3)) /* remove? */ + { + list_remove(l, li, li); + clear_tv(&li->li_tv); + vim_free(li); } - return b; + else + { + typval_T v; + luaV_totypval(L, 3, &v); + clear_tv(&li->li_tv); + copy_tv(&v, &li->li_tv); + } + return 0; +} + + static int +luaV_list_add (lua_State *L) +{ + luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST); + list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis); + listitem_T *li; + if (l->lv_lock) + luaL_error(L, "list is locked"); + li = listitem_alloc(); + if (li != NULL) + { + typval_T v; + lua_settop(L, 2); + luaV_totypval(L, 2, &v); + list_append_tv(l, &v); + } + lua_settop(L, 1); + return 1; +} + + static int +luaV_list_insert (lua_State *L) +{ + luaV_List *lis = luaV_checkudata(L, 1, LUAVIM_LIST); + list_T *l = (list_T *) luaV_checkcache(L, (void *) *lis); + long pos = luaL_optlong(L, 3, 0); + listitem_T *li = NULL; + typval_T v; + if (l->lv_lock) + luaL_error(L, "list is locked"); + if (pos < l->lv_len) + { + li = list_find(l, pos); + if (li == NULL) + luaL_error(L, "invalid position"); + } + lua_settop(L, 2); + luaV_totypval(L, 2, &v); + list_insert_tv(l, &v, li); + lua_settop(L, 1); + return 1; +} + +static const luaL_Reg luaV_List_mt[] = { + {"__tostring", luaV_list_tostring}, + {"__gc", luaV_list_gc}, + {"__len", luaV_list_len}, + {"__call", luaV_list_call}, + {"__index", luaV_list_index}, + {"__newindex", luaV_list_newindex}, + {"add", luaV_list_add}, + {"insert", luaV_list_insert}, + {NULL, NULL} +}; + + +/* ======= Dict type ======= */ + + static luaV_Dict * +luaV_newdict (lua_State *L, dict_T *dic) +{ + luaV_Dict *d = (luaV_Dict *) lua_newuserdata(L, sizeof(luaV_Dict)); + *d = dic; + dic->dv_refcount++; /* reference in Lua */ + luaV_setudata(L, dic); /* cache[dic] = udata */ + luaV_getfield(L, LUAVIM_DICT); + lua_setmetatable(L, -2); + return d; +} + +luaV_pushtype(dict_T, dict, luaV_Dict) +luaV_type_tostring(dict, LUAVIM_DICT) + + static int +luaV_dict_gc (lua_State *L) +{ + dict_unref(luaV_unbox(L, luaV_Dict, 1)); + return 0; +} + + static int +luaV_dict_len (lua_State *L) +{ + dict_T *d = luaV_unbox(L, luaV_Dict, 1); + lua_pushinteger(L, (d == NULL) ? 0 : (int) d->dv_hashtab.ht_used); + return 1; +} + + static int +luaV_dict_iter (lua_State *L) +{ + hashitem_T *hi = (hashitem_T *) lua_touserdata(L, lua_upvalueindex(2)); + int n = lua_tointeger(L, lua_upvalueindex(3)); + dictitem_T *di; + if (n <= 0) return 0; + while (HASHITEM_EMPTY(hi)) hi++; + di = dict_lookup(hi); + lua_pushstring(L, (char *) hi->hi_key); + luaV_pushtypval(L, &di->di_tv); + lua_pushlightuserdata(L, (void *) (hi + 1)); + lua_replace(L, lua_upvalueindex(2)); + lua_pushinteger(L, n - 1); + lua_replace(L, lua_upvalueindex(3)); + return 2; } -/* Buffer metamethods */ + static int +luaV_dict_call (lua_State *L) +{ + dict_T *d = luaV_unbox(L, luaV_Dict, 1); + hashtab_T *ht = &d->dv_hashtab; + lua_pushvalue(L, lua_upvalueindex(1)); /* pass cache table along */ + lua_pushlightuserdata(L, (void *) ht->ht_array); + lua_pushinteger(L, ht->ht_used); /* # remaining items */ + lua_pushcclosure(L, luaV_dict_iter, 3); + return 1; +} static int -luaV_buffer_tostring(lua_State *L) +luaV_dict_index (lua_State *L) { - lua_pushfstring(L, "%s: %p", LUAVIM_BUFFER, lua_touserdata(L, 1)); + dict_T *d = luaV_unbox(L, luaV_Dict, 1); + char_u *key = (char_u *) luaL_checkstring(L, 2); + dictitem_T *di = dict_find(d, key, -1); + if (di == NULL) + lua_pushnil(L); + else + luaV_pushtypval(L, &di->di_tv); return 1; } static int +luaV_dict_newindex (lua_State *L) +{ + dict_T *d = luaV_unbox(L, luaV_Dict, 1); + char_u *key = (char_u *) luaL_checkstring(L, 2); + dictitem_T *di; + if (d->dv_lock) + luaL_error(L, "dict is locked"); + di = dict_find(d, key, -1); + if (di == NULL) /* non-existing key? */ + { + if (lua_isnil(L, 3)) return 0; + di = dictitem_alloc(key); + if (di == NULL) return 0; + if (dict_add(d, di) == FAIL) + { + vim_free(di); + return 0; + } + } + else + clear_tv(&di->di_tv); + if (lua_isnil(L, 3)) /* remove? */ + { + hashitem_T *hi = hash_find(&d->dv_hashtab, di->di_key); + hash_remove(&d->dv_hashtab, hi); + dictitem_free(di); + } + else { + typval_T v; + luaV_totypval(L, 3, &v); + copy_tv(&v, &di->di_tv); + } + return 0; +} + +static const luaL_Reg luaV_Dict_mt[] = { + {"__tostring", luaV_dict_tostring}, + {"__gc", luaV_dict_gc}, + {"__len", luaV_dict_len}, + {"__call", luaV_dict_call}, + {"__index", luaV_dict_index}, + {"__newindex", luaV_dict_newindex}, + {NULL, NULL} +}; + + +/* ======= Buffer type ======= */ + +luaV_newtype(buf_T, buffer, luaV_Buffer, LUAVIM_BUFFER) +luaV_pushtype(buf_T, buffer, luaV_Buffer) +luaV_type_tostring(buffer, LUAVIM_BUFFER) + + static int luaV_buffer_len(lua_State *L) { - luaV_Buffer *b = lua_touserdata(L, 1); - lua_pushinteger(L, (*b)->b_ml.ml_line_count); + buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1); + lua_pushinteger(L, b->b_ml.ml_line_count); return 1; } static int luaV_buffer_call(lua_State *L) { - luaV_Buffer *b = (luaV_Buffer *) lua_touserdata(L, 1); + buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1); lua_settop(L, 1); - set_curbuf(*b, DOBUF_SPLIT); + set_curbuf(b, DOBUF_SPLIT); return 1; } static int luaV_buffer_index(lua_State *L) { - luaV_Buffer *b = (luaV_Buffer *) lua_touserdata(L, 1); + buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1); linenr_T n = (linenr_T) lua_tointeger(L, 2); - if (n > 0 && n <= (*b)->b_ml.ml_line_count) - luaV_pushline(L, *b, n); + if (n > 0 && n <= b->b_ml.ml_line_count) + luaV_pushline(L, b, n); else if (lua_isstring(L, 2)) { const char *s = lua_tostring(L, 2); if (strncmp(s, "name", 4) == 0) - lua_pushstring(L, (char *) (*b)->b_sfname); + lua_pushstring(L, (char *) b->b_sfname); else if (strncmp(s, "fname", 5) == 0) - lua_pushstring(L, (char *) (*b)->b_ffname); + lua_pushstring(L, (char *) b->b_ffname); else if (strncmp(s, "number", 6) == 0) - lua_pushinteger(L, (*b)->b_fnum); + lua_pushinteger(L, b->b_fnum); /* methods */ else if (strncmp(s, "insert", 6) == 0 || strncmp(s, "next", 4) == 0 @@ -582,17 +992,17 @@ static int luaV_buffer_newindex(lua_State *L) { - luaV_Buffer *b = (luaV_Buffer *) lua_touserdata(L, 1); + buf_T *b = (buf_T *) luaV_checkvalid(L, luaV_Buffer, 1); linenr_T n = (linenr_T) luaL_checkinteger(L, 2); #ifdef HAVE_SANDBOX luaV_checksandbox(L); #endif - if (n < 1 || n > (*b)->b_ml.ml_line_count) + if (n < 1 || n > b->b_ml.ml_line_count) luaL_error(L, "invalid line number"); if (lua_isnil(L, 3)) /* delete line */ { buf_T *buf = curbuf; - curbuf = *b; + curbuf = b; if (u_savedel(n, 1L) == FAIL) { curbuf = buf; @@ -605,7 +1015,7 @@ } else { deleted_lines_mark(n, 1L); - if (*b == curwin->w_buffer) /* fix cursor in current window? */ + if (b == curwin->w_buffer) /* fix cursor in current window? */ { if (curwin->w_cursor.lnum >= n) { @@ -625,7 +1035,7 @@ else if (lua_isstring(L, 3)) /* update line */ { buf_T *buf = curbuf; - curbuf = *b; + curbuf = b; if (u_savesub(n) == FAIL) { curbuf = buf; @@ -638,7 +1048,7 @@ } else changed_bytes(n, 0); curbuf = buf; - if (*b == curwin->w_buffer) + if (b == curwin->w_buffer) check_cursor_col(); } else @@ -649,8 +1059,9 @@ static int luaV_buffer_insert(lua_State *L) { - luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); - linenr_T last = (*b)->b_ml.ml_line_count; + luaV_Buffer *lb = luaV_checkudata(L, 1, LUAVIM_BUFFER); + buf_T *b = (buf_T *) luaV_checkcache(L, (void *) *lb); + linenr_T last = b->b_ml.ml_line_count; linenr_T n = (linenr_T) luaL_optinteger(L, 3, last); buf_T *buf; luaL_checktype(L, 2, LUA_TSTRING); @@ -662,7 +1073,7 @@ if (n > last) n = last; /* insert */ buf = curbuf; - curbuf = *b; + curbuf = b; if (u_save(n, n + 1) == FAIL) { curbuf = buf; @@ -684,7 +1095,8 @@ luaV_buffer_next(lua_State *L) { luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); - luaV_pushbuffer(L, (*b)->b_next); + buf_T *buf = (buf_T *) luaV_checkcache(L, (void *) *b); + luaV_pushbuffer(L, buf->b_next); return 1; } @@ -692,7 +1104,8 @@ luaV_buffer_previous(lua_State *L) { luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); - luaV_pushbuffer(L, (*b)->b_prev); + buf_T *buf = (buf_T *) luaV_checkcache(L, (void *) *b); + luaV_pushbuffer(L, buf->b_prev); return 1; } @@ -700,8 +1113,7 @@ luaV_buffer_isvalid(lua_State *L) { luaV_Buffer *b = luaV_checkudata(L, 1, LUAVIM_BUFFER); - lua_pushlightuserdata(L, (void *) (*b)); - lua_rawget(L, LUA_ENVIRONINDEX); + luaV_getudata(L, *b); lua_pushboolean(L, !lua_isnil(L, -1)); return 1; } @@ -722,78 +1134,36 @@ /* ======= Window type ======= */ - static luaV_Window * -luaV_newwindow(lua_State *L, win_T *win) -{ - luaV_Window *w = (luaV_Window *) lua_newuserdata(L, sizeof(luaV_Window)); - *w = win; - lua_pushlightuserdata(L, (void *) win); - lua_pushvalue(L, -2); - lua_rawset(L, LUA_ENVIRONINDEX); /* env[win] = udata */ - /* to avoid GC, store as key in env */ - lua_pushvalue(L, -1); - lua_pushboolean(L, 1); - lua_rawset(L, LUA_ENVIRONINDEX); /* env[udata] = true */ - /* set metatable */ - luaV_getfield(L, LUAVIM_WINDOW); - lua_setmetatable(L, -2); - return w; -} - - static luaV_Window * -luaV_pushwindow(lua_State *L, win_T *win) -{ - luaV_Window *w = NULL; - if (win == NULL) - lua_pushnil(L); - else { - lua_pushlightuserdata(L, (void *) win); - lua_rawget(L, LUA_ENVIRONINDEX); - if (lua_isnil(L, -1)) /* not interned? */ - { - lua_pop(L, 1); - w = luaV_newwindow(L, win); - } - else w = (luaV_Window *) lua_touserdata(L, -1); - } - return w; -} - -/* Window metamethods */ - - static int -luaV_window_tostring(lua_State *L) -{ - lua_pushfstring(L, "%s: %p", LUAVIM_WINDOW, lua_touserdata(L, 1)); - return 1; -} +luaV_newtype(win_T, window, luaV_Window, LUAVIM_WINDOW) +luaV_pushtype(win_T, window, luaV_Window) +luaV_type_tostring(window, LUAVIM_WINDOW) static int luaV_window_call(lua_State *L) { - luaV_Window *w = (luaV_Window *) lua_touserdata(L, 1); + win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1); lua_settop(L, 1); - win_goto(*w); + win_goto(w); return 1; } static int luaV_window_index(lua_State *L) { - luaV_Window *w = (luaV_Window *) lua_touserdata(L, 1); + win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1); const char *s = luaL_checkstring(L, 2); if (strncmp(s, "buffer", 6) == 0) - luaV_pushbuffer(L, (*w)->w_buffer); + luaV_pushbuffer(L, w->w_buffer); else if (strncmp(s, "line", 4) == 0) - lua_pushinteger(L, (*w)->w_cursor.lnum); + lua_pushinteger(L, w->w_cursor.lnum); else if (strncmp(s, "col", 3) == 0) - lua_pushinteger(L, (*w)->w_cursor.col + 1); + lua_pushinteger(L, w->w_cursor.col + 1); #ifdef FEAT_VERTSPLIT else if (strncmp(s, "width", 5) == 0) - lua_pushinteger(L, W_WIDTH((*w))); + lua_pushinteger(L, W_WIDTH(w)); #endif else if (strncmp(s, "height", 6) == 0) - lua_pushinteger(L, (*w)->w_height); + lua_pushinteger(L, w->w_height); /* methods */ else if (strncmp(s, "next", 4) == 0 || strncmp(s, "previous", 8) == 0 @@ -810,7 +1180,7 @@ static int luaV_window_newindex (lua_State *L) { - luaV_Window *w = (luaV_Window *) lua_touserdata(L, 1); + win_T *w = (win_T *) luaV_checkvalid(L, luaV_Window, 1); const char *s = luaL_checkstring(L, 2); int v = luaL_checkinteger(L, 3); if (strncmp(s, "line", 4) == 0) @@ -818,9 +1188,9 @@ #ifdef HAVE_SANDBOX luaV_checksandbox(L); #endif - if (v < 1 || v > (*w)->w_buffer->b_ml.ml_line_count) + if (v < 1 || v > w->w_buffer->b_ml.ml_line_count) luaL_error(L, "line out of range"); - (*w)->w_cursor.lnum = v; + w->w_cursor.lnum = v; update_screen(VALID); } else if (strncmp(s, "col", 3) == 0) @@ -828,7 +1198,7 @@ #ifdef HAVE_SANDBOX luaV_checksandbox(L); #endif - (*w)->w_cursor.col = v - 1; + w->w_cursor.col = v - 1; update_screen(VALID); } #ifdef FEAT_VERTSPLIT @@ -838,7 +1208,7 @@ #ifdef FEAT_GUI need_mouse_correct = TRUE; #endif - curwin = *w; + curwin = w; win_setwidth(v); curwin = win; } @@ -849,7 +1219,7 @@ #ifdef FEAT_GUI need_mouse_correct = TRUE; #endif - curwin = *w; + curwin = w; win_setheight(v); curwin = win; } @@ -862,7 +1232,8 @@ luaV_window_next(lua_State *L) { luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); - luaV_pushwindow(L, (*w)->w_next); + win_T *win = (win_T *) luaV_checkcache(L, (void *) *w); + luaV_pushwindow(L, win->w_next); return 1; } @@ -870,7 +1241,8 @@ luaV_window_previous(lua_State *L) { luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); - luaV_pushwindow(L, (*w)->w_prev); + win_T *win = (win_T *) luaV_checkcache(L, (void *) *w); + luaV_pushwindow(L, win->w_prev); return 1; } @@ -878,8 +1250,7 @@ luaV_window_isvalid(lua_State *L) { luaV_Window *w = luaV_checkudata(L, 1, LUAVIM_WINDOW); - lua_pushlightuserdata(L, (void *) (*w)); - lua_rawget(L, LUA_ENVIRONINDEX); + luaV_getudata(L, *w); lua_pushboolean(L, !lua_isnil(L, -1)); return 1; } @@ -925,6 +1296,31 @@ } static int +luaV_debug(lua_State *L) +{ + lua_settop(L, 0); + lua_getglobal(L, "vim"); + lua_getfield(L, -1, "eval"); + lua_remove(L, -2); /* vim.eval at position 1 */ + for (;;) + { + const char *input; + size_t l; + lua_pushvalue(L, 1); /* vim.eval */ + lua_pushliteral(L, "input('lua_debug> ')"); + lua_call(L, 1, 1); /* return string */ + input = lua_tolstring(L, -1, &l); + if (l == 0 || strcmp(input, "cont") == 0) + return 0; + msg_putchar('\n'); /* avoid outputting on input line */ + if (luaL_loadbuffer(L, input, l, "=(debug command)") + || lua_pcall(L, 0, 0, 0)) + luaV_emsg(L); + lua_settop(L, 1); /* remove eventual returns, but keep vim.eval */ + } +} + + static int luaV_command(lua_State *L) { do_cmdline_cmd((char_u *) luaL_checkstring(L, 1)); @@ -956,6 +1352,28 @@ } static int +luaV_list(lua_State *L) +{ + list_T *l = list_alloc(); + if (l == NULL) + lua_pushnil(L); + else + luaV_newlist(L, l); + return 1; +} + + static int +luaV_dict(lua_State *L) +{ + dict_T *d = dict_alloc(); + if (d == NULL) + lua_pushnil(L); + else + luaV_newdict(L, d); + return 1; +} + + static int luaV_buffer(lua_State *L) { buf_T *buf; @@ -981,15 +1399,10 @@ break; } } - if (buf == NULL) /* not found? */ - lua_pushnil(L); - else - luaV_pushbuffer(L, buf); } - else { + else buf = (lua_toboolean(L, 1)) ? firstbuf : curbuf; /* first buffer? */ - luaV_pushbuffer(L, buf); - } + luaV_pushbuffer(L, buf); return 1; } @@ -1002,59 +1415,62 @@ int n = lua_tointeger(L, 1); for (win = firstwin; win != NULL; win = win->w_next, n--) if (n == 1) break; - if (win == NULL) /* not found? */ - lua_pushnil(L); - else - luaV_pushwindow(L, win); } - else { + else win = (lua_toboolean(L, 1)) ? firstwin : curwin; /* first window? */ - luaV_pushwindow(L, win); - } + luaV_pushwindow(L, win); return 1; } static int luaV_open(lua_State *L) { - luaV_Buffer *b; char_u *s = NULL; #ifdef HAVE_SANDBOX luaV_checksandbox(L); #endif if (lua_isstring(L, 1)) s = (char_u *) lua_tostring(L, 1); - b = luaV_pushbuffer(L, buflist_new(s, NULL, 1L, BLN_LISTED)); - return 1; -} - - static int -luaV_isbuffer(lua_State *L) -{ - lua_pushboolean(L, luaV_toudata(L, 1, LUAVIM_BUFFER) != NULL); - return 1; -} - - static int -luaV_iswindow(lua_State *L) -{ - lua_pushboolean(L, luaV_toudata(L, 1, LUAVIM_WINDOW) != NULL); + luaV_pushbuffer(L, buflist_new(s, NULL, 1L, BLN_LISTED)); return 1; } -/* for freeing buffer and window objects; lightuserdata as arg */ static int -luaV_free(lua_State *L) +luaV_type(lua_State *L) { - lua_pushvalue(L, 1); /* lightudata */ - lua_rawget(L, LUA_ENVIRONINDEX); - if (!lua_isnil(L, -1)) + luaL_checkany(L, 1); + if (lua_type(L, 1) == LUA_TUSERDATA) /* check vim udata? */ { - lua_pushnil(L); - lua_rawset(L, LUA_ENVIRONINDEX); /* env[udata] = nil */ - lua_pushnil(L); - lua_rawset(L, LUA_ENVIRONINDEX); /* env[lightudata] = nil */ + lua_settop(L, 1); + if (lua_getmetatable(L, 1)) + { + luaV_getfield(L, LUAVIM_LIST); + if (lua_rawequal(L, -1, 2)) + { + lua_pushstring(L, "list"); + return 1; + } + luaV_getfield(L, LUAVIM_DICT); + if (lua_rawequal(L, -1, 2)) + { + lua_pushstring(L, "dict"); + return 1; + } + luaV_getfield(L, LUAVIM_BUFFER); + if (lua_rawequal(L, -1, 2)) + { + lua_pushstring(L, "buffer"); + return 1; + } + luaV_getfield(L, LUAVIM_WINDOW); + if (lua_rawequal(L, -1, 2)) + { + lua_pushstring(L, "window"); + return 1; + } + } } - return 0; + lua_pushstring(L, luaL_typename(L, 1)); /* fallback */ + return 1; } static const luaL_Reg luaV_module[] = { @@ -1062,37 +1478,128 @@ {"eval", luaV_eval}, {"beep", luaV_beep}, {"line", luaV_line}, + {"list", luaV_list}, + {"dict", luaV_dict}, {"buffer", luaV_buffer}, {"window", luaV_window}, {"open", luaV_open}, - {"isbuffer", luaV_isbuffer}, - {"iswindow", luaV_iswindow}, + {"type", luaV_type}, {NULL, NULL} }; +/* for freeing list, dict, buffer and window objects; lightuserdata as arg */ + static int +luaV_free(lua_State *L) +{ + lua_pushnil(L); + luaV_setudata(L, lua_touserdata(L, 1)); + return 0; +} + + static int +luaV_luaeval (lua_State *L) +{ + luaL_Buffer b; + size_t l; + const char *str = lua_tolstring(L, 1, &l); + typval_T *arg = (typval_T *) lua_touserdata(L, 2); + typval_T *rettv = (typval_T *) lua_touserdata(L, 3); + luaL_buffinit(L, &b); + luaL_addlstring(&b, LUAVIM_EVALHEADER, sizeof(LUAVIM_EVALHEADER) - 1); + luaL_addlstring(&b, str, l); + luaL_pushresult(&b); + str = lua_tolstring(L, -1, &l); + if (luaL_loadbuffer(L, str, l, LUAVIM_EVALNAME)) /* compile error? */ + { + luaV_emsg(L); + return 0; + } + luaV_pushtypval(L, arg); + if (lua_pcall(L, 1, 1, 0)) /* running error? */ + { + luaV_emsg(L); + return 0; + } + luaV_totypval(L, -1, rettv); + return 0; +} + + static int +luaV_setref (lua_State *L) +{ + int copyID = lua_tointeger(L, 1); + typval_T tv; + luaV_getfield(L, LUAVIM_LIST); + luaV_getfield(L, LUAVIM_DICT); + lua_pushnil(L); + while (lua_next(L, lua_upvalueindex(1)) != 0) /* traverse cache table */ + { + lua_getmetatable(L, -1); + if (lua_rawequal(L, -1, 2)) /* list? */ + { + tv.v_type = VAR_LIST; + tv.vval.v_list = (list_T *) lua_touserdata(L, 4); /* key */ + } + else if (lua_rawequal(L, -1, 3)) /* dict? */ + { + tv.v_type = VAR_DICT; + tv.vval.v_dict = (dict_T *) lua_touserdata(L, 4); /* key */ + } + lua_pop(L, 2); /* metatable and value */ + set_ref_in_item(&tv, copyID); + } + return 0; +} + static int luaopen_vim(lua_State *L) { - /* set environment */ + /* set cache table */ lua_newtable(L); lua_newtable(L); - lua_pushliteral(L, "v"); + lua_pushstring(L, "v"); lua_setfield(L, -2, "__mode"); - lua_setmetatable(L, -2); - lua_replace(L, LUA_ENVIRONINDEX); + lua_setmetatable(L, -2); /* cache is weak-valued */ /* print */ lua_pushcfunction(L, luaV_print); lua_setglobal(L, "print"); + /* debug.debug */ + lua_getglobal(L, "debug"); + lua_pushcfunction(L, luaV_debug); + lua_setfield(L, -2, "debug"); + lua_pop(L, 1); /* free */ lua_pushlightuserdata(L, (void *) LUAVIM_FREE); - lua_pushcfunction(L, luaV_free); + lua_pushvalue(L, 1); /* cache table */ + lua_pushcclosure(L, luaV_free, 1); + lua_rawset(L, LUA_REGISTRYINDEX); + /* luaeval */ + lua_pushlightuserdata(L, (void *) LUAVIM_LUAEVAL); + lua_pushvalue(L, 1); /* cache table */ + lua_pushcclosure(L, luaV_luaeval, 1); + lua_rawset(L, LUA_REGISTRYINDEX); + /* setref */ + lua_pushlightuserdata(L, (void *) LUAVIM_SETREF); + lua_pushvalue(L, 1); /* cache table */ + lua_pushcclosure(L, luaV_setref, 1); lua_rawset(L, LUA_REGISTRYINDEX); /* register */ + luaV_newmetatable(L, LUAVIM_LIST); + lua_pushvalue(L, 1); + luaV_openlib(L, luaV_List_mt, 1); + luaV_newmetatable(L, LUAVIM_DICT); + lua_pushvalue(L, 1); + luaV_openlib(L, luaV_Dict_mt, 1); luaV_newmetatable(L, LUAVIM_BUFFER); - luaL_register(L, NULL, luaV_Buffer_mt); + lua_pushvalue(L, 1); /* cache table */ + luaV_openlib(L, luaV_Buffer_mt, 1); luaV_newmetatable(L, LUAVIM_WINDOW); - luaL_register(L, NULL, luaV_Window_mt); - luaL_register(L, LUAVIM_NAME, luaV_module); + lua_pushvalue(L, 1); /* cache table */ + luaV_openlib(L, luaV_Window_mt, 1); + lua_newtable(L); /* vim table */ + lua_pushvalue(L, 1); /* cache table */ + luaV_openlib(L, luaV_module, 1); + lua_setglobal(L, LUAVIM_NAME); return 0; } @@ -1123,7 +1630,7 @@ static lua_State *L = NULL; static int -lua_is_open(void) +lua_isopen(void) { return L != NULL; } @@ -1131,7 +1638,7 @@ static int lua_init(void) { - if (L == NULL) + if (!lua_isopen()) { #ifdef DYNAMIC_LUA if (!lua_enabled(TRUE)) @@ -1148,7 +1655,7 @@ void lua_end(void) { - if (L != NULL) + if (lua_isopen()) { lua_close(L); L = NULL; @@ -1191,7 +1698,7 @@ } luaV_setrange(L, eap->line1, eap->line2); luaL_buffinit(L, &b); - luaL_addlstring(&b, "return function(line) ", 22); /* header */ + luaL_addlstring(&b, "return function(line, linenr) ", 30); /* header */ luaL_addlstring(&b, s, strlen(s)); luaL_addlstring(&b, " end", 4); /* footer */ luaL_pushresult(&b); @@ -1208,7 +1715,8 @@ { lua_pushvalue(L, -1); /* function */ luaV_pushline(L, curbuf, l); /* current line as arg */ - if (lua_pcall(L, 1, 1, 0)) + lua_pushinteger(L, l); /* current line number as arg */ + if (lua_pcall(L, 2, 1, 0)) { luaV_emsg(L); break; @@ -1242,23 +1750,36 @@ } } -/* buffer */ +#define luaV_freetype(typ,tname) \ + void \ + lua_##tname##_free(typ *o) \ + { \ + if (!lua_isopen()) return; \ + luaV_getfield(L, LUAVIM_FREE); \ + lua_pushlightuserdata(L, (void *) o); \ + lua_call(L, 1, 0); \ + } + +luaV_freetype(buf_T, buffer) +luaV_freetype(win_T, window) + void -lua_buffer_free(buf_T *buf) +do_luaeval (char_u *str, typval_T *arg, typval_T *rettv) { - if (!lua_is_open()) return; - luaV_getfield(L, LUAVIM_FREE); - lua_pushlightuserdata(L, (void *) buf); - lua_call(L, 1, 0); + lua_init(); + luaV_getfield(L, LUAVIM_LUAEVAL); + lua_pushstring(L, (char *) str); + lua_pushlightuserdata(L, (void *) arg); + lua_pushlightuserdata(L, (void *) rettv); + lua_call(L, 3, 0); } -/* window */ void -lua_window_free(win_T *win) +set_ref_in_lua (int copyID) { - if (!lua_is_open()) return; - luaV_getfield(L, LUAVIM_FREE); - lua_pushlightuserdata(L, (void *) win); + if (!lua_isopen()) return; + luaV_getfield(L, LUAVIM_SETREF); + lua_pushinteger(L, copyID); lua_call(L, 1, 0); } diff -Naur vim73.orig/src/if_mzsch.c vim73/src/if_mzsch.c --- vim73.orig/src/if_mzsch.c 2010-06-26 03:56:17.000000000 +0000 +++ vim73/src/if_mzsch.c 2012-07-20 20:31:14.800975981 +0000 @@ -31,8 +31,6 @@ * depend". */ #if defined(FEAT_MZSCHEME) || defined(PROTO) -#include - /* Base data structures */ #define SCHEME_VIMBUFFERP(obj) SAME_TYPE(SCHEME_TYPE(obj), mz_buffer_type) #define SCHEME_VIMWINDOWP(obj) SAME_TYPE(SCHEME_TYPE(obj), mz_window_type) @@ -556,20 +554,20 @@ if (hMzGC && hMzSch) return OK; - hMzSch = LoadLibrary(sch_dll); - hMzGC = LoadLibrary(gc_dll); + hMzSch = vimLoadLib(sch_dll); + hMzGC = vimLoadLib(gc_dll); - if (!hMzSch) + if (!hMzGC) { if (verbose) - EMSG2(_(e_loadlib), sch_dll); + EMSG2(_(e_loadlib), gc_dll); return FAIL; } - if (!hMzGC) + if (!hMzSch) { if (verbose) - EMSG2(_(e_loadlib), gc_dll); + EMSG2(_(e_loadlib), sch_dll); return FAIL; } @@ -794,62 +792,72 @@ #endif } - void -mzscheme_main(void) +#if MZSCHEME_VERSION_MAJOR >= 500 && defined(WIN32) && defined(USE_THREAD_LOCAL) +static __declspec(thread) void *tls_space; +#endif + +/* + * Since version 4.x precise GC requires trampolined startup. + * Futures and places in version 5.x need it too. + */ +#if defined(MZ_PRECISE_GC) && MZSCHEME_VERSION_MAJOR >= 400 \ + || MZSCHEME_VERSION_MAJOR >= 500 && (defined(MZ_USE_FUTURES) || defined(MZ_USE_PLACES)) +# ifdef DYNAMIC_MZSCHEME +# error Precise GC v.4+ or Racket with futures/places do not support dynamic MzScheme +# endif +# define TRAMPOLINED_MZVIM_STARTUP +#endif + + int +mzscheme_main(int argc, char** argv) { -#if defined(MZ_PRECISE_GC) && MZSCHEME_VERSION_MAJOR >= 400 - /* use trampoline for precise GC in MzScheme >= 4.x */ - scheme_main_setup(TRUE, mzscheme_env_main, 0, NULL); +#if MZSCHEME_VERSION_MAJOR >= 500 && defined(WIN32) && defined(USE_THREAD_LOCAL) + scheme_register_tls_space(&tls_space, 0); +#endif +#ifdef TRAMPOLINED_MZVIM_STARTUP + return scheme_main_setup(TRUE, mzscheme_env_main, argc, argv); #else - mzscheme_env_main(NULL, 0, NULL); + return mzscheme_env_main(NULL, argc, argv); #endif } static int -mzscheme_env_main(Scheme_Env *env, int argc UNUSED, char **argv UNUSED) +mzscheme_env_main(Scheme_Env *env, int argc, char **argv) { - /* neither argument nor return values are used */ -#ifdef MZ_PRECISE_GC -# if MZSCHEME_VERSION_MAJOR < 400 - /* - * Starting from version 4.x, embedding applications must use - * scheme_main_setup/scheme_main_stack_setup trampolines - * rather than setting stack base directly with scheme_set_stack_base - */ + int vim_main_result; +#ifdef TRAMPOLINED_MZVIM_STARTUP + /* Scheme has created the environment for us */ + environment = env; +#else +# ifdef MZ_PRECISE_GC Scheme_Object *dummy = NULL; MZ_GC_DECL_REG(1); MZ_GC_VAR_IN_REG(0, dummy); stack_base = &__gc_var_stack__; # else - /* environment has been created by us by Scheme */ - environment = env; -# endif - /* - * In 4.x, all activities must be performed inside trampoline - * so we are forced to initialise GC immediately - * This can be postponed in 3.x but I see no point in implementing - * a feature which will work in older versions only. - * One would better use conservative GC if he needs dynamic MzScheme - */ - mzscheme_init(); -#else int dummy = 0; stack_base = (void *)&dummy; +# endif #endif - main_loop(FALSE, FALSE); -#if defined(MZ_PRECISE_GC) && MZSCHEME_VERSION_MAJOR < 400 + + /* mzscheme_main is called as a trampoline from main. + * We trampoline into vim_main2 + * Passing argc, argv through from mzscheme_main + */ + vim_main_result = vim_main2(argc, argv); +#if !defined(TRAMPOLINED_MZVIM_STARTUP) && defined(MZ_PRECISE_GC) /* releasing dummy */ MZ_GC_REG(); MZ_GC_UNREG(); #endif - return 0; + return vim_main_result; } static void startup_mzscheme(void) { -#if !defined(MZ_PRECISE_GC) || MZSCHEME_VERSION_MAJOR < 400 +#ifndef TRAMPOLINED_MZVIM_STARTUP scheme_set_stack_base(stack_base, 1); #endif @@ -861,7 +869,7 @@ MZ_REGISTER_STATIC(exn_message); MZ_REGISTER_STATIC(vim_exn); -#if !defined(MZ_PRECISE_GC) || MZSCHEME_VERSION_MAJOR < 400 +#ifndef TRAMPOLINED_MZVIM_STARTUP /* in newer versions of precise GC the initial env has been created */ environment = scheme_basic_env(); #endif @@ -3006,7 +3014,6 @@ MZ_GC_REG(); tmp = scheme_make_struct_names(exn_name, scheme_null, 0, &nc); - assert(nc <= 5); mch_memmove(exn_names, tmp, nc * sizeof(Scheme_Object *)); MZ_GC_CHECK(); diff -Naur vim73.orig/src/if_ole.h vim73/src/if_ole.h --- vim73.orig/src/if_ole.h 2010-05-15 11:04:07.000000000 +0000 +++ vim73/src/if_ole.h 2012-07-20 20:31:11.164306700 +0000 @@ -46,8 +46,11 @@ /* header files for imported files */ #include "oaidl.h" -void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t); -void __RPC_USER MIDL_user_free( void __RPC_FAR * ); +#ifndef __MIDL_user_allocate_free_DEFINED__ +#define __MIDL_user_allocate_free_DEFINED__ + void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t); + void __RPC_USER MIDL_user_free( void __RPC_FAR * ); +#endif #ifndef __IVim_INTERFACE_DEFINED__ #define __IVim_INTERFACE_DEFINED__ diff -Naur vim73.orig/src/if_perl.xs vim73/src/if_perl.xs --- vim73.orig/src/if_perl.xs 2010-07-22 09:33:37.000000000 +0000 +++ vim73/src/if_perl.xs 2012-07-20 20:31:15.314309683 +0000 @@ -106,7 +106,7 @@ #define close_dll dlclose #else #define PERL_PROC FARPROC -#define load_dll LoadLibrary +#define load_dll vimLoadLib #define symbol_from_dll GetProcAddress #define close_dll FreeLibrary #endif @@ -147,7 +147,12 @@ # define Perl_save_int dll_Perl_save_int # define Perl_stack_grow dll_Perl_stack_grow # define Perl_set_context dll_Perl_set_context +# if (PERL_REVISION == 5) && (PERL_VERSION >= 14) +# define Perl_sv_2bool_flags dll_Perl_sv_2bool_flags +# define Perl_xs_apiversion_bootcheck dll_Perl_xs_apiversion_bootcheck +# else # define Perl_sv_2bool dll_Perl_sv_2bool +# endif # define Perl_sv_2iv dll_Perl_sv_2iv # define Perl_sv_2mortal dll_Perl_sv_2mortal # if (PERL_REVISION == 5) && (PERL_VERSION >= 8) @@ -252,7 +257,12 @@ static void (*Perl_save_int)(pTHX_ int*); static SV** (*Perl_stack_grow)(pTHX_ SV**, SV**p, int); static SV** (*Perl_set_context)(void*); +#if (PERL_REVISION == 5) && (PERL_VERSION >= 14) +static bool (*Perl_sv_2bool_flags)(pTHX_ SV*, I32); +static void (*Perl_xs_apiversion_bootcheck)(pTHX_ SV *module, const char *api_p, STRLEN api_len); +#else static bool (*Perl_sv_2bool)(pTHX_ SV*); +#endif static IV (*Perl_sv_2iv)(pTHX_ SV*); static SV* (*Perl_sv_2mortal)(pTHX_ SV*); #if (PERL_REVISION == 5) && (PERL_VERSION >= 8) @@ -360,7 +370,12 @@ {"Perl_save_int", (PERL_PROC*)&Perl_save_int}, {"Perl_stack_grow", (PERL_PROC*)&Perl_stack_grow}, {"Perl_set_context", (PERL_PROC*)&Perl_set_context}, +#if (PERL_REVISION == 5) && (PERL_VERSION >= 14) + {"Perl_sv_2bool_flags", (PERL_PROC*)&Perl_sv_2bool_flags}, + {"Perl_xs_apiversion_bootcheck",(PERL_PROC*)&Perl_xs_apiversion_bootcheck}, +#else {"Perl_sv_2bool", (PERL_PROC*)&Perl_sv_2bool}, +#endif {"Perl_sv_2iv", (PERL_PROC*)&Perl_sv_2iv}, {"Perl_sv_2mortal", (PERL_PROC*)&Perl_sv_2mortal}, #if (PERL_REVISION == 5) && (PERL_VERSION >= 8) @@ -407,6 +422,9 @@ {"Perl_sv_free2", (PERL_PROC*)&Perl_sv_free2}, {"Perl_sys_init", (PERL_PROC*)&Perl_sys_init}, {"Perl_sys_term", (PERL_PROC*)&Perl_sys_term}, + {"Perl_call_list", (PERL_PROC*)&Perl_call_list}, +# if (PERL_REVISION == 5) && (PERL_VERSION >= 14) +# else {"Perl_ISv_ptr", (PERL_PROC*)&Perl_ISv_ptr}, {"Perl_Istack_max_ptr", (PERL_PROC*)&Perl_Istack_max_ptr}, {"Perl_Istack_base_ptr", (PERL_PROC*)&Perl_Istack_base_ptr}, @@ -418,15 +436,18 @@ {"Perl_Imarkstack_max_ptr", (PERL_PROC*)&Perl_Imarkstack_max_ptr}, {"Perl_Istack_sp_ptr", (PERL_PROC*)&Perl_Istack_sp_ptr}, {"Perl_Iop_ptr", (PERL_PROC*)&Perl_Iop_ptr}, - {"Perl_call_list", (PERL_PROC*)&Perl_call_list}, {"Perl_Iscopestack_ix_ptr", (PERL_PROC*)&Perl_Iscopestack_ix_ptr}, {"Perl_Iunitcheckav_ptr", (PERL_PROC*)&Perl_Iunitcheckav_ptr}, +# endif #endif +#if (PERL_REVISION == 5) && (PERL_VERSION >= 14) +#else {"Perl_Idefgv_ptr", (PERL_PROC*)&Perl_Idefgv_ptr}, {"Perl_Ierrgv_ptr", (PERL_PROC*)&Perl_Ierrgv_ptr}, {"Perl_Isv_yes_ptr", (PERL_PROC*)&Perl_Isv_yes_ptr}, - {"boot_DynaLoader", (PERL_PROC*)&boot_DynaLoader}, {"Perl_Gthr_key_ptr", (PERL_PROC*)&Perl_Gthr_key_ptr}, +#endif + {"boot_DynaLoader", (PERL_PROC*)&boot_DynaLoader}, {"", NULL}, }; @@ -590,7 +611,7 @@ if (ptr->w_perl_private == NULL) { ptr->w_perl_private = newSV(0); - sv_setiv(ptr->w_perl_private, (IV)ptr); + sv_setiv(ptr->w_perl_private, PTR2IV(ptr)); } else SvREFCNT_inc(ptr->w_perl_private); @@ -608,7 +629,7 @@ if (ptr->b_perl_private == NULL) { ptr->b_perl_private = newSV(0); - sv_setiv(ptr->b_perl_private, (IV)ptr); + sv_setiv(ptr->b_perl_private, PTR2IV(ptr)); } else SvREFCNT_inc(ptr->b_perl_private); @@ -755,7 +776,7 @@ #ifdef HAVE_SANDBOX if (sandbox) { - safe = perl_get_sv( "VIM::safe", FALSE ); + safe = perl_get_sv("VIM::safe", FALSE); # ifndef MAKE_TEST /* avoid a warning for unreachable code */ if (safe == NULL || !SvTRUE(safe)) EMSG(_("E299: Perl evaluation forbidden in sandbox without the Safe module")); @@ -892,24 +913,6 @@ win_T *win_find_nr(int n) { return curwin; } #endif -XS(XS_VIM_Msg); -XS(XS_VIM_SetOption); -XS(XS_VIM_DoCommand); -XS(XS_VIM_Eval); -XS(XS_VIM_Buffers); -XS(XS_VIM_Windows); -XS(XS_VIWIN_DESTROY); -XS(XS_VIWIN_Buffer); -XS(XS_VIWIN_SetHeight); -XS(XS_VIWIN_Cursor); -XS(XS_VIBUF_DESTROY); -XS(XS_VIBUF_Name); -XS(XS_VIBUF_Number); -XS(XS_VIBUF_Count); -XS(XS_VIBUF_Get); -XS(XS_VIBUF_Set); -XS(XS_VIBUF_Delete); -XS(XS_VIBUF_Append); XS(boot_VIM); static void @@ -1108,7 +1111,7 @@ VIWIN win PPCODE: - if(items == 1) + if (items == 1) { EXTEND(sp, 2); if (!win_valid(win)) @@ -1116,7 +1119,7 @@ PUSHs(sv_2mortal(newSViv(win->w_cursor.lnum))); PUSHs(sv_2mortal(newSViv(win->w_cursor.col))); } - else if(items == 3) + else if (items == 3) { int lnum, col; @@ -1249,9 +1252,9 @@ { lnum = SvIV(ST(1)); count = 1 + SvIV(ST(2)) - lnum; - if(count == 0) + if (count == 0) count = 1; - if(count < 0) + if (count < 0) { lnum -= count; count = -count; diff -Naur vim73.orig/src/if_py_both.h vim73/src/if_py_both.h --- vim73.orig/src/if_py_both.h 2010-08-08 11:06:29.000000000 +0000 +++ vim73/src/if_py_both.h 2012-07-20 20:31:17.820978145 +0000 @@ -1,4 +1,4 @@ -/* vi:set ts=8 sts=4 sw=4: +/* vi:set ts=8 sts=4 sw=4 noet: * * VIM - Vi IMproved by Bram Moolenaar * @@ -12,6 +12,12 @@ * Common code for if_python.c and if_python3.c. */ +#ifdef FEAT_MBYTE +# define ENC_OPT p_enc +#else +# define ENC_OPT "latin1" +#endif + /* * obtain a lock on the Vim data structures */ @@ -33,7 +39,9 @@ static PyObject *OutputWrite(PyObject *, PyObject *); static PyObject *OutputWritelines(PyObject *, PyObject *); +static PyObject *OutputFlush(PyObject *, PyObject *); +/* Function to write a line, points to either msg() or emsg(). */ typedef void (*writefn)(char_u *); static void writer(writefn fn, char_u *str, PyInt n); @@ -46,9 +54,10 @@ static struct PyMethodDef OutputMethods[] = { /* name, function, calling, documentation */ - {"write", OutputWrite, 1, "" }, - {"writelines", OutputWritelines, 1, "" }, - { NULL, NULL, 0, NULL } + {"write", OutputWrite, 1, ""}, + {"writelines", OutputWritelines, 1, ""}, + {"flush", OutputFlush, 1, ""}, + { NULL, NULL, 0, NULL} }; #define PyErr_SetVim(str) PyErr_SetString(VimError, str) @@ -62,10 +71,15 @@ OutputWrite(PyObject *self, PyObject *args) { int len; - char *str; + char *str = NULL; int error = ((OutputObject *)(self))->error; - if (!PyArg_ParseTuple(args, "s#", &str, &len)) + if (!PyArg_ParseTuple(args, "et#", ENC_OPT, &str, &len)) + return NULL; + + /* TODO: This works around a gcc optimizer problem and avoids Vim + * from crashing. Should find a real solution. */ + if (str == NULL) return NULL; Py_BEGIN_ALLOW_THREADS @@ -73,6 +87,7 @@ writer((writefn)(error ? emsg : msg), (char_u *)str, len); Python_Release_Vim(); Py_END_ALLOW_THREADS + PyMem_Free(str); Py_INCREF(Py_None); return Py_None; @@ -90,7 +105,8 @@ return NULL; Py_INCREF(list); - if (!PyList_Check(list)) { + if (!PyList_Check(list)) + { PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings")); Py_DECREF(list); return NULL; @@ -101,10 +117,11 @@ for (i = 0; i < n; ++i) { PyObject *line = PyList_GetItem(list, i); - char *str; + char *str = NULL; PyInt len; - if (!PyArg_Parse(line, "s#", &str, &len)) { + if (!PyArg_Parse(line, "et#", ENC_OPT, &str, &len)) + { PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings")); Py_DECREF(list); return NULL; @@ -115,6 +132,7 @@ writer((writefn)(error ? emsg : msg), (char_u *)str, len); Python_Release_Vim(); Py_END_ALLOW_THREADS + PyMem_Free(str); } Py_DECREF(list); @@ -122,52 +140,28 @@ return Py_None; } -static char_u *buffer = NULL; -static PyInt buffer_len = 0; -static PyInt buffer_size = 0; - -static writefn old_fn = NULL; - - static void -buffer_ensure(PyInt n) + static PyObject * +OutputFlush(PyObject *self UNUSED, PyObject *args UNUSED) { - PyInt new_size; - char_u *new_buffer; - - if (n < buffer_size) - return; - - new_size = buffer_size; - while (new_size < n) - new_size += 80; - - if (new_size != buffer_size) - { - new_buffer = alloc((unsigned)new_size); - if (new_buffer == NULL) - return; + /* do nothing */ + Py_INCREF(Py_None); + return Py_None; +} - if (buffer) - { - memcpy(new_buffer, buffer, buffer_len); - vim_free(buffer); - } - buffer = new_buffer; - buffer_size = new_size; - } -} +/* Buffer IO, we write one whole line at a time. */ +static garray_T io_ga = {0, 0, 1, 80, NULL}; +static writefn old_fn = NULL; static void PythonIO_Flush(void) { - if (old_fn && buffer_len) + if (old_fn != NULL && io_ga.ga_len > 0) { - buffer[buffer_len] = 0; - old_fn(buffer); + ((char_u *)io_ga.ga_data)[io_ga.ga_len] = NUL; + old_fn((char_u *)io_ga.ga_data); } - - buffer_len = 0; + io_ga.ga_len = 0; } static void @@ -175,30 +169,34 @@ { char_u *ptr; - if (fn != old_fn && old_fn != NULL) + /* Flush when switching output function. */ + if (fn != old_fn) PythonIO_Flush(); - old_fn = fn; + /* Write each NL separated line. Text after the last NL is kept for + * writing later. */ while (n > 0 && (ptr = memchr(str, '\n', n)) != NULL) { PyInt len = ptr - str; - buffer_ensure(buffer_len + len + 1); + if (ga_grow(&io_ga, (int)(len + 1)) == FAIL) + break; - memcpy(buffer + buffer_len, str, len); - buffer_len += len; - buffer[buffer_len] = 0; - fn(buffer); + mch_memmove(((char *)io_ga.ga_data) + io_ga.ga_len, str, (size_t)len); + ((char *)io_ga.ga_data)[io_ga.ga_len + len] = NUL; + fn((char_u *)io_ga.ga_data); str = ptr + 1; n -= len + 1; - buffer_len = 0; + io_ga.ga_len = 0; } - /* Put the remaining text into the buffer for later printing */ - buffer_ensure(buffer_len + n + 1); - memcpy(buffer + buffer_len, str, n); - buffer_len += n; + /* Put the remaining text into io_ga for later printing. */ + if (n > 0 && ga_grow(&io_ga, (int)(n + 1)) == OK) + { + mch_memmove(((char *)io_ga.ga_data) + io_ga.ga_len, str, (size_t)n); + io_ga.ga_len += (int)n; + } } /***************/ @@ -301,7 +299,7 @@ { PyObject *result; PyObject *newObj; - char ptrBuf[NUMBUFLEN]; + char ptrBuf[sizeof(void *) * 2 + 3]; /* Avoid infinite recursion */ if (depth > 100) @@ -316,9 +314,9 @@ if ((our_tv->v_type == VAR_LIST && our_tv->vval.v_list != NULL) || (our_tv->v_type == VAR_DICT && our_tv->vval.v_dict != NULL)) { - sprintf(ptrBuf, PRINTF_DECIMAL_LONG_U, - our_tv->v_type == VAR_LIST ? (long_u)our_tv->vval.v_list - : (long_u)our_tv->vval.v_dict); + sprintf(ptrBuf, "%p", + our_tv->v_type == VAR_LIST ? (void *)our_tv->vval.v_list + : (void *)our_tv->vval.v_dict); result = PyDict_GetItemString(lookupDict, ptrBuf); if (result != NULL) { @@ -449,6 +447,57 @@ #endif } +static PyObject *ConvertToPyObject(typval_T *); + + static PyObject * +VimEvalPy(PyObject *self UNUSED, PyObject *args UNUSED) +{ +#ifdef FEAT_EVAL + char *expr; + typval_T *our_tv; + PyObject *result; + + if (!PyArg_ParseTuple(args, "s", &expr)) + return NULL; + + Py_BEGIN_ALLOW_THREADS + Python_Lock_Vim(); + our_tv = eval_expr((char_u *)expr, NULL); + + Python_Release_Vim(); + Py_END_ALLOW_THREADS + + if (our_tv == NULL) + { + PyErr_SetVim(_("invalid expression")); + return NULL; + } + + result = ConvertToPyObject(our_tv); + Py_BEGIN_ALLOW_THREADS + Python_Lock_Vim(); + free_tv(our_tv); + Python_Release_Vim(); + Py_END_ALLOW_THREADS + + return result; +#else + PyErr_SetVim(_("expressions disabled at compile time")); + return NULL; +#endif +} + + static PyObject * +VimStrwidth(PyObject *self UNUSED, PyObject *args) +{ + char *expr; + + if (!PyArg_ParseTuple(args, "s", &expr)) + return NULL; + + return PyLong_FromLong(mb_string2cells((char_u *)expr, (int)STRLEN(expr))); +} + /* * Vim module - Definitions */ @@ -457,6 +506,8 @@ /* name, function, calling, documentation */ {"command", VimCommand, 1, "Execute a Vim ex-mode command" }, {"eval", VimEval, 1, "Evaluate an expression using Vim evaluator" }, + {"bindeval", VimEvalPy, 1, "Like eval(), but returns objects attached to vim ones"}, + {"strwidth", VimStrwidth, 1, "Screen string width, counts as having width 1"}, { NULL, NULL, 0, NULL } }; @@ -464,8 +515,7 @@ { PyObject_HEAD buf_T *buf; -} -BufferObject; +} BufferObject; #define INVALID_BUFFER_VALUE ((buf_T *)(-1)) @@ -509,161 +559,919 @@ win_T *win; } WindowObject; -#define INVALID_WINDOW_VALUE ((win_T *)(-1)) +static int ConvertFromPyObject(PyObject *, typval_T *); +static int _ConvertFromPyObject(PyObject *, typval_T *, PyObject *); - static int -CheckWindow(WindowObject *this) +typedef struct pylinkedlist_S { + struct pylinkedlist_S *pll_next; + struct pylinkedlist_S *pll_prev; + PyObject *pll_obj; +} pylinkedlist_T; + +static pylinkedlist_T *lastdict = NULL; +static pylinkedlist_T *lastlist = NULL; + + static void +pyll_remove(pylinkedlist_T *ref, pylinkedlist_T **last) { - if (this->win == INVALID_WINDOW_VALUE) + if (ref->pll_prev == NULL) { - PyErr_SetVim(_("attempt to refer to deleted window")); - return -1; + if (ref->pll_next == NULL) + { + *last = NULL; + return; + } } + else + ref->pll_prev->pll_next = ref->pll_next; - return 0; + if (ref->pll_next == NULL) + *last = ref->pll_prev; + else + ref->pll_next->pll_prev = ref->pll_prev; } -static int WindowSetattr(PyObject *, char *, PyObject *); -static PyObject *WindowRepr(PyObject *); + static void +pyll_add(PyObject *self, pylinkedlist_T *ref, pylinkedlist_T **last) +{ + if (*last == NULL) + ref->pll_prev = NULL; + else + { + (*last)->pll_next = ref; + ref->pll_prev = *last; + } + ref->pll_next = NULL; + ref->pll_obj = self; + *last = ref; +} - static int -WindowSetattr(PyObject *self, char *name, PyObject *val) +static PyTypeObject DictionaryType; + +typedef struct { - WindowObject *this = (WindowObject *)(self); + PyObject_HEAD + dict_T *dict; + pylinkedlist_T ref; +} DictionaryObject; - if (CheckWindow(this)) - return -1; + static PyObject * +DictionaryNew(dict_T *dict) +{ + DictionaryObject *self; - if (strcmp(name, "buffer") == 0) + self = PyObject_NEW(DictionaryObject, &DictionaryType); + if (self == NULL) + return NULL; + self->dict = dict; + ++dict->dv_refcount; + + pyll_add((PyObject *)(self), &self->ref, &lastdict); + + return (PyObject *)(self); +} + + static int +pydict_to_tv(PyObject *obj, typval_T *tv, PyObject *lookupDict) +{ + dict_T *d; + char_u *key; + dictitem_T *di; + PyObject *keyObject; + PyObject *valObject; + Py_ssize_t iter = 0; + + d = dict_alloc(); + if (d == NULL) { - PyErr_SetString(PyExc_TypeError, _("readonly attribute")); + PyErr_NoMemory(); return -1; } - else if (strcmp(name, "cursor") == 0) + + tv->v_type = VAR_DICT; + tv->vval.v_dict = d; + + while (PyDict_Next(obj, &iter, &keyObject, &valObject)) { - long lnum; - long col; - long len; + DICTKEY_DECL - if (!PyArg_Parse(val, "(ll)", &lnum, &col)) + if (keyObject == NULL) + return -1; + if (valObject == NULL) return -1; - if (lnum <= 0 || lnum > this->win->w_buffer->b_ml.ml_line_count) + DICTKEY_GET(-1) + + di = dictitem_alloc(key); + + DICTKEY_UNREF + + if (di == NULL) { - PyErr_SetVim(_("cursor position outside buffer")); + PyErr_NoMemory(); return -1; } + di->di_tv.v_lock = 0; - /* Check for keyboard interrupts */ - if (VimErrorCheck()) + if (_ConvertFromPyObject(valObject, &di->di_tv, lookupDict) == -1) + { + vim_free(di); return -1; + } + if (dict_add(d, di) == FAIL) + { + vim_free(di); + PyErr_SetVim(_("failed to add key to dictionary")); + return -1; + } + } + return 0; +} - /* When column is out of range silently correct it. */ - len = (long)STRLEN(ml_get_buf(this->win->w_buffer, lnum, FALSE)); - if (col > len) - col = len; - - this->win->w_cursor.lnum = lnum; - this->win->w_cursor.col = col; -#ifdef FEAT_VIRTUALEDIT - this->win->w_cursor.coladd = 0; -#endif - update_screen(VALID); + static int +pymap_to_tv(PyObject *obj, typval_T *tv, PyObject *lookupDict) +{ + dict_T *d; + char_u *key; + dictitem_T *di; + PyObject *list; + PyObject *litem; + PyObject *keyObject; + PyObject *valObject; + Py_ssize_t lsize; - return 0; + d = dict_alloc(); + if (d == NULL) + { + PyErr_NoMemory(); + return -1; } - else if (strcmp(name, "height") == 0) + + tv->v_type = VAR_DICT; + tv->vval.v_dict = d; + + list = PyMapping_Items(obj); + lsize = PyList_Size(list); + while (lsize--) { - int height; - win_T *savewin; + DICTKEY_DECL - if (!PyArg_Parse(val, "i", &height)) + litem = PyList_GetItem(list, lsize); + if (litem == NULL) + { + Py_DECREF(list); return -1; + } -#ifdef FEAT_GUI - need_mouse_correct = TRUE; -#endif - savewin = curwin; - curwin = this->win; - win_setheight(height); - curwin = savewin; - - /* Check for keyboard interrupts */ - if (VimErrorCheck()) + keyObject = PyTuple_GetItem(litem, 0); + if (keyObject == NULL) + { + Py_DECREF(list); + Py_DECREF(litem); return -1; + } - return 0; - } -#ifdef FEAT_VERTSPLIT - else if (strcmp(name, "width") == 0) - { - int width; - win_T *savewin; + DICTKEY_GET(-1) - if (!PyArg_Parse(val, "i", &width)) + valObject = PyTuple_GetItem(litem, 1); + if (valObject == NULL) + { + Py_DECREF(list); + Py_DECREF(litem); return -1; + } -#ifdef FEAT_GUI - need_mouse_correct = TRUE; -#endif - savewin = curwin; - curwin = this->win; - win_setwidth(width); - curwin = savewin; + di = dictitem_alloc(key); - /* Check for keyboard interrupts */ - if (VimErrorCheck()) + DICTKEY_UNREF + + if (di == NULL) + { + Py_DECREF(list); + Py_DECREF(litem); + PyErr_NoMemory(); return -1; + } + di->di_tv.v_lock = 0; - return 0; - } -#endif - else - { - PyErr_SetString(PyExc_AttributeError, name); - return -1; + if (_ConvertFromPyObject(valObject, &di->di_tv, lookupDict) == -1) + { + vim_free(di); + Py_DECREF(list); + Py_DECREF(litem); + return -1; + } + if (dict_add(d, di) == FAIL) + { + vim_free(di); + Py_DECREF(list); + Py_DECREF(litem); + PyErr_SetVim(_("failed to add key to dictionary")); + return -1; + } + Py_DECREF(litem); } + Py_DECREF(list); + return 0; +} + + static PyInt +DictionaryLength(PyObject *self) +{ + return ((PyInt) ((((DictionaryObject *)(self))->dict->dv_hashtab.ht_used))); } static PyObject * -WindowRepr(PyObject *self) +DictionaryItem(PyObject *self, PyObject *keyObject) { - static char repr[100]; - WindowObject *this = (WindowObject *)(self); + char_u *key; + dictitem_T *val; + DICTKEY_DECL - if (this->win == INVALID_WINDOW_VALUE) - { - vim_snprintf(repr, 100, _(""), (self)); - return PyString_FromString(repr); - } - else - { - int i = 0; - win_T *w; + DICTKEY_GET(NULL) - for (w = firstwin; w != NULL && w != this->win; w = W_NEXT(w)) - ++i; + val = dict_find(((DictionaryObject *) (self))->dict, key, -1); - if (w == NULL) - vim_snprintf(repr, 100, _(""), - (self)); - else - vim_snprintf(repr, 100, _(""), i); + DICTKEY_UNREF - return PyString_FromString(repr); - } + return ConvertToPyObject(&val->di_tv); } -/* - * Window list object - Implementation - */ static PyInt -WinListLength(PyObject *self UNUSED) +DictionaryAssItem(PyObject *self, PyObject *keyObject, PyObject *valObject) { - win_T *w = firstwin; - PyInt n = 0; + char_u *key; + typval_T tv; + dict_T *d = ((DictionaryObject *)(self))->dict; + dictitem_T *di; + DICTKEY_DECL - while (w != NULL) + if (d->dv_lock) + { + PyErr_SetVim(_("dict is locked")); + return -1; + } + + DICTKEY_GET(-1) + + di = dict_find(d, key, -1); + + if (valObject == NULL) + { + hashitem_T *hi; + + if (di == NULL) + { + PyErr_SetString(PyExc_IndexError, _("no such key in dictionary")); + return -1; + } + hi = hash_find(&d->dv_hashtab, di->di_key); + hash_remove(&d->dv_hashtab, hi); + dictitem_free(di); + return 0; + } + + if (ConvertFromPyObject(valObject, &tv) == -1) + return -1; + + if (di == NULL) + { + di = dictitem_alloc(key); + if (di == NULL) + { + PyErr_NoMemory(); + return -1; + } + di->di_tv.v_lock = 0; + + if (dict_add(d, di) == FAIL) + { + vim_free(di); + PyErr_SetVim(_("failed to add key to dictionary")); + return -1; + } + } + else + clear_tv(&di->di_tv); + + DICTKEY_UNREF + + copy_tv(&tv, &di->di_tv); + return 0; +} + + static PyObject * +DictionaryListKeys(PyObject *self) +{ + dict_T *dict = ((DictionaryObject *)(self))->dict; + long_u todo = dict->dv_hashtab.ht_used; + Py_ssize_t i = 0; + PyObject *r; + hashitem_T *hi; + + r = PyList_New(todo); + for (hi = dict->dv_hashtab.ht_array; todo > 0; ++hi) + { + if (!HASHITEM_EMPTY(hi)) + { + PyList_SetItem(r, i, PyBytes_FromString((char *)(hi->hi_key))); + --todo; + ++i; + } + } + return r; +} + +static struct PyMethodDef DictionaryMethods[] = { + {"keys", (PyCFunction)DictionaryListKeys, METH_NOARGS, ""}, + { NULL, NULL, 0, NULL } +}; + +static PyTypeObject ListType; + +typedef struct +{ + PyObject_HEAD + list_T *list; + pylinkedlist_T ref; +} ListObject; + + static PyObject * +ListNew(list_T *list) +{ + ListObject *self; + + self = PyObject_NEW(ListObject, &ListType); + if (self == NULL) + return NULL; + self->list = list; + ++list->lv_refcount; + + pyll_add((PyObject *)(self), &self->ref, &lastlist); + + return (PyObject *)(self); +} + + static int +list_py_concat(list_T *l, PyObject *obj, PyObject *lookupDict) +{ + Py_ssize_t i; + Py_ssize_t lsize = PySequence_Size(obj); + PyObject *litem; + listitem_T *li; + + for(i=0; ili_tv.v_lock = 0; + + litem = PySequence_GetItem(obj, i); + if (litem == NULL) + return -1; + if (_ConvertFromPyObject(litem, &li->li_tv, lookupDict) == -1) + return -1; + + list_append(l, li); + } + return 0; +} + + static int +pyseq_to_tv(PyObject *obj, typval_T *tv, PyObject *lookupDict) +{ + list_T *l; + + l = list_alloc(); + if (l == NULL) + { + PyErr_NoMemory(); + return -1; + } + + tv->v_type = VAR_LIST; + tv->vval.v_list = l; + + if (list_py_concat(l, obj, lookupDict) == -1) + return -1; + + return 0; +} + + static int +pyiter_to_tv(PyObject *obj, typval_T *tv, PyObject *lookupDict) +{ + PyObject *iterator = PyObject_GetIter(obj); + PyObject *item; + list_T *l; + listitem_T *li; + + l = list_alloc(); + + if (l == NULL) + { + PyErr_NoMemory(); + return -1; + } + + tv->vval.v_list = l; + tv->v_type = VAR_LIST; + + + if (iterator == NULL) + return -1; + + while ((item = PyIter_Next(obj))) + { + li = listitem_alloc(); + if (li == NULL) + { + PyErr_NoMemory(); + return -1; + } + li->li_tv.v_lock = 0; + + if (_ConvertFromPyObject(item, &li->li_tv, lookupDict) == -1) + return -1; + + list_append(l, li); + + Py_DECREF(item); + } + + Py_DECREF(iterator); + return 0; +} + + static PyInt +ListLength(PyObject *self) +{ + return ((PyInt) (((ListObject *) (self))->list->lv_len)); +} + + static PyObject * +ListItem(PyObject *self, Py_ssize_t index) +{ + listitem_T *li; + + if (index>=ListLength(self)) + { + PyErr_SetString(PyExc_IndexError, "list index out of range"); + return NULL; + } + li = list_find(((ListObject *) (self))->list, (long) index); + if (li == NULL) + { + PyErr_SetVim(_("internal error: failed to get vim list item")); + return NULL; + } + return ConvertToPyObject(&li->li_tv); +} + +#define PROC_RANGE \ + if (last < 0) {\ + if (last < -size) \ + last = 0; \ + else \ + last += size; \ + } \ + if (first < 0) \ + first = 0; \ + if (first > size) \ + first = size; \ + if (last > size) \ + last = size; + + static PyObject * +ListSlice(PyObject *self, Py_ssize_t first, Py_ssize_t last) +{ + PyInt i; + PyInt size = ListLength(self); + PyInt n; + PyObject *list; + int reversed = 0; + + PROC_RANGE + if (first >= last) + first = last; + + n = last-first; + list = PyList_New(n); + if (list == NULL) + return NULL; + + for (i = 0; i < n; ++i) + { + PyObject *item = ListItem(self, i); + if (item == NULL) + { + Py_DECREF(list); + return NULL; + } + + if ((PyList_SetItem(list, ((reversed)?(n-i-1):(i)), item))) + { + Py_DECREF(item); + Py_DECREF(list); + return NULL; + } + } + + return list; +} + + static int +ListAssItem(PyObject *self, Py_ssize_t index, PyObject *obj) +{ + typval_T tv; + list_T *l = ((ListObject *) (self))->list; + listitem_T *li; + Py_ssize_t length = ListLength(self); + + if (l->lv_lock) + { + PyErr_SetVim(_("list is locked")); + return -1; + } + if (index>length || (index==length && obj==NULL)) + { + PyErr_SetString(PyExc_IndexError, "list index out of range"); + return -1; + } + + if (obj == NULL) + { + li = list_find(l, (long) index); + list_remove(l, li, li); + clear_tv(&li->li_tv); + vim_free(li); + return 0; + } + + if (ConvertFromPyObject(obj, &tv) == -1) + return -1; + + if (index == length) + { + if (list_append_tv(l, &tv) == FAIL) + { + PyErr_SetVim(_("Failed to add item to list")); + return -1; + } + } + else + { + li = list_find(l, (long) index); + clear_tv(&li->li_tv); + copy_tv(&tv, &li->li_tv); + } + return 0; +} + + static int +ListAssSlice(PyObject *self, Py_ssize_t first, Py_ssize_t last, PyObject *obj) +{ + PyInt size = ListLength(self); + Py_ssize_t i; + Py_ssize_t lsize; + PyObject *litem; + listitem_T *li; + listitem_T *next; + typval_T v; + list_T *l = ((ListObject *) (self))->list; + + if (l->lv_lock) + { + PyErr_SetVim(_("list is locked")); + return -1; + } + + PROC_RANGE + + if (first == size) + li = NULL; + else + { + li = list_find(l, (long) first); + if (li == NULL) + { + PyErr_SetVim(_("internal error: no vim list item")); + return -1; + } + if (last > first) + { + i = last - first; + while (i-- && li != NULL) + { + next = li->li_next; + listitem_remove(l, li); + li = next; + } + } + } + + if (obj == NULL) + return 0; + + if (!PyList_Check(obj)) + { + PyErr_SetString(PyExc_TypeError, _("can only assign lists to slice")); + return -1; + } + + lsize = PyList_Size(obj); + + for(i=0; ilist; + PyObject *lookup_dict; + + if (l->lv_lock) + { + PyErr_SetVim(_("list is locked")); + return NULL; + } + + if (!PySequence_Check(obj)) + { + PyErr_SetString(PyExc_TypeError, _("can only concatenate with lists")); + return NULL; + } + + lookup_dict = PyDict_New(); + if (list_py_concat(l, obj, lookup_dict) == -1) + { + Py_DECREF(lookup_dict); + return NULL; + } + Py_DECREF(lookup_dict); + + Py_INCREF(self); + return self; +} + +static struct PyMethodDef ListMethods[] = { + {"extend", (PyCFunction)ListConcatInPlace, METH_O, ""}, + { NULL, NULL, 0, NULL } +}; + +typedef struct +{ + PyObject_HEAD + char_u *name; +} FunctionObject; + +static PyTypeObject FunctionType; + + static PyObject * +FunctionNew(char_u *name) +{ + FunctionObject *self; + + self = PyObject_NEW(FunctionObject, &FunctionType); + if (self == NULL) + return NULL; + self->name = PyMem_New(char_u, STRLEN(name) + 1); + if (self->name == NULL) + { + PyErr_NoMemory(); + return NULL; + } + STRCPY(self->name, name); + func_ref(name); + return (PyObject *)(self); +} + + static PyObject * +FunctionCall(PyObject *self, PyObject *argsObject, PyObject *kwargs) +{ + FunctionObject *this = (FunctionObject *)(self); + char_u *name = this->name; + typval_T args; + typval_T selfdicttv; + typval_T rettv; + dict_T *selfdict = NULL; + PyObject *selfdictObject; + PyObject *result; + int error; + + if (ConvertFromPyObject(argsObject, &args) == -1) + return NULL; + + if (kwargs != NULL) + { + selfdictObject = PyDict_GetItemString(kwargs, "self"); + if (selfdictObject != NULL) + { + if (!PyDict_Check(selfdictObject)) + { + PyErr_SetString(PyExc_TypeError, _("'self' argument must be a dictionary")); + clear_tv(&args); + return NULL; + } + if (ConvertFromPyObject(selfdictObject, &selfdicttv) == -1) + return NULL; + selfdict = selfdicttv.vval.v_dict; + } + } + + error = func_call(name, &args, selfdict, &rettv); + if (error != OK) + { + result = NULL; + PyErr_SetVim(_("failed to run function")); + } + else + result = ConvertToPyObject(&rettv); + + /* FIXME Check what should really be cleared. */ + clear_tv(&args); + clear_tv(&rettv); + /* + * if (selfdict!=NULL) + * clear_tv(selfdicttv); + */ + + return result; +} + +static struct PyMethodDef FunctionMethods[] = { + {"__call__", (PyCFunction)FunctionCall, METH_VARARGS|METH_KEYWORDS, ""}, + { NULL, NULL, 0, NULL } +}; + +#define INVALID_WINDOW_VALUE ((win_T *)(-1)) + + static int +CheckWindow(WindowObject *this) +{ + if (this->win == INVALID_WINDOW_VALUE) + { + PyErr_SetVim(_("attempt to refer to deleted window")); + return -1; + } + + return 0; +} + +static int WindowSetattr(PyObject *, char *, PyObject *); +static PyObject *WindowRepr(PyObject *); + + static int +WindowSetattr(PyObject *self, char *name, PyObject *val) +{ + WindowObject *this = (WindowObject *)(self); + + if (CheckWindow(this)) + return -1; + + if (strcmp(name, "buffer") == 0) + { + PyErr_SetString(PyExc_TypeError, _("readonly attribute")); + return -1; + } + else if (strcmp(name, "cursor") == 0) + { + long lnum; + long col; + + if (!PyArg_Parse(val, "(ll)", &lnum, &col)) + return -1; + + if (lnum <= 0 || lnum > this->win->w_buffer->b_ml.ml_line_count) + { + PyErr_SetVim(_("cursor position outside buffer")); + return -1; + } + + /* Check for keyboard interrupts */ + if (VimErrorCheck()) + return -1; + + this->win->w_cursor.lnum = lnum; + this->win->w_cursor.col = col; +#ifdef FEAT_VIRTUALEDIT + this->win->w_cursor.coladd = 0; +#endif + /* When column is out of range silently correct it. */ + check_cursor_col_win(this->win); + + update_screen(VALID); + return 0; + } + else if (strcmp(name, "height") == 0) + { + int height; + win_T *savewin; + + if (!PyArg_Parse(val, "i", &height)) + return -1; + +#ifdef FEAT_GUI + need_mouse_correct = TRUE; +#endif + savewin = curwin; + curwin = this->win; + win_setheight(height); + curwin = savewin; + + /* Check for keyboard interrupts */ + if (VimErrorCheck()) + return -1; + + return 0; + } +#ifdef FEAT_VERTSPLIT + else if (strcmp(name, "width") == 0) + { + int width; + win_T *savewin; + + if (!PyArg_Parse(val, "i", &width)) + return -1; + +#ifdef FEAT_GUI + need_mouse_correct = TRUE; +#endif + savewin = curwin; + curwin = this->win; + win_setwidth(width); + curwin = savewin; + + /* Check for keyboard interrupts */ + if (VimErrorCheck()) + return -1; + + return 0; + } +#endif + else + { + PyErr_SetString(PyExc_AttributeError, name); + return -1; + } +} + + static PyObject * +WindowRepr(PyObject *self) +{ + static char repr[100]; + WindowObject *this = (WindowObject *)(self); + + if (this->win == INVALID_WINDOW_VALUE) + { + vim_snprintf(repr, 100, _(""), (self)); + return PyString_FromString(repr); + } + else + { + int i = 0; + win_T *w; + + for (w = firstwin; w != NULL && w != this->win; w = W_NEXT(w)) + ++i; + + if (w == NULL) + vim_snprintf(repr, 100, _(""), + (self)); + else + vim_snprintf(repr, 100, _(""), i); + + return PyString_FromString(repr); + } +} + +/* + * Window list object - Implementation + */ + static PyInt +WinListLength(PyObject *self UNUSED) +{ + win_T *w = firstwin; + PyInt n = 0; + + while (w != NULL) { ++n; w = W_NEXT(w); @@ -698,6 +1506,7 @@ { const char *str; char *save; + PyObject *bytes; PyInt len; PyInt i; char *p; @@ -708,8 +1517,9 @@ return NULL; } - str = PyString_AsString(obj); - len = PyString_Size(obj); + bytes = PyString_AsBytes(obj); /* for Python 2 this does nothing */ + str = PyString_AsString(bytes); + len = PyString_Size(bytes); /* * Error checking: String must not contain newlines, as we @@ -748,6 +1558,7 @@ } save[i] = '\0'; + PyString_FreeBytes(bytes); /* Python 2 does nothing here */ return save; } @@ -831,42 +1642,142 @@ check_cursor_col(); changed_cline_bef_curs(); } - invalidate_botline(); + invalidate_botline(); +} + +/* + * Replace a line in the specified buffer. The line number is + * in Vim format (1-based). The replacement line is given as + * a Python string object. The object is checked for validity + * and correct format. Errors are returned as a value of FAIL. + * The return value is OK on success. + * If OK is returned and len_change is not NULL, *len_change + * is set to the change in the buffer length. + */ + static int +SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change) +{ + /* First of all, we check the thpe of the supplied Python object. + * There are three cases: + * 1. NULL, or None - this is a deletion. + * 2. A string - this is a replacement. + * 3. Anything else - this is an error. + */ + if (line == Py_None || line == NULL) + { + buf_T *savebuf = curbuf; + + PyErr_Clear(); + curbuf = buf; + + if (u_savedel((linenr_T)n, 1L) == FAIL) + PyErr_SetVim(_("cannot save undo information")); + else if (ml_delete((linenr_T)n, FALSE) == FAIL) + PyErr_SetVim(_("cannot delete line")); + else + { + if (buf == curwin->w_buffer) + py_fix_cursor((linenr_T)n, (linenr_T)n + 1, (linenr_T)-1); + deleted_lines_mark((linenr_T)n, 1L); + } + + curbuf = savebuf; + + if (PyErr_Occurred() || VimErrorCheck()) + return FAIL; + + if (len_change) + *len_change = -1; + + return OK; + } + else if (PyString_Check(line)) + { + char *save = StringToLine(line); + buf_T *savebuf = curbuf; + + if (save == NULL) + return FAIL; + + /* We do not need to free "save" if ml_replace() consumes it. */ + PyErr_Clear(); + curbuf = buf; + + if (u_savesub((linenr_T)n) == FAIL) + { + PyErr_SetVim(_("cannot save undo information")); + vim_free(save); + } + else if (ml_replace((linenr_T)n, (char_u *)save, FALSE) == FAIL) + { + PyErr_SetVim(_("cannot replace line")); + vim_free(save); + } + else + changed_bytes((linenr_T)n, 0); + + curbuf = savebuf; + + /* Check that the cursor is not beyond the end of the line now. */ + if (buf == curwin->w_buffer) + check_cursor_col(); + + if (PyErr_Occurred() || VimErrorCheck()) + return FAIL; + + if (len_change) + *len_change = 0; + + return OK; + } + else + { + PyErr_BadArgument(); + return FAIL; + } } -/* Replace a line in the specified buffer. The line number is - * in Vim format (1-based). The replacement line is given as - * a Python string object. The object is checked for validity - * and correct format. Errors are returned as a value of FAIL. - * The return value is OK on success. +/* Replace a range of lines in the specified buffer. The line numbers are in + * Vim format (1-based). The range is from lo up to, but not including, hi. + * The replacement lines are given as a Python list of string objects. The + * list is checked for validity and correct format. Errors are returned as a + * value of FAIL. The return value is OK on success. * If OK is returned and len_change is not NULL, *len_change * is set to the change in the buffer length. */ static int -SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change) +SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, PyInt *len_change) { /* First of all, we check the thpe of the supplied Python object. * There are three cases: * 1. NULL, or None - this is a deletion. - * 2. A string - this is a replacement. + * 2. A list - this is a replacement. * 3. Anything else - this is an error. */ - if (line == Py_None || line == NULL) + if (list == Py_None || list == NULL) { - buf_T *savebuf = curbuf; + PyInt i; + PyInt n = (int)(hi - lo); + buf_T *savebuf = curbuf; PyErr_Clear(); curbuf = buf; - if (u_savedel((linenr_T)n, 1L) == FAIL) + if (u_savedel((linenr_T)lo, (long)n) == FAIL) PyErr_SetVim(_("cannot save undo information")); - else if (ml_delete((linenr_T)n, FALSE) == FAIL) - PyErr_SetVim(_("cannot delete line")); else { + for (i = 0; i < n; ++i) + { + if (ml_delete((linenr_T)lo, FALSE) == FAIL) + { + PyErr_SetVim(_("cannot delete line")); + break; + } + } if (buf == curwin->w_buffer) - py_fix_cursor((linenr_T)n, (linenr_T)n + 1, (linenr_T)-1); - deleted_lines_mark((linenr_T)n, 1L); + py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)-n); + deleted_lines_mark((linenr_T)lo, (long)i); } curbuf = savebuf; @@ -875,46 +1786,135 @@ return FAIL; if (len_change) - *len_change = -1; + *len_change = -n; return OK; } - else if (PyString_Check(line)) + else if (PyList_Check(list)) { - char *save = StringToLine(line); - buf_T *savebuf = curbuf; + PyInt i; + PyInt new_len = PyList_Size(list); + PyInt old_len = hi - lo; + PyInt extra = 0; /* lines added to text, can be negative */ + char **array; + buf_T *savebuf; - if (save == NULL) - return FAIL; + if (new_len == 0) /* avoid allocating zero bytes */ + array = NULL; + else + { + array = (char **)alloc((unsigned)(new_len * sizeof(char *))); + if (array == NULL) + { + PyErr_NoMemory(); + return FAIL; + } + } + + for (i = 0; i < new_len; ++i) + { + PyObject *line = PyList_GetItem(list, i); + + array[i] = StringToLine(line); + if (array[i] == NULL) + { + while (i) + vim_free(array[--i]); + vim_free(array); + return FAIL; + } + } + + savebuf = curbuf; - /* We do not need to free "save" if ml_replace() consumes it. */ PyErr_Clear(); curbuf = buf; - if (u_savesub((linenr_T)n) == FAIL) - { + if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL) PyErr_SetVim(_("cannot save undo information")); - vim_free(save); + + /* If the size of the range is reducing (ie, new_len < old_len) we + * need to delete some old_len. We do this at the start, by + * repeatedly deleting line "lo". + */ + if (!PyErr_Occurred()) + { + for (i = 0; i < old_len - new_len; ++i) + if (ml_delete((linenr_T)lo, FALSE) == FAIL) + { + PyErr_SetVim(_("cannot delete line")); + break; + } + extra -= i; } - else if (ml_replace((linenr_T)n, (char_u *)save, FALSE) == FAIL) + + /* For as long as possible, replace the existing old_len with the + * new old_len. This is a more efficient operation, as it requires + * less memory allocation and freeing. + */ + if (!PyErr_Occurred()) { - PyErr_SetVim(_("cannot replace line")); - vim_free(save); + for (i = 0; i < old_len && i < new_len; ++i) + if (ml_replace((linenr_T)(lo+i), (char_u *)array[i], FALSE) + == FAIL) + { + PyErr_SetVim(_("cannot replace line")); + break; + } } else - changed_bytes((linenr_T)n, 0); + i = 0; - curbuf = savebuf; + /* Now we may need to insert the remaining new old_len. If we do, we + * must free the strings as we finish with them (we can't pass the + * responsibility to vim in this case). + */ + if (!PyErr_Occurred()) + { + while (i < new_len) + { + if (ml_append((linenr_T)(lo + i - 1), + (char_u *)array[i], 0, FALSE) == FAIL) + { + PyErr_SetVim(_("cannot insert line")); + break; + } + vim_free(array[i]); + ++i; + ++extra; + } + } + + /* Free any left-over old_len, as a result of an error */ + while (i < new_len) + { + vim_free(array[i]); + ++i; + } + + /* Free the array of old_len. All of its contents have now + * been dealt with (either freed, or the responsibility passed + * to vim. + */ + vim_free(array); + + /* Adjust marks. Invalidate any which lie in the + * changed range, and move any in the remainder of the buffer. + */ + mark_adjust((linenr_T)lo, (linenr_T)(hi - 1), + (long)MAXLNUM, (long)extra); + changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra); - /* Check that the cursor is not beyond the end of the line now. */ if (buf == curwin->w_buffer) - check_cursor_col(); + py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)extra); + + curbuf = savebuf; if (PyErr_Occurred() || VimErrorCheck()) return FAIL; if (len_change) - *len_change = 0; + *len_change = new_len - old_len; return OK; } @@ -925,7 +1925,6 @@ } } - /* Insert a number of lines into the specified buffer after the specifed line. * The line number is in Vim format (1-based). The lines to be inserted are * given as a Python list of string objects or as a single string. The lines @@ -1130,6 +2129,40 @@ return 0; } + static PyInt +RBAsSlice(BufferObject *self, PyInt lo, PyInt hi, PyObject *val, PyInt start, PyInt end, PyInt *new_end) +{ + PyInt size; + PyInt len_change; + + /* Self must be a valid buffer */ + if (CheckBuffer(self)) + return -1; + + /* Sort out the slice range */ + size = end - start + 1; + + if (lo < 0) + lo = 0; + else if (lo > size) + lo = size; + if (hi < 0) + hi = 0; + if (hi < lo) + hi = lo; + else if (hi > size) + hi = size; + + if (SetBufferLineList(self->buf, lo + start, hi + start, + val, &len_change) == FAIL) + return -1; + + if (new_end) + *new_end = end + len_change; + + return 0; +} + static PyObject * RBAppend(BufferObject *self, PyObject *args, PyInt start, PyInt end, PyInt *new_end) @@ -1267,6 +2300,9 @@ {"append", BufferAppend, 1, "Append data to Vim buffer" }, {"mark", BufferMark, 1, "Return (row,col) representing position of named mark" }, {"range", BufferRange, 1, "Return a range object which represents the part of the given buffer between line numbers s and e" }, +#if PY_VERSION_HEX >= 0x03000000 + {"__dir__", BufferDir, 4, "List its attributes" }, +#endif { NULL, NULL, 0, NULL } }; @@ -1347,3 +2383,270 @@ { NULL, NULL, 0, NULL } }; + static void +set_ref_in_py(const int copyID) +{ + pylinkedlist_T *cur; + dict_T *dd; + list_T *ll; + + if (lastdict != NULL) + for(cur = lastdict ; cur != NULL ; cur = cur->pll_prev) + { + dd = ((DictionaryObject *) (cur->pll_obj))->dict; + if (dd->dv_copyID != copyID) + { + dd->dv_copyID = copyID; + set_ref_in_ht(&dd->dv_hashtab, copyID); + } + } + + if (lastlist != NULL) + for(cur = lastlist ; cur != NULL ; cur = cur->pll_prev) + { + ll = ((ListObject *) (cur->pll_obj))->list; + if (ll->lv_copyID != copyID) + { + ll->lv_copyID = copyID; + set_ref_in_list(ll, copyID); + } + } +} + + static int +set_string_copy(char_u *str, typval_T *tv) +{ + tv->vval.v_string = vim_strsave(str); + if (tv->vval.v_string == NULL) + { + PyErr_NoMemory(); + return -1; + } + return 0; +} + +#ifdef FEAT_EVAL +typedef int (*pytotvfunc)(PyObject *, typval_T *, PyObject *); + + static int +convert_dl(PyObject *obj, typval_T *tv, + pytotvfunc py_to_tv, PyObject *lookupDict) +{ + PyObject *capsule; + char hexBuf[sizeof(void *) * 2 + 3]; + + sprintf(hexBuf, "%p", obj); + +# ifdef PY_USE_CAPSULE + capsule = PyDict_GetItemString(lookupDict, hexBuf); +# else + capsule = (PyObject *)PyDict_GetItemString(lookupDict, hexBuf); +# endif + if (capsule == NULL) + { +# ifdef PY_USE_CAPSULE + capsule = PyCapsule_New(tv, NULL, NULL); +# else + capsule = PyCObject_FromVoidPtr(tv, NULL); +# endif + PyDict_SetItemString(lookupDict, hexBuf, capsule); + Py_DECREF(capsule); + if (py_to_tv(obj, tv, lookupDict) == -1) + { + tv->v_type = VAR_UNKNOWN; + return -1; + } + /* As we are not using copy_tv which increments reference count we must + * do it ourself. */ + switch(tv->v_type) + { + case VAR_DICT: ++tv->vval.v_dict->dv_refcount; break; + case VAR_LIST: ++tv->vval.v_list->lv_refcount; break; + } + } + else + { + typval_T *v; + +# ifdef PY_USE_CAPSULE + v = PyCapsule_GetPointer(capsule, NULL); +# else + v = PyCObject_AsVoidPtr(capsule); +# endif + copy_tv(v, tv); + } + return 0; +} + + static int +ConvertFromPyObject(PyObject *obj, typval_T *tv) +{ + PyObject *lookup_dict; + int r; + + lookup_dict = PyDict_New(); + r = _ConvertFromPyObject(obj, tv, lookup_dict); + Py_DECREF(lookup_dict); + return r; +} + + static int +_ConvertFromPyObject(PyObject *obj, typval_T *tv, PyObject *lookupDict) +{ + if (obj->ob_type == &DictionaryType) + { + tv->v_type = VAR_DICT; + tv->vval.v_dict = (((DictionaryObject *)(obj))->dict); + ++tv->vval.v_dict->dv_refcount; + } + else if (obj->ob_type == &ListType) + { + tv->v_type = VAR_LIST; + tv->vval.v_list = (((ListObject *)(obj))->list); + ++tv->vval.v_list->lv_refcount; + } + else if (obj->ob_type == &FunctionType) + { + if (set_string_copy(((FunctionObject *) (obj))->name, tv) == -1) + return -1; + + tv->v_type = VAR_FUNC; + func_ref(tv->vval.v_string); + } +#if PY_MAJOR_VERSION >= 3 + else if (PyBytes_Check(obj)) + { + char_u *result = (char_u *) PyBytes_AsString(obj); + + if (result == NULL) + return -1; + + if (set_string_copy(result, tv) == -1) + return -1; + + tv->v_type = VAR_STRING; + } + else if (PyUnicode_Check(obj)) + { + PyObject *bytes; + char_u *result; + + bytes = PyString_AsBytes(obj); + if (bytes == NULL) + return -1; + + result = (char_u *) PyBytes_AsString(bytes); + if (result == NULL) + return -1; + + if (set_string_copy(result, tv) == -1) + { + Py_XDECREF(bytes); + return -1; + } + Py_XDECREF(bytes); + + tv->v_type = VAR_STRING; + } +#else + else if (PyUnicode_Check(obj)) + { + PyObject *bytes; + char_u *result; + + bytes = PyUnicode_AsEncodedString(obj, (char *)ENC_OPT, NULL); + if (bytes == NULL) + return -1; + + result=(char_u *) PyString_AsString(bytes); + if (result == NULL) + return -1; + + if (set_string_copy(result, tv) == -1) + { + Py_XDECREF(bytes); + return -1; + } + Py_XDECREF(bytes); + + tv->v_type = VAR_STRING; + } + else if (PyString_Check(obj)) + { + char_u *result = (char_u *) PyString_AsString(obj); + + if (result == NULL) + return -1; + + if (set_string_copy(result, tv) == -1) + return -1; + + tv->v_type = VAR_STRING; + } + else if (PyInt_Check(obj)) + { + tv->v_type = VAR_NUMBER; + tv->vval.v_number = (varnumber_T) PyInt_AsLong(obj); + } +#endif + else if (PyLong_Check(obj)) + { + tv->v_type = VAR_NUMBER; + tv->vval.v_number = (varnumber_T) PyLong_AsLong(obj); + } + else if (PyDict_Check(obj)) + return convert_dl(obj, tv, pydict_to_tv, lookupDict); +#ifdef FEAT_FLOAT + else if (PyFloat_Check(obj)) + { + tv->v_type = VAR_FLOAT; + tv->vval.v_float = (float_T) PyFloat_AsDouble(obj); + } +#endif + else if (PyIter_Check(obj)) + return convert_dl(obj, tv, pyiter_to_tv, lookupDict); + else if (PySequence_Check(obj)) + return convert_dl(obj, tv, pyseq_to_tv, lookupDict); + else if (PyMapping_Check(obj)) + return convert_dl(obj, tv, pymap_to_tv, lookupDict); + else + { + PyErr_SetString(PyExc_TypeError, _("unable to convert to vim structure")); + return -1; + } + return 0; +} + + static PyObject * +ConvertToPyObject(typval_T *tv) +{ + if (tv == NULL) + { + PyErr_SetVim(_("NULL reference passed")); + return NULL; + } + switch (tv->v_type) + { + case VAR_STRING: + return PyBytes_FromString((char *) tv->vval.v_string); + case VAR_NUMBER: + return PyLong_FromLong((long) tv->vval.v_number); +#ifdef FEAT_FLOAT + case VAR_FLOAT: + return PyFloat_FromDouble((double) tv->vval.v_float); +#endif + case VAR_LIST: + return ListNew(tv->vval.v_list); + case VAR_DICT: + return DictionaryNew(tv->vval.v_dict); + case VAR_FUNC: + return FunctionNew(tv->vval.v_string); + case VAR_UNKNOWN: + Py_INCREF(Py_None); + return Py_None; + default: + PyErr_SetVim(_("internal error: invalid value type")); + return NULL; + } +} +#endif diff -Naur vim73.orig/src/if_python.c vim73/src/if_python.c --- vim73.orig/src/if_python.c 2010-08-13 13:59:41.000000000 +0000 +++ vim73/src/if_python.c 2012-07-20 20:31:17.824311481 +0000 @@ -1,4 +1,4 @@ -/* vi:set ts=8 sts=4 sw=4: +/* vi:set ts=8 sts=4 sw=4 noet: * * VIM - Vi IMproved by Bram Moolenaar * @@ -56,6 +56,12 @@ static void init_structs(void); +#define PyBytes_FromString PyString_FromString + +/* No-op conversion functions, use with care! */ +#define PyString_AsBytes(obj) (obj) +#define PyString_FreeBytes(obj) + #if !defined(FEAT_PYTHON) && defined(PROTO) /* Use this to be able to generate prototypes without python being used. */ # define PyObject Py_ssize_t @@ -65,6 +71,10 @@ # define PySequenceMethods Py_ssize_t #endif +#if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02070000 +# define PY_USE_CAPSULE +#endif + #if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02050000 # define PyInt Py_ssize_t # define PyInquiry lenfunc @@ -102,7 +112,7 @@ # include # define FARPROC void* # define HINSTANCE void* -# ifdef PY_NO_RTLD_GLOBAL +# if defined(PY_NO_RTLD_GLOBAL) && defined(PY3_NO_RTLD_GLOBAL) # define load_dll(n) dlopen((n), RTLD_LAZY) # else # define load_dll(n) dlopen((n), RTLD_LAZY|RTLD_GLOBAL) @@ -110,7 +120,7 @@ # define close_dll dlclose # define symbol_from_dll dlsym # else -# define load_dll LoadLibrary +# define load_dll vimLoadLib # define close_dll FreeLibrary # define symbol_from_dll GetProcAddress # endif @@ -118,17 +128,21 @@ /* This makes if_python.c compile without warnings against Python 2.5 * on Win32 and Win64. */ # undef PyRun_SimpleString +# undef PyRun_String # undef PyArg_Parse # undef PyArg_ParseTuple # undef Py_BuildValue # undef Py_InitModule4 # undef Py_InitModule4_64 +# undef PyObject_CallMethod /* * Wrapper defines */ # define PyArg_Parse dll_PyArg_Parse # define PyArg_ParseTuple dll_PyArg_ParseTuple +# define PyMem_Free dll_PyMem_Free +# define PyMem_Malloc dll_PyMem_Malloc # define PyDict_SetItemString dll_PyDict_SetItemString # define PyErr_BadArgument dll_PyErr_BadArgument # define PyErr_Clear dll_PyErr_Clear @@ -145,35 +159,67 @@ # endif # define PyInt_AsLong dll_PyInt_AsLong # define PyInt_FromLong dll_PyInt_FromLong +# define PyLong_AsLong dll_PyLong_AsLong +# define PyLong_FromLong dll_PyLong_FromLong # define PyInt_Type (*dll_PyInt_Type) +# define PyLong_Type (*dll_PyLong_Type) # define PyList_GetItem dll_PyList_GetItem # define PyList_Append dll_PyList_Append # define PyList_New dll_PyList_New # define PyList_SetItem dll_PyList_SetItem # define PyList_Size dll_PyList_Size # define PyList_Type (*dll_PyList_Type) +# define PySequence_Check dll_PySequence_Check +# define PySequence_Size dll_PySequence_Size +# define PySequence_GetItem dll_PySequence_GetItem +# define PyTuple_Size dll_PyTuple_Size +# define PyTuple_GetItem dll_PyTuple_GetItem +# define PyTuple_Type (*dll_PyTuple_Type) # define PyImport_ImportModule dll_PyImport_ImportModule # define PyDict_New dll_PyDict_New # define PyDict_GetItemString dll_PyDict_GetItemString +# define PyDict_Next dll_PyDict_Next +# ifdef PyMapping_Items +# define PY_NO_MAPPING_ITEMS +# else +# define PyMapping_Items dll_PyMapping_Items +# endif +# define PyObject_CallMethod dll_PyObject_CallMethod +# define PyMapping_Check dll_PyMapping_Check +# define PyIter_Next dll_PyIter_Next # define PyModule_GetDict dll_PyModule_GetDict # define PyRun_SimpleString dll_PyRun_SimpleString +# define PyRun_String dll_PyRun_String # define PyString_AsString dll_PyString_AsString # define PyString_FromString dll_PyString_FromString # define PyString_FromStringAndSize dll_PyString_FromStringAndSize # define PyString_Size dll_PyString_Size # define PyString_Type (*dll_PyString_Type) +# define PyUnicode_Type (*dll_PyUnicode_Type) +# undef PyUnicode_AsEncodedString +# define PyUnicode_AsEncodedString py_PyUnicode_AsEncodedString +# define PyFloat_AsDouble dll_PyFloat_AsDouble +# define PyFloat_FromDouble dll_PyFloat_FromDouble +# define PyFloat_Type (*dll_PyFloat_Type) +# define PyImport_AddModule (*dll_PyImport_AddModule) # define PySys_SetObject dll_PySys_SetObject # define PySys_SetArgv dll_PySys_SetArgv # define PyType_Type (*dll_PyType_Type) +# define PyType_Ready (*dll_PyType_Ready) # define Py_BuildValue dll_Py_BuildValue # define Py_FindMethod dll_Py_FindMethod # define Py_InitModule4 dll_Py_InitModule4 +# define Py_SetPythonHome dll_Py_SetPythonHome # define Py_Initialize dll_Py_Initialize # define Py_Finalize dll_Py_Finalize # define Py_IsInitialized dll_Py_IsInitialized # define _PyObject_New dll__PyObject_New +# if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02070000 +# define _PyObject_NextNotImplemented (*dll__PyObject_NextNotImplemented) +# endif # define _Py_NoneStruct (*dll__Py_NoneStruct) # define PyObject_Init dll__PyObject_Init +# define PyObject_GetIter dll_PyObject_GetIter # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000 # define PyType_IsSubtype dll_PyType_IsSubtype # endif @@ -181,12 +227,21 @@ # define PyObject_Malloc dll_PyObject_Malloc # define PyObject_Free dll_PyObject_Free # endif +# ifdef PY_USE_CAPSULE +# define PyCapsule_New dll_PyCapsule_New +# define PyCapsule_GetPointer dll_PyCapsule_GetPointer +# else +# define PyCObject_FromVoidPtr dll_PyCObject_FromVoidPtr +# define PyCObject_AsVoidPtr dll_PyCObject_AsVoidPtr +# endif /* * Pointers for dynamic link */ static int(*dll_PyArg_Parse)(PyObject *, char *, ...); static int(*dll_PyArg_ParseTuple)(PyObject *, char *, ...); +static int(*dll_PyMem_Free)(void *); +static void* (*dll_PyMem_Malloc)(size_t); static int(*dll_PyDict_SetItemString)(PyObject *dp, char *key, PyObject *item); static int(*dll_PyErr_BadArgument)(void); static void(*dll_PyErr_Clear)(void); @@ -200,37 +255,66 @@ # ifdef PY_CAN_RECURSE static PyGILState_STATE (*dll_PyGILState_Ensure)(void); static void (*dll_PyGILState_Release)(PyGILState_STATE); -#endif +# endif static long(*dll_PyInt_AsLong)(PyObject *); static PyObject*(*dll_PyInt_FromLong)(long); +static long(*dll_PyLong_AsLong)(PyObject *); +static PyObject*(*dll_PyLong_FromLong)(long); static PyTypeObject* dll_PyInt_Type; +static PyTypeObject* dll_PyLong_Type; static PyObject*(*dll_PyList_GetItem)(PyObject *, PyInt); static PyObject*(*dll_PyList_Append)(PyObject *, 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 int (*dll_PySequence_Check)(PyObject *); +static PyInt(*dll_PySequence_Size)(PyObject *); +static PyObject*(*dll_PySequence_GetItem)(PyObject *, PyInt); +static PyInt(*dll_PyTuple_Size)(PyObject *); +static PyObject*(*dll_PyTuple_GetItem)(PyObject *, PyInt); +static PyTypeObject* dll_PyTuple_Type; static PyObject*(*dll_PyImport_ImportModule)(const char *); static PyObject*(*dll_PyDict_New)(void); static PyObject*(*dll_PyDict_GetItemString)(PyObject *, const char *); +static int (*dll_PyDict_Next)(PyObject *, Py_ssize_t *, PyObject **, PyObject **); +# ifndef PY_NO_MAPPING_ITEMS +static PyObject* (*dll_PyMapping_Items)(PyObject *); +# endif +static PyObject* (*dll_PyObject_CallMethod)(PyObject *, char *, PyObject *); +static int (*dll_PyMapping_Check)(PyObject *); +static PyObject* (*dll_PyIter_Next)(PyObject *); static PyObject*(*dll_PyModule_GetDict)(PyObject *); static int(*dll_PyRun_SimpleString)(char *); +static PyObject *(*dll_PyRun_String)(char *, int, PyObject *, PyObject *); static char*(*dll_PyString_AsString)(PyObject *); static PyObject*(*dll_PyString_FromString)(const char *); static PyObject*(*dll_PyString_FromStringAndSize)(const char *, PyInt); static PyInt(*dll_PyString_Size)(PyObject *); static PyTypeObject* dll_PyString_Type; +static PyTypeObject* dll_PyUnicode_Type; +static PyObject *(*py_PyUnicode_AsEncodedString)(PyObject *, char *, char *); +static double(*dll_PyFloat_AsDouble)(PyObject *); +static PyObject*(*dll_PyFloat_FromDouble)(double); +static PyTypeObject* dll_PyFloat_Type; static int(*dll_PySys_SetObject)(char *, PyObject *); static int(*dll_PySys_SetArgv)(int, char **); static PyTypeObject* dll_PyType_Type; +static int (*dll_PyType_Ready)(PyTypeObject *type); static PyObject*(*dll_Py_BuildValue)(char *, ...); static PyObject*(*dll_Py_FindMethod)(struct PyMethodDef[], PyObject *, char *); static PyObject*(*dll_Py_InitModule4)(char *, struct PyMethodDef *, char *, PyObject *, int); +static PyObject*(*dll_PyImport_AddModule)(char *); +static void(*dll_Py_SetPythonHome)(char *home); static void(*dll_Py_Initialize)(void); static void(*dll_Py_Finalize)(void); static int(*dll_Py_IsInitialized)(void); static PyObject*(*dll__PyObject_New)(PyTypeObject *, PyObject *); static PyObject*(*dll__PyObject_Init)(PyObject *, PyTypeObject *); +static PyObject* (*dll_PyObject_GetIter)(PyObject *); +# if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02070000 +static iternextfunc dll__PyObject_NextNotImplemented; +# endif static PyObject* dll__Py_NoneStruct; # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000 static int (*dll_PyType_IsSubtype)(PyTypeObject *, PyTypeObject *); @@ -239,6 +323,13 @@ static void* (*dll_PyObject_Malloc)(size_t); static void (*dll_PyObject_Free)(void*); # endif +# ifdef PY_USE_CAPSULE +static PyObject* (*dll_PyCapsule_New)(void *, char *, PyCapsule_Destructor); +static void* (*dll_PyCapsule_GetPointer)(PyObject *, char *); +# else +static PyObject* (*dll_PyCObject_FromVoidPtr)(void *cobj, void (*destr)(void *)); +static void* (*dll_PyCObject_AsVoidPtr)(PyObject *); +# endif static HINSTANCE hinstPython = 0; /* Instance of python.dll */ @@ -267,6 +358,8 @@ { {"PyArg_Parse", (PYTHON_PROC*)&dll_PyArg_Parse}, {"PyArg_ParseTuple", (PYTHON_PROC*)&dll_PyArg_ParseTuple}, + {"PyMem_Free", (PYTHON_PROC*)&dll_PyMem_Free}, + {"PyMem_Malloc", (PYTHON_PROC*)&dll_PyMem_Malloc}, {"PyDict_SetItemString", (PYTHON_PROC*)&dll_PyDict_SetItemString}, {"PyErr_BadArgument", (PYTHON_PROC*)&dll_PyErr_BadArgument}, {"PyErr_Clear", (PYTHON_PROC*)&dll_PyErr_Clear}, @@ -283,38 +376,67 @@ # endif {"PyInt_AsLong", (PYTHON_PROC*)&dll_PyInt_AsLong}, {"PyInt_FromLong", (PYTHON_PROC*)&dll_PyInt_FromLong}, + {"PyLong_AsLong", (PYTHON_PROC*)&dll_PyLong_AsLong}, + {"PyLong_FromLong", (PYTHON_PROC*)&dll_PyLong_FromLong}, {"PyInt_Type", (PYTHON_PROC*)&dll_PyInt_Type}, + {"PyLong_Type", (PYTHON_PROC*)&dll_PyLong_Type}, {"PyList_GetItem", (PYTHON_PROC*)&dll_PyList_GetItem}, {"PyList_Append", (PYTHON_PROC*)&dll_PyList_Append}, {"PyList_New", (PYTHON_PROC*)&dll_PyList_New}, {"PyList_SetItem", (PYTHON_PROC*)&dll_PyList_SetItem}, {"PyList_Size", (PYTHON_PROC*)&dll_PyList_Size}, {"PyList_Type", (PYTHON_PROC*)&dll_PyList_Type}, + {"PySequence_GetItem", (PYTHON_PROC*)&dll_PySequence_GetItem}, + {"PySequence_Size", (PYTHON_PROC*)&dll_PySequence_Size}, + {"PySequence_Check", (PYTHON_PROC*)&dll_PySequence_Check}, + {"PyTuple_GetItem", (PYTHON_PROC*)&dll_PyTuple_GetItem}, + {"PyTuple_Size", (PYTHON_PROC*)&dll_PyTuple_Size}, + {"PyTuple_Type", (PYTHON_PROC*)&dll_PyTuple_Type}, {"PyImport_ImportModule", (PYTHON_PROC*)&dll_PyImport_ImportModule}, {"PyDict_GetItemString", (PYTHON_PROC*)&dll_PyDict_GetItemString}, + {"PyDict_Next", (PYTHON_PROC*)&dll_PyDict_Next}, {"PyDict_New", (PYTHON_PROC*)&dll_PyDict_New}, +# ifndef PY_NO_MAPPING_ITEMS + {"PyMapping_Items", (PYTHON_PROC*)&dll_PyMapping_Items}, +# endif + {"PyObject_CallMethod", (PYTHON_PROC*)&dll_PyObject_CallMethod}, + {"PyMapping_Check", (PYTHON_PROC*)&dll_PyMapping_Check}, + {"PyIter_Next", (PYTHON_PROC*)&dll_PyIter_Next}, {"PyModule_GetDict", (PYTHON_PROC*)&dll_PyModule_GetDict}, {"PyRun_SimpleString", (PYTHON_PROC*)&dll_PyRun_SimpleString}, + {"PyRun_String", (PYTHON_PROC*)&dll_PyRun_String}, {"PyString_AsString", (PYTHON_PROC*)&dll_PyString_AsString}, {"PyString_FromString", (PYTHON_PROC*)&dll_PyString_FromString}, {"PyString_FromStringAndSize", (PYTHON_PROC*)&dll_PyString_FromStringAndSize}, {"PyString_Size", (PYTHON_PROC*)&dll_PyString_Size}, {"PyString_Type", (PYTHON_PROC*)&dll_PyString_Type}, + {"PyUnicode_Type", (PYTHON_PROC*)&dll_PyUnicode_Type}, + {"PyFloat_Type", (PYTHON_PROC*)&dll_PyFloat_Type}, + {"PyFloat_AsDouble", (PYTHON_PROC*)&dll_PyFloat_AsDouble}, + {"PyFloat_FromDouble", (PYTHON_PROC*)&dll_PyFloat_FromDouble}, + {"PyImport_AddModule", (PYTHON_PROC*)&dll_PyImport_AddModule}, {"PySys_SetObject", (PYTHON_PROC*)&dll_PySys_SetObject}, {"PySys_SetArgv", (PYTHON_PROC*)&dll_PySys_SetArgv}, {"PyType_Type", (PYTHON_PROC*)&dll_PyType_Type}, + {"PyType_Ready", (PYTHON_PROC*)&dll_PyType_Ready}, {"Py_BuildValue", (PYTHON_PROC*)&dll_Py_BuildValue}, {"Py_FindMethod", (PYTHON_PROC*)&dll_Py_FindMethod}, -# if (PY_VERSION_HEX >= 0x02050000) && SIZEOF_SIZE_T != SIZEOF_INT +# if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02050000 \ + && SIZEOF_SIZE_T != SIZEOF_INT {"Py_InitModule4_64", (PYTHON_PROC*)&dll_Py_InitModule4}, # else {"Py_InitModule4", (PYTHON_PROC*)&dll_Py_InitModule4}, # endif + {"Py_SetPythonHome", (PYTHON_PROC*)&dll_Py_SetPythonHome}, {"Py_Initialize", (PYTHON_PROC*)&dll_Py_Initialize}, {"Py_Finalize", (PYTHON_PROC*)&dll_Py_Finalize}, {"Py_IsInitialized", (PYTHON_PROC*)&dll_Py_IsInitialized}, {"_PyObject_New", (PYTHON_PROC*)&dll__PyObject_New}, {"PyObject_Init", (PYTHON_PROC*)&dll__PyObject_Init}, + {"PyObject_GetIter", (PYTHON_PROC*)&dll_PyObject_GetIter}, +# if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02070000 + {"_PyObject_NextNotImplemented", (PYTHON_PROC*)&dll__PyObject_NextNotImplemented}, +# endif {"_Py_NoneStruct", (PYTHON_PROC*)&dll__Py_NoneStruct}, # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000 {"PyType_IsSubtype", (PYTHON_PROC*)&dll_PyType_IsSubtype}, @@ -323,6 +445,13 @@ {"PyObject_Malloc", (PYTHON_PROC*)&dll_PyObject_Malloc}, {"PyObject_Free", (PYTHON_PROC*)&dll_PyObject_Free}, # endif +# ifdef PY_USE_CAPSULE + {"PyCapsule_New", (PYTHON_PROC*)&dll_PyCapsule_New}, + {"PyCapsule_GetPointer", (PYTHON_PROC*)&dll_PyCapsule_GetPointer}, +# else + {"PyCObject_FromVoidPtr", (PYTHON_PROC*)&dll_PyCObject_FromVoidPtr}, + {"PyCObject_AsVoidPtr", (PYTHON_PROC*)&dll_PyCObject_AsVoidPtr}, +# endif {"", NULL}, }; @@ -348,14 +477,16 @@ python_runtime_link_init(char *libname, int verbose) { int i; + void *ucs_as_encoded_string; -#if !defined(PY_NO_RTLD_GLOBAL) && defined(UNIX) && defined(FEAT_PYTHON3) +#if !(defined(PY_NO_RTLD_GLOBAL) && defined(PY3_NO_RTLD_GLOBAL)) && defined(UNIX) && defined(FEAT_PYTHON3) /* Can't have Python and Python3 loaded at the same time. * It cause a crash, because RTLD_GLOBAL is needed for * standard C extension libraries of one or both python versions. */ if (python3_loaded()) { - EMSG(_("E836: This Vim cannot execute :python after using :py3")); + if (verbose) + EMSG(_("E836: This Vim cannot execute :python after using :py3")); return FAIL; } #endif @@ -382,6 +513,25 @@ return FAIL; } } + + /* Load unicode functions separately as only the ucs2 or the ucs4 functions + * will be present in the library. */ + ucs_as_encoded_string = symbol_from_dll(hinstPython, + "PyUnicodeUCS2_AsEncodedString"); + if (ucs_as_encoded_string == NULL) + ucs_as_encoded_string = symbol_from_dll(hinstPython, + "PyUnicodeUCS4_AsEncodedString"); + if (ucs_as_encoded_string != NULL) + py_PyUnicode_AsEncodedString = ucs_as_encoded_string; + else + { + close_dll(hinstPython); + hinstPython = 0; + if (verbose) + EMSG2(_(e_loadfunc), "PyUnicode_UCSX_*"); + return FAIL; + } + return OK; } @@ -420,10 +570,25 @@ static PyObject *BufferNew (buf_T *); static PyObject *WindowNew(win_T *); +static PyObject *DictionaryNew(dict_T *); static PyObject *LineToString(const char *); static PyTypeObject RangeType; +static int initialised = 0; +#define PYINITIALISED initialised + +/* Add conversion from PyInt? */ +#define DICTKEY_GET(err) \ + if (!PyString_Check(keyObject)) \ + { \ + PyErr_SetString(PyExc_TypeError, _("only string keys are allowed")); \ + return err; \ + } \ + key = (char_u *) PyString_AsString(keyObject); +#define DICTKEY_UNREF +#define DICTKEY_DECL + /* * Include the code shared with if_python3.c */ @@ -437,6 +602,8 @@ static PyInt RangeStart; static PyInt RangeEnd; +static PyObject *globals; + static void PythonIO_Flush(void); static int PythonIO_Init(void); static int PythonMod_Init(void); @@ -452,8 +619,6 @@ * 1. Python interpreter main program. */ -static int initialised = 0; - #if PYTHON_API_VERSION < 1007 /* Python 1.4 */ typedef PyObject PyThreadState; #endif @@ -543,6 +708,10 @@ } #endif +#ifdef PYTHON_HOME + Py_SetPythonHome(PYTHON_HOME); +#endif + init_structs(); #if !defined(MACOS) || defined(MACOS_X_UNIX) @@ -563,6 +732,8 @@ if (PythonMod_Init()) goto fail; + globals = PyModule_GetDict(PyImport_AddModule("__main__")); + /* Remove the element from sys.path that was added because of our * argv[0] value in PythonMod_Init(). Previously we used an empty * string, but dependinding on the OS we then get an empty entry or @@ -591,7 +762,7 @@ * External interface */ static void -DoPythonCommand(exarg_T *eap, const char *cmd) +DoPythonCommand(exarg_T *eap, const char *cmd, typval_T *rettv) { #ifndef PY_CAN_RECURSE static int recursive = 0; @@ -621,8 +792,16 @@ if (Python_Init()) goto theend; - RangeStart = eap->line1; - RangeEnd = eap->line2; + if (rettv == NULL) + { + RangeStart = eap->line1; + RangeEnd = eap->line2; + } + else + { + RangeStart = (PyInt) curwin->w_cursor.lnum; + RangeEnd = RangeStart; + } Python_Release_Vim(); /* leave vim */ #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) @@ -640,7 +819,23 @@ Python_RestoreThread(); /* enter python */ - PyRun_SimpleString((char *)(cmd)); + if (rettv == NULL) + PyRun_SimpleString((char *)(cmd)); + else + { + PyObject *r; + + r = PyRun_String((char *)(cmd), Py_eval_input, globals, globals); + if (r == NULL) + EMSG(_("E858: Eval did not return a valid python object")); + else + { + if (ConvertFromPyObject(r, rettv) == -1) + EMSG(_("E859: Failed to convert returned python object to vim value")); + Py_DECREF(r); + } + PyErr_Clear(); + } Python_SaveThread(); /* leave python */ @@ -662,7 +857,7 @@ #ifndef PY_CAN_RECURSE --recursive; #endif - return; /* keeps lint happy */ + return; } /* @@ -677,9 +872,9 @@ if (!eap->skip) { if (script == NULL) - DoPythonCommand(eap, (char *)eap->arg); + DoPythonCommand(eap, (char *)eap->arg, NULL); else - DoPythonCommand(eap, (char *)script); + DoPythonCommand(eap, (char *)script, NULL); } vim_free(script); } @@ -725,7 +920,7 @@ *p++ = '\0'; /* Execute the file */ - DoPythonCommand(eap, buffer); + DoPythonCommand(eap, buffer, NULL); } /****************************************************** @@ -747,14 +942,16 @@ static int OutputSetattr(PyObject *self, char *name, PyObject *val) { - if (val == NULL) { + if (val == NULL) + { PyErr_SetString(PyExc_AttributeError, _("can't delete OutputObject attributes")); return -1; } if (strcmp(name, "softspace") == 0) { - if (!PyInt_Check(val)) { + if (!PyInt_Check(val)) + { PyErr_SetString(PyExc_TypeError, _("softspace must be an integer")); return -1; } @@ -773,7 +970,7 @@ PythonIO_Init(void) { /* Fixups... */ - OutputType.ob_type = &PyType_Type; + PyType_Ready(&OutputType); return PythonIO_Init_io(); } @@ -782,6 +979,9 @@ * 3. Implementation of the Vim module for Python */ +static PyObject *ConvertToPyObject(typval_T *); +static int ConvertFromPyObject(PyObject *, typval_T *); + /* Window type - Implementation functions * -------------------------------------- */ @@ -823,44 +1023,6 @@ static PyObject *CurrentGetattr(PyObject *, char *); static int CurrentSetattr(PyObject *, char *, PyObject *); -/* Common routines for buffers and line ranges - * ------------------------------------------- - */ - - static PyInt -RBAssSlice(BufferObject *self, PyInt lo, PyInt hi, PyObject *val, PyInt start, PyInt end, PyInt *new_end) -{ - PyInt size; - PyInt len_change; - - /* Self must be a valid buffer */ - if (CheckBuffer(self)) - return -1; - - /* Sort out the slice range */ - size = end - start + 1; - - if (lo < 0) - lo = 0; - else if (lo > size) - lo = size; - if (hi < 0) - hi = 0; - if (hi < lo) - hi = lo; - else if (hi > size) - hi = size; - - if (SetBufferLineList(self->buf, lo + start, hi + start, - val, &len_change) == FAIL) - return -1; - - if (new_end) - *new_end = end + len_change; - - return 0; -} - static PySequenceMethods BufferAsSeq = { (PyInquiry) BufferLength, /* sq_length, len(x) */ (binaryfunc) 0, /* BufferConcat, */ /* sq_concat, x+y */ @@ -1028,7 +1190,7 @@ static PyInt BufferAssSlice(PyObject *self, PyInt lo, PyInt hi, PyObject *val) { - return RBAssSlice((BufferObject *)(self), lo, hi, val, 1, + return RBAsSlice((BufferObject *)(self), lo, hi, val, 1, (PyInt)((BufferObject *)(self))->buf->b_ml.ml_line_count, NULL); } @@ -1078,7 +1240,7 @@ static PyInt RangeAssSlice(PyObject *self, PyInt lo, PyInt hi, PyObject *val) { - return RBAssSlice(((RangeObject *)(self))->buf, lo, hi, val, + return RBAsSlice(((RangeObject *)(self))->buf, lo, hi, val, ((RangeObject *)(self))->start, ((RangeObject *)(self))->end, &((RangeObject *)(self))->end); @@ -1395,12 +1557,12 @@ static char *(argv[2]) = {"/must>not&exist/foo", NULL}; /* Fixups... */ - BufferType.ob_type = &PyType_Type; - RangeType.ob_type = &PyType_Type; - WindowType.ob_type = &PyType_Type; - BufListType.ob_type = &PyType_Type; - WinListType.ob_type = &PyType_Type; - CurrentType.ob_type = &PyType_Type; + PyType_Ready(&BufferType); + PyType_Ready(&RangeType); + PyType_Ready(&WindowType); + PyType_Ready(&BufListType); + PyType_Ready(&WinListType); + PyType_Ready(&CurrentType); /* Set sys.argv[] to avoid a crash in warn(). */ PySys_SetArgv(1, argv); @@ -1425,194 +1587,6 @@ * 4. Utility functions for handling the interface between Vim and Python. */ -/* Replace a range of lines in the specified buffer. The line numbers are in - * Vim format (1-based). The range is from lo up to, but not including, hi. - * The replacement lines are given as a Python list of string objects. The - * list is checked for validity and correct format. Errors are returned as a - * value of FAIL. The return value is OK on success. - * If OK is returned and len_change is not NULL, *len_change - * is set to the change in the buffer length. - */ - static int -SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, PyInt *len_change) -{ - /* First of all, we check the thpe of the supplied Python object. - * There are three cases: - * 1. NULL, or None - this is a deletion. - * 2. A list - this is a replacement. - * 3. Anything else - this is an error. - */ - if (list == Py_None || list == NULL) - { - PyInt i; - PyInt n = (int)(hi - lo); - buf_T *savebuf = curbuf; - - PyErr_Clear(); - curbuf = buf; - - if (u_savedel((linenr_T)lo, (long)n) == FAIL) - PyErr_SetVim(_("cannot save undo information")); - else - { - for (i = 0; i < n; ++i) - { - if (ml_delete((linenr_T)lo, FALSE) == FAIL) - { - PyErr_SetVim(_("cannot delete line")); - break; - } - } - if (buf == curwin->w_buffer) - py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)-n); - deleted_lines_mark((linenr_T)lo, (long)i); - } - - curbuf = savebuf; - - if (PyErr_Occurred() || VimErrorCheck()) - return FAIL; - - if (len_change) - *len_change = -n; - - return OK; - } - else if (PyList_Check(list)) - { - PyInt i; - PyInt new_len = PyList_Size(list); - PyInt old_len = hi - lo; - PyInt extra = 0; /* lines added to text, can be negative */ - char **array; - buf_T *savebuf; - - if (new_len == 0) /* avoid allocating zero bytes */ - array = NULL; - else - { - array = (char **)alloc((unsigned)(new_len * sizeof(char *))); - if (array == NULL) - { - PyErr_NoMemory(); - return FAIL; - } - } - - for (i = 0; i < new_len; ++i) - { - PyObject *line = PyList_GetItem(list, i); - - array[i] = StringToLine(line); - if (array[i] == NULL) - { - while (i) - vim_free(array[--i]); - vim_free(array); - return FAIL; - } - } - - savebuf = curbuf; - - PyErr_Clear(); - curbuf = buf; - - if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL) - PyErr_SetVim(_("cannot save undo information")); - - /* If the size of the range is reducing (ie, new_len < old_len) we - * need to delete some old_len. We do this at the start, by - * repeatedly deleting line "lo". - */ - if (!PyErr_Occurred()) - { - for (i = 0; i < old_len - new_len; ++i) - if (ml_delete((linenr_T)lo, FALSE) == FAIL) - { - PyErr_SetVim(_("cannot delete line")); - break; - } - extra -= i; - } - - /* For as long as possible, replace the existing old_len with the - * new old_len. This is a more efficient operation, as it requires - * less memory allocation and freeing. - */ - if (!PyErr_Occurred()) - { - for (i = 0; i < old_len && i < new_len; ++i) - if (ml_replace((linenr_T)(lo+i), (char_u *)array[i], FALSE) - == FAIL) - { - PyErr_SetVim(_("cannot replace line")); - break; - } - } - else - i = 0; - - /* Now we may need to insert the remaining new old_len. If we do, we - * must free the strings as we finish with them (we can't pass the - * responsibility to vim in this case). - */ - if (!PyErr_Occurred()) - { - while (i < new_len) - { - if (ml_append((linenr_T)(lo + i - 1), - (char_u *)array[i], 0, FALSE) == FAIL) - { - PyErr_SetVim(_("cannot insert line")); - break; - } - vim_free(array[i]); - ++i; - ++extra; - } - } - - /* Free any left-over old_len, as a result of an error */ - while (i < new_len) - { - vim_free(array[i]); - ++i; - } - - /* Free the array of old_len. All of its contents have now - * been dealt with (either freed, or the responsibility passed - * to vim. - */ - vim_free(array); - - /* Adjust marks. Invalidate any which lie in the - * changed range, and move any in the remainder of the buffer. - */ - mark_adjust((linenr_T)lo, (linenr_T)(hi - 1), - (long)MAXLNUM, (long)extra); - changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra); - - if (buf == curwin->w_buffer) - py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)extra); - - curbuf = savebuf; - - if (PyErr_Occurred() || VimErrorCheck()) - return FAIL; - - if (len_change) - *len_change = new_len - old_len; - - return OK; - } - else - { - PyErr_BadArgument(); - return FAIL; - } -} - /* Convert a Vim line into a Python string. * All internal newlines are replaced by null characters. * @@ -1649,6 +1623,172 @@ return result; } +static void DictionaryDestructor(PyObject *); +static PyObject *DictionaryGetattr(PyObject *, char*); + +static PyMappingMethods DictionaryAsMapping = { + (PyInquiry) DictionaryLength, + (binaryfunc) DictionaryItem, + (objobjargproc) DictionaryAssItem, +}; + +static PyTypeObject DictionaryType = { + PyObject_HEAD_INIT(0) + 0, + "vimdictionary", + sizeof(DictionaryObject), + 0, + + (destructor) DictionaryDestructor, + (printfunc) 0, + (getattrfunc) DictionaryGetattr, + (setattrfunc) 0, + (cmpfunc) 0, + (reprfunc) 0, + + 0, /* as number */ + 0, /* as sequence */ + &DictionaryAsMapping, /* as mapping */ + + (hashfunc) 0, + (ternaryfunc) 0, + (reprfunc) 0, +}; + + static void +DictionaryDestructor(PyObject *self) +{ + DictionaryObject *this = ((DictionaryObject *) (self)); + + pyll_remove(&this->ref, &lastdict); + dict_unref(this->dict); + + Py_DECREF(self); +} + + static PyObject * +DictionaryGetattr(PyObject *self, char *name) +{ + return Py_FindMethod(DictionaryMethods, self, name); +} + +static void ListDestructor(PyObject *); +static PyObject *ListGetattr(PyObject *, char *); + +static PySequenceMethods ListAsSeq = { + (PyInquiry) ListLength, + (binaryfunc) 0, + (PyIntArgFunc) 0, + (PyIntArgFunc) ListItem, + (PyIntIntArgFunc) ListSlice, + (PyIntObjArgProc) ListAssItem, + (PyIntIntObjArgProc) ListAssSlice, + (objobjproc) 0, +#if PY_MAJOR_VERSION >= 2 + (binaryfunc) ListConcatInPlace, + 0, +#endif +}; + +static PyTypeObject ListType = { + PyObject_HEAD_INIT(0) + 0, + "vimlist", + sizeof(ListObject), + 0, + + (destructor) ListDestructor, + (printfunc) 0, + (getattrfunc) ListGetattr, + (setattrfunc) 0, + (cmpfunc) 0, + (reprfunc) 0, + + 0, /* as number */ + &ListAsSeq, /* as sequence */ + 0, /* as mapping */ + + (hashfunc) 0, + (ternaryfunc) 0, + (reprfunc) 0, +}; + + static void +ListDestructor(PyObject *self) +{ + ListObject *this = ((ListObject *) (self)); + + pyll_remove(&this->ref, &lastlist); + list_unref(this->list); + + Py_DECREF(self); +} + + static PyObject * +ListGetattr(PyObject *self, char *name) +{ + return Py_FindMethod(ListMethods, self, name); +} + +static void FunctionDestructor(PyObject *); +static PyObject *FunctionGetattr(PyObject *, char *); + +static PyTypeObject FunctionType = { + PyObject_HEAD_INIT(0) + 0, + "vimfunction", + sizeof(FunctionObject), + 0, + + (destructor) FunctionDestructor, + (printfunc) 0, + (getattrfunc) FunctionGetattr, + (setattrfunc) 0, + (cmpfunc) 0, + (reprfunc) 0, + + 0, /* as number */ + 0, /* as sequence */ + 0, /* as mapping */ + + (hashfunc) 0, + (ternaryfunc) FunctionCall, + (reprfunc) 0, +}; + + static void +FunctionDestructor(PyObject *self) +{ + FunctionObject *this = (FunctionObject *) (self); + + func_unref(this->name); + PyMem_Del(this->name); + + Py_DECREF(self); +} + + static PyObject * +FunctionGetattr(PyObject *self, char *name) +{ + FunctionObject *this = (FunctionObject *)(self); + + if (strcmp(name, "name") == 0) + return PyString_FromString((char *)(this->name)); + else + return Py_FindMethod(FunctionMethods, self, name); +} + + void +do_pyeval (char_u *str, typval_T *rettv) +{ + DoPythonCommand(NULL, (char *) str, rettv); + switch(rettv->v_type) + { + case VAR_DICT: ++rettv->vval.v_dict->dv_refcount; break; + case VAR_LIST: ++rettv->vval.v_list->lv_refcount; break; + case VAR_FUNC: func_ref(rettv->vval.v_string); break; + } +} /* Don't generate a prototype for the next function, it generates an error on * newer Python versions. */ @@ -1661,6 +1801,12 @@ } #endif /* Python 1.4 */ + void +set_ref_in_python (int copyID) +{ + set_ref_in_py(copyID); +} + static void init_structs(void) { diff -Naur vim73.orig/src/if_python3.c vim73/src/if_python3.c --- vim73.orig/src/if_python3.c 2010-08-13 13:59:40.000000000 +0000 +++ vim73/src/if_python3.c 2012-07-20 20:31:17.787644787 +0000 @@ -22,8 +22,8 @@ * Adaptations to support both python3.x and python2.x */ -// uncomment this if used with the debug version of python -// #define Py_DEBUG +/* uncomment this if used with the debug version of python */ +/* #define Py_DEBUG */ #include "vim.h" @@ -68,19 +68,31 @@ static void init_structs(void); +/* The "surrogateescape" error handler is new in Python 3.1 */ +#if PY_VERSION_HEX >= 0x030100f0 +# define CODEC_ERROR_HANDLER "surrogateescape" +#else +# define CODEC_ERROR_HANDLER NULL +#endif + +/* Python 3 does not support CObjects, always use Capsules */ +#define PY_USE_CAPSULE + #define PyInt Py_ssize_t #define PyString_Check(obj) PyUnicode_Check(obj) -#define PyString_AsString(obj) _PyUnicode_AsString(obj) -#define PyString_Size(obj) PyUnicode_GET_SIZE(obj) +#define PyString_AsBytes(obj) PyUnicode_AsEncodedString(obj, (char *)ENC_OPT, CODEC_ERROR_HANDLER) +#define PyString_FreeBytes(obj) Py_XDECREF(bytes) +#define PyString_AsString(obj) PyBytes_AsString(obj) +#define PyString_Size(obj) PyBytes_GET_SIZE(bytes) #define PyString_FromString(repr) PyUnicode_FromString(repr) -#if defined(DYNAMIC_PYTHON3) +#if defined(DYNAMIC_PYTHON3) || defined(PROTO) # ifndef WIN3264 # include # define FARPROC void* # define HINSTANCE void* -# ifdef PY_NO_RTLD_GLOBAL +# if defined(PY_NO_RTLD_GLOBAL) && defined(PY3_NO_RTLD_GLOBAL) # define load_dll(n) dlopen((n), RTLD_LAZY) # else # define load_dll(n) dlopen((n), RTLD_LAZY|RTLD_GLOBAL) @@ -88,7 +100,7 @@ # define close_dll dlclose # define symbol_from_dll dlsym # else -# define load_dll LoadLibrary +# define load_dll vimLoadLib # define close_dll FreeLibrary # define symbol_from_dll GetProcAddress # endif @@ -99,6 +111,8 @@ # define PyArg_Parse py3_PyArg_Parse # undef PyArg_ParseTuple # define PyArg_ParseTuple py3_PyArg_ParseTuple +# define PyMem_Free py3_PyMem_Free +# define PyMem_Malloc py3_PyMem_Malloc # define PyDict_SetItemString py3_PyDict_SetItemString # define PyErr_BadArgument py3_PyErr_BadArgument # define PyErr_Clear py3_PyErr_Clear @@ -118,29 +132,54 @@ # define PyList_New py3_PyList_New # define PyList_SetItem py3_PyList_SetItem # define PyList_Size py3_PyList_Size +# define PySequence_Check py3_PySequence_Check +# define PySequence_Size py3_PySequence_Size +# define PySequence_GetItem py3_PySequence_GetItem +# define PyTuple_Size py3_PyTuple_Size +# define PyTuple_GetItem py3_PyTuple_GetItem # define PySlice_GetIndicesEx py3_PySlice_GetIndicesEx # define PyImport_ImportModule py3_PyImport_ImportModule +# define PyImport_AddModule py3_PyImport_AddModule # define PyObject_Init py3__PyObject_Init # define PyDict_New py3_PyDict_New # define PyDict_GetItemString py3_PyDict_GetItemString +# define PyDict_Next py3_PyDict_Next +# define PyMapping_Check py3_PyMapping_Check +# define PyMapping_Items py3_PyMapping_Items +# define PyIter_Next py3_PyIter_Next +# define PyObject_GetIter py3_PyObject_GetIter # define PyModule_GetDict py3_PyModule_GetDict #undef PyRun_SimpleString # define PyRun_SimpleString py3_PyRun_SimpleString +#undef PyRun_String +# define PyRun_String py3_PyRun_String # define PySys_SetObject py3_PySys_SetObject # define PySys_SetArgv py3_PySys_SetArgv # define PyType_Type (*py3_PyType_Type) # define PyType_Ready py3_PyType_Ready #undef Py_BuildValue # define Py_BuildValue py3_Py_BuildValue +# define Py_SetPythonHome py3_Py_SetPythonHome # define Py_Initialize py3_Py_Initialize # define Py_Finalize py3_Py_Finalize # define Py_IsInitialized py3_Py_IsInitialized # define _Py_NoneStruct (*py3__Py_NoneStruct) +# define _PyObject_NextNotImplemented (*py3__PyObject_NextNotImplemented) # define PyModule_AddObject py3_PyModule_AddObject # define PyImport_AppendInittab py3_PyImport_AppendInittab # define _PyUnicode_AsString py3__PyUnicode_AsString +# undef PyUnicode_AsEncodedString +# define PyUnicode_AsEncodedString py3_PyUnicode_AsEncodedString +# undef PyBytes_AsString +# define PyBytes_AsString py3_PyBytes_AsString +# undef PyBytes_FromString +# define PyBytes_FromString py3_PyBytes_FromString +# define PyFloat_FromDouble py3_PyFloat_FromDouble +# define PyFloat_AsDouble py3_PyFloat_AsDouble # define PyObject_GenericGetAttr py3_PyObject_GenericGetAttr # define PySlice_Type (*py3_PySlice_Type) +# define PyFloat_Type (*py3_PyFloat_Type) +# define PyErr_NewException py3_PyErr_NewException # ifdef Py_DEBUG # define _Py_NegativeRefcount py3__Py_NegativeRefcount # define _Py_RefTotal (*py3__Py_RefTotal) @@ -156,8 +195,11 @@ # define PyModule_Create2 py3_PyModule_Create2 # undef PyUnicode_FromString # define PyUnicode_FromString py3_PyUnicode_FromString -# undef PyUnicode_FromStringAndSize -# define PyUnicode_FromStringAndSize py3_PyUnicode_FromStringAndSize +# undef PyUnicode_Decode +# define PyUnicode_Decode py3_PyUnicode_Decode +# define PyType_IsSubtype py3_PyType_IsSubtype +# define PyCapsule_New py3_PyCapsule_New +# define PyCapsule_GetPointer py3_PyCapsule_GetPointer # ifdef Py_DEBUG # undef PyObject_NEW @@ -170,6 +212,7 @@ * Pointers for dynamic link */ static int (*py3_PySys_SetArgv)(int, wchar_t **); +static void (*py3_Py_SetPythonHome)(wchar_t *home); static void (*py3_Py_Initialize)(void); static PyObject* (*py3_PyList_New)(Py_ssize_t size); static PyGILState_STATE (*py3_PyGILState_Ensure)(void); @@ -177,27 +220,40 @@ static int (*py3_PySys_SetObject)(char *, PyObject *); static PyObject* (*py3_PyList_Append)(PyObject *, PyObject *); static Py_ssize_t (*py3_PyList_Size)(PyObject *); -static int (*py3_PySlice_GetIndicesEx)(PySliceObject *r, Py_ssize_t length, +static int (*py3_PySequence_Check)(PyObject *); +static Py_ssize_t (*py3_PySequence_Size)(PyObject *); +static PyObject* (*py3_PySequence_GetItem)(PyObject *, Py_ssize_t); +static Py_ssize_t (*py3_PyTuple_Size)(PyObject *); +static PyObject* (*py3_PyTuple_GetItem)(PyObject *, Py_ssize_t); +static int (*py3_PyMapping_Check)(PyObject *); +static PyObject* (*py3_PyMapping_Items)(PyObject *); +static int (*py3_PySlice_GetIndicesEx)(PyObject *r, Py_ssize_t length, Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step, Py_ssize_t *slicelength); static PyObject* (*py3_PyErr_NoMemory)(void); static void (*py3_Py_Finalize)(void); static void (*py3_PyErr_SetString)(PyObject *, const char *); static int (*py3_PyRun_SimpleString)(char *); +static PyObject* (*py3_PyRun_String)(char *, int, PyObject *, PyObject *); static PyObject* (*py3_PyList_GetItem)(PyObject *, Py_ssize_t); static PyObject* (*py3_PyImport_ImportModule)(const char *); +static PyObject* (*py3_PyImport_AddModule)(const char *); static int (*py3_PyErr_BadArgument)(void); static PyTypeObject* py3_PyType_Type; static PyObject* (*py3_PyErr_Occurred)(void); static PyObject* (*py3_PyModule_GetDict)(PyObject *); static int (*py3_PyList_SetItem)(PyObject *, Py_ssize_t, PyObject *); static PyObject* (*py3_PyDict_GetItemString)(PyObject *, const char *); +static int (*py3_PyDict_Next)(PyObject *, Py_ssize_t *, PyObject **, PyObject **); static PyObject* (*py3_PyLong_FromLong)(long); static PyObject* (*py3_PyDict_New)(void); +static PyObject* (*py3_PyIter_Next)(PyObject *); +static PyObject* (*py3_PyObject_GetIter)(PyObject *); static PyObject* (*py3_Py_BuildValue)(char *, ...); static int (*py3_PyType_Ready)(PyTypeObject *type); static int (*py3_PyDict_SetItemString)(PyObject *dp, char *key, PyObject *item); static PyObject* (*py3_PyUnicode_FromString)(const char *u); -static PyObject* (*py3_PyUnicode_FromStringAndSize)(const char *u, Py_ssize_t size); +static PyObject* (*py3_PyUnicode_Decode)(const char *u, Py_ssize_t size, + const char *encoding, const char *errors); static long (*py3_PyLong_AsLong)(PyObject *); static void (*py3_PyErr_SetNone)(PyObject *); static void (*py3_PyEval_InitThreads)(void); @@ -205,18 +261,30 @@ static PyThreadState*(*py3_PyEval_SaveThread)(void); static int (*py3_PyArg_Parse)(PyObject *, char *, ...); static int (*py3_PyArg_ParseTuple)(PyObject *, char *, ...); +static int (*py3_PyMem_Free)(void *); +static void* (*py3_PyMem_Malloc)(size_t); static int (*py3_Py_IsInitialized)(void); static void (*py3_PyErr_Clear)(void); static PyObject*(*py3__PyObject_Init)(PyObject *, PyTypeObject *); +static iternextfunc py3__PyObject_NextNotImplemented; static PyObject* py3__Py_NoneStruct; static int (*py3_PyModule_AddObject)(PyObject *m, const char *name, PyObject *o); static int (*py3_PyImport_AppendInittab)(const char *name, PyObject* (*initfunc)(void)); static char* (*py3__PyUnicode_AsString)(PyObject *unicode); +static PyObject* (*py3_PyUnicode_AsEncodedString)(PyObject *unicode, const char* encoding, const char* errors); +static char* (*py3_PyBytes_AsString)(PyObject *bytes); +static PyObject* (*py3_PyBytes_FromString)(char *str); +static PyObject* (*py3_PyFloat_FromDouble)(double num); +static double (*py3_PyFloat_AsDouble)(PyObject *); static PyObject* (*py3_PyObject_GenericGetAttr)(PyObject *obj, PyObject *name); static PyObject* (*py3_PyModule_Create2)(struct PyModuleDef* module, int module_api_version); static PyObject* (*py3_PyType_GenericAlloc)(PyTypeObject *type, Py_ssize_t nitems); static PyObject* (*py3_PyType_GenericNew)(PyTypeObject *type, PyObject *args, PyObject *kwds); static PyTypeObject* py3_PySlice_Type; +static PyTypeObject* py3_PyFloat_Type; +static PyObject* (*py3_PyErr_NewException)(char *name, PyObject *base, PyObject *dict); +static PyObject* (*py3_PyCapsule_New)(void *, char *, PyCapsule_Destructor); +static void* (*py3_PyCapsule_GetPointer)(PyObject *, char *); # ifdef Py_DEBUG static void (*py3__Py_NegativeRefcount)(const char *fname, int lineno, PyObject *op); static Py_ssize_t* py3__Py_RefTotal; @@ -227,6 +295,7 @@ static void (*py3_PyObject_Free)(void*); static void* (*py3_PyObject_Malloc)(size_t); # endif +static int (*py3_PyType_IsSubtype)(PyTypeObject *, PyTypeObject *); static HINSTANCE hinstPy3 = 0; /* Instance of python.dll */ @@ -254,27 +323,42 @@ } py3_funcname_table[] = { {"PySys_SetArgv", (PYTHON_PROC*)&py3_PySys_SetArgv}, + {"Py_SetPythonHome", (PYTHON_PROC*)&py3_Py_SetPythonHome}, {"Py_Initialize", (PYTHON_PROC*)&py3_Py_Initialize}, {"PyArg_ParseTuple", (PYTHON_PROC*)&py3_PyArg_ParseTuple}, + {"PyMem_Free", (PYTHON_PROC*)&py3_PyMem_Free}, + {"PyMem_Malloc", (PYTHON_PROC*)&py3_PyMem_Malloc}, {"PyList_New", (PYTHON_PROC*)&py3_PyList_New}, {"PyGILState_Ensure", (PYTHON_PROC*)&py3_PyGILState_Ensure}, {"PyGILState_Release", (PYTHON_PROC*)&py3_PyGILState_Release}, {"PySys_SetObject", (PYTHON_PROC*)&py3_PySys_SetObject}, {"PyList_Append", (PYTHON_PROC*)&py3_PyList_Append}, {"PyList_Size", (PYTHON_PROC*)&py3_PyList_Size}, + {"PySequence_Check", (PYTHON_PROC*)&py3_PySequence_Check}, + {"PySequence_Size", (PYTHON_PROC*)&py3_PySequence_Size}, + {"PySequence_GetItem", (PYTHON_PROC*)&py3_PySequence_GetItem}, + {"PyTuple_Size", (PYTHON_PROC*)&py3_PyTuple_Size}, + {"PyTuple_GetItem", (PYTHON_PROC*)&py3_PyTuple_GetItem}, {"PySlice_GetIndicesEx", (PYTHON_PROC*)&py3_PySlice_GetIndicesEx}, {"PyErr_NoMemory", (PYTHON_PROC*)&py3_PyErr_NoMemory}, {"Py_Finalize", (PYTHON_PROC*)&py3_Py_Finalize}, {"PyErr_SetString", (PYTHON_PROC*)&py3_PyErr_SetString}, {"PyRun_SimpleString", (PYTHON_PROC*)&py3_PyRun_SimpleString}, + {"PyRun_String", (PYTHON_PROC*)&py3_PyRun_String}, {"PyList_GetItem", (PYTHON_PROC*)&py3_PyList_GetItem}, {"PyImport_ImportModule", (PYTHON_PROC*)&py3_PyImport_ImportModule}, + {"PyImport_AddModule", (PYTHON_PROC*)&py3_PyImport_AddModule}, {"PyErr_BadArgument", (PYTHON_PROC*)&py3_PyErr_BadArgument}, {"PyType_Type", (PYTHON_PROC*)&py3_PyType_Type}, {"PyErr_Occurred", (PYTHON_PROC*)&py3_PyErr_Occurred}, {"PyModule_GetDict", (PYTHON_PROC*)&py3_PyModule_GetDict}, {"PyList_SetItem", (PYTHON_PROC*)&py3_PyList_SetItem}, {"PyDict_GetItemString", (PYTHON_PROC*)&py3_PyDict_GetItemString}, + {"PyDict_Next", (PYTHON_PROC*)&py3_PyDict_Next}, + {"PyMapping_Check", (PYTHON_PROC*)&py3_PyMapping_Check}, + {"PyMapping_Items", (PYTHON_PROC*)&py3_PyMapping_Items}, + {"PyIter_Next", (PYTHON_PROC*)&py3_PyIter_Next}, + {"PyObject_GetIter", (PYTHON_PROC*)&py3_PyObject_GetIter}, {"PyLong_FromLong", (PYTHON_PROC*)&py3_PyLong_FromLong}, {"PyDict_New", (PYTHON_PROC*)&py3_PyDict_New}, {"Py_BuildValue", (PYTHON_PROC*)&py3_Py_BuildValue}, @@ -286,19 +370,25 @@ {"PyEval_RestoreThread", (PYTHON_PROC*)&py3_PyEval_RestoreThread}, {"PyEval_SaveThread", (PYTHON_PROC*)&py3_PyEval_SaveThread}, {"PyArg_Parse", (PYTHON_PROC*)&py3_PyArg_Parse}, - {"PyArg_ParseTuple", (PYTHON_PROC*)&py3_PyArg_ParseTuple}, {"Py_IsInitialized", (PYTHON_PROC*)&py3_Py_IsInitialized}, + {"_PyObject_NextNotImplemented", (PYTHON_PROC*)&py3__PyObject_NextNotImplemented}, {"_Py_NoneStruct", (PYTHON_PROC*)&py3__Py_NoneStruct}, {"PyErr_Clear", (PYTHON_PROC*)&py3_PyErr_Clear}, {"PyObject_Init", (PYTHON_PROC*)&py3__PyObject_Init}, {"PyModule_AddObject", (PYTHON_PROC*)&py3_PyModule_AddObject}, {"PyImport_AppendInittab", (PYTHON_PROC*)&py3_PyImport_AppendInittab}, {"_PyUnicode_AsString", (PYTHON_PROC*)&py3__PyUnicode_AsString}, + {"PyBytes_AsString", (PYTHON_PROC*)&py3_PyBytes_AsString}, + {"PyBytes_FromString", (PYTHON_PROC*)&py3_PyBytes_FromString}, + {"PyFloat_FromDouble", (PYTHON_PROC*)&py3_PyFloat_FromDouble}, + {"PyFloat_AsDouble", (PYTHON_PROC*)&py3_PyFloat_AsDouble}, {"PyObject_GenericGetAttr", (PYTHON_PROC*)&py3_PyObject_GenericGetAttr}, {"PyModule_Create2", (PYTHON_PROC*)&py3_PyModule_Create2}, {"PyType_GenericAlloc", (PYTHON_PROC*)&py3_PyType_GenericAlloc}, {"PyType_GenericNew", (PYTHON_PROC*)&py3_PyType_GenericNew}, {"PySlice_Type", (PYTHON_PROC*)&py3_PySlice_Type}, + {"PyFloat_Type", (PYTHON_PROC*)&py3_PyFloat_Type}, + {"PyErr_NewException", (PYTHON_PROC*)&py3_PyErr_NewException}, # ifdef Py_DEBUG {"_Py_NegativeRefcount", (PYTHON_PROC*)&py3__Py_NegativeRefcount}, {"_Py_RefTotal", (PYTHON_PROC*)&py3__Py_RefTotal}, @@ -309,6 +399,9 @@ {"PyObject_Malloc", (PYTHON_PROC*)&py3_PyObject_Malloc}, {"PyObject_Free", (PYTHON_PROC*)&py3_PyObject_Free}, # endif + {"PyType_IsSubtype", (PYTHON_PROC*)&py3_PyType_IsSubtype}, + {"PyCapsule_New", (PYTHON_PROC*)&py3_PyCapsule_New}, + {"PyCapsule_GetPointer", (PYTHON_PROC*)&py3_PyCapsule_GetPointer}, {"", NULL}, }; @@ -334,15 +427,16 @@ py3_runtime_link_init(char *libname, int verbose) { int i; - void *ucs_from_string, *ucs_from_string_and_size; + void *ucs_from_string, *ucs_decode, *ucs_as_encoded_string; -# if !defined(PY_NO_RTLD_GLOBAL) && defined(UNIX) && defined(FEAT_PYTHON) +# if !(defined(PY_NO_RTLD_GLOBAL) && defined(PY3_NO_RTLD_GLOBAL)) && defined(UNIX) && defined(FEAT_PYTHON) /* Can't have Python and Python3 loaded at the same time. * It cause a crash, because RTLD_GLOBAL is needed for * standard C extension libraries of one or both python versions. */ if (python_loaded()) { - EMSG(_("E837: This Vim cannot execute :py3 after using :python")); + if (verbose) + EMSG(_("E837: This Vim cannot execute :py3 after using :python")); return FAIL; } # endif @@ -374,19 +468,24 @@ /* Load unicode functions separately as only the ucs2 or the ucs4 functions * will be present in the library. */ ucs_from_string = symbol_from_dll(hinstPy3, "PyUnicodeUCS2_FromString"); - ucs_from_string_and_size = symbol_from_dll(hinstPy3, - "PyUnicodeUCS2_FromStringAndSize"); - if (!ucs_from_string || !ucs_from_string_and_size) + ucs_decode = symbol_from_dll(hinstPy3, + "PyUnicodeUCS2_Decode"); + ucs_as_encoded_string = symbol_from_dll(hinstPy3, + "PyUnicodeUCS2_AsEncodedString"); + if (!ucs_from_string || !ucs_decode || !ucs_as_encoded_string) { ucs_from_string = symbol_from_dll(hinstPy3, "PyUnicodeUCS4_FromString"); - ucs_from_string_and_size = symbol_from_dll(hinstPy3, - "PyUnicodeUCS4_FromStringAndSize"); + ucs_decode = symbol_from_dll(hinstPy3, + "PyUnicodeUCS4_Decode"); + ucs_as_encoded_string = symbol_from_dll(hinstPy3, + "PyUnicodeUCS4_AsEncodedString"); } - if (ucs_from_string && ucs_from_string_and_size) + if (ucs_from_string && ucs_decode && ucs_as_encoded_string) { py3_PyUnicode_FromString = ucs_from_string; - py3_PyUnicode_FromStringAndSize = ucs_from_string_and_size; + py3_PyUnicode_Decode = ucs_decode; + py3_PyUnicode_AsEncodedString = ucs_as_encoded_string; } else { @@ -437,14 +536,45 @@ static PyObject *BufferNew (buf_T *); static PyObject *WindowNew(win_T *); static PyObject *LineToString(const char *); +static PyObject *BufferDir(PyObject *, PyObject *); static PyTypeObject RangeType; +static int py3initialised = 0; + +#define PYINITIALISED py3initialised + +/* Add conversion from PyInt? */ +#define DICTKEY_GET(err) \ + if (PyBytes_Check(keyObject)) \ + key = (char_u *) PyBytes_AsString(keyObject); \ + else if (PyUnicode_Check(keyObject)) \ + { \ + bytes = PyString_AsBytes(keyObject); \ + if (bytes == NULL) \ + return err; \ + key = (char_u *) PyBytes_AsString(bytes); \ + if (key == NULL) \ + return err; \ + } \ + else \ + { \ + PyErr_SetString(PyExc_TypeError, _("only string keys are allowed")); \ + return err; \ + } +#define DICTKEY_UNREF \ + if (bytes != NULL) \ + Py_XDECREF(bytes); + +#define DICTKEY_DECL PyObject *bytes = NULL; + /* * Include the code shared with if_python.c */ #include "if_py_both.h" +#define PY3OBJ_DELETED(obj) (obj->ob_base.ob_refcnt<=0) + static void call_PyObject_Free(void *p) { @@ -474,6 +604,8 @@ static Py_ssize_t RangeStart; static Py_ssize_t RangeEnd; +static PyObject *globals; + static int PythonIO_Init(void); static void PythonIO_Fini(void); PyMODINIT_FUNC Py3Init_vim(void); @@ -482,8 +614,6 @@ * 1. Python interpreter main program. */ -static int py3initialised = 0; - static PyGILState_STATE pygilstate = PyGILState_UNLOCKED; void @@ -539,14 +669,18 @@ init_structs(); - /* initialise threads */ - PyEval_InitThreads(); + +#ifdef PYTHON3_HOME + Py_SetPythonHome(PYTHON3_HOME); +#endif #if !defined(MACOS) || defined(MACOS_X_UNIX) Py_Initialize(); #else PyMac_Initialize(); #endif + /* initialise threads, must be after Py_Initialize() */ + PyEval_InitThreads(); #ifdef DYNAMIC_PYTHON3 get_py3_exceptions(); @@ -557,11 +691,16 @@ PyImport_AppendInittab("vim", Py3Init_vim); + globals = PyModule_GetDict(PyImport_AddModule("__main__")); + /* Remove the element from sys.path that was added because of our * argv[0] value in Py3Init_vim(). Previously we used an empty * string, but dependinding on the OS we then get an empty entry or - * the current directory in sys.path. */ - PyRun_SimpleString("import sys; sys.path = list(filter(lambda x: x != '/must>not&exist', sys.path))"); + * the current directory in sys.path. + * Only after vim has been imported, the element does exist in + * sys.path. + */ + PyRun_SimpleString("import vim; import sys; sys.path = list(filter(lambda x: not x.endswith('must>not&exist'), sys.path))"); // lock is created and acquired in PyEval_InitThreads() and thread // state is created in Py_Initialize() @@ -590,7 +729,7 @@ * External interface */ static void -DoPy3Command(exarg_T *eap, const char *cmd) +DoPy3Command(exarg_T *eap, const char *cmd, typval_T *rettv) { #if defined(MACOS) && !defined(MACOS_X_UNIX) GrafPtr oldPort; @@ -598,6 +737,8 @@ #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) char *saved_locale; #endif + PyObject *cmdstr; + PyObject *cmdbytes; #if defined(MACOS) && !defined(MACOS_X_UNIX) GetPort(&oldPort); @@ -608,8 +749,16 @@ if (Python3_Init()) goto theend; - RangeStart = eap->line1; - RangeEnd = eap->line2; + if (rettv == NULL) + { + RangeStart = eap->line1; + RangeEnd = eap->line2; + } + else + { + RangeStart = (PyInt) curwin->w_cursor.lnum; + RangeEnd = RangeStart; + } Python_Release_Vim(); /* leave vim */ #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) @@ -627,7 +776,31 @@ pygilstate = PyGILState_Ensure(); - PyRun_SimpleString((char *)(cmd)); + /* PyRun_SimpleString expects a UTF-8 string. Wrong encoding may cause + * SyntaxError (unicode error). */ + cmdstr = PyUnicode_Decode(cmd, strlen(cmd), + (char *)ENC_OPT, CODEC_ERROR_HANDLER); + cmdbytes = PyUnicode_AsEncodedString(cmdstr, "utf-8", CODEC_ERROR_HANDLER); + Py_XDECREF(cmdstr); + if (rettv == NULL) + PyRun_SimpleString(PyBytes_AsString(cmdbytes)); + else + { + PyObject *r; + + r = PyRun_String(PyBytes_AsString(cmdbytes), Py_eval_input, + globals, globals); + if (r == NULL) + EMSG(_("E860: Eval did not return a valid python 3 object")); + else + { + if (ConvertFromPyObject(r, rettv) == -1) + EMSG(_("E861: Failed to convert returned python 3 object to vim value")); + Py_DECREF(r); + } + PyErr_Clear(); + } + Py_XDECREF(cmdbytes); PyGILState_Release(pygilstate); @@ -661,9 +834,9 @@ if (!eap->skip) { if (script == NULL) - DoPy3Command(eap, (char *)eap->arg); + DoPy3Command(eap, (char *)eap->arg, NULL); else - DoPy3Command(eap, (char *)script); + DoPy3Command(eap, (char *)script, NULL); } vim_free(script); } @@ -686,7 +859,10 @@ * different options under Windows, meaning that stdio pointers aren't * compatible between the two. Yuk. * - * construct: exec(compile(open('a_filename').read(), 'a_filename', 'exec')) + * construct: exec(compile(open('a_filename', 'rb').read(), 'a_filename', 'exec')) + * + * Using bytes so that Python can detect the source encoding as it normally + * does. The doc does not say "compile" accept bytes, though. * * We need to escape any backslashes or single quotes in the file name, so that * Python won't mangle the file name. @@ -709,8 +885,8 @@ return; if (i==0) { - strcpy(p,"').read(),'"); - p += 11; + strcpy(p,"','rb').read(),'"); + p += 16; } else { @@ -721,7 +897,7 @@ /* Execute the file */ - DoPy3Command(eap, buffer); + DoPy3Command(eap, buffer, NULL); } /****************************************************** @@ -751,14 +927,16 @@ if (PyUnicode_Check(nameobj)) name = _PyUnicode_AsString(nameobj); - if (val == NULL) { + if (val == NULL) + { PyErr_SetString(PyExc_AttributeError, _("can't delete OutputObject attributes")); return -1; } if (strcmp(name, "softspace") == 0) { - if (!PyLong_Check(val)) { + if (!PyLong_Check(val)) + { PyErr_SetString(PyExc_TypeError, _("softspace must be an integer")); return -1; } @@ -805,8 +983,8 @@ static Py_ssize_t BufferLength(PyObject *); static PyObject *BufferItem(PyObject *, Py_ssize_t); -static Py_ssize_t BufferAsItem(PyObject *, Py_ssize_t, PyObject *); -static PyObject* BufferSubscript(PyObject *self, PyObject* idx); +static PyObject* BufferSubscript(PyObject *self, PyObject *idx); +static Py_ssize_t BufferAsSubscript(PyObject *self, PyObject *idx, PyObject *val); /* Line range type - Implementation functions @@ -815,8 +993,9 @@ #define RangeType_Check(obj) ((obj)->ob_base.ob_type == &RangeType) -static PyObject* RangeSubscript(PyObject *self, PyObject* idx); +static PyObject* RangeSubscript(PyObject *self, PyObject *idx); static Py_ssize_t RangeAsItem(PyObject *, Py_ssize_t, PyObject *); +static Py_ssize_t RangeAsSubscript(PyObject *self, PyObject *idx, PyObject *val); /* Current objects type - Implementation functions * ----------------------------------------------- @@ -828,7 +1007,7 @@ (ssizeargfunc) 0, /* sq_repeat, x*n */ (ssizeargfunc) BufferItem, /* sq_item, x[i] */ 0, /* was_sq_slice, x[i:j] */ - (ssizeobjargproc) BufferAsItem, /* sq_ass_item, x[i]=v */ + 0, /* sq_ass_item, x[i]=v */ 0, /* sq_ass_slice, x[i:j]=v */ 0, /* sq_contains */ 0, /* sq_inplace_concat */ @@ -838,7 +1017,7 @@ PyMappingMethods BufferAsMapping = { /* mp_length */ (lenfunc)BufferLength, /* mp_subscript */ (binaryfunc)BufferSubscript, - /* mp_ass_subscript */ (objobjargproc)0, + /* mp_ass_subscript */ (objobjargproc)BufferAsSubscript, }; @@ -890,6 +1069,8 @@ if (this->buf && this->buf != INVALID_BUFFER_VALUE) this->buf->b_python3_ref = NULL; + + Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject * @@ -908,13 +1089,18 @@ return Py_BuildValue("s", this->buf->b_ffname); else if (strcmp(name, "number") == 0) return Py_BuildValue("n", this->buf->b_fnum); - else if (strcmp(name,"__members__") == 0) - return Py_BuildValue("[ss]", "name", "number"); else return PyObject_GenericGetAttr(self, nameobj); } static PyObject * +BufferDir(PyObject *self UNUSED, PyObject *args UNUSED) +{ + return Py_BuildValue("[sssss]", "name", "number", + "append", "mark", "range"); +} + + static PyObject * BufferRepr(PyObject *self) { static char repr[100]; @@ -968,37 +1154,64 @@ (Py_ssize_t)((BufferObject *)(self))->buf->b_ml.ml_line_count); } - static Py_ssize_t -BufferAsItem(PyObject *self, Py_ssize_t n, PyObject *val) -{ - return RBAsItem((BufferObject *)(self), n, val, 1, - (Py_ssize_t)((BufferObject *)(self))->buf->b_ml.ml_line_count, - NULL); -} - - static PyObject * BufferSubscript(PyObject *self, PyObject* idx) { - if (PyLong_Check(idx)) { + if (PyLong_Check(idx)) + { long _idx = PyLong_AsLong(idx); return BufferItem(self,_idx); - } else if (PySlice_Check(idx)) { + } else if (PySlice_Check(idx)) + { Py_ssize_t start, stop, step, slicelen; - if (PySlice_GetIndicesEx((PySliceObject *)idx, + if (PySlice_GetIndicesEx((PyObject *)idx, (Py_ssize_t)((BufferObject *)(self))->buf->b_ml.ml_line_count+1, &start, &stop, - &step, &slicelen) < 0) { + &step, &slicelen) < 0) + { return NULL; } - return BufferSlice(self,start,stop+1); - } else { + return BufferSlice(self, start, stop); + } + else + { PyErr_SetString(PyExc_IndexError, "Index must be int or slice"); return NULL; } } + static Py_ssize_t +BufferAsSubscript(PyObject *self, PyObject* idx, PyObject* val) +{ + if (PyLong_Check(idx)) + { + long n = PyLong_AsLong(idx); + return RBAsItem((BufferObject *)(self), n, val, 1, + (Py_ssize_t)((BufferObject *)(self))->buf->b_ml.ml_line_count, + NULL); + } else if (PySlice_Check(idx)) + { + Py_ssize_t start, stop, step, slicelen; + + if (PySlice_GetIndicesEx((PyObject *)idx, + (Py_ssize_t)((BufferObject *)(self))->buf->b_ml.ml_line_count+1, + &start, &stop, + &step, &slicelen) < 0) + { + return -1; + } + return RBAsSlice((BufferObject *)(self), start, stop, val, 1, + (PyInt)((BufferObject *)(self))->buf->b_ml.ml_line_count, + NULL); + } + else + { + PyErr_SetString(PyExc_IndexError, "Index must be int or slice"); + return -1; + } +} + static PySequenceMethods RangeAsSeq = { (lenfunc) RangeLength, /* sq_length, len(x) */ (binaryfunc) 0, /* RangeConcat, sq_concat, x+y */ @@ -1015,7 +1228,7 @@ PyMappingMethods RangeAsMapping = { /* mp_length */ (lenfunc)RangeLength, /* mp_subscript */ (binaryfunc)RangeSubscript, - /* mp_ass_subscript */ (objobjargproc)0, + /* mp_ass_subscript */ (objobjargproc)RangeAsSubscript, }; /* Line range object - Implementation @@ -1025,6 +1238,7 @@ RangeDestructor(PyObject *self) { Py_DECREF(((RangeObject *)(self))->buf); + Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject * @@ -1053,28 +1267,70 @@ &((RangeObject *)(self))->end); } + static Py_ssize_t +RangeAsSlice(PyObject *self, Py_ssize_t lo, Py_ssize_t hi, PyObject *val) +{ + return RBAsSlice(((RangeObject *)(self))->buf, lo, hi, val, + ((RangeObject *)(self))->start, + ((RangeObject *)(self))->end, + &((RangeObject *)(self))->end); +} + static PyObject * RangeSubscript(PyObject *self, PyObject* idx) { - if (PyLong_Check(idx)) { + if (PyLong_Check(idx)) + { long _idx = PyLong_AsLong(idx); return RangeItem(self,_idx); - } else if (PySlice_Check(idx)) { + } else if (PySlice_Check(idx)) + { Py_ssize_t start, stop, step, slicelen; - if (PySlice_GetIndicesEx((PySliceObject *)idx, + if (PySlice_GetIndicesEx((PyObject *)idx, ((RangeObject *)(self))->end-((RangeObject *)(self))->start+1, &start, &stop, - &step, &slicelen) < 0) { + &step, &slicelen) < 0) + { return NULL; } - return RangeSlice(self,start,stop+1); - } else { + return RangeSlice(self, start, stop); + } + else + { PyErr_SetString(PyExc_IndexError, "Index must be int or slice"); return NULL; } } + static Py_ssize_t +RangeAsSubscript(PyObject *self, PyObject *idx, PyObject *val) +{ + if (PyLong_Check(idx)) + { + long n = PyLong_AsLong(idx); + return RangeAsItem(self, n, val); + } else if (PySlice_Check(idx)) + { + Py_ssize_t start, stop, step, slicelen; + + if (PySlice_GetIndicesEx((PyObject *)idx, + ((RangeObject *)(self))->end-((RangeObject *)(self))->start+1, + &start, &stop, + &step, &slicelen) < 0) + { + return -1; + } + return RangeAsSlice(self, start, stop, val); + } + else + { + PyErr_SetString(PyExc_IndexError, "Index must be int or slice"); + return -1; + } +} + + /* Buffer list object - Definitions */ @@ -1152,6 +1408,8 @@ if (this->win && this->win != INVALID_WINDOW_VALUE) this->win->w_python3_ref = NULL; + + Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject * @@ -1279,6 +1537,147 @@ } } +/* Dictionary object - Definitions + */ + +static PyInt DictionaryLength(PyObject *); + +static PyMappingMethods DictionaryAsMapping = { + /* mp_length */ (lenfunc) DictionaryLength, + /* mp_subscript */ (binaryfunc) DictionaryItem, + /* mp_ass_subscript */ (objobjargproc) DictionaryAssItem, +}; + +static PyTypeObject DictionaryType; + + static void +DictionaryDestructor(PyObject *self) +{ + DictionaryObject *this = (DictionaryObject *)(self); + + pyll_remove(&this->ref, &lastdict); + dict_unref(this->dict); + + Py_TYPE(self)->tp_free((PyObject*)self); +} + +/* List object - Definitions + */ + +static PyInt ListLength(PyObject *); +static PyObject *ListItem(PyObject *, Py_ssize_t); + +static PySequenceMethods ListAsSeq = { + (lenfunc) ListLength, /* sq_length, len(x) */ + (binaryfunc) 0, /* RangeConcat, sq_concat, x+y */ + (ssizeargfunc) 0, /* RangeRepeat, sq_repeat, x*n */ + (ssizeargfunc) ListItem, /* sq_item, x[i] */ + (void *) 0, /* was_sq_slice, x[i:j] */ + (ssizeobjargproc) ListAssItem, /* sq_as_item, x[i]=v */ + (void *) 0, /* was_sq_ass_slice, x[i:j]=v */ + 0, /* sq_contains */ + (binaryfunc) ListConcatInPlace,/* sq_inplace_concat */ + 0, /* sq_inplace_repeat */ +}; + +static PyObject *ListSubscript(PyObject *, PyObject *); +static Py_ssize_t ListAsSubscript(PyObject *, PyObject *, PyObject *); + +static PyMappingMethods ListAsMapping = { + /* mp_length */ (lenfunc) ListLength, + /* mp_subscript */ (binaryfunc) ListSubscript, + /* mp_ass_subscript */ (objobjargproc) ListAsSubscript, +}; + +static PyTypeObject ListType; + + static PyObject * +ListSubscript(PyObject *self, PyObject* idxObject) +{ + if (PyLong_Check(idxObject)) + { + long idx = PyLong_AsLong(idxObject); + return ListItem(self, idx); + } + else if (PySlice_Check(idxObject)) + { + Py_ssize_t start, stop, step, slicelen; + + if (PySlice_GetIndicesEx(idxObject, ListLength(self), &start, &stop, + &step, &slicelen) < 0) + return NULL; + return ListSlice(self, start, stop); + } + else + { + PyErr_SetString(PyExc_IndexError, "Index must be int or slice"); + return NULL; + } +} + + static Py_ssize_t +ListAsSubscript(PyObject *self, PyObject *idxObject, PyObject *obj) +{ + if (PyLong_Check(idxObject)) + { + long idx = PyLong_AsLong(idxObject); + return ListAssItem(self, idx, obj); + } + else if (PySlice_Check(idxObject)) + { + Py_ssize_t start, stop, step, slicelen; + + if (PySlice_GetIndicesEx(idxObject, ListLength(self), &start, &stop, + &step, &slicelen) < 0) + return -1; + return ListAssSlice(self, start, stop, obj); + } + else + { + PyErr_SetString(PyExc_IndexError, "Index must be int or slice"); + return -1; + } +} + + static void +ListDestructor(PyObject *self) +{ + ListObject *this = (ListObject *)(self); + + pyll_remove(&this->ref, &lastlist); + list_unref(this->list); + + Py_TYPE(self)->tp_free((PyObject*)self); +} + +/* Function object - Definitions + */ + + static void +FunctionDestructor(PyObject *self) +{ + FunctionObject *this = (FunctionObject *) (self); + + func_unref(this->name); + PyMem_Del(this->name); + + Py_TYPE(self)->tp_free((PyObject*)self); +} + + static PyObject * +FunctionGetattro(PyObject *self, PyObject *nameobj) +{ + FunctionObject *this = (FunctionObject *)(self); + char *name = ""; + if (PyUnicode_Check(nameobj)) + name = _PyUnicode_AsString(nameobj); + + if (strcmp(name, "name") == 0) + return PyUnicode_FromString((char *)(this->name)); + + return PyObject_GenericGetAttr(self, nameobj); +} + /* External interface */ @@ -1338,13 +1737,19 @@ PyType_Ready(&BufListType); PyType_Ready(&WinListType); PyType_Ready(&CurrentType); + PyType_Ready(&DictionaryType); + PyType_Ready(&ListType); + PyType_Ready(&FunctionType); /* Set sys.argv[] to avoid a crash in warn(). */ PySys_SetArgv(1, argv); mod = PyModule_Create(&vimmodule); + if (mod == NULL) + return NULL; - VimError = Py_BuildValue("s", "vim.error"); + VimError = PyErr_NewException("vim.error", NULL, NULL); + Py_INCREF(VimError); PyModule_AddObject(mod, "error", VimError); Py_INCREF((PyObject *)(void *)&TheBufferList); @@ -1397,12 +1802,30 @@ } *p = '\0'; - result = PyUnicode_FromStringAndSize(tmp, len); + result = PyUnicode_Decode(tmp, len, (char *)ENC_OPT, CODEC_ERROR_HANDLER); vim_free(tmp); return result; } + void +do_py3eval (char_u *str, typval_T *rettv) +{ + DoPy3Command(NULL, (char *) str, rettv); + switch(rettv->v_type) + { + case VAR_DICT: ++rettv->vval.v_dict->dv_refcount; break; + case VAR_LIST: ++rettv->vval.v_list->lv_refcount; break; + case VAR_FUNC: func_ref(rettv->vval.v_string); break; + } +} + + void +set_ref_in_python3 (int copyID) +{ + set_ref_in_py(copyID); +} + static void init_structs(void) { @@ -1484,6 +1907,35 @@ CurrentType.tp_flags = Py_TPFLAGS_DEFAULT; CurrentType.tp_doc = "vim current object"; + vim_memset(&DictionaryType, 0, sizeof(DictionaryType)); + DictionaryType.tp_name = "vim.dictionary"; + DictionaryType.tp_basicsize = sizeof(DictionaryObject); + DictionaryType.tp_dealloc = DictionaryDestructor; + DictionaryType.tp_as_mapping = &DictionaryAsMapping; + DictionaryType.tp_flags = Py_TPFLAGS_DEFAULT; + DictionaryType.tp_doc = "dictionary pushing modifications to vim structure"; + DictionaryType.tp_methods = DictionaryMethods; + + vim_memset(&ListType, 0, sizeof(ListType)); + ListType.tp_name = "vim.list"; + ListType.tp_dealloc = ListDestructor; + ListType.tp_basicsize = sizeof(ListObject); + ListType.tp_as_sequence = &ListAsSeq; + ListType.tp_as_mapping = &ListAsMapping; + ListType.tp_flags = Py_TPFLAGS_DEFAULT; + ListType.tp_doc = "list pushing modifications to vim structure"; + ListType.tp_methods = ListMethods; + + vim_memset(&FunctionType, 0, sizeof(FunctionType)); + FunctionType.tp_name = "vim.list"; + FunctionType.tp_basicsize = sizeof(FunctionObject); + FunctionType.tp_getattro = FunctionGetattro; + FunctionType.tp_dealloc = FunctionDestructor; + FunctionType.tp_call = FunctionCall; + FunctionType.tp_flags = Py_TPFLAGS_DEFAULT; + FunctionType.tp_doc = "object that calls vim function"; + FunctionType.tp_methods = FunctionMethods; + vim_memset(&vimmodule, 0, sizeof(vimmodule)); vimmodule.m_name = "vim"; vimmodule.m_doc = vim_module_doc; diff -Naur vim73.orig/src/if_ruby.c vim73/src/if_ruby.c --- vim73.orig/src/if_ruby.c 2010-06-30 19:33:12.000000000 +0000 +++ vim73/src/if_ruby.c 2012-07-20 20:31:15.810976706 +0000 @@ -4,12 +4,17 @@ * * Ruby interface by Shugo Maeda * with improvements by SegPhault (Ryan Paul) + * with improvements by Jon Maken * * Do ":help uganda" in Vim to read copying and usage conditions. * Do ":help credits" in Vim to see a list of people who contributed. * See README.txt for an overview of the Vim source code. */ +#ifdef HAVE_CONFIG_H +# include "auto/config.h" +#endif + #include #include @@ -26,12 +31,12 @@ # define RUBYEXTERN extern #endif +#ifdef DYNAMIC_RUBY /* * This is tricky. In ruby.h there is (inline) function rb_class_of() * definition. This function use these variables. But we want function to * use dll_* variables. */ -#ifdef DYNAMIC_RUBY # define rb_cFalseClass (*dll_rb_cFalseClass) # define rb_cFixnum (*dll_rb_cFixnum) # define rb_cNilClass (*dll_rb_cNilClass) @@ -46,8 +51,23 @@ */ # define RUBY_EXPORT # endif + +#if !(defined(WIN32) || defined(_WIN64)) +# include +# define HINSTANCE void* +# define RUBY_PROC void* +# define load_dll(n) dlopen((n), RTLD_LAZY|RTLD_GLOBAL) +# define symbol_from_dll dlsym +# define close_dll dlclose +#else +# define RUBY_PROC FARPROC +# define load_dll vimLoadLib +# define symbol_from_dll GetProcAddress +# define close_dll FreeLibrary #endif +#endif /* ifdef DYNAMIC_RUBY */ + /* suggested by Ariya Mizutani */ #if (_MSC_VER == 1200) # undef _WIN32_WINNT @@ -70,6 +90,7 @@ # include #endif +#undef off_t /* ruby defines off_t as _int64, Mingw uses long */ #undef EXTERN #undef _ @@ -160,28 +181,35 @@ #define rb_lastline_get dll_rb_lastline_get #define rb_lastline_set dll_rb_lastline_set #define rb_load_protect dll_rb_load_protect +#ifndef RUBY19_OR_LATER #define rb_num2long dll_rb_num2long +#endif #define rb_num2ulong dll_rb_num2ulong #define rb_obj_alloc dll_rb_obj_alloc #define rb_obj_as_string dll_rb_obj_as_string #define rb_obj_id dll_rb_obj_id #define rb_raise dll_rb_raise -#define rb_str2cstr dll_rb_str2cstr #define rb_str_cat dll_rb_str_cat #define rb_str_concat dll_rb_str_concat #define rb_str_new dll_rb_str_new #ifdef rb_str_new2 /* Ruby may #define rb_str_new2 to use rb_str_new_cstr. */ # define need_rb_str_new_cstr 1 +/* Ruby's headers #define rb_str_new_cstr to make use of GCC's + * __builtin_constant_p extension. */ +# undef rb_str_new_cstr # define rb_str_new_cstr dll_rb_str_new_cstr #else # define rb_str_new2 dll_rb_str_new2 #endif #if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18 +# define rb_string_value dll_rb_string_value # define rb_string_value_ptr dll_rb_string_value_ptr # define rb_float_new dll_rb_float_new # define rb_ary_new dll_rb_ary_new # define rb_ary_push dll_rb_ary_push +#else +# define rb_str2cstr dll_rb_str2cstr #endif #ifdef RUBY19_OR_LATER # define rb_errinfo dll_rb_errinfo @@ -190,9 +218,11 @@ #endif #define ruby_init dll_ruby_init #define ruby_init_loadpath dll_ruby_init_loadpath -#define NtInitialize dll_NtInitialize -#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18 -# define rb_w32_snprintf dll_rb_w32_snprintf +#ifdef WIN3264 +# define NtInitialize dll_NtInitialize +# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18 +# define rb_w32_snprintf dll_rb_w32_snprintf +# endif #endif #ifdef RUBY19_OR_LATER @@ -201,7 +231,9 @@ # define rb_enc_find dll_rb_enc_find # define rb_enc_str_new dll_rb_enc_str_new # define rb_sprintf dll_rb_sprintf +# define rb_require dll_rb_require # define ruby_init_stack dll_ruby_init_stack +# define ruby_process_options dll_ruby_process_options #endif /* @@ -246,7 +278,11 @@ static VALUE (*dll_rb_obj_as_string) (VALUE); static VALUE (*dll_rb_obj_id) (VALUE); static void (*dll_rb_raise) (VALUE, const char*, ...); +#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18 +static VALUE (*dll_rb_string_value) (volatile VALUE*); +#else static char *(*dll_rb_str2cstr) (VALUE,int*); +#endif static VALUE (*dll_rb_str_cat) (VALUE, const char*, long); static VALUE (*dll_rb_str_concat) (VALUE, VALUE); static VALUE (*dll_rb_str_new) (const char*, long); @@ -263,7 +299,12 @@ #endif static void (*dll_ruby_init) (void); static void (*dll_ruby_init_loadpath) (void); +#ifdef WIN3264 static void (*dll_NtInitialize) (int*, char***); +# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18 +static int (*dll_rb_w32_snprintf)(char*, size_t, const char*, ...); +# endif +#endif #if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18 static char * (*dll_rb_string_value_ptr) (volatile VALUE*); static VALUE (*dll_rb_float_new) (double); @@ -273,9 +314,6 @@ #ifdef RUBY19_OR_LATER static VALUE (*dll_rb_int2big)(SIGNED_VALUE); #endif -#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18 -static int (*dll_rb_w32_snprintf)(char*, size_t, const char*, ...); -#endif #ifdef RUBY19_OR_LATER static void (*dll_ruby_script) (const char*); @@ -283,7 +321,9 @@ static rb_encoding* (*dll_rb_enc_find) (const char*); static VALUE (*dll_rb_enc_str_new) (const char*, long, rb_encoding*); static VALUE (*dll_rb_sprintf) (const char*, ...); +static VALUE (*dll_rb_require) (const char*); static void (*ruby_init_stack)(VALUE*); +static void* (*ruby_process_options)(int, char**); #endif #ifdef RUBY19_OR_LATER @@ -297,12 +337,11 @@ } #endif -static HINSTANCE hinstRuby = 0; /* Instance of ruby.dll */ +static HINSTANCE hinstRuby = NULL; /* Instance of ruby.dll */ /* * Table of name to function pointer of ruby. */ -#define RUBY_PROC FARPROC static struct { char *name; @@ -347,7 +386,11 @@ {"rb_obj_as_string", (RUBY_PROC*)&dll_rb_obj_as_string}, {"rb_obj_id", (RUBY_PROC*)&dll_rb_obj_id}, {"rb_raise", (RUBY_PROC*)&dll_rb_raise}, +#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18 + {"rb_string_value", (RUBY_PROC*)&dll_rb_string_value}, +#else {"rb_str2cstr", (RUBY_PROC*)&dll_rb_str2cstr}, +#endif {"rb_str_cat", (RUBY_PROC*)&dll_rb_str_cat}, {"rb_str_concat", (RUBY_PROC*)&dll_rb_str_concat}, {"rb_str_new", (RUBY_PROC*)&dll_rb_str_new}, @@ -363,15 +406,17 @@ #endif {"ruby_init", (RUBY_PROC*)&dll_ruby_init}, {"ruby_init_loadpath", (RUBY_PROC*)&dll_ruby_init_loadpath}, +#ifdef WIN3264 { -#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER < 19 +# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER < 19 "NtInitialize", -#else +# else "ruby_sysinit", -#endif +# endif (RUBY_PROC*)&dll_NtInitialize}, -#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18 +# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18 {"rb_w32_snprintf", (RUBY_PROC*)&dll_rb_w32_snprintf}, +# endif #endif #if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18 {"rb_string_value_ptr", (RUBY_PROC*)&dll_rb_string_value_ptr}, @@ -386,7 +431,9 @@ {"rb_enc_find", (RUBY_PROC*)&dll_rb_enc_find}, {"rb_enc_str_new", (RUBY_PROC*)&dll_rb_enc_str_new}, {"rb_sprintf", (RUBY_PROC*)&dll_rb_sprintf}, + {"rb_require", (RUBY_PROC*)&dll_rb_require}, {"ruby_init_stack", (RUBY_PROC*)&dll_ruby_init_stack}, + {"ruby_process_options", (RUBY_PROC*)&dll_ruby_process_options}, #endif {"", NULL}, }; @@ -399,8 +446,8 @@ { if (hinstRuby) { - FreeLibrary(hinstRuby); - hinstRuby = 0; + close_dll(hinstRuby); + hinstRuby = NULL; } } @@ -416,7 +463,7 @@ if (hinstRuby) return OK; - hinstRuby = LoadLibrary(libname); + hinstRuby = load_dll(libname); if (!hinstRuby) { if (verbose) @@ -426,11 +473,11 @@ for (i = 0; ruby_funcname_table[i].ptr; ++i) { - if (!(*ruby_funcname_table[i].ptr = GetProcAddress(hinstRuby, + if (!(*ruby_funcname_table[i].ptr = symbol_from_dll(hinstRuby, ruby_funcname_table[i].name))) { - FreeLibrary(hinstRuby); - hinstRuby = 0; + close_dll(hinstRuby); + hinstRuby = NULL; if (verbose) EMSG2(_(e_loadfunc), ruby_funcname_table[i].name); return FAIL; @@ -539,9 +586,9 @@ if (u_save(eap->line1 - 1, eap->line2 + 1) != OK) return; for (i = eap->line1; i <= eap->line2; i++) { - VALUE line, oldline; + VALUE line; - line = oldline = vim_str2rb_enc_str((char *)ml_get(i)); + line = vim_str2rb_enc_str((char *)ml_get(i)); rb_lastline_set(line); eval_enc_string_protect((char *) eap->arg, &state); if (state) { @@ -616,13 +663,16 @@ ruby_init(); } #ifdef RUBY19_OR_LATER + { + int dummy_argc = 2; + char *dummy_argv[] = {"vim-ruby", "-e0"}; + ruby_process_options(dummy_argc, dummy_argv); + } ruby_script("vim-ruby"); -#endif +#else ruby_init_loadpath(); - ruby_io_init(); -#ifdef RUBY19_OR_LATER - rb_enc_find_index("encdb"); #endif + ruby_io_init(); ruby_vim_init(); ruby_initialized = 1; #ifdef DYNAMIC_RUBY @@ -711,11 +761,19 @@ char *buff, *p; str = rb_obj_as_string(str); - buff = ALLOCA_N(char, RSTRING_LEN(str)); - strcpy(buff, RSTRING_PTR(str)); - p = strchr(buff, '\n'); - if (p) *p = '\0'; - MSG(buff); + if (RSTRING_LEN(str) > 0) + { + /* Only do this when the string isn't empty, alloc(0) causes trouble. */ + buff = ALLOCA_N(char, RSTRING_LEN(str)); + strcpy(buff, RSTRING_PTR(str)); + p = strchr(buff, '\n'); + if (p) *p = '\0'; + MSG(buff); + } + else + { + MSG(""); + } return Qnil; } @@ -906,15 +964,9 @@ static VALUE get_buffer_line(buf_T *buf, linenr_T n) { - if (n > 0 && n <= buf->b_ml.ml_line_count) - { - char *line = (char *)ml_get_buf(buf, n, FALSE); - return line ? vim_str2rb_enc_str(line) : Qnil; - } - rb_raise(rb_eIndexError, "line number %ld out of range", (long)n); -#ifndef __GNUC__ - return Qnil; /* For stop warning */ -#endif + if (n <= 0 || n > buf->b_ml.ml_line_count) + rb_raise(rb_eIndexError, "line number %ld out of range", (long)n); + return vim_str2rb_enc_str((char *)ml_get_buf(buf, n, FALSE)); } static VALUE buffer_aref(VALUE self, VALUE num) @@ -953,9 +1005,6 @@ else { rb_raise(rb_eIndexError, "line number %ld out of range", (long)n); -#ifndef __GNUC__ - return Qnil; /* For stop warning */ -#endif } return str; } @@ -1010,7 +1059,8 @@ long n = NUM2LONG(num); aco_save_T aco; - if (line == NULL) { + if (line == NULL) + { rb_raise(rb_eIndexError, "NULL line"); } else if (n >= 0 && n <= buf->b_ml.ml_line_count) @@ -1034,7 +1084,8 @@ update_curbuf(NOT_VALID); } - else { + else + { rb_raise(rb_eIndexError, "line number %ld out of range", n); } return str; @@ -1187,6 +1238,11 @@ return Qnil; } +static VALUE f_nop(VALUE self UNUSED) +{ + return Qnil; +} + static VALUE f_p(int argc, VALUE *argv, VALUE self UNUSED) { int i; @@ -1208,6 +1264,7 @@ rb_stdout = rb_obj_alloc(rb_cObject); rb_define_singleton_method(rb_stdout, "write", vim_message, 1); + rb_define_singleton_method(rb_stdout, "flush", f_nop, 0); rb_define_global_function("p", f_p, -1); } diff -Naur vim73.orig/src/if_sniff.c vim73/src/if_sniff.c --- vim73.orig/src/if_sniff.c 2010-05-15 11:04:06.000000000 +0000 +++ vim73/src/if_sniff.c 2012-07-20 20:31:08.870971712 +0000 @@ -9,7 +9,6 @@ #ifdef WIN32 # include -# include "vimio.h" # include # include # include diff -Naur vim73.orig/src/if_tcl.c vim73/src/if_tcl.c --- vim73.orig/src/if_tcl.c 2010-08-08 13:07:25.000000000 +0000 +++ vim73/src/if_tcl.c 2012-07-20 20:31:14.990976118 +0000 @@ -74,18 +74,18 @@ #endif #include -#include #include typedef struct { Tcl_Interp *interp; + int exitvalue; int range_start, range_end; int lbase; char *curbuf, *curwin; } tcl_info; -static tcl_info tclinfo = { NULL, 0, 0, 0, NULL, NULL }; +static tcl_info tclinfo = { NULL, 0, 0, 0, 0, NULL, NULL }; #define VAR_RANGE1 "::vim::range(start)" #define VAR_RANGE2 "::vim::range(begin)" @@ -280,16 +280,19 @@ ****************************************************************************/ /* - * Replace standard "exit" and "catch" commands. + * Replace standard "exit" command. * - * This is a design flaw in Tcl - the standard "exit" command just calls - * exit() and kills the application. It should return TCL_EXIT to the - * app, which then decides if it wants to terminate or not. In our case, - * we just delete the Tcl interpreter (and create a new one with the next - * :tcl command). + * Delete the Tcl interpreter; a new one will be created with the next + * :tcl command). The exit code is saved (and retrieved in tclexit()). + * Since Tcl's exit is never expected to return and this replacement + * does, then (except for a trivial case) additional Tcl commands will + * be run. Since the interpreter is now marked as deleted, an error + * will be returned -- typically "attempt to call eval in deleted + * interpreter". Hopefully, at this point, checks for TCL_ERROR take + * place and control percolates back up to Vim -- but with this new error + * string in the interpreter's result value. Therefore it would be + * useless for this routine to return the exit code via Tcl_SetResult(). */ -#define TCL_EXIT 5 - static int exitcmd(dummy, interp, objc, objv) ClientData dummy UNUSED; @@ -306,47 +309,12 @@ break; /* FALLTHROUGH */ case 1: - Tcl_SetObjResult(interp, Tcl_NewIntObj(value)); - return TCL_EXIT; - default: - Tcl_WrongNumArgs(interp, 1, objv, "?returnCode?"); - } - return TCL_ERROR; -} + tclinfo.exitvalue = value; - static int -catchcmd(dummy, interp, objc, objv) - ClientData dummy UNUSED; - Tcl_Interp *interp; - int objc; - Tcl_Obj *CONST objv[]; -{ - char *varname = NULL; - int result; - - switch (objc) - { - case 3: - varname = Tcl_GetStringFromObj(objv[2], NULL); - /* fallthrough */ - case 2: - Tcl_ResetResult(interp); - Tcl_AllowExceptions(interp); - result = Tcl_EvalObj(interp, objv[1]); - if (result == TCL_EXIT) - return result; - if (varname) - { - if (Tcl_SetVar(interp, varname, Tcl_GetStringResult(interp), 0) == NULL) - { - Tcl_SetResult(interp, "couldn't save command result in variable", TCL_STATIC); - return TCL_ERROR; - } - } - Tcl_SetObjResult(interp, Tcl_NewIntObj(result)); - return TCL_OK; + Tcl_DeleteInterp(interp); + break; default: - Tcl_WrongNumArgs(interp, 1, objv, "command ?varName?"); + Tcl_WrongNumArgs(interp, 1, objv, "?returnCode?"); } return TCL_ERROR; } @@ -373,6 +341,7 @@ /* * "::vim::buffer list" - create a list of buffer commands. * "::vim::buffer {N}" - create buffer command for buffer N. + * "::vim::buffer exists {N}" - test if buffer N exists. * "::vim::buffer new" - create a new buffer (not implemented) */ static int @@ -1664,7 +1633,7 @@ static Tcl_ChannelType channel_type = { "vimmessage", /* typeName */ - NULL, /* version */ + TCL_CHANNEL_VERSION_2, /* version */ channel_close, /* closeProc */ channel_input, /* inputProc */ channel_output, /* outputProc */ @@ -1679,6 +1648,8 @@ NULL, /* flushProc */ NULL, /* handlerProc */ #endif +/* The following should not be necessary since TCL_CHANNEL_VERSION_2 was + * set above */ #ifdef TCL_CHANNEL_VERSION_3 NULL, /* wideSeekProc */ #endif @@ -1742,7 +1713,9 @@ Tcl_Interp *interp; static Tcl_Channel ch1, ch2; - /* replace stdout and stderr */ + /* Create replacement channels for stdout and stderr; this has to be + * done each time an interpreter is created since the channels are closed + * when the interpreter is deleted */ ch1 = Tcl_CreateChannel(&channel_type, "vimout", VIMOUT, TCL_WRITABLE); ch2 = Tcl_CreateChannel(&channel_type, "vimerr", VIMERR, TCL_WRITABLE); Tcl_SetStdChannel(ch1, TCL_STDOUT); @@ -1762,15 +1735,18 @@ #endif Tcl_SetChannelOption(interp, ch1, "-buffering", "line"); +#ifdef WIN3264 + Tcl_SetChannelOption(interp, ch1, "-translation", "lf"); +#endif Tcl_SetChannelOption(interp, ch2, "-buffering", "line"); +#ifdef WIN3264 + Tcl_SetChannelOption(interp, ch2, "-translation", "lf"); +#endif - /* replace some standard Tcl commands */ + /* replace standard Tcl exit command */ Tcl_DeleteCommand(interp, "exit"); Tcl_CreateObjCommand(interp, "exit", exitcmd, (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL); - Tcl_DeleteCommand(interp, "catch"); - Tcl_CreateObjCommand(interp, "catch", catchcmd, - (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL); /* new commands, in ::vim namespace */ Tcl_CreateObjCommand(interp, "::vim::buffer", buffercmd, @@ -1822,6 +1798,8 @@ tclinfo.range_end = row2tcl(eap->line2); tclupdatevars(); } + + tclinfo.exitvalue = 0; return OK; } @@ -1885,30 +1863,23 @@ { int newerr = OK; - if (error == TCL_EXIT ) + if (Tcl_InterpDeleted(tclinfo.interp) /* True if we intercepted Tcl's exit command */ +#if (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION >= 5) || TCL_MAJOR_VERSION > 8 + || Tcl_LimitExceeded(tclinfo.interp) /* True if the interpreter cannot continue */ +#endif + ) { - int retval; char buf[50]; - Tcl_Obj *robj; - robj = Tcl_GetObjResult(tclinfo.interp); - if( Tcl_GetIntFromObj(tclinfo.interp, robj, &retval) != TCL_OK ) + sprintf(buf, _("E572: exit code %d"), tclinfo.exitvalue); + tclerrmsg(buf); + if (tclinfo.exitvalue == 0) { - EMSG(_("E281: TCL ERROR: exit code is not int!? Please report this to vim-dev@vim.org")); - newerr = FAIL; + did_emsg = 0; + newerr = OK; } else - { - sprintf(buf, _("E572: exit code %d"), retval); - tclerrmsg(buf); - if (retval == 0 ) - { - did_emsg = 0; - newerr = OK; - } - else - newerr = FAIL; - } + newerr = FAIL; tcldelthisinterp(); } @@ -2022,7 +1993,12 @@ Tcl_SetVar(tclinfo.interp, var_line, line, 0); Tcl_AllowExceptions(tclinfo.interp); err = Tcl_Eval(tclinfo.interp, script); - if (err != TCL_OK) + if (err != TCL_OK + || Tcl_InterpDeleted(tclinfo.interp) +#if (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION >= 5) || TCL_MAJOR_VERSION > 8 + || Tcl_LimitExceeded(tclinfo.interp) +#endif + ) break; line = (char *)Tcl_GetVar(tclinfo.interp, var_line, 0); if (line) diff -Naur vim73.orig/src/if_xcmdsrv.c vim73/src/if_xcmdsrv.c --- vim73.orig/src/if_xcmdsrv.c 2010-05-15 11:04:08.000000000 +0000 +++ vim73/src/if_xcmdsrv.c 2012-07-20 20:31:17.997644938 +0000 @@ -572,61 +572,55 @@ { time_t start; time_t now; - time_t lastChk = 0; XEvent event; - XPropertyEvent *e = (XPropertyEvent *)&event; -# define SEND_MSEC_POLL 50 + +#define UI_MSEC_DELAY 50 +#define SEND_MSEC_POLL 500 +#ifndef HAVE_SELECT + struct pollfd fds; + + fds.fd = ConnectionNumber(dpy); + fds.events = POLLIN; +#else + fd_set fds; + struct timeval tv; + + tv.tv_sec = 0; + tv.tv_usec = SEND_MSEC_POLL * 1000; + FD_ZERO(&fds); + FD_SET(ConnectionNumber(dpy), &fds); +#endif time(&start); - while (endCond(endData) == 0) + while (TRUE) { + while (XCheckWindowEvent(dpy, commWindow, PropertyChangeMask, &event)) + serverEventProc(dpy, &event); + + if (endCond(endData) != 0) + break; + if (!WindowValid(dpy, w)) + break; time(&now); if (seconds >= 0 && (now - start) >= seconds) break; - if (now != lastChk) - { - lastChk = now; - if (!WindowValid(dpy, w)) - break; - /* - * Sometimes the PropertyChange event doesn't come. - * This can be seen in eg: vim -c 'echo remote_expr("gvim", "3+2")' - */ - serverEventProc(dpy, NULL); - } + + /* Just look out for the answer without calling back into Vim */ if (localLoop) { - /* Just look out for the answer without calling back into Vim */ #ifndef HAVE_SELECT - struct pollfd fds; - - fds.fd = ConnectionNumber(dpy); - fds.events = POLLIN; if (poll(&fds, 1, SEND_MSEC_POLL) < 0) break; #else - fd_set fds; - struct timeval tv; - - tv.tv_sec = 0; - tv.tv_usec = SEND_MSEC_POLL * 1000; - FD_ZERO(&fds); - FD_SET(ConnectionNumber(dpy), &fds); - if (select(ConnectionNumber(dpy) + 1, &fds, NULL, NULL, &tv) < 0) + if (select(FD_SETSIZE, &fds, NULL, NULL, &tv) < 0) break; #endif - while (XEventsQueued(dpy, QueuedAfterReading) > 0) - { - XNextEvent(dpy, &event); - if (event.type == PropertyNotify && e->window == commWindow) - serverEventProc(dpy, &event); - } } else { if (got_int) break; - ui_delay((long)SEND_MSEC_POLL, TRUE); + ui_delay((long)UI_MSEC_DELAY, TRUE); ui_breakcheck(); } } @@ -655,7 +649,6 @@ if (SendInit(dpy) < 0) return NULL; } - ga_init2(&ga, 1, 100); /* * Read the registry property. @@ -1198,9 +1191,8 @@ if ((*p == 'c' || *p == 'k') && (p[1] == 0)) { Window resWindow; - char_u *name, *script, *serial, *end, *res; + char_u *name, *script, *serial, *end; Bool asKeys = *p == 'k'; - garray_T reply; char_u *enc; /* @@ -1256,50 +1248,52 @@ if (script == NULL || name == NULL) continue; - /* - * Initialize the result property, so that we're ready at any - * time if we need to return an error. - */ - if (resWindow != None) - { - ga_init2(&reply, 1, 100); + if (serverName != NULL && STRICMP(name, serverName) == 0) + { + script = serverConvert(enc, script, &tofree); + if (asKeys) + server_to_input_buf(script); + else + { + char_u *res; + + res = eval_client_expr_to_string(script); + if (resWindow != None) + { + garray_T reply; + + /* Initialize the result property. */ + ga_init2(&reply, 1, 100); #ifdef FEAT_MBYTE - ga_grow(&reply, 50 + STRLEN(p_enc)); - sprintf(reply.ga_data, "%cr%c-E %s%c-s %s%c-r ", + ga_grow(&reply, 50 + STRLEN(p_enc)); + sprintf(reply.ga_data, "%cr%c-E %s%c-s %s%c-r ", 0, 0, p_enc, 0, serial, 0); - reply.ga_len = 14 + STRLEN(p_enc) + STRLEN(serial); + reply.ga_len = 14 + STRLEN(p_enc) + STRLEN(serial); #else - ga_grow(&reply, 50); - sprintf(reply.ga_data, "%cr%c-s %s%c-r ", 0, 0, serial, 0); - reply.ga_len = 10 + STRLEN(serial); + ga_grow(&reply, 50); + sprintf(reply.ga_data, "%cr%c-s %s%c-r ", + 0, 0, serial, 0); + reply.ga_len = 10 + STRLEN(serial); #endif - } - res = NULL; - if (serverName != NULL && STRICMP(name, serverName) == 0) - { - script = serverConvert(enc, script, &tofree); - if (asKeys) - server_to_input_buf(script); - else - res = eval_client_expr_to_string(script); - vim_free(tofree); - } - if (resWindow != None) - { - if (res != NULL) - ga_concat(&reply, res); - else if (asKeys == 0) - { - ga_concat(&reply, (char_u *)_(e_invexprmsg)); - ga_append(&reply, 0); - ga_concat(&reply, (char_u *)"-c 1"); - } - ga_append(&reply, NUL); - (void)AppendPropCarefully(dpy, resWindow, commProperty, - reply.ga_data, reply.ga_len); - ga_clear(&reply); - } - vim_free(res); + + /* Evaluate the expression and return the result. */ + if (res != NULL) + ga_concat(&reply, res); + else + { + ga_concat(&reply, (char_u *)_(e_invexprmsg)); + ga_append(&reply, 0); + ga_concat(&reply, (char_u *)"-c 1"); + } + ga_append(&reply, NUL); + (void)AppendPropCarefully(dpy, resWindow, commProperty, + reply.ga_data, reply.ga_len); + ga_clear(&reply); + } + vim_free(res); + } + vim_free(tofree); + } } else if (*p == 'r' && p[1] == 0) { diff -Naur vim73.orig/src/integration.c vim73/src/integration.c --- vim73.orig/src/integration.c 2010-08-08 13:09:21.000000000 +0000 +++ vim73/src/integration.c 2012-07-20 20:31:08.974305120 +0000 @@ -33,7 +33,6 @@ #include #endif -#include #include #include #include diff -Naur vim73.orig/src/keymap.h vim73/src/keymap.h --- vim73.orig/src/keymap.h 2010-07-25 13:14:04.000000000 +0000 +++ vim73/src/keymap.h 2012-07-20 20:31:14.177642201 +0000 @@ -92,13 +92,13 @@ */ #define KS_TEAROFF 244 -/* used for JSB term mouse */ +/* Used for JSB term mouse. */ #define KS_JSBTERM_MOUSE 243 -/* used a termcap entry that produces a normal character */ +/* Used a termcap entry that produces a normal character. */ #define KS_KEY 242 -/* Used for the qnx pterm mouse */ +/* Used for the qnx pterm mouse. */ #define KS_PTERM_MOUSE 241 /* Used for click in a tab pages label. */ @@ -107,6 +107,9 @@ /* Used for menu in a tab pages line. */ #define KS_TABMENU 239 +/* Used for the urxvt mouse. */ +#define KS_URXVT_MOUSE 238 + /* * Filler used after KS_SPECIAL and others */ @@ -408,6 +411,7 @@ #define K_DEC_MOUSE TERMCAP2KEY(KS_DEC_MOUSE, KE_FILLER) #define K_JSBTERM_MOUSE TERMCAP2KEY(KS_JSBTERM_MOUSE, KE_FILLER) #define K_PTERM_MOUSE TERMCAP2KEY(KS_PTERM_MOUSE, KE_FILLER) +#define K_URXVT_MOUSE TERMCAP2KEY(KS_URXVT_MOUSE, KE_FILLER) #define K_SELECT TERMCAP2KEY(KS_SELECT, KE_FILLER) #define K_TEAROFF TERMCAP2KEY(KS_TEAROFF, KE_FILLER) diff -Naur vim73.orig/src/link.sh vim73/src/link.sh --- vim73.orig/src/link.sh 2010-07-21 19:43:29.000000000 +0000 +++ vim73/src/link.sh 2012-07-20 20:31:08.227637914 +0000 @@ -5,7 +5,7 @@ # libraries when they exist, but this doesn't mean they are needed for Vim. # # Author: Bram Moolenaar -# Last change: 2006 Sep 26 +# Last change: 2010 Nov 03 # License: Public domain # # Warning: This fails miserably if the linker doesn't return an error code! @@ -16,11 +16,23 @@ echo "$LINK " >link.cmd exit_value=0 +if test "$LINK_AS_NEEDED" = yes; then + echo "link.sh: \$LINK_AS_NEEDED set to 'yes': invoking linker directly." + cat link.cmd + if sh link.cmd; then + exit_value=0 + echo "link.sh: Linked fine" + else + exit_value=$? + echo "link.sh: Linking failed" + fi +else + if test -f auto/link.sed; then + # # If auto/link.sed already exists, use it. We assume a previous run of # link.sh has found the correct set of libraries. # -if test -f auto/link.sed; then echo "link.sh: The file 'auto/link.sed' exists, which is going to be used now." echo "link.sh: If linking fails, try deleting the auto/link.sed file." echo "link.sh: If this fails too, try creating an empty auto/link.sed file." @@ -124,6 +136,8 @@ fi fi +fi + # # cleanup # diff -Naur vim73.orig/src/macros.h vim73/src/macros.h --- vim73.orig/src/macros.h 2010-07-17 19:41:21.000000000 +0000 +++ vim73/src/macros.h 2012-07-20 20:31:18.307645159 +0000 @@ -259,6 +259,8 @@ * PTR2CHAR(): get character from pointer. */ #ifdef FEAT_MBYTE +/* Get the length of the character p points to */ +# define MB_PTR2LEN(p) (has_mbyte ? (*mb_ptr2len)(p) : 1) /* Advance multi-byte pointer, skip over composing chars. */ # define mb_ptr_adv(p) p += has_mbyte ? (*mb_ptr2len)(p) : 1 /* Advance multi-byte pointer, do not skip over composing chars. */ @@ -272,6 +274,7 @@ # define MB_CHARLEN(p) (has_mbyte ? mb_charlen(p) : (int)STRLEN(p)) # define PTR2CHAR(p) (has_mbyte ? mb_ptr2char(p) : (int)*(p)) #else +# define MB_PTR2LEN(p) 1 # define mb_ptr_adv(p) ++p # define mb_cptr_adv(p) ++p # define mb_ptr_back(s, p) --p @@ -285,3 +288,17 @@ #else # define DO_AUTOCHDIR #endif + +#if defined(FEAT_SCROLLBIND) && defined(FEAT_CURSORBIND) +# define RESET_BINDING(wp) (wp)->w_p_scb = FALSE; (wp)->w_p_crb = FALSE +#else +# if defined(FEAT_SCROLLBIND) +# define RESET_BINDING(wp) (wp)->w_p_scb = FALSE +# else +# if defined(FEAT_CURSORBIND) +# define RESET_BINDING(wp) (wp)->w_p_crb = FALSE +# else +# define RESET_BINDING(wp) +# endif +# endif +#endif diff -Naur vim73.orig/src/main.c vim73/src/main.c --- vim73.orig/src/main.c 2010-08-08 13:09:55.000000000 +0000 +++ vim73/src/main.c 2012-07-20 20:31:15.920976784 +0000 @@ -7,10 +7,6 @@ * See README.txt for an overview of the Vim source code. */ -#if defined(MSDOS) || defined(WIN16) || defined(WIN32) || defined(_WIN64) -# include "vimio.h" /* for close() and dup() */ -#endif - #define EXTERN #include "vim.h" @@ -96,37 +92,39 @@ #define EDIT_TAG 3 /* tag name argument given, use tagname */ #define EDIT_QF 4 /* start in quickfix mode */ -#if defined(UNIX) || defined(VMS) +#if (defined(UNIX) || defined(VMS)) && !defined(NO_VIM_MAIN) static int file_owned __ARGS((char *fname)); #endif static void mainerr __ARGS((int, char_u *)); +#ifndef NO_VIM_MAIN static void main_msg __ARGS((char *s)); static void usage __ARGS((void)); static int get_number_arg __ARGS((char_u *p, int *idx, int def)); -#if defined(HAVE_LOCALE_H) || defined(X_LOCALE) +# if defined(HAVE_LOCALE_H) || defined(X_LOCALE) static void init_locale __ARGS((void)); -#endif +# endif static void parse_command_name __ARGS((mparm_T *parmp)); static void early_arg_scan __ARGS((mparm_T *parmp)); static void command_line_scan __ARGS((mparm_T *parmp)); static void check_tty __ARGS((mparm_T *parmp)); static void read_stdin __ARGS((void)); static void create_windows __ARGS((mparm_T *parmp)); -#ifdef FEAT_WINDOWS +# ifdef FEAT_WINDOWS static void edit_buffers __ARGS((mparm_T *parmp)); -#endif +# endif static void exe_pre_commands __ARGS((mparm_T *parmp)); static void exe_commands __ARGS((mparm_T *parmp)); static void source_startup_scripts __ARGS((mparm_T *parmp)); static void main_start_gui __ARGS((void)); -#if defined(HAS_SWAP_EXISTS_ACTION) +# if defined(HAS_SWAP_EXISTS_ACTION) static void check_swap_exists_action __ARGS((void)); -#endif -#ifdef FEAT_CLIENTSERVER +# endif +# if defined(FEAT_CLIENTSERVER) || defined(PROTO) static void exec_on_server __ARGS((mparm_T *parmp)); static void prepare_server __ARGS((mparm_T *parmp)); static void cmdsrv_main __ARGS((int *argc, char **argv, char_u *serverName_arg, char_u **serverStr)); static char_u *serverMakeName __ARGS((char_u *arg, char *cmd)); +# endif #endif @@ -149,7 +147,8 @@ #define ME_INVALID_ARG 5 }; -#ifndef PROTO /* don't want a prototype for main() */ +#ifndef NO_VIM_MAIN /* skip this for unittests */ +#ifndef PROTO /* don't want a prototype for main() */ int # ifdef VIMDLL _export @@ -555,6 +554,31 @@ debug_break_level = params.use_debug_break_level; #endif +#ifdef FEAT_MZSCHEME + /* + * Newer version of MzScheme (Racket) require earlier (trampolined) + * initialisation via scheme_main_setup. + * Implement this by initialising it as early as possible + * and splitting off remaining Vim main into vim_main2 + */ + { + /* Pack up preprocessed command line arguments. + * It is safe because Scheme does not access argc/argv. */ + char *args[2]; + args[0] = (char *)fname; + args[1] = (char *)¶ms; + return mzscheme_main(2, args); + } +} + +int vim_main2(int argc, char **argv) +{ + char_u *fname = (char_u *)argv[0]; + mparm_T params; + + memcpy(¶ms, argv[1], sizeof(params)); +#endif + /* Execute --cmd arguments. */ exe_pre_commands(¶ms); @@ -904,6 +928,18 @@ TIME_MSG("VimEnter autocommands"); #endif +#if defined(FEAT_EVAL) && defined(FEAT_CLIPBOARD) + /* Adjust default register name for "unnamed" in 'clipboard'. Can only be + * done after the clipboard is available and all initial commands that may + * modify the 'clipboard' setting have run; i.e. just before entering the + * main loop. */ + { + int default_regname = 0; + adjust_clip_reg(&default_regname); + set_reg_var(default_regname); + } +#endif + #if defined(FEAT_DIFF) && defined(FEAT_SCROLLBIND) /* When a startup script or session file setup for diff'ing and * scrollbind, sync the scrollbind now. */ @@ -940,7 +976,7 @@ if (netbeansArg != NULL && strncmp("-nb", netbeansArg, 3) == 0) { # ifdef FEAT_GUI -# if !defined(FEAT_GUI_MOTIF) && !defined(FEAT_GUI_GTK) \ +# if !defined(FEAT_GUI_X11) && !defined(FEAT_GUI_GTK) \ && !defined(FEAT_GUI_W32) if (gui.in_use) { @@ -958,18 +994,13 @@ /* * Call the main command loop. This never returns. - * For embedded MzScheme the main_loop will be called by Scheme - * for proper stack tracking - */ -#ifndef FEAT_MZSCHEME + */ main_loop(FALSE, FALSE); -#else - mzscheme_main(); -#endif return 0; } #endif /* PROTO */ +#endif /* NO_VIM_MAIN */ /* * Main loop: Execute Normal mode commands until exiting Vim. @@ -1009,6 +1040,7 @@ skip_redraw = FALSE; RedrawingDisabled = 0; no_wait_return = 0; + vgetc_busy = 0; # ifdef FEAT_EVAL emsg_skip = 0; # endif @@ -1202,7 +1234,9 @@ || conceal_cursor_line(curwin) || need_cursor_line_redraw)) { - if (conceal_old_cursor_line != conceal_new_cursor_line) + if (conceal_old_cursor_line != conceal_new_cursor_line + && conceal_old_cursor_line + <= curbuf->b_ml.ml_line_count) update_single_line(curwin, conceal_old_cursor_line); update_single_line(curwin, conceal_new_cursor_line); curwin->w_valid &= ~VALID_CROW; @@ -1335,7 +1369,7 @@ { apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname, FALSE, buf); - buf->b_changedtick = -1; /* note that we did it already */ + buf->b_changedtick = -1; /* note that we did it already */ /* start all over, autocommands may mess up the lists */ next_tp = first_tabpage; break; @@ -1432,6 +1466,7 @@ mch_exit(exitval); } +#ifndef NO_VIM_MAIN /* * Get a (optional) count for a Vim argument. */ @@ -2996,6 +3031,8 @@ #endif } +#endif /* NO_VIM_MAIN */ + /* * Get an environment variable, and execute it as Ex commands. * Returns FAIL if the environment variable was not executed, OK otherwise. @@ -3035,7 +3072,7 @@ return FAIL; } -#if defined(UNIX) || defined(VMS) +#if (defined(UNIX) || defined(VMS)) && !defined(NO_VIM_MAIN) /* * Return TRUE if we are certain the user owns the file "fname". * Used for ".vimrc" and ".exrc". @@ -3093,6 +3130,7 @@ mainerr(ME_ARG_MISSING, str); } +#ifndef NO_VIM_MAIN /* * print a message with three spaces prepended and '\n' appended. */ @@ -3155,6 +3193,7 @@ #endif main_msg(_("-v\t\t\tVi mode (like \"vi\")")); main_msg(_("-e\t\t\tEx mode (like \"ex\")")); + main_msg(_("-E\t\t\tImproved Ex mode")); main_msg(_("-s\t\t\tSilent (batch) mode (only for \"ex\")")); #ifdef FEAT_DIFF main_msg(_("-d\t\t\tDiff mode (like \"vimdiff\")")); @@ -3270,11 +3309,6 @@ main_msg(_("+reverse\t\tDon't use reverse video (also: +rv)")); main_msg(_("-xrm \tSet the specified resource")); #endif /* FEAT_GUI_X11 */ -#if defined(FEAT_GUI) && defined(RISCOS) - mch_msg(_("\nArguments recognised by gvim (RISC OS version):\n")); - main_msg(_("--columns \tInitial width of window in columns")); - main_msg(_("--rows \tInitial height of window in rows")); -#endif #ifdef FEAT_GUI_GTK mch_msg(_("\nArguments recognised by gvim (GTK+ version):\n")); main_msg(_("-font \t\tUse for normal text (also: -fn)")); @@ -3283,6 +3317,7 @@ main_msg(_("-display \tRun vim on (also: --display)")); main_msg(_("--role \tSet a unique role to identify the main window")); main_msg(_("--socketid \tOpen Vim inside another GTK widget")); + main_msg(_("--echo-wid\t\tMake gvim echo the Window ID on stdout")); #endif #ifdef FEAT_GUI_W32 main_msg(_("-P \tOpen Vim inside parent application")); @@ -3292,7 +3327,10 @@ #ifdef FEAT_GUI_GNOME /* Gnome gives extra messages for --help if we continue, but not for -h. */ if (gui.starting) + { mch_msg("\n"); + gui.dofork = FALSE; + } else #endif mch_exit(0); @@ -3313,6 +3351,8 @@ } #endif +#endif + #if defined(STARTUPTIME) || defined(PROTO) static void time_diff __ARGS((struct timeval *then, struct timeval *now)); @@ -3422,7 +3462,7 @@ #endif -#if defined(FEAT_CLIENTSERVER) || defined(PROTO) +#if (defined(FEAT_CLIENTSERVER) && !defined(NO_VIM_MAIN)) || defined(PROTO) /* * Common code for the X command server and the Win32 command server. @@ -3806,7 +3846,7 @@ int i; char_u *inicmd = NULL; char_u *p; - char_u cwd[MAXPATHL]; + char_u *cwd; if (filec > 0 && filev[0][0] == '+') { @@ -3817,15 +3857,25 @@ /* Check if we have at least one argument. */ if (filec <= 0) mainerr_arg_missing((char_u *)filev[-1]); + + /* Temporarily cd to the current directory to handle relative file names. */ + cwd = alloc(MAXPATHL); + if (cwd == NULL) + return NULL; if (mch_dirname(cwd, MAXPATHL) != OK) + { + vim_free(cwd); return NULL; - if ((p = vim_strsave_escaped_ext(cwd, + } + 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) + '\\', TRUE); + vim_free(cwd); + if (p == NULL) return NULL; ga_init2(&ga, 1, 100); ga_concat(&ga, (char_u *)":cd "); @@ -3858,13 +3908,20 @@ ga_concat(&ga, p); vim_free(p); } + ga_concat(&ga, (char_u *)"|if exists('*inputrestore')|call inputrestore()|endif"); + /* The :drop commands goes to Insert mode when 'insertmode' is set, use * CTRL-\ CTRL-N again. */ - ga_concat(&ga, (char_u *)"|if exists('*inputrestore')|call inputrestore()|endif"); - ga_concat(&ga, (char_u *)":cd -"); + ga_concat(&ga, (char_u *)""); + + /* Switch back to the correct current directory (prior to temporary path + * switch) unless 'autochdir' is set, in which case it will already be + * correct after the :drop command. */ + ga_concat(&ga, (char_u *)":if !exists('+acd')||!&acd|cd -|endif"); + if (sendReply) - ga_concat(&ga, (char_u *)":call SetupRemoteReplies()"); - ga_concat(&ga, (char_u *)":"); + ga_concat(&ga, (char_u *)":call SetupRemoteReplies()"); + ga_concat(&ga, (char_u *)":"); if (inicmd != NULL) { /* Can't use after "inicmd", because an "startinsert" would cause @@ -3881,6 +3938,32 @@ } /* + * Make our basic server name: use the specified "arg" if given, otherwise use + * the tail of the command "cmd" we were started with. + * Return the name in allocated memory. This doesn't include a serial number. + */ + static char_u * +serverMakeName(arg, cmd) + char_u *arg; + char *cmd; +{ + char_u *p; + + if (arg != NULL && *arg != NUL) + p = vim_strsave_up(arg); + else + { + p = vim_strsave_up(gettail((char_u *)cmd)); + /* Remove .exe or .bat from the name. */ + if (p != NULL && vim_strchr(p, '.') != NULL) + *vim_strchr(p, '.') = NUL; + } + return p; +} +#endif /* FEAT_CLIENTSERVER */ + +#if defined(FEAT_CLIENTSERVER) || defined(PROTO) +/* * Replace termcodes such as and insert as key presses if there is room. */ void @@ -3991,32 +4074,7 @@ # endif return res; } - - -/* - * Make our basic server name: use the specified "arg" if given, otherwise use - * the tail of the command "cmd" we were started with. - * Return the name in allocated memory. This doesn't include a serial number. - */ - static char_u * -serverMakeName(arg, cmd) - char_u *arg; - char *cmd; -{ - char_u *p; - - if (arg != NULL && *arg != NUL) - p = vim_strsave_up(arg); - else - { - p = vim_strsave_up(gettail((char_u *)cmd)); - /* Remove .exe or .bat from the name. */ - if (p != NULL && vim_strchr(p, '.') != NULL) - *vim_strchr(p, '.') = NUL; - } - return p; -} -#endif /* FEAT_CLIENTSERVER */ +#endif /* * When FEAT_FKMAP is defined, also compile the Farsi source code. diff -Naur vim73.orig/src/mark.c vim73/src/mark.c --- vim73.orig/src/mark.c 2010-08-13 09:14:35.000000000 +0000 +++ vim73/src/mark.c 2012-07-20 20:31:17.910978208 +0000 @@ -98,6 +98,19 @@ return OK; } +#ifdef FEAT_VISUAL + if (c == '<') + { + curbuf->b_visual.vi_start = *pos; + return OK; + } + if (c == '>') + { + curbuf->b_visual.vi_end = *pos; + return OK; + } +#endif + #ifndef EBCDIC if (c > 'z') /* some islower() and isupper() cannot handle characters above 127 */ @@ -1750,7 +1763,10 @@ { if (line[1] != NUL) { - sscanf((char *)line + 2, "%ld %u", &pos.lnum, &pos.col); + unsigned u; + + sscanf((char *)line + 2, "%ld %u", &pos.lnum, &u); + pos.col = u; switch (line[1]) { case '"': curbuf->b_last_cursor = pos; break; diff -Naur vim73.orig/src/mbyte.c vim73/src/mbyte.c --- vim73.orig/src/mbyte.c 2010-07-18 13:05:44.000000000 +0000 +++ vim73/src/mbyte.c 2012-07-20 20:31:16.520977215 +0000 @@ -132,6 +132,7 @@ static int dbcs_char2cells __ARGS((int c)); static int dbcs_ptr2cells_len __ARGS((char_u *p, int size)); static int dbcs_ptr2char __ARGS((char_u *p)); +static int utf_safe_read_char_adv __ARGS((char_u **s, size_t *n)); /* * Lookup table to quickly get the length in bytes of a UTF-8 character from @@ -707,7 +708,7 @@ */ n = (i & 0x80) ? 2 : 1; # else - char buf[MB_MAXBYTES]; + char buf[MB_MAXBYTES + 1]; # ifdef X_LOCALE # ifndef mblen # define mblen _Xmblen @@ -837,6 +838,27 @@ } /* + * Remove all BOM from "s" by moving remaining text. + */ + void +remove_bom(s) + char_u *s; +{ + if (enc_utf8) + { + char_u *p = s; + + while ((p = vim_strbyte(p, 0xef)) != NULL) + { + if (p[1] == 0xbb && p[2] == 0xbf) + STRMOVE(p, p + 3); + else + ++p; + } + } +} + +/* * Get class of pointer: * 0 for blank or NUL * 1 for punctuation @@ -1701,6 +1723,66 @@ } /* + * Convert a UTF-8 byte sequence to a wide character. + * String is assumed to be terminated by NUL or after "n" bytes, whichever + * comes first. + * The function is safe in the sense that it never accesses memory beyond the + * first "n" bytes of "s". + * + * On success, returns decoded codepoint, advances "s" to the beginning of + * next character and decreases "n" accordingly. + * + * If end of string was reached, returns 0 and, if "n" > 0, advances "s" past + * NUL byte. + * + * If byte sequence is illegal or incomplete, returns -1 and does not advance + * "s". + */ + static int +utf_safe_read_char_adv(s, n) + char_u **s; + size_t *n; +{ + int c, k; + + if (*n == 0) /* end of buffer */ + return 0; + + k = utf8len_tab_zero[**s]; + + if (k == 1) + { + /* ASCII character or NUL */ + (*n)--; + return *(*s)++; + } + + if ((size_t)k <= *n) + { + /* We have a multibyte sequence and it isn't truncated by buffer + * limits so utf_ptr2char() is safe to use. Or the first byte is + * illegal (k=0), and it's also safe to use utf_ptr2char(). */ + c = utf_ptr2char(*s); + + /* On failure, utf_ptr2char() returns the first byte, so here we + * check equality with the first byte. The only non-ASCII character + * which equals the first byte of its own UTF-8 representation is + * U+00C3 (UTF-8: 0xC3 0x83), so need to check that special case too. + * It's safe even if n=1, else we would have k=2 > n. */ + if (c != (int)(**s) || (c == 0xC3 && (*s)[1] == 0x83)) + { + /* byte sequence was successfully decoded */ + *s += k; + *n -= k; + return c; + } + } + + /* byte sequence is incomplete or illegal */ + return -1; +} + +/* * Get character at **pp and advance *pp to the next character. * Note: composing characters are skipped! */ @@ -1871,7 +1953,7 @@ /* * Convert the character at screen position "off" to a sequence of bytes. * Includes the composing characters. - * "buf" must at least have the length MB_MAXBYTES. + * "buf" must at least have the length MB_MAXBYTES + 1. * Only to be used when ScreenLinesUC[off] != 0. * Returns the produced number of bytes. */ @@ -2667,7 +2749,8 @@ {0x10400,0x10427,1,40} }; -static int utf_convert(int a, convertStruct table[], int tableSize); +static int utf_convert __ARGS((int a, convertStruct table[], int tableSize)); +static int utf_strnicmp __ARGS((char_u *s1, char_u *s2, size_t n1, size_t n2)); /* * Generic conversion function for case operations. @@ -2681,19 +2764,22 @@ int tableSize; { int start, mid, end; /* indices into table */ + int entries = tableSize / sizeof(convertStruct); start = 0; - end = tableSize / sizeof(convertStruct); + end = entries; while (start < end) { /* need to search further */ - mid = (end + start) /2; + mid = (end + start) / 2; if (table[mid].rangeEnd < a) start = mid + 1; else end = mid; } - if (table[start].rangeStart <= a && a <= table[start].rangeEnd + if (start < entries + && table[start].rangeStart <= a + && a <= table[start].rangeEnd && (a - table[start].rangeStart) % table[start].step == 0) return (a + table[start].offset); else @@ -2708,7 +2794,7 @@ utf_fold(a) int a; { - return utf_convert(a, foldCase, sizeof(foldCase)); + return utf_convert(a, foldCase, (int)sizeof(foldCase)); } static convertStruct toLower[] = @@ -2863,7 +2949,7 @@ { {0x61,0x7a,1,-32}, {0xb5,0xb5,-1,743}, - {0xe0,0xf6,1,-32}, + {0xe0,0xf6,1,-32}, /* 0xdf (German sharp s) is not upper-cased */ {0xf8,0xfe,1,-32}, {0xff,0xff,-1,121}, {0x101,0x12f,2,-1}, @@ -3036,14 +3122,15 @@ return TOUPPER_LOC(a); /* For any other characters use the above mapping table. */ - return utf_convert(a, toUpper, sizeof(toUpper)); + return utf_convert(a, toUpper, (int)sizeof(toUpper)); } int utf_islower(a) int a; { - return (utf_toupper(a) != a); + /* German sharp s is lower case but has no upper case equivalent. */ + return (utf_toupper(a) != a) || a == 0xdf; } /* @@ -3069,7 +3156,7 @@ return TOLOWER_LOC(a); /* For any other characters use the above mapping table. */ - return utf_convert(a, toLower, sizeof(toLower)); + return utf_convert(a, toLower, (int)sizeof(toLower)); } int @@ -3079,6 +3166,80 @@ return (utf_tolower(a) != a); } + static int +utf_strnicmp(s1, s2, n1, n2) + char_u *s1, *s2; + size_t n1, n2; +{ + int c1, c2, cdiff; + char_u buffer[6]; + + for (;;) + { + c1 = utf_safe_read_char_adv(&s1, &n1); + c2 = utf_safe_read_char_adv(&s2, &n2); + + if (c1 <= 0 || c2 <= 0) + break; + + if (c1 == c2) + continue; + + cdiff = utf_fold(c1) - utf_fold(c2); + if (cdiff != 0) + return cdiff; + } + + /* some string ended or has an incomplete/illegal character sequence */ + + if (c1 == 0 || c2 == 0) + { + /* some string ended. shorter string is smaller */ + if (c1 == 0 && c2 == 0) + return 0; + return c1 == 0 ? -1 : 1; + } + + /* Continue with bytewise comparison to produce some result that + * would make comparison operations involving this function transitive. + * + * If only one string had an error, comparison should be made with + * folded version of the other string. In this case it is enough + * to fold just one character to determine the result of comparison. */ + + if (c1 != -1 && c2 == -1) + { + n1 = utf_char2bytes(utf_fold(c1), buffer); + s1 = buffer; + } + else if (c2 != -1 && c1 == -1) + { + n2 = utf_char2bytes(utf_fold(c2), buffer); + s2 = buffer; + } + + while (n1 > 0 && n2 > 0 && *s1 != NUL && *s2 != NUL) + { + cdiff = (int)(*s1) - (int)(*s2); + if (cdiff != 0) + return cdiff; + + s1++; + s2++; + n1--; + n2--; + } + + if (n1 > 0 && *s1 == NUL) + n1 = 0; + if (n2 > 0 && *s2 == NUL) + n2 = 0; + + if (n1 == 0 && n2 == 0) + return 0; + return n1 == 0 ? -1 : 1; +} + /* * Version of strnicmp() that handles multi-byte characters. * Needed for Big5, Sjift-JIS and UTF-8 encoding. Other DBCS encodings can @@ -3092,46 +3253,21 @@ char_u *s1, *s2; size_t nn; { - int i, j, l; + int i, l; int cdiff; - int incomplete = FALSE; int n = (int)nn; - for (i = 0; i < n; i += l) + if (enc_utf8) { - if (s1[i] == NUL && s2[i] == NUL) /* both strings end */ - return 0; - if (enc_utf8) - { - l = utf_byte2len(s1[i]); - if (l > n - i) - { - l = n - i; /* incomplete character */ - incomplete = TRUE; - } - /* Check directly first, it's faster. */ - for (j = 0; j < l; ++j) - { - if (s1[i + j] != s2[i + j]) - break; - if (s1[i + j] == 0) - /* Both stings have the same bytes but are incomplete or - * have illegal bytes, accept them as equal. */ - l = j; - } - if (j < l) - { - /* If one of the two characters is incomplete return -1. */ - if (incomplete || i + utf_byte2len(s2[i]) > n) - return -1; - cdiff = utf_fold(utf_ptr2char(s1 + i)) - - utf_fold(utf_ptr2char(s2 + i)); - if (cdiff != 0) - return cdiff; - } - } - else + return utf_strnicmp(s1, s2, nn, nn); + } + else + { + for (i = 0; i < n; i += l) { + if (s1[i] == NUL && s2[i] == NUL) /* both strings end */ + return 0; + l = (*mb_ptr2len)(s1 + i); if (l <= 1) { @@ -3560,7 +3696,7 @@ void mb_adjust_cursor() { - mb_adjustpos(&curwin->w_cursor); + mb_adjustpos(curbuf, &curwin->w_cursor); } /* @@ -3568,7 +3704,8 @@ * If it points to a tail byte it's moved backwards to the head byte. */ void -mb_adjustpos(lp) +mb_adjustpos(buf, lp) + buf_T *buf; pos_T *lp; { char_u *p; @@ -3579,7 +3716,7 @@ #endif ) { - p = ml_get(lp->lnum); + p = ml_get_buf(buf, lp->lnum, FALSE); lp->col -= (*mb_head_off)(p, p + lp->col); #ifdef FEAT_VIRTUALEDIT /* Reset "coladd" when the cursor would be on the right half of a @@ -4126,7 +4263,7 @@ done = to - (char *)result; } - if (resultlenp != NULL) + if (resultlenp != NULL && result != NULL) *resultlenp = (int)(to - (char *)result); return result; } @@ -4159,11 +4296,11 @@ { if (hIconvDLL != 0 && hMsvcrtDLL != 0) return TRUE; - hIconvDLL = LoadLibrary(DYNAMIC_ICONV_DLL); + hIconvDLL = vimLoadLib(DYNAMIC_ICONV_DLL); if (hIconvDLL == 0) /* sometimes it's called libiconv.dll */ - hIconvDLL = LoadLibrary(DYNAMIC_ICONV_DLL_ALT); + hIconvDLL = vimLoadLib(DYNAMIC_ICONV_DLL_ALT); if (hIconvDLL != 0) - hMsvcrtDLL = LoadLibrary(DYNAMIC_MSVCRT_DLL); + hMsvcrtDLL = vimLoadLib(DYNAMIC_MSVCRT_DLL); if (hIconvDLL == 0 || hMsvcrtDLL == 0) { /* Only give the message when 'verbose' is set, otherwise it might be @@ -4368,7 +4505,8 @@ vgetc_busy = TRUE; showmode(); vgetc_busy = old_vgetc_busy; - setcursor(); + if ((State & NORMAL) || (State & INSERT)) + setcursor(); out_flush(); } @@ -5058,6 +5196,10 @@ /* We had a keypad key, and XIM tried to thieve it */ return FALSE; + /* This is supposed to fix a problem with iBus, that space + * characters don't work in input mode. */ + xim_expected_char = NUL; + /* Normal processing */ return imresult; } @@ -5167,16 +5309,16 @@ void xim_set_preedit() { - if (xic == NULL) - return; - - xim_set_focus(TRUE); - XVaNestedList attr_list; XRectangle spot_area; XPoint over_spot; int line_space; + if (xic == NULL) + return; + + xim_set_focus(TRUE); + if (!xim_has_focus) { /* hide XIM cursor */ @@ -5554,12 +5696,12 @@ void xim_set_status_area() { - if (xic == NULL) - return; - XVaNestedList preedit_list = 0, status_list = 0, list = 0; XRectangle pre_area, status_area; + if (xic == NULL) + return; + if (input_style & XIMStatusArea) { if (input_style & XIMPreeditArea) diff -Naur vim73.orig/src/memfile.c vim73/src/memfile.c --- vim73.orig/src/memfile.c 2010-06-21 02:59:57.000000000 +0000 +++ vim73/src/memfile.c 2012-07-20 20:31:10.797639769 +0000 @@ -32,10 +32,6 @@ * file is opened. */ -#if defined(MSDOS) || defined(WIN16) || defined(WIN32) || defined(_WIN64) -# include "vimio.h" /* for lseek(), must be before vim.h */ -#endif - #include "vim.h" /* @@ -88,6 +84,13 @@ static int mf_write_block __ARGS((memfile_T *mfp, bhdr_T *hp, off_t offset, unsigned size)); static int mf_trans_add __ARGS((memfile_T *, bhdr_T *)); static void mf_do_open __ARGS((memfile_T *, char_u *, int)); +static void mf_hash_init __ARGS((mf_hashtab_T *)); +static void mf_hash_free __ARGS((mf_hashtab_T *)); +static void mf_hash_free_all __ARGS((mf_hashtab_T *)); +static mf_hashitem_T *mf_hash_find __ARGS((mf_hashtab_T *, blocknr_T)); +static void mf_hash_add_item __ARGS((mf_hashtab_T *, mf_hashitem_T *)); +static void mf_hash_rem_item __ARGS((mf_hashtab_T *, mf_hashitem_T *)); +static int mf_hash_grow __ARGS((mf_hashtab_T *)); /* * The functions for using a memfile: @@ -123,7 +126,6 @@ int flags; { memfile_T *mfp; - int i; off_t size; #if defined(STATFS) && defined(UNIX) && !defined(__QNX__) # define USE_FSTATFS @@ -156,11 +158,8 @@ mfp->mf_used_last = NULL; mfp->mf_dirty = FALSE; mfp->mf_used_count = 0; - for (i = 0; i < MEMHASHSIZE; ++i) - { - mfp->mf_hash[i] = NULL; /* hash lists are empty */ - mfp->mf_trans[i] = NULL; /* trans lists are empty */ - } + mf_hash_init(&mfp->mf_hash); + mf_hash_init(&mfp->mf_trans); mfp->mf_page_size = MEMFILE_PAGE_SIZE; #ifdef FEAT_CRYPT mfp->mf_old_key = NULL; @@ -246,8 +245,6 @@ int del_file; { bhdr_T *hp, *nextp; - NR_TRANS *tp, *tpnext; - int i; if (mfp == NULL) /* safety check */ return; @@ -267,12 +264,8 @@ } while (mfp->mf_free_first != NULL) /* free entries in free list */ vim_free(mf_rem_free(mfp)); - for (i = 0; i < MEMHASHSIZE; ++i) /* free entries in trans lists */ - for (tp = mfp->mf_trans[i]; tp != NULL; tp = tpnext) - { - tpnext = tp->nt_next; - vim_free(tp); - } + mf_hash_free(&mfp->mf_hash); + mf_hash_free_all(&mfp->mf_trans); /* free hashtable and its items */ vim_free(mfp->mf_fname); vim_free(mfp->mf_ffname); vim_free(mfp); @@ -747,16 +740,7 @@ memfile_T *mfp; bhdr_T *hp; { - bhdr_T *hhp; - int hash; - - hash = MEMHASH(hp->bh_bnum); - hhp = mfp->mf_hash[hash]; - hp->bh_hash_next = hhp; - hp->bh_hash_prev = NULL; - if (hhp != NULL) - hhp->bh_hash_prev = hp; - mfp->mf_hash[hash] = hp; + mf_hash_add_item(&mfp->mf_hash, (mf_hashitem_T *)hp); } /* @@ -767,13 +751,7 @@ memfile_T *mfp; bhdr_T *hp; { - if (hp->bh_hash_prev == NULL) - mfp->mf_hash[MEMHASH(hp->bh_bnum)] = hp->bh_hash_next; - else - hp->bh_hash_prev->bh_hash_next = hp->bh_hash_next; - - if (hp->bh_hash_next) - hp->bh_hash_next->bh_hash_prev = hp->bh_hash_prev; + mf_hash_rem_item(&mfp->mf_hash, (mf_hashitem_T *)hp); } /* @@ -784,12 +762,7 @@ memfile_T *mfp; blocknr_T nr; { - bhdr_T *hp; - - for (hp = mfp->mf_hash[MEMHASH(nr)]; hp != NULL; hp = hp->bh_hash_next) - if (hp->bh_bnum == nr) - break; - return hp; + return (bhdr_T *)mf_hash_find(&mfp->mf_hash, nr); } /* @@ -1049,7 +1022,7 @@ PERROR(_("E294: Seek error in swap file read")); return FAIL; } - if ((unsigned)vim_read(mfp->mf_fd, hp->bh_data, size) != size) + if ((unsigned)read_eintr(mfp->mf_fd, hp->bh_data, size) != size) { PERROR(_("E295: Read error in swap file")); return FAIL; @@ -1168,7 +1141,7 @@ } #endif - if ((unsigned)vim_write(mfp->mf_fd, data, size) != size) + if ((unsigned)write_eintr(mfp->mf_fd, data, size) != size) result = FAIL; #ifdef FEAT_CRYPT @@ -1191,7 +1164,6 @@ { bhdr_T *freep; blocknr_T new_bnum; - int hash; NR_TRANS *np; int page_count; @@ -1239,12 +1211,8 @@ hp->bh_bnum = new_bnum; mf_ins_hash(mfp, hp); /* insert in new hash list */ - hash = MEMHASH(np->nt_old_bnum); /* insert in trans list */ - np->nt_next = mfp->mf_trans[hash]; - mfp->mf_trans[hash] = np; - if (np->nt_next != NULL) - np->nt_next->nt_prev = np; - np->nt_prev = NULL; + /* Insert "np" into "mf_trans" hashtable with key "np->nt_old_bnum" */ + mf_hash_add_item(&mfp->mf_trans, (mf_hashitem_T *)np); return OK; } @@ -1259,25 +1227,20 @@ memfile_T *mfp; blocknr_T old_nr; { - int hash; NR_TRANS *np; blocknr_T new_bnum; - hash = MEMHASH(old_nr); - for (np = mfp->mf_trans[hash]; np != NULL; np = np->nt_next) - if (np->nt_old_bnum == old_nr) - break; + np = (NR_TRANS *)mf_hash_find(&mfp->mf_trans, old_nr); + if (np == NULL) /* not found */ return old_nr; mfp->mf_neg_count--; new_bnum = np->nt_new_bnum; - if (np->nt_prev != NULL) /* remove entry from the trans list */ - np->nt_prev->nt_next = np->nt_next; - else - mfp->mf_trans[hash] = np->nt_next; - if (np->nt_next != NULL) - np->nt_next->nt_prev = np->nt_prev; + + /* remove entry from the trans list */ + mf_hash_rem_item(&mfp->mf_trans, (mf_hashitem_T *)np); + vim_free(np); return new_bnum; @@ -1344,7 +1307,7 @@ * fname cannot be NameBuff, because it must have been allocated. */ mf_set_ffname(mfp); -#if defined(MSDOS) || defined(MSWIN) || defined(RISCOS) +#if defined(MSDOS) || defined(MSWIN) /* * A ":!cd e:xxx" may change the directory without us knowning, use the * full pathname always. Careful: This frees fname! @@ -1401,3 +1364,207 @@ mch_hide(mfp->mf_fname); /* try setting the 'hidden' flag */ } } + +/* + * Implementation of mf_hashtab_T follows. + */ + +/* + * The number of buckets in the hashtable is increased by a factor of + * MHT_GROWTH_FACTOR when the average number of items per bucket + * exceeds 2 ^ MHT_LOG_LOAD_FACTOR. + */ +#define MHT_LOG_LOAD_FACTOR 6 +#define MHT_GROWTH_FACTOR 2 /* must be a power of two */ + +/* + * Initialize an empty hash table. + */ + static void +mf_hash_init(mht) + mf_hashtab_T *mht; +{ + vim_memset(mht, 0, sizeof(mf_hashtab_T)); + mht->mht_buckets = mht->mht_small_buckets; + mht->mht_mask = MHT_INIT_SIZE - 1; +} + +/* + * Free the array of a hash table. Does not free the items it contains! + * The hash table must not be used again without another mf_hash_init() call. + */ + static void +mf_hash_free(mht) + mf_hashtab_T *mht; +{ + if (mht->mht_buckets != mht->mht_small_buckets) + vim_free(mht->mht_buckets); +} + +/* + * Free the array of a hash table and all the items it contains. + */ + static void +mf_hash_free_all(mht) + mf_hashtab_T *mht; +{ + long_u idx; + mf_hashitem_T *mhi; + mf_hashitem_T *next; + + for (idx = 0; idx <= mht->mht_mask; idx++) + for (mhi = mht->mht_buckets[idx]; mhi != NULL; mhi = next) + { + next = mhi->mhi_next; + vim_free(mhi); + } + + mf_hash_free(mht); +} + +/* + * Find "key" in hashtable "mht". + * Returns a pointer to a mf_hashitem_T or NULL if the item was not found. + */ + static mf_hashitem_T * +mf_hash_find(mht, key) + mf_hashtab_T *mht; + blocknr_T key; +{ + mf_hashitem_T *mhi; + + mhi = mht->mht_buckets[key & mht->mht_mask]; + while (mhi != NULL && mhi->mhi_key != key) + mhi = mhi->mhi_next; + + return mhi; +} + +/* + * Add item "mhi" to hashtable "mht". + * "mhi" must not be NULL. + */ + static void +mf_hash_add_item(mht, mhi) + mf_hashtab_T *mht; + mf_hashitem_T *mhi; +{ + long_u idx; + + idx = mhi->mhi_key & mht->mht_mask; + mhi->mhi_next = mht->mht_buckets[idx]; + mhi->mhi_prev = NULL; + if (mhi->mhi_next != NULL) + mhi->mhi_next->mhi_prev = mhi; + mht->mht_buckets[idx] = mhi; + + mht->mht_count++; + + /* + * Grow hashtable when we have more thank 2^MHT_LOG_LOAD_FACTOR + * items per bucket on average + */ + if (mht->mht_fixed == 0 + && (mht->mht_count >> MHT_LOG_LOAD_FACTOR) > mht->mht_mask) + { + if (mf_hash_grow(mht) == FAIL) + { + /* stop trying to grow after first failure to allocate memory */ + mht->mht_fixed = 1; + } + } +} + +/* + * Remove item "mhi" from hashtable "mht". + * "mhi" must not be NULL and must have been inserted into "mht". + */ + static void +mf_hash_rem_item(mht, mhi) + mf_hashtab_T *mht; + mf_hashitem_T *mhi; +{ + if (mhi->mhi_prev == NULL) + mht->mht_buckets[mhi->mhi_key & mht->mht_mask] = mhi->mhi_next; + else + mhi->mhi_prev->mhi_next = mhi->mhi_next; + + if (mhi->mhi_next != NULL) + mhi->mhi_next->mhi_prev = mhi->mhi_prev; + + mht->mht_count--; + + /* We could shrink the table here, but it typically takes little memory, + * so why bother? */ +} + +/* + * Increase number of buckets in the hashtable by MHT_GROWTH_FACTOR and + * rehash items. + * Returns FAIL when out of memory. + */ + static int +mf_hash_grow(mht) + mf_hashtab_T *mht; +{ + long_u i, j; + int shift; + mf_hashitem_T *mhi; + mf_hashitem_T *tails[MHT_GROWTH_FACTOR]; + mf_hashitem_T **buckets; + size_t size; + + size = (mht->mht_mask + 1) * MHT_GROWTH_FACTOR * sizeof(void *); + buckets = (mf_hashitem_T **)lalloc_clear(size, FALSE); + if (buckets == NULL) + return FAIL; + + shift = 0; + while ((mht->mht_mask >> shift) != 0) + shift++; + + for (i = 0; i <= mht->mht_mask; i++) + { + /* + * Traverse the items in the i-th original bucket and move them into + * MHT_GROWTH_FACTOR new buckets, preserving their relative order + * within each new bucket. Preserving the order is important because + * mf_get() tries to keep most recently used items at the front of + * each bucket. + * + * Here we strongly rely on the fact the hashes are computed modulo + * a power of two. + */ + + vim_memset(tails, 0, sizeof(tails)); + + for (mhi = mht->mht_buckets[i]; mhi != NULL; mhi = mhi->mhi_next) + { + j = (mhi->mhi_key >> shift) & (MHT_GROWTH_FACTOR - 1); + if (tails[j] == NULL) + { + buckets[i + (j << shift)] = mhi; + tails[j] = mhi; + mhi->mhi_prev = NULL; + } + else + { + tails[j]->mhi_next = mhi; + mhi->mhi_prev = tails[j]; + tails[j] = mhi; + } + } + + for (j = 0; j < MHT_GROWTH_FACTOR; j++) + if (tails[j] != NULL) + tails[j]->mhi_next = NULL; + } + + if (mht->mht_buckets != mht->mht_small_buckets) + vim_free(mht->mht_buckets); + + mht->mht_buckets = buckets; + mht->mht_mask = (mht->mht_mask + 1) * MHT_GROWTH_FACTOR - 1; + + return OK; +} diff -Naur vim73.orig/src/memfile_test.c vim73/src/memfile_test.c --- vim73.orig/src/memfile_test.c 1970-01-01 00:00:00.000000000 +0000 +++ vim73/src/memfile_test.c 2012-07-20 20:31:09.837639076 +0000 @@ -0,0 +1,145 @@ +/* vi:set ts=8 sts=4 sw=4: + * + * VIM - Vi IMproved by Bram Moolenaar + * + * Do ":help uganda" in Vim to read copying and usage conditions. + * Do ":help credits" in Vim to see a list of people who contributed. + * See README.txt for an overview of the Vim source code. + */ + +/* + * memfile_test.c: Unittests for memfile.c + * Mostly by Ivan Krasilnikov. + */ + +#undef NDEBUG +#include + +/* Must include main.c because it contains much more than just main() */ +#define NO_VIM_MAIN +#include "main.c" + +/* This file has to be included because the tested functions are static */ +#include "memfile.c" + +#define index_to_key(i) ((i) ^ 15167) +#define TEST_COUNT 50000 + +static void test_mf_hash __ARGS((void)); + +/* + * Test mf_hash_*() functions. + */ + static void +test_mf_hash() +{ + mf_hashtab_T ht; + mf_hashitem_T *item; + blocknr_T key; + long_u i; + long_u num_buckets; + + mf_hash_init(&ht); + + /* insert some items and check invariants */ + for (i = 0; i < TEST_COUNT; i++) + { + assert(ht.mht_count == i); + + /* check that number of buckets is a power of 2 */ + num_buckets = ht.mht_mask + 1; + assert(num_buckets > 0 && (num_buckets & (num_buckets - 1)) == 0); + + /* check load factor */ + assert(ht.mht_count <= (num_buckets << MHT_LOG_LOAD_FACTOR)); + + if (i < (MHT_INIT_SIZE << MHT_LOG_LOAD_FACTOR)) + { + /* first expansion shouldn't have occurred yet */ + assert(num_buckets == MHT_INIT_SIZE); + assert(ht.mht_buckets == ht.mht_small_buckets); + } + else + { + assert(num_buckets > MHT_INIT_SIZE); + assert(ht.mht_buckets != ht.mht_small_buckets); + } + + key = index_to_key(i); + assert(mf_hash_find(&ht, key) == NULL); + + /* allocate and add new item */ + item = (mf_hashitem_T *)lalloc_clear(sizeof(mf_hashtab_T), FALSE); + assert(item != NULL); + item->mhi_key = key; + mf_hash_add_item(&ht, item); + + assert(mf_hash_find(&ht, key) == item); + + if (ht.mht_mask + 1 != num_buckets) + { + /* hash table was expanded */ + assert(ht.mht_mask + 1 == num_buckets * MHT_GROWTH_FACTOR); + assert(i + 1 == (num_buckets << MHT_LOG_LOAD_FACTOR)); + } + } + + /* check presence of inserted items */ + for (i = 0; i < TEST_COUNT; i++) + { + key = index_to_key(i); + item = mf_hash_find(&ht, key); + assert(item != NULL); + assert(item->mhi_key == key); + } + + /* delete some items */ + for (i = 0; i < TEST_COUNT; i++) + { + if (i % 100 < 70) + { + key = index_to_key(i); + item = mf_hash_find(&ht, key); + assert(item != NULL); + assert(item->mhi_key == key); + + mf_hash_rem_item(&ht, item); + assert(mf_hash_find(&ht, key) == NULL); + + mf_hash_add_item(&ht, item); + assert(mf_hash_find(&ht, key) == item); + + mf_hash_rem_item(&ht, item); + assert(mf_hash_find(&ht, key) == NULL); + + vim_free(item); + } + } + + /* check again */ + for (i = 0; i < TEST_COUNT; i++) + { + key = index_to_key(i); + item = mf_hash_find(&ht, key); + + if (i % 100 < 70) + { + assert(item == NULL); + } + else + { + assert(item != NULL); + assert(item->mhi_key == key); + } + } + + /* free hash table and all remaining items */ + mf_hash_free_all(&ht); +} + + int +main() +{ + test_mf_hash(); + return 0; +} diff -Naur vim73.orig/src/memline.c vim73/src/memline.c --- vim73.orig/src/memline.c 2010-08-08 13:11:46.000000000 +0000 +++ vim73/src/memline.c 2012-07-20 20:31:13.220974846 +0000 @@ -42,10 +42,6 @@ * mf_get(). */ -#if defined(MSDOS) || defined(WIN16) || defined(WIN32) || defined(_WIN64) -# include "vimio.h" /* for mch_open(), must be before vim.h */ -#endif - #include "vim.h" #ifndef UNIX /* it's in os_unix.h for Unix */ @@ -56,10 +52,6 @@ # include /* for Open() and Close() */ #endif -#ifdef HAVE_ERRNO_H -# include -#endif - typedef struct block0 ZERO_BL; /* contents of the first block */ typedef struct pointer_block PTR_BL; /* contents of a pointer block */ typedef struct data_block DATA_BL; /* contents of a data block */ @@ -582,6 +574,9 @@ idx = ip->ip_index + 1; /* go to next index */ page_count = 1; } + + if (error > 0) + EMSG(_("E843: Error while updating swap file crypt")); } mfp->mf_old_key = NULL; @@ -626,6 +621,8 @@ break; fname = findswapname(buf, &dirp, mfp->mf_fname); /* alloc's fname */ + if (dirp == NULL) /* out of memory */ + break; if (fname == NULL) /* no file name found for this dir */ continue; @@ -749,11 +746,13 @@ * and creating it, another Vim creates the file. In that case the * creation will fail and we will use another directory. */ fname = findswapname(buf, &dirp, NULL); /* allocates fname */ + if (dirp == NULL) + break; /* out of memory */ if (fname == NULL) continue; if (mf_open_file(mfp, fname) == OK) /* consumes fname! */ { -#if defined(MSDOS) || defined(MSWIN) || defined(RISCOS) +#if defined(MSDOS) || defined(MSWIN) /* * set full pathname for swap file now, because a ":!cd dir" may * change directory without us knowing it. @@ -938,7 +937,7 @@ b0p->b0_fname[0] = NUL; else { -#if defined(MSDOS) || defined(MSWIN) || defined(AMIGA) || defined(RISCOS) +#if defined(MSDOS) || defined(MSWIN) || defined(AMIGA) /* Systems that cannot translate "~user" back into a path: copy the * file name unmodified. Do use slashes instead of backslashes for * portability. */ @@ -1108,7 +1107,7 @@ fname = (char_u *)""; len = (int)STRLEN(fname); if (len >= 4 && -#if defined(VMS) || defined(RISCOS) +#if defined(VMS) STRNICMP(fname + len - 4, "_s" , 2) #else STRNICMP(fname + len - 4, ".s" , 2) @@ -1512,6 +1511,7 @@ bnum = pp->pb_pointer[idx].pe_bnum; line_count = pp->pb_pointer[idx].pe_line_count; page_count = pp->pb_pointer[idx].pe_page_count; + idx = 0; continue; } } @@ -1778,11 +1778,7 @@ #ifdef VMS names[0] = vim_strsave((char_u *)"*_sw%"); #else -# ifdef RISCOS - names[0] = vim_strsave((char_u *)"*_sw#"); -# else names[0] = vim_strsave((char_u *)"*.sw?"); -# endif #endif #if defined(UNIX) || defined(WIN3264) /* For Unix names starting with a dot are special. MS-Windows @@ -1809,11 +1805,7 @@ #ifdef VMS names[0] = concat_fnames(dir_name, (char_u *)"*_sw%", TRUE); #else -# ifdef RISCOS - names[0] = concat_fnames(dir_name, (char_u *)"*_sw#", TRUE); -# else names[0] = concat_fnames(dir_name, (char_u *)"*.sw?", TRUE); -# endif #endif #if defined(UNIX) || defined(WIN3264) /* For Unix names starting with a dot are special. MS-Windows @@ -1882,7 +1874,7 @@ char_u *swapname; swapname = modname(fname_res, -#if defined(VMS) || defined(RISCOS) +#if defined(VMS) (char_u *)"_swp", FALSE #else (char_u *)".swp", TRUE @@ -2059,7 +2051,7 @@ fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0); if (fd >= 0) { - if (read(fd, (char *)&b0, sizeof(b0)) == sizeof(b0)) + if (read_eintr(fd, &b0, sizeof(b0)) == sizeof(b0)) { if (STRNCMP(b0.b0_version, "VIM 3.0", 7) == 0) { @@ -2181,11 +2173,7 @@ #ifdef VMS names[num_names] = concat_fnames(path, (char_u *)"_sw%", FALSE); #else -# ifdef RISCOS - names[num_names] = concat_fnames(path, (char_u *)"_sw#", FALSE); -# else names[num_names] = concat_fnames(path, (char_u *)".sw?", FALSE); -# endif #endif if (names[num_names] == NULL) goto end; @@ -2212,11 +2200,7 @@ #ifdef VMS names[num_names] = modname(path, (char_u *)"_sw%", FALSE); #else -# ifdef RISCOS - names[num_names] = modname(path, (char_u *)"_sw#", FALSE); -# else names[num_names] = modname(path, (char_u *)".sw?", FALSE); -# endif #endif if (names[num_names] == NULL) goto end; @@ -2384,7 +2368,7 @@ * Make a copy of the line if necessary. */ /* - * get a pointer to a (read-only copy of a) line + * Return a pointer to a (read-only copy of a) line. * * On failure an error message is given and IObuff is returned (to avoid * having to check for error everywhere). @@ -2397,7 +2381,7 @@ } /* - * ml_get_pos: get pointer to position 'pos' + * Return pointer to position "pos". */ char_u * ml_get_pos(pos) @@ -2407,7 +2391,7 @@ } /* - * ml_get_curline: get pointer to cursor line. + * Return pointer to cursor line. */ char_u * ml_get_curline() @@ -2416,7 +2400,7 @@ } /* - * ml_get_cursor: get pointer to cursor position + * Return pointer to cursor position. */ char_u * ml_get_cursor() @@ -2426,7 +2410,7 @@ } /* - * get a pointer to a line in a specific buffer + * Return a pointer to a line in a specific buffer * * "will_change": if TRUE mark the buffer dirty (chars in the line will be * changed) @@ -3210,7 +3194,8 @@ mf_free(mfp, hp); /* free the data block */ buf->b_ml.ml_locked = NULL; - for (stack_idx = buf->b_ml.ml_stack_top - 1; stack_idx >= 0; --stack_idx) + for (stack_idx = buf->b_ml.ml_stack_top - 1; stack_idx >= 0; + --stack_idx) { buf->b_ml.ml_stack_top = 0; /* stack is invalid when failing */ ip = &(buf->b_ml.ml_stack[stack_idx]); @@ -3961,14 +3946,9 @@ #else (buf->b_p_sn || buf->b_shortname), #endif -#ifdef RISCOS - /* Avoid problems if fname has special chars, eg */ - ffname, -#else fname_res, -#endif (char_u *) -#if defined(VMS) || defined(RISCOS) +#if defined(VMS) "_swp", #else ".swp", @@ -4076,9 +4056,9 @@ } /* Some of these messages are long to allow translation to * other languages. */ - MSG_PUTS(_("\n(1) Another program may be editing the same file.\n If this is the case, be careful not to end up with two\n different instances of the same file when making changes.\n")); - MSG_PUTS(_(" Quit, or continue with caution.\n")); - MSG_PUTS(_("\n(2) An edit session for this file crashed.\n")); + MSG_PUTS(_("\n(1) Another program may be editing the same file. If this is the case,\n be careful not to end up with two different instances of the same\n file when making changes.")); + MSG_PUTS(_(" Quit, or continue with caution.\n")); + MSG_PUTS(_("(2) An edit session for this file crashed.\n")); MSG_PUTS(_(" If this is the case, use \":recover\" or \"vim -r ")); msg_outtrans(buf->b_fname); MSG_PUTS(_("\"\n to recover the changes (see \":help recovery\").\n")); @@ -4138,6 +4118,7 @@ * * Several names are tried to find one that does not exist * Returns the name in allocated memory or NULL. + * When out of memory "dirp" is set to NULL. * * Note: If BASENAMELEN is not correct, you will get error messages for * not being able to open the swap or undo file @@ -4181,7 +4162,9 @@ * First allocate some memory to put the directory name in. */ dir_name = alloc((unsigned)STRLEN(*dirp) + 1); - if (dir_name != NULL) + if (dir_name == NULL) + *dirp = NULL; + else (void)copy_option_part(dirp, dir_name, 31000, ","); /* @@ -4389,7 +4372,7 @@ fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0); if (fd >= 0) { - if (read(fd, (char *)&b0, sizeof(b0)) == sizeof(b0)) + if (read_eintr(fd, &b0, sizeof(b0)) == sizeof(b0)) { /* * If the swapfile has the same directory as the @@ -4432,14 +4415,6 @@ } close(fd); } -#ifdef RISCOS - else - /* Can't open swap file, though it does exist. - * Assume that the user is editing two files with - * the same name in different directories. No error. - */ - differ = TRUE; -#endif /* give the ATTENTION message when there is an old swap file * for the current file, and the buffer was not recovered. */ @@ -4521,7 +4496,7 @@ process_still_running ? (char_u *)_("&Open Read-Only\n&Edit anyway\n&Recover\n&Quit\n&Abort") : # endif - (char_u *)_("&Open Read-Only\n&Edit anyway\n&Recover\n&Delete it\n&Quit\n&Abort"), 1, NULL); + (char_u *)_("&Open Read-Only\n&Edit anyway\n&Recover\n&Delete it\n&Quit\n&Abort"), 1, NULL, FALSE); # if defined(UNIX) || defined(__EMX__) || defined(VMS) if (process_still_running && choice >= 4) diff -Naur vim73.orig/src/menu.c vim73/src/menu.c --- vim73.orig/src/menu.c 2010-07-14 14:49:01.000000000 +0000 +++ vim73/src/menu.c 2012-07-20 20:31:10.130972621 +0000 @@ -1394,7 +1394,8 @@ int idx; { static vimmenu_T *menu = NULL; - static char_u tbuffer[256]; /*hack*/ +#define TBUFFER_LEN 256 + static char_u tbuffer[TBUFFER_LEN]; /*hack*/ char_u *str; #ifdef FEAT_MULTI_LANG static int should_advance = FALSE; @@ -1428,11 +1429,11 @@ { #ifdef FEAT_MULTI_LANG if (should_advance) - STRCPY(tbuffer, menu->en_dname); + vim_strncpy(tbuffer, menu->en_dname, TBUFFER_LEN - 2); else { #endif - STRCPY(tbuffer, menu->dname); + vim_strncpy(tbuffer, menu->dname, TBUFFER_LEN - 2); #ifdef FEAT_MULTI_LANG if (menu->en_dname == NULL) should_advance = TRUE; @@ -1512,8 +1513,8 @@ { #ifdef FEAT_MULTI_LANG if (menu->en_name != NULL - && (menu_namecmp(name,menu->en_name) - || menu_namecmp(name,menu->en_dname))) + && (menu_namecmp(name, menu->en_name) + || menu_namecmp(name, menu->en_dname))) return TRUE; #endif return menu_namecmp(name, menu->name) || menu_namecmp(name, menu->dname); @@ -2342,7 +2343,7 @@ while (menu != NULL) { - if (STRCMP(name, menu->name) == 0 || STRCMP(name, menu->dname) == 0) + if (menu_name_equal(name, menu)) { if (menu->children == NULL) { diff -Naur vim73.orig/src/message.c vim73/src/message.c --- vim73.orig/src/message.c 2010-08-04 18:10:02.000000000 +0000 +++ vim73/src/message.c 2012-07-20 20:31:15.594309884 +0000 @@ -39,7 +39,6 @@ static void msg_screen_putchar __ARGS((int c, int attr)); static int msg_check_screen __ARGS((void)); static void redir_write __ARGS((char_u *s, int maxlen)); -static void verbose_write __ARGS((char_u *s, int maxlen)); #ifdef FEAT_CON_DIALOG static char_u *msg_show_console_dialog __ARGS((char_u *message, char_u *buttons, int dfltbutton)); static int confirm_msg_used = FALSE; /* displaying confirm_msg */ @@ -58,6 +57,9 @@ static struct msg_hist *last_msg_hist = NULL; static int msg_hist_len = 0; +static FILE *verbose_fd = NULL; +static int verbose_did_open = FALSE; + /* * When writing messages to the screen, there are many different situations. * A number of variables is used to remember the current state: @@ -83,7 +85,7 @@ * need_wait_return to be set. This is a hack to make ":ts" * work without an extra prompt. * lines_left Number of lines available for messages before the - * more-prompt is to be given. + * more-prompt is to be given. -1 when not set. * need_wait_return TRUE when the hit-return prompt is needed. * Reset: After giving the hit-return prompt, when the user * has answered some other prompt. @@ -220,15 +222,16 @@ if (enc_utf8) /* may have up to 18 bytes per cell (6 per char, up to two * composing chars) */ - buf = alloc((room + 2) * 18); + len = (room + 2) * 18; else if (enc_dbcs == DBCS_JPNU) /* may have up to 2 bytes per cell for euc-jp */ - buf = alloc((room + 2) * 2); + len = (room + 2) * 2; else #endif - buf = alloc(room + 2); + len = room + 2; + buf = alloc(len); if (buf != NULL) - trunc_string(s, buf, room); + trunc_string(s, buf, room, len); } } return buf; @@ -239,10 +242,11 @@ * "s" and "buf" may be equal. */ void -trunc_string(s, buf, room) +trunc_string(s, buf, room, buflen) char_u *s; char_u *buf; int room; + int buflen; { int half; int len; @@ -255,7 +259,7 @@ len = 0; /* First part: Start of the string. */ - for (e = 0; len < half; ++e) + for (e = 0; len < half && e < buflen; ++e) { if (s[e] == NUL) { @@ -272,7 +276,8 @@ if (has_mbyte) for (n = (*mb_ptr2len)(s + e); --n > 0; ) { - ++e; + if (++e == buflen) + break; buf[e] = s[e]; } #endif @@ -317,8 +322,19 @@ } /* Set the middle and copy the last part. */ - mch_memmove(buf + e, "...", (size_t)3); - STRMOVE(buf + e + 3, s + i); + if (e + 3 < buflen) + { + mch_memmove(buf + e, "...", (size_t)3); + len = (int)STRLEN(s + i) + 1; + if (len >= buflen - e - 3) + len = buflen - e - 3 - 1; + mch_memmove(buf + e + 3, s + i, len); + buf[e + 3 + len - 1] = NUL; + } + else + { + buf[e - 1] = NUL; /* make sure it is truncated */ + } } /* @@ -569,6 +585,10 @@ int severe; #endif + /* Skip this if not giving error messages at the moment. */ + if (emsg_not_now()) + return TRUE; + called_emsg = TRUE; ex_exitval = 1; @@ -581,10 +601,6 @@ emsg_severe = FALSE; #endif - /* Skip this if not giving error messages at the moment. */ - if (emsg_not_now()) - return TRUE; - if (!emsg_off || vim_strchr(p_debug, 't') != NULL) { #ifdef FEAT_EVAL @@ -853,6 +869,7 @@ cmdline_row = msg_row; msg_col = 0; msg_clr_eos(); + lines_left = -1; } #endif @@ -879,16 +896,17 @@ if (msg_silent != 0) return; -/* - * With the global command (and some others) we only need one return at the - * end. Adjust cmdline_row to avoid the next message overwriting the last one. - * When inside vgetc(), we can't wait for a typed character at all. - */ + /* + * When inside vgetc(), we can't wait for a typed character at all. + * With the global command (and some others) we only need one return at + * the end. Adjust cmdline_row to avoid the next message overwriting the + * last one. + */ if (vgetc_busy > 0) return; + need_wait_return = TRUE; if (no_wait_return) { - need_wait_return = TRUE; if (!exmode_active) cmdline_row = msg_row; return; @@ -1477,6 +1495,27 @@ return retval; } +#if defined(FEAT_EVAL) || defined(PROTO) +/* + * Return the lhs or rhs of a mapping, with the key codes turned into printable + * strings, in an allocated string. + */ + char_u * +str2special_save(str, is_lhs) + char_u *str; + int is_lhs; /* TRUE for lhs, FALSE for rhs */ +{ + garray_T ga; + char_u *p = str; + + ga_init2(&ga, 1, 40); + while (*p != NUL) + ga_concat(&ga, str2special(&p, is_lhs)); + ga_append(&ga, NUL); + return (char_u *)ga.ga_data; +} +#endif + /* * Return the printable string for the key codes at "*sp". * Used for translating the lhs or rhs of a mapping to printable chars. @@ -1525,16 +1564,27 @@ if (IS_SPECIAL(c) || modifiers) /* special key */ special = TRUE; } - *sp = str + 1; #ifdef FEAT_MBYTE - /* For multi-byte characters check for an illegal byte. */ - if (has_mbyte && MB_BYTE2LEN(*str) > (*mb_ptr2len)(str)) + if (has_mbyte && !IS_SPECIAL(c)) { - transchar_nonprint(buf, c); - return buf; + int len = (*mb_ptr2len)(str); + + /* For multi-byte characters check for an illegal byte. */ + if (has_mbyte && MB_BYTE2LEN(*str) > len) + { + transchar_nonprint(buf, c); + *sp = str + 1; + return buf; + } + /* Since 'special' is TRUE the multi-byte character 'c' will be + * processed by get_special_key_name() */ + c = (*mb_ptr2char)(str); + *sp = str + len; } + else #endif + *sp = str + 1; /* Make unprintable characters in <> form, also and . * Use only for lhs of a mapping. */ @@ -1616,8 +1666,16 @@ else if (has_mbyte && (l = (*mb_ptr2len)(s)) > 1) { col += (*mb_ptr2cells)(s); - mch_memmove(buf, s, (size_t)l); - buf[l] = NUL; + if (lcs_nbsp != NUL && list && mb_ptr2char(s) == 160) + { + mb_char2bytes(lcs_nbsp, buf); + buf[(*mb_ptr2len)(buf)] = NUL; + } + else + { + mch_memmove(buf, s, (size_t)l); + buf[l] = NUL; + } msg_puts(buf); s += l; continue; @@ -1643,6 +1701,11 @@ attr = hl_attr(HLF_8); } } + else if (c == 160 && list && lcs_nbsp != NUL) + { + c = lcs_nbsp; + attr = hl_attr(HLF_8); + } else if (c == NUL && list && lcs_eol != NUL) { p_extra = (char_u *)""; @@ -2285,6 +2348,16 @@ } /* + * Mark the last message chunk as finishing the line. + */ + void +msg_sb_eol() +{ + if (last_msgchunk != NULL) + last_msgchunk->sb_eol = TRUE; +} + +/* * Display a screen line from previously displayed text at row "row". * Returns a pointer to the text for the next line (can be NULL). */ @@ -2438,7 +2511,7 @@ #ifdef FEAT_CON_DIALOG int retval = FALSE; #endif - int scroll; + int toscroll; msgchunk_T *mp_last = NULL; msgchunk_T *mp; int i; @@ -2489,49 +2562,49 @@ } #endif - scroll = 0; + toscroll = 0; switch (c) { case BS: /* scroll one line back */ case K_BS: case 'k': case K_UP: - scroll = -1; + toscroll = -1; break; case CAR: /* one extra line */ case NL: case 'j': case K_DOWN: - scroll = 1; + toscroll = 1; break; case 'u': /* Up half a page */ - scroll = -(Rows / 2); + toscroll = -(Rows / 2); break; case 'd': /* Down half a page */ - scroll = Rows / 2; + toscroll = Rows / 2; break; case 'b': /* one page back */ case K_PAGEUP: - scroll = -(Rows - 1); + toscroll = -(Rows - 1); break; case ' ': /* one extra page */ case 'f': case K_PAGEDOWN: case K_LEFTMOUSE: - scroll = Rows - 1; + toscroll = Rows - 1; break; case 'g': /* all the way back to the start */ - scroll = -999999; + toscroll = -999999; break; case 'G': /* all the way to the end */ - scroll = 999999; + toscroll = 999999; lines_left = 999999; break; @@ -2584,9 +2657,9 @@ continue; } - if (scroll != 0) + if (toscroll != 0) { - if (scroll < 0) + if (toscroll < 0) { /* go to start of last line */ if (mp_last == NULL) @@ -2604,7 +2677,7 @@ if (mp != NULL && mp->sb_prev != NULL) { /* Find line to be displayed at top. */ - for (i = 0; i > scroll; --i) + for (i = 0; i > toscroll; --i) { if (mp == NULL || mp->sb_prev == NULL) break; @@ -2615,7 +2688,7 @@ mp_last = msg_sb_start(mp_last->sb_prev); } - if (scroll == -1 && screen_ins_lines(0, 0, 1, + if (toscroll == -1 && screen_ins_lines(0, 0, 1, (int)Rows, NULL) == OK) { /* display line at top */ @@ -2631,13 +2704,13 @@ ++msg_scrolled; } } - scroll = 0; + toscroll = 0; } } else { /* First display any text that we scrolled back. */ - while (scroll > 0 && mp_last != NULL) + while (toscroll > 0 && mp_last != NULL) { /* scroll up, display line at bottom */ msg_scroll_up(); @@ -2645,11 +2718,11 @@ screen_fill((int)Rows - 2, (int)Rows - 1, 0, (int)Columns, ' ', ' ', 0); mp_last = disp_sb_line((int)Rows - 2, mp_last); - --scroll; + --toscroll; } } - if (scroll <= 0) + if (toscroll <= 0) { /* displayed the requested text, more prompt again */ screen_fill((int)Rows - 1, (int)Rows, 0, @@ -2659,7 +2732,7 @@ } /* display more text, return to caller */ - lines_left = scroll; + lines_left = toscroll; } break; @@ -3019,12 +3092,9 @@ if (redir_off) return; - /* - * If 'verbosefile' is set write message in that file. - * Must come before the rest because of updating "msg_col". - */ - if (*p_vfile != NUL) - verbose_write(s, maxlen); + /* If 'verbosefile' is set prepare for writing in that file. */ + if (*p_vfile != NUL && verbose_fd == NULL) + verbose_open(); if (redirecting()) { @@ -3038,9 +3108,12 @@ write_reg_contents(redir_reg, (char_u *)" ", -1, TRUE); else if (redir_vname) var_redir_str((char_u *)" ", -1); - else if (redir_fd) + else #endif + if (redir_fd != NULL) fputs(" ", redir_fd); + if (verbose_fd != NULL) + fputs(" ", verbose_fd); ++cur_col; } } @@ -3052,13 +3125,16 @@ var_redir_str(s, maxlen); #endif - /* Adjust the current column */ + /* Write and adjust the current column. */ while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen)) { #ifdef FEAT_EVAL - if (!redir_reg && !redir_vname && redir_fd != NULL) + if (!redir_reg && !redir_vname) #endif - putc(*s, redir_fd); + if (redir_fd != NULL) + putc(*s, redir_fd); + if (verbose_fd != NULL) + putc(*s, verbose_fd); if (*s == '\r' || *s == '\n') cur_col = 0; else if (*s == '\t') @@ -3076,7 +3152,7 @@ int redirecting() { - return redir_fd != NULL + return redir_fd != NULL || *p_vfile != NUL #ifdef FEAT_EVAL || redir_reg || redir_vname #endif @@ -3134,9 +3210,6 @@ cmdline_row = msg_row; } -static FILE *verbose_fd = NULL; -static int verbose_did_open = FALSE; - /* * Called when 'verbosefile' is set: stop writing to the file. */ @@ -3174,49 +3247,6 @@ } /* - * Write a string to 'verbosefile'. - * When "maxlen" is -1 write the whole string, otherwise up to "maxlen" bytes. - */ - static void -verbose_write(str, maxlen) - char_u *str; - int maxlen; -{ - char_u *s = str; - static int cur_col = 0; - - /* Open the file when called the first time. */ - if (verbose_fd == NULL) - verbose_open(); - - if (verbose_fd != NULL) - { - /* If the string doesn't start with CR or NL, go to msg_col */ - if (*s != '\n' && *s != '\r') - { - while (cur_col < msg_col) - { - fputs(" ", verbose_fd); - ++cur_col; - } - } - - /* Adjust the current column */ - while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen)) - { - putc(*s, verbose_fd); - if (*s == '\r' || *s == '\n') - cur_col = 0; - else if (*s == '\t') - cur_col += (8 - cur_col % 8); - else - ++cur_col; - ++s; - } - } -} - -/* * Give a warning message (for searching). * Use 'w' highlighting and may repeat the message after redrawing */ @@ -3294,7 +3324,7 @@ * different letter. */ int -do_dialog(type, title, message, buttons, dfltbutton, textfield) +do_dialog(type, title, message, buttons, dfltbutton, textfield, ex_cmd) int type UNUSED; char_u *title UNUSED; char_u *message; @@ -3302,6 +3332,8 @@ int dfltbutton; char_u *textfield UNUSED; /* IObuff for inputdialog(), NULL otherwise */ + int ex_cmd; /* when TRUE pressing : accepts default and starts + Ex command */ { int oldState; int retval = 0; @@ -3320,7 +3352,7 @@ if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL) { c = gui_mch_dialog(type, title, message, buttons, dfltbutton, - textfield); + textfield, ex_cmd); /* avoid a hit-enter prompt without clearing the cmdline */ need_wait_return = FALSE; emsg_on_display = FALSE; @@ -3367,6 +3399,13 @@ default: /* Could be a hotkey? */ if (c < 0) /* special keys are ignored here */ continue; + if (c == ':' && ex_cmd) + { + retval = dfltbutton; + ins_char_typebuf(':'); + break; + } + /* Make the character lowercase, as chars in "hotkeys" are. */ c = MB_TOLOWER(c); retval = 1; @@ -3640,7 +3679,7 @@ if (do_dialog(type, title == NULL ? (char_u *)_("Question") : title, message, - (char_u *)_("&Yes\n&No"), dflt, NULL) == 1) + (char_u *)_("&Yes\n&No"), dflt, NULL, FALSE) == 1) return VIM_YES; return VIM_NO; } @@ -3655,7 +3694,7 @@ switch (do_dialog(type, title == NULL ? (char_u *)_("Question") : title, message, - (char_u *)_("&Yes\n&No\n&Cancel"), dflt, NULL)) + (char_u *)_("&Yes\n&No\n&Cancel"), dflt, NULL, FALSE)) { case 1: return VIM_YES; case 2: return VIM_NO; @@ -3674,7 +3713,7 @@ title == NULL ? (char_u *)"Question" : title, message, (char_u *)_("&Yes\n&No\nSave &All\n&Discard All\n&Cancel"), - dflt, NULL)) + dflt, NULL, FALSE)) { case 1: return VIM_YES; case 2: return VIM_NO; diff -Naur vim73.orig/src/misc1.c vim73/src/misc1.c --- vim73.orig/src/misc1.c 2010-08-15 11:24:05.000000000 +0000 +++ vim73/src/misc1.c 2012-07-20 20:31:17.904311537 +0000 @@ -363,7 +363,7 @@ /* 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 && !curbuf->b_p_et) { todo -= tab_pad; ++ind_len; @@ -372,7 +372,7 @@ } /* Add tabs required for indent */ - while (todo >= (int)curbuf->b_p_ts) + while (todo >= (int)curbuf->b_p_ts && !curbuf->b_p_et) { todo -= (int)curbuf->b_p_ts; ++ind_len; @@ -423,27 +423,36 @@ { colnr_T col; pos_T pos; - regmmatch_T regmatch; + + regmatch_T regmatch; + int lead_len = 0; /* length of comment leader */ if (lnum > curbuf->b_ml.ml_line_count) return -1; pos.lnum = 0; + +#ifdef FEAT_COMMENTS + /* In format_lines() (i.e. not insert mode), fo+=q is needed too... */ + if ((State & INSERT) || has_format_option(FO_Q_COMS)) + lead_len = get_leader_len(ml_get(lnum), NULL, FALSE, TRUE); +#endif regmatch.regprog = vim_regcomp(curbuf->b_p_flp, RE_MAGIC); if (regmatch.regprog != NULL) { - regmatch.rmm_ic = FALSE; - regmatch.rmm_maxcol = 0; - if (vim_regexec_multi(®match, curwin, curbuf, lnum, - (colnr_T)0, NULL)) + regmatch.rm_ic = FALSE; + + /* vim_regexec() expects a pointer to a line. This lets us + * start matching for the flp beyond any comment leader... */ + if (vim_regexec(®match, ml_get(lnum) + lead_len, (colnr_T)0)) { - pos.lnum = regmatch.endpos[0].lnum + lnum; - pos.col = regmatch.endpos[0].col; + pos.lnum = lnum; + pos.col = (colnr_T)(*regmatch.endp - ml_get(lnum)); #ifdef FEAT_VIRTUALEDIT pos.coladd = 0; #endif } - vim_free(regmatch.regprog); } + vim_free(regmatch.regprog); if (pos.lnum == 0 || *ml_get_pos(&pos) == NUL) return -1; @@ -502,14 +511,18 @@ * OPENLINE_DO_COM format comments * OPENLINE_KEEPTRAIL keep trailing spaces * OPENLINE_MARKFIX adjust mark positions after the line break + * OPENLINE_COM_LIST format comments with list or 2nd line indent + * + * "second_line_indent": indent for after ^^D in Insert mode or if flag + * OPENLINE_COM_LIST * * Return TRUE for success, FALSE for failure */ int -open_line(dir, flags, old_indent) +open_line(dir, flags, second_line_indent) int dir; /* FORWARD or BACKWARD */ int flags; - int old_indent; /* indent for after ^^D in Insert mode */ + int second_line_indent; { char_u *saved_line; /* copy of the original line */ char_u *next_line = NULL; /* copy of the next line */ @@ -650,8 +663,8 @@ * count white space on current line */ newindent = get_indent_str(saved_line, (int)curbuf->b_p_ts); - if (newindent == 0) - newindent = old_indent; /* for ^^D command in insert mode */ + if (newindent == 0 && !(flags & OPENLINE_COM_LIST)) + newindent = second_line_indent; /* for ^^D command in insert mode */ #ifdef FEAT_SMARTINDENT /* @@ -671,7 +684,7 @@ ptr = saved_line; # ifdef FEAT_COMMENTS if (flags & OPENLINE_DO_COM) - lead_len = get_leader_len(ptr, NULL, FALSE); + lead_len = get_leader_len(ptr, NULL, FALSE, TRUE); else lead_len = 0; # endif @@ -693,7 +706,7 @@ } # ifdef FEAT_COMMENTS if (flags & OPENLINE_DO_COM) - lead_len = get_leader_len(ptr, NULL, FALSE); + lead_len = get_leader_len(ptr, NULL, FALSE, TRUE); else lead_len = 0; if (lead_len > 0) @@ -836,7 +849,7 @@ */ end_comment_pending = NUL; if (flags & OPENLINE_DO_COM) - lead_len = get_leader_len(saved_line, &lead_flags, dir == BACKWARD); + lead_len = get_leader_len(saved_line, &lead_flags, dir == BACKWARD, TRUE); else lead_len = 0; if (lead_len > 0) @@ -1007,9 +1020,9 @@ } if (lead_len) { - /* allocate buffer (may concatenate p_exta later) */ - leader = alloc(lead_len + lead_repl_len + extra_space + - extra_len + 1); + /* allocate buffer (may concatenate p_extra later) */ + leader = alloc(lead_len + lead_repl_len + extra_space + extra_len + + (second_line_indent > 0 ? second_line_indent : 0) + 1); allocated = leader; /* remember to free it later */ if (leader == NULL) @@ -1304,6 +1317,21 @@ /* concatenate leader and p_extra, if there is a leader */ if (lead_len) { + if (flags & OPENLINE_COM_LIST && second_line_indent > 0) + { + int i; + int padding = second_line_indent + - (newindent + (int)STRLEN(leader)); + + /* Here whitespace is inserted after the comment char. + * Below, set_indent(newindent, SIN_INSERT) will insert the + * whitespace needed before the comment char. */ + for (i = 0; i < padding; i++) + { + STRCAT(leader, " "); + newcol++; + } + } STRCAT(leader, p_extra); p_extra = leader; did_ai = TRUE; /* So truncating blanks works with comments */ @@ -1548,28 +1576,35 @@ * When "flags" is not NULL, it is set to point to the flags of the recognized * comment leader. * "backward" must be true for the "O" command. + * If "include_space" is set, include trailing whitespace while calculating the + * length. */ int -get_leader_len(line, flags, backward) +get_leader_len(line, flags, backward, include_space) char_u *line; char_u **flags; int backward; + int include_space; { int i, j; + int result; int got_com = FALSE; int found_one; char_u part_buf[COM_MAX_LEN]; /* buffer for one option part */ char_u *string; /* pointer to comment string */ char_u *list; + int middle_match_len = 0; + char_u *prev_list; + char_u *saved_flags = NULL; - i = 0; + result = i = 0; while (vim_iswhite(line[i])) /* leading white space is ignored */ ++i; /* * Repeat to match several nested comment strings. */ - while (line[i]) + while (line[i] != NUL) { /* * scan through the 'comments' option for a match @@ -1577,29 +1612,161 @@ found_one = FALSE; for (list = curbuf->b_p_com; *list; ) { - /* - * Get one option part into part_buf[]. Advance list to next one. - * put string at start of string. - */ - if (!got_com && flags != NULL) /* remember where flags started */ - *flags = list; + /* Get one option part into part_buf[]. Advance "list" to next + * one. Put "string" at start of string. */ + if (!got_com && flags != NULL) + *flags = list; /* remember where flags started */ + prev_list = list; (void)copy_option_part(&list, part_buf, COM_MAX_LEN, ","); string = vim_strchr(part_buf, ':'); if (string == NULL) /* missing ':', ignore this part */ continue; *string++ = NUL; /* isolate flags from string */ - /* - * When already found a nested comment, only accept further - * nested comments. - */ + /* If we found a middle match previously, use that match when this + * is not a middle or end. */ + if (middle_match_len != 0 + && vim_strchr(part_buf, COM_MIDDLE) == NULL + && vim_strchr(part_buf, COM_END) == NULL) + break; + + /* When we already found a nested comment, only accept further + * nested comments. */ if (got_com && vim_strchr(part_buf, COM_NEST) == NULL) continue; - /* When 'O' flag used don't use for "O" command */ + /* When 'O' flag present and using "O" command skip this one. */ if (backward && vim_strchr(part_buf, COM_NOBACK) != NULL) continue; + /* Line contents and string must match. + * When string starts with white space, must have some white space + * (but the amount does not need to match, there might be a mix of + * TABs and spaces). */ + if (vim_iswhite(string[0])) + { + if (i == 0 || !vim_iswhite(line[i - 1])) + continue; /* missing shite space */ + while (vim_iswhite(string[0])) + ++string; + } + for (j = 0; string[j] != NUL && string[j] == line[i + j]; ++j) + ; + if (string[j] != NUL) + continue; /* string doesn't match */ + + /* When 'b' flag used, there must be white space or an + * end-of-line after the string in the line. */ + if (vim_strchr(part_buf, COM_BLANK) != NULL + && !vim_iswhite(line[i + j]) && line[i + j] != NUL) + continue; + + /* We have found a match, stop searching unless this is a middle + * comment. The middle comment can be a substring of the end + * comment in which case it's better to return the length of the + * end comment and its flags. Thus we keep searching with middle + * and end matches and use an end match if it matches better. */ + if (vim_strchr(part_buf, COM_MIDDLE) != NULL) + { + if (middle_match_len == 0) + { + middle_match_len = j; + saved_flags = prev_list; + } + continue; + } + if (middle_match_len != 0 && j > middle_match_len) + /* Use this match instead of the middle match, since it's a + * longer thus better match. */ + middle_match_len = 0; + + if (middle_match_len == 0) + i += j; + found_one = TRUE; + break; + } + + if (middle_match_len != 0) + { + /* Use the previously found middle match after failing to find a + * match with an end. */ + if (!got_com && flags != NULL) + *flags = saved_flags; + i += middle_match_len; + found_one = TRUE; + } + + /* No match found, stop scanning. */ + if (!found_one) + break; + + result = i; + + /* Include any trailing white space. */ + while (vim_iswhite(line[i])) + ++i; + + if (include_space) + result = i; + + /* If this comment doesn't nest, stop here. */ + got_com = TRUE; + if (vim_strchr(part_buf, COM_NEST) == NULL) + break; + } + return result; +} + +/* + * Return the offset at which the last comment in line starts. If there is no + * comment in the whole line, -1 is returned. + * + * When "flags" is not null, it is set to point to the flags describing the + * recognized comment leader. + */ + int +get_last_leader_offset(line, flags) + char_u *line; + char_u **flags; +{ + int result = -1; + int i, j; + int lower_check_bound = 0; + char_u *string; + char_u *com_leader; + char_u *com_flags; + char_u *list; + int found_one; + char_u part_buf[COM_MAX_LEN]; /* buffer for one option part */ + + /* + * Repeat to match several nested comment strings. + */ + i = (int)STRLEN(line); + while (--i >= lower_check_bound) + { + /* + * scan through the 'comments' option for a match + */ + found_one = FALSE; + for (list = curbuf->b_p_com; *list; ) + { + char_u *flags_save = list; + + /* + * Get one option part into part_buf[]. Advance list to next one. + * put string at start of string. + */ + (void)copy_option_part(&list, part_buf, COM_MAX_LEN, ","); + string = vim_strchr(part_buf, ':'); + if (string == NULL) /* If everything is fine, this cannot actually + * happen. */ + { + continue; + } + *string++ = NUL; /* Isolate flags from string. */ + com_leader = string; + /* * Line contents and string must match. * When string starts with white space, must have some white space @@ -1614,7 +1781,7 @@ ++string; } for (j = 0; string[j] != NUL && string[j] == line[i + j]; ++j) - ; + /* do nothing */; if (string[j] != NUL) continue; @@ -1623,37 +1790,77 @@ * end-of-line after the string in the line. */ if (vim_strchr(part_buf, COM_BLANK) != NULL - && !vim_iswhite(line[i + j]) && line[i + j] != NUL) + && !vim_iswhite(line[i + j]) && line[i + j] != NUL) + { continue; + } /* * We have found a match, stop searching. */ - i += j; - got_com = TRUE; found_one = TRUE; + + if (flags) + *flags = flags_save; + com_flags = flags_save; + break; } - /* - * No match found, stop scanning. - */ - if (!found_one) - break; + if (found_one) + { + char_u part_buf2[COM_MAX_LEN]; /* buffer for one option part */ + int len1, len2, off; - /* - * Include any trailing white space. - */ - while (vim_iswhite(line[i])) - ++i; + result = i; + /* + * If this comment nests, continue searching. + */ + if (vim_strchr(part_buf, COM_NEST) != NULL) + continue; - /* - * If this comment doesn't nest, stop here. - */ - if (vim_strchr(part_buf, COM_NEST) == NULL) - break; + lower_check_bound = i; + + /* Let's verify whether the comment leader found is a substring + * of other comment leaders. If it is, let's adjust the + * lower_check_bound so that we make sure that we have determined + * the comment leader correctly. + */ + + while (vim_iswhite(*com_leader)) + ++com_leader; + len1 = (int)STRLEN(com_leader); + + for (list = curbuf->b_p_com; *list; ) + { + char_u *flags_save = list; + + (void)copy_option_part(&list, part_buf2, COM_MAX_LEN, ","); + if (flags_save == com_flags) + continue; + string = vim_strchr(part_buf2, ':'); + ++string; + while (vim_iswhite(*string)) + ++string; + len2 = (int)STRLEN(string); + if (len2 == 0) + continue; + + /* Now we have to verify whether string ends with a substring + * beginning the com_leader. */ + for (off = (len2 > i ? i : len2); off > 0 && off + len1 > len2;) + { + --off; + if (!STRNCMP(string + off, com_leader, len2 - off)) + { + if (i - off < lower_check_bound) + lower_check_bound = i - off; + } + } + } + } } - return (got_com ? i : 0); + return result; } #endif @@ -1907,7 +2114,7 @@ int c; { #if defined(FEAT_MBYTE) || defined(PROTO) - char_u buf[MB_MAXBYTES]; + char_u buf[MB_MAXBYTES + 1]; int n; n = (*mb_char2bytes)(c, buf); @@ -2919,7 +3126,7 @@ buf_T *buf; int ff; /* also reset 'fileformat' */ { - if (buf->b_changed || (ff && file_ff_differs(buf))) + if (buf->b_changed || (ff && file_ff_differs(buf, FALSE))) { buf->b_changed = 0; ml_setflags(buf); @@ -3080,8 +3287,9 @@ int get_keystroke() { -#define CBUFLEN 151 - char_u buf[CBUFLEN]; + char_u *buf = NULL; + int buflen = 150; + int maxlen; int len = 0; int n; int save_mapped_ctrl_c = mapped_ctrl_c; @@ -3093,12 +3301,29 @@ cursor_on(); out_flush(); + /* Leave some room for check_termcode() to insert a key code into (max + * 5 chars plus NUL). And fix_input_buffer() can triple the number of + * bytes. */ + maxlen = (buflen - 6 - len) / 3; + if (buf == NULL) + buf = alloc(buflen); + else if (maxlen < 10) + { + /* Need some more space. This might happen when receiving a long + * escape sequence. */ + buflen += 100; + buf = vim_realloc(buf, buflen); + maxlen = (buflen - 6 - len) / 3; + } + if (buf == NULL) + { + do_outofmem_msg((long_u)buflen); + return ESC; /* panic! */ + } + /* First time: blocking wait. Second time: wait up to 100ms for a - * terminal code to complete. Leave some room for check_termcode() to - * insert a key code into (max 5 chars plus NUL). And - * fix_input_buffer() can triple the number of bytes. */ - n = ui_inchar(buf + len, (CBUFLEN - 6 - len) / 3, - len == 0 ? -1L : 100L, 0); + * terminal code to complete. */ + n = ui_inchar(buf + len, maxlen, len == 0 ? -1L : 100L, 0); if (n > 0) { /* Replace zero and CSI by a special key code. */ @@ -3110,14 +3335,23 @@ ++waited; /* keep track of the waiting time */ /* Incomplete termcode and not timed out yet: get more characters */ - if ((n = check_termcode(1, buf, len)) < 0 + if ((n = check_termcode(1, buf, buflen, &len)) < 0 && (!p_ttimeout || waited * 100L < (p_ttm < 0 ? p_tm : p_ttm))) continue; - /* found a termcode: adjust length */ - if (n > 0) + if (n == KEYLEN_REMOVED) /* key code removed */ + { + if (must_redraw != 0 && !need_wait_return && (State & CMDLINE) == 0) + { + /* Redrawing was postponed, do it now. */ + update_screen(0); + setcursor(); /* put cursor back where it belongs */ + } + continue; + } + if (n > 0) /* found a termcode: adjust length */ len = n; - if (len == 0) /* nothing typed yet */ + if (len == 0) /* nothing typed yet */ continue; /* Handle modifier and/or special key code. */ @@ -3169,7 +3403,7 @@ { if (MB_BYTE2LEN(n) > len) continue; /* more bytes to get */ - buf[len >= CBUFLEN ? CBUFLEN - 1 : len] = NUL; + buf[len >= buflen ? buflen - 1 : len] = NUL; n = (*mb_ptr2char)(buf); } #endif @@ -3179,6 +3413,7 @@ #endif break; } + vim_free(buf); mapped_ctrl_c = save_mapped_ctrl_c; return n; @@ -3323,19 +3558,23 @@ if (pn == 1) { if (n > 0) - STRCPY(msg_buf, _("1 more line")); + vim_strncpy(msg_buf, (char_u *)_("1 more line"), + MSG_BUF_LEN - 1); else - STRCPY(msg_buf, _("1 line less")); + vim_strncpy(msg_buf, (char_u *)_("1 line less"), + MSG_BUF_LEN - 1); } else { if (n > 0) - sprintf((char *)msg_buf, _("%ld more lines"), pn); + vim_snprintf((char *)msg_buf, MSG_BUF_LEN, + _("%ld more lines"), pn); else - sprintf((char *)msg_buf, _("%ld fewer lines"), pn); + vim_snprintf((char *)msg_buf, MSG_BUF_LEN, + _("%ld fewer lines"), pn); } if (got_int) - STRCAT(msg_buf, _(" (Interrupted)")); + vim_strcat(msg_buf, (char_u *)_(" (Interrupted)"), MSG_BUF_LEN); if (msg(msg_buf)) { set_keep_msg(msg_buf, 0); @@ -3492,7 +3731,7 @@ if (enc_utf8 && var != NULL) { int len; - char_u *pp; + char_u *pp = NULL; /* Convert from active codepage to UTF-8. Other conversions are * not done, because they would fail for non-ASCII characters. */ @@ -3859,11 +4098,13 @@ * Vim's version of getenv(). * Special handling of $HOME, $VIM and $VIMRUNTIME. * Also does ACP to 'enc' conversion for Win32. + * "mustfree" is set to TRUE when returned is allocated, it must be + * initialized to FALSE by the caller. */ char_u * vim_getenv(name, mustfree) char_u *name; - int *mustfree; /* set to TRUE when returned is allocated */ + int *mustfree; { char_u *p; char_u *pend; @@ -3885,7 +4126,7 @@ if (enc_utf8) { int len; - char_u *pp; + char_u *pp = NULL; /* Convert from active codepage to UTF-8. Other conversions are * not done, because they would fail for non-ASCII characters. */ @@ -3929,7 +4170,7 @@ if (enc_utf8) { int len; - char_u *pp; + char_u *pp = NULL; /* Convert from active codepage to UTF-8. Other conversions * are not done, because they would fail for non-ASCII @@ -3937,7 +4178,7 @@ acp_to_enc(p, (int)STRLEN(p), &pp, &len); if (pp != NULL) { - if (mustfree) + if (*mustfree) vim_free(p); p = pp; *mustfree = TRUE; @@ -4074,17 +4315,6 @@ { vim_setenv((char_u *)"VIMRUNTIME", p); didset_vimruntime = TRUE; -#ifdef FEAT_GETTEXT - { - char_u *buf = concat_str(p, (char_u *)"/lang"); - - if (buf != NULL) - { - bindtextdomain(VIMPACKAGE, (char *)buf); - vim_free(buf); - } - } -#endif } else { @@ -4162,6 +4392,22 @@ putenv((char *)envbuf); } #endif +#ifdef FEAT_GETTEXT + /* + * When setting $VIMRUNTIME adjust the directory to find message + * translations to $VIMRUNTIME/lang. + */ + if (*val != NUL && STRICMP(name, "VIMRUNTIME") == 0) + { + char_u *buf = concat_str(val, (char_u *)"/lang"); + + if (buf != NULL) + { + bindtextdomain(VIMPACKAGE, (char *)buf); + vim_free(buf); + } + } +#endif } #if defined(FEAT_CMDL_COMPL) || defined(PROTO) @@ -4220,7 +4466,7 @@ { size_t dirlen = 0, envlen = 0; size_t len; - char_u *homedir_env; + char_u *homedir_env, *homedir_env_orig; char_u *p; if (src == NULL) @@ -4246,13 +4492,31 @@ dirlen = STRLEN(homedir); #ifdef VMS - homedir_env = mch_getenv((char_u *)"SYS$LOGIN"); + homedir_env_orig = homedir_env = mch_getenv((char_u *)"SYS$LOGIN"); #else - homedir_env = mch_getenv((char_u *)"HOME"); + homedir_env_orig = homedir_env = mch_getenv((char_u *)"HOME"); #endif - + /* Empty is the same as not set. */ if (homedir_env != NULL && *homedir_env == NUL) homedir_env = NULL; + +#if defined(FEAT_MODIFY_FNAME) || defined(WIN3264) + if (homedir_env != NULL && vim_strchr(homedir_env, '~') != NULL) + { + int usedlen = 0; + int flen; + char_u *fbuf = NULL; + + flen = (int)STRLEN(homedir_env); + (void)modify_fname((char_u *)":p", &usedlen, + &homedir_env, &fbuf, &flen); + flen = (int)STRLEN(homedir_env); + if (flen > 0 && vim_ispathsep(homedir_env[flen - 1])) + /* Remove the trailing / that is added to a directory. */ + homedir_env[flen - 1] = NUL; + } +#endif + if (homedir_env != NULL) envlen = STRLEN(homedir_env); @@ -4306,6 +4570,9 @@ /* if (dstlen == 0) out of space, what to do??? */ *dst = NUL; + + if (homedir_env != homedir_env_orig) + vim_free(homedir_env); } /* @@ -4549,25 +4816,21 @@ vim_ispathsep(c) int c; { -#ifdef RISCOS - return (c == '.' || c == ':'); -#else -# ifdef UNIX +#ifdef UNIX return (c == '/'); /* UNIX has ':' inside file names */ -# else -# ifdef BACKSLASH_IN_FILENAME +#else +# ifdef BACKSLASH_IN_FILENAME return (c == ':' || c == '/' || c == '\\'); -# else -# ifdef VMS +# else +# ifdef VMS /* server"user passwd"::device:[full.path.name]fname.extension;version" */ return (c == ':' || c == '[' || c == ']' || c == '/' || c == '<' || c == '>' || c == '"' ); -# else /* Amiga */ +# else return (c == ':' || c == '/'); -# endif /* VMS */ -# endif +# endif /* VMS */ # endif -#endif /* RISC OS */ +#endif } #if defined(FEAT_SEARCHPATH) || defined(PROTO) @@ -4752,8 +5015,8 @@ char_u * FullName_save(fname, force) char_u *fname; - int force; /* force expansion, even when it already looks - like a full path name */ + int force; /* force expansion, even when it already looks + * like a full path name */ { char_u *buf; char_u *new_fname = NULL; @@ -4907,11 +5170,12 @@ static int cin_islinecomment __ARGS((char_u *)); static int cin_isterminated __ARGS((char_u *, int, int)); static int cin_isinit __ARGS((void)); -static int cin_isfuncdecl __ARGS((char_u **, linenr_T)); +static int cin_isfuncdecl __ARGS((char_u **, linenr_T, linenr_T, int, int)); static int cin_isif __ARGS((char_u *)); static int cin_iselse __ARGS((char_u *)); static int cin_isdo __ARGS((char_u *)); static int cin_iswhileofdo __ARGS((char_u *, linenr_T, int)); +static int cin_is_if_for_while_before_offset __ARGS((char_u *line, int *poffset)); 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((colnr_T *col)); @@ -4923,6 +5187,7 @@ static int corr_ind_maxparen __ARGS((int ind_maxparen, pos_T *startpos)); static int find_last_paren __ARGS((char_u *l, int start, int end)); static int find_match __ARGS((int lookfor, linenr_T ourscope, int ind_maxparen, int ind_maxcomment)); +static int cin_is_cpp_namespace __ARGS((char_u *)); static int ind_hash_comment = 0; /* # starts a comment */ @@ -4968,7 +5233,7 @@ } /* - * Return TRUE if there there is no code at *s. White space and comments are + * Return TRUE if there is no code at *s. White space and comments are * not considered code. */ static int @@ -5101,6 +5366,9 @@ if (STRNCMP(s, "typedef", 7) == 0 && !vim_isIDc(s[7])) s = cin_skipcomment(s + 7); + if (STRNCMP(s, "static", 6) == 0 && !vim_isIDc(s[6])) + s = cin_skipcomment(s + 6); + if (STRNCMP(s, "enum", 4) == 0 && !vim_isIDc(s[4])) return TRUE; @@ -5185,6 +5453,50 @@ return (*(s = cin_skipcomment(s + i)) == ':' && s[1] != ':'); } +/* Maximum number of lines to search back for a "namespace" line. */ +#define FIND_NAMESPACE_LIM 20 + +/* + * Recognize a "namespace" scope declaration. + */ + static int +cin_is_cpp_namespace(s) + char_u *s; +{ + char_u *p; + int has_name = FALSE; + + s = cin_skipcomment(s); + if (STRNCMP(s, "namespace", 9) == 0 && (s[9] == NUL || !vim_iswordc(s[9]))) + { + p = cin_skipcomment(skipwhite(s + 9)); + while (*p != NUL) + { + if (vim_iswhite(*p)) + { + has_name = TRUE; /* found end of a name */ + p = cin_skipcomment(skipwhite(p)); + } + else if (*p == '{') + { + break; + } + else if (vim_iswordc(*p)) + { + if (has_name) + return FALSE; /* word character after skipping past name */ + ++p; + } + else + { + return FALSE; + } + } + return TRUE; + } + return FALSE; +} + /* * Return a pointer to the first non-empty non-comment character after a ':'. * Return NULL if not found. @@ -5383,8 +5695,7 @@ cin_ispreproc(s) char_u *s; { - s = skipwhite(s); - if (*s == '#') + if (*skipwhite(s) == '#') return TRUE; return FALSE; } @@ -5444,8 +5755,11 @@ } /* - * Recognize a line that starts with '{' or '}', or ends with ';', '{' or '}'. + * Recognize a line that starts with '{' or '}', or ends with ';', ',', '{' or + * '}'. * Don't consider "} else" a terminated line. + * If a line begins with an "else", only consider it terminated if no unmatched + * opening braces follow (handle "else { foo();" correctly). * Return the character terminating the line (ending char's have precedence if * both apply in order to determine initializations). */ @@ -5455,21 +5769,35 @@ int incl_open; /* include '{' at the end as terminator */ int incl_comma; /* recognize a trailing comma */ { - char_u found_start = 0; + char_u found_start = 0; + unsigned n_open = 0; + int is_else = FALSE; s = cin_skipcomment(s); if (*s == '{' || (*s == '}' && !cin_iselse(s))) found_start = *s; + if (!found_start) + is_else = cin_iselse(s); + while (*s) { /* skip over comments, "" strings and 'c'haracters */ s = skip_string(cin_skipcomment(s)); - if ((*s == ';' || (incl_open && *s == '{') || *s == '}' - || (incl_comma && *s == ',')) + if (*s == '}' && n_open > 0) + --n_open; + if ((!is_else || n_open == 0) + && (*s == ';' || *s == '}' || (incl_comma && *s == ',')) && cin_nocode(s + 1)) return *s; + else if (*s == '{') + { + if (incl_open && cin_nocode(s + 1)) + return *s; + else + ++n_open; + } if (*s) s++; @@ -5485,21 +5813,41 @@ * "sp" points to a string with the line. When looking at other lines it must * be restored to the line. When it's NULL fetch lines here. * "lnum" is where we start looking. + * "min_lnum" is the line before which we will not be looking. */ static int -cin_isfuncdecl(sp, first_lnum) +cin_isfuncdecl(sp, first_lnum, min_lnum, ind_maxparen, ind_maxcomment) char_u **sp; linenr_T first_lnum; + linenr_T min_lnum; + int ind_maxparen; + int ind_maxcomment; { char_u *s; linenr_T lnum = first_lnum; int retval = FALSE; + pos_T *trypos; + int just_started = TRUE; if (sp == NULL) s = ml_get(lnum); else s = *sp; + if (find_last_paren(s, '(', ')') + && (trypos = find_match_paren(ind_maxparen, ind_maxcomment)) != NULL) + { + lnum = trypos->lnum; + if (lnum < min_lnum) + return FALSE; + + s = ml_get(lnum); + } + + /* Ignore line starting with #. */ + if (cin_ispreproc(s)) + return FALSE; + while (*s && *s != '(' && *s != ';' && *s != '\'' && *s != '"') { if (cin_iscomment(s)) /* ignore comments */ @@ -5525,18 +5873,38 @@ retval = TRUE; goto done; } - if (*s == ',' && cin_nocode(s + 1)) + if ((*s == ',' && cin_nocode(s + 1)) || s[1] == NUL || cin_nocode(s)) { - /* ',' at the end: continue looking in the next line */ + int comma = (*s == ','); + + /* ',' at the end: continue looking in the next line. + * At the end: check for ',' in the next line, for this style: + * func(arg1 + * , arg2) */ + for (;;) + { + if (lnum >= curbuf->b_ml.ml_line_count) + break; + s = ml_get(++lnum); + if (!cin_ispreproc(s)) + break; + } if (lnum >= curbuf->b_ml.ml_line_count) break; - - s = ml_get(++lnum); + /* Require a comma at end of the line or a comma or ')' at the + * start of next line. */ + s = skipwhite(s); + if (!just_started && (!comma && *s != ',' && *s != ')')) + break; + just_started = FALSE; } else if (cin_iscomment(s)) /* ignore comments */ s = cin_skipcomment(s); else + { ++s; + just_started = FALSE; + } } done: @@ -5607,6 +5975,52 @@ } /* + * Check whether in "p" there is an "if", "for" or "while" before "*poffset". + * Return 0 if there is none. + * Otherwise return !0 and update "*poffset" to point to the place where the + * string was found. + */ + static int +cin_is_if_for_while_before_offset(line, poffset) + char_u *line; + int *poffset; +{ + int offset = *poffset; + + if (offset-- < 2) + return 0; + while (offset > 2 && vim_iswhite(line[offset])) + --offset; + + offset -= 1; + if (!STRNCMP(line + offset, "if", 2)) + goto probablyFound; + + if (offset >= 1) + { + offset -= 1; + if (!STRNCMP(line + offset, "for", 3)) + goto probablyFound; + + if (offset >= 2) + { + offset -= 2; + if (!STRNCMP(line + offset, "while", 5)) + goto probablyFound; + } + } + return 0; + +probablyFound: + if (!offset || !vim_isIDc(line[offset - 1])) + { + *poffset = offset; + return 1; + } + return 0; +} + +/* * Return TRUE if we are at the end of a do-while. * do * nothing; @@ -5754,7 +6168,9 @@ continue; } - if (s[0] == ':') + if (s[0] == '"') + s = skip_string(s) + 1; + else if (s[0] == ':') { if (s[1] == ':') { @@ -5958,7 +6374,7 @@ /* * Find the matching '(', failing if it is in a comment. - * Return NULL of no match found. + * Return NULL if no match found. */ static pos_T * find_match_paren(ind_maxparen, ind_maxcomment) /* XXX */ @@ -6008,7 +6424,7 @@ /* * Set w_cursor.col to the column number of the last unmatched ')' or '{' in - * line "l". + * line "l". "l" must point to the start of the line. */ static int find_last_paren(l, start, end) @@ -6021,7 +6437,7 @@ curwin->w_cursor.col = 0; /* default is start of line */ - for (i = 0; l[i]; i++) + for (i = 0; l[i] != NUL; i++) { i = (int)(cin_skipcomment(l + i) - l); /* ignore parens in comments */ i = (int)(skip_string(l + i) - l); /* ignore parens in quotes */ @@ -6222,6 +6638,17 @@ */ int ind_keep_case_label = 0; + /* + * handle C++ namespace + */ + int ind_cpp_namespace = 0; + + /* + * handle continuation lines containing conditions of if(), for() and + * while() + */ + int ind_if_for_while = 0; + pos_T cur_curpos; int amount; int scope_amount; @@ -6257,19 +6684,23 @@ int whilelevel; linenr_T lnum; char_u *options; + char_u *digits; int fraction = 0; /* init for GCC */ int divider; int n; int iscase; int lookfor_break; + int lookfor_cpp_namespace = FALSE; int cont_amount = 0; /* amount for continuation line */ int original_line_islabel; + int added_to_amount = 0; for (options = curbuf->b_p_cino; *options; ) { l = options++; if (*options == '-') ++options; + digits = options; /* remember where the digits start */ n = getdigits(&options); divider = 0; if (*options == '.') /* ".5s" means a fraction */ @@ -6286,7 +6717,7 @@ } if (*options == 's') /* "2s" means two times 'shiftwidth' */ { - if (n == 0 && fraction == 0) + if (options == digits) n = curbuf->b_p_sw; /* just "s" is one 'shiftwidth' */ else { @@ -6335,6 +6766,8 @@ case 'J': ind_js = n; break; case 'l': ind_keep_case_label = n; break; case '#': ind_hash_comment = n; break; + case 'N': ind_cpp_namespace = n; break; + case 'k': ind_if_for_while = n; break; } if (*options == ',') ++options; @@ -6424,6 +6857,8 @@ /* find how indented the line beginning the comment is */ getvcol(curwin, trypos, &col, NULL, NULL); amount = col; + *lead_start = NUL; + *lead_middle = NUL; p = curbuf->b_p_com; while (*p != NUL) @@ -6636,6 +7071,33 @@ if (amount == -1) { int ignore_paren_col = 0; + int is_if_for_while = 0; + + if (ind_if_for_while) + { + /* Look for the outermost opening parenthesis on this line + * and check whether it belongs to an "if", "for" or "while". */ + + pos_T cursor_save = curwin->w_cursor; + pos_T outermost; + char_u *line; + + trypos = &our_paren_pos; + do { + outermost = *trypos; + curwin->w_cursor.lnum = outermost.lnum; + curwin->w_cursor.col = outermost.col; + + trypos = find_match_paren(ind_maxparen, ind_maxcomment); + } while (trypos && trypos->lnum == outermost.lnum); + + curwin->w_cursor = cursor_save; + + line = ml_get(outermost.lnum); + + is_if_for_while = + cin_is_if_for_while_before_offset(line, &outermost.col); + } amount = skip_label(our_paren_pos.lnum, &look, ind_maxcomment); look = skipwhite(look); @@ -6660,7 +7122,7 @@ curwin->w_cursor.lnum = save_lnum; look = ml_get(our_paren_pos.lnum) + look_col; } - if (theline[0] == ')' || ind_unclosed == 0 + if (theline[0] == ')' || (ind_unclosed == 0 && is_if_for_while == 0) || (!ind_unclosed_noignore && *look == '(' && ignore_paren_col == 0)) { @@ -6731,7 +7193,8 @@ { /* Line up with the start of the matching paren line. */ } - else if (ind_unclosed == 0 || (!ind_unclosed_noignore + else if ((ind_unclosed == 0 && is_if_for_while == 0) + || (!ind_unclosed_noignore && *look == '(' && ignore_paren_col == 0)) { if (cur_amount != MAXCOL) @@ -6764,11 +7227,15 @@ { curwin->w_cursor.lnum = our_paren_pos.lnum; curwin->w_cursor.col = col; - if ((trypos = find_match_paren(ind_maxparen, - ind_maxcomment)) != NULL) + if (find_match_paren(ind_maxparen, ind_maxcomment) != NULL) amount += ind_unclosed2; else - amount += ind_unclosed; + { + if (is_if_for_while) + amount += ind_if_for_while; + else + amount += ind_unclosed; + } } /* * For a line starting with ')' use the minimum of the two @@ -6838,7 +7305,7 @@ * ldfd) { * } */ - if ((ind_keep_case_label + if (ind_js || (ind_keep_case_label && cin_iscase(skipwhite(ml_get_curline()), FALSE))) amount = get_indent(); else @@ -6901,11 +7368,24 @@ if (start_brace == BRACE_IN_COL0) /* '{' is in column 0 */ { amount = ind_open_left_imag; + lookfor_cpp_namespace = TRUE; + } + else if (start_brace == BRACE_AT_START && + lookfor_cpp_namespace) /* '{' is at start */ + { + + lookfor_cpp_namespace = TRUE; } else { if (start_brace == BRACE_AT_END) /* '{' is at end of line */ + { amount += ind_open_imag; + + l = skipwhite(ml_get_curline()); + if (cin_is_cpp_namespace(l)) + amount += ind_cpp_namespace; + } else { /* Compensate for adding ind_open_extra later. */ @@ -7014,7 +7494,8 @@ * (it's a variable declaration). */ if (start_brace != BRACE_IN_COL0 - || !cin_isfuncdecl(&l, curwin->w_cursor.lnum)) + || !cin_isfuncdecl(&l, curwin->w_cursor.lnum, + 0, ind_maxparen, ind_maxcomment)) { /* if the line is terminated with another ',' * it is a continued variable initialization. @@ -7076,12 +7557,59 @@ else amount += ind_continuation; } - else if (lookfor != LOOKFOR_TERM - && lookfor != LOOKFOR_CPP_BASECLASS) + else { - amount = scope_amount; - if (theline[0] == '{') - amount += ind_open_extra; + if (lookfor != LOOKFOR_TERM + && lookfor != LOOKFOR_CPP_BASECLASS) + { + amount = scope_amount; + if (theline[0] == '{') + { + amount += ind_open_extra; + added_to_amount = ind_open_extra; + } + } + + if (lookfor_cpp_namespace) + { + /* + * Looking for C++ namespace, need to look further + * back. + */ + if (curwin->w_cursor.lnum == ourscope) + continue; + + if (curwin->w_cursor.lnum == 0 + || curwin->w_cursor.lnum + < ourscope - FIND_NAMESPACE_LIM) + break; + + l = ml_get_curline(); + + /* If we're in a comment now, skip to the start of + * the comment. */ + trypos = find_start_comment(ind_maxcomment); + if (trypos != NULL) + { + curwin->w_cursor.lnum = trypos->lnum + 1; + curwin->w_cursor.col = 0; + continue; + } + + /* Skip preprocessor directives and blank lines. */ + if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum)) + continue; + + /* Finally the actual check for "namespace". */ + if (cin_is_cpp_namespace(l)) + { + amount += ind_cpp_namespace - added_to_amount; + break; + } + + if (cin_nocode(l)) + continue; + } } break; } @@ -7466,17 +7994,25 @@ /* * When searching for a terminated line, don't use the - * one between the "if" and the "else". + * one between the "if" and the matching "else". * Need to use the scope of this "else". XXX * If whilelevel != 0 continue looking for a "do {". */ - if (cin_iselse(l) - && whilelevel == 0 - && ((trypos = find_start_brace(ind_maxcomment)) - == NULL + if (cin_iselse(l) && whilelevel == 0) + { + /* If we're looking at "} else", let's make sure we + * find the opening brace of the enclosing scope, + * not the one from "if () {". */ + if (*l == '}') + curwin->w_cursor.col = + (colnr_T)(l - ml_get_curline()) + 1; + + if ((trypos = find_start_brace(ind_maxcomment)) + == NULL || find_match(LOOKFOR_IF, trypos->lnum, - ind_maxparen, ind_maxcomment) == FAIL)) - break; + ind_maxparen, ind_maxcomment) == FAIL) + break; + } } /* @@ -7757,8 +8293,8 @@ * If we're at the end of a block, skip to the start of * that block. */ - curwin->w_cursor.col = 0; - if (*cin_skipcomment(l) == '}' + l = ml_get_curline(); + if (find_last_paren(l, '{', '}') && (trypos = find_start_brace(ind_maxcomment)) != NULL) /* XXX */ { @@ -7820,7 +8356,9 @@ && vim_strchr(theline, '}') == NULL && !cin_ends_in(theline, (char_u *)":", NULL) && !cin_ends_in(theline, (char_u *)",", NULL) - && cin_isfuncdecl(NULL, cur_curpos.lnum + 1) + && cin_isfuncdecl(NULL, cur_curpos.lnum + 1, + cur_curpos.lnum + 1, + ind_maxparen, ind_maxcomment) && !cin_isterminated(theline, FALSE, TRUE)) { amount = ind_func_type; @@ -7926,7 +8464,8 @@ * If the line looks like a function declaration, and we're * not in a comment, put it the left margin. */ - if (cin_isfuncdecl(NULL, cur_curpos.lnum)) /* XXX */ + if (cin_isfuncdecl(NULL, cur_curpos.lnum, 0, + ind_maxparen, ind_maxcomment)) /* XXX */ break; l = ml_get_curline(); @@ -7947,11 +8486,35 @@ break; /* + * Find a line only has a semicolon that belongs to a previous + * line ending in '}', e.g. before an #endif. Don't increase + * indent then. + */ + if (*(look = skipwhite(l)) == ';' && cin_nocode(look + 1)) + { + pos_T curpos_save = curwin->w_cursor; + + while (curwin->w_cursor.lnum > 1) + { + look = ml_get(--curwin->w_cursor.lnum); + if (!(cin_nocode(look) || cin_ispreproc_cont( + &look, &curwin->w_cursor.lnum))) + break; + } + if (curwin->w_cursor.lnum > 0 + && cin_ends_in(look, (char_u *)"}", NULL)) + break; + + curwin->w_cursor = curpos_save; + } + + /* * If the PREVIOUS line is a function declaration, the current * line (and the ones that follow) needs to be indented as * parameters. */ - if (cin_isfuncdecl(&l, curwin->w_cursor.lnum)) + if (cin_isfuncdecl(&l, curwin->w_cursor.lnum, 0, + ind_maxparen, ind_maxcomment)) { amount = ind_param; break; @@ -8856,11 +9419,15 @@ } /* compile the regexp into a program */ + if (flags & (EW_NOERROR | EW_NOTWILD)) + ++emsg_silent; regmatch.rm_ic = TRUE; /* Always ignore case */ regmatch.regprog = vim_regcomp(pat, RE_MAGIC); + if (flags & (EW_NOERROR | EW_NOTWILD)) + --emsg_silent; vim_free(pat); - if (regmatch.regprog == NULL) + if (regmatch.regprog == NULL && (flags & EW_NOTWILD) == 0) { vim_free(buf); return 0; @@ -8928,7 +9495,10 @@ * all entries found with "matchname". */ if ((p[0] != '.' || starts_with_dot) && (matchname == NULL - || vim_regexec(®match, p, (colnr_T)0))) + || (regmatch.regprog != NULL + && vim_regexec(®match, p, (colnr_T)0)) + || ((flags & EW_NOTWILD) + && fnamencmp(path + (s - buf), p, e - s) == 0))) { #ifdef WIN3264 STRCPY(s, p); @@ -9096,6 +9666,7 @@ /* * Find the first part in the path name that contains a wildcard. + * When EW_ICASE is set every letter is considered to be a wildcard. * Copy it into "buf", including the preceding characters. */ p = buf; @@ -9115,7 +9686,12 @@ s = p + 1; } else if (path_end >= path + wildoff - && vim_strchr((char_u *)"*?[{~$", *path_end) != NULL) + && (vim_strchr((char_u *)"*?[{~$", *path_end) != NULL +#ifndef CASE_INSENSITIVE_FILENAME + || ((flags & EW_ICASE) + && isalpha(PTR2CHAR(path_end))) +#endif + )) e = p; #ifdef FEAT_MBYTE if (has_mbyte) @@ -9132,7 +9708,7 @@ e = p; *e = NUL; - /* now we have one wildcard component between "s" and "e" */ + /* Now we have one wildcard component between "s" and "e". */ /* Remove backslashes between "wildoff" and the start of the wildcard * component. */ for (p = buf + wildoff; p < s; ++p) @@ -9161,12 +9737,19 @@ #ifdef CASE_INSENSITIVE_FILENAME regmatch.rm_ic = TRUE; /* Behave like Terminal.app */ #else - regmatch.rm_ic = FALSE; /* Don't ever ignore case */ + if (flags & EW_ICASE) + regmatch.rm_ic = TRUE; /* 'wildignorecase' set */ + else + regmatch.rm_ic = FALSE; /* Don't ignore case */ #endif + if (flags & (EW_NOERROR | EW_NOTWILD)) + ++emsg_silent; regmatch.regprog = vim_regcomp(pat, RE_MAGIC); + if (flags & (EW_NOERROR | EW_NOTWILD)) + --emsg_silent; vim_free(pat); - if (regmatch.regprog == NULL) + if (regmatch.regprog == NULL && (flags & EW_NOTWILD) == 0) { vim_free(buf); return 0; @@ -9196,7 +9779,10 @@ if (dp == NULL) break; if ((dp->d_name[0] != '.' || starts_with_dot) - && vim_regexec(®match, (char_u *)dp->d_name, (colnr_T)0)) + && ((regmatch.regprog != NULL && vim_regexec(®match, + (char_u *)dp->d_name, (colnr_T)0)) + || ((flags & EW_NOTWILD) + && fnamencmp(path + (s - buf), dp->d_name, e - s) == 0))) { STRCPY(s, dp->d_name); len = STRLEN(buf); @@ -9317,7 +9903,8 @@ continue; /* it's different when it's shorter */ rival = other_paths[j] + other_path_len - candidate_len; - if (fnamecmp(maybe_unique, rival) == 0) + if (fnamecmp(maybe_unique, rival) == 0 + && (rival == other_paths[j] || vim_ispathsep(*(rival - 1)))) return FALSE; /* match */ } @@ -9642,7 +10229,7 @@ if (paths == NULL) return 0; - files = globpath(paths, pattern, 0); + files = globpath(paths, pattern, (flags & EW_ICASE) ? WILD_ICASE : 0); vim_free(paths); if (files == NULL) return 0; diff -Naur vim73.orig/src/misc2.c vim73/src/misc2.c --- vim73.orig/src/misc2.c 2010-08-13 09:14:35.000000000 +0000 +++ vim73/src/misc2.c 2012-07-20 20:31:17.620978002 +0000 @@ -200,7 +200,6 @@ } #endif - idx = -1; ptr = line; while (col <= wcol && *ptr != NUL) { @@ -334,7 +333,7 @@ #ifdef FEAT_MBYTE /* prevent from moving onto a trail byte */ if (has_mbyte) - mb_adjustpos(pos); + mb_adjustpos(curbuf, pos); #endif if (col < wcol) @@ -545,16 +544,26 @@ void check_cursor_col() { + check_cursor_col_win(curwin); +} + +/* + * Make sure win->w_cursor.col is valid. + */ + void +check_cursor_col_win(win) + win_T *win; +{ colnr_T len; #ifdef FEAT_VIRTUALEDIT - colnr_T oldcol = curwin->w_cursor.col; - colnr_T oldcoladd = curwin->w_cursor.col + curwin->w_cursor.coladd; + colnr_T oldcol = win->w_cursor.col; + colnr_T oldcoladd = win->w_cursor.col + win->w_cursor.coladd; #endif - len = (colnr_T)STRLEN(ml_get_curline()); + len = (colnr_T)STRLEN(ml_get_buf(win->w_buffer, win->w_cursor.lnum, FALSE)); if (len == 0) - curwin->w_cursor.col = 0; - else if (curwin->w_cursor.col >= len) + win->w_cursor.col = 0; + else if (win->w_cursor.col >= len) { /* Allow cursor past end-of-line when: * - in Insert mode or restarting Insert mode @@ -568,33 +577,33 @@ || (ve_flags & VE_ONEMORE) #endif || virtual_active()) - curwin->w_cursor.col = len; + win->w_cursor.col = len; else { - curwin->w_cursor.col = len - 1; + win->w_cursor.col = len - 1; #ifdef FEAT_MBYTE - /* prevent cursor from moving on the trail byte */ + /* Move the cursor to the head byte. */ if (has_mbyte) - mb_adjust_cursor(); + mb_adjustpos(win->w_buffer, &win->w_cursor); #endif } } - else if (curwin->w_cursor.col < 0) - curwin->w_cursor.col = 0; + else if (win->w_cursor.col < 0) + win->w_cursor.col = 0; #ifdef FEAT_VIRTUALEDIT /* If virtual editing is on, we can leave the cursor on the old position, * only we must set it to virtual. But don't do it when at the end of the * line. */ if (oldcol == MAXCOL) - curwin->w_cursor.coladd = 0; + win->w_cursor.coladd = 0; else if (ve_flags == VE_ALL) { - if (oldcoladd > curwin->w_cursor.col) - curwin->w_cursor.coladd = oldcoladd - curwin->w_cursor.col; + if (oldcoladd > win->w_cursor.col) + win->w_cursor.coladd = oldcoladd - win->w_cursor.col; else /* avoid weird number when there is a miscalculation or overflow */ - curwin->w_cursor.coladd = 0; + win->w_cursor.coladd = 0; } #endif } @@ -806,6 +815,7 @@ #else # define KEEP_ROOM (2 * 8192L) #endif +#define KEEP_ROOM_KB (KEEP_ROOM / 1024L) /* * Note: if unsigned is 16 bits we can only allocate up to 64K with alloc(). @@ -931,7 +941,7 @@ allocated = 0; # endif /* 3. check for available memory: call mch_avail_mem() */ - if (mch_avail_mem(TRUE) < KEEP_ROOM && !releasing) + if (mch_avail_mem(TRUE) < KEEP_ROOM_KB && !releasing) { free((char *)p); /* System is low... no go! */ p = NULL; @@ -1003,8 +1013,12 @@ { /* Don't hide this message */ emsg_silent = 0; - EMSGN(_("E342: Out of memory! (allocating %lu bytes)"), size); + + /* Must come first to avoid coming back here when printing the error + * message fails, e.g. when setting v:errmsg. */ did_outofmem_msg = TRUE; + + EMSGN(_("E342: Out of memory! (allocating %lu bytes)"), size); } } @@ -1160,7 +1174,7 @@ for (buf = firstbuf; buf != NULL; ) { nextbuf = buf->b_next; - close_buffer(NULL, buf, DOBUF_WIPE); + close_buffer(NULL, buf, DOBUF_WIPE, FALSE); if (buf_valid(buf)) buf = nextbuf; /* didn't work, try next one */ else @@ -1223,7 +1237,7 @@ #endif /* - * copy a string into newly allocated memory + * Copy "string" into newly allocated memory. */ char_u * vim_strsave(string) @@ -1239,6 +1253,12 @@ return p; } +/* + * Copy up to "len" bytes of "string" into newly allocated memory and + * terminate with a NUL. + * The allocated memory always has size "len + 1", also when "string" is + * shorter. + */ char_u * vim_strnsave(string, len) char_u *string; @@ -1540,7 +1560,7 @@ if (enc_utf8) { int c, uc; - int nl; + int newl; char_u *s; c = utf_ptr2char(p); @@ -1549,21 +1569,21 @@ /* Reallocate string when byte count changes. This is rare, * thus it's OK to do another malloc()/free(). */ l = utf_ptr2len(p); - nl = utf_char2len(uc); - if (nl != l) + newl = utf_char2len(uc); + if (newl != l) { - s = alloc((unsigned)STRLEN(res) + 1 + nl - l); + s = alloc((unsigned)STRLEN(res) + 1 + newl - l); if (s == NULL) break; mch_memmove(s, res, p - res); - STRCPY(s + (p - res) + nl, p + l); + STRCPY(s + (p - res) + newl, p + l); p = s + (p - res); vim_free(res); res = s; } utf_char2bytes(uc, p); - p += nl; + p += newl; } else if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) p += l; /* skip multi-byte character */ @@ -1642,6 +1662,28 @@ } /* + * Like strcat(), but make sure the result fits in "tosize" bytes and is + * always NUL terminated. + */ + void +vim_strcat(to, from, tosize) + char_u *to; + char_u *from; + size_t tosize; +{ + size_t tolen = STRLEN(to); + size_t fromlen = STRLEN(from); + + if (tolen + fromlen + 1 > tosize) + { + mch_memmove(to + tolen, from, tosize - tolen - 1); + to[tosize - 1] = NUL; + } + else + STRCPY(to + tolen, from); +} + +/* * Isolate one part of a string option where parts are separated with * "sep_chars". * The part is copied into "buf[maxlen]". @@ -2023,24 +2065,22 @@ garray_T *gap; int n; { - size_t len; + size_t old_len; + size_t new_len; char_u *pp; if (gap->ga_maxlen - gap->ga_len < n) { if (n < gap->ga_growsize) n = gap->ga_growsize; - len = gap->ga_itemsize * (gap->ga_len + n); - pp = alloc_clear((unsigned)len); + new_len = gap->ga_itemsize * (gap->ga_len + n); + pp = (gap->ga_data == NULL) + ? alloc((unsigned)new_len) : vim_realloc(gap->ga_data, new_len); if (pp == NULL) return FAIL; + old_len = gap->ga_itemsize * gap->ga_maxlen; + vim_memset(pp + old_len, 0, new_len - old_len); gap->ga_maxlen = gap->ga_len + n; - if (gap->ga_data != NULL) - { - mch_memmove(pp, gap->ga_data, - (size_t)(gap->ga_itemsize * gap->ga_len)); - vim_free(gap->ga_data); - } gap->ga_data = pp; } return OK; @@ -2109,6 +2149,25 @@ } } +#if (defined(UNIX) && !defined(USE_SYSTEM)) || defined(WIN3264) +/* + * Append the text in "gap" below the cursor line and clear "gap". + */ + void +append_ga_line(gap) + garray_T *gap; +{ + /* Remove trailing CR. */ + if (gap->ga_len > 0 + && !curbuf->b_p_bin + && ((char_u *)gap->ga_data)[gap->ga_len - 1] == CAR) + --gap->ga_len; + ga_append(gap, NUL); + ml_append(curwin->w_cursor.lnum++, gap->ga_data, 0, FALSE); + gap->ga_len = 0; +} +#endif + /************************************************************************ * functions that use lookup tables for various things, generally to do with * special key codes. @@ -2356,10 +2415,21 @@ {'<', (char_u *)"lt"}, {K_MOUSE, (char_u *)"Mouse"}, +#ifdef FEAT_MOUSE_NET {K_NETTERM_MOUSE, (char_u *)"NetMouse"}, +#endif +#ifdef FEAT_MOUSE_DEC {K_DEC_MOUSE, (char_u *)"DecMouse"}, +#endif +#ifdef FEAT_MOUSE_JSB {K_JSBTERM_MOUSE, (char_u *)"JsbMouse"}, +#endif +#ifdef FEAT_MOUSE_PTERM {K_PTERM_MOUSE, (char_u *)"PtermMouse"}, +#endif +#ifdef FEAT_MOUSE_URXVT + {K_URXVT_MOUSE, (char_u *)"UrxvtMouse"}, +#endif {K_LEFTMOUSE, (char_u *)"LeftMouse"}, {K_LEFTMOUSE_NM, (char_u *)"LeftMouseNM"}, {K_LEFTDRAG, (char_u *)"LeftDrag"}, @@ -2698,6 +2768,7 @@ int bit; int key; unsigned long n; + int l; src = *srcp; if (src[0] != '<') @@ -2710,26 +2781,32 @@ if (*bp == '-') { last_dash = bp; - if (bp[1] != NUL && bp[2] == '>') - ++bp; /* anything accepted, like */ + if (bp[1] != NUL) + { +#ifdef FEAT_MBYTE + if (has_mbyte) + l = mb_ptr2len(bp + 1); + else +#endif + l = 1; + if (bp[l + 1] == '>') + bp += l; /* anything accepted, like */ + } } if (bp[0] == 't' && bp[1] == '_' && bp[2] && bp[3]) bp += 3; /* skip t_xx, xx may be '-' or '>' */ + else if (STRNICMP(bp, "char-", 5) == 0) + { + vim_str2nr(bp + 5, NULL, &l, TRUE, TRUE, NULL, NULL); + bp += l + 5; + break; + } } if (*bp == '>') /* found matching '>' */ { end_of_name = bp + 1; - if (STRNICMP(src + 1, "char-", 5) == 0 && VIM_ISDIGIT(src[6])) - { - /* or or */ - vim_str2nr(src + 6, NULL, NULL, TRUE, TRUE, NULL, &n); - *modp = 0; - *srcp = end_of_name; - return (int)n; - } - /* Which modifiers are given? */ modifiers = 0x0; for (bp = src + 1; bp < last_dash; bp++) @@ -2748,16 +2825,32 @@ */ if (bp >= last_dash) { - /* - * Modifier with single letter, or special key name. - */ - if (modifiers != 0 && last_dash[2] == '>') - key = last_dash[1]; + if (STRNICMP(last_dash + 1, "char-", 5) == 0 + && VIM_ISDIGIT(last_dash[6])) + { + /* or or */ + vim_str2nr(last_dash + 6, NULL, NULL, TRUE, TRUE, NULL, &n); + key = (int)n; + } else { - key = get_special_key_code(last_dash + 1); - if (!keep_x_key) - key = handle_x_keys(key); + /* + * Modifier with single letter, or special key name. + */ +#ifdef FEAT_MBYTE + if (has_mbyte) + l = mb_ptr2len(last_dash + 1); + else +#endif + l = 1; + if (modifiers != 0 && last_dash[l + 1] == '>') + key = PTR2CHAR(last_dash + 1); + else + { + key = get_special_key_code(last_dash + 1); + if (!keep_x_key) + key = handle_x_keys(key); + } } /* @@ -3131,17 +3224,31 @@ retval = mch_call_shell(cmd, opt); else { - ncmd = alloc((unsigned)(STRLEN(cmd) + STRLEN(p_sxq) * 2 + 1)); + char_u *ecmd = cmd; + + if (*p_sxe != NUL && STRCMP(p_sxq, "(") == 0) + { + ecmd = vim_strsave_escaped_ext(cmd, p_sxe, '^', FALSE); + if (ecmd == NULL) + ecmd = cmd; + } + ncmd = alloc((unsigned)(STRLEN(ecmd) + STRLEN(p_sxq) * 2 + 1)); if (ncmd != NULL) { STRCPY(ncmd, p_sxq); - STRCAT(ncmd, cmd); - STRCAT(ncmd, p_sxq); + STRCAT(ncmd, ecmd); + /* When 'shellxquote' is ( append ). + * When 'shellxquote' is "( append )". */ + STRCAT(ncmd, STRCMP(p_sxq, "(") == 0 ? (char_u *)")" + : STRCMP(p_sxq, "\"(") == 0 ? (char_u *)")\"" + : p_sxq); retval = mch_call_shell(ncmd, opt); vim_free(ncmd); } else retval = -1; + if (ecmd != cmd) + vim_free(ecmd); } #ifdef FEAT_GUI --hold_gui_events; @@ -3191,7 +3298,7 @@ #if defined(FEAT_MBYTE) || defined(PROTO) /* * Return TRUE if "p" points to just after a path separator. - * Take care of multi-byte characters. + * Takes care of multi-byte characters. * "b" must point to the start of the file name */ int @@ -3199,7 +3306,7 @@ char_u *b; char_u *p; { - return vim_ispathsep(p[-1]) + return p > b && vim_ispathsep(p[-1]) && (!has_mbyte || (*mb_head_off)(b, p - 1) == 0); } #endif @@ -4210,6 +4317,8 @@ static int ff_path_in_stoplist __ARGS((char_u *, int, char_u **)); #endif +static char_u e_pathtoolong[] = N_("E854: path too long for completion"); + #if 0 /* * if someone likes findfirst/findnext, here are the functions @@ -4506,6 +4615,11 @@ len = 0; while (*wc_part != NUL) { + if (len + 5 >= MAXPATHL) + { + EMSG(_(e_pathtoolong)); + break; + } if (STRNCMP(wc_part, "**", 2) == 0) { ff_expand_buffer[len++] = *wc_part++; @@ -4551,6 +4665,12 @@ } /* create an absolute path */ + if (STRLEN(search_ctx->ffsc_start_dir) + + STRLEN(search_ctx->ffsc_fix_path) + 3 >= MAXPATHL) + { + EMSG(_(e_pathtoolong)); + goto error_return; + } STRCPY(ff_expand_buffer, search_ctx->ffsc_start_dir); add_pathsep(ff_expand_buffer); STRCAT(ff_expand_buffer, search_ctx->ffsc_fix_path); @@ -4597,9 +4717,8 @@ { if (r_ptr[0] == '\\' && r_ptr[1] == ';') { - /* overwrite the escape char, - * use STRLEN(r_ptr) to move the trailing '\0' - */ + /* Overwrite the escape char, + * use STRLEN(r_ptr) to move the trailing '\0'. */ STRMOVE(r_ptr, r_ptr + 1); r_ptr++; } @@ -4858,10 +4977,13 @@ stackp->ffs_filearray_size = 0; } else + /* Add EW_NOTWILD because the expanded path may contain + * wildcard characters that are to be taken literally. + * This is a bit of a hack. */ expand_wildcards((dirptrs[1] == NULL) ? 1 : 2, dirptrs, &stackp->ffs_filearray_size, &stackp->ffs_filearray, - EW_DIR|EW_ADDSLASH|EW_SILENT); + EW_DIR|EW_ADDSLASH|EW_SILENT|EW_NOTWILD); stackp->ffs_filearray_cur = 0; stackp->ffs_stage = 0; @@ -6443,3 +6565,23 @@ #endif #endif + +#if (defined(FEAT_MBYTE) && defined(FEAT_QUICKFIX)) \ + || defined(FEAT_SPELL) || defined(PROTO) +/* + * Return TRUE if string "s" contains a non-ASCII character (128 or higher). + * When "s" is NULL FALSE is returned. + */ + int +has_non_ascii(s) + char_u *s; +{ + char_u *p; + + if (s != NULL) + for (p = s; *p != NUL; ++p) + if (*p >= 128) + return TRUE; + return FALSE; +} +#endif diff -Naur vim73.orig/src/move.c vim73/src/move.c --- vim73.orig/src/move.c 2010-08-08 13:12:31.000000000 +0000 +++ vim73/src/move.c 2012-07-20 20:31:15.540976512 +0000 @@ -362,7 +362,7 @@ #endif ) { - dollar_vcol = 0; + dollar_vcol = -1; if (curwin->w_skipcol != 0) { curwin->w_skipcol = 0; @@ -926,8 +926,8 @@ * Also updates curwin->w_leftcol. */ void -curs_columns(scroll) - int scroll; /* when TRUE, may scroll horizontally */ +curs_columns(may_scroll) + int may_scroll; /* when TRUE, may scroll horizontally */ { int diff; int extra; /* offset for first screen line */ @@ -966,7 +966,7 @@ /* remove '$' from change command when cursor moves onto it */ if (startcol > dollar_vcol) - dollar_vcol = 0; + dollar_vcol = -1; extra = curwin_col_off(); curwin->w_wcol = curwin->w_virtcol + extra; @@ -1014,7 +1014,7 @@ /* No line wrapping: compute curwin->w_leftcol if scrolling is on and line * is not folded. * If scrolling is off, curwin->w_leftcol is assumed to be 0 */ - else if (scroll + else if (may_scroll #ifdef FEAT_FOLDING && !curwin->w_cline_folded #endif @@ -2843,9 +2843,15 @@ do_check_cursorbind() { linenr_T line = curwin->w_cursor.lnum; - colnr_T col = curwin->w_cursor.col; + colnr_T col = curwin->w_cursor.col; +# ifdef FEAT_VIRTUALEDIT + colnr_T coladd = curwin->w_cursor.coladd; +# endif + colnr_T curswant = curwin->w_curswant; + int set_curswant = curwin->w_set_curswant; win_T *old_curwin = curwin; buf_T *old_curbuf = curbuf; + int restart_edit_save; # ifdef FEAT_VISUAL int old_VIsual_select = VIsual_select; int old_VIsual_active = VIsual_active; @@ -2874,17 +2880,28 @@ # endif curwin->w_cursor.lnum = line; curwin->w_cursor.col = col; +# ifdef FEAT_VIRTUALEDIT + curwin->w_cursor.coladd = coladd; +# endif + curwin->w_curswant = curswant; + curwin->w_set_curswant = set_curswant; - /* Make sure the cursor is in a valid position. */ + /* Make sure the cursor is in a valid position. Temporarily set + * "restart_edit" to allow the cursor to be beyond the EOL. */ + restart_edit_save = restart_edit; + restart_edit = TRUE; check_cursor(); + restart_edit = restart_edit_save; # ifdef FEAT_MBYTE /* Correct cursor for multi-byte character. */ if (has_mbyte) mb_adjust_cursor(); # endif - redraw_later(VALID); - update_topline(); + + /* Only scroll when 'scrollbind' hasn't done this. */ + if (!curwin->w_p_scb) + update_topline(); # ifdef FEAT_WINDOWS curwin->w_redr_status = TRUE; # endif diff -Naur vim73.orig/src/msvc2010.bat vim73/src/msvc2010.bat --- vim73.orig/src/msvc2010.bat 1970-01-01 00:00:00.000000000 +0000 +++ vim73/src/msvc2010.bat 2012-07-20 20:31:11.317640143 +0000 @@ -0,0 +1,7 @@ +@echo off +rem To be used on MS-Windows for Visual C++ 2010 Express Edition +rem aka Microsoft Visual Studio 10.0. +rem See INSTALLpc.txt for information. +@echo on + +call "%VS100COMNTOOLS%%vsvars32.bat" diff -Naur vim73.orig/src/netbeans.c vim73/src/netbeans.c --- vim73.orig/src/netbeans.c 2010-08-09 20:48:09.000000000 +0000 +++ vim73/src/netbeans.c 2012-07-20 20:31:15.804310035 +0000 @@ -14,12 +14,15 @@ * which are *between* characters, whereas vim uses line number * and column number which are *on* characters. * See ":help netbeans-protocol" for explanation. + * + * The Netbeans messages are received and queued in the gui event loop, or in + * the select loop when Vim runs in a terminal. These messages are processed + * by netbeans_parse_messages() which is invoked in the idle loop when Vim is + * waiting for user input. The function netbeans_parse_messages() is also + * called from the ":sleep" command, to allow the execution of test cases that + * may not invoke the idle loop. */ -#if defined(MSDOS) || defined(WIN16) || defined(WIN32) || defined(_WIN64) -# include "vimio.h" /* for mch_open(), must be before vim.h */ -#endif - #include "vim.h" #if defined(FEAT_NETBEANS_INTG) || defined(PROTO) @@ -87,7 +90,7 @@ static void nb_init_graphics __ARGS((void)); static void coloncmd __ARGS((char *cmd, ...)); static void nb_set_curbuf __ARGS((buf_T *buf)); -#ifdef FEAT_GUI_MOTIF +#ifdef FEAT_GUI_X11 static void messageFromNetbeans __ARGS((XtPointer, int *, XtInputId *)); #endif #ifdef FEAT_GUI_GTK @@ -112,7 +115,7 @@ static NBSOCK nbsock = -1; /* socket fd for Netbeans connection */ #define NETBEANS_OPEN (nbsock != -1) -#ifdef FEAT_GUI_MOTIF +#ifdef FEAT_GUI_X11 static XtInputId inputHandler = (XtInputId)NULL; /* Cookie for input */ #endif #ifdef FEAT_GUI_GTK @@ -135,15 +138,13 @@ static int needupdate = 0; static int inAtomic = 0; +/* + * Close the socket and remove the input handlers. + */ static void -netbeans_close(void) +nb_close_socket(void) { - if (!NETBEANS_OPEN) - return; - - netbeans_send_disconnect(); - -#ifdef FEAT_GUI_MOTIF +#ifdef FEAT_GUI_X11 if (inputHandler != (XtInputId)NULL) { XtRemoveInput(inputHandler); @@ -167,13 +168,27 @@ # endif #endif + sock_close(nbsock); + nbsock = -1; +} + +/* + * Close the connection and cleanup. + * May be called when nb_close_socket() was called earlier. + */ + static void +netbeans_close(void) +{ + if (NETBEANS_OPEN) + { + netbeans_send_disconnect(); + nb_close_socket(); + } + #ifdef FEAT_BEVAL bevalServers &= ~BEVAL_NETBEANS; #endif - sock_close(nbsock); - nbsock = -1; - needupdate = 0; inAtomic = 0; nb_free(); @@ -183,6 +198,7 @@ changed_window_setting(); update_screen(CLEAR); setcursor(); + cursor_on(); out_flush(); #ifdef FEAT_GUI if (gui.in_use) @@ -311,14 +327,9 @@ server.sin_port = htons(port); if ((host = gethostbyname(hostname)) == NULL) { - if (mch_access(hostname, R_OK) >= 0) - { - /* DEBUG: input file */ - sd = mch_open(hostname, O_RDONLY, 0); - goto theend; - } nbdebug(("error in gethostbyname() in netbeans_connect()\n")); PERROR("gethostbyname() in netbeans_connect()"); + sock_close(sd); goto theend; } memcpy((char *)&server.sin_addr, host->h_addr, host->h_length); @@ -368,15 +379,12 @@ || (errno == EINTR))) { nbdebug(("retrying...\n")); - sleep(5); - if (!doabort) + mch_delay(3000L, TRUE); + ui_breakcheck(); + if (got_int) { - ui_breakcheck(); - if (got_int) - { - errno = EINTR; - break; - } + errno = EINTR; + break; } if (connect(sd, (struct sockaddr *)&server, sizeof(server)) == 0) @@ -391,6 +399,7 @@ /* Get here when the server can't be found. */ nbdebug(("Cannot connect to Netbeans #2\n")); PERROR(_("Cannot connect to Netbeans #2")); + sock_close(sd); if (doabort) getout(1); goto theend; @@ -401,6 +410,7 @@ { nbdebug(("Cannot connect to Netbeans\n")); PERROR(_("Cannot connect to Netbeans")); + sock_close(sd); if (doabort) getout(1); goto theend; @@ -433,7 +443,7 @@ FILE *fp; char_u buf[BUFSIZ]; char_u *lp; - char_u *nl; + char_u *nlp; #ifdef UNIX struct stat st; @@ -462,8 +472,8 @@ /* Read the file. There should be one of each parameter */ while ((lp = (char_u *)fgets((char *)buf, BUFSIZ, fp)) != NULL) { - if ((nl = vim_strchr(lp, '\n')) != NULL) - *nl = 0; /* strip off the trailing newline */ + if ((nlp = vim_strchr(lp, '\n')) != NULL) + *nlp = 0; /* strip off the trailing newline */ if (STRNCMP(lp, "host=", 5) == 0) { @@ -631,9 +641,7 @@ { char_u *p; queue_T *node; - - if (!NETBEANS_OPEN) - return; + int own_node; while (head.next != NULL && head.next != &head) { @@ -672,20 +680,25 @@ *p++ = NUL; if (*p == NUL) { + own_node = TRUE; head.next = node->next; node->next->prev = node->prev; } + else + own_node = FALSE; /* now, parse and execute the commands */ nb_parse_cmd(node->buffer); - if (*p == NUL) + if (own_node) { /* buffer finished, dispose of the node and buffer */ vim_free(node->buffer); vim_free(node); } - else + /* Check that "head" wasn't changed under our fingers, e.g. when a + * DETACH command was handled. */ + else if (head.next == node) { /* more follows, move to the start */ STRMOVE(node->buffer, p); @@ -700,7 +713,7 @@ /* * Read a command from netbeans. */ -#ifdef FEAT_GUI_MOTIF +#ifdef FEAT_GUI_X11 static void messageFromNetbeans(XtPointer clientData UNUSED, int *unused1 UNUSED, @@ -720,15 +733,14 @@ } #endif +#define DETACH_MSG "DETACH\n" + void netbeans_read() { static char_u *buf = NULL; int len = 0; int readlen = 0; -#if defined(NB_HAS_GUI) && !defined(FEAT_GUI_GTK) && !defined(FEAT_GUI_W32) - static int level = 0; -#endif #ifdef HAVE_SELECT struct timeval tval; fd_set rfds; @@ -744,13 +756,6 @@ return; } -#if defined(NB_HAS_GUI) && !defined(FEAT_GUI_GTK) && !defined(FEAT_GUI_W32) - /* recursion guard; this will be called from the X event loop at unknown - * moments */ - if (NB_HAS_GUI) - ++level; -#endif - /* Allocate a buffer to read into. */ if (buf == NULL) { @@ -790,34 +795,32 @@ break; /* did read everything that's available */ } + /* Reading a socket disconnection (readlen == 0), or a socket error. */ if (readlen <= 0) { - /* read error or didn't read anything */ - netbeans_close(); - nbdebug(("messageFromNetbeans: Error in read() from socket\n")); + /* Queue a "DETACH" netbeans message in the command queue in order to + * terminate the netbeans session later. Do not end the session here + * directly as we may be running in the context of a call to + * netbeans_parse_messages(): + * netbeans_parse_messages + * -> autocmd triggered while processing the netbeans cmd + * -> ui_breakcheck + * -> gui event loop or select loop + * -> netbeans_read() + */ + save((char_u *)DETACH_MSG, (int)strlen(DETACH_MSG)); + nb_close_socket(); + if (len < 0) { nbdebug(("read from Netbeans socket\n")); PERROR(_("read from Netbeans socket")); } - return; /* don't try to parse it */ } -#if defined(NB_HAS_GUI) && !defined(FEAT_GUI_W32) - /* Let the main loop handle messages. */ - if (NB_HAS_GUI) - { -# ifdef FEAT_GUI_GTK - if (gtk_main_level() > 0) - gtk_main_quit(); -# else - /* Parse the messages now, but avoid recursion. */ - if (level == 1) - netbeans_parse_messages(); - - --level; -# endif - } +#if defined(NB_HAS_GUI) && defined(FEAT_GUI_GTK) + if (NB_HAS_GUI && gtk_main_level() > 0) + gtk_main_quit(); #endif } @@ -955,7 +958,6 @@ keyQ_T *key_node = keyHead.next; queue_T *cmd_node = head.next; nbbuf_T buf; - buf_T *bufp; int i; /* free the netbeans buffer list */ @@ -964,7 +966,7 @@ buf = buf_list[i]; vim_free(buf.displayname); vim_free(buf.signmap); - if ((bufp=buf.bufp) != NULL) + if (buf.bufp != NULL) { buf.bufp->b_netbeans_file = FALSE; buf.bufp->b_was_netbeans_file = FALSE; @@ -1186,6 +1188,10 @@ nbdebug(("REP %d: \n", cmdno)); + /* Avoid printing an annoying error message. */ + if (!NETBEANS_OPEN) + return; + sprintf(reply, "%d\n", cmdno); nb_send(reply, "nb_reply_nil"); } @@ -1389,7 +1395,7 @@ int cmdno, char_u *args) /* points to space before arguments or NUL */ { - int doupdate = 0; + int do_update = 0; long off = 0; nbbuf_T *buf = nb_get_buf(bufno); static int skip = 0; @@ -1594,7 +1600,7 @@ last.lnum, last.col)); del_from_lnum = first.lnum; del_to_lnum = last.lnum; - doupdate = 1; + do_update = 1; /* Get the position of the first byte after the deleted * section. "next" is NULL when deleting to the end of the @@ -1734,7 +1740,7 @@ int added = 0; int oldFire = netbeansFireChanges; int old_b_changed; - char_u *nl; + char_u *nlp; linenr_T lnum; linenr_T lnum_start; pos_T *pos; @@ -1771,11 +1777,11 @@ lnum = lnum_start; /* Loop over the "\n" separated lines of the argument. */ - doupdate = 1; + do_update = 1; while (*args != NUL) { - nl = vim_strchr(args, '\n'); - if (nl == NULL) + nlp = vim_strchr(args, '\n'); + if (nlp == NULL) { /* Incomplete line, probably truncated. Next "insert" * command should append to this one. */ @@ -1783,13 +1789,13 @@ } else { - len = nl - args; + len = nlp - args; /* * We need to detect EOL style, because the commands * use a character offset. */ - if (nl > args && nl[-1] == '\r') + if (nlp > args && nlp[-1] == '\r') { ff_detected = EOL_DOS; --len; @@ -1806,13 +1812,15 @@ char_u *oldline = ml_get(lnum); char_u *newline; - /* Insert halfway a line. For simplicity we assume we - * need to append to the line. */ - newline = alloc_check((unsigned)(STRLEN(oldline) + len + 1)); + /* Insert halfway a line. */ + newline = alloc_check( + (unsigned)(STRLEN(oldline) + len + 1)); if (newline != NULL) { - STRCPY(newline, oldline); + mch_memmove(newline, oldline, (size_t)pos->col); + newline[pos->col] = NUL; STRCAT(newline, args); + STRCAT(newline, oldline + pos->col); ml_replace(lnum, newline, FALSE); } } @@ -1820,14 +1828,15 @@ { /* Append a new line. Not that we always do this, * also when the text doesn't end in a "\n". */ - ml_append((linenr_T)(lnum - 1), args, (colnr_T)(len + 1), FALSE); + ml_append((linenr_T)(lnum - 1), args, + (colnr_T)(len + 1), FALSE); ++added; } - if (nl == NULL) + if (nlp == NULL) break; ++lnum; - args = nl + 1; + args = nlp + 1; } /* Adjust the marks below the inserted lines. */ @@ -1986,7 +1995,7 @@ EMSG("E640: invalid buffer identifier in initDone"); return FAIL; } - doupdate = 1; + do_update = 1; buf->initDone = TRUE; nb_set_curbuf(buf->bufp); #if defined(FEAT_AUTOCMD) @@ -2075,7 +2084,7 @@ ECMD_HIDE + ECMD_OLDBUF, curwin); buf->bufp = curbuf; buf->initDone = TRUE; - doupdate = 1; + do_update = 1; #if defined(FEAT_TITLE) maketitle(); #endif @@ -2103,7 +2112,7 @@ exarg.forceit = FALSE; dosetvisible = TRUE; goto_buffer(&exarg, DOBUF_FIRST, FORWARD, buf->bufp->b_fnum); - doupdate = 1; + do_update = 1; dosetvisible = FALSE; #ifdef FEAT_GUI @@ -2250,6 +2259,7 @@ update_topline(); /* scroll to show the line */ update_screen(VALID); setcursor(); + cursor_on(); out_flush(); #ifdef FEAT_GUI if (gui.in_use) @@ -2302,7 +2312,7 @@ buf->bufp->b_fnum, TRUE); buf->bufp = NULL; buf->initDone = FALSE; - doupdate = 1; + do_update = 1; /* =====================================================================*/ } else if (streq((char *)cmd, "setStyle")) /* obsolete... */ @@ -2393,7 +2403,7 @@ return FAIL; } - doupdate = 1; + do_update = 1; cp = (char *)args; serNum = strtol(cp, &cp, 10); @@ -2441,7 +2451,7 @@ nbdebug((" invalid buffer identifier in removeAnno\n")); return FAIL; } - doupdate = 1; + do_update = 1; cp = (char *)args; serNum = strtol(cp, &cp, 10); args = (char_u *)cp; @@ -2486,7 +2496,7 @@ len = strtol(cp, NULL, 10); args = (char_u *)cp; pos = off2pos(buf->bufp, off); - doupdate = 1; + do_update = 1; if (!pos) nbdebug((" no such start pos in %s, %ld\n", cmd, off)); else @@ -2548,7 +2558,7 @@ inAtomic = 0; if (needupdate) { - doupdate = 1; + do_update = 1; needupdate = 0; } /* =====================================================================*/ @@ -2629,21 +2639,22 @@ * Unrecognized command is ignored. */ } - if (inAtomic && doupdate) + if (inAtomic && do_update) { needupdate = 1; - doupdate = 0; + do_update = 0; } /* * Is this needed? I moved the netbeans_Xt_connect() later during startup * and it may no longer be necessary. If its not needed then needupdate - * and doupdate can also be removed. + * and do_update can also be removed. */ - if (buf != NULL && buf->initDone && doupdate) + if (buf != NULL && buf->initDone && do_update) { update_screen(NOT_VALID); setcursor(); + cursor_on(); out_flush(); #ifdef FEAT_GUI if (gui.in_use) @@ -2773,6 +2784,16 @@ ex_nbstart(eap) exarg_T *eap; { +#ifdef FEAT_GUI +# if !defined(FEAT_GUI_X11) && !defined(FEAT_GUI_GTK) \ + && !defined(FEAT_GUI_W32) + if (gui.in_use) + { + EMSG(_("E838: netbeans is not supported with this GUI")); + return; + } +# endif +#endif netbeans_open((char *)eap->arg, FALSE); } @@ -2880,7 +2901,7 @@ char_u *text; linenr_T lnum; int col; - char buf[MAXPATHL * 2 + 25]; + char *buf; char_u *p; /* Don't do anything when 'ballooneval' is off, messages scrolled the @@ -2894,15 +2915,20 @@ * length. */ if (text != NULL && text[0] != NUL && STRLEN(text) < MAXPATHL) { - p = nb_quote(text); - if (p != NULL) + buf = (char *)alloc(MAXPATHL * 2 + 25); + if (buf != NULL) { - vim_snprintf(buf, sizeof(buf), - "0:balloonText=%d \"%s\"\n", r_cmdno, p); - vim_free(p); + p = nb_quote(text); + if (p != NULL) + { + vim_snprintf(buf, MAXPATHL * 2 + 25, + "0:balloonText=%d \"%s\"\n", r_cmdno, p); + vim_free(p); + } + nbdebug(("EVT: %s", buf)); + nb_send(buf, "netbeans_beval_cb"); + vim_free(buf); } - nbdebug(("EVT: %s", buf)); - nb_send(buf, "netbeans_beval_cb"); } vim_free(text); } @@ -2937,7 +2963,7 @@ if (!NB_HAS_GUI || !NETBEANS_OPEN) return; -# ifdef FEAT_GUI_MOTIF +# ifdef FEAT_GUI_X11 /* tell notifier we are interested in being called * when there is input on the editor connection socket */ @@ -3000,6 +3026,7 @@ changed_window_setting(); update_screen(CLEAR); setcursor(); + cursor_on(); out_flush(); #ifdef FEAT_GUI if (gui.in_use) @@ -3027,7 +3054,7 @@ } } -#if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_W32) || defined(PROTO) +#if defined(FEAT_GUI_X11) || defined(FEAT_GUI_W32) || defined(PROTO) /* * Tell netbeans that the window was moved or resized. */ @@ -3458,7 +3485,7 @@ return FALSE; } -#if defined(FEAT_GUI_MOTIF) || defined(PROTO) +#if defined(FEAT_GUI_X11) || defined(PROTO) /* * We have multiple signs to draw at the same location. Draw the * multi-sign indicator instead. This is the Motif version. @@ -3487,7 +3514,7 @@ XDrawPoint(gui.dpy, gui.wid, gui.text_gc, x+3, y++); XDrawPoint(gui.dpy, gui.wid, gui.text_gc, x+2, y); } -#endif /* FEAT_GUI_MOTIF */ +#endif /* FEAT_GUI_X11 */ #if defined(FEAT_GUI_GTK) && !defined(PROTO) /* @@ -3902,14 +3929,12 @@ } else { - char_u ebuf[BUFSIZ]; + char_u msgbuf[IOSIZE]; - STRCPY(ebuf, (char_u *)_("E505: ")); - STRCAT(ebuf, IObuff); - STRCAT(ebuf, (char_u *)_("is read-only (add ! to override)")); - STRCPY(IObuff, ebuf); - nbdebug((" %s\n", ebuf )); - emsg(IObuff); + vim_snprintf((char *)msgbuf, IOSIZE, + _("E505: %s is read-only (add ! to override)"), IObuff); + nbdebug((" %s\n", msgbuf)); + emsg(msgbuf); } } diff -Naur vim73.orig/src/normal.c vim73/src/normal.c --- vim73.orig/src/normal.c 2010-07-31 13:25:19.000000000 +0000 +++ vim73/src/normal.c 2012-07-20 20:31:18.050978309 +0000 @@ -20,15 +20,18 @@ */ static int resel_VIsual_mode = NUL; /* 'v', 'V', or Ctrl-V */ static linenr_T resel_VIsual_line_count; /* number of lines */ -static colnr_T resel_VIsual_col; /* nr of cols or end col */ +static colnr_T resel_VIsual_vcol; /* nr of cols or end col */ static int restart_VIsual_select = 0; #endif +#ifdef FEAT_EVAL +static void set_vcount_ca __ARGS((cmdarg_T *cap, int *set_prevcount)); +#endif static int -# ifdef __BORLANDC__ -_RTLENTRYF -# endif +#ifdef __BORLANDC__ + _RTLENTRYF +#endif nv_compare __ARGS((const void *s1, const void *s2)); static int find_command __ARGS((int cmdchar)); static void op_colon __ARGS((oparg_T *oap)); @@ -648,6 +651,14 @@ dont_scroll = FALSE; /* allow scrolling here */ #endif +#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 + * when there is no count. */ + if (toplevel && stuff_empty()) + set_vcount_ca(&ca, &set_prevcount); +#endif + /* * Get the command character from the user. */ @@ -725,15 +736,7 @@ * command, so that v:count can be used in an expression mapping * right after the count. */ if (toplevel && stuff_empty()) - { - long count = ca.count0; - - /* multiply with ca.opcount the same way as below */ - if (ca.opcount != 0) - count = ca.opcount * (count == 0 ? 1 : count); - set_vcount(count, count == 0 ? 1 : count, set_prevcount); - set_prevcount = FALSE; /* only set v:prevcount once */ - } + set_vcount_ca(&ca, &set_prevcount); #endif if (ctrl_w) { @@ -1199,7 +1202,16 @@ { clearop(oap); #ifdef FEAT_EVAL - set_reg_var('"'); + { + int regname = 0; + + /* Adjust the register according to 'clipboard', so that when + * "unnamed" is present it becomes '*' or '+' instead of '"'. */ +# ifdef FEAT_CLIPBOARD + adjust_clip_reg(®name); +# endif + set_reg_var(regname); + } #endif } @@ -1386,6 +1398,26 @@ opcount = ca.opcount; } +#ifdef FEAT_EVAL +/* + * Set v:count and v:count1 according to "cap". + * Set v:prevcount only when "set_prevcount" is TRUE. + */ + static void +set_vcount_ca(cap, set_prevcount) + cmdarg_T *cap; + int *set_prevcount; +{ + long count = cap->count0; + + /* multiply with cap->opcount the same way as above */ + if (cap->opcount != 0) + count = cap->opcount * (count == 0 ? 1 : count); + set_vcount(count, count == 0 ? 1 : count, *set_prevcount); + *set_prevcount = FALSE; /* only set v:prevcount once */ +} +#endif + /* * Handle an operator after visual mode or when the movement is finished */ @@ -1404,7 +1436,7 @@ /* The visual area is remembered for redo */ static int redo_VIsual_mode = NUL; /* 'v', 'V', or Ctrl-V */ static linenr_T redo_VIsual_line_count; /* number of lines */ - static colnr_T redo_VIsual_col; /* number of cols or end column */ + static colnr_T redo_VIsual_vcol; /* number of cols or end column */ static long redo_VIsual_count; /* count for Visual operator */ # ifdef FEAT_VIRTUALEDIT int include_line_break = FALSE; @@ -1419,7 +1451,7 @@ * This could call do_pending_operator() recursively, but that's OK * because gui_yank will be TRUE for the nested call. */ - if (clip_star.available + if ((clip_star.available || clip_plus.available) && oap->op_type != OP_NOP && !gui_yank # ifdef FEAT_VISUAL @@ -1517,22 +1549,31 @@ #ifdef FEAT_VISUAL if (redo_VIsual_busy) { + /* Redo of an operation on a Visual area. Use the same size from + * redo_VIsual_line_count and redo_VIsual_vcol. */ oap->start = curwin->w_cursor; curwin->w_cursor.lnum += redo_VIsual_line_count - 1; if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; VIsual_mode = redo_VIsual_mode; - if (VIsual_mode == 'v') + if (redo_VIsual_vcol == MAXCOL || VIsual_mode == 'v') { - if (redo_VIsual_line_count <= 1) - curwin->w_cursor.col += redo_VIsual_col - 1; + if (VIsual_mode == 'v') + { + if (redo_VIsual_line_count <= 1) + { + validate_virtcol(); + curwin->w_curswant = + curwin->w_virtcol + redo_VIsual_vcol - 1; + } + else + curwin->w_curswant = redo_VIsual_vcol; + } else - curwin->w_cursor.col = redo_VIsual_col; - } - if (redo_VIsual_col == MAXCOL) - { - curwin->w_curswant = MAXCOL; - coladvance((colnr_T)MAXCOL); + { + curwin->w_curswant = MAXCOL; + } + coladvance(curwin->w_curswant); } cap->count0 = redo_VIsual_count; if (redo_VIsual_count != 0) @@ -1678,7 +1719,7 @@ } } else if (redo_VIsual_busy) - oap->end_vcol = oap->start_vcol + redo_VIsual_col - 1; + oap->end_vcol = oap->start_vcol + redo_VIsual_vcol - 1; /* * Correct oap->end.col and oap->start.col to be the * upper-left and lower-right corner of the block area. @@ -1703,13 +1744,22 @@ */ resel_VIsual_mode = VIsual_mode; if (curwin->w_curswant == MAXCOL) - resel_VIsual_col = MAXCOL; - else if (VIsual_mode == Ctrl_V) - resel_VIsual_col = oap->end_vcol - oap->start_vcol + 1; - else if (oap->line_count > 1) - resel_VIsual_col = oap->end.col; + resel_VIsual_vcol = MAXCOL; else - resel_VIsual_col = oap->end.col - oap->start.col + 1; + { + if (VIsual_mode != Ctrl_V) + getvvcol(curwin, &(oap->end), + NULL, NULL, &oap->end_vcol); + if (VIsual_mode == Ctrl_V || oap->line_count <= 1) + { + if (VIsual_mode != Ctrl_V) + getvvcol(curwin, &(oap->start), + &oap->start_vcol, NULL, NULL); + resel_VIsual_vcol = oap->end_vcol - oap->start_vcol + 1; + } + else + resel_VIsual_vcol = oap->end_vcol; + } resel_VIsual_line_count = oap->line_count; } @@ -1737,7 +1787,7 @@ if (!redo_VIsual_busy) { redo_VIsual_mode = resel_VIsual_mode; - redo_VIsual_col = resel_VIsual_col; + redo_VIsual_vcol = resel_VIsual_vcol; redo_VIsual_line_count = resel_VIsual_line_count; redo_VIsual_count = cap->count0; } @@ -1763,17 +1813,25 @@ { oap->inclusive = FALSE; /* Try to include the newline, unless it's an operator - * that works on lines only */ - if (*p_sel != 'o' - && !op_on_lines(oap->op_type) - && oap->end.lnum < curbuf->b_ml.ml_line_count) + * that works on lines only. */ + if (*p_sel != 'o' && !op_on_lines(oap->op_type)) { - ++oap->end.lnum; - oap->end.col = 0; + if (oap->end.lnum < curbuf->b_ml.ml_line_count) + { + ++oap->end.lnum; + oap->end.col = 0; # ifdef FEAT_VIRTUALEDIT - oap->end.coladd = 0; + oap->end.coladd = 0; # endif - ++oap->line_count; + ++oap->line_count; + } + else + { + /* Cannot move below the last line, make the op + * inclusive to tell the operation to include the + * line break. */ + oap->inclusive = TRUE; + } } } } @@ -1910,7 +1968,7 @@ beep_flush(); else { - (void)do_join(oap->line_count, oap->op_type == OP_JOIN, TRUE); + (void)do_join(oap->line_count, oap->op_type == OP_JOIN, TRUE, TRUE); auto_format(FALSE, TRUE); } break; @@ -1920,7 +1978,10 @@ VIsual_reselect = FALSE; /* don't reselect now */ #endif if (empty_region_error) + { vim_beep(); + CancelRedo(); + } else { (void)op_delete(oap); @@ -1934,7 +1995,10 @@ if (empty_region_error) { if (!gui_yank) + { vim_beep(); + CancelRedo(); + } } else (void)op_yank(oap, FALSE, !gui_yank); @@ -1946,7 +2010,10 @@ VIsual_reselect = FALSE; /* don't reselect now */ #endif if (empty_region_error) + { vim_beep(); + CancelRedo(); + } else { /* This is a new edit command, not a restart. Need to @@ -2008,7 +2075,10 @@ case OP_LOWER: case OP_ROT13: if (empty_region_error) + { vim_beep(); + CancelRedo(); + } else op_tilde(oap); check_cursor_col(); @@ -2041,7 +2111,10 @@ #endif #ifdef FEAT_VISUALEXTRA if (empty_region_error) + { vim_beep(); + CancelRedo(); + } else { /* This is a new edit command, not a restart. Need to @@ -2071,7 +2144,10 @@ #ifdef FEAT_VISUALEXTRA if (empty_region_error) #endif + { vim_beep(); + CancelRedo(); + } #ifdef FEAT_VISUALEXTRA else op_replace(oap, cap->nchar); @@ -2203,6 +2279,7 @@ { #ifdef FEAT_EVAL char_u *(argv[1]); + int save_virtual_op = virtual_op; if (*p_opfunc == NUL) EMSG(_("E774: 'operatorfunc' is empty")); @@ -2221,7 +2298,14 @@ argv[0] = (char_u *)"line"; else argv[0] = (char_u *)"char"; + + /* Reset virtual_op so that 'virtualedit' can be changed in the + * function. */ + virtual_op = MAYBE; + (void)call_func_retnr(p_opfunc, 1, argv, FALSE); + + virtual_op = save_virtual_op; } #else EMSG(_("E775: Eval feature not available")); @@ -4342,7 +4426,7 @@ break; } #ifdef FEAT_COMMENTS - if (get_leader_len(ml_get_curline(), NULL, FALSE) > 0) + if (get_leader_len(ml_get_curline(), NULL, FALSE, TRUE) > 0) { /* Ignore this line, continue at start of next line. */ ++curwin->w_cursor.lnum; @@ -4501,6 +4585,7 @@ } curwin->w_cursor.lnum++; curwin->w_curswant %= width2; + linelen = linetabsize(ml_get_curline()); } } } @@ -5666,8 +5751,13 @@ else if (cmdchar == '#') aux_ptr = (char_u *)(p_magic ? "/?.*~[^$\\" : "/?^$\\"); else if (tag_cmd) - /* Don't escape spaces and Tabs in a tag with a backslash */ - aux_ptr = (char_u *)"\\|\"\n["; + { + if (curbuf->b_help) + /* ":help" handles unescaped argument */ + aux_ptr = (char_u *)""; + else + aux_ptr = (char_u *)"\\|\"\n["; + } else aux_ptr = (char_u *)"\\|\"\n*?["; @@ -6980,7 +7070,18 @@ for (n = cap->count1; n > 0; --n) { State = REPLACE; - ins_char(cap->nchar); + if (cap->nchar == Ctrl_E || cap->nchar == Ctrl_Y) + { + int c = ins_copychar(curwin->w_cursor.lnum + + (cap->nchar == Ctrl_Y ? -1 : 1)); + if (c != NUL) + ins_char(c); + else + /* will be decremented further down */ + ++curwin->w_cursor.col; + } + else + ins_char(cap->nchar); State = old_State; if (cap->ncharC1 != 0) ins_char(cap->ncharC1); @@ -7002,7 +7103,15 @@ * line will be changed. */ ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE); - ptr[curwin->w_cursor.col] = cap->nchar; + if (cap->nchar == Ctrl_E || cap->nchar == Ctrl_Y) + { + int c = ins_copychar(curwin->w_cursor.lnum + + (cap->nchar == Ctrl_Y ? -1 : 1)); + if (c != NUL) + ptr[curwin->w_cursor.col] = c; + } + else + ptr[curwin->w_cursor.col] = cap->nchar; if (p_sm && msg_silent == 0) showmatch(cap->nchar); ++curwin->w_cursor.col; @@ -7551,13 +7660,9 @@ else /* start Visual mode */ { check_visual_highlight(); - if (cap->count0) /* use previously selected part */ + if (cap->count0 > 0 && resel_VIsual_mode != NUL) { - if (resel_VIsual_mode == NUL) /* there is none */ - { - beep_flush(); - return; - } + /* use previously selected part */ VIsual = curwin->w_cursor; VIsual_active = TRUE; @@ -7585,12 +7690,16 @@ if (VIsual_mode == 'v') { if (resel_VIsual_line_count <= 1) - curwin->w_cursor.col += resel_VIsual_col * cap->count0 - 1; + { + validate_virtcol(); + curwin->w_curswant = curwin->w_virtcol + + resel_VIsual_vcol * cap->count0 - 1; + } else - curwin->w_cursor.col = resel_VIsual_col; - check_cursor_col(); + curwin->w_curswant = resel_VIsual_vcol; + coladvance(curwin->w_curswant); } - if (resel_VIsual_col == MAXCOL) + if (resel_VIsual_vcol == MAXCOL) { curwin->w_curswant = MAXCOL; coladvance((colnr_T)MAXCOL); @@ -7599,7 +7708,7 @@ { validate_virtcol(); curwin->w_curswant = curwin->w_virtcol - + resel_VIsual_col * cap->count0 - 1; + + resel_VIsual_vcol * cap->count0 - 1; coladvance(curwin->w_curswant); } else @@ -7612,6 +7721,16 @@ /* start Select mode when 'selectmode' contains "cmd" */ may_start_select('c'); n_start_visual_mode(cap->cmdchar); + if (VIsual_mode != 'V' && *p_sel == 'e') + ++cap->count1; /* include one more char */ + if (cap->count0 > 0 && --cap->count1 > 0) + { + /* With a count select that many characters or lines. */ + if (VIsual_mode == 'v' || VIsual_mode == Ctrl_V) + nv_right(cap); + else if (VIsual_mode == 'V') + nv_down(cap); + } } } } @@ -8274,10 +8393,12 @@ #ifdef FEAT_WINDOWS case 't': - goto_tabpage((int)cap->count0); + if (!checkclearop(oap)) + goto_tabpage((int)cap->count0); break; case 'T': - goto_tabpage(-(int)cap->count1); + if (!checkclearop(oap)) + goto_tabpage(-(int)cap->count1); break; #endif @@ -8524,7 +8645,7 @@ else curwin->w_curswant = 0; /* keep curswant at the column where we wanted to go, not where - we ended; differs if line is too short */ + * we ended; differs if line is too short */ curwin->w_set_curswant = FALSE; } @@ -8736,7 +8857,7 @@ { --pp->col; #ifdef FEAT_MBYTE - mb_adjustpos(pp); + mb_adjustpos(curbuf, pp); #endif } else if (pp->lnum > 1) @@ -9205,7 +9326,7 @@ { prep_redo(cap->oap->regname, cap->count0, NUL, cap->cmdchar, NUL, NUL, cap->nchar); - (void)do_join(cap->count0, cap->nchar == NUL, TRUE); + (void)do_join(cap->count0, cap->nchar == NUL, TRUE, TRUE); } } } @@ -9261,7 +9382,7 @@ # ifdef FEAT_CLIPBOARD adjust_clip_reg(®name); # endif - if (regname == 0 || VIM_ISDIGIT(regname) + if (regname == 0 || regname == '"' || VIM_ISDIGIT(regname) # ifdef FEAT_CLIPBOARD || (clip_unnamed && (regname == '*' || regname == '+')) # endif diff -Naur vim73.orig/src/ops.c vim73/src/ops.c --- vim73.orig/src/ops.c 2010-08-01 12:16:08.000000000 +0000 +++ vim73/src/ops.c 2012-07-20 20:31:18.057644980 +0000 @@ -112,6 +112,9 @@ # endif #endif static void dis_msg __ARGS((char_u *p, int skip_esc)); +#if defined(FEAT_COMMENTS) || defined(PROTO) +static char_u *skip_comment __ARGS((char_u *line, int process, int include_space, int *is_comment)); +#endif #ifdef FEAT_VISUAL static void block_prep __ARGS((oparg_T *oap, struct block_def *, linenr_T, int)); #endif @@ -959,8 +962,14 @@ * selection too. */ if (name == '*' && clip_star.available) { - if (clip_isautosel()) - clip_update_selection(); + if (clip_isautosel_star()) + clip_update_selection(&clip_star); + may_get_selection(name); + } + if (name == '+' && clip_plus.available) + { + if (clip_isautosel_plus()) + clip_update_selection(&clip_plus); may_get_selection(name); } #endif @@ -1584,9 +1593,11 @@ adjust_clip_reg(rp) int *rp; { - /* If no reg. specified, and "unnamed" is in 'clipboard', use '*' reg. */ - if (*rp == 0 && clip_unnamed) - *rp = '*'; + /* If no reg. specified, and "unnamed" or "unnamedplus" is in 'clipboard', + * use '*' or '+' reg, respectively. "unnamedplus" prevails. */ + if (*rp == 0 && clip_unnamed != 0) + *rp = ((clip_unnamed & CLIP_UNNAMED_PLUS) && clip_plus.available) + ? '+' : '*'; if (!clip_star.available && *rp == '*') *rp = 0; if (!clip_plus.available && *rp == '+') @@ -1646,9 +1657,12 @@ && !oap->block_mode #endif && oap->line_count > 1 + && oap->motion_force == NUL && oap->op_type == OP_DELETE) { - ptr = ml_get(oap->end.lnum) + oap->end.col + oap->inclusive; + ptr = ml_get(oap->end.lnum) + oap->end.col; + if (*ptr != NUL) + ptr += oap->inclusive; ptr = skipwhite(ptr); if (*ptr == NUL && inindent(0)) oap->motion_type = MLINE; @@ -1715,9 +1729,14 @@ did_yank = TRUE; } - /* Yank into small delete register when no register specified and the - * delete is within one line. */ - if (oap->regname == 0 && oap->motion_type != MLINE + /* Yank into small delete register when no named register specified + * and the delete is within one line. */ + if (( +#ifdef FEAT_CLIPBOARD + ((clip_unnamed & CLIP_UNNAMED) && oap->regname == '*') || + ((clip_unnamed & CLIP_UNNAMED_PLUS) && oap->regname == '+') || +#endif + oap->regname == 0) && oap->motion_type != MLINE && oap->line_count == 1) { oap->regname = '-'; @@ -1918,38 +1937,66 @@ curwin->w_cursor.coladd = 0; } #endif - (void)del_bytes((long)n, !virtual_op, oap->op_type == OP_DELETE + if (oap->op_type == OP_DELETE + && oap->inclusive + && oap->end.lnum == curbuf->b_ml.ml_line_count + && n > (int)STRLEN(ml_get(oap->end.lnum))) + { + /* Special case: gH deletes the last line. */ + del_lines(1L, FALSE); + } + else + { + (void)del_bytes((long)n, !virtual_op, oap->op_type == OP_DELETE #ifdef FEAT_VISUAL && !oap->is_VIsual #endif ); + } } else /* delete characters between lines */ { pos_T curpos; + int delete_last_line; /* save deleted and changed lines for undo */ if (u_save((linenr_T)(curwin->w_cursor.lnum - 1), (linenr_T)(curwin->w_cursor.lnum + oap->line_count)) == FAIL) return FAIL; + delete_last_line = (oap->end.lnum == curbuf->b_ml.ml_line_count); truncate_line(TRUE); /* delete from cursor to end of line */ curpos = curwin->w_cursor; /* remember curwin->w_cursor */ ++curwin->w_cursor.lnum; del_lines((long)(oap->line_count - 2), FALSE); - /* delete from start of line until op_end */ - curwin->w_cursor.col = 0; - (void)del_bytes((long)(oap->end.col + 1 - !oap->inclusive), - !virtual_op, oap->op_type == OP_DELETE + if (delete_last_line) + oap->end.lnum = curbuf->b_ml.ml_line_count; + + n = (oap->end.col + 1 - !oap->inclusive); + if (oap->inclusive && delete_last_line + && n > (int)STRLEN(ml_get(oap->end.lnum))) + { + /* Special case: gH deletes the last line. */ + del_lines(1L, FALSE); + curwin->w_cursor = curpos; /* restore curwin->w_cursor */ + if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) + curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; + } + else + { + /* delete from start of line until op_end */ + curwin->w_cursor.col = 0; + (void)del_bytes((long)n, !virtual_op, oap->op_type == OP_DELETE #ifdef FEAT_VISUAL && !oap->is_VIsual #endif ); - curwin->w_cursor = curpos; /* restore curwin->w_cursor */ - - (void)do_join(2, FALSE, FALSE); + curwin->w_cursor = curpos; /* restore curwin->w_cursor */ + } + if (curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) + (void)do_join(2, FALSE, FALSE, FALSE); } } @@ -2569,7 +2616,8 @@ firstline = ml_get(oap->start.lnum) + bd.textcol; if (oap->op_type == OP_APPEND) firstline += bd.textlen; - if ((ins_len = (long)STRLEN(firstline) - pre_textlen) > 0) + if (pre_textlen >= 0 + && (ins_len = (long)STRLEN(firstline) - pre_textlen) > 0) { ins_text = vim_strnsave(firstline, (int)ins_len); if (ins_text != NULL) @@ -2842,6 +2890,9 @@ char_u *p; char_u *pnew; struct block_def bd; +#if defined(FEAT_CLIPBOARD) && defined(FEAT_X11) + int did_star = FALSE; +#endif /* check for read-only register */ if (oap->regname != 0 && !valid_yank_reg(oap->regname, TRUE)) @@ -3000,6 +3051,8 @@ } #endif } + if (endcol == MAXCOL) + endcol = (colnr_T)STRLEN(p); if (startcol > endcol #ifdef FEAT_VIRTUALEDIT || is_oneChar @@ -3008,8 +3061,6 @@ bd.textlen = 0; else { - if (endcol == MAXCOL) - endcol = (colnr_T)STRLEN(p); bd.textlen = endcol - startcol + oap->inclusive; } bd.textstart = p + startcol; @@ -3115,7 +3166,8 @@ */ if (clip_star.available && (curr == &(y_regs[STAR_REGISTER]) - || (!deleting && oap->regname == 0 && clip_unnamed))) + || (!deleting && oap->regname == 0 + && (clip_unnamed & CLIP_UNNAMED)))) { if (curr != &(y_regs[STAR_REGISTER])) /* Copy the text from register 0 to the clipboard register. */ @@ -3123,6 +3175,9 @@ clip_own_selection(&clip_star); clip_gen_set_selection(&clip_star); +# ifdef FEAT_X11 + did_star = TRUE; +# endif } # ifdef FEAT_X11 @@ -3130,12 +3185,19 @@ * If we were yanking to the '+' register, send result to selection. * Also copy to the '*' register, in case auto-select is off. */ - else if (clip_plus.available && curr == &(y_regs[PLUS_REGISTER])) + if (clip_plus.available + && (curr == &(y_regs[PLUS_REGISTER]) + || (!deleting && oap->regname == 0 + && (clip_unnamed & CLIP_UNNAMED_PLUS)))) { - /* No need to copy to * register upon 'unnamed' now - see below */ + if (curr != &(y_regs[PLUS_REGISTER])) + /* Copy the text from register 0 to the clipboard register. */ + copy_yank_reg(&(y_regs[PLUS_REGISTER])); + clip_own_selection(&clip_plus); clip_gen_set_selection(&clip_plus); - if (!clip_isautosel()) + if (!clip_isautosel_star() && !did_star + && curr == &(y_regs[PLUS_REGISTER])) { copy_yank_reg(&(y_regs[STAR_REGISTER])); clip_own_selection(&clip_star); @@ -3293,8 +3355,8 @@ if (regname == '=') { /* For the = register we need to split the string at NL - * characters. */ - /* Loop twice: count the number of lines and save them. */ + * characters. + * Loop twice: count the number of lines and save them. */ for (;;) { y_size = 0; @@ -3310,7 +3372,7 @@ if (y_array != NULL) *ptr = NUL; ++ptr; - /* A trailing '\n' makes the string linewise */ + /* A trailing '\n' makes the register linewise. */ if (*ptr == NUL) { y_type = MLINE; @@ -3979,7 +4041,12 @@ for (i = -1; i < NUM_REGISTERS && !got_int; ++i) { name = get_register_name(i); - if (arg != NULL && vim_strchr(arg, name) == NULL) + if (arg != NULL && vim_strchr(arg, name) == NULL +#ifdef ONE_CLIPBOARD + /* Star register and plus register contain the same thing. */ + && (name != '*' || vim_strchr(arg, '+') == NULL) +#endif + ) continue; /* did not ask for this register */ #ifdef FEAT_CLIPBOARD @@ -4140,22 +4207,101 @@ ui_breakcheck(); } +#if defined(FEAT_COMMENTS) || defined(PROTO) +/* + * If "process" is TRUE and the line begins with a comment leader (possibly + * after some white space), return a pointer to the text after it. Put a boolean + * value indicating whether the line ends with an unclosed comment in + * "is_comment". + * line - line to be processed, + * process - if FALSE, will only check whether the line ends with an unclosed + * comment, + * include_space - whether to also skip space following the comment leader, + * is_comment - will indicate whether the current line ends with an unclosed + * comment. + */ + static char_u * +skip_comment(line, process, include_space, is_comment) + char_u *line; + int process; + int include_space; + int *is_comment; +{ + char_u *comment_flags = NULL; + int lead_len; + int leader_offset = get_last_leader_offset(line, &comment_flags); + + *is_comment = FALSE; + if (leader_offset != -1) + { + /* Let's check whether the line ends with an unclosed comment. + * If the last comment leader has COM_END in flags, there's no comment. + */ + while (*comment_flags) + { + if (*comment_flags == COM_END + || *comment_flags == ':') + break; + ++comment_flags; + } + if (*comment_flags != COM_END) + *is_comment = TRUE; + } + + if (process == FALSE) + return line; + + lead_len = get_leader_len(line, &comment_flags, FALSE, include_space); + + if (lead_len == 0) + return line; + + /* Find: + * - COM_END, + * - colon, + * whichever comes first. + */ + while (*comment_flags) + { + if (*comment_flags == COM_END + || *comment_flags == ':') + { + break; + } + ++comment_flags; + } + + /* If we found a colon, it means that we are not processing a line + * starting with a closing part of a three-part comment. That's good, + * because we don't want to remove those as this would be annoying. + */ + if (*comment_flags == ':' || *comment_flags == NUL) + line += lead_len; + + return line; +} +#endif + /* * Join 'count' lines (minimal 2) at cursor position. * When "save_undo" is TRUE save lines for undo first. + * Set "use_formatoptions" to FALSE when e.g. processing + * backspace and comment leaders should not be removed. * * return FAIL for failure, OK otherwise */ int -do_join(count, insert_space, save_undo) +do_join(count, insert_space, save_undo, use_formatoptions) long count; int insert_space; int save_undo; + int use_formatoptions UNUSED; { char_u *curr = NULL; + char_u *curr_start = NULL; char_u *cend; char_u *newp; - char_u *spaces; /* number of spaces inserte before a line */ + char_u *spaces; /* number of spaces inserted before a line */ int endcurr1 = NUL; int endcurr2 = NUL; int currsize = 0; /* size of the current line */ @@ -4163,6 +4309,13 @@ linenr_T t; colnr_T col = 0; int ret = OK; +#if defined(FEAT_COMMENTS) || defined(PROTO) + int *comments = NULL; + int remove_comments = (use_formatoptions == TRUE) + && has_format_option(FO_REMOVE_COMS); + int prev_was_comment; +#endif + if (save_undo && u_save((linenr_T)(curwin->w_cursor.lnum - 1), (linenr_T)(curwin->w_cursor.lnum + count)) == FAIL) @@ -4174,6 +4327,17 @@ spaces = lalloc_clear((long_u)count, TRUE); if (spaces == NULL) return FAIL; +#if defined(FEAT_COMMENTS) || defined(PROTO) + if (remove_comments) + { + comments = (int *)lalloc_clear((long_u)count * sizeof(int), TRUE); + if (comments == NULL) + { + vim_free(spaces); + return FAIL; + } + } +#endif /* * Don't move anything, just compute the final line length @@ -4181,7 +4345,26 @@ */ for (t = 0; t < count; ++t) { - curr = ml_get((linenr_T)(curwin->w_cursor.lnum + t)); + curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t)); +#if defined(FEAT_COMMENTS) || defined(PROTO) + if (remove_comments) + { + /* We don't want to remove the comment leader if the + * previous line is not a comment. */ + if (t > 0 && prev_was_comment) + { + + char_u *new_curr = skip_comment(curr, TRUE, insert_space, + &prev_was_comment); + comments[t] = (int)(new_curr - curr); + curr = new_curr; + } + else + curr = skip_comment(curr, FALSE, insert_space, + &prev_was_comment); + } +#endif + if (insert_space && t > 0) { curr = skipwhite(curr); @@ -4265,10 +4448,14 @@ copy_spaces(cend, (size_t)(spaces[t])); } mark_col_adjust(curwin->w_cursor.lnum + t, (colnr_T)0, (linenr_T)-t, - (long)(cend - newp + spaces[t])); + (long)(cend - newp + spaces[t] - (curr - curr_start))); if (t == 0) break; - curr = ml_get((linenr_T)(curwin->w_cursor.lnum + t - 1)); + curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t - 1)); +#if defined(FEAT_COMMENTS) || defined(PROTO) + if (remove_comments) + curr += comments[t - 1]; +#endif if (insert_space && t > 1) curr = skipwhite(curr); currsize = (int)STRLEN(curr); @@ -4306,6 +4493,10 @@ theend: vim_free(spaces); +#if defined(FEAT_COMMENTS) || defined(PROTO) + if (remove_comments) + vim_free(comments); +#endif return ret; } @@ -4388,7 +4579,7 @@ #endif /* - * implementation of the format operator 'gq' + * Implementation of the format operator 'gq'. */ void op_format(oap, keep_cursor) @@ -4539,9 +4730,11 @@ char_u *leader_flags = NULL; /* flags for leader of current line */ char_u *next_leader_flags; /* flags for leader of next line */ int do_comments; /* format comments */ + int do_comments_list = 0; /* format comments with 'n' or '2' */ #endif int advance = TRUE; - int second_indent = -1; + int second_indent = -1; /* indent for second line (comment + * aware) */ int do_second_indent; int do_number_indent; int do_trail_white; @@ -4644,18 +4837,46 @@ if (first_par_line && (do_second_indent || do_number_indent) && prev_is_end_par - && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count + && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) + { + if (do_second_indent && !lineempty(curwin->w_cursor.lnum + 1)) + { #ifdef FEAT_COMMENTS - && leader_len == 0 - && next_leader_len == 0 + if (leader_len == 0 && next_leader_len == 0) + { + /* no comment found */ #endif - ) - { - if (do_second_indent - && !lineempty(curwin->w_cursor.lnum + 1)) - second_indent = get_indent_lnum(curwin->w_cursor.lnum + 1); + second_indent = + get_indent_lnum(curwin->w_cursor.lnum + 1); +#ifdef FEAT_COMMENTS + } + else + { + second_indent = next_leader_len; + do_comments_list = 1; + } +#endif + } else if (do_number_indent) - second_indent = get_number_indent(curwin->w_cursor.lnum); + { +#ifdef FEAT_COMMENTS + if (leader_len == 0 && next_leader_len == 0) + { + /* no comment found */ +#endif + second_indent = + get_number_indent(curwin->w_cursor.lnum); +#ifdef FEAT_COMMENTS + } + else + { + /* get_number_indent() is now "comment aware"... */ + second_indent = + get_number_indent(curwin->w_cursor.lnum); + do_comments_list = 1; + } +#endif + } } /* @@ -4694,6 +4915,8 @@ insertchar(NUL, INSCHAR_FORMAT #ifdef FEAT_COMMENTS + (do_comments ? INSCHAR_DO_COM : 0) + + (do_comments && do_comments_list + ? INSCHAR_COM_LIST : 0) #endif + (avoid_fex ? INSCHAR_NO_FEX : 0), second_indent); State = old_State; @@ -4730,7 +4953,7 @@ (long)-next_leader_len); #endif curwin->w_cursor.lnum--; - if (do_join(2, TRUE, FALSE) == FAIL) + if (do_join(2, TRUE, FALSE, FALSE) == FAIL) { beep_flush(); break; @@ -4786,7 +5009,7 @@ ptr = ml_get(lnum); if (do_comments) - *leader_len = get_leader_len(ptr, leader_flags, FALSE); + *leader_len = get_leader_len(ptr, leader_flags, FALSE, TRUE); else *leader_len = 0; @@ -5712,7 +5935,9 @@ } } -/* Convert from the GUI selection string into the '*'/'+' register */ +/* + * Convert from the GUI selection string into the '*'/'+' register. + */ void clip_yank_selection(type, str, len, cbd) int type; @@ -6069,9 +6294,6 @@ if (yank_type == MBLOCK) yank_type = MAUTO; #endif - if (yank_type == MAUTO) - yank_type = ((len > 0 && (str[len - 1] == '\n' || str[len - 1] == '\r')) - ? MLINE : MCHAR); str_to_reg(y_current, yank_type, str, len, block_len); # ifdef FEAT_CLIPBOARD @@ -6092,13 +6314,14 @@ * is appended. */ static void -str_to_reg(y_ptr, type, str, len, blocklen) +str_to_reg(y_ptr, yank_type, str, len, blocklen) struct yankreg *y_ptr; /* pointer to yank register */ - int type; /* MCHAR, MLINE or MBLOCK */ + int yank_type; /* MCHAR, MLINE, MBLOCK, MAUTO */ char_u *str; /* string to put in register */ long len; /* length of string */ long blocklen; /* width of Visual block */ { + int type; /* MCHAR, MLINE or MBLOCK */ int lnum; long start; long i; @@ -6115,6 +6338,12 @@ if (y_ptr->y_array == NULL) /* NULL means empty register */ y_ptr->y_size = 0; + if (yank_type == MAUTO) + type = ((len > 0 && (str[len - 1] == NL || str[len - 1] == CAR)) + ? MLINE : MCHAR); + else + type = yank_type; + /* * Count the number of lines within the string */ @@ -6236,7 +6465,7 @@ long chars = 0; int is_word = 0; - for (i = 0; line[i] && i < limit; ) + for (i = 0; i < limit && line[i] != NUL; ) { if (is_word) { @@ -6261,7 +6490,7 @@ *wc += words; /* Add eol_size if the end of line was reached before hitting limit. */ - if (line[i] == NUL && i < limit) + if (i < limit && line[i] == NUL) { i += eol_size; chars += eol_size; diff -Naur vim73.orig/src/option.c vim73/src/option.c --- vim73.orig/src/option.c 2010-08-04 18:49:18.000000000 +0000 +++ vim73/src/option.c 2012-07-20 20:31:18.180978402 +0000 @@ -140,9 +140,6 @@ #define PV_MOD OPT_BUF(BV_MOD) #define PV_MPS OPT_BUF(BV_MPS) #define PV_NF OPT_BUF(BV_NF) -#ifdef FEAT_OSFILETYPE -# define PV_OFT OPT_BUF(BV_OFT) -#endif #ifdef FEAT_COMPL_FUNC # define PV_OFU OPT_BUF(BV_OFU) #endif @@ -337,9 +334,6 @@ static int p_mod; static char_u *p_mps; static char_u *p_nf; -#ifdef FEAT_OSFILETYPE -static char_u *p_oft; -#endif static int p_pi; #ifdef FEAT_TEXTOBJ static char_u *p_qe; @@ -439,17 +433,19 @@ #define P_RCLR 0x7000 /* clear and redraw all */ #define P_COMMA 0x8000 /* comma separated list */ -#define P_NODUP 0x10000L/* don't allow duplicate strings */ -#define P_FLAGLIST 0x20000L/* list of single-char flags */ +#define P_NODUP 0x10000L /* don't allow duplicate strings */ +#define P_FLAGLIST 0x20000L /* list of single-char flags */ -#define P_SECURE 0x40000L/* cannot change in modeline or secure mode */ -#define P_GETTEXT 0x80000L/* expand default value with _() */ -#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 +#define P_SECURE 0x40000L /* cannot change in modeline or secure mode */ +#define P_GETTEXT 0x80000L /* expand default value with _() */ +#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 P_NO_ML 0x1000000L/* not allowed in modeline */ +#define P_NO_ML 0x1000000L /* not allowed in modeline */ +#define P_CURSWANT 0x2000000L /* update curswant required; not needed when + * there is a redraw flag */ #define ISK_LATIN1 (char_u *)"@,48-57,_,192-255" @@ -466,9 +462,9 @@ #if defined(FEAT_DIFF) || defined(FEAT_FOLDING) || defined(FEAT_SPELL) \ || defined(FEAT_VERTSPLIT) || defined(FEAT_CLIPBOARD) \ || defined(FEAT_INS_EXPAND) || defined(FEAT_SYN_HL) || defined(FEAT_CONCEAL) -# define HIGHLIGHT_INIT "8:SpecialKey,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn,-:Conceal,B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel,x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill,!:CursorColumn,.:CursorLine,o:ColorColumn" +# define HIGHLIGHT_INIT "8:SpecialKey,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,N:CursorLineNr,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn,-:Conceal,B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel,x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill,!:CursorColumn,.:CursorLine,o:ColorColumn" #else -# define HIGHLIGHT_INIT "8:SpecialKey,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,r:Question,s:StatusLine,S:StatusLineNC,t:Title,v:Visual,w:WarningMsg,W:WildMenu,>:SignColumn,*:TabLine,#:TabLineSel,_:TabLineFill" +# define HIGHLIGHT_INIT "8:SpecialKey,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,N:CursorLineNr,r:Question,s:StatusLine,S:StatusLineNC,t:Title,v:Visual,w:WarningMsg,W:WildMenu,>:SignColumn,*:TabLine,#:TabLineSel,_:TabLineFill" #endif /* @@ -485,7 +481,7 @@ #endif options[] = { - {"aleph", "al", P_NUM|P_VI_DEF, + {"aleph", "al", P_NUM|P_VI_DEF|P_CURSWANT, #ifdef FEAT_RIGHTLEFT (char_u *)&p_aleph, PV_NONE, #else @@ -507,7 +503,7 @@ {(char_u *)FALSE, (char_u *)FALSE} #endif SCRIPTID_INIT}, - {"arabic", "arab", P_BOOL|P_VI_DEF|P_VIM, + {"arabic", "arab", P_BOOL|P_VI_DEF|P_VIM|P_CURSWANT, #ifdef FEAT_ARABIC (char_u *)VAR_WIN, PV_ARAB, #else @@ -784,7 +780,7 @@ {"columns", "co", P_NUM|P_NODEFAULT|P_NO_MKRC|P_VI_DEF|P_RCLR, (char_u *)&Columns, PV_NONE, {(char_u *)80L, (char_u *)0L} SCRIPTID_INIT}, - {"comments", "com", P_STRING|P_ALLOCED|P_VI_DEF|P_COMMA|P_NODUP, + {"comments", "com", P_STRING|P_ALLOCED|P_VI_DEF|P_COMMA|P_NODUP|P_CURSWANT, #ifdef FEAT_COMMENTS (char_u *)&p_com, PV_COM, {(char_u *)"s1:/*,mb:*,ex:*/,://,b:#,:%,:XCOMM,n:>,fb:-", @@ -794,7 +790,7 @@ {(char_u *)0L, (char_u *)0L} #endif SCRIPTID_INIT}, - {"commentstring", "cms", P_STRING|P_ALLOCED|P_VI_DEF, + {"commentstring", "cms", P_STRING|P_ALLOCED|P_VI_DEF|P_CURSWANT, #ifdef FEAT_FOLDING (char_u *)&p_cms, PV_CMS, {(char_u *)"/*%s*/", (char_u *)0L} @@ -907,6 +903,13 @@ {(char_u *)0L, (char_u *)0L} #endif SCRIPTID_INIT}, + {"cscoperelative", "csre", P_BOOL|P_VI_DEF|P_VIM, +#ifdef FEAT_CSCOPE + (char_u *)&p_csre, PV_NONE, +#else + (char_u *)NULL, PV_NONE, +#endif + {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, {"cscopetag", "cst", P_BOOL|P_VI_DEF|P_VIM, #ifdef FEAT_CSCOPE (char_u *)&p_cst, PV_NONE, @@ -952,7 +955,7 @@ {"debug", NULL, P_STRING|P_VI_DEF, (char_u *)&p_debug, PV_NONE, {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, - {"define", "def", P_STRING|P_ALLOCED|P_VI_DEF, + {"define", "def", P_STRING|P_ALLOCED|P_VI_DEF|P_CURSWANT, #ifdef FEAT_FIND_ID (char_u *)&p_def, PV_DEF, {(char_u *)"^\\s*#\\s*define", (char_u *)0L} @@ -982,7 +985,7 @@ (char_u *)NULL, PV_NONE, #endif {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, - {"diffexpr", "dex", P_STRING|P_VI_DEF|P_SECURE, + {"diffexpr", "dex", P_STRING|P_VI_DEF|P_SECURE|P_CURSWANT, #if defined(FEAT_DIFF) && defined(FEAT_EVAL) (char_u *)&p_dex, PV_NONE, {(char_u *)"", (char_u *)0L} @@ -1098,7 +1101,7 @@ {(char_u *)0L, (char_u *)0L} #endif SCRIPTID_INIT}, - {"fileformat", "ff", P_STRING|P_ALLOCED|P_VI_DEF|P_RSTAT|P_NO_MKRC, + {"fileformat", "ff", P_STRING|P_ALLOCED|P_VI_DEF|P_RSTAT|P_NO_MKRC|P_CURSWANT, (char_u *)&p_ff, PV_FF, {(char_u *)DFLT_FF, (char_u *)0L} SCRIPTID_INIT}, {"fileformats", "ffs", P_STRING|P_VIM|P_COMMA|P_NODUP, @@ -1158,7 +1161,7 @@ {"foldlevel", "fdl", P_NUM|P_VI_DEF|P_RWIN, (char_u *)VAR_WIN, PV_FDL, {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, - {"foldlevelstart","fdls", P_NUM|P_VI_DEF, + {"foldlevelstart","fdls", P_NUM|P_VI_DEF|P_CURSWANT, (char_u *)&p_fdls, PV_NONE, {(char_u *)-1L, (char_u *)0L} SCRIPTID_INIT}, {"foldmarker", "fmr", P_STRING|P_ALLOCED|P_VIM|P_VI_DEF| @@ -1175,7 +1178,7 @@ {"foldnestmax", "fdn", P_NUM|P_VI_DEF|P_RWIN, (char_u *)VAR_WIN, PV_FDN, {(char_u *)20L, (char_u *)0L} SCRIPTID_INIT}, - {"foldopen", "fdo", P_STRING|P_VI_DEF|P_COMMA|P_NODUP, + {"foldopen", "fdo", P_STRING|P_VI_DEF|P_COMMA|P_NODUP|P_CURSWANT, (char_u *)&p_fdo, PV_NONE, {(char_u *)"block,hor,mark,percent,quickfix,search,tag,undo", (char_u *)0L} SCRIPTID_INIT}, @@ -1740,7 +1743,7 @@ {"matchtime", "mat", P_NUM|P_VI_DEF, (char_u *)&p_mat, PV_NONE, {(char_u *)5L, (char_u *)0L} SCRIPTID_INIT}, - {"maxcombine", "mco", P_NUM|P_VI_DEF, + {"maxcombine", "mco", P_NUM|P_VI_DEF|P_CURSWANT, #ifdef FEAT_MBYTE (char_u *)&p_mco, PV_NONE, #else @@ -1901,14 +1904,8 @@ (char_u *)NULL, PV_NONE, {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, {"osfiletype", "oft", P_STRING|P_ALLOCED|P_VI_DEF, -#ifdef FEAT_OSFILETYPE - (char_u *)&p_oft, PV_OFT, - {(char_u *)DFLT_OFT, (char_u *)0L} -#else (char_u *)NULL, PV_NONE, - {(char_u *)0L, (char_u *)0L} -#endif - SCRIPTID_INIT}, + {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, {"paragraphs", "para", P_STRING|P_VI_DEF, (char_u *)&p_para, PV_NONE, {(char_u *)"IPLPPPQPP TPHPLIPpLpItpplpipbp", @@ -2278,6 +2275,15 @@ (char_u *)"", #endif (char_u *)0L} SCRIPTID_INIT}, + {"shellxescape", "sxe", P_STRING|P_VI_DEF|P_SECURE, + (char_u *)&p_sxe, PV_NONE, + { +#if defined(MSDOS) || defined(WIN16) || defined(WIN3264) + (char_u *)"\"&|<>()@^", +#else + (char_u *)"", +#endif + (char_u *)0L} SCRIPTID_INIT}, {"shiftround", "sr", P_BOOL|P_VI_DEF|P_VIM, (char_u *)&p_sr, PV_NONE, {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, @@ -2706,7 +2712,7 @@ {(char_u *)0L, (char_u *)0L} #endif SCRIPTID_INIT}, - {"virtualedit", "ve", P_STRING|P_COMMA|P_NODUP|P_VI_DEF|P_VIM, + {"virtualedit", "ve", P_STRING|P_COMMA|P_NODUP|P_VI_DEF|P_VIM|P_CURSWANT, #ifdef FEAT_VIRTUALEDIT (char_u *)&p_ve, PV_NONE, {(char_u *)"", (char_u *)""} @@ -2740,7 +2746,7 @@ (char_u *)&p_wc, PV_NONE, {(char_u *)(long)Ctrl_E, (char_u *)(long)TAB} SCRIPTID_INIT}, - {"wildcharm", "wcm", P_NUM|P_VI_DEF, + {"wildcharm", "wcm", P_NUM|P_VI_DEF, (char_u *)&p_wcm, PV_NONE, {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, {"wildignore", "wig", P_STRING|P_VI_DEF|P_COMMA|P_NODUP, @@ -2750,6 +2756,9 @@ (char_u *)NULL, PV_NONE, #endif {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, + {"wildignorecase", "wic", P_BOOL|P_VI_DEF, + (char_u *)&p_wic, PV_NONE, + {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, {"wildmenu", "wmnu", P_BOOL|P_VI_DEF, #ifdef FEAT_WILDMENU (char_u *)&p_wmnu, PV_NONE, @@ -3145,7 +3154,7 @@ { #ifdef HAVE_AVAIL_MEM /* Use amount of memory available at this moment. */ - n = (mch_avail_mem(FALSE) >> 11); + n = (mch_avail_mem(FALSE) >> 1); #else # ifdef HAVE_TOTAL_MEM /* Use amount of memory available to Vim. */ @@ -3843,6 +3852,8 @@ # ifndef OS2 /* Always use bourne shell style redirection if we reach this */ if ( fnamecmp(p, "sh") == 0 || fnamecmp(p, "ksh") == 0 + || fnamecmp(p, "mksh") == 0 + || fnamecmp(p, "pdksh") == 0 || fnamecmp(p, "zsh") == 0 || fnamecmp(p, "zsh-beta") == 0 || fnamecmp(p, "bash") == 0 @@ -3850,6 +3861,8 @@ || fnamecmp(p, "cmd") == 0 || fnamecmp(p, "sh.exe") == 0 || fnamecmp(p, "ksh.exe") == 0 + || fnamecmp(p, "mksh.exe") == 0 + || fnamecmp(p, "pdksh.exe") == 0 || fnamecmp(p, "zsh.exe") == 0 || fnamecmp(p, "zsh-beta.exe") == 0 || fnamecmp(p, "bash.exe") == 0 @@ -3881,7 +3894,8 @@ #if defined(MSDOS) || defined(WIN3264) || defined(OS2) /* - * Set 'shellcmdflag and 'shellquote' depending on the 'shell' option. + * Set 'shellcmdflag', 'shellxquote', and 'shellquote' depending on the + * 'shell' option. * This is done after other initializations, where 'shell' might have been * set, but only if they have not been set before. Default for p_shcf is * "/c", for p_shq is "". For "sh" like shells it is changed here to @@ -3918,6 +3932,37 @@ # endif # endif } + else if (strstr((char *)gettail(p_sh), "cmd.exe") != NULL) + { + int idx3; + + /* + * cmd.exe on Windows will strip the first and last double quote given + * on the command line, e.g. most of the time things like: + * cmd /c "my path/to/echo" "my args to echo" + * become: + * my path/to/echo" "my args to echo + * when executed. + * + * To avoid this, set shellxquote to surround the command in + * parenthesis. This appears to make most commands work, without + * breaking commands that worked previously, such as + * '"path with spaces/cmd" "a&b"'. + */ + idx3 = findoption((char_u *)"sxq"); + if (idx3 >= 0 && !(options[idx3].flags & P_WAS_SET)) + { + p_sxq = (char_u *)"("; + options[idx3].def_val[VI_DEFAULT] = p_sxq; + } + + idx3 = findoption((char_u *)"shcf"); + if (idx3 >= 0 && !(options[idx3].flags & P_WAS_SET)) + { + p_shcf = (char_u *)"/c"; + options[idx3].def_val[VI_DEFAULT] = p_shcf; + } + } #endif #ifdef FEAT_TITLE @@ -4349,7 +4394,7 @@ p = find_termcode(key_name); if (p == NULL) { - errmsg = (char_u *)N_("E518: Unknown option"); + errmsg = (char_u *)N_("E846: Key code not set"); goto skip; } else @@ -4565,6 +4610,31 @@ arg = errbuf; } /* + * Convert 'backspace' number to string, for + * adding, prepending and removing string. + */ + else if (varp == (char_u *)&p_bs + && VIM_ISDIGIT(**(char_u **)varp)) + { + i = getdigits((char_u **)varp); + switch (i) + { + case 0: + *(char_u **)varp = empty_option; + break; + case 1: + *(char_u **)varp = vim_strsave( + (char_u *)"indent,eol"); + break; + case 2: + *(char_u **)varp = vim_strsave( + (char_u *)"indent,eol,start"); + break; + } + vim_free(oldval); + oldval = *(char_u **)varp; + } + /* * Convert 'whichwrap' number to string, for * backwards compatibility with Vim 3.0. * Misuse errbuf[] for the resulting string. @@ -4697,8 +4767,8 @@ || s[i] == ',' || s[i] == NUL)) break; - /* Count backspaces. Only a comma with an - * even number of backspaces before it is + /* Count backslashes. Only a comma with an + * even number of backslashes before it is * recognized as a separator */ if (s > origval && s[-1] == '\\') ++bs; @@ -5275,9 +5345,6 @@ #ifdef FEAT_AUTOCMD check_string_option(&buf->b_p_ft); #endif -#ifdef FEAT_OSFILETYPE - check_string_option(&buf->b_p_oft); -#endif #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT) check_string_option(&buf->b_p_cinw); #endif @@ -6635,7 +6702,7 @@ { for (s = *varp; *s;) { - while(*s == ',' || *s == ' ') + while (*s == ',' || *s == ' ') s++; if (!*s) break; @@ -6999,8 +7066,10 @@ } #endif - if (curwin->w_curswant != MAXCOL) - curwin->w_set_curswant = TRUE; /* in case 'showbreak' changed */ + if (curwin->w_curswant != MAXCOL + && (options[opt_idx].flags & (P_CURSWANT | P_RCLR)) != 0) + curwin->w_set_curswant = TRUE; + #ifdef FEAT_GUI /* check redraw when it's not a GUI option or the GUI is active. */ if (!redraw_gui_only || gui.in_use) @@ -7037,6 +7106,9 @@ int i; int j = 0; + if (wp->w_buffer == NULL) + return NULL; /* buffer was closed */ + for (s = wp->w_p_cc; *s != NUL && count < 255;) { if (*s == '-' || *s == '+') @@ -7304,8 +7376,9 @@ static char_u * check_clipboard_option() { - int new_unnamed = FALSE; - int new_autoselect = FALSE; + int new_unnamed = 0; + int new_autoselect_star = FALSE; + int new_autoselect_plus = FALSE; int new_autoselectml = FALSE; int new_html = FALSE; regprog_T *new_exclude_prog = NULL; @@ -7316,17 +7389,29 @@ { if (STRNCMP(p, "unnamed", 7) == 0 && (p[7] == ',' || p[7] == NUL)) { - new_unnamed = TRUE; + new_unnamed |= CLIP_UNNAMED; p += 7; } + else if (STRNCMP(p, "unnamedplus", 11) == 0 + && (p[11] == ',' || p[11] == NUL)) + { + new_unnamed |= CLIP_UNNAMED_PLUS; + p += 11; + } else if (STRNCMP(p, "autoselect", 10) == 0 - && (p[10] == ',' || p[10] == NUL)) + && (p[10] == ',' || p[10] == NUL)) { - new_autoselect = TRUE; + new_autoselect_star = TRUE; p += 10; } + else if (STRNCMP(p, "autoselectplus", 14) == 0 + && (p[14] == ',' || p[14] == NUL)) + { + new_autoselect_plus = TRUE; + p += 14; + } else if (STRNCMP(p, "autoselectml", 12) == 0 - && (p[12] == ',' || p[12] == NUL)) + && (p[12] == ',' || p[12] == NUL)) { new_autoselectml = TRUE; p += 12; @@ -7355,7 +7440,8 @@ if (errmsg == NULL) { clip_unnamed = new_unnamed; - clip_autoselect = new_autoselect; + clip_autoselect_star = new_autoselect_star; + clip_autoselect_plus = new_autoselect_plus; clip_autoselectml = new_autoselectml; clip_html = new_html; vim_free(clip_exclude_prog); @@ -7483,14 +7569,36 @@ compatible_set(); } +#ifdef FEAT_PERSISTENT_UNDO + /* 'undofile' */ + else if ((int *)varp == &curbuf->b_p_udf || (int *)varp == &p_udf) + { + char_u hash[UNDO_HASH_SIZE]; + buf_T *save_curbuf = curbuf; + + for (curbuf = firstbuf; curbuf != NULL; curbuf = curbuf->b_next) + { + /* When 'undofile' is set globally: for every buffer, otherwise + * only for the current buffer: Try to read in the undofile, if + * one exists and the buffer wasn't changed and the buffer was + * loaded. */ + if ((curbuf == save_curbuf + || (opt_flags & OPT_GLOBAL) || opt_flags == 0) + && !curbufIsChanged() && curbuf->b_ml.ml_mfp != NULL) + { + u_compute_hash(hash); + u_read_undo(NULL, hash, curbuf->b_fname); + } + } + curbuf = save_curbuf; + } +#endif + /* 'list', 'number' */ else if ((int *)varp == &curwin->w_p_list || (int *)varp == &curwin->w_p_nu || (int *)varp == &curwin->w_p_rnu) { - if (curwin->w_curswant != MAXCOL) - curwin->w_set_curswant = TRUE; - /* If 'number' is set, reset 'relativenumber'. */ /* If 'relativenumber' is set, reset 'number'. */ if ((int *)varp == &curwin->w_p_nu && curwin->w_p_nu) @@ -7735,8 +7843,6 @@ { if (curwin->w_p_wrap) curwin->w_leftcol = 0; - if (curwin->w_curswant != MAXCOL) - curwin->w_set_curswant = TRUE; } #ifdef FEAT_WINDOWS @@ -7763,9 +7869,9 @@ #ifdef FEAT_BEVAL else if ((int *)varp == &p_beval) { - if (p_beval == TRUE) + if (p_beval && !old_value) gui_mch_enable_beval_area(balloonEval); - else + else if (!p_beval && old_value) gui_mch_disable_beval_area(balloonEval); } #endif @@ -7798,6 +7904,10 @@ /* Only de-activate it here, it will be enabled when changing mode. */ if (p_imdisable) im_set_active(FALSE); + else if (State & INSERT) + /* When the option is set from an autocommand, it may need to take + * effect right away. */ + im_set_active(curbuf->b_p_iminsert == B_IMODE_IM); } #endif @@ -7959,31 +8069,8 @@ curbuf->b_p_imsearch = B_IMODE_USE_INSERT; # endif } - if (curwin->w_curswant != MAXCOL) - curwin->w_set_curswant = TRUE; } - else if ((int *)varp == &p_arshape) - { - if (curwin->w_curswant != MAXCOL) - curwin->w_set_curswant = TRUE; - } -#endif - -#ifdef FEAT_LINEBREAK - if ((int *)varp == &curwin->w_p_lbr) - { - if (curwin->w_curswant != MAXCOL) - curwin->w_set_curswant = TRUE; - } -#endif - -#ifdef FEAT_RIGHTLEFT - if ((int *)varp == &curwin->w_p_rl) - { - if (curwin->w_curswant != MAXCOL) - curwin->w_set_curswant = TRUE; - } #endif /* @@ -7993,7 +8080,9 @@ options[opt_idx].flags |= P_WAS_SET; comp_col(); /* in case 'ruler' or 'showcmd' changed */ - + if (curwin->w_curswant != MAXCOL + && (options[opt_idx].flags & (P_CURSWANT | P_RCLR)) != 0) + curwin->w_set_curswant = TRUE; check_redraw(options[opt_idx].flags); return NULL; @@ -8508,8 +8597,9 @@ options[opt_idx].flags |= P_WAS_SET; comp_col(); /* in case 'columns' or 'ls' changed */ - if (curwin->w_curswant != MAXCOL) - curwin->w_set_curswant = TRUE; /* in case 'tabstop' changed */ + if (curwin->w_curswant != MAXCOL + && (options[opt_idx].flags & (P_CURSWANT | P_RCLR)) != 0) + curwin->w_set_curswant = TRUE; check_redraw(options[opt_idx].flags); return errmsg; @@ -8523,8 +8613,8 @@ long_u flags; { /* Careful: P_RCLR and P_RALL are a combination of other P_ flags */ - int clear = (flags & P_RCLR) == P_RCLR; - int all = ((flags & P_RALL) == P_RALL || clear); + int doclear = (flags & P_RCLR) == P_RCLR; + int all = ((flags & P_RALL) == P_RALL || doclear); #ifdef FEAT_WINDOWS if ((flags & P_RSTAT) || all) /* mark all status lines dirty */ @@ -8535,7 +8625,7 @@ changed_window_setting(); if (flags & P_RBUF) redraw_curbuf_later(NOT_VALID); - if (clear) + if (doclear) redraw_all_later(CLEAR); else if (all) redraw_all_later(NOT_VALID); @@ -9172,7 +9262,7 @@ int expand; { char_u *s; - char_u buf[MAXPATHL]; + char_u *buf; if (fprintf(fd, "%s %s=", cmd, name) < 0) return FAIL; @@ -9190,9 +9280,16 @@ } else if (expand) { + buf = alloc(MAXPATHL); + if (buf == NULL) + return FAIL; home_replace(NULL, *valuep, buf, MAXPATHL, FALSE); if (put_escstr(fd, buf, 2) == FAIL) + { + vim_free(buf); return FAIL; + } + vim_free(buf); } else if (put_escstr(fd, *valuep, 2) == FAIL) return FAIL; @@ -9645,9 +9742,6 @@ case PV_MA: return (char_u *)&(curbuf->b_p_ma); case PV_MOD: return (char_u *)&(curbuf->b_changed); case PV_NF: return (char_u *)&(curbuf->b_p_nf); -#ifdef FEAT_OSFILETYPE - case PV_OFT: return (char_u *)&(curbuf->b_p_oft); -#endif case PV_PI: return (char_u *)&(curbuf->b_p_pi); #ifdef FEAT_TEXTOBJ case PV_QE: return (char_u *)&(curbuf->b_p_qe); @@ -9756,6 +9850,9 @@ #ifdef FEAT_SCROLLBIND to->wo_scb = from->wo_scb; #endif +#ifdef FEAT_CURSORBIND + to->wo_crb = from->wo_crb; +#endif #ifdef FEAT_SPELL to->wo_spell = from->wo_spell; #endif @@ -9995,9 +10092,6 @@ /* Don't copy 'filetype', it must be detected */ buf->b_p_ft = empty_option; #endif -#ifdef FEAT_OSFILETYPE - buf->b_p_oft = vim_strsave(p_oft); -#endif buf->b_p_pi = p_pi; #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT) buf->b_p_cinw = vim_strsave(p_cinw); @@ -10011,7 +10105,7 @@ buf->b_p_smc = p_smc; #endif #ifdef FEAT_SPELL - buf->b_s.b_p_spc = vim_strsave(p_spf); + buf->b_s.b_p_spc = vim_strsave(p_spc); (void)compile_cap_prog(&buf->b_s); buf->b_s.b_p_spf = vim_strsave(p_spf); buf->b_s.b_p_spl = vim_strsave(p_spl); @@ -10877,7 +10971,8 @@ shortmess(x) int x; { - return ( vim_strchr(p_shm, x) != NULL + return p_shm != NULL && + ( vim_strchr(p_shm, x) != NULL || (vim_strchr(p_shm, 'a') != NULL && vim_strchr((char_u *)SHM_A, x) != NULL)); } @@ -11284,16 +11379,19 @@ * from when editing started (save_file_ff() called). * 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. + * When "ignore_empty" is true don't consider a new, empty buffer to be + * changed. */ int -file_ff_differs(buf) +file_ff_differs(buf, ignore_empty) buf_T *buf; + int ignore_empty; { /* 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) + if (ignore_empty + && (buf->b_flags & BF_NEW) && buf->b_ml.ml_line_count == 1 && *ml_get_buf(buf, (linenr_T)1, FALSE) == NUL) return FALSE; diff -Naur vim73.orig/src/option.h vim73/src/option.h --- vim73.orig/src/option.h 2010-07-25 14:15:02.000000000 +0000 +++ vim73/src/option.h 2012-07-20 20:31:18.070978324 +0000 @@ -33,7 +33,7 @@ # ifdef EBCDIC #define DFLT_EFM "%*[^ ] %*[^ ] %f:%l%*[ ]%m,%*[^\"]\"%f\"%*\\D%l: %m,\"%f\"%*\\D%l: %m,%f:%l:%c:%m,%f(%l):%m,%f:%l:%m,\"%f\"\\, line %l%*\\D%c%*[^ ] %m,%D%*\\a[%*\\d]: Entering directory `%f',%X%*\\a[%*\\d]: Leaving directory `%f',%DMaking %*\\a in %f,%f|%l| %m" # else -#define DFLT_EFM "%*[^\"]\"%f\"%*\\D%l: %m,\"%f\"%*\\D%l: %m,%-G%f:%l: (Each undeclared identifier is reported only once,%-G%f:%l: for each function it appears in.),%-GIn file included from %f:%l:%c,%-GIn file included from %f:%l,%-Gfrom %f:%l:%c,%-Gfrom %f:%l,%f:%l:%c:%m,%f(%l):%m,%f:%l:%m,\"%f\"\\, line %l%*\\D%c%*[^ ] %m,%D%*\\a[%*\\d]: Entering directory `%f',%X%*\\a[%*\\d]: Leaving directory `%f',%D%*\\a: Entering directory `%f',%X%*\\a: Leaving directory `%f',%DMaking %*\\a in %f,%f|%l| %m" +#define DFLT_EFM "%*[^\"]\"%f\"%*\\D%l: %m,\"%f\"%*\\D%l: %m,%-G%f:%l: (Each undeclared identifier is reported only once,%-G%f:%l: for each function it appears in.),%-GIn file included from %f:%l:%c:,%-GIn file included from %f:%l:%c\\,,%-GIn file included from %f:%l:%c,%-GIn file included from %f:%l,%-G%*[ ]from %f:%l:%c,%-G%*[ ]from %f:%l:,%-G%*[ ]from %f:%l\\,,%-G%*[ ]from %f:%l,%f:%l:%c:%m,%f(%l):%m,%f:%l:%m,\"%f\"\\, line %l%*\\D%c%*[^ ] %m,%D%*\\a[%*\\d]: Entering directory `%f',%X%*\\a[%*\\d]: Leaving directory `%f',%D%*\\a: Entering directory `%f',%X%*\\a: Leaving directory `%f',%DMaking %*\\a in %f,%f|%l| %m" # endif # endif # endif @@ -104,10 +104,11 @@ #define FO_ONE_LETTER '1' #define FO_WHITE_PAR 'w' /* trailing white space continues paragr. */ #define FO_AUTO 'a' /* automatic formatting */ +#define FO_REMOVE_COMS 'j' /* remove comment leaders when joining lines */ #define DFLT_FO_VI "vt" #define DFLT_FO_VIM "tcq" -#define FO_ALL "tcroq2vlb1mMBn,aw" /* for do_set() */ +#define FO_ALL "tcroq2vlb1mMBn,awj" /* for do_set() */ /* characters for the p_cpo option: */ #define CPO_ALTREAD 'a' /* ":read" sets alternate file name */ @@ -169,10 +170,12 @@ #define CPO_SUBPERCENT '/' /* % in :s string uses previous one */ #define CPO_BACKSL '\\' /* \ is not special in [] */ #define CPO_CHDIR '.' /* don't chdir if buffer is modified */ +#define CPO_SCOLON ';' /* using "," and ";" will skip over char if + * cursor would not move */ /* default values for Vim, Vi and POSIX */ #define CPO_VIM "aABceFs" -#define CPO_VI "aAbBcCdDeEfFgHiIjJkKlLmMnoOpPqrRsStuvwWxXyZ$!%*-+<>" -#define CPO_ALL "aAbBcCdDeEfFgHiIjJkKlLmMnoOpPqrRsStuvwWxXyZ$!%*-+<>#{|&/\\." +#define CPO_VI "aAbBcCdDeEfFgHiIjJkKlLmMnoOpPqrRsStuvwWxXyZ$!%*-+<>;" +#define CPO_ALL "aAbBcCdDeEfFgHiIjJkKlLmMnoOpPqrRsStuvwWxXyZ$!%*-+<>#{|&/\\.;" /* characters for p_ww option: */ #define WW_ALL "bshl<>[],~" @@ -226,6 +229,7 @@ #define GO_MENUS 'm' /* use menu bar */ #define GO_NOSYSMENU 'M' /* don't source system menu */ #define GO_POINTER 'p' /* pointer enter/leave callbacks */ +#define GO_ASELPLUS 'P' /* autoselectPlus */ #define GO_RIGHT 'r' /* use right scrollbar */ #define GO_VRIGHT 'R' /* right scrollbar with vert split */ #define GO_TEAROFF 't' /* add tear-off menu items */ @@ -391,6 +395,7 @@ EXTERN char_u *p_cpo; /* 'cpoptions' */ #ifdef FEAT_CSCOPE EXTERN char_u *p_csprg; /* 'cscopeprg' */ +EXTERN int p_csre; /* 'cscoperelative' */ # ifdef FEAT_QUICKFIX EXTERN char_u *p_csqf; /* 'cscopequickfix' */ # define CSQF_CMDS "sgdctefi" @@ -709,6 +714,7 @@ #endif EXTERN char_u *p_shq; /* 'shellquote' */ EXTERN char_u *p_sxq; /* 'shellxquote' */ +EXTERN char_u *p_sxe; /* 'shellxescape' */ EXTERN char_u *p_srr; /* 'shellredir' */ #ifdef AMIGA EXTERN long p_st; /* 'shelltype' */ @@ -816,7 +822,7 @@ EXTERN char_u *p_ttym; /* 'ttymouse' */ EXTERN unsigned ttym_flags; # ifdef IN_OPTION_C -static char *(p_ttym_values[]) = {"xterm", "xterm2", "dec", "netterm", "jsbterm", "pterm", NULL}; +static char *(p_ttym_values[]) = {"xterm", "xterm2", "dec", "netterm", "jsbterm", "pterm", "urxvt", NULL}; # endif # define TTYM_XTERM 0x01 # define TTYM_XTERM2 0x02 @@ -824,6 +830,7 @@ # define TTYM_NETTERM 0x08 # define TTYM_JSBTERM 0x10 # define TTYM_PTERM 0x20 +# define TTYM_URXVT 0x40 #endif EXTERN char_u *p_udir; /* 'undodir' */ EXTERN long p_ul; /* 'undolevels' */ @@ -854,7 +861,11 @@ # define VE_ONEMORE 8 #endif EXTERN long p_verbose; /* 'verbose' */ -EXTERN char_u *p_vfile; /* 'verbosefile' */ +#ifdef IN_OPTION_C +char_u *p_vfile = (char_u *)""; /* used before options are initialized */ +#else +extern char_u *p_vfile; /* 'verbosefile' */ +#endif EXTERN int p_warn; /* 'warn' */ #ifdef FEAT_CMDL_COMPL EXTERN char_u *p_wop; /* 'wildoptions' */ @@ -872,6 +883,7 @@ EXTERN char_u *p_ww; /* 'whichwrap' */ EXTERN long p_wc; /* 'wildchar' */ EXTERN long p_wcm; /* 'wildcharm' */ +EXTERN long p_wic; /* 'wildignorecase' */ EXTERN char_u *p_wim; /* 'wildmode' */ #ifdef FEAT_WILDMENU EXTERN int p_wmnu; /* 'wildmenu' */ @@ -979,9 +991,6 @@ , BV_MOD , BV_MPS , BV_NF -#ifdef FEAT_OSFILETYPE - , BV_OFT -#endif #ifdef FEAT_COMPL_FUNC , BV_OFU #endif diff -Naur vim73.orig/src/os_amiga.c vim73/src/os_amiga.c --- vim73.orig/src/os_amiga.c 2010-05-15 11:04:08.000000000 +0000 +++ vim73/src/os_amiga.c 2012-07-20 20:31:17.630978008 +0000 @@ -191,16 +191,16 @@ } /* - * Return amount of memory still available. + * Return amount of memory still available in Kbyte. */ long_u mch_avail_mem(special) int special; { #ifdef __amigaos4__ - return (long_u)AvailMem(MEMF_ANY); + return (long_u)AvailMem(MEMF_ANY) >> 10; #else - return (long_u)AvailMem(special ? (long)MEMF_CHIP : (long)MEMF_ANY); + return (long_u)(AvailMem(special ? (long)MEMF_CHIP : (long)MEMF_ANY)) >> 10; #endif } @@ -1022,7 +1022,7 @@ /* insure longword alignment */ #ifdef __amigaos4__ - if(!(id = AllocDosObject(DOS_INFODATA, 0))) + if (!(id = AllocDosObject(DOS_INFODATA, 0))) goto out; #else id = (struct InfoData *)(((long)id_a + 3L) & ~3L); diff -Naur vim73.orig/src/os_mac_conv.c vim73/src/os_mac_conv.c --- vim73.orig/src/os_mac_conv.c 2010-07-14 11:50:20.000000000 +0000 +++ vim73/src/os_mac_conv.c 2012-07-20 20:31:13.047641389 +0000 @@ -14,6 +14,8 @@ */ #define NO_X11_INCLUDES +#define BalloonEval int /* used in header files */ + #include "vim.h" #ifndef FEAT_GUI_MAC # include @@ -75,7 +77,7 @@ *unconvlenp = 0; cfstr = CFStringCreateWithBytes(NULL, ptr, len, from, 0); - if(cfstr == NULL) + if (cfstr == NULL) fprintf(stderr, "Encoding failed\n"); /* When conversion failed, try excluding bytes from the end, helps when * there is an incomplete byte sequence. Only do up to 6 bytes to avoid diff -Naur vim73.orig/src/os_macosx.m vim73/src/os_macosx.m --- vim73.orig/src/os_macosx.m 2010-08-15 10:56:50.000000000 +0000 +++ vim73/src/os_macosx.m 2012-07-20 20:31:11.617640360 +0000 @@ -15,6 +15,11 @@ Error: MACOS 9 is no longer supported in Vim 7 #endif +/* Avoid a conflict for the definition of Boolean between Mac header files and + * X11 header files. */ +#define NO_X11_INCLUDES +#define BalloonEval int /* used in header files */ + #include "vim.h" #import @@ -23,9 +28,9 @@ * Clipboard support for the console. * Don't include this when building the GUI version, the functions in * gui_mac.c are used then. TODO: remove those instead? - * But for MacVim we need these ones. + * But for MacVim we do need these ones. */ -#if defined(FEAT_CLIPBOARD) && (!defined(FEAT_GUI) || defined(FEAT_GUI_MACVIM)) +#if defined(FEAT_CLIPBOARD) && (!defined(FEAT_GUI_ENABLED) || defined(FEAT_GUI_MACVIM)) /* Used to identify clipboard data copied from Vim. */ @@ -60,7 +65,7 @@ NSString *bestType = [pb availableTypeFromArray:supportedTypes]; if (!bestType) goto releasepool; - int motion_type = MCHAR; + int motion_type = MAUTO; NSString *string = nil; if ([bestType isEqual:VimPboardType]) @@ -84,9 +89,7 @@ if (!string) { - /* Use NSStringPboardType. The motion type is set to line-wise if the - * string contains at least one EOL character, otherwise it is set to - * character-wise (block-wise is never used). + /* Use NSStringPboardType. The motion type is detected automatically. */ NSMutableString *mstring = [[pb stringForType:NSStringPboardType] mutableCopy]; @@ -103,19 +106,13 @@ options:0 range:range]; } - /* Scan for newline character to decide whether the string should be - * pasted line-wise or character-wise. - */ - motion_type = MCHAR; - if (0 < n || NSNotFound != [mstring rangeOfString:@"\n"].location) - motion_type = MLINE; - string = mstring; } + /* Default to MAUTO, uses MCHAR or MLINE depending on trailing NL. */ if (!(MCHAR == motion_type || MLINE == motion_type || MBLOCK == motion_type || MAUTO == motion_type)) - motion_type = MCHAR; + motion_type = MAUTO; char_u *str = (char_u*)[string UTF8String]; int len = [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; diff -Naur vim73.orig/src/os_msdos.c vim73/src/os_msdos.c --- vim73.orig/src/os_msdos.c 2010-05-15 11:04:07.000000000 +0000 +++ vim73/src/os_msdos.c 2012-07-20 20:31:17.634311344 +0000 @@ -21,7 +21,6 @@ * Some functions are also used for Win16 (MS-Windows 3.1). */ -#include "vimio.h" #include "vim.h" #include @@ -551,15 +550,15 @@ #endif /* - * Return amount of memory currently available. + * Return amount of memory currently available in Kbyte. */ long_u mch_avail_mem(int special) { #ifdef DJGPP - return _go32_dpmi_remaining_virtual_memory(); + return _go32_dpmi_remaining_virtual_memory() >> 10; #else - return coreleft(); + return coreleft() >> 10; #endif } @@ -2233,7 +2232,7 @@ void clip_mch_request_selection(VimClipboard *cbd) { - int type = MCHAR; + int type = MAUTO; char_u *pAllocated = NULL; char_u *pClipText = NULL; int clip_data_format = 0; @@ -2281,14 +2280,12 @@ { clip_data_format = CF_TEXT; pClipText = pAllocated; - type = (vim_strchr((char*)pClipText, '\r') != NULL) ? MLINE : MCHAR; } else if ((pAllocated = Win16GetClipboardData(CF_OEMTEXT)) != NULL) { clip_data_format = CF_OEMTEXT; pClipText = pAllocated; - type = (vim_strchr((char*)pClipText, '\r') != NULL) ? MLINE : MCHAR; } /* Did we get anything? */ diff -Naur vim73.orig/src/os_mswin.c vim73/src/os_mswin.c --- vim73.orig/src/os_mswin.c 2010-07-27 19:39:05.000000000 +0000 +++ vim73/src/os_mswin.c 2012-07-20 20:31:13.320974919 +0000 @@ -22,7 +22,6 @@ # endif #endif -#include "vimio.h" #include "vim.h" #ifdef WIN16 @@ -31,7 +30,6 @@ # include #endif #include -#include #include #include #include @@ -595,7 +593,7 @@ gui.starting ? (char_u *)_("Message") : #endif (char_u *)_("Error"), - p, (char_u *)_("&Ok"), 1, NULL); + p, (char_u *)_("&Ok"), 1, NULL, FALSE); break; } ga_clear(&error_ga); @@ -817,7 +815,11 @@ BOOL fRunTimeLinkSuccess = FALSE; // Get a handle to the DLL module. +# ifdef WIN16 hinstLib = LoadLibrary(libname); +# else + hinstLib = vimLoadLib(libname); +# endif // If the handle is valid, try to get the function address. if (hinstLib != NULL) @@ -1103,132 +1105,6 @@ return ret; } -#if defined(FEAT_MBYTE) || defined(PROTO) -/* - * Note: the following two functions are only guaranteed to work when using - * valid MS-Windows codepages or when iconv() is available. - */ - -/* - * Convert "str" from 'encoding' to UTF-16. - * Input in "str" with length "*lenp". When "lenp" is NULL, use strlen(). - * Output is returned as an allocated string. "*lenp" is set to the length of - * the result. A trailing NUL is always added. - * Returns NULL when out of memory. - */ - short_u * -enc_to_utf16(char_u *str, int *lenp) -{ - vimconv_T conv; - WCHAR *ret; - char_u *allocbuf = NULL; - int len_loc; - int length; - - if (lenp == NULL) - { - len_loc = (int)STRLEN(str) + 1; - lenp = &len_loc; - } - - if (enc_codepage > 0) - { - /* We can do any CP### -> UTF-16 in one pass, and we can do it - * without iconv() (convert_* may need iconv). */ - MultiByteToWideChar_alloc(enc_codepage, 0, str, *lenp, &ret, &length); - } - else - { - /* Use "latin1" by default, we might be called before we have p_enc - * set up. Convert to utf-8 first, works better with iconv(). Does - * nothing if 'encoding' is "utf-8". */ - conv.vc_type = CONV_NONE; - if (convert_setup(&conv, p_enc ? p_enc : (char_u *)"latin1", - (char_u *)"utf-8") == FAIL) - return NULL; - if (conv.vc_type != CONV_NONE) - { - str = allocbuf = string_convert(&conv, str, lenp); - if (str == NULL) - return NULL; - } - convert_setup(&conv, NULL, NULL); - - length = utf8_to_utf16(str, *lenp, NULL, NULL); - ret = (WCHAR *)alloc((unsigned)((length + 1) * sizeof(WCHAR))); - if (ret != NULL) - { - utf8_to_utf16(str, *lenp, (short_u *)ret, NULL); - ret[length] = 0; - } - - vim_free(allocbuf); - } - - *lenp = length; - return (short_u *)ret; -} - -/* - * Convert an UTF-16 string to 'encoding'. - * Input in "str" with length (counted in wide characters) "*lenp". When - * "lenp" is NULL, use wcslen(). - * Output is returned as an allocated string. If "*lenp" is not NULL it is - * set to the length of the result. - * Returns NULL when out of memory. - */ - char_u * -utf16_to_enc(short_u *str, int *lenp) -{ - vimconv_T conv; - char_u *utf8_str = NULL, *enc_str = NULL; - int len_loc; - - if (lenp == NULL) - { - len_loc = (int)wcslen(str) + 1; - lenp = &len_loc; - } - - if (enc_codepage > 0) - { - /* We can do any UTF-16 -> CP### in one pass. */ - int length; - - WideCharToMultiByte_alloc(enc_codepage, 0, str, *lenp, - (LPSTR *)&enc_str, &length, 0, 0); - *lenp = length; - return enc_str; - } - - /* Avoid allocating zero bytes, it generates an error message. */ - utf8_str = alloc(utf16_to_utf8(str, *lenp == 0 ? 1 : *lenp, NULL)); - if (utf8_str != NULL) - { - *lenp = utf16_to_utf8(str, *lenp, utf8_str); - - /* We might be called before we have p_enc set up. */ - conv.vc_type = CONV_NONE; - convert_setup(&conv, (char_u *)"utf-8", - p_enc? p_enc: (char_u *)"latin1"); - if (conv.vc_type == CONV_NONE) - { - /* p_enc is utf-8, so we're done. */ - enc_str = utf8_str; - } - else - { - enc_str = string_convert(&conv, utf8_str, lenp); - vim_free(utf8_str); - } - - convert_setup(&conv, NULL, NULL); - } - - return enc_str; -} -#endif /* FEAT_MBYTE */ - /* * Wait for another process to Close the Clipboard. * Returns TRUE for success. @@ -1408,9 +1284,9 @@ { char_u *temp_clipboard; - /* If the type is not known guess it. */ + /* If the type is not known detect it. */ if (metadata.type == -1) - metadata.type = (vim_strchr(str, '\n') == NULL) ? MCHAR : MLINE; + metadata.type = MAUTO; /* Translate into . */ temp_clipboard = crnl_to_nl(str, &str_size); @@ -1434,32 +1310,6 @@ #endif } -#if (defined(FEAT_MBYTE) && defined(WIN3264)) || defined(PROTO) -/* - * Convert from the active codepage to 'encoding'. - * Input is "str[str_size]". - * The result is in allocated memory: "out[outlen]". With terminating NUL. - */ - void -acp_to_enc(str, str_size, out, outlen) - char_u *str; - int str_size; - char_u **out; - int *outlen; - -{ - LPWSTR widestr; - - MultiByteToWideChar_alloc(GetACP(), 0, str, str_size, &widestr, outlen); - if (widestr != NULL) - { - ++*outlen; /* Include the 0 after the string */ - *out = utf16_to_enc((short_u *)widestr, outlen); - vim_free(widestr); - } -} -#endif - /* * Send the current selection to the clipboard. */ @@ -1624,6 +1474,158 @@ #endif /* FEAT_CLIPBOARD */ +#if defined(FEAT_MBYTE) || defined(PROTO) +/* + * Note: the following two functions are only guaranteed to work when using + * valid MS-Windows codepages or when iconv() is available. + */ + +/* + * Convert "str" from 'encoding' to UTF-16. + * Input in "str" with length "*lenp". When "lenp" is NULL, use strlen(). + * Output is returned as an allocated string. "*lenp" is set to the length of + * the result. A trailing NUL is always added. + * Returns NULL when out of memory. + */ + short_u * +enc_to_utf16(char_u *str, int *lenp) +{ + vimconv_T conv; + WCHAR *ret; + char_u *allocbuf = NULL; + int len_loc; + int length; + + if (lenp == NULL) + { + len_loc = (int)STRLEN(str) + 1; + lenp = &len_loc; + } + + if (enc_codepage > 0) + { + /* We can do any CP### -> UTF-16 in one pass, and we can do it + * without iconv() (convert_* may need iconv). */ + MultiByteToWideChar_alloc(enc_codepage, 0, str, *lenp, &ret, &length); + } + else + { + /* Use "latin1" by default, we might be called before we have p_enc + * set up. Convert to utf-8 first, works better with iconv(). Does + * nothing if 'encoding' is "utf-8". */ + conv.vc_type = CONV_NONE; + if (convert_setup(&conv, p_enc ? p_enc : (char_u *)"latin1", + (char_u *)"utf-8") == FAIL) + return NULL; + if (conv.vc_type != CONV_NONE) + { + str = allocbuf = string_convert(&conv, str, lenp); + if (str == NULL) + return NULL; + } + convert_setup(&conv, NULL, NULL); + + length = utf8_to_utf16(str, *lenp, NULL, NULL); + ret = (WCHAR *)alloc((unsigned)((length + 1) * sizeof(WCHAR))); + if (ret != NULL) + { + utf8_to_utf16(str, *lenp, (short_u *)ret, NULL); + ret[length] = 0; + } + + vim_free(allocbuf); + } + + *lenp = length; + return (short_u *)ret; +} + +/* + * Convert an UTF-16 string to 'encoding'. + * Input in "str" with length (counted in wide characters) "*lenp". When + * "lenp" is NULL, use wcslen(). + * Output is returned as an allocated string. If "*lenp" is not NULL it is + * set to the length of the result. + * Returns NULL when out of memory. + */ + char_u * +utf16_to_enc(short_u *str, int *lenp) +{ + vimconv_T conv; + char_u *utf8_str = NULL, *enc_str = NULL; + int len_loc; + + if (lenp == NULL) + { + len_loc = (int)wcslen(str) + 1; + lenp = &len_loc; + } + + if (enc_codepage > 0) + { + /* We can do any UTF-16 -> CP### in one pass. */ + int length; + + WideCharToMultiByte_alloc(enc_codepage, 0, str, *lenp, + (LPSTR *)&enc_str, &length, 0, 0); + *lenp = length; + return enc_str; + } + + /* Avoid allocating zero bytes, it generates an error message. */ + utf8_str = alloc(utf16_to_utf8(str, *lenp == 0 ? 1 : *lenp, NULL)); + if (utf8_str != NULL) + { + *lenp = utf16_to_utf8(str, *lenp, utf8_str); + + /* We might be called before we have p_enc set up. */ + conv.vc_type = CONV_NONE; + convert_setup(&conv, (char_u *)"utf-8", + p_enc? p_enc: (char_u *)"latin1"); + if (conv.vc_type == CONV_NONE) + { + /* p_enc is utf-8, so we're done. */ + enc_str = utf8_str; + } + else + { + enc_str = string_convert(&conv, utf8_str, lenp); + vim_free(utf8_str); + } + + convert_setup(&conv, NULL, NULL); + } + + return enc_str; +} +#endif /* FEAT_MBYTE */ + +#if (defined(FEAT_MBYTE) && defined(WIN3264)) || defined(PROTO) +/* + * Convert from the active codepage to 'encoding'. + * Input is "str[str_size]". + * The result is in allocated memory: "out[outlen]". With terminating NUL. + */ + void +acp_to_enc(str, str_size, out, outlen) + char_u *str; + int str_size; + char_u **out; + int *outlen; + +{ + LPWSTR widestr; + + MultiByteToWideChar_alloc(GetACP(), 0, str, str_size, &widestr, outlen); + if (widestr != NULL) + { + ++*outlen; /* Include the 0 after the string */ + *out = utf16_to_enc((short_u *)widestr, outlen); + vim_free(widestr); + } +} +#endif + /* * Debugging helper: expose the MCH_WRITE_DUMP stuff to other modules @@ -1779,7 +1781,7 @@ } /* Attempt to make this work for old and new compilers */ -#if !defined(_MSC_VER) || (_MSC_VER < 1300) || !defined(INT_PTR) +#if !defined(_WIN64) && (!defined(_MSC_VER) || _MSC_VER < 1300) # define PDP_RETVAL BOOL #else # define PDP_RETVAL INT_PTR @@ -1854,12 +1856,12 @@ { MSG msg; - while (!*bUserAbort && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + while (!*bUserAbort && pPeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { - if (!hDlgPrint || !IsDialogMessage(hDlgPrint, &msg)) + if (!hDlgPrint || !pIsDialogMessage(hDlgPrint, &msg)) { TranslateMessage(&msg); - DispatchMessage(&msg); + pDispatchMessage(&msg); } } return !*bUserAbort; @@ -1867,7 +1869,7 @@ #ifndef FEAT_GUI - static UINT CALLBACK + static UINT_PTR CALLBACK PrintHookProc( HWND hDlg, // handle to dialog box UINT uiMsg, // message identifier @@ -3130,10 +3132,10 @@ { MSG msg; - while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + while (pPeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); - DispatchMessage(&msg); + pDispatchMessage(&msg); } } diff -Naur vim73.orig/src/os_qnx.c vim73/src/os_qnx.c --- vim73.orig/src/os_qnx.c 2010-05-24 09:42:44.000000000 +0000 +++ vim73/src/os_qnx.c 2012-07-20 20:31:12.814307887 +0000 @@ -24,10 +24,10 @@ #if defined(FEAT_GUI_PHOTON) PhChannelParms_t parms; - memset( &parms, 0, sizeof( parms ) ); + memset(&parms, 0, sizeof(parms)); parms.flags = Ph_DYNAMIC_BUFFER; - is_photon_available = (PhAttach( NULL, &parms ) != NULL) ? TRUE : FALSE; + is_photon_available = (PhAttach(NULL, &parms) != NULL) ? TRUE : FALSE; #endif } @@ -39,8 +39,8 @@ /* Turn on the clipboard for a console vim when photon is running */ void qnx_clip_init() { - if( is_photon_available == TRUE && !gui.in_use) - clip_init( TRUE ); + if (is_photon_available == TRUE && !gui.in_use) + clip_init(TRUE); } /*****************************************************************************/ @@ -48,32 +48,32 @@ /* No support for owning the clipboard */ int -clip_mch_own_selection( VimClipboard *cbd ) +clip_mch_own_selection(VimClipboard *cbd) { return FALSE; } void -clip_mch_lose_selection( VimClipboard *cbd ) +clip_mch_lose_selection(VimClipboard *cbd) { } void -clip_mch_request_selection( VimClipboard *cbd ) +clip_mch_request_selection(VimClipboard *cbd) { int type = MLINE, clip_length = 0, is_type_set = FALSE; void *cbdata; PhClipHeader *clip_header; char_u *clip_text = NULL; - cbdata = PhClipboardPasteStart( PhInputGroup( NULL )); - if( cbdata != NULL ) + cbdata = PhClipboardPasteStart(PhInputGroup(NULL)); + if (cbdata != NULL) { /* Look for the vim specific clip first */ - clip_header = PhClipboardPasteType( cbdata, CLIP_TYPE_VIM ); - if( clip_header != NULL && clip_header->data != NULL ) + clip_header = PhClipboardPasteType(cbdata, CLIP_TYPE_VIM); + if (clip_header != NULL && clip_header->data != NULL) { - switch( *(char *) clip_header->data ) + switch(*(char *) clip_header->data) { default: /* fallthrough to line type */ case 'L': type = MLINE; break; @@ -86,27 +86,27 @@ } /* Try for just normal text */ - clip_header = PhClipboardPasteType( cbdata, CLIP_TYPE_TEXT ); - if( clip_header != NULL ) + clip_header = PhClipboardPasteType(cbdata, CLIP_TYPE_TEXT); + if (clip_header != NULL) { clip_text = clip_header->data; clip_length = clip_header->length - 1; - if( clip_text != NULL && is_type_set == FALSE ) - type = (strchr( clip_text, '\r' ) != NULL) ? MLINE : MCHAR; + if (clip_text != NULL && is_type_set == FALSE) + type = MAUTO; } - if( (clip_text != NULL) && (clip_length > 0) ) + if ((clip_text != NULL) && (clip_length > 0)) { - clip_yank_selection( type, clip_text, clip_length, cbd ); + clip_yank_selection(type, clip_text, clip_length, cbd); } - PhClipboardPasteFinish( cbdata ); + PhClipboardPasteFinish(cbdata); } } void -clip_mch_set_selection( VimClipboard *cbd ) +clip_mch_set_selection(VimClipboard *cbd) { int type; long_u len; @@ -114,31 +114,31 @@ PhClipHeader clip_header[2]; /* Prevent recursion from clip_get_selection() */ - if( cbd->owned == TRUE ) + if (cbd->owned == TRUE) return; cbd->owned = TRUE; - clip_get_selection( cbd ); + clip_get_selection(cbd); cbd->owned = FALSE; - type = clip_convert_selection( &str, &len, cbd ); - if( type >= 0 ) + type = clip_convert_selection(&str, &len, cbd); + if (type >= 0) { - text_clip = lalloc( len + 1, TRUE ); /* Normal text */ + text_clip = lalloc(len + 1, TRUE); /* Normal text */ - if( text_clip && vim_clip ) + if (text_clip && vim_clip) { - memset( clip_header, 0, sizeof( clip_header ) ); + memset(clip_header, 0, sizeof(clip_header)); - STRNCPY( clip_header[0].type, CLIP_TYPE_VIM, 8 ); - clip_header[0].length = sizeof( vim_clip ); + STRNCPY(clip_header[0].type, CLIP_TYPE_VIM, 8); + clip_header[0].length = sizeof(vim_clip); clip_header[0].data = vim_clip; - STRNCPY( clip_header[1].type, CLIP_TYPE_TEXT, 8 ); + STRNCPY(clip_header[1].type, CLIP_TYPE_TEXT, 8); clip_header[1].length = len + 1; clip_header[1].data = text_clip; - switch( type ) + switch(type) { default: /* fallthrough to MLINE */ case MLINE: *vim_clip = 'L'; break; @@ -148,14 +148,14 @@ #endif } - vim_strncpy( text_clip, str, len ); + vim_strncpy(text_clip, str, len); vim_clip[ 1 ] = NUL; - PhClipboardCopy( PhInputGroup( NULL ), 2, clip_header); + PhClipboardCopy(PhInputGroup(NULL), 2, clip_header); } - vim_free( text_clip ); + vim_free(text_clip); } - vim_free( str ); + vim_free(str); } #endif diff -Naur vim73.orig/src/os_riscos.c vim73/src/os_riscos.c --- vim73.orig/src/os_riscos.c 2010-05-15 11:04:08.000000000 +0000 +++ vim73/src/os_riscos.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1292 +0,0 @@ -/* vi:set ts=8 sts=4 sw=4: - * - * VIM - Vi IMproved by Bram Moolenaar - * - * Do ":help uganda" in Vim to read copying and usage conditions. - * Do ":help credits" in Vim to see a list of people who contributed. - * See README.txt for an overview of the Vim source code. - */ - -#include "vim.h" - -/* - * os_riscos.c - * - * Thomas Leonard - */ - -const char *__dynamic_da_name = "Vim heap"; /* Enable and name our dynamic area */ -int ro_line_mode = TRUE; /* For Ex mode we much echo chars to the screen ourselves */ -int windowed; /* Flag - are we running inside a text window? */ -int WinLeft, WinTop; /* We might be started inside a text window */ -int ScrollTop; /* Make cursor movements relative to ScrollTop. */ - -int old_escape_state = -1; -int old_cursor_state = -1; - -#define rgb(r,g,b) ((b<<24) + (g<<16) + (r<<8)) -#define NORMAL_FG 0x00000000 -#define NORMAL_BG 0xffffffff - -/* Convert a DOS colour number to an RGB palette entry. - * Mappings from X11 rgb/txt file. - */ - static int -map_colour(dos) - int dos; /* Standard DOS colour number. */ -{ - switch (dos) - { - case 0: return 0; /* Black */ - case 1: return rgb(0,0,139); /* DarkBlue */ - case 2: return rgb(0,100,0); /* DarkGreen */ - case 3: return rgb(0,139,139); /* DarkCyan */ - case 4: return rgb(139,0,0); /* DarkRed */ - case 5: return rgb(139,0,139); /* DarkMagenta */ - case 6: return rgb(165,42,42); /* Brown, DarkYellow */ - case 7: return rgb(211,211,211); /* LightGray, LightGrey, Gray, Grey */ - case 8: return rgb(169,169,169); /* DarkGray, DarkGrey */ - case 9: return rgb(173,216,230); /* Blue, LightBlue */ - case 10: return rgb(144,238,144); /* Green, LightGreen */ - case 11: return rgb(224,255,255); /* Cyan, LightCyan */ - case 12: return rgb(255,0,0); /* Red, LightRed */ - case 13: return rgb(255,0,255); /* Magenta, LightMagenta */ - case 14: return rgb(255,255,0); /* Yellow, LightYellow */ - case 15: return rgb(255,255,255); /* White */ - } - return rgb(100,100,100); -} - - static void -text_fg(fg) - int fg; /* Foregound colour in the form &BBGGRR00 */ -{ - xswi(ColourTrans_SetTextColour, fg, 0, 0, 0); -} - - static void -text_bg(bg) - int bg; /* Backgound colour in the form &BBGGRR00 */ -{ - xswi(ColourTrans_SetTextColour, bg, 0, 0, 1 << 7); -} - -#define OUT_NORMAL 0 -#define OUT_NUMBER 1 /* Reading in a number */ - - void -mch_write(s, len) - char_u *s; - int len; -{ - static int mode = OUT_NORMAL; - static int x, y; /* For reading numbers in. */ - - if (!term_console) - { - /* Maybe we are running Vim remotely - don't interpret chars */ - while (len--) - { - char_u c = *s++; - swi(OS_WriteC, c); - /* We might need to send a CR too. This shouldn't - * hurt if we don't need it, should it? - */ - if (c == 10) - swi(OS_WriteI + 13); - } - return; - } - - while (len--) - { - char_u c = *s++; - switch (mode) - { - case OUT_NUMBER: - if (c < '0' || c > '9') - { - mode = OUT_NORMAL; - } - else - { - x = (x * 10) + c - '0'; - continue; - } - /* note: no break here! */ - - case OUT_NORMAL: - switch (c) - { - case 1: - /* Number (in decimal) follows. */ - mode = OUT_NUMBER; - y = x; - x = 0; - break; - case 2: - /* Position cursor. */ - swi(OS_WriteI + 31); - swi(OS_WriteC, x); - swi(OS_WriteC, y - ScrollTop); - break; - case 3: - /* Set scroll region. */ - if (x == Rows -1 && y == 0 && !windowed) - { - /* Whole screen - remove text window. - * This is MUCH faster. - */ - swi(OS_WriteI + 26); - } - else - { - /* Create a text window. */ - swi(OS_WriteI + 28); - swi(OS_WriteC, WinLeft); - swi(OS_WriteC, WinTop + x); - swi(OS_WriteC, WinLeft + Columns - 1); - swi(OS_WriteC, WinTop + y); - } - ScrollTop = y; - break; - case 4: - /* Normal mode. */ - text_fg(NORMAL_FG); - text_bg(NORMAL_BG); - break; - case 5: - /* Reverse mode. */ - text_fg(NORMAL_BG); - text_bg(NORMAL_FG); - break; - case 10: - swi(OS_NewLine); - break; - case 14: - /* Cursor invisible. */ - swi(OS_WriteN, - "\027\001\000\000\000\000\000\000\000\000", - 10); - break; - case 15: - /* Cursor visible. */ - swi(OS_WriteN, - "\027\001\002\000\000\000\000\000\000\000", - 10); - break; - case 16: - /* Cursor very visible (flash) */ - swi(OS_WriteN, - "\027\001\003\000\000\000\000\000\000\000", - 10); - case 17: - /* Set foreground colour. */ - text_fg(map_colour(x)); - break; - case 18: - /* Set background colour. */ - text_bg(map_colour(x)); - break; - case 19: - /* Scroll text down. */ - swi(OS_WriteN, - "\027\007\000\002\000\000\000\000\000\000", - 10); - break; - default: - swi(OS_WriteC, c); - } - continue; - - default: - printf("[output error]"); - mode = OUT_NORMAL; - } - } -} - -/* - * mch_inchar(): low level input funcion. - * Get a characters from the keyboard. - * Return the number of characters that are available. - * If wtime == 0 do not wait for characters. - * If wtime == n wait n msecs for characters. - * If wtime == -1 wait forever for characters. - * - * TODO: call convert_input() for 'fileencoding' to 'encoding' conversion. - */ - int -mch_inchar(buf, maxlen, wtime, tb_change_cnt) - char_u *buf; - int maxlen; - long wtime; - int tb_change_cnt; -{ - int got=0; - unsigned int start_time = clock(); - - if (ro_line_mode) - { - /* We're probably in Ex mode - get whole lines at a time. */ - - static char_u line_buffer[256]; - static int remaining_chars = 0; - static int buf_pos = 0; - - /* Do we need to fetch another line? */ - if (remaining_chars == 0) - { - int old_esc_state; - swi(OS_Byte, 200, 1, 0xfe); - old_esc_state = r1; - - buf_pos = 0; - if (xswi(OS_ReadLine, line_buffer, 255, 0, 255) & (c_flag | v_flag)) - { - got_int = TRUE; /* ESC pressed */ - r1 = 0; - } - line_buffer[r1] = 13; - remaining_chars = r1 + 1; /* Count CR as part of input */ - - swi(OS_Byte, 200, old_esc_state, 0); - } - - /* Can we send the rest of the buffer back in one go? */ - if (remaining_chars <= maxlen) - { - int got = remaining_chars; - - memcpy(buf, line_buffer + buf_pos, got); - remaining_chars = 0; - return got; - } - - /* Send as much as we can */ - memcpy(buf, line_buffer + buf_pos, maxlen); - buf_pos += maxlen; - remaining_chars -= maxlen; - - return maxlen; - } - - if (!term_console) - { - /* Use OS_ReadC for all input. - * Avoids problems with remote access getting interference from - * the keyboard. - */ - if (wtime == 0) - return 0; /* Ignore quick key checks */ - - if (xswi(OS_ReadC) & c_flag) - { - got_int = TRUE; /* ESC pressed - can this happen? */ - swi(OS_Byte, 124); /* Clear Escape state */ - r0 = 0x1b; /* It *might* not have been Escape! */ - } - buf[0] = r0; - return 1; - } - - /* - * OK, here's the plan: - * - * 1) Wait until wtime expires or we get a key - * 2) Get keys until the keyboard buffer is empty or buf is full - */ - - while (xswi(OS_Byte,145,0) & c_flag) - { - /* Nothing at all in the keyboard buffer. - * Has our time expired yet? - */ - if ( (wtime != -1) && (clock() - start_time) >= wtime ) - return 0; /* Nothing read - giving up */ - } - - /* We've got one char (in r2) - are there any more? */ - - while (got < maxlen) - { - buf[got++] = r2; - - if (xswi(OS_Byte,145,0) & c_flag) - return got; /* Keyboard buffer empty */ - } - return got; /* buf is full */ -} - -/* - * return non-zero if a character is available - */ - int -mch_char_avail() -{ - if (!term_console) - return 0; /* Can't tell */ - if (xswi(OS_Byte, 152, 0) & c_flag) - return 0; - return 1; -} - -/* Find out how much free memory we have. - * I don't know how to work this out exactly but, since we can claim - * more memory from the OS, let's just report the free pool size. - * Dynamic area 6 doesn't exist pre 3.6 according to StrongHelp, so - * we'll use Wimp_SlotSize. If that fails (outside the desktop?) - * then just return a big number and hope. - */ - long_u -mch_avail_mem(special) - int special; -{ - if (xswi(Wimp_SlotSize, -1, -1) & v_flag) - return 0x7fffffff; - return r2; -} - - void -mch_delay(msec, ignoreinput) - long msec; - int ignoreinput; -{ - int start_time, time_now; - int csec = msec / 10; - - swi(OS_ReadMonotonicTime); - start_time = r0; - - for (;;) - { - swi(OS_ReadMonotonicTime); - time_now = r0; - if (time_now - start_time > csec) - return; -#ifdef FEAT_GUI - /* In the GUI, allow other programs to run while waiting. */ - if (gui.in_use) - gui_mch_wait_for_chars(start_time + csec); -#endif - } -} - -/* - * If the machine has job control, use it to suspend the program, - * otherwise fake it by starting a new shell. - */ - void -mch_suspend() -{ - suspend_shell(); -} - - void -mch_init() -{ - /* - * Read window size first. Calls to mch_get_shellsize() will - * simply return these values in future so that setting the - * text window (used for scrolling) won't give strange results. - */ - - int buf[7] = {132, 135, 256, 257, 1, 2, -1}; - - /* Command windows are no longer forced open, since if we are - * in the desktop then we'll use the GUI version. - * Opening a command window here messes up the GUI version startup - */ -#ifndef FEAT_GUI - swi(OS_WriteI); -#endif - swi(OS_ReadVduVariables, buf, buf); - WinLeft = buf[0]; - WinTop = buf[1]; - Columns = buf[2]; - Rows = buf[3] + 1; /* Seems to be one off (VduVars wrong?) */ - ScrollTop = 0; - - /* Are we running in a textwindow? */ - if (Rows == buf[5] + 1 && Columns == buf[4] + 1) - windowed = 0; - else - windowed = 1; - - /* Choose a nice colour scheme. */ - text_fg(NORMAL_FG); - text_bg(NORMAL_BG); -} - -/* - * Check_win checks whether we have an interactive stdout. - */ -/* ARGSUSED */ - int -mch_check_win(argc, argv) - int argc; - char **argv; -{ - return OK; -} - -/* - * Return TRUE if the input comes from a terminal, FALSE otherwise. - */ - int -mch_input_isatty() -{ - if (xswi(OS_ChangeRedirection, -1, -1) & v_flag) - return TRUE; /* Error - TRUE is probably correct though */ - if (r0 == 0) - return TRUE; - return FALSE; -} - -#ifdef FEAT_TITLE - int -mch_can_restore_title() -{ - return FALSE; -} - - int -mch_can_restore_icon() -{ - return FALSE; -} - - -/* - * Set the window title and icon. - */ - void -mch_settitle(title, icon) - char_u *title; - char_u *icon; -{ - if (title == NULL) - title = (char_u *) ""; -#ifdef FEAT_GUI - if (gui.in_use && strcmp(title, gui.window_title)) - { - int length; - length = strlen(title); - if (length >= gui.window_title_size) - length = gui.window_title_size - 1; - strncpy(gui.window_title, title, length); - gui.window_title[length] = 0; - ro_redraw_title(gui.window_handle); - } -#endif - return; -} - -/* - * Restore the window/icon title. - * "which" is one of: - * 1 only restore title - * 2 only restore icon - * 3 restore title and icon - */ - void -mch_restore_title(which) - int which; -{ - return; -} -#endif - -/* - * Insert user name in s[len]. - * Return OK if a name found. - */ - int -mch_get_user_name(s, len) - char_u *s; - int len; -{ - /* RISC OS doesn't support user names. */ - *s = NUL; - return FAIL; -} - -/* - * Insert host name in s[len]. - */ - - void -mch_get_host_name(s, len) - char_u *s; - int len; -{ - if (xswi(OS_ReadVarVal, "Machine$Name", s, len, 0, 3) & v_flag) - { - /* Variable does not exist (normal operation) */ - vim_strncpy(s, "(unknown)", len - 1); - } -} - -/* - * return process ID - */ - long -mch_get_pid() -{ - if (xswi(Wimp_ReadSysInfo, 5) & v_flag) - return 0; - return r0; -} - -/* - * Get name of current directory into buffer 'buf' of length 'len' bytes. - * Return OK for success, FAIL for failure. - */ - int -mch_dirname(buf, len) - char_u *buf; - int len; -{ - if (xswi(OS_FSControl, 37, "@", buf, 0, 0, len) & v_flag) - return FAIL; - return OK; -} - -/* - * Get absolute file name into buffer 'buf' of length 'len' bytes. - * - * return FAIL for failure, OK for success - */ - int -mch_FullName(fname, buf, len, force) - char_u *fname, *buf; - int len; - int force; /* Also expand when already absolute path name. - * Not used under RISC OS. - */ -{ - if (xswi(OS_FSControl, 37, fname, buf, 0, 0, len) & v_flag) - return FAIL; - return OK; -} - -/* - * Return TRUE if "fname" does not depend on the current directory. - */ - int -mch_isFullName(fname) - char_u *fname; -{ - if (strstr(fname, "::") && strstr(fname,".$.")) - return TRUE; - return FALSE; -} - -/* - * Get file permissions for 'name'. - * Returns -1 when it doesn't exist. - */ - long -mch_getperm(name) - char_u *name; -{ - struct stat statb; - - if (stat((char *)name, &statb)) - return -1; - return statb.st_mode; -} - -/* - * set file permission for 'name' to 'perm' - * - * return FAIL for failure, OK otherwise - */ - int -mch_setperm(name, perm) - char_u *name; - long perm; -{ - return (chmod((char *)name, (mode_t)perm) == 0 ? OK : FAIL); -} - -/* - * Set hidden flag for "name". - */ -/* ARGSUSED */ - void -mch_hide(name) - char_u *name; -{ - /* can't hide a file */ -} - -/* - * return TRUE if "name" is a directory - * return FALSE if "name" is not a directory - * return FALSE for error - */ - int -mch_isdir(name) - char_u *name; -{ - if (xswi(OS_File, 17, name) & v_flag) - return FALSE; - if (r0 == 2 || r0 == 3) - return TRUE; /* Count image files as directories. */ - return FALSE; -} - -/* - * Return 1 if "name" can be executed, 0 if not. - * Return -1 if unknown. Requires which to work. - */ - int -mch_can_exe(name) - char_u *name; -{ - char_u *buf; - char_u *p; - int retval; - - buf = alloc((unsigned)STRLEN(name) + 7); - if (buf == NULL) - return -1; - sprintf((char *)buf, "which %s", name); - p = get_cmd_output(buf, NULL, SHELL_SILENT); - vim_free(buf); - if (p == NULL) - return -1; - /* result can be: "name: Command not found" */ - retval = (*p != NUL && strstr((char *)p, "not found") == NULL); - vim_free(p); - return retval; -} - -/* - * Check what "name" is: - * NODE_NORMAL: file or directory (or doesn't exist) - * NODE_WRITABLE: writable device, socket, fifo, etc. - * NODE_OTHER: non-writable things - */ - int -mch_nodetype(name) - char_u *name; -{ - /* TODO */ - return NODE_NORMAL; -} - - void -mch_early_init() -{ - /* Turn off all the horrible filename munging in UnixLib. */ - int __riscosify_control = __RISCOSIFY_NO_PROCESS; -} - - void -mch_exit(r) - int r; -{ - settmode(TMODE_COOK); - exiting = TRUE; - out_flush(); - ml_close_all(TRUE); /* remove all memfiles */ - -#ifdef FEAT_GUI - if (gui.in_use) - gui_exit(r); -#endif - swi(OS_NewLine); - if (old_escape_state != -1) - swi(OS_Byte, 229, old_escape_state, 0); - if (old_cursor_state != -1) - swi(OS_Byte, 4, old_cursor_state); - exit(r); -} - - void -mch_settmode(tmode) - int tmode; /* TMODE_RAW or TMODE_COOK */ -{ - if (tmode == TMODE_COOK) - { - ro_line_mode = TRUE; - return; - } - - ro_line_mode = FALSE; - - if (term_console) - { - /* Block cursor. */ - swi(OS_WriteN, - "\027\000\012\000\000\000\000\000\000\000", - 10); - - /* Disable the standard cursor key actions. */ - swi(OS_Byte, 4, 1); - if (old_cursor_state == -1) - old_cursor_state = r1; - } - - /* Stop Escape from quitting Vim! */ - swi(OS_Byte, 229, 1, 0); - if (old_escape_state == -1) - old_escape_state = r1; -} - -/* - * set mouse clicks on or off (only works for xterms) - */ - void -mch_setmouse(on) - int on; -{ -} - -/* - * set screen mode, always fails. - */ -/* ARGSUSED */ - int -mch_screenmode(arg) - char_u *arg; -{ - EMSG(_(e_screenmode)); - return FAIL; -} - -/* - * Try to get the current window size. - * Return OK when size could be determined, FAIL otherwise. - * Simply return results stored by mch_init() if we are the - * machine's console. If not, we don't know how big the screen is. - */ - int -mch_get_shellsize() -{ - /* if size changed: screenalloc will allocate new screen buffers */ - return term_console ? OK : FAIL; -} - -/* - * Can't change the size. - * Assume the user knows what he's doing and use the new values. - */ - void -mch_set_shellsize() -{ - /* Assume the user knows what he's doing and use the new values. */ -} - -/* - * Rows and/or Columns has changed. - */ - void -mch_new_shellsize() -{ - /* Nothing to do. */ -} - - int -mch_call_shell(cmd, options) - char_u *cmd; - int options; /* SHELL_*, see vim.h */ -{ - int retval; - int tmode = cur_tmode; - - if (cmd == NULL) - cmd = (char_u *) "GOS"; - -#ifdef FEAT_GUI - if (gui.in_use) - return gui_mch_call_shell(cmd, options); -#endif - if (options & SHELL_COOKED) - settmode(TMODE_COOK); /* set to normal mode */ - MSG_PUTS("\n"); - - /* I don't even want to think about what UnixLib must - * be doing to allow this to work... - */ - retval = system(cmd); - if (retval && !(options & SHELL_SILENT)) - EMSG(strerror(EOPSYS)); /* Doesn't seem to set errno? */ - - swi(OS_Byte, 229, 1, 0); /* Re-disable escape */ - if (tmode == TMODE_RAW) - settmode(TMODE_RAW); /* set to raw mode */ - return retval ? FAIL : OK; -} - -/* - * Check for Escape being pressed right now. - * [ different if !term_console? ] - */ - void -mch_breakcheck() -{ - if (xswi(OS_Byte, 121, 0xf0) & v_flag) - return; - if (r1 == 0xff) - { - got_int = TRUE; - swi(OS_Byte, 15, 1); /* Flush input buffer */ - } -} - -/* - * Recursively expand one path component into all matching files and/or - * directories. - * "path" has backslashes before chars that are not to be expanded. - * Return the number of matches found. - */ - int -mch_expandpath(gap, path, flags) - garray_T *gap; /* Grow array for results. */ - char_u *path; - int flags; /* EW_* flags */ -{ - int got; /* Number of matches. */ - char_u *pattern; - - /* Plan: - * - * 1) Get first part of path - no wildcards - * 2) Get next path element (wildcarded) - * 3) Get rest of path - * - * If (3) is nothing then only the leaf is wildcarded - add to gap - * Otherwise call recursively for each path in (2), passing (3) - * - * This is just the header function. - */ - - /* We must be able to modifiy path, so make a copy */ - pattern = vim_strsave(path); - if (pattern == NULL) - return 0; - got = expand_section(gap, (char_u *)"", pattern, flags); - vim_free(pattern); - return got; -} - -/* - * expand_section(gap, "$.Dir1.Dir2", "ABBA*.myleaf##") - * - * calls expand_section(gap, "$.Dir1.Dir2.ABBA_Gold", "myleaf##") - * and expand_section(gap, "$.Dir1.Dir2.ABBA_Live", "myleaf##") - * - * If rest is just a leaf then all matches are added to gap. - * - * Returns number of items added to gap. - */ - int -expand_section(gap, root, rest, flags) - garray_T *gap; - char_u *root; /* Non-wildcarded path to search */ - char_u *rest; /* Wildcarded remainder of path */ - int flags; /* Add dirs/files/missing objects. */ -{ - static char_u buf[MAXPATHL]; /* Temporary buffer. */ - char_u dir[MAXPATHL]; - int start_element = -1; /* Start of wildcarded element */ - char_u c; - int i; - int got, dir_pos; - int buflen; /* Chars used in buf[] */ - int colon = 0; /* Dir ends in ':' */ - - buflen = strlen(root); - STRNCPY(buf, root, buflen); /* Copy root into buffer. */ - - /* - * Find end of nonwildcarded section. - * Count ':' as a path sep since Vim:Bug* is a valid pathname. - */ - - for (i = 0; c = rest[i]; i++) - { - if (c == PATHSEP) - { - start_element = i; - colon = 0; - } - if (c == ':') - { - start_element = i + 1; - colon = 1; - } - if (c == '#' || c == '*') - break; - } - if (c == 0) - start_element = i; - - /* - * start_element +> terminator for non-wildcarded section. - * Transfer this bit into buf. - */ - if (buflen + start_element + 4 >= MAXPATHL) - return 0; /* Buffer full */ - if (start_element >= 0) - { - if (*root && !colon) - buf[buflen++] = PATHSEP; - strncpy(buf + buflen, rest, start_element); - buflen += start_element; - } - buf[buflen] = 0; - - /* - * Did we reach the end of the string without hitting any wildcards? - */ - if (c == 0) - { - /* Yes - add combined path to grow array and return. */ - addfile(gap, buf, flags); - return 1; - } - - if (start_element < 0 || !colon) - start_element++; - rest += start_element; - - /* - * rest does contain wildcards if we get here. - * - * Now : have we reached the leaf names part yet? - * If so, add all matches (files and dirs) to gap. - * If not, get next path element and scan all matching directories. - */ - - start_element = -1; - for (i = 0; rest[i]; i++) - { - if (rest[i] == '.') - { - start_element = i; - rest[i] = 0; /* Break string here. */ - break; - } - } - - /* If start_element is -1 then we are matching leaf names */ - - r3 = 0; /* Number of objs read. */ - dir_pos = 0; /* Position through directory. */ - got = 0; /* Files added so far. */ - while (dir_pos != -1) - { - buf[buflen] = 0; - if (xswi(OS_GBPB, 9, - buf, /* Directory to scan. */ - buf + buflen + (1 - colon), /* Buffer for result. */ - 1, /* Number of objects to read. */ - dir_pos, /* Search position. */ - MAXPATHL - 2 - buflen, /* Size of result buffer. */ - rest) /* Wildcarded leafname. */ - & v_flag) - { - EMSG(r0 + 4); - r4 = -1; - } - dir_pos = r4; /* r4 corrupted by addfile() */ - if (r3 > 0) - { - char_u *path = buf; - if (buflen == 0) - path++; /* Don't do '.File' */ - else if (!colon) - buf[buflen] = '.'; /* Join path and leaf */ - - /* Path -> full path of object found */ - if (start_element == -1) - { - addfile(gap, path, flags); - got++; - } - else - { - /* Scan into subdirectories and images; ignore files */ - swi(OS_File, 17, path); - if (r0 == 2 || r0 == 3) - got += expand_section(gap, - path, - rest + start_element + 1, - flags); - } - } - } - - /* Restore the dot if we removed it. */ - if (start_element >= 0) - rest[start_element] = '.'; - return got; -} - -/* - * mch_expand_wildcards() - this code does wild-card pattern matching using - * the shell. It isn't used under RISC OS. - * - * return OK for success, FAIL for error (you may lose some memory) and put - * an error message in *file. - * - * num_pat is number of input patterns - * pat is array of pointers to input patterns - * num_file is pointer to number of matched file names - * file is pointer to array of pointers to matched file names - */ - int -mch_expand_wildcards(num_pat, pat, num_file, file, flags) - int num_pat; - char_u **pat; - int *num_file; - char_u ***file; - int flags; /* EW_* flags */ -{ - /* This doesn't get called unless SPECIAL_WILDCHAR is defined. */ - return FAIL; -} - -/* - * Return TRUE if "p" contains wildcards which can be expanded by - * mch_expandpath(). - */ - int -mch_has_exp_wildcard(p) - char_u *p; -{ - if (vim_strpbrk((char_u *)"*#", p)) - return TRUE; - return FALSE; -} - -/* Return TRUE if "p" contains wildcards. */ - int -mch_has_wildcard(p) - char_u *p; -{ - if (vim_strpbrk((char_u *)"*#`", p)) - return TRUE; - return FALSE; -} - - int /* see Unix unlink(2) */ -mch_remove(file) - char_u *file; /* Name of file to delete. */ -{ - if (xswi(OS_FSControl, 27, file, 0, 0) & v_flag) - return EXIT_FAILURE; - return EXIT_SUCCESS; -} - -/* Try to make existing scripts work without modification. - * Return a pointer to the new string (freed by caller), or NULL - * - * Two main cases: - * - Absolute : $VIM/syntax/help.vim - * - Relative : Adfs::4.$.!Vim.Resources.Syntax/help.vim - */ - char_u * -mch_munge_fname(fname) - char_u *fname; -{ - char_u c; - int len; - char_u *retval; - - retval = fname = vim_strsave(fname); - if (fname == NULL) - return NULL; - - if (strncmp(fname, "$VIM/", 5) == 0) - { - strncpy(fname, "Vim:", 4); - for (fname += 5; c = *fname; fname++) - { - if (c == '.') - break; - if (c == '/') - fname[-1] = '.'; - else - fname[-1] = c; - } - fname[-1] = '\0'; - } - else - { - /* Check to see if the file exists without modification. */ - if (xswi(OS_File, 17, fname) & v_flag) - r0 == 0; /* Invalid filename? */ - if (r0) - return retval; - - len = strlen(fname); - if (strcmp(fname + len - 4, ".vim") == 0) - { - fname[len - 4] = '\0'; - for (; c = *fname; fname++) - { - if (c == '/') - *fname = '.'; - } - } - } - return retval; -} - -/* QuickFix reads munged names from the error file. - * Correct them. - */ - int -ro_buflist_add(old_name) - char_u *old_name; /* Name of file found by quickfix */ -{ - char_u *fname; - char_u *leaf; /* Pointer to start of leaf in old_name */ - char_u *ptr; - char_u c; - int retval; - - if (old_name == NULL) - return buflist_add(NULL, 0); - - /* Copy the name so we can mess around with it. */ - fname = vim_strsave(old_name); - if (fname == NULL) - /* Out of memory - can't modify name */ - return buflist_add(old_name, 0); - - /* Change `dir/main.c' into `dir.c.main' */ - leaf = fname; - for (ptr = fname; c = *ptr; ptr++) - { - if (c == '/') - { - leaf = ptr + 1; - *ptr = '.'; - } - else if (c == '.') - break; - } - if (c == '.') - { - /* Change `main.c' into `c.main' - * | | - * leaf ptr - */ - ptr += old_name - fname; - *ptr = '\0'; - sprintf(leaf, - "%s.%s", - ptr + 1, - leaf - fname + old_name); - } - - retval = buflist_add(fname, 0); - free(fname); - return retval; -} - -/* Change the current directory. - * Strip trailing dots to make it easier to use with filename completion. - * Return 0 for success, -1 for failure. - */ - int -mch_chdir(dir) - char_u *dir; -{ - int length; - int retval; - char_u *new_dir; - - if (p_verbose >= 5) - { - verbose_enter(); - smsg((char_u *)"chdir(%s)", dir); - verbose_leave(); - } - length = strlen(dir); - if (dir[length - 1] != '.') - return chdir(dir); /* No trailing dots - nothing to do. */ - new_dir = vim_strsave(dir); - if (new_dir == NULL) - return chdir(dir); /* Can't allocate memory. */ - - while (new_dir[--length] == '.') - new_dir[length] = '\0'; - - retval = chdir(new_dir); - vim_free(new_dir); - return retval; -} - -/* Examine the named file, and set the 'osfiletype' option - * (in curbuf) to the file's type. - */ - void -mch_read_filetype(file) - char_u *file; -{ - int type; - char_u type_string[9]; - int i; - - if (xswi(OS_File, 23, file) & v_flag) - type = 0xfff; /* Default to Text */ - else - type = r6; - - /* Type is the numerical value - see if we have a textual equivalent */ - swi(OS_FSControl, 18, 0, type); - ((int *) type_string)[0] = r2; - ((int *) type_string)[1] = r3; - type_string[8] = 0; - for (i = 0; type_string[i] > ' '; i++) - ; - type_string[i] = 0; - - set_string_option_direct("osfiletype", -1, type_string, OPT_FREE, 0); - return; -} - - void -mch_set_filetype(file, type) - char_u *file; - char_u *type; -{ - if (xswi(OS_FSControl, 31, type) & v_flag) - { - EMSG(_("E366: Invalid 'osfiletype' option - using Text")); - r2 = 0xfff; - } - - swi(OS_File, 18, file, r2); -} - -/* Return TRUE if the file's type matches 'type' - * RISC OS types always start with '&' - */ - int -mch_check_filetype(fname, type) - char_u *fname; - char_u *type; -{ - int value; - char *end; - - if (*type != '&') - return FALSE; - - value = strtol(type + 1, &end, 16); - if (*end) - return FALSE; /* Invalid type (report error?) */ - - if (xswi(OS_File, 23, fname) & v_flag) - return FALSE; /* Invalid filename? */ - - return (r0 && r6 == value); -} diff -Naur vim73.orig/src/os_riscos.h vim73/src/os_riscos.h --- vim73.orig/src/os_riscos.h 2010-05-23 12:16:06.000000000 +0000 +++ vim73/src/os_riscos.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,166 +0,0 @@ -/* vi:set ts=8 sts=4 sw=4: - * - * VIM - Vi IMproved by Bram Moolenaar - * - * Do ":help uganda" in Vim to read copying and usage conditions. - * Do ":help credits" in Vim to see a list of people who contributed. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define CASE_INSENSITIVE_FILENAME -#define FEAT_MODIFY_FNAME -#define FEAT_OSFILETYPE -#define DFLT_OFT "Text" -#define USE_TERM_CONSOLE -#define HAVE_AVAIL_MEM - -/* Longer filenames now accessible to all */ -#ifndef BASENAMELEN -# define BASENAMELEN 64 /* Same length as unzip */ -#endif - -#ifndef TEMNAME -# define TEMPNAME ".v?XXXXXX" -# define TEMPNAMELEN 25 -#endif - -#ifndef DFLT_HELPFILE -# define DFLT_HELPFILE "Vim:doc.help" -#endif - -#ifndef DFLT_BDIR -# define DFLT_BDIR ".,." /* default for 'backupdir' */ -#endif - -/* Paths to try putting swap file in. */ -#ifndef DFLT_DIR -# define DFLT_DIR ".,." /* default for 'directory' */ -#endif - -#ifndef DFLT_VDIR -# define DFLT_VDIR "Choices:Vim.view" /* default for 'viewdir' */ -#endif - -#ifndef TERMCAPFILE -# define TERMCAPFILE "Vim:TermCap" -#endif -#define HAVE_TGETENT - -#ifndef SYNTAX_FNAME -# define SYNTAX_FNAME "Vim:Syntax.%s" -#endif - -#ifndef EVIM_FILE -# define EVIM_FILE "Vim:Evim" -#endif - -#define FEAT_VIMINFO - -#ifndef VIMINFO_FILE -# define VIMINFO_FILE ".Vim.VimInfo" -#endif -#ifndef VIMINFO_FILE2 -# define VIMINFO_FILE2 "Choices:Vim.VimInfo" -#endif - -#ifndef VIMRC_FILE -# define VIMRC_FILE "/vimrc" -#endif -#ifndef EXRC_FILE -# define EXRC_FILE "/exrc" -#endif -#ifndef GVIMRC_FILE -# define GVIMRC_FILE "/gvimrc" -#endif -#ifndef USR_VIMRC_FILE -# define USR_VIMRC_FILE "Vim:Evim" -#endif -#ifndef SESSION_FILE -# define SESSION_FILE "/Session.vim" -#endif -#ifndef USR_VIMRC_FILE -# define USR_VIMRC_FILE "Choices:Vim.VimRC" -#endif -#ifndef USR_GVIMRC_FILE -# define USR_GVIMRC_FILE "Choices:Vim.GVimRC" -#endif -#ifndef USR_EXRC_FILE -# define USR_EXRC_FILE "Choices:Vim.ExRC" -#endif -#ifndef SYS_VIMRC_FILE -# define SYS_VIMRC_FILE "Vim:VimRC" -#endif -#ifndef SYS_GVIMRC_FILE -# define SYS_GVIMRC_FILE "Vim:GVimRC" -#endif -#ifndef SYS_MENU_FILE -# define SYS_MENU_FILE "Vim:Menu" -#endif -#ifndef SYS_OPTWIN_FILE -# define SYS_OPTWIN_FILE "Vim:Optwin" -#endif -#ifndef FILETYPE_FILE -# define FILETYPE_FILE "Vim:Filetype" -#endif -#ifndef FTPLUGIN_FILE -# define FTPLUGIN_FILE "Vim:Ftplugin/vim" -#endif -#ifndef INDENT_FILE -# define INDENT_FILE "Vim:Indent/vim" -#endif -#ifndef FTOFF_FILE -# define FTOFF_FILE "Vim:Ftoff" -#endif -#ifndef FTPLUGOF_FILE -# define FTPLUGOF_FILE "Vim:Ftplugof" -#endif -#ifndef INDOFF_FILE -# define INDOFF_FILE "Vim:Indoff" -#endif - -#define DFLT_ERRORFILE "errors/vim" -#define DFLT_RUNTIMEPATH "Choices:Vim,Vim:,Choices:Vim.after" - -/* - * RISC PCs have plenty of memory, use large buffers - */ -#define CMDBUFFSIZE 1024 /* size of the command processing buffer */ -#define MAXPATHL 256 /* paths are always quite short though */ - -#ifndef DFLT_MAXMEM -# define DFLT_MAXMEM (5*1024) /* use up to 5 Mbyte for a buffer */ -#endif - -#ifndef DFLT_MAXMEMTOT -# define DFLT_MAXMEMTOT (10*1024) /* use up to 10 Mbyte for Vim */ -#endif - -#ifdef HAVE_SIGSET -# define signal sigset -#endif - -#define n_flag (1<<31) -#define z_flag (1<<30) -#define c_flag (1<<29) -#define v_flag (1<<28) - -/* These take r0-r7 as inputs, returns r0-r7 in global variables. */ -void swi(int swinum, ...); /* Handles errors itself */ -int xswi(int swinum, ...); /* Returns errors using v flag */ -extern int r0, r1, r2, r3, r4, r5, r6, r7; /* For return values */ - -#include -#include - -#define mch_memmove(to, from, len) memmove((char *)(to), (char *)(from), len) -#define mch_rename(src, dst) rename(src, dst) -#define mch_getenv(x) (char_u *)getenv((char *)x) -#define mch_setenv(name, val, x) setenv(name, val, x) diff -Naur vim73.orig/src/os_unix.c vim73/src/os_unix.c --- vim73.orig/src/os_unix.c 2010-08-08 13:14:04.000000000 +0000 +++ vim73/src/os_unix.c 2012-07-20 20:31:15.784310019 +0000 @@ -154,6 +154,13 @@ static void may_core_dump __ARGS((void)); +#ifdef HAVE_UNION_WAIT +typedef union wait waitstatus; +#else +typedef int waitstatus; +#endif +static pid_t wait4pid __ARGS((pid_t, waitstatus *)); + static int WaitForChar __ARGS((long)); #if defined(__BEOS__) int RealWaitForChar __ARGS((int, long, int *)); @@ -283,7 +290,7 @@ #ifdef SIGTERM {SIGTERM, "TERM", TRUE}, #endif -#ifdef SIGVTALRM +#if defined(SIGVTALRM) && !defined(FEAT_RUBY) {SIGVTALRM, "VTALRM", TRUE}, #endif #if defined(SIGPROF) && !defined(FEAT_MZSCHEME) && !defined(WE_ARE_PROFILING) @@ -1107,7 +1114,7 @@ * On Linux, signal is not always handled immediately either. * See https://bugs.launchpad.net/bugs/291373 * - * volatile because it is used in in signal handler sigcont_handler(). + * volatile because it is used in signal handler sigcont_handler(). */ static volatile int sigcont_received; static RETSIGTYPE sigcont_handler __ARGS(SIGPROTOARG); @@ -1123,6 +1130,30 @@ } #endif +# if defined(FEAT_CLIPBOARD) && defined(FEAT_X11) +static void loose_clipboard __ARGS((void)); + +/* + * Called when Vim is going to sleep or execute a shell command. + * We can't respond to requests for the X selections. Lose them, otherwise + * other applications will hang. But first copy the text to cut buffer 0. + */ + static void +loose_clipboard() +{ + if (clip_star.owned || clip_plus.owned) + { + x11_export_final_selection(); + if (clip_star.owned) + clip_lose_selection(&clip_star); + if (clip_plus.owned) + clip_lose_selection(&clip_plus); + if (x11_display != NULL) + XFlush(x11_display); + } +} +#endif + /* * If the machine has job control, use it to suspend the program, * otherwise fake it by starting a new shell. @@ -1137,19 +1168,7 @@ out_flush(); /* needed to disable mouse on some systems */ # if defined(FEAT_CLIPBOARD) && defined(FEAT_X11) - /* Since we are going to sleep, we can't respond to requests for the X - * selections. Lose them, otherwise other applications will hang. But - * first copy the text to cut buffer 0. */ - if (clip_star.owned || clip_plus.owned) - { - x11_export_final_selection(); - if (clip_star.owned) - clip_lose_selection(&clip_star); - if (clip_plus.owned) - clip_lose_selection(&clip_plus); - if (x11_display != NULL) - XFlush(x11_display); - } + loose_clipboard(); # endif # if defined(_REENTRANT) && defined(SIGCONT) @@ -1726,6 +1745,11 @@ } if (x11_window == 0 || x11_display == NULL) return (result = FAIL); + +# ifdef FEAT_EVAL + set_vim_var_nr(VV_WINDOWID, (long)x11_window); +# endif + return (result = OK); } @@ -2134,10 +2158,13 @@ * Return non-zero when using an xterm mouse, according to 'ttymouse'. * Return 1 for "xterm". * Return 2 for "xterm2". + * Return 3 for "urxvt". */ int use_xterm_mouse() { + if (ttym_flags == TTYM_URXVT) + return 3; if (ttym_flags == TTYM_XTERM2) return 2; if (ttym_flags == TTYM_XTERM) @@ -2719,6 +2746,13 @@ #ifdef HAVE_POSIX_ACL ret = (vim_acl_T)acl_get_file((char *)fname, ACL_TYPE_ACCESS); #else +#ifdef HAVE_SOLARIS_ZFS_ACL + acl_t *aclent; + + if (acl_get((char *)fname, 0, &aclent) < 0) + return NULL; + ret = (vim_acl_T)aclent; +#else #ifdef HAVE_SOLARIS_ACL vim_acl_solaris_T *aclent; @@ -2764,6 +2798,7 @@ ret = (vim_acl_T)aclent; #endif /* HAVE_AIX_ACL */ #endif /* HAVE_SOLARIS_ACL */ +#endif /* HAVE_SOLARIS_ZFS_ACL */ #endif /* HAVE_POSIX_ACL */ return ret; } @@ -2781,6 +2816,9 @@ #ifdef HAVE_POSIX_ACL acl_set_file((char *)fname, ACL_TYPE_ACCESS, (acl_t)aclent); #else +#ifdef HAVE_SOLARIS_ZFS_ACL + acl_set((char *)fname, (acl_t *)aclent); +#else #ifdef HAVE_SOLARIS_ACL acl((char *)fname, SETACL, ((vim_acl_solaris_T *)aclent)->acl_cnt, ((vim_acl_solaris_T *)aclent)->acl_entry); @@ -2789,6 +2827,7 @@ chacl((char *)fname, aclent, ((struct acl *)aclent)->acl_len); #endif /* HAVE_AIX_ACL */ #endif /* HAVE_SOLARIS_ACL */ +#endif /* HAVE_SOLARIS_ZFS_ACL */ #endif /* HAVE_POSIX_ACL */ } @@ -2801,6 +2840,9 @@ #ifdef HAVE_POSIX_ACL acl_free((acl_t)aclent); #else +#ifdef HAVE_SOLARIS_ZFS_ACL + acl_free((acl_t *)aclent); +#else #ifdef HAVE_SOLARIS_ACL free(((vim_acl_solaris_T *)aclent)->acl_entry); free(aclent); @@ -2809,6 +2851,7 @@ free(aclent); #endif /* HAVE_AIX_ACL */ #endif /* HAVE_SOLARIS_ACL */ +#endif /* HAVE_SOLARIS_ZFS_ACL */ #endif /* HAVE_POSIX_ACL */ } #endif @@ -3294,6 +3337,17 @@ return; xterm_mouse_vers = use_xterm_mouse(); + +# ifdef FEAT_MOUSE_URXVT + if (ttym_flags == TTYM_URXVT) { + out_str_nf((char_u *) + (on + ? IF_EB("\033[?1015h", ESC_STR "[?1015h") + : IF_EB("\033[?1015l", ESC_STR "[?1015l"))); + ison = on; + } +# endif + if (xterm_mouse_vers > 0) { if (on) /* enable mouse events, use mouse tracking if available */ @@ -3410,6 +3464,9 @@ { # ifdef FEAT_MOUSE_XTERM if (use_xterm_mouse() +# ifdef FEAT_MOUSE_URXVT + && use_xterm_mouse() != 3 +# endif # ifdef FEAT_GUI && !gui.in_use # endif @@ -3499,6 +3556,27 @@ else del_mouse_termcode(KS_PTERM_MOUSE); # endif +# ifdef FEAT_MOUSE_URXVT + /* same as the dec mouse */ + if (use_xterm_mouse() == 3 +# ifdef FEAT_GUI + && !gui.in_use +# endif + ) + { + set_mouse_termcode(KS_URXVT_MOUSE, (char_u *)(term_is_8bit(T_NAME) + ? IF_EB("\233", CSI_STR) + : IF_EB("\033[", ESC_STR "["))); + + if (*p_mouse != NUL) + { + mch_setmouse(FALSE); + setmouse(); + } + } + else + del_mouse_termcode(KS_URXVT_MOUSE); +# endif } #endif @@ -3643,26 +3721,43 @@ /* Nothing to do. */ } -#ifndef USE_SYSTEM -static void append_ga_line __ARGS((garray_T *gap)); - /* - * Append the text in "gap" below the cursor line and clear "gap". + * Wait for process "child" to end. + * Return "child" if it exited properly, <= 0 on error. */ - static void -append_ga_line(gap) - garray_T *gap; -{ - /* Remove trailing CR. */ - if (gap->ga_len > 0 - && !curbuf->b_p_bin - && ((char_u *)gap->ga_data)[gap->ga_len - 1] == CAR) - --gap->ga_len; - ga_append(gap, NUL); - ml_append(curwin->w_cursor.lnum++, gap->ga_data, 0, FALSE); - gap->ga_len = 0; + static pid_t +wait4pid(child, status) + pid_t child; + waitstatus *status; +{ + pid_t wait_pid = 0; + + while (wait_pid != child) + { + /* When compiled with Python threads are probably used, in which case + * wait() sometimes hangs for no obvious reason. Use waitpid() + * instead and loop (like the GUI). Also needed for other interfaces, + * they might call system(). */ +# ifdef __NeXT__ + wait_pid = wait4(child, status, WNOHANG, (struct rusage *)0); +# else + wait_pid = waitpid(child, status, WNOHANG); +# endif + if (wait_pid == 0) + { + /* Wait for 1/100 sec before trying again. */ + mch_delay(10L, TRUE); + continue; + } + if (wait_pid <= 0 +# ifdef ECHILD + && errno == ECHILD +# endif + ) + break; + } + return wait_pid; } -#endif int mch_call_shell(cmd, options) @@ -3706,6 +3801,10 @@ if (options & SHELL_COOKED) settmode(TMODE_COOK); /* set to normal mode */ +# if defined(FEAT_CLIPBOARD) && defined(FEAT_X11) + loose_clipboard(); +# endif + # ifdef __EMX__ if (cmd == NULL) x = system(""); /* this starts an interactive shell in emx */ @@ -3795,6 +3894,7 @@ int retval = -1; char **argv = NULL; int argc; + char_u *p_shcf_copy = NULL; int i; char_u *p; int inquote; @@ -3814,13 +3914,17 @@ # endif int did_settmode = FALSE; /* settmode(TMODE_RAW) called */ + newcmd = vim_strsave(p_sh); + if (newcmd == NULL) /* out of memory */ + goto error; + out_flush(); if (options & SHELL_COOKED) settmode(TMODE_COOK); /* set to normal mode */ - newcmd = vim_strsave(p_sh); - if (newcmd == NULL) /* out of memory */ - goto error; +# if defined(FEAT_CLIPBOARD) && defined(FEAT_X11) + loose_clipboard(); +# endif /* * Do this loop twice: @@ -3851,6 +3955,19 @@ } if (argv == NULL) { + /* + * Account for possible multiple args in p_shcf. + */ + p = p_shcf; + for (;;) + { + p = skiptowhite(p); + if (*p == NUL) + break; + ++argc; + p = skipwhite(p); + } + argv = (char **)alloc((unsigned)((argc + 4) * sizeof(char *))); if (argv == NULL) /* out of memory */ goto error; @@ -3858,9 +3975,27 @@ } if (cmd != NULL) { + char_u *s; + if (extra_shell_arg != NULL) argv[argc++] = (char *)extra_shell_arg; - argv[argc++] = (char *)p_shcf; + + /* Break 'shellcmdflag' into white separated parts. This doesn't + * handle quoted strings, they are very unlikely to appear. */ + p_shcf_copy = alloc((unsigned)STRLEN(p_shcf) + 1); + if (p_shcf_copy == NULL) /* out of memory */ + goto error; + s = p_shcf_copy; + p = p_shcf; + while (*p != NUL) + { + argv[argc++] = (char *)s; + while (*p && *p != ' ' && *p != TAB) + *s++ = *p++; + *s++ = NUL; + p = skipwhite(p); + } + argv[argc++] = (char *)cmd; } argv[argc] = NULL; @@ -3885,11 +4020,21 @@ if (p_guipty && !(options & (SHELL_READ|SHELL_WRITE))) { pty_master_fd = OpenPTY(&tty_name); /* open pty */ - if (pty_master_fd >= 0 && ((pty_slave_fd = - open(tty_name, O_RDWR | O_EXTRA, 0)) < 0)) + if (pty_master_fd >= 0) { - close(pty_master_fd); - pty_master_fd = -1; + /* Leaving out O_NOCTTY may lead to waitpid() always returning + * 0 on Mac OS X 10.7 thereby causing freezes. Let's assume + * adding O_NOCTTY always works when defined. */ +#ifdef O_NOCTTY + pty_slave_fd = open(tty_name, O_RDWR | O_NOCTTY | O_EXTRA, 0); +#else + pty_slave_fd = open(tty_name, O_RDWR | O_EXTRA, 0); +#endif + if (pty_slave_fd < 0) + { + close(pty_master_fd); + pty_master_fd = -1; + } } } /* @@ -4148,7 +4293,6 @@ # ifdef FEAT_GUI if (pty_master_fd >= 0) { - close(pty_slave_fd); /* close slave side of pty */ fromshell_fd = pty_master_fd; toshell_fd = dup(pty_master_fd); } @@ -4190,15 +4334,13 @@ { MSG_PUTS(_("\nCannot fork\n")); } - else if (wpid == 0) + else if (wpid == 0) /* child */ { linenr_T lnum = curbuf->b_op_start.lnum; int written = 0; char_u *lp = ml_get(lnum); - char_u *s; size_t l; - /* child */ close(fromshell_fd); for (;;) { @@ -4210,7 +4352,8 @@ len = write(toshell_fd, "", (size_t)1); else { - s = vim_strchr(lp + written, NL); + char_u *s = vim_strchr(lp + written, NL); + len = write(toshell_fd, (char *)lp + written, s == NULL ? l : (size_t)(s - (lp + written))); @@ -4221,7 +4364,7 @@ * should not have one. */ if (lnum != curbuf->b_op_end.lnum || !curbuf->b_p_bin - || (lnum != write_no_eol_lnum + || (lnum != curbuf->b_no_eol_lnum && (lnum != curbuf->b_ml.ml_line_count || curbuf->b_p_eol))) @@ -4243,7 +4386,7 @@ } _exit(0); } - else + else /* parent */ { close(toshell_fd); toshell_fd = -1; @@ -4430,7 +4573,7 @@ ++noread_cnt; while (RealWaitForChar(fromshell_fd, 10L, NULL)) { - len = read(fromshell_fd, (char *)buffer + len = read_eintr(fromshell_fd, buffer # ifdef FEAT_MBYTE + buffer_off, (size_t)(BUFLEN - buffer_off) # else @@ -4540,7 +4683,7 @@ * typed characters (otherwise we would lose typeahead). */ # ifdef __NeXT__ - wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *) 0); + wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *)0); # else wait_pid = waitpid(pid, &status, WNOHANG); # endif @@ -4564,10 +4707,10 @@ { append_ga_line(&ga); /* remember that the NL was missing */ - write_no_eol_lnum = curwin->w_cursor.lnum; + curbuf->b_no_eol_lnum = curwin->w_cursor.lnum; } else - write_no_eol_lnum = 0; + curbuf->b_no_eol_lnum = 0; ga_clear(&ga); } @@ -4589,38 +4732,24 @@ * Don't wait if wait_pid was already set above, indicating the * child already exited. */ - while (wait_pid != pid) - { -# ifdef _THREAD_SAFE - /* Ugly hack: when compiled with Python threads are probably - * used, in which case wait() sometimes hangs for no obvious - * reason. Use waitpid() instead and loop (like the GUI). */ -# ifdef __NeXT__ - wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *)0); -# else - wait_pid = waitpid(pid, &status, WNOHANG); -# endif - if (wait_pid == 0) - { - /* Wait for 1/100 sec before trying again. */ - mch_delay(10L, TRUE); - continue; - } -# else - wait_pid = wait(&status); -# endif - if (wait_pid <= 0 -# ifdef ECHILD - && errno == ECHILD + if (wait_pid != pid) + wait_pid = wait4pid(pid, &status); + +# ifdef FEAT_GUI + /* Close slave side of pty. Only do this after the child has + * exited, otherwise the child may hang when it tries to write on + * the pty. */ + if (pty_master_fd >= 0) + close(pty_slave_fd); # endif - ) - break; - } /* Make sure the child that writes to the external program is * dead. */ if (wpid > 0) + { kill(wpid, SIGKILL); + wait4pid(wpid, NULL); + } /* * Set to raw mode right now, otherwise a CTRL-C after @@ -4656,6 +4785,7 @@ } } vim_free(argv); + vim_free(p_shcf_copy); error: if (!did_settmode) @@ -4766,7 +4896,8 @@ /* * Wait "msec" msec until a character is available from file descriptor "fd". - * Time == -1 will block forever. + * "msec" == 0 will check for characters once. + * "msec" == -1 will block until a character is available. * When a GUI is being used, this will not be used for input -- webb * Returns also, when a request from Sniff is waiting -- toni. * Or when a Linux GPM mouse event is waiting. @@ -5004,7 +5135,8 @@ /* * Select on ready for reading and exceptional condition (end of file). */ - FD_ZERO(&rfds); /* calls bzero() on a sun */ +select_eintr: + FD_ZERO(&rfds); FD_ZERO(&efds); FD_SET(fd, &rfds); # if !defined(__QNX__) && !defined(__CYGWIN32__) @@ -5064,6 +5196,21 @@ # else ret = select(maxfd + 1, &rfds, NULL, &efds, tvp); # endif +# ifdef EINTR + if (ret == -1 && errno == EINTR) + { + /* Check whether window has been resized, EINTR may be caused by + * SIGWINCH. */ + if (do_resize) + handle_resize(); + + /* Interrupted by a signal, need to try again. We ignore msec + * here, because we do want to check even after a timeout if + * characters are available. Needed for reading output of an + * external command after the process has finished. */ + goto select_eintr; + } +# endif # ifdef __TANDEM if (ret == -1 && errno == ENOTSUP) { @@ -5071,7 +5218,7 @@ FD_ZERO(&efds); ret = 0; } -#endif +# endif # ifdef FEAT_MZSCHEME if (ret == 0 && mzquantum_used) /* loop if MzThreads must be scheduled and timeout occurred */ @@ -5693,6 +5840,7 @@ if (shell_style == STYLE_PRINT && !did_find_nul) { /* If there is a NUL, set did_find_nul, else set check_spaces */ + buffer[len] = NUL; if (len && (int)STRLEN(buffer) < (int)len - 1) did_find_nul = TRUE; else @@ -6562,7 +6710,7 @@ xterm_hints.x = 2; return TRUE; } - if (mouse_code == NULL) + if (mouse_code == NULL || STRLEN(mouse_code) > 45) { xterm_trace = 0; return FALSE; diff -Naur vim73.orig/src/os_unix.h vim73/src/os_unix.h --- vim73.orig/src/os_unix.h 2010-05-23 12:16:14.000000000 +0000 +++ vim73/src/os_unix.h 2012-07-20 20:31:09.687638968 +0000 @@ -184,10 +184,6 @@ #define BASENAMELEN (MAXNAMLEN - 5) -#ifdef HAVE_ERRNO_H -# include -#endif - #ifdef HAVE_PWD_H # include #endif diff -Naur vim73.orig/src/os_win16.c vim73/src/os_win16.c --- vim73.orig/src/os_win16.c 2010-06-26 04:03:31.000000000 +0000 +++ vim73/src/os_win16.c 2012-07-20 20:31:17.634311344 +0000 @@ -20,13 +20,11 @@ # pragma warn -obs #endif -#include "vimio.h" #include "vim.h" #include #include #include -#include #include #include #include @@ -245,9 +243,9 @@ /* Wait for the command to terminate before continuing */ while (GetModuleUsage((HINSTANCE)h_module) > 0 && again ) { - while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) && again ) + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) && again) { - if(msg.message == WM_QUIT) + if (msg.message == WM_QUIT) { PostQuitMessage(msg.wParam); @@ -381,13 +379,13 @@ /* - * How much memory is available? + * How much memory is available in Kbyte? */ long_u mch_avail_mem( int special) { - return GetFreeSpace(0); + return GetFreeSpace(0) >> 10; } diff -Naur vim73.orig/src/os_win32.c vim73/src/os_win32.c --- vim73.orig/src/os_win32.c 2010-07-14 14:49:36.000000000 +0000 +++ vim73/src/os_win32.c 2012-07-20 20:31:18.294311815 +0000 @@ -20,7 +20,6 @@ * Roger Knobbe did the initial port of Vim 3.0. */ -#include "vimio.h" #include "vim.h" #ifdef FEAT_MZSCHEME @@ -28,7 +27,6 @@ #endif #include -#include #include #include #include @@ -154,6 +152,14 @@ # define wcsicmp(a, b) wcscmpi((a), (b)) #endif +/* Enable common dialogs input unicode from IME if posible. */ +#ifdef FEAT_MBYTE +LRESULT (WINAPI *pDispatchMessage)(LPMSG) = DispatchMessage; +BOOL (WINAPI *pGetMessage)(LPMSG, HWND, UINT, UINT) = GetMessage; +BOOL (WINAPI *pIsDialogMessage)(HWND, LPMSG) = IsDialogMessage; +BOOL (WINAPI *pPeekMessage)(LPMSG, HWND, UINT, UINT, UINT) = PeekMessage; +#endif + #ifndef FEAT_GUI_W32 /* Win32 Console handles for input and output */ static HANDLE g_hConIn = INVALID_HANDLE_VALUE; @@ -206,55 +212,109 @@ static int suppress_winsize = 1; /* don't fiddle with console */ #endif +static char_u *exe_path = NULL; + static void get_exe_name(void) { - char temp[256]; - static int did_set_PATH = FALSE; + /* Maximum length of $PATH is more than MAXPATHL. 8191 is often mentioned + * as the maximum length that works (plus a NUL byte). */ +#define MAX_ENV_PATH_LEN 8192 + char temp[MAX_ENV_PATH_LEN]; + char_u *p; if (exe_name == NULL) { /* store the name of the executable, may be used for $VIM */ - GetModuleFileName(NULL, temp, 255); + GetModuleFileName(NULL, temp, MAX_ENV_PATH_LEN - 1); if (*temp != NUL) exe_name = FullName_save((char_u *)temp, FALSE); } - if (!did_set_PATH && exe_name != NULL) + if (exe_path == NULL && exe_name != NULL) { - char_u *p; - char_u *newpath; - - /* Append our starting directory to $PATH, so that when doing "!xxd" - * it's found in our starting directory. Needed because SearchPath() - * also looks there. */ - p = mch_getenv("PATH"); - newpath = alloc((unsigned)(STRLEN(p) + STRLEN(exe_name) + 2)); - if (newpath != NULL) - { - STRCPY(newpath, p); - STRCAT(newpath, ";"); - vim_strncpy(newpath + STRLEN(newpath), exe_name, - gettail_sep(exe_name) - exe_name); - vim_setenv((char_u *)"PATH", newpath); - vim_free(newpath); + exe_path = vim_strnsave(exe_name, + (int)(gettail_sep(exe_name) - exe_name)); + if (exe_path != NULL) + { + /* Append our starting directory to $PATH, so that when doing + * "!xxd" it's found in our starting directory. Needed because + * SearchPath() also looks there. */ + p = mch_getenv("PATH"); + if (p == NULL + || STRLEN(p) + STRLEN(exe_path) + 2 < MAX_ENV_PATH_LEN) + { + if (p == NULL || *p == NUL) + temp[0] = NUL; + else + { + STRCPY(temp, p); + STRCAT(temp, ";"); + } + STRCAT(temp, exe_path); + vim_setenv((char_u *)"PATH", temp); + } } + } +} + +/* + * Unescape characters in "p" that appear in "escaped". + */ + static void +unescape_shellxquote(char_u *p, char_u *escaped) +{ + int l = (int)STRLEN(p); + int n; - did_set_PATH = TRUE; + while (*p != NUL) + { + if (*p == '^' && vim_strchr(escaped, p[1]) != NULL) + mch_memmove(p, p + 1, l--); +#ifdef FEAT_MBYTE + n = (*mb_ptr2len)(p); +#else + n = 1; +#endif + p += n; + l -= n; } } +/* + * Load library "name". + */ + HINSTANCE +vimLoadLib(char *name) +{ + HINSTANCE dll = NULL; + char old_dir[MAXPATHL]; + + if (exe_path == NULL) + get_exe_name(); + if (exe_path != NULL && mch_dirname(old_dir, MAXPATHL) == OK) + { + /* Change directory to where the executable is, both to make sure we + * find a .dll there and to avoid looking for a .dll in the current + * directory. */ + mch_chdir(exe_path); + dll = LoadLibrary(name); + mch_chdir(old_dir); + } + return dll; +} + #if defined(DYNAMIC_GETTEXT) || defined(PROTO) # ifndef GETTEXT_DLL # define GETTEXT_DLL "libintl.dll" # endif -/* Dummy funcitons */ +/* Dummy functions */ static char *null_libintl_gettext(const char *); static char *null_libintl_textdomain(const char *); static char *null_libintl_bindtextdomain(const char *, const char *); static char *null_libintl_bind_textdomain_codeset(const char *, const char *); -static HINSTANCE hLibintlDLL = 0; +static HINSTANCE hLibintlDLL = NULL; char *(*dyn_libintl_gettext)(const char *) = null_libintl_gettext; char *(*dyn_libintl_textdomain)(const char *) = null_libintl_textdomain; char *(*dyn_libintl_bindtextdomain)(const char *, const char *) @@ -282,26 +342,16 @@ if (hLibintlDLL) return 1; /* Load gettext library (libintl.dll) */ - hLibintlDLL = LoadLibrary(libname != NULL ? libname : GETTEXT_DLL); + hLibintlDLL = vimLoadLib(libname != NULL ? libname : GETTEXT_DLL); if (!hLibintlDLL) { - char_u dirname[_MAX_PATH]; - - /* Try using the path from gvim.exe to find the .dll there. */ - get_exe_name(); - STRCPY(dirname, exe_name); - STRCPY(gettail(dirname), GETTEXT_DLL); - hLibintlDLL = LoadLibrary((char *)dirname); - if (!hLibintlDLL) + if (p_verbose > 0) { - if (p_verbose > 0) - { - verbose_enter(); - EMSG2(_(e_loadlib), GETTEXT_DLL); - verbose_leave(); - } - return 0; + verbose_enter(); + EMSG2(_(e_loadlib), GETTEXT_DLL); + verbose_leave(); } + return 0; } for (i = 0; libintl_entry[i].name != NULL && libintl_entry[i].ptr != NULL; ++i) @@ -398,6 +448,11 @@ static PGNSECINFO pGetNamedSecurityInfo; #endif +typedef BOOL (WINAPI *PSETHANDLEINFORMATION)(HANDLE, DWORD, DWORD); + +static BOOL allowPiping = FALSE; +static PSETHANDLEINFORMATION pSetHandleInformation; + /* * Set g_PlatformId to VER_PLATFORM_WIN32_NT (NT) or * VER_PLATFORM_WIN32_WINDOWS (Win95). @@ -430,7 +485,7 @@ * Seems like a lot of overhead to load/unload ADVAPI32.DLL each * time we verify security... */ - advapi_lib = LoadLibrary("ADVAPI32.DLL"); + advapi_lib = vimLoadLib("ADVAPI32.DLL"); if (advapi_lib != NULL) { pSetNamedSecurityInfo = (PSNSECINFO)GetProcAddress(advapi_lib, @@ -448,6 +503,18 @@ } } #endif + /* + * If we are on windows NT, try to load the pipe functions, only + * available from Win2K. + */ + if (g_PlatformId == VER_PLATFORM_WIN32_NT) + { + HANDLE kernel32 = GetModuleHandle("kernel32"); + pSetHandleInformation = (PSETHANDLEINFORMATION)GetProcAddress( + kernel32, "SetHandleInformation"); + + allowPiping = pSetHandleInformation != NULL; + } done = TRUE; } } @@ -1342,7 +1409,7 @@ /* - * mch_inchar(): low-level input funcion. + * mch_inchar(): low-level input function. * Get one or more characters from the keyboard or the mouse. * If time == 0, do not wait for characters. * If time == n, wait a short time for characters. @@ -1615,6 +1682,35 @@ return TRUE; } +#if ((defined(__MINGW32__) || defined (__CYGWIN32__)) && \ + __MSVCRT_VERSION__ >= 0x800) || (defined(_MSC_VER) && _MSC_VER >= 1400) +/* + * Bad parameter handler. + * + * Certain MS CRT functions will intentionally crash when passed invalid + * parameters to highlight possible security holes. Setting this function as + * the bad parameter handler will prevent the crash. + * + * In debug builds the parameters contain CRT information that might help track + * down the source of a problem, but in non-debug builds the arguments are all + * NULL/0. Debug builds will also produce assert dialogs from the CRT, it is + * worth allowing these to make debugging of issues easier. + */ + static void +bad_param_handler(const wchar_t *expression, + const wchar_t *function, + const wchar_t *file, + unsigned int line, + uintptr_t pReserved) +{ +} + +# define SET_INVALID_PARAM_HANDLER \ + ((void)_set_invalid_parameter_handler(bad_param_handler)) +#else +# define SET_INVALID_PARAM_HANDLER +#endif + #ifdef FEAT_GUI_W32 /* @@ -1627,6 +1723,9 @@ extern int _fmode; #endif + /* Silently handle invalid parameters to CRT functions */ + SET_INVALID_PARAM_HANDLER; + /* Let critical errors result in a failure, not in a dialog box. Required * for the timestamp test to work on removed floppies. */ SetErrorMode(SEM_FAILCRITICALERRORS); @@ -1835,8 +1934,7 @@ cb->BufferSize.X = cb->Info.dwSize.X; cb->BufferSize.Y = cb->Info.dwSize.Y; NumCells = cb->BufferSize.X * cb->BufferSize.Y; - if (cb->Buffer != NULL) - vim_free(cb->Buffer); + vim_free(cb->Buffer); cb->Buffer = (PCHAR_INFO)alloc(NumCells * sizeof(CHAR_INFO)); if (cb->Buffer == NULL) return FALSE; @@ -2103,6 +2201,9 @@ extern int _fmode; #endif + /* Silently handle invalid parameters to CRT functions */ + SET_INVALID_PARAM_HANDLER; + /* Let critical errors result in a failure, not in a dialog box. Required * for the timestamp test to work on removed floppies. */ SetErrorMode(SEM_FAILCRITICALERRORS); @@ -2273,12 +2374,14 @@ int len) { char szTrueName[_MAX_PATH + 2]; + char szTrueNameTemp[_MAX_PATH + 2]; char *ptrue, *ptruePrev; char *porig, *porigPrev; int flen; WIN32_FIND_DATA fb; HANDLE hFind; int c; + int slen; flen = (int)STRLEN(name); if (flen == 0 || flen > _MAX_PATH) @@ -2323,12 +2426,19 @@ } *ptrue = NUL; + /* To avoid a slow failure append "\*" when searching a directory, + * server or network share. */ + STRCPY(szTrueNameTemp, szTrueName); + slen = (int)strlen(szTrueNameTemp); + if (*porig == psepc && slen + 2 < _MAX_PATH) + STRCPY(szTrueNameTemp + slen, "\\*"); + /* Skip "", "." and "..". */ if (ptrue > ptruePrev && (ptruePrev[0] != '.' || (ptruePrev[1] != NUL && (ptruePrev[1] != '.' || ptruePrev[2] != NUL))) - && (hFind = FindFirstFile(szTrueName, &fb)) + && (hFind = FindFirstFile(szTrueNameTemp, &fb)) != INVALID_HANDLE_VALUE) { c = *porig; @@ -2578,30 +2688,73 @@ } /* + * Create directory "name". + * Return 0 on success, -1 on error. + */ + int +mch_mkdir(char_u *name) +{ +#ifdef FEAT_MBYTE + if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) + { + WCHAR *p; + int retval; + + p = enc_to_utf16(name, NULL); + if (p == NULL) + return -1; + retval = _wmkdir(p); + vim_free(p); + return retval; + } +#endif + return _mkdir(name); +} + +/* * Return TRUE if file "fname" has more than one link. */ int mch_is_linked(char_u *fname) { + BY_HANDLE_FILE_INFORMATION info; + + return win32_fileinfo(fname, &info) == FILEINFO_OK + && info.nNumberOfLinks > 1; +} + +/* + * Get the by-handle-file-information for "fname". + * Returns FILEINFO_OK when OK. + * returns FILEINFO_ENC_FAIL when enc_to_utf16() failed. + * Returns FILEINFO_READ_FAIL when CreateFile() failed. + * Returns FILEINFO_INFO_FAIL when GetFileInformationByHandle() failed. + */ + int +win32_fileinfo(char_u *fname, BY_HANDLE_FILE_INFORMATION *info) +{ HANDLE hFile; - int res = 0; - BY_HANDLE_FILE_INFORMATION inf; + int res = FILEINFO_READ_FAIL; #ifdef FEAT_MBYTE WCHAR *wn = NULL; if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) + { wn = enc_to_utf16(fname, NULL); + if (wn == NULL) + res = FILEINFO_ENC_FAIL; + } if (wn != NULL) { hFile = CreateFileW(wn, /* file name */ GENERIC_READ, /* access mode */ - 0, /* share mode */ + FILE_SHARE_READ | FILE_SHARE_WRITE, /* share mode */ NULL, /* security descriptor */ OPEN_EXISTING, /* creation disposition */ - 0, /* file attributes */ + FILE_FLAG_BACKUP_SEMANTICS, /* file attributes */ NULL); /* handle to template file */ if (hFile == INVALID_HANDLE_VALUE - && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) + && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) { /* Retry with non-wide function (for Windows 98). */ vim_free(wn); @@ -2612,17 +2765,18 @@ #endif hFile = CreateFile(fname, /* file name */ GENERIC_READ, /* access mode */ - 0, /* share mode */ + FILE_SHARE_READ | FILE_SHARE_WRITE, /* share mode */ NULL, /* security descriptor */ OPEN_EXISTING, /* creation disposition */ - 0, /* file attributes */ + FILE_FLAG_BACKUP_SEMANTICS, /* file attributes */ NULL); /* handle to template file */ if (hFile != INVALID_HANDLE_VALUE) { - if (GetFileInformationByHandle(hFile, &inf) != 0 - && inf.nNumberOfLinks > 1) - res = 1; + if (GetFileInformationByHandle(hFile, info) != 0) + res = FILEINFO_OK; + else + res = FILEINFO_INFO_FAIL; CloseHandle(hFile); } @@ -3104,7 +3258,7 @@ * 4. Prompt the user to press a key to close the console window */ static int -mch_system(char *cmd, int options) +mch_system_classic(char *cmd, int options) { STARTUPINFO si; PROCESS_INFORMATION pi; @@ -3120,9 +3274,10 @@ * It's nicer to run a filter command in a minimized window, but in * Windows 95 this makes the command MUCH slower. We can't do it under * Win32s either as it stops the synchronous spawn workaround working. + * Don't activate the window to keep focus on Vim. */ if ((options & SHELL_DOOUT) && !mch_windows95() && !gui_is_win32s()) - si.wShowWindow = SW_SHOWMINIMIZED; + si.wShowWindow = SW_SHOWMINNOACTIVE; else si.wShowWindow = SW_SHOWNORMAL; si.cbReserved2 = 0; @@ -3160,10 +3315,10 @@ { MSG msg; - if (PeekMessage(&msg, (HWND)NULL, 0, 0, PM_REMOVE)) + if (pPeekMessage(&msg, (HWND)NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); - DispatchMessage(&msg); + pDispatchMessage(&msg); } if (WaitForSingleObject(pi.hProcess, delay) != WAIT_TIMEOUT) break; @@ -3208,6 +3363,506 @@ return ret; } + +/* + * Thread launched by the gui to send the current buffer data to the + * process. This way avoid to hang up vim totally if the children + * process take a long time to process the lines. + */ + static DWORD WINAPI +sub_process_writer(LPVOID param) +{ + HANDLE g_hChildStd_IN_Wr = param; + linenr_T lnum = curbuf->b_op_start.lnum; + DWORD len = 0; + DWORD l; + char_u *lp = ml_get(lnum); + char_u *s; + int written = 0; + + for (;;) + { + l = (DWORD)STRLEN(lp + written); + if (l == 0) + len = 0; + else if (lp[written] == NL) + { + /* NL -> NUL translation */ + WriteFile(g_hChildStd_IN_Wr, "", 1, &len, NULL); + } + else + { + s = vim_strchr(lp + written, NL); + WriteFile(g_hChildStd_IN_Wr, (char *)lp + written, + s == NULL ? l : (DWORD)(s - (lp + written)), + &len, NULL); + } + if (len == (int)l) + { + /* Finished a line, add a NL, unless this line should not have + * one. */ + if (lnum != curbuf->b_op_end.lnum + || !curbuf->b_p_bin + || (lnum != curbuf->b_no_eol_lnum + && (lnum != curbuf->b_ml.ml_line_count + || curbuf->b_p_eol))) + { + WriteFile(g_hChildStd_IN_Wr, "\n", 1, &ignored, NULL); + } + + ++lnum; + if (lnum > curbuf->b_op_end.lnum) + break; + + lp = ml_get(lnum); + written = 0; + } + else if (len > 0) + written += len; + } + + /* finished all the lines, close pipe */ + CloseHandle(g_hChildStd_IN_Wr); + ExitThread(0); +} + + +# define BUFLEN 100 /* length for buffer, stolen from unix version */ + +/* + * This function read from the children's stdout and write the + * data on screen or in the buffer accordingly. + */ + static void +dump_pipe(int options, + HANDLE g_hChildStd_OUT_Rd, + garray_T *ga, + char_u buffer[], + DWORD *buffer_off) +{ + DWORD availableBytes = 0; + DWORD i; + int ret; + DWORD len; + DWORD toRead; + int repeatCount; + + /* we query the pipe to see if there is any data to read + * to avoid to perform a blocking read */ + ret = PeekNamedPipe(g_hChildStd_OUT_Rd, /* pipe to query */ + NULL, /* optional buffer */ + 0, /* buffer size */ + NULL, /* number of read bytes */ + &availableBytes, /* available bytes total */ + NULL); /* byteLeft */ + + repeatCount = 0; + /* We got real data in the pipe, read it */ + while (ret != 0 && availableBytes > 0) + { + repeatCount++; + toRead = +# ifdef FEAT_MBYTE + (DWORD)(BUFLEN - *buffer_off); +# else + (DWORD)BUFLEN; +# endif + toRead = availableBytes < toRead ? availableBytes : toRead; + ReadFile(g_hChildStd_OUT_Rd, buffer +# ifdef FEAT_MBYTE + + *buffer_off, toRead +# else + , toRead +# endif + , &len, NULL); + + /* If we haven't read anything, there is a problem */ + if (len == 0) + break; + + availableBytes -= len; + + if (options & SHELL_READ) + { + /* Do NUL -> NL translation, append NL separated + * lines to the current buffer. */ + for (i = 0; i < len; ++i) + { + if (buffer[i] == NL) + append_ga_line(ga); + else if (buffer[i] == NUL) + ga_append(ga, NL); + else + ga_append(ga, buffer[i]); + } + } +# ifdef FEAT_MBYTE + else if (has_mbyte) + { + int l; + int c; + char_u *p; + + len += *buffer_off; + buffer[len] = NUL; + + /* Check if the last character in buffer[] is + * incomplete, keep these bytes for the next + * round. */ + for (p = buffer; p < buffer + len; p += l) + { + l = mb_cptr2len(p); + if (l == 0) + l = 1; /* NUL byte? */ + else if (MB_BYTE2LEN(*p) != l) + break; + } + if (p == buffer) /* no complete character */ + { + /* avoid getting stuck at an illegal byte */ + if (len >= 12) + ++p; + else + { + *buffer_off = len; + return; + } + } + c = *p; + *p = NUL; + msg_puts(buffer); + if (p < buffer + len) + { + *p = c; + *buffer_off = (DWORD)((buffer + len) - p); + mch_memmove(buffer, p, *buffer_off); + return; + } + *buffer_off = 0; + } +# endif /* FEAT_MBYTE */ + else + { + buffer[len] = NUL; + msg_puts(buffer); + } + + windgoto(msg_row, msg_col); + cursor_on(); + out_flush(); + } +} + +/* + * Version of system to use for windows NT > 5.0 (Win2K), use pipe + * for communication and doesn't open any new window. + */ + static int +mch_system_piped(char *cmd, int options) +{ + STARTUPINFO si; + PROCESS_INFORMATION pi; + DWORD ret = 0; + + HANDLE g_hChildStd_IN_Rd = NULL; + HANDLE g_hChildStd_IN_Wr = NULL; + HANDLE g_hChildStd_OUT_Rd = NULL; + HANDLE g_hChildStd_OUT_Wr = NULL; + + char_u buffer[BUFLEN + 1]; /* reading buffer + size */ + DWORD len; + + /* buffer used to receive keys */ + char_u ta_buf[BUFLEN + 1]; /* TypeAHead */ + int ta_len = 0; /* valid bytes in ta_buf[] */ + + DWORD i; + int c; + int noread_cnt = 0; + garray_T ga; + int delay = 1; + DWORD buffer_off = 0; /* valid bytes in buffer[] */ + char *p = NULL; + + SECURITY_ATTRIBUTES saAttr; + + /* Set the bInheritHandle flag so pipe handles are inherited. */ + saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); + saAttr.bInheritHandle = TRUE; + saAttr.lpSecurityDescriptor = NULL; + + if ( ! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0) + /* Ensure the read handle to the pipe for STDOUT is not inherited. */ + || ! pSetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) + /* Create a pipe for the child process's STDIN. */ + || ! CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0) + /* Ensure the write handle to the pipe for STDIN is not inherited. */ + || ! pSetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) ) + { + CloseHandle(g_hChildStd_IN_Rd); + CloseHandle(g_hChildStd_IN_Wr); + CloseHandle(g_hChildStd_OUT_Rd); + CloseHandle(g_hChildStd_OUT_Wr); + MSG_PUTS(_("\nCannot create pipes\n")); + } + + si.cb = sizeof(si); + si.lpReserved = NULL; + si.lpDesktop = NULL; + si.lpTitle = NULL; + si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; + + /* set-up our file redirection */ + si.hStdError = g_hChildStd_OUT_Wr; + si.hStdOutput = g_hChildStd_OUT_Wr; + si.hStdInput = g_hChildStd_IN_Rd; + si.wShowWindow = SW_HIDE; + si.cbReserved2 = 0; + si.lpReserved2 = NULL; + + if (options & SHELL_READ) + ga_init2(&ga, 1, BUFLEN); + + if (cmd != NULL) + { + p = (char *)vim_strsave((char_u *)cmd); + if (p != NULL) + unescape_shellxquote((char_u *)p, p_sxe); + else + p = cmd; + } + + /* Now, run the command */ + CreateProcess(NULL, /* Executable name */ + p, /* Command to execute */ + NULL, /* Process security attributes */ + NULL, /* Thread security attributes */ + + // this command can be litigious, handle inheritance was + // deactivated for pending temp file, but, if we deactivate + // it, the pipes don't work for some reason. + TRUE, /* Inherit handles, first deactivated, + * but needed */ + CREATE_DEFAULT_ERROR_MODE, /* Creation flags */ + NULL, /* Environment */ + NULL, /* Current directory */ + &si, /* Startup information */ + &pi); /* Process information */ + + if (p != cmd) + vim_free(p); + + /* Close our unused side of the pipes */ + CloseHandle(g_hChildStd_IN_Rd); + CloseHandle(g_hChildStd_OUT_Wr); + + if (options & SHELL_WRITE) + { + HANDLE thread = + CreateThread(NULL, /* security attributes */ + 0, /* default stack size */ + sub_process_writer, /* function to be executed */ + g_hChildStd_IN_Wr, /* parameter */ + 0, /* creation flag, start immediately */ + NULL); /* we don't care about thread id */ + CloseHandle(thread); + g_hChildStd_IN_Wr = NULL; + } + + /* Keep updating the window while waiting for the shell to finish. */ + for (;;) + { + MSG msg; + + if (PeekMessage(&msg, (HWND)NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + /* write pipe information in the window */ + if ((options & (SHELL_READ|SHELL_WRITE)) +# ifdef FEAT_GUI + || gui.in_use +# endif + ) + { + len = 0; + if (!(options & SHELL_EXPAND) + && ((options & + (SHELL_READ|SHELL_WRITE|SHELL_COOKED)) + != (SHELL_READ|SHELL_WRITE|SHELL_COOKED) +# ifdef FEAT_GUI + || gui.in_use +# endif + ) + && (ta_len > 0 || noread_cnt > 4)) + { + if (ta_len == 0) + { + /* Get extra characters when we don't have any. Reset the + * counter and timer. */ + noread_cnt = 0; +# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) + gettimeofday(&start_tv, NULL); +# endif + len = ui_inchar(ta_buf, BUFLEN, 10L, 0); + } + if (ta_len > 0 || len > 0) + { + /* + * For pipes: Check for CTRL-C: send interrupt signal to + * child. Check for CTRL-D: EOF, close pipe to child. + */ + if (len == 1 && cmd != NULL) + { + if (ta_buf[ta_len] == Ctrl_C) + { + /* Learn what exit code is expected, for + * now put 9 as SIGKILL */ + TerminateProcess(pi.hProcess, 9); + } + if (ta_buf[ta_len] == Ctrl_D) + { + CloseHandle(g_hChildStd_IN_Wr); + g_hChildStd_IN_Wr = NULL; + } + } + + /* replace K_BS by and K_DEL by */ + for (i = ta_len; i < ta_len + len; ++i) + { + if (ta_buf[i] == CSI && len - i > 2) + { + c = TERMCAP2KEY(ta_buf[i + 1], ta_buf[i + 2]); + if (c == K_DEL || c == K_KDEL || c == K_BS) + { + mch_memmove(ta_buf + i + 1, ta_buf + i + 3, + (size_t)(len - i - 2)); + if (c == K_DEL || c == K_KDEL) + ta_buf[i] = DEL; + else + ta_buf[i] = Ctrl_H; + len -= 2; + } + } + else if (ta_buf[i] == '\r') + ta_buf[i] = '\n'; +# ifdef FEAT_MBYTE + if (has_mbyte) + i += (*mb_ptr2len_len)(ta_buf + i, + ta_len + len - i) - 1; +# endif + } + + /* + * For pipes: echo the typed characters. For a pty this + * does not seem to work. + */ + for (i = ta_len; i < ta_len + len; ++i) + { + if (ta_buf[i] == '\n' || ta_buf[i] == '\b') + msg_putchar(ta_buf[i]); +# ifdef FEAT_MBYTE + else if (has_mbyte) + { + int l = (*mb_ptr2len)(ta_buf + i); + + msg_outtrans_len(ta_buf + i, l); + i += l - 1; + } +# endif + else + msg_outtrans_len(ta_buf + i, 1); + } + windgoto(msg_row, msg_col); + out_flush(); + + ta_len += len; + + /* + * Write the characters to the child, unless EOF has been + * typed for pipes. Write one character at a time, to + * avoid losing too much typeahead. When writing buffer + * lines, drop the typed characters (only check for + * CTRL-C). + */ + if (options & SHELL_WRITE) + ta_len = 0; + else if (g_hChildStd_IN_Wr != NULL) + { + WriteFile(g_hChildStd_IN_Wr, (char*)ta_buf, + 1, &len, NULL); + // if we are typing in, we want to keep things reactive + delay = 1; + if (len > 0) + { + ta_len -= len; + mch_memmove(ta_buf, ta_buf + len, ta_len); + } + } + } + } + } + + if (ta_len) + ui_inchar_undo(ta_buf, ta_len); + + if (WaitForSingleObject(pi.hProcess, delay) != WAIT_TIMEOUT) + { + dump_pipe(options, g_hChildStd_OUT_Rd, &ga, buffer, &buffer_off); + break; + } + + ++noread_cnt; + dump_pipe(options, g_hChildStd_OUT_Rd, &ga, buffer, &buffer_off); + + /* We start waiting for a very short time and then increase it, so + * that we respond quickly when the process is quick, and don't + * consume too much overhead when it's slow. */ + if (delay < 50) + delay += 10; + } + + /* Close the pipe */ + CloseHandle(g_hChildStd_OUT_Rd); + if (g_hChildStd_IN_Wr != NULL) + CloseHandle(g_hChildStd_IN_Wr); + + WaitForSingleObject(pi.hProcess, INFINITE); + + /* Get the command exit code */ + GetExitCodeProcess(pi.hProcess, &ret); + + if (options & SHELL_READ) + { + if (ga.ga_len > 0) + { + append_ga_line(&ga); + /* remember that the NL was missing */ + curbuf->b_no_eol_lnum = curwin->w_cursor.lnum; + } + else + curbuf->b_no_eol_lnum = 0; + ga_clear(&ga); + } + + /* Close the handles to the subprocess, so that it goes away */ + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + + return ret; +} + + static int +mch_system(char *cmd, int options) +{ + /* if we can pipe and the shelltemp option is off */ + if (allowPiping && !p_stmp) + return mch_system_piped(cmd, options); + else + return mch_system_classic(cmd, options); +} #else # define mch_system(c, o) system(c) @@ -3278,84 +3933,147 @@ else { /* we use "command" or "cmd" to start the shell; slow but easy */ - char_u *newcmd; - long_u cmdlen = ( -#ifdef FEAT_GUI_W32 - STRLEN(vimrun_path) + -#endif - STRLEN(p_sh) + STRLEN(p_shcf) + STRLEN(cmd) + 10); + char_u *newcmd = NULL; + char_u *cmdbase = cmd; + long_u cmdlen; + + /* Skip a leading ", ( and "(. */ + if (*cmdbase == '"' ) + ++cmdbase; + if (*cmdbase == '(') + ++cmdbase; + + if ((STRNICMP(cmdbase, "start", 5) == 0) && vim_iswhite(cmdbase[5])) + { + STARTUPINFO si; + PROCESS_INFORMATION pi; + DWORD flags = CREATE_NEW_CONSOLE; + char_u *p; + + si.cb = sizeof(si); + si.lpReserved = NULL; + si.lpDesktop = NULL; + si.lpTitle = NULL; + si.dwFlags = 0; + si.cbReserved2 = 0; + si.lpReserved2 = NULL; + + cmdbase = skipwhite(cmdbase + 5); + if ((STRNICMP(cmdbase, "/min", 4) == 0) + && vim_iswhite(cmdbase[4])) + { + cmdbase = skipwhite(cmdbase + 4); + si.dwFlags = STARTF_USESHOWWINDOW; + si.wShowWindow = SW_SHOWMINNOACTIVE; + } + else if ((STRNICMP(cmdbase, "/b", 2) == 0) + && vim_iswhite(cmdbase[2])) + { + cmdbase = skipwhite(cmdbase + 2); + flags = CREATE_NO_WINDOW; + si.dwFlags = STARTF_USESTDHANDLES; + si.hStdInput = CreateFile("\\\\.\\NUL", // File name + GENERIC_READ, // Access flags + 0, // Share flags + NULL, // Security att. + OPEN_EXISTING, // Open flags + FILE_ATTRIBUTE_NORMAL, // File att. + NULL); // Temp file + si.hStdOutput = si.hStdInput; + si.hStdError = si.hStdInput; + } - newcmd = lalloc(cmdlen, TRUE); - if (newcmd != NULL) - { - char_u *cmdbase = (*cmd == '"' ? cmd + 1 : cmd); + /* Remove a trailing ", ) and )" if they have a match + * at the start of the command. */ + if (cmdbase > cmd) + { + p = cmdbase + STRLEN(cmdbase); + if (p > cmdbase && p[-1] == '"' && *cmd == '"') + *--p = NUL; + if (p > cmdbase && p[-1] == ')' + && (*cmd =='(' || cmd[1] == '(')) + *--p = NUL; + } - if ((STRNICMP(cmdbase, "start", 5) == 0) && vim_iswhite(cmdbase[5])) + newcmd = cmdbase; + unescape_shellxquote(cmdbase, p_sxe); + + /* + * If creating new console, arguments are passed to the + * 'cmd.exe' as-is. If it's not, arguments are not treated + * correctly for current 'cmd.exe'. So unescape characters in + * shellxescape except '|' for avoiding to be treated as + * argument to them. Pass the arguments to sub-shell. + */ + if (flags != CREATE_NEW_CONSOLE) { - STARTUPINFO si; - PROCESS_INFORMATION pi; - - si.cb = sizeof(si); - si.lpReserved = NULL; - si.lpDesktop = NULL; - si.lpTitle = NULL; - si.dwFlags = 0; - si.cbReserved2 = 0; - si.lpReserved2 = NULL; - - cmdbase = skipwhite(cmdbase + 5); - if ((STRNICMP(cmdbase, "/min", 4) == 0) - && vim_iswhite(cmdbase[4])) - { - cmdbase = skipwhite(cmdbase + 4); - si.dwFlags = STARTF_USESHOWWINDOW; - si.wShowWindow = SW_SHOWMINNOACTIVE; - } + char_u *subcmd; + char_u *cmd_shell = mch_getenv("COMSPEC"); - /* When the command is in double quotes, but 'shellxquote' is - * empty, keep the double quotes around the command. - * Otherwise remove the double quotes, they aren't needed - * here, because we don't use a shell to run the command. */ - if (*cmd == '"' && *p_sxq == NUL) - { - newcmd[0] = '"'; - STRCPY(newcmd + 1, cmdbase); - } - else + if (cmd_shell == NULL || *cmd_shell == NUL) + cmd_shell = default_shell(); + + subcmd = vim_strsave_escaped_ext(cmdbase, "|", '^', FALSE); + if (subcmd != NULL) { - STRCPY(newcmd, cmdbase); - if (*cmd == '"' && *newcmd != NUL) - newcmd[STRLEN(newcmd) - 1] = NUL; + /* make "cmd.exe /c arguments" */ + cmdlen = STRLEN(cmd_shell) + STRLEN(subcmd) + 5; + newcmd = lalloc(cmdlen, TRUE); + if (newcmd != NULL) + vim_snprintf((char *)newcmd, cmdlen, "%s /c %s", + cmd_shell, subcmd); + else + newcmd = cmdbase; + vim_free(subcmd); } + } - /* - * Now, start the command as a process, so that it doesn't - * inherit our handles which causes unpleasant dangling swap - * files if we exit before the spawned process - */ - if (CreateProcess (NULL, // Executable name - newcmd, // Command to execute - NULL, // Process security attributes - NULL, // Thread security attributes - FALSE, // Inherit handles - CREATE_NEW_CONSOLE, // Creation flags - NULL, // Environment - NULL, // Current directory - &si, // Startup information - &pi)) // Process information - x = 0; - else - { - x = -1; + /* + * Now, start the command as a process, so that it doesn't + * inherit our handles which causes unpleasant dangling swap + * files if we exit before the spawned process + */ + if (CreateProcess(NULL, // Executable name + newcmd, // Command to execute + NULL, // Process security attributes + NULL, // Thread security attributes + FALSE, // Inherit handles + flags, // Creation flags + NULL, // Environment + NULL, // Current directory + &si, // Startup information + &pi)) // Process information + x = 0; + else + { + x = -1; #ifdef FEAT_GUI_W32 - EMSG(_("E371: Command not found")); + EMSG(_("E371: Command not found")); #endif - } - /* Close the handles to the subprocess, so that it goes away */ - CloseHandle(pi.hThread); - CloseHandle(pi.hProcess); } - else + + if (newcmd != cmdbase) + vim_free(newcmd); + + if (si.hStdInput != NULL) + { + /* Close the handle to \\.\NUL */ + CloseHandle(si.hStdInput); + } + /* Close the handles to the subprocess, so that it goes away */ + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + } + else + { + cmdlen = ( +#ifdef FEAT_GUI_W32 + (allowPiping && !p_stmp ? 0 : STRLEN(vimrun_path)) + +#endif + STRLEN(p_sh) + STRLEN(p_shcf) + STRLEN(cmd) + 10); + + newcmd = lalloc(cmdlen, TRUE); + if (newcmd != NULL) { #if defined(FEAT_GUI_W32) if (need_vimrun_warning) @@ -3368,7 +4086,7 @@ MB_ICONWARNING); need_vimrun_warning = FALSE; } - if (!s_dont_use_vimrun) + if (!s_dont_use_vimrun && (!allowPiping || p_stmp)) /* Use vimrun to execute the command. It opens a console * window, which can be closed without killing Vim. */ vim_snprintf((char *)newcmd, cmdlen, "%s%s%s %s %s", @@ -3381,8 +4099,8 @@ vim_snprintf((char *)newcmd, cmdlen, "%s %s %s", p_sh, p_shcf, cmd); x = mch_system((char *)newcmd, options); + vim_free(newcmd); } - vim_free(newcmd); } } @@ -3392,7 +4110,8 @@ /* Print the return value, unless "vimrun" was used. */ if (x != 0 && !(options & SHELL_SILENT) && !emsg_silent #if defined(FEAT_GUI_W32) - && ((options & SHELL_DOOUT) || s_dont_use_vimrun) + && ((options & SHELL_DOOUT) || s_dont_use_vimrun + || (allowPiping && !p_stmp)) #endif ) { @@ -4273,18 +4992,34 @@ /* - * How much memory is available? + * How much memory is available in Kbyte? * Return sum of available physical and page file memory. */ /*ARGSUSED*/ long_u mch_avail_mem(int special) { - MEMORYSTATUS ms; +#ifdef MEMORYSTATUSEX + PlatformId(); + if (g_PlatformId == VER_PLATFORM_WIN32_NT) + { + MEMORYSTATUSEX ms; + + /* Need to use GlobalMemoryStatusEx() when there is more memory than + * what fits in 32 bits. But it's not always available. */ + ms.dwLength = sizeof(MEMORYSTATUSEX); + GlobalMemoryStatusEx(&ms); + return (long_u)((ms.ullAvailPhys + ms.ullAvailPageFile) >> 10); + } + else +#endif + { + MEMORYSTATUS ms; - ms.dwLength = sizeof(MEMORYSTATUS); - GlobalMemoryStatus(&ms); - return (long_u) (ms.dwAvailPhys + ms.dwAvailPageFile); + ms.dwLength = sizeof(MEMORYSTATUS); + GlobalMemoryStatus(&ms); + return (long_u)((ms.dwAvailPhys + ms.dwAvailPageFile) >> 10); + } } #ifdef FEAT_MBYTE diff -Naur vim73.orig/src/os_win32.h vim73/src/os_win32.h --- vim73.orig/src/os_win32.h 2010-05-31 19:50:24.000000000 +0000 +++ vim73/src/os_win32.h 2012-07-20 20:31:12.314307528 +0000 @@ -191,5 +191,19 @@ #ifdef __BORLANDC__ # define vim_mkdir(x, y) mkdir(x) #else -# define vim_mkdir(x, y) _mkdir(x) +# define vim_mkdir(x, y) mch_mkdir(x) +#endif + +/* Enable common dialogs input unicode from IME if posible. */ +#ifdef FEAT_MBYTE + /* The variables are defined in os_win32.c. */ +extern LRESULT (WINAPI *pDispatchMessage)(LPMSG); +extern BOOL (WINAPI *pGetMessage)(LPMSG, HWND, UINT, UINT); +extern BOOL (WINAPI *pIsDialogMessage)(HWND, LPMSG); +extern BOOL (WINAPI *pPeekMessage)(LPMSG, HWND, UINT, UINT, UINT); +#else +# define pDispatchMessage DispatchMessage +# define pGetMessage GetMessage +# define pIsDialogMessage IsDialogMessage +# define pPeekMessage PeekMessage #endif diff -Naur vim73.orig/src/popupmnu.c vim73/src/popupmnu.c --- vim73.orig/src/popupmnu.c 2010-08-08 13:14:58.000000000 +0000 +++ vim73/src/popupmnu.c 2012-07-20 20:31:08.150971192 +0000 @@ -558,8 +558,11 @@ win_T *curwin_save = curwin; int res = OK; - /* Open a preview window. 3 lines by default. */ + /* Open a preview window. 3 lines by default. Prefer + * 'previewheight' if set and smaller. */ g_do_tagpreview = 3; + if (p_pvh > 0 && p_pvh < g_do_tagpreview) + g_do_tagpreview = p_pvh; resized = prepare_tagpreview(FALSE); g_do_tagpreview = 0; diff -Naur vim73.orig/src/proto/buffer.pro vim73/src/proto/buffer.pro --- vim73.orig/src/proto/buffer.pro 2010-08-15 12:30:19.000000000 +0000 +++ vim73/src/proto/buffer.pro 2012-07-20 20:31:18.014311616 +0000 @@ -1,7 +1,7 @@ /* buffer.c */ int open_buffer __ARGS((int read_stdin, exarg_T *eap, int flags)); int buf_valid __ARGS((buf_T *buf)); -void close_buffer __ARGS((win_T *win, buf_T *buf, int action)); +void close_buffer __ARGS((win_T *win, buf_T *buf, int action, int abort_if_last)); void buf_clear_file __ARGS((buf_T *buf)); void buf_freeall __ARGS((buf_T *buf, int flags)); void goto_buffer __ARGS((exarg_T *eap, int start, int dir, int count)); @@ -60,6 +60,7 @@ int buf_findsign_id __ARGS((buf_T *buf, linenr_T lnum)); int buf_findsigntype_id __ARGS((buf_T *buf, linenr_T lnum, int typenr)); int buf_signcount __ARGS((buf_T *buf, linenr_T lnum)); +void buf_delete_signs __ARGS((buf_T *buf)); void buf_delete_all_signs __ARGS((void)); void sign_list_placed __ARGS((buf_T *rbuf)); void sign_mark_adjust __ARGS((linenr_T line1, linenr_T line2, long amount, long amount_after)); diff -Naur vim73.orig/src/proto/edit.pro vim73/src/proto/edit.pro --- vim73.orig/src/proto/edit.pro 2010-08-15 12:30:22.000000000 +0000 +++ vim73/src/proto/edit.pro 2012-07-20 20:31:16.054310214 +0000 @@ -39,4 +39,5 @@ int hkmap __ARGS((int c)); void ins_scroll __ARGS((void)); void ins_horscroll __ARGS((void)); +int ins_copychar __ARGS((linenr_T lnum)); /* vim: set ft=c : */ diff -Naur vim73.orig/src/proto/eval.pro vim73/src/proto/eval.pro --- vim73.orig/src/proto/eval.pro 2010-08-15 12:30:23.000000000 +0000 +++ vim73/src/proto/eval.pro 2012-07-20 20:31:18.257645124 +0000 @@ -23,6 +23,7 @@ list_T *eval_spell_expr __ARGS((char_u *badword, char_u *expr)); int get_spellword __ARGS((list_T *list, char_u **pp)); typval_T *eval_expr __ARGS((char_u *arg, char_u **nextcmd)); +int call_vim_function __ARGS((char_u *func, int argc, char_u **argv, int safe, typval_T *rettv)); void *call_func_retstr __ARGS((char_u *func, int argc, char_u **argv, int safe)); long call_func_retnr __ARGS((char_u *func, int argc, char_u **argv, int safe)); void *call_func_retlist __ARGS((char_u *func, int argc, char_u **argv, int safe)); @@ -45,13 +46,23 @@ list_T *list_alloc __ARGS((void)); void list_unref __ARGS((list_T *l)); void list_free __ARGS((list_T *l, int recurse)); +listitem_T *listitem_alloc __ARGS((void)); +void listitem_remove __ARGS((list_T *l, listitem_T *item)); dictitem_T *dict_lookup __ARGS((hashitem_T *hi)); +listitem_T *list_find __ARGS((list_T *l, long n)); char_u *list_find_str __ARGS((list_T *l, long idx)); +void list_append __ARGS((list_T *l, listitem_T *item)); int list_append_tv __ARGS((list_T *l, typval_T *tv)); int list_append_dict __ARGS((list_T *list, dict_T *dict)); int list_append_string __ARGS((list_T *l, char_u *str, int len)); +int list_insert_tv __ARGS((list_T *l, typval_T *tv, listitem_T *item)); +void list_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2)); int garbage_collect __ARGS((void)); +void set_ref_in_ht __ARGS((hashtab_T *ht, int copyID)); +void set_ref_in_list __ARGS((list_T *l, int copyID)); +void set_ref_in_item __ARGS((typval_T *tv, int copyID)); dict_T *dict_alloc __ARGS((void)); +void dict_unref __ARGS((dict_T *d)); dictitem_T *dictitem_alloc __ARGS((char_u *key)); void dictitem_free __ARGS((dictitem_T *item)); int dict_add __ARGS((dict_T *d, dictitem_T *item)); @@ -62,6 +73,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)); +int func_call __ARGS((char_u *name, typval_T *args, dict_T *selfdict, typval_T *rettv)); 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)); @@ -81,7 +93,7 @@ char_u *get_tv_string_chk __ARGS((typval_T *varp)); char_u *get_var_value __ARGS((char_u *name)); void new_script_vars __ARGS((scid_T id)); -void init_var_dict __ARGS((dict_T *dict, dictitem_T *dict_var)); +void init_var_dict __ARGS((dict_T *dict, dictitem_T *dict_var, int scope)); void vars_clear __ARGS((hashtab_T *ht)); void copy_tv __ARGS((typval_T *from, typval_T *to)); void ex_echo __ARGS((exarg_T *eap)); @@ -92,6 +104,8 @@ void func_dump_profile __ARGS((FILE *fd)); char_u *get_user_func_name __ARGS((expand_T *xp, int idx)); void ex_delfunction __ARGS((exarg_T *eap)); +void func_unref __ARGS((char_u *name)); +void func_ref __ARGS((char_u *name)); void ex_return __ARGS((exarg_T *eap)); int do_return __ARGS((exarg_T *eap, int reanimate, int is_cmd, void *rettv)); void discard_pending_return __ARGS((void *rettv)); diff -Naur vim73.orig/src/proto/ex_cmds.pro vim73/src/proto/ex_cmds.pro --- vim73.orig/src/proto/ex_cmds.pro 2010-08-15 12:30:24.000000000 +0000 +++ vim73/src/proto/ex_cmds.pro 2012-07-20 20:31:15.897643435 +0000 @@ -23,6 +23,7 @@ void ex_update __ARGS((exarg_T *eap)); void ex_write __ARGS((exarg_T *eap)); int do_write __ARGS((exarg_T *eap)); +int check_overwrite __ARGS((exarg_T *eap, buf_T *buf, char_u *fname, char_u *ffname, int other)); void ex_wnext __ARGS((exarg_T *eap)); void do_wqall __ARGS((exarg_T *eap)); int not_writing __ARGS((void)); diff -Naur vim73.orig/src/proto/ex_cmds2.pro vim73/src/proto/ex_cmds2.pro --- vim73.orig/src/proto/ex_cmds2.pro 2010-08-15 12:30:25.000000000 +0000 +++ vim73/src/proto/ex_cmds2.pro 2012-07-20 20:31:17.374311158 +0000 @@ -42,7 +42,7 @@ int check_fname __ARGS((void)); int buf_write_all __ARGS((buf_T *buf, int forceit)); int get_arglist __ARGS((garray_T *gap, char_u *str)); -int get_arglist_exp __ARGS((char_u *str, int *fcountp, char_u ***fnamesp)); +int get_arglist_exp __ARGS((char_u *str, int *fcountp, char_u ***fnamesp, int wig)); void set_arglist __ARGS((char_u *str)); void check_arg_idx __ARGS((win_T *win)); void ex_args __ARGS((exarg_T *eap)); @@ -83,5 +83,7 @@ char_u *get_mess_lang __ARGS((void)); void set_lang_var __ARGS((void)); void ex_language __ARGS((exarg_T *eap)); +void free_locales __ARGS((void)); char_u *get_lang_arg __ARGS((expand_T *xp, int idx)); +char_u *get_locales __ARGS((expand_T *xp, int idx)); /* vim: set ft=c : */ diff -Naur vim73.orig/src/proto/ex_docmd.pro vim73/src/proto/ex_docmd.pro --- vim73.orig/src/proto/ex_docmd.pro 2010-08-15 12:30:26.000000000 +0000 +++ vim73/src/proto/ex_docmd.pro 2012-07-20 20:31:14.470975744 +0000 @@ -1,7 +1,7 @@ /* ex_docmd.c */ void do_exmode __ARGS((int improved)); int do_cmdline_cmd __ARGS((char_u *cmd)); -int do_cmdline __ARGS((char_u *cmdline, char_u *(*getline)(int, void *, int), void *cookie, int flags)); +int do_cmdline __ARGS((char_u *cmdline, char_u *(*fgetline)(int, void *, int), void *cookie, int flags)); 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)); diff -Naur vim73.orig/src/proto/ex_getln.pro vim73/src/proto/ex_getln.pro --- vim73.orig/src/proto/ex_getln.pro 2010-08-15 12:30:27.000000000 +0000 +++ vim73/src/proto/ex_getln.pro 2012-07-20 20:31:11.154306693 +0000 @@ -31,7 +31,7 @@ char_u *addstar __ARGS((char_u *fname, int len, int context)); void set_cmd_context __ARGS((expand_T *xp, char_u *str, int len, int col)); int expand_cmdline __ARGS((expand_T *xp, char_u *str, int col, int *matchcount, char_u ***matches)); -int ExpandGeneric __ARGS((expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file, char_u *((*func)(expand_T *, int)))); +int ExpandGeneric __ARGS((expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file, char_u *((*func)(expand_T *, int)), int escaped)); char_u *globpath __ARGS((char_u *path, char_u *file, int expand_options)); void init_history __ARGS((void)); int get_histtype __ARGS((char_u *name)); diff -Naur vim73.orig/src/proto/fileio.pro vim73/src/proto/fileio.pro --- vim73.orig/src/proto/fileio.pro 2010-08-15 12:30:28.000000000 +0000 +++ vim73/src/proto/fileio.pro 2012-07-20 20:31:15.164309576 +0000 @@ -35,6 +35,7 @@ void do_autocmd __ARGS((char_u *arg, int forceit)); int do_doautocmd __ARGS((char_u *arg, int do_msg)); void ex_doautoall __ARGS((exarg_T *eap)); +int check_nomodeline __ARGS((char_u **argp)); void aucmd_prepbuf __ARGS((aco_save_T *aco, buf_T *buf)); void aucmd_restbuf __ARGS((aco_save_T *aco)); int apply_autocmds __ARGS((event_T event, char_u *fname, char_u *fname_io, int force, buf_T *buf)); @@ -43,6 +44,7 @@ int trigger_cursorhold __ARGS((void)); int has_cursormoved __ARGS((void)); int has_cursormovedI __ARGS((void)); +int has_insertcharpre __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)); @@ -54,4 +56,6 @@ int match_file_pat __ARGS((char_u *pattern, regprog_T *prog, char_u *fname, char_u *sfname, char_u *tail, int allow_dirs)); int match_file_list __ARGS((char_u *list, char_u *sfname, char_u *ffname)); char_u *file_pat_to_reg_pat __ARGS((char_u *pat, char_u *pat_end, char *allow_dirs, int no_bslash)); +long read_eintr __ARGS((int fd, void *buf, size_t bufsize)); +long write_eintr __ARGS((int fd, void *buf, size_t bufsize)); /* vim: set ft=c : */ diff -Naur vim73.orig/src/proto/getchar.pro vim73/src/proto/getchar.pro --- vim73.orig/src/proto/getchar.pro 2010-08-15 12:30:29.000000000 +0000 +++ vim73/src/proto/getchar.pro 2012-07-20 20:31:14.557642473 +0000 @@ -4,8 +4,9 @@ char_u *get_inserted __ARGS((void)); int stuff_empty __ARGS((void)); void typeahead_noflush __ARGS((int c)); -void flush_buffers __ARGS((int typeahead)); +void flush_buffers __ARGS((int flush_typeahead)); void ResetRedobuff __ARGS((void)); +void CancelRedo __ARGS((void)); void saveRedobuff __ARGS((void)); void restoreRedobuff __ARGS((void)); void AppendToRedobuff __ARGS((char_u *s)); @@ -51,6 +52,7 @@ int get_map_mode __ARGS((char_u **cmdp, int forceit)); void map_clear __ARGS((char_u *cmdp, char_u *arg, int forceit, int abbr)); void map_clear_int __ARGS((buf_T *buf, int mode, int local, int abbr)); +char_u *map_mode_to_chars __ARGS((int mode)); int map_to_exists __ARGS((char_u *str, char_u *modechars, int abbr)); int map_to_exists_mode __ARGS((char_u *rhs, int mode, int abbr)); char_u *set_context_in_map_cmd __ARGS((expand_T *xp, char_u *cmd, char_u *arg, int forceit, int isabbrev, int isunmap, cmdidx_T cmdidx)); @@ -61,7 +63,7 @@ int makemap __ARGS((FILE *fd, buf_T *buf)); int put_escstr __ARGS((FILE *fd, char_u *strstart, int what)); void check_map_keycodes __ARGS((void)); -char_u *check_map __ARGS((char_u *keys, int mode, int exact, int ign_mod, int abbr)); +char_u *check_map __ARGS((char_u *keys, int mode, int exact, int ign_mod, int abbr, mapblock_T **mp_ptr, int *local_ptr)); void init_mappings __ARGS((void)); void add_map __ARGS((char_u *map, int mode)); /* vim: set ft=c : */ diff -Naur vim73.orig/src/proto/gui_athena.pro vim73/src/proto/gui_athena.pro --- vim73.orig/src/proto/gui_athena.pro 2010-08-15 12:31:06.000000000 +0000 +++ vim73/src/proto/gui_athena.pro 2012-07-20 20:31:09.297638687 +0000 @@ -27,5 +27,5 @@ void gui_mch_set_scrollbar_colors __ARGS((scrollbar_T *sb)); Window gui_x11_get_wid __ARGS((void)); char_u *gui_mch_browse __ARGS((int saving, char_u *title, char_u *dflt, char_u *ext, char_u *initdir, char_u *filter)); -int gui_mch_dialog __ARGS((int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield)); +int gui_mch_dialog __ARGS((int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield, int ex_cmd)); /* vim: set ft=c : */ diff -Naur vim73.orig/src/proto/gui_gtk.pro vim73/src/proto/gui_gtk.pro --- vim73.orig/src/proto/gui_gtk.pro 2010-08-15 12:31:03.000000000 +0000 +++ vim73/src/proto/gui_gtk.pro 2012-07-20 20:31:09.297638687 +0000 @@ -13,7 +13,7 @@ void gui_mch_destroy_scrollbar __ARGS((scrollbar_T *sb)); char_u *gui_mch_browse __ARGS((int saving, char_u *title, char_u *dflt, char_u *ext, char_u *initdir, char_u *filter)); char_u *gui_mch_browsedir __ARGS((char_u *title, char_u *initdir)); -int gui_mch_dialog __ARGS((int type, char_u *title, char_u *message, char_u *buttons, int def_but, char_u *textfield)); +int gui_mch_dialog __ARGS((int type, char_u *title, char_u *message, char_u *buttons, int def_but, char_u *textfield, int ex_cmd)); void gui_mch_show_popupmenu __ARGS((vimmenu_T *menu)); void gui_make_popup __ARGS((char_u *path_name, int mouse_pos)); void gui_mch_find_dialog __ARGS((exarg_T *eap)); diff -Naur vim73.orig/src/proto/gui_gtk_x11.pro vim73/src/proto/gui_gtk_x11.pro --- vim73.orig/src/proto/gui_gtk_x11.pro 2010-08-15 12:31:07.000000000 +0000 +++ vim73/src/proto/gui_gtk_x11.pro 2012-07-20 20:31:16.160976957 +0000 @@ -4,6 +4,7 @@ void gui_mch_set_blinking __ARGS((long waittime, long on, long off)); void gui_mch_stop_blink __ARGS((void)); void gui_mch_start_blink __ARGS((void)); +int gui_mch_early_init_check __ARGS((void)); int gui_mch_init_check __ARGS((void)); void gui_mch_show_tabline __ARGS((int showit)); int gui_mch_showing_tabline __ARGS((void)); @@ -20,6 +21,7 @@ void gui_mch_set_winpos __ARGS((int x, int y)); int gui_mch_maximized __ARGS((void)); void gui_mch_unmaximize __ARGS((void)); +void gui_mch_newfont __ARGS((void)); void gui_mch_set_shellsize __ARGS((int width, int height, int min_width, int min_height, int base_width, int base_height, int direction)); void gui_mch_get_screen_dimensions __ARGS((int *screen_w, int *screen_h)); void gui_mch_settitle __ARGS((char_u *title, char_u *icon)); diff -Naur vim73.orig/src/proto/gui_mac.pro vim73/src/proto/gui_mac.pro --- vim73.orig/src/proto/gui_mac.pro 2010-08-14 19:40:45.000000000 +0000 +++ vim73/src/proto/gui_mac.pro 2012-07-20 20:31:09.297638687 +0000 @@ -81,7 +81,7 @@ int gui_mch_get_mouse_y __ARGS((void)); void gui_mch_setmouse __ARGS((int x, int y)); void gui_mch_show_popupmenu __ARGS((vimmenu_T *menu)); -int gui_mch_dialog __ARGS((int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield)); +int gui_mch_dialog __ARGS((int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield, int ex_cmd)); char_u *gui_mch_browse __ARGS((int saving, char_u *title, char_u *dflt, char_u *ext, char_u *initdir, char_u *filter)); void gui_mch_set_foreground __ARGS((void)); void gui_mch_show_tabline __ARGS((int showit)); diff -Naur vim73.orig/src/proto/gui_motif.pro vim73/src/proto/gui_motif.pro --- vim73.orig/src/proto/gui_motif.pro 2010-08-15 12:31:04.000000000 +0000 +++ vim73/src/proto/gui_motif.pro 2012-07-20 20:31:09.297638687 +0000 @@ -29,7 +29,7 @@ void gui_mch_set_scrollbar_colors __ARGS((scrollbar_T *sb)); Window gui_x11_get_wid __ARGS((void)); char_u *gui_mch_browse __ARGS((int saving, char_u *title, char_u *dflt, char_u *ext, char_u *initdir, char_u *filter)); -int gui_mch_dialog __ARGS((int type, char_u *title, char_u *message, char_u *button_names, int dfltbutton, char_u *textfield)); +int gui_mch_dialog __ARGS((int type, char_u *title, char_u *message, char_u *button_names, int dfltbutton, char_u *textfield, int ex_cmd)); void gui_mch_enable_footer __ARGS((int showit)); void gui_mch_set_footer __ARGS((char_u *s)); void gui_mch_show_toolbar __ARGS((int showit)); diff -Naur vim73.orig/src/proto/gui_photon.pro vim73/src/proto/gui_photon.pro --- vim73.orig/src/proto/gui_photon.pro 2010-08-15 12:31:10.000000000 +0000 +++ vim73/src/proto/gui_photon.pro 2012-07-20 20:31:09.297638687 +0000 @@ -8,7 +8,7 @@ void gui_mch_update __ARGS((void)); int gui_mch_wait_for_chars __ARGS((int wtime)); char_u *gui_mch_browse __ARGS((int saving, char_u *title, char_u *default_name, char_u *ext, char_u *initdir, char_u *filter)); -int gui_mch_dialog __ARGS((int type, char_u *title, char_u *message, char_u *buttons, int default_button, char_u *textfield)); +int gui_mch_dialog __ARGS((int type, char_u *title, char_u *message, char_u *buttons, int default_button, char_u *textfield, int ex_cmd)); int gui_mch_get_winpos __ARGS((int *x, int *y)); void gui_mch_set_winpos __ARGS((int x, int y)); void gui_mch_set_shellsize __ARGS((int width, int height, int min_width, int min_height, int base_width, int base_height, int direction)); diff -Naur vim73.orig/src/proto/gui_riscos.pro vim73/src/proto/gui_riscos.pro --- vim73.orig/src/proto/gui_riscos.pro 2010-05-15 11:04:08.000000000 +0000 +++ vim73/src/proto/gui_riscos.pro 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -/* Prototypes for gui_riscos.c - * Based on gui_x11_pro.h (10 March 2002 version) - */ -void gui_mch_prepare __ARGS((int *argc, char **argv)); -int gui_mch_init_check __ARGS((void)); -int gui_mch_init __ARGS((void)); -void gui_mch_uninit __ARGS((void)); -void gui_mch_new_colors __ARGS((void)); -int gui_mch_open __ARGS((void)); -void gui_init_tooltip_font __ARGS((void)); -void gui_init_menu_font __ARGS((void));void gui_mch_exit __ARGS((int rc)); -int gui_mch_get_winpos __ARGS((int *x, int *y)); -void gui_mch_set_winpos __ARGS((int x, int y)); -void gui_mch_set_shellsize __ARGS((int width, int height, int min_width, int min_height, int base_width, int base_height)); -void gui_mch_get_screen_dimensions __ARGS((int *screen_w, int *screen_h)); -int gui_mch_init_font __ARGS((char_u *font_name, int do_fontset)); -GuiFont gui_mch_get_font __ARGS((char_u *name, int giveErrorIfMissing)); -int gui_mch_adjust_charheight __ARGS((void)); -void gui_mch_set_font __ARGS((GuiFont font)); -void gui_mch_set_fontset __ARGS((GuiFontset fontset)); -void gui_mch_free_font __ARGS((GuiFont font)); -void gui_mch_free_fontset __ARGS((GuiFontset fontset)); -GuiFontset gui_mch_get_fontset __ARGS((char_u *name, int giveErrorIfMissing, int fixed_width)); -guicolor_T gui_mch_get_color __ARGS((char_u *reqname)); -void gui_mch_set_fg_color __ARGS((guicolor_T color)); -void gui_mch_set_bg_color __ARGS((guicolor_T color)); -void gui_mch_draw_string __ARGS((int row, int col, char_u *s, int len, int flags)); -int gui_mch_haskey __ARGS((char_u *name)); -void gui_mch_beep __ARGS((void)); -void gui_mch_flash __ARGS((int msec)); -void gui_mch_invert_rectangle __ARGS((int r, int c, int nr, int nc)); -void gui_mch_iconify __ARGS((void)); -void gui_mch_set_foreground __ARGS((void)); -void gui_mch_draw_hollow_cursor __ARGS((guicolor_T color)); -void gui_mch_draw_part_cursor __ARGS((int w, int h, guicolor_T color)); -void gui_mch_update __ARGS((void)); -int gui_mch_wait_for_chars __ARGS((long wtime)); -void gui_mch_flush __ARGS((void)); -void gui_mch_clear_block __ARGS((int row1, int col1, int row2, int col2)); -void gui_mch_clear_all __ARGS((void)); -void gui_mch_delete_lines __ARGS((int row, int num_lines)); -void gui_mch_insert_lines __ARGS((int row, int num_lines)); -void clip_mch_lose_selection __ARGS((VimClipboard *cbd)); -int clip_mch_own_selection __ARGS((VimClipboard *cbd)); -void clip_mch_request_selection __ARGS((VimClipboard *cbd)); -void clip_mch_set_selection __ARGS((VimClipboard *cbd)); -void gui_mch_menu_grey __ARGS((vimmenu_T *menu, int grey)); -void gui_mch_menu_hidden __ARGS((vimmenu_T *menu, int hidden)); -void gui_mch_draw_menubar __ARGS((void)); -void gui_mch_set_blinking __ARGS((long waittime, long on, long off)); -void gui_mch_stop_blink __ARGS((void)); -void gui_mch_start_blink __ARGS((void)); -void process_event __ARGS((int event, int *block)); -void gui_mch_show_popupmenu __ARGS((vimmenu_T *menu)); -long_u gui_mch_get_rgb __ARGS((guicolor_T pixel)); -void gui_mch_getmouse __ARGS((int *x, int *y)); -void gui_mch_setmouse __ARGS((int x, int y)); -void gui_mch_drawsign __ARGS((int row, int col, int typenr)); -void gui_mch_destroy_sign __ARGS((XImage *sign)); -void gui_mch_mousehide __ARGS((int hide)); -void mch_set_mouse_shape __ARGS((int shape)); -void gui_mch_menu_set_tip __ARGS((vimmenu_T *menu)); - -void ro_redraw_title __ARGS((int window)); -int ro_ok_to_quit __ARGS((void)); -/* vim: set ft=c : */ diff -Naur vim73.orig/src/proto/gui_w16.pro vim73/src/proto/gui_w16.pro --- vim73.orig/src/proto/gui_w16.pro 2010-08-15 12:31:09.000000000 +0000 +++ vim73/src/proto/gui_w16.pro 2012-07-20 20:31:09.300972023 +0000 @@ -74,6 +74,6 @@ void gui_mch_add_menu_item __ARGS((vimmenu_T *menu, int idx)); void gui_mch_destroy_menu __ARGS((vimmenu_T *menu)); void gui_mch_menu_grey __ARGS((vimmenu_T *menu, int grey)); -int gui_mch_dialog __ARGS((int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield)); +int gui_mch_dialog __ARGS((int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield, int ex_cmd)); void gui_mch_set_foreground __ARGS((void)); /* vim: set ft=c : */ diff -Naur vim73.orig/src/proto/gui_w32.pro vim73/src/proto/gui_w32.pro --- vim73.orig/src/proto/gui_w32.pro 2010-08-15 12:31:09.000000000 +0000 +++ vim73/src/proto/gui_w32.pro 2012-07-20 20:31:09.300972023 +0000 @@ -81,7 +81,7 @@ void gui_mch_add_menu_item __ARGS((vimmenu_T *menu, int idx)); void gui_mch_destroy_menu __ARGS((vimmenu_T *menu)); void gui_mch_menu_grey __ARGS((vimmenu_T *menu, int grey)); -int gui_mch_dialog __ARGS((int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield)); +int gui_mch_dialog __ARGS((int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield, int ex_cmd)); void gui_mch_set_foreground __ARGS((void)); void gui_mch_drawsign __ARGS((int row, int col, int typenr)); void *gui_mch_register_sign __ARGS((char_u *signfile)); diff -Naur vim73.orig/src/proto/if_lua.pro vim73/src/proto/if_lua.pro --- vim73.orig/src/proto/if_lua.pro 2010-07-22 19:29:02.000000000 +0000 +++ vim73/src/proto/if_lua.pro 2012-07-20 20:31:15.690976620 +0000 @@ -6,4 +6,6 @@ void ex_luafile __ARGS((exarg_T *eap)); void lua_buffer_free __ARGS((buf_T *buf)); void lua_window_free __ARGS((win_T *win)); +void do_luaeval __ARGS((char_u *str, typval_T *arg, typval_T *rettv)); +void set_ref_in_lua __ARGS((int copyID)); /* vim: set ft=c : */ diff -Naur vim73.orig/src/proto/if_mzsch.pro vim73/src/proto/if_mzsch.pro --- vim73.orig/src/proto/if_mzsch.pro 2010-05-15 11:04:08.000000000 +0000 +++ vim73/src/proto/if_mzsch.pro 2012-07-20 20:31:14.807642652 +0000 @@ -14,6 +14,7 @@ void mzvim_reset_timer __ARGS((void)); void *mzvim_eval_string __ARGS((char_u *str)); int mzthreads_allowed __ARGS((void)); -void mzscheme_main __ARGS((void)); +int mzscheme_main __ARGS((int argc, char **argv)); void do_mzeval __ARGS((char_u *str, typval_T *rettv)); +int vim_main2 __ARGS((int argc, char **argv)); /* vim: set ft=c : */ diff -Naur vim73.orig/src/proto/if_python.pro vim73/src/proto/if_python.pro --- vim73.orig/src/proto/if_python.pro 2010-08-15 12:30:35.000000000 +0000 +++ vim73/src/proto/if_python.pro 2012-07-20 20:31:17.334311130 +0000 @@ -6,4 +6,6 @@ void ex_pyfile __ARGS((exarg_T *eap)); void python_buffer_free __ARGS((buf_T *buf)); void python_window_free __ARGS((win_T *win)); +void do_pyeval __ARGS((char_u *str, typval_T *rettv)); +void set_ref_in_python __ARGS((int copyID)); /* vim: set ft=c : */ diff -Naur vim73.orig/src/proto/if_python3.pro vim73/src/proto/if_python3.pro --- vim73.orig/src/proto/if_python3.pro 2010-08-15 12:30:36.000000000 +0000 +++ vim73/src/proto/if_python3.pro 2012-07-20 20:31:17.337644466 +0000 @@ -6,4 +6,6 @@ void ex_py3file __ARGS((exarg_T *eap)); void python3_buffer_free __ARGS((buf_T *buf)); void python3_window_free __ARGS((win_T *win)); +void do_py3eval __ARGS((char_u *str, typval_T *rettv)); +void set_ref_in_python3 __ARGS((int copyID)); /* vim: set ft=c : */ diff -Naur vim73.orig/src/proto/mbyte.pro vim73/src/proto/mbyte.pro --- vim73.orig/src/proto/mbyte.pro 2010-08-15 12:30:44.000000000 +0000 +++ vim73/src/proto/mbyte.pro 2012-07-20 20:31:12.267640827 +0000 @@ -2,6 +2,7 @@ int enc_canon_props __ARGS((char_u *name)); char_u *mb_init __ARGS((void)); int bomb_size __ARGS((void)); +void remove_bom __ARGS((char_u *s)); int mb_get_class __ARGS((char_u *p)); int dbcs_class __ARGS((unsigned lead, unsigned trail)); int latin_char2len __ARGS((int c)); @@ -56,7 +57,7 @@ int utf_valid_string __ARGS((char_u *s, char_u *end)); int dbcs_screen_tail_off __ARGS((char_u *base, char_u *p)); void mb_adjust_cursor __ARGS((void)); -void mb_adjustpos __ARGS((pos_T *lp)); +void mb_adjustpos __ARGS((buf_T *buf, pos_T *lp)); char_u *mb_prevptr __ARGS((char_u *line, char_u *p)); int mb_charlen __ARGS((char_u *str)); int mb_charlen_len __ARGS((char_u *str, int len)); diff -Naur vim73.orig/src/proto/message.pro vim73/src/proto/message.pro --- vim73.orig/src/proto/message.pro 2010-08-15 12:30:41.000000000 +0000 +++ vim73/src/proto/message.pro 2012-07-20 20:31:15.597643219 +0000 @@ -4,7 +4,7 @@ int msg_attr __ARGS((char_u *s, int attr)); int msg_attr_keep __ARGS((char_u *s, int attr, int keep)); char_u *msg_strtrunc __ARGS((char_u *s, int force)); -void trunc_string __ARGS((char_u *s, char_u *buf, int room)); +void trunc_string __ARGS((char_u *s, char_u *buf, int room, int buflen)); void reset_last_sourcing __ARGS((void)); void msg_source __ARGS((int attr)); int emsg_not_now __ARGS((void)); @@ -33,6 +33,7 @@ int msg_outtrans_len_attr __ARGS((char_u *msgstr, int len, int attr)); void msg_make __ARGS((char_u *arg)); int msg_outtrans_special __ARGS((char_u *strstart, int from)); +char_u *str2special_save __ARGS((char_u *str, int is_lhs)); char_u *str2special __ARGS((char_u **sp, int from)); void str2specialbuf __ARGS((char_u *sp, char_u *buf, int len)); void msg_prt_line __ARGS((char_u *s, int list)); @@ -44,6 +45,7 @@ void may_clear_sb_text __ARGS((void)); void clear_sb_text __ARGS((void)); void show_sb_text __ARGS((void)); +void msg_sb_eol __ARGS((void)); int msg_use_printf __ARGS((void)); void mch_errmsg __ARGS((char *str)); void mch_msg __ARGS((char *str)); @@ -63,7 +65,7 @@ int verbose_open __ARGS((void)); void give_warning __ARGS((char_u *message, int hl)); void msg_advance __ARGS((int col)); -int do_dialog __ARGS((int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield)); +int do_dialog __ARGS((int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield, int ex_cmd)); void display_confirm_msg __ARGS((void)); int vim_dialog_yesno __ARGS((int type, char_u *title, char_u *message, int dflt)); int vim_dialog_yesnocancel __ARGS((int type, char_u *title, char_u *message, int dflt)); diff -Naur vim73.orig/src/proto/misc1.pro vim73/src/proto/misc1.pro --- vim73.orig/src/proto/misc1.pro 2010-08-15 12:30:42.000000000 +0000 +++ vim73/src/proto/misc1.pro 2012-07-20 20:31:16.614310614 +0000 @@ -6,7 +6,8 @@ int set_indent __ARGS((int size, int flags)); int get_number_indent __ARGS((linenr_T lnum)); int open_line __ARGS((int dir, int flags, int old_indent)); -int get_leader_len __ARGS((char_u *line, char_u **flags, int backward)); +int get_leader_len __ARGS((char_u *line, char_u **flags, int backward, int do_skip_space)); +int get_last_leader_offset __ARGS((char_u *line, char_u **flags)); int plines __ARGS((linenr_T lnum)); int plines_win __ARGS((win_T *wp, linenr_T lnum, int winheight)); int plines_nofill __ARGS((linenr_T lnum)); diff -Naur vim73.orig/src/proto/misc2.pro vim73/src/proto/misc2.pro --- vim73.orig/src/proto/misc2.pro 2010-08-15 12:30:42.000000000 +0000 +++ vim73/src/proto/misc2.pro 2012-07-20 20:31:13.947642036 +0000 @@ -14,6 +14,7 @@ linenr_T get_cursor_rel_lnum __ARGS((win_T *wp, linenr_T lnum)); void check_cursor_lnum __ARGS((void)); void check_cursor_col __ARGS((void)); +void check_cursor_col_win __ARGS((win_T *win)); void check_cursor __ARGS((void)); void adjust_cursor_col __ARGS((void)); int leftcol_changed __ARGS((void)); @@ -40,6 +41,7 @@ void copy_chars __ARGS((char_u *ptr, size_t count, int c)); void del_trailing_spaces __ARGS((char_u *ptr)); void vim_strncpy __ARGS((char_u *to, char_u *from, size_t len)); +void vim_strcat __ARGS((char_u *to, char_u *from, size_t tosize)); int copy_option_part __ARGS((char_u **option, char_u *buf, int maxlen, char *sep_chars)); void vim_free __ARGS((void *x)); int vim_stricmp __ARGS((char *s1, char *s2)); @@ -56,6 +58,7 @@ char_u *ga_concat_strings __ARGS((garray_T *gap)); void ga_concat __ARGS((garray_T *gap, char_u *s)); void ga_append __ARGS((garray_T *gap, int c)); +void append_ga_line __ARGS((garray_T *gap)); int name_to_mod_mask __ARGS((int c)); int simplify_key __ARGS((int key, int *modifiers)); int handle_x_keys __ARGS((int key)); @@ -113,4 +116,5 @@ char_u *read_string __ARGS((FILE *fd, int cnt)); int put_bytes __ARGS((FILE *fd, long_u nr, int len)); void put_time __ARGS((FILE *fd, time_t the_time)); +int has_non_ascii __ARGS((char_u *s)); /* vim: set ft=c : */ diff -Naur vim73.orig/src/proto/ops.pro vim73/src/proto/ops.pro --- vim73.orig/src/proto/ops.pro 2010-08-15 12:30:45.000000000 +0000 +++ vim73/src/proto/ops.pro 2012-07-20 20:31:16.614310614 +0000 @@ -36,7 +36,7 @@ int preprocs_left __ARGS((void)); int get_register_name __ARGS((int num)); void ex_display __ARGS((exarg_T *eap)); -int do_join __ARGS((long count, int insert_space, int save_undo)); +int do_join __ARGS((long count, int insert_space, int save_undo, int use_formatoptions)); 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)); diff -Naur vim73.orig/src/proto/option.pro vim73/src/proto/option.pro --- vim73.orig/src/proto/option.pro 2010-08-15 12:30:46.000000000 +0000 +++ vim73/src/proto/option.pro 2012-07-20 20:31:09.320972037 +0000 @@ -54,6 +54,6 @@ int option_was_set __ARGS((char_u *name)); int can_bs __ARGS((int what)); void save_file_ff __ARGS((buf_T *buf)); -int file_ff_differs __ARGS((buf_T *buf)); +int file_ff_differs __ARGS((buf_T *buf, int ignore_empty)); int check_ff_value __ARGS((char_u *p)); /* vim: set ft=c : */ diff -Naur vim73.orig/src/proto/os_riscos.pro vim73/src/proto/os_riscos.pro --- vim73.orig/src/proto/os_riscos.pro 2010-08-15 12:31:16.000000000 +0000 +++ vim73/src/proto/os_riscos.pro 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -/* os_riscos.c */ -void mch_write __ARGS((char_u *s, int len)); -int mch_inchar __ARGS((char_u *buf, int maxlen, long wtime, int tb_change_cnt)); -int mch_char_avail __ARGS((void)); -long_u mch_avail_mem __ARGS((int special)); -void mch_delay __ARGS((long msec, int ignoreinput)); -void mch_suspend __ARGS((void)); -void mch_init __ARGS((void)); -int mch_check_win __ARGS((int argc, char **argv)); -int mch_input_isatty __ARGS((void)); -int mch_can_restore_title __ARGS((void)); -int mch_can_restore_icon __ARGS((void)); -void mch_settitle __ARGS((char_u *title, char_u *icon)); -void mch_restore_title __ARGS((int which)); -int mch_get_user_name __ARGS((char_u *s, int len)); -void mch_get_host_name __ARGS((char_u *s, int len)); -long mch_get_pid __ARGS((void)); -int mch_dirname __ARGS((char_u *buf, int len)); -int mch_FullName __ARGS((char_u *fname, char_u *buf, int len, int force)); -int mch_isFullName __ARGS((char_u *fname)); -long mch_getperm __ARGS((char_u *name)); -int mch_setperm __ARGS((char_u *name, long perm)); -void mch_hide __ARGS((char_u *name)); -int mch_isdir __ARGS((char_u *name)); -int mch_can_exe __ARGS((char_u *name)); -int mch_nodetype __ARGS((char_u *name)); -void mch_early_init __ARGS((void)); -void mch_exit __ARGS((int r)); -void mch_settmode __ARGS((int tmode)); -void mch_setmouse __ARGS((int on)); -int mch_screenmode __ARGS((char_u *arg)); -int mch_get_shellsize __ARGS((void)); -void mch_set_shellsize __ARGS((void)); -void mch_new_shellsize __ARGS((void)); -int mch_call_shell __ARGS((char_u *cmd, int options)); -void mch_breakcheck __ARGS((void)); -int mch_expandpath __ARGS((garray_T *gap, char_u *path, int flags)); -int expand_section __ARGS((garray_T *gap, char_u *root, char_u *rest, int flags)); -int mch_expand_wildcards __ARGS((int num_pat, char_u **pat, int *num_file, char_u ***file, int flags)); -int mch_has_exp_wildcard __ARGS((char_u *p)); -int mch_has_wildcard __ARGS((char_u *p)); -int mch_remove __ARGS((char_u *file)); -char_u *mch_munge_fname __ARGS((char_u *fname)); -int ro_buflist_add __ARGS((char_u *old_name)); -int mch_chdir __ARGS((char_u *dir)); -void mch_read_filetype __ARGS((char_u *file)); -void mch_set_filetype __ARGS((char_u *file, char_u *type)); -int mch_check_filetype __ARGS((char_u *fname, char_u *type)); -/* vim: set ft=c : */ diff -Naur vim73.orig/src/proto/os_win32.pro vim73/src/proto/os_win32.pro --- vim73.orig/src/proto/os_win32.pro 2010-08-15 12:31:14.000000000 +0000 +++ vim73/src/proto/os_win32.pro 2012-07-20 20:31:10.627639646 +0000 @@ -1,4 +1,5 @@ /* os_win32.c */ +HINSTANCE vimLoadLib __ARGS((char *name)); int dyn_libintl_init __ARGS((char *libname)); void dyn_libintl_end __ARGS((void)); void PlatformId __ARGS((void)); @@ -19,7 +20,9 @@ int mch_setperm __ARGS((char_u *name, long perm)); void mch_hide __ARGS((char_u *name)); int mch_isdir __ARGS((char_u *name)); +int mch_mkdir __ARGS((char_u *name)); int mch_is_linked __ARGS((char_u *fname)); +int win32_fileinfo __ARGS((char_u *name, BY_HANDLE_FILE_INFORMATION *lpFileInfo)); int mch_writable __ARGS((char_u *name)); int mch_can_exe __ARGS((char_u *name)); int mch_nodetype __ARGS((char_u *name)); diff -Naur vim73.orig/src/proto/term.pro vim73/src/proto/term.pro --- vim73.orig/src/proto/term.pro 2010-08-15 12:30:56.000000000 +0000 +++ vim73/src/proto/term.pro 2012-07-20 20:31:14.587642496 +0000 @@ -50,7 +50,7 @@ char_u *get_termcode __ARGS((int i)); void del_termcode __ARGS((char_u *name)); void set_mouse_topline __ARGS((win_T *wp)); -int check_termcode __ARGS((int max_offset, char_u *buf, int buflen)); +int check_termcode __ARGS((int max_offset, char_u *buf, int bufsize, int *buflen)); char_u *replace_termcodes __ARGS((char_u *from, char_u **bufp, int from_part, int do_lt, int special)); int find_term_bykeys __ARGS((char_u *src)); void show_termcodes __ARGS((void)); diff -Naur vim73.orig/src/proto/ui.pro vim73/src/proto/ui.pro --- vim73.orig/src/proto/ui.pro 2010-08-15 12:30:57.000000000 +0000 +++ vim73/src/proto/ui.pro 2012-07-20 20:31:18.070978324 +0000 @@ -11,17 +11,17 @@ void ui_new_shellsize __ARGS((void)); void ui_breakcheck __ARGS((void)); void clip_init __ARGS((int can_use)); -void clip_update_selection __ARGS((void)); +void clip_update_selection __ARGS((VimClipboard *clip)); void clip_own_selection __ARGS((VimClipboard *cbd)); void clip_lose_selection __ARGS((VimClipboard *cbd)); -void clip_copy_selection __ARGS((void)); void clip_auto_select __ARGS((void)); -int clip_isautosel __ARGS((void)); +int clip_isautosel_star __ARGS((void)); +int clip_isautosel_plus __ARGS((void)); void clip_modeless __ARGS((int button, int is_click, int is_drag)); void clip_start_selection __ARGS((int col, int row, int repeated_click)); void clip_process_selection __ARGS((int button, int col, int row, int_u repeated_click)); void clip_may_redraw_selection __ARGS((int row, int col, int len)); -void clip_clear_selection __ARGS((void)); +void clip_clear_selection __ARGS((VimClipboard *cbd)); void clip_may_clear_selection __ARGS((int row1, int row2)); void clip_scroll_selection __ARGS((int rows)); void clip_copy_modeless_selection __ARGS((int both)); diff -Naur vim73.orig/src/proto/window.pro vim73/src/proto/window.pro --- vim73.orig/src/proto/window.pro 2010-08-15 12:30:59.000000000 +0000 +++ vim73/src/proto/window.pro 2012-07-20 20:31:18.337645181 +0000 @@ -1,13 +1,14 @@ /* window.c */ void do_window __ARGS((int nchar, long Prenum, int xchar)); int win_split __ARGS((int size, int flags)); -int win_split_ins __ARGS((int size, int flags, win_T *newwin, int dir)); +int win_split_ins __ARGS((int size, int flags, win_T *new_wp, int dir)); int win_valid __ARGS((win_T *win)); int win_count __ARGS((void)); int make_windows __ARGS((int count, int vertical)); void win_move_after __ARGS((win_T *win1, win_T *win2)); void win_equal __ARGS((win_T *next_curwin, int current, int dir)); void close_windows __ARGS((buf_T *buf, int keep_curwin)); +int one_window __ARGS((void)); void win_close __ARGS((win_T *win, int free_buf)); void win_close_othertab __ARGS((win_T *win, int free_buf, tabpage_T *tp)); void win_free_all __ARGS((void)); @@ -26,7 +27,7 @@ tabpage_T *find_tabpage __ARGS((int n)); int tabpage_index __ARGS((tabpage_T *ftp)); void goto_tabpage __ARGS((int n)); -void goto_tabpage_tp __ARGS((tabpage_T *tp)); +void goto_tabpage_tp __ARGS((tabpage_T *tp, int trigger_autocmds)); void goto_tabpage_win __ARGS((tabpage_T *tp, win_T *wp)); void tabpage_move __ARGS((int nr)); void win_goto __ARGS((win_T *wp)); @@ -50,6 +51,8 @@ void win_setminheight __ARGS((void)); void win_drag_status_line __ARGS((win_T *dragwin, int offset)); void win_drag_vsep_line __ARGS((win_T *dragwin, int offset)); +void win_new_height __ARGS((win_T *wp, int height)); +void win_new_width __ARGS((win_T *wp, int width)); void win_comp_scroll __ARGS((win_T *wp)); void command_height __ARGS((void)); void last_status __ARGS((int morewin)); diff -Naur vim73.orig/src/proto.h vim73/src/proto.h --- vim73.orig/src/proto.h 2010-07-17 15:28:51.000000000 +0000 +++ vim73/src/proto.h 2012-07-20 20:31:10.807639777 +0000 @@ -62,9 +62,6 @@ # ifdef __BEOS__ # include "os_beos.pro" # endif -# ifdef RISCOS -# include "os_riscos.pro" -# endif # ifdef __QNX__ # include "os_qnx.pro" # endif @@ -245,9 +242,6 @@ # ifdef FEAT_GUI_X11 # include "gui_x11.pro" # endif -# ifdef RISCOS -# include "gui_riscos.pro" -# endif # ifdef FEAT_GUI_PHOTON # include "gui_photon.pro" # endif diff -Naur vim73.orig/src/pty.c vim73/src/pty.c --- vim73.orig/src/pty.c 2010-07-24 18:23:01.000000000 +0000 +++ vim73/src/pty.c 2012-07-20 20:31:14.287642279 +0000 @@ -14,6 +14,10 @@ * It has been modified to work better with Vim. * The parts that are not used in Vim have been deleted. * See the "screen" sources for the complete stuff. + * + * This specific version is distibuted under the Vim license (attribution by + * Juergen Weigert), the GPL applies to the original version, see the + * copyright notice below. */ /* Copyright (c) 1993 @@ -123,8 +127,7 @@ static void initmaster __ARGS((int)); /* - * Open all ptys with O_NOCTTY, just to be on the safe side - * (RISCos mips breaks otherwise) + * Open all ptys with O_NOCTTY, just to be on the safe side. */ #ifndef O_NOCTTY # define O_NOCTTY 0 @@ -209,8 +212,8 @@ #ifdef _SEQUENT_ fvhangup(s); #endif - strncpy(PtyName, m, sizeof(PtyName)); - strncpy(TtyName, s, sizeof(TtyName)); + vim_strncpy((char_u *)PtyName, (char_u *)m, sizeof(PtyName) - 1); + vim_strncpy((char_u *)TtyName, (char_u *)s, sizeof(TtyName) - 1); initmaster(f); *ttyn = TtyName; return f; @@ -301,7 +304,7 @@ return -1; } signal(SIGCHLD, sigcld); - strncpy(TtyName, m, sizeof(TtyName)); + vim_strncpy((char_u *)TtyName, (char_u *)m, sizeof(TtyName) - 1); initmaster(f); *ttyn = TtyName; return f; @@ -326,7 +329,7 @@ /* a dumb looking loop replaced by mycrofts code: */ if ((f = open("/dev/ptc", O_RDWR | O_NOCTTY | O_EXTRA)) < 0) return -1; - strncpy(TtyName, ttyname(f), sizeof(TtyName)); + vim_strncpy((char_u *)TtyName, (char_u *)ttyname(f), sizeof(TtyName) - 1); if (geteuid() != ROOT_UID && mch_access(TtyName, R_OK | W_OK)) { close(f); diff -Naur vim73.orig/src/quickfix.c vim73/src/quickfix.c --- vim73.orig/src/quickfix.c 2010-08-09 20:12:14.000000000 +0000 +++ vim73/src/quickfix.c 2012-07-20 20:31:17.374311158 +0000 @@ -126,12 +126,14 @@ static win_T *qf_find_win __ARGS((qf_info_T *qi)); static buf_T *qf_find_buf __ARGS((qf_info_T *qi)); static void qf_update_buffer __ARGS((qf_info_T *qi)); +static void qf_set_title __ARGS((qf_info_T *qi)); static void qf_fill_buffer __ARGS((qf_info_T *qi)); #endif static char_u *get_mef_name __ARGS((void)); -static buf_T *load_dummy_buffer __ARGS((char_u *fname)); -static void wipe_dummy_buffer __ARGS((buf_T *buf)); -static void unload_dummy_buffer __ARGS((buf_T *buf)); +static void restore_start_dir __ARGS((char_u *dirname_start)); +static buf_T *load_dummy_buffer __ARGS((char_u *fname, char_u *dirname_start, char_u *resulting_dir)); +static void wipe_dummy_buffer __ARGS((buf_T *buf, char_u *dirname_start)); +static void unload_dummy_buffer __ARGS((buf_T *buf, char_u *dirname_start)); static qf_info_T *ll_get_or_alloc_list __ARGS((win_T *)); /* Quickfix window check helper macro */ @@ -245,7 +247,7 @@ {'t', "."}, {'m', ".\\+"}, {'r', ".*"}, - {'p', "[- .]*"}, + {'p', "[- .]*"}, {'v', "\\d\\+"}, {'s', ".\\+"} }; @@ -561,6 +563,10 @@ break; IObuff[CMDBUFFSIZE - 2] = NUL; /* for very long lines */ +#ifdef FEAT_MBYTE + remove_bom(IObuff); +#endif + if ((efmp = vim_strrchr(IObuff, '\n')) != NULL) *efmp = NUL; #ifdef USE_CRNL @@ -671,11 +677,23 @@ } if ((i = (int)fmt_ptr->addr[7]) > 0) /* %p */ { + char_u *match_ptr; + if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) continue; - col = (int)(regmatch.endp[i] - regmatch.startp[i] + 1); - if (*((char_u *)regmatch.startp[i]) != TAB) - use_viscol = TRUE; + col = 0; + for (match_ptr = regmatch.startp[i]; + match_ptr != regmatch.endp[i]; ++match_ptr) + { + ++col; + if (*match_ptr == TAB) + { + col += 7; + col -= col % 8; + } + } + ++col; + use_viscol = TRUE; } if ((i = (int)fmt_ptr->addr[8]) > 0) /* %v */ { @@ -894,8 +912,7 @@ } else qi->qf_curlist = qi->qf_listcount++; - qi->qf_lists[qi->qf_curlist].qf_index = 0; - qi->qf_lists[qi->qf_curlist].qf_count = 0; + vim_memset(&qi->qf_lists[qi->qf_curlist], 0, (size_t)(sizeof(qf_list_T))); if (qf_title != NULL) { char_u *p = alloc((int)STRLEN(qf_title) + 2); @@ -904,8 +921,6 @@ if (p != NULL) sprintf((char *)p, ":%s", (char *)qf_title); } - else - qi->qf_lists[qi->qf_curlist].qf_title = NULL; } /* @@ -1164,7 +1179,7 @@ /* When no valid entries are present in the list, qf_ptr points to * the first item in the list */ - if (to_qfl->qf_nonevalid == TRUE) + if (to_qfl->qf_nonevalid) to_qfl->qf_ptr = to_qfl->qf_start; } @@ -1182,21 +1197,17 @@ if (fname == NULL || *fname == NUL) /* no file name */ return 0; { -#ifdef RISCOS - /* Name is reported as `main.c', but file is `c.main' */ - return ro_buflist_add(fname); -#else char_u *ptr; int fnum; -# ifdef VMS +#ifdef VMS vms_remove_version(fname); -# endif -# ifdef BACKSLASH_IN_FILENAME +#endif +#ifdef BACKSLASH_IN_FILENAME if (directory != NULL) slash_adjust(directory); slash_adjust(fname); -# endif +#endif if (directory != NULL && !vim_isAbsName(fname) && (ptr = concat_fnames(directory, fname, TRUE)) != NULL) { @@ -1221,7 +1232,6 @@ return fnum; } return buflist_add(fname, 0); -#endif } } @@ -1656,9 +1666,7 @@ opened_window = TRUE; /* close it when fail */ p_swb = empty_option; /* don't split again */ swb_flags = 0; -# ifdef FEAT_SCROLLBIND - curwin->w_p_scb = FALSE; -# endif + RESET_BINDING(curwin); if (ll_ref != NULL) { /* The new window should use the location list from the @@ -1847,8 +1855,10 @@ #endif if (print_message) { - /* Update the screen before showing the message */ - update_topline_redraw(); + /* Update the screen before showing the message, unless the screen + * scrolled up. */ + if (!msg_scrolled) + update_topline_redraw(); sprintf((char *)IObuff, _("(%d of %d)%s%s: "), qf_index, qi->qf_lists[qi->qf_curlist].qf_count, qf_ptr->qf_cleared ? _(" (line deleted)") : "", @@ -2125,6 +2135,7 @@ --qi->qf_lists[idx].qf_count; } vim_free(qi->qf_lists[idx].qf_title); + qi->qf_lists[idx].qf_title = NULL; } /* @@ -2244,6 +2255,7 @@ * it if we have errors; otherwise, leave it closed. */ if (qi->qf_lists[qi->qf_curlist].qf_nonevalid + || qi->qf_lists[qi->qf_curlist].qf_count == 0 || qi->qf_curlist >= qi->qf_listcount) { if (win != NULL) @@ -2333,9 +2345,7 @@ win_goto(lastwin); if (win_split(height, WSP_BELOW | WSP_NEWLOC) == FAIL) return; /* not enough room for window */ -#ifdef FEAT_SCROLLBIND - curwin->w_p_scb = FALSE; -#endif + RESET_BINDING(curwin); if (eap->cmdidx == CMD_lopen || eap->cmdidx == CMD_lwindow) { @@ -2362,6 +2372,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); + RESET_BINDING(curwin); #ifdef FEAT_DIFF curwin->w_p_diff = FALSE; #endif @@ -2390,8 +2401,7 @@ qf_fill_buffer(qi); if (qi->qf_lists[qi->qf_curlist].qf_title != NULL) - set_internal_string_var((char_u *)"w:quickfix_title", - qi->qf_lists[qi->qf_curlist].qf_title); + qf_set_title(qi); curwin->w_cursor.lnum = qi->qf_lists[qi->qf_curlist].qf_index; curwin->w_cursor.col = 0; @@ -2528,6 +2538,8 @@ qf_info_T *qi; { buf_T *buf; + win_T *win; + win_T *curwin_save; aco_save_T aco; /* Check if a buffer for the quickfix list exists. Update it. */ @@ -2539,6 +2551,16 @@ qf_fill_buffer(qi); + if (qi->qf_lists[qi->qf_curlist].qf_title != NULL + && (win = qf_find_win(qi)) != NULL) + { + curwin_save = curwin; + curwin = win; + qf_set_title(qi); + curwin = curwin_save; + + } + /* restore curwin/curbuf and a few other things */ aucmd_restbuf(&aco); @@ -2546,6 +2568,14 @@ } } + static void +qf_set_title(qi) + qf_info_T *qi; +{ + set_internal_string_var((char_u *)"w:quickfix_title", + qi->qf_lists[qi->qf_curlist].qf_title); +} + /* * Fill current buffer with quickfix errors, replacing any previous contents. * curbuf must be the quickfix buffer! @@ -2657,7 +2687,7 @@ bt_quickfix(buf) buf_T *buf; { - return (buf->b_p_bt[0] == 'q'); + return buf != NULL && buf->b_p_bt[0] == 'q'; } /* @@ -2668,8 +2698,8 @@ bt_nofile(buf) buf_T *buf; { - return (buf->b_p_bt[0] == 'n' && buf->b_p_bt[2] == 'f') - || buf->b_p_bt[0] == 'a'; + return buf != NULL && ((buf->b_p_bt[0] == 'n' && buf->b_p_bt[2] == 'f') + || buf->b_p_bt[0] == 'a'); } /* @@ -2679,7 +2709,7 @@ bt_dontwrite(buf) buf_T *buf; { - return (buf->b_p_bt[0] == 'n'); + return buf != NULL && buf->b_p_bt[0] == 'n'; } int @@ -2744,6 +2774,13 @@ #ifdef FEAT_AUTOCMD char_u *au_name = NULL; + /* Redirect ":grep" to ":vimgrep" if 'grepprg' is "internal". */ + if (grep_internal(eap->cmdidx)) + { + ex_vimgrep(eap); + return; + } + switch (eap->cmdidx) { case CMD_make: au_name = (char_u *)"make"; break; @@ -2765,13 +2802,6 @@ } #endif - /* Redirect ":grep" to ":vimgrep" if 'grepprg' is "internal". */ - if (grep_internal(eap->cmdidx)) - { - ex_vimgrep(eap); - return; - } - if (eap->cmdidx == CMD_lmake || eap->cmdidx == CMD_lgrep || eap->cmdidx == CMD_lgrepadd) wp = curwin; @@ -2819,17 +2849,21 @@ (eap->cmdidx != CMD_grepadd && eap->cmdidx != CMD_lgrepadd), *eap->cmdlinep); + if (wp != NULL) + qi = GET_LOC_LIST(wp); #ifdef FEAT_AUTOCMD if (au_name != NULL) + { apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, curbuf->b_fname, TRUE, curbuf); + if (qi->qf_curlist < qi->qf_listcount) + res = qi->qf_lists[qi->qf_curlist].qf_count; + else + res = 0; + } #endif if (res > 0 && !eap->forceit) - { - if (wp != NULL) - qi = GET_LOC_LIST(wp); qf_jump(qi, 0, 0, FALSE); /* display first error */ - } mch_remove(fname); vim_free(fname); @@ -2974,11 +3008,28 @@ { win_T *wp = NULL; qf_info_T *qi = &ql_info; +#ifdef FEAT_AUTOCMD + char_u *au_name = NULL; +#endif if (eap->cmdidx == CMD_lfile || eap->cmdidx == CMD_lgetfile - || eap->cmdidx == CMD_laddfile) + || eap->cmdidx == CMD_laddfile) wp = curwin; +#ifdef FEAT_AUTOCMD + switch (eap->cmdidx) + { + case CMD_cfile: au_name = (char_u *)"cfile"; break; + case CMD_cgetfile: au_name = (char_u *)"cgetfile"; break; + case CMD_caddfile: au_name = (char_u *)"caddfile"; break; + case CMD_lfile: au_name = (char_u *)"lfile"; break; + case CMD_lgetfile: au_name = (char_u *)"lgetfile"; break; + case CMD_laddfile: au_name = (char_u *)"laddfile"; break; + default: break; + } + if (au_name != NULL) + apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, NULL, FALSE, curbuf); +#endif #ifdef FEAT_BROWSE if (cmdmod.browse) { @@ -3010,10 +3061,22 @@ && (eap->cmdidx == CMD_cfile || eap->cmdidx == CMD_lfile)) { +#ifdef FEAT_AUTOCMD + if (au_name != NULL) + apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, NULL, FALSE, curbuf); +#endif if (wp != NULL) qi = GET_LOC_LIST(wp); qf_jump(qi, 0, 0, eap->forceit); /* display first error */ } + + else + { +#ifdef FEAT_AUTOCMD + if (au_name != NULL) + apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, NULL, FALSE, curbuf); +#endif + } } /* @@ -3051,18 +3114,22 @@ int flags = 0; colnr_T col; long tomatch; - char_u dirname_start[MAXPATHL]; - char_u dirname_now[MAXPATHL]; + char_u *dirname_start = NULL; + char_u *dirname_now = NULL; char_u *target_dir = NULL; #ifdef FEAT_AUTOCMD char_u *au_name = NULL; switch (eap->cmdidx) { - case CMD_vimgrep: au_name = (char_u *)"vimgrep"; break; - case CMD_lvimgrep: au_name = (char_u *)"lvimgrep"; break; - case CMD_vimgrepadd: au_name = (char_u *)"vimgrepadd"; break; + case CMD_vimgrep: au_name = (char_u *)"vimgrep"; break; + case CMD_lvimgrep: au_name = (char_u *)"lvimgrep"; break; + case CMD_vimgrepadd: au_name = (char_u *)"vimgrepadd"; break; case CMD_lvimgrepadd: au_name = (char_u *)"lvimgrepadd"; break; + case CMD_grep: au_name = (char_u *)"grep"; break; + case CMD_lgrep: au_name = (char_u *)"lgrep"; break; + case CMD_grepadd: au_name = (char_u *)"grepadd"; break; + case CMD_lgrepadd: au_name = (char_u *)"lgrepadd"; break; default: break; } if (au_name != NULL) @@ -3122,7 +3189,7 @@ ; /* parse the list of arguments */ - if (get_arglist_exp(p, &fcount, &fnames) == FAIL) + if (get_arglist_exp(p, &fcount, &fnames, TRUE) == FAIL) goto theend; if (fcount == 0) { @@ -3130,6 +3197,11 @@ goto theend; } + dirname_start = alloc(MAXPATHL); + dirname_now = alloc(MAXPATHL); + if (dirname_start == NULL || dirname_now == NULL) + goto theend; + /* Remember the current directory, because a BufRead autocommand that does * ":lcd %:p:h" changes the meaning of short path names. */ mch_dirname(dirname_start, MAXPATHL); @@ -3178,19 +3250,7 @@ /* Load file into a buffer, so that 'fileencoding' is detected, * autocommands applied, etc. */ - buf = load_dummy_buffer(fname); - - /* When autocommands changed directory: go back. We assume it was - * ":lcd %:p:h". */ - mch_dirname(dirname_now, MAXPATHL); - if (STRCMP(dirname_start, dirname_now) != 0) - { - exarg_T ea; - - ea.arg = dirname_start; - ea.cmdidx = CMD_lcd; - ex_cd(&ea); - } + buf = load_dummy_buffer(fname, dirname_start, dirname_now); p_mls = save_mls; #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL) @@ -3261,7 +3321,7 @@ { /* Never keep a dummy buffer if there is another buffer * with the same name. */ - wipe_dummy_buffer(buf); + wipe_dummy_buffer(buf, dirname_start); buf = NULL; } else if (!cmdmod.hide @@ -3277,12 +3337,12 @@ * many swap files. */ if (!found_match) { - wipe_dummy_buffer(buf); + wipe_dummy_buffer(buf, dirname_start); buf = NULL; } else if (buf != first_match_buf || (flags & VGR_NOJUMP)) { - unload_dummy_buffer(buf); + unload_dummy_buffer(buf, dirname_start); buf = NULL; } } @@ -3366,6 +3426,8 @@ } theend: + vim_free(dirname_now); + vim_free(dirname_start); vim_free(target_dir); vim_free(regmatch.regprog); } @@ -3426,15 +3488,51 @@ } /* - * Load file "fname" into a dummy buffer and return the buffer pointer. + * Restore current working directory to "dirname_start" if they differ, taking + * into account whether it is set locally or globally. + */ + static void +restore_start_dir(dirname_start) + char_u *dirname_start; +{ + char_u *dirname_now = alloc(MAXPATHL); + + if (NULL != dirname_now) + { + mch_dirname(dirname_now, MAXPATHL); + if (STRCMP(dirname_start, dirname_now) != 0) + { + /* If the directory has changed, change it back by building up an + * appropriate ex command and executing it. */ + exarg_T ea; + + ea.arg = dirname_start; + ea.cmdidx = (curwin->w_localdir == NULL) ? CMD_cd : CMD_lcd; + ex_cd(&ea); + } + } +} + +/* + * Load file "fname" into a dummy buffer and return the buffer pointer, + * placing the directory resulting from the buffer load into the + * "resulting_dir" pointer. "resulting_dir" must be allocated by the caller + * prior to calling this function. Restores directory to "dirname_start" prior + * to returning, if autocmds or the 'autochdir' option have changed it. + * + * If creating the dummy buffer does not fail, must call unload_dummy_buffer() + * or wipe_dummy_buffer() later! + * * Returns NULL if it fails. - * Must call unload_dummy_buffer() or wipe_dummy_buffer() later! */ static buf_T * -load_dummy_buffer(fname) +load_dummy_buffer(fname, dirname_start, resulting_dir) char_u *fname; + char_u *dirname_start; /* in: old directory */ + char_u *resulting_dir; /* out: new directory */ { buf_T *newbuf; + buf_T *newbuf_to_wipe = NULL; int failed = TRUE; aco_save_T aco; @@ -3471,33 +3569,48 @@ failed = FALSE; if (curbuf != newbuf) { - /* Bloody autocommands changed the buffer! */ - if (buf_valid(newbuf)) - wipe_buffer(newbuf, FALSE); + /* Bloody autocommands changed the buffer! Can happen when + * using netrw and editing a remote file. Use the current + * buffer instead, delete the dummy one after restoring the + * window stuff. */ + newbuf_to_wipe = newbuf; newbuf = curbuf; } } /* restore curwin/curbuf and a few other things */ aucmd_restbuf(&aco); + if (newbuf_to_wipe != NULL && buf_valid(newbuf_to_wipe)) + wipe_buffer(newbuf_to_wipe, FALSE); } + /* + * When autocommands/'autochdir' option changed directory: go back. + * Let the caller know what the resulting dir was first, in case it is + * important. + */ + mch_dirname(resulting_dir, MAXPATHL); + restore_start_dir(dirname_start); + if (!buf_valid(newbuf)) return NULL; if (failed) { - wipe_dummy_buffer(newbuf); + wipe_dummy_buffer(newbuf, dirname_start); return NULL; } return newbuf; } /* - * Wipe out the dummy buffer that load_dummy_buffer() created. + * Wipe out the dummy buffer that load_dummy_buffer() created. Restores + * directory to "dirname_start" prior to returning, if autocmds or the + * 'autochdir' option have changed it. */ static void -wipe_dummy_buffer(buf) +wipe_dummy_buffer(buf, dirname_start) buf_T *buf; + char_u *dirname_start; { if (curbuf != buf) /* safety check */ { @@ -3517,18 +3630,28 @@ * new aborting error, interrupt, or uncaught exception. */ leave_cleanup(&cs); #endif + /* When autocommands/'autochdir' option changed directory: go back. */ + restore_start_dir(dirname_start); } } /* - * Unload the dummy buffer that load_dummy_buffer() created. + * Unload the dummy buffer that load_dummy_buffer() created. Restores + * directory to "dirname_start" prior to returning, if autocmds or the + * 'autochdir' option have changed it. */ static void -unload_dummy_buffer(buf) +unload_dummy_buffer(buf, dirname_start) buf_T *buf; + char_u *dirname_start; { if (curbuf != buf) /* safety check */ - close_buffer(NULL, buf, DOBUF_UNLOAD); + { + close_buffer(NULL, buf, DOBUF_UNLOAD, FALSE); + + /* When autocommands/'autochdir' option changed directory: go back. */ + restore_start_dir(dirname_start); + } } #if defined(FEAT_EVAL) || defined(PROTO) @@ -3697,7 +3820,7 @@ } if (qi->qf_lists[qi->qf_curlist].qf_index == 0) - /* empty list or no valid entry */ + /* no valid entry */ qi->qf_lists[qi->qf_curlist].qf_nonevalid = TRUE; else qi->qf_lists[qi->qf_curlist].qf_nonevalid = FALSE; @@ -3841,16 +3964,35 @@ qf_info_T *qi = &ql_info; int new_qi = FALSE; win_T *wp; - - /* Make 'cpoptions' empty, the 'l' flag should not be used here. */ - save_cpo = p_cpo; - p_cpo = empty_option; +#ifdef FEAT_AUTOCMD + char_u *au_name = NULL; +#endif #ifdef FEAT_MULTI_LANG /* Check for a specified language */ lang = check_help_lang(eap->arg); #endif +#ifdef FEAT_AUTOCMD + switch (eap->cmdidx) + { + case CMD_helpgrep: au_name = (char_u *)"helpgrep"; break; + case CMD_lhelpgrep: au_name = (char_u *)"lhelpgrep"; break; + default: break; + } + if (au_name != NULL) + { + apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, + curbuf->b_fname, TRUE, curbuf); + if (did_throw || force_abort) + return; + } +#endif + + /* Make 'cpoptions' empty, the 'l' flag should not be used here. */ + save_cpo = p_cpo; + p_cpo = empty_option; + if (eap->cmdidx == CMD_lhelpgrep) { /* Find an existing help window */ @@ -3876,6 +4018,16 @@ regmatch.rm_ic = FALSE; if (regmatch.regprog != NULL) { +#ifdef FEAT_MBYTE + vimconv_T vc; + + /* Help files are in utf-8 or latin1, convert lines when 'encoding' + * differs. */ + vc.vc_type = CONV_NONE; + if (!enc_utf8) + convert_setup(&vc, (char_u *)"utf-8", p_enc); +#endif + /* create a new quickfix list */ qf_new_list(qi, *eap->cmdlinep); @@ -3910,21 +4062,33 @@ lnum = 1; while (!vim_fgets(IObuff, IOSIZE, fd) && !got_int) { - if (vim_regexec(®match, IObuff, (colnr_T)0)) + char_u *line = IObuff; +#ifdef FEAT_MBYTE + /* Convert a line if 'encoding' is not utf-8 and + * the line contains a non-ASCII character. */ + if (vc.vc_type != CONV_NONE + && has_non_ascii(IObuff)) { + line = string_convert(&vc, IObuff, NULL); + if (line == NULL) + line = IObuff; + } +#endif + + if (vim_regexec(®match, line, (colnr_T)0)) { - int l = (int)STRLEN(IObuff); + int l = (int)STRLEN(line); /* remove trailing CR, LF, spaces, etc. */ - while (l > 0 && IObuff[l - 1] <= ' ') - IObuff[--l] = NUL; + while (l > 0 && line[l - 1] <= ' ') + line[--l] = NUL; if (qf_add_entry(qi, &prevp, NULL, /* dir */ fnames[fi], 0, - IObuff, + line, lnum, - (int)(regmatch.startp[0] - IObuff) + (int)(regmatch.startp[0] - line) + 1, /* col */ FALSE, /* vis_col */ NULL, /* search pattern */ @@ -3934,9 +4098,17 @@ ) == FAIL) { got_int = TRUE; +#ifdef FEAT_MBYTE + if (line != IObuff) + vim_free(line); +#endif break; } } +#ifdef FEAT_MBYTE + if (line != IObuff) + vim_free(line); +#endif ++lnum; line_breakcheck(); } @@ -3946,7 +4118,12 @@ FreeWild(fcount, fnames); } } + vim_free(regmatch.regprog); +#ifdef FEAT_MBYTE + if (vc.vc_type != CONV_NONE) + convert_setup(&vc, NULL, NULL); +#endif qi->qf_lists[qi->qf_curlist].qf_nonevalid = FALSE; qi->qf_lists[qi->qf_curlist].qf_ptr = @@ -3964,6 +4141,17 @@ qf_update_buffer(qi); #endif +#ifdef FEAT_AUTOCMD + if (au_name != NULL) + { + apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, + curbuf->b_fname, TRUE, curbuf); + if (!new_qi && qi != &ql_info && qf_find_buf(qi) == NULL) + /* autocommands made "qi" invalid */ + return; + } +#endif + /* Jump to first match. */ if (qi->qf_lists[qi->qf_curlist].qf_count > 0) qf_jump(qi, 0, 0, FALSE); diff -Naur vim73.orig/src/regexp.c vim73/src/regexp.c --- vim73.orig/src/regexp.c 2010-07-12 20:41:48.000000000 +0000 +++ vim73/src/regexp.c 2012-07-20 20:31:12.114307384 +0000 @@ -666,8 +666,12 @@ static void regc __ARGS((int b)); #ifdef FEAT_MBYTE static void regmbc __ARGS((int c)); +# define REGMBC(x) regmbc(x); +# define CASEMBC(x) case x: #else # define regmbc(c) regc(c) +# define REGMBC(x) +# define CASEMBC(x) #endif static void reginsert __ARGS((int, char_u *)); static void reginsert_limits __ARGS((int, long, long, char_u *)); @@ -787,68 +791,295 @@ switch (c) { case 'A': case '\300': case '\301': case '\302': + CASEMBC(0x100) CASEMBC(0x102) CASEMBC(0x104) CASEMBC(0x1cd) + CASEMBC(0x1de) CASEMBC(0x1e0) CASEMBC(0x1ea2) case '\303': case '\304': case '\305': regmbc('A'); regmbc('\300'); regmbc('\301'); regmbc('\302'); regmbc('\303'); regmbc('\304'); regmbc('\305'); + REGMBC(0x100) REGMBC(0x102) REGMBC(0x104) + REGMBC(0x1cd) REGMBC(0x1de) REGMBC(0x1e0) + REGMBC(0x1ea2) + return; + case 'B': CASEMBC(0x1e02) CASEMBC(0x1e06) + regmbc('B'); REGMBC(0x1e02) REGMBC(0x1e06) return; case 'C': case '\307': + CASEMBC(0x106) CASEMBC(0x108) CASEMBC(0x10a) CASEMBC(0x10c) regmbc('C'); regmbc('\307'); + REGMBC(0x106) REGMBC(0x108) REGMBC(0x10a) + REGMBC(0x10c) + return; + case 'D': CASEMBC(0x10e) CASEMBC(0x110) CASEMBC(0x1e0a) + CASEMBC(0x1e0e) CASEMBC(0x1e10) + regmbc('D'); REGMBC(0x10e) REGMBC(0x110) + REGMBC(0x1e0a) REGMBC(0x1e0e) REGMBC(0x1e10) return; case 'E': case '\310': case '\311': case '\312': case '\313': + CASEMBC(0x112) CASEMBC(0x114) CASEMBC(0x116) CASEMBC(0x118) + CASEMBC(0x11a) CASEMBC(0x1eba) CASEMBC(0x1ebc) regmbc('E'); regmbc('\310'); regmbc('\311'); regmbc('\312'); regmbc('\313'); + REGMBC(0x112) REGMBC(0x114) REGMBC(0x116) + REGMBC(0x118) REGMBC(0x11a) REGMBC(0x1eba) + REGMBC(0x1ebc) + return; + case 'F': CASEMBC(0x1e1e) + regmbc('F'); REGMBC(0x1e1e) + return; + case 'G': CASEMBC(0x11c) CASEMBC(0x11e) CASEMBC(0x120) + CASEMBC(0x122) CASEMBC(0x1e4) CASEMBC(0x1e6) CASEMBC(0x1f4) + CASEMBC(0x1e20) + regmbc('G'); REGMBC(0x11c) REGMBC(0x11e) + REGMBC(0x120) REGMBC(0x122) REGMBC(0x1e4) + REGMBC(0x1e6) REGMBC(0x1f4) REGMBC(0x1e20) + return; + case 'H': CASEMBC(0x124) CASEMBC(0x126) CASEMBC(0x1e22) + CASEMBC(0x1e26) CASEMBC(0x1e28) + regmbc('H'); REGMBC(0x124) REGMBC(0x126) + REGMBC(0x1e22) REGMBC(0x1e26) REGMBC(0x1e28) return; case 'I': case '\314': case '\315': case '\316': case '\317': + CASEMBC(0x128) CASEMBC(0x12a) CASEMBC(0x12c) CASEMBC(0x12e) + CASEMBC(0x130) CASEMBC(0x1cf) CASEMBC(0x1ec8) regmbc('I'); regmbc('\314'); regmbc('\315'); regmbc('\316'); regmbc('\317'); + REGMBC(0x128) REGMBC(0x12a) REGMBC(0x12c) + REGMBC(0x12e) REGMBC(0x130) REGMBC(0x1cf) + REGMBC(0x1ec8) + return; + case 'J': CASEMBC(0x134) + regmbc('J'); REGMBC(0x134) + return; + case 'K': CASEMBC(0x136) CASEMBC(0x1e8) CASEMBC(0x1e30) + CASEMBC(0x1e34) + regmbc('K'); REGMBC(0x136) REGMBC(0x1e8) + REGMBC(0x1e30) REGMBC(0x1e34) + return; + case 'L': CASEMBC(0x139) CASEMBC(0x13b) CASEMBC(0x13d) + CASEMBC(0x13f) CASEMBC(0x141) CASEMBC(0x1e3a) + regmbc('L'); REGMBC(0x139) REGMBC(0x13b) + REGMBC(0x13d) REGMBC(0x13f) REGMBC(0x141) + REGMBC(0x1e3a) + return; + case 'M': CASEMBC(0x1e3e) CASEMBC(0x1e40) + regmbc('M'); REGMBC(0x1e3e) REGMBC(0x1e40) return; case 'N': case '\321': + CASEMBC(0x143) CASEMBC(0x145) CASEMBC(0x147) CASEMBC(0x1e44) + CASEMBC(0x1e48) regmbc('N'); regmbc('\321'); + REGMBC(0x143) REGMBC(0x145) REGMBC(0x147) + REGMBC(0x1e44) REGMBC(0x1e48) return; case 'O': case '\322': case '\323': case '\324': case '\325': - case '\326': + case '\326': case '\330': + CASEMBC(0x14c) CASEMBC(0x14e) CASEMBC(0x150) CASEMBC(0x1a0) + CASEMBC(0x1d1) CASEMBC(0x1ea) CASEMBC(0x1ec) CASEMBC(0x1ece) regmbc('O'); regmbc('\322'); regmbc('\323'); regmbc('\324'); regmbc('\325'); regmbc('\326'); + regmbc('\330'); + REGMBC(0x14c) REGMBC(0x14e) REGMBC(0x150) + REGMBC(0x1a0) REGMBC(0x1d1) REGMBC(0x1ea) + REGMBC(0x1ec) REGMBC(0x1ece) + return; + case 'P': case 0x1e54: case 0x1e56: + regmbc('P'); REGMBC(0x1e54) REGMBC(0x1e56) + return; + case 'R': CASEMBC(0x154) CASEMBC(0x156) CASEMBC(0x158) + CASEMBC(0x1e58) CASEMBC(0x1e5e) + regmbc('R'); REGMBC(0x154) REGMBC(0x156) REGMBC(0x158) + REGMBC(0x1e58) REGMBC(0x1e5e) + return; + case 'S': CASEMBC(0x15a) CASEMBC(0x15c) CASEMBC(0x15e) + CASEMBC(0x160) CASEMBC(0x1e60) + regmbc('S'); REGMBC(0x15a) REGMBC(0x15c) + REGMBC(0x15e) REGMBC(0x160) REGMBC(0x1e60) + return; + case 'T': CASEMBC(0x162) CASEMBC(0x164) CASEMBC(0x166) + CASEMBC(0x1e6a) CASEMBC(0x1e6e) + regmbc('T'); REGMBC(0x162) REGMBC(0x164) + REGMBC(0x166) REGMBC(0x1e6a) REGMBC(0x1e6e) return; case 'U': case '\331': case '\332': case '\333': case '\334': + CASEMBC(0x168) CASEMBC(0x16a) CASEMBC(0x16c) CASEMBC(0x16e) + CASEMBC(0x170) CASEMBC(0x172) CASEMBC(0x1af) CASEMBC(0x1d3) + CASEMBC(0x1ee6) regmbc('U'); regmbc('\331'); regmbc('\332'); regmbc('\333'); regmbc('\334'); + REGMBC(0x168) REGMBC(0x16a) REGMBC(0x16c) + REGMBC(0x16e) REGMBC(0x170) REGMBC(0x172) + REGMBC(0x1af) REGMBC(0x1d3) REGMBC(0x1ee6) + return; + case 'V': CASEMBC(0x1e7c) + regmbc('V'); REGMBC(0x1e7c) + return; + case 'W': CASEMBC(0x174) CASEMBC(0x1e80) CASEMBC(0x1e82) + CASEMBC(0x1e84) CASEMBC(0x1e86) + regmbc('W'); REGMBC(0x174) REGMBC(0x1e80) + REGMBC(0x1e82) REGMBC(0x1e84) REGMBC(0x1e86) + return; + case 'X': CASEMBC(0x1e8a) CASEMBC(0x1e8c) + regmbc('X'); REGMBC(0x1e8a) REGMBC(0x1e8c) return; case 'Y': case '\335': + CASEMBC(0x176) CASEMBC(0x178) CASEMBC(0x1e8e) CASEMBC(0x1ef2) + CASEMBC(0x1ef6) CASEMBC(0x1ef8) regmbc('Y'); regmbc('\335'); + REGMBC(0x176) REGMBC(0x178) REGMBC(0x1e8e) + REGMBC(0x1ef2) REGMBC(0x1ef6) REGMBC(0x1ef8) + return; + case 'Z': CASEMBC(0x179) CASEMBC(0x17b) CASEMBC(0x17d) + CASEMBC(0x1b5) CASEMBC(0x1e90) CASEMBC(0x1e94) + regmbc('Z'); REGMBC(0x179) REGMBC(0x17b) + REGMBC(0x17d) REGMBC(0x1b5) REGMBC(0x1e90) + REGMBC(0x1e94) return; case 'a': case '\340': case '\341': case '\342': case '\343': case '\344': case '\345': + CASEMBC(0x101) CASEMBC(0x103) CASEMBC(0x105) CASEMBC(0x1ce) + CASEMBC(0x1df) CASEMBC(0x1e1) CASEMBC(0x1ea3) regmbc('a'); regmbc('\340'); regmbc('\341'); regmbc('\342'); regmbc('\343'); regmbc('\344'); regmbc('\345'); + REGMBC(0x101) REGMBC(0x103) REGMBC(0x105) + REGMBC(0x1ce) REGMBC(0x1df) REGMBC(0x1e1) + REGMBC(0x1ea3) + return; + case 'b': CASEMBC(0x1e03) CASEMBC(0x1e07) + regmbc('b'); REGMBC(0x1e03) REGMBC(0x1e07) return; case 'c': case '\347': + CASEMBC(0x107) CASEMBC(0x109) CASEMBC(0x10b) CASEMBC(0x10d) regmbc('c'); regmbc('\347'); + REGMBC(0x107) REGMBC(0x109) REGMBC(0x10b) + REGMBC(0x10d) + return; + case 'd': CASEMBC(0x10f) CASEMBC(0x111) CASEMBC(0x1d0b) + CASEMBC(0x1e11) + regmbc('d'); REGMBC(0x10f) REGMBC(0x111) + REGMBC(0x1e0b) REGMBC(0x01e0f) REGMBC(0x1e11) return; case 'e': case '\350': case '\351': case '\352': case '\353': + CASEMBC(0x113) CASEMBC(0x115) CASEMBC(0x117) CASEMBC(0x119) + CASEMBC(0x11b) CASEMBC(0x1ebb) CASEMBC(0x1ebd) regmbc('e'); regmbc('\350'); regmbc('\351'); regmbc('\352'); regmbc('\353'); + REGMBC(0x113) REGMBC(0x115) REGMBC(0x117) + REGMBC(0x119) REGMBC(0x11b) REGMBC(0x1ebb) + REGMBC(0x1ebd) + return; + case 'f': CASEMBC(0x1e1f) + regmbc('f'); REGMBC(0x1e1f) + return; + case 'g': CASEMBC(0x11d) CASEMBC(0x11f) CASEMBC(0x121) + CASEMBC(0x123) CASEMBC(0x1e5) CASEMBC(0x1e7) CASEMBC(0x1f5) + CASEMBC(0x1e21) + regmbc('g'); REGMBC(0x11d) REGMBC(0x11f) + REGMBC(0x121) REGMBC(0x123) REGMBC(0x1e5) + REGMBC(0x1e7) REGMBC(0x1f5) REGMBC(0x1e21) + return; + case 'h': CASEMBC(0x125) CASEMBC(0x127) CASEMBC(0x1e23) + CASEMBC(0x1e27) CASEMBC(0x1e29) CASEMBC(0x1e96) + regmbc('h'); REGMBC(0x125) REGMBC(0x127) + REGMBC(0x1e23) REGMBC(0x1e27) REGMBC(0x1e29) + REGMBC(0x1e96) return; case 'i': case '\354': case '\355': case '\356': case '\357': + CASEMBC(0x129) CASEMBC(0x12b) CASEMBC(0x12d) CASEMBC(0x12f) + CASEMBC(0x1d0) CASEMBC(0x1ec9) regmbc('i'); regmbc('\354'); regmbc('\355'); regmbc('\356'); regmbc('\357'); + REGMBC(0x129) REGMBC(0x12b) REGMBC(0x12d) + REGMBC(0x12f) REGMBC(0x1d0) REGMBC(0x1ec9) + return; + case 'j': CASEMBC(0x135) CASEMBC(0x1f0) + regmbc('j'); REGMBC(0x135) REGMBC(0x1f0) + return; + case 'k': CASEMBC(0x137) CASEMBC(0x1e9) CASEMBC(0x1e31) + CASEMBC(0x1e35) + regmbc('k'); REGMBC(0x137) REGMBC(0x1e9) + REGMBC(0x1e31) REGMBC(0x1e35) + return; + case 'l': CASEMBC(0x13a) CASEMBC(0x13c) CASEMBC(0x13e) + CASEMBC(0x140) CASEMBC(0x142) CASEMBC(0x1e3b) + regmbc('l'); REGMBC(0x13a) REGMBC(0x13c) + REGMBC(0x13e) REGMBC(0x140) REGMBC(0x142) + REGMBC(0x1e3b) + return; + case 'm': CASEMBC(0x1e3f) CASEMBC(0x1e41) + regmbc('m'); REGMBC(0x1e3f) REGMBC(0x1e41) return; case 'n': case '\361': + CASEMBC(0x144) CASEMBC(0x146) CASEMBC(0x148) CASEMBC(0x149) + CASEMBC(0x1e45) CASEMBC(0x1e49) regmbc('n'); regmbc('\361'); + REGMBC(0x144) REGMBC(0x146) REGMBC(0x148) + REGMBC(0x149) REGMBC(0x1e45) REGMBC(0x1e49) return; case 'o': case '\362': case '\363': case '\364': case '\365': - case '\366': + case '\366': case '\370': + CASEMBC(0x14d) CASEMBC(0x14f) CASEMBC(0x151) CASEMBC(0x1a1) + CASEMBC(0x1d2) CASEMBC(0x1eb) CASEMBC(0x1ed) CASEMBC(0x1ecf) regmbc('o'); regmbc('\362'); regmbc('\363'); regmbc('\364'); regmbc('\365'); regmbc('\366'); + regmbc('\370'); + REGMBC(0x14d) REGMBC(0x14f) REGMBC(0x151) + REGMBC(0x1a1) REGMBC(0x1d2) REGMBC(0x1eb) + REGMBC(0x1ed) REGMBC(0x1ecf) + return; + case 'p': CASEMBC(0x1e55) CASEMBC(0x1e57) + regmbc('p'); REGMBC(0x1e55) REGMBC(0x1e57) + return; + case 'r': CASEMBC(0x155) CASEMBC(0x157) CASEMBC(0x159) + CASEMBC(0x1e59) CASEMBC(0x1e5f) + regmbc('r'); REGMBC(0x155) REGMBC(0x157) REGMBC(0x159) + REGMBC(0x1e59) REGMBC(0x1e5f) + return; + case 's': CASEMBC(0x15b) CASEMBC(0x15d) CASEMBC(0x15f) + CASEMBC(0x161) CASEMBC(0x1e61) + regmbc('s'); REGMBC(0x15b) REGMBC(0x15d) + REGMBC(0x15f) REGMBC(0x161) REGMBC(0x1e61) + return; + case 't': CASEMBC(0x163) CASEMBC(0x165) CASEMBC(0x167) + CASEMBC(0x1e6b) CASEMBC(0x1e6f) CASEMBC(0x1e97) + regmbc('t'); REGMBC(0x163) REGMBC(0x165) REGMBC(0x167) + REGMBC(0x1e6b) REGMBC(0x1e6f) REGMBC(0x1e97) return; case 'u': case '\371': case '\372': case '\373': case '\374': + CASEMBC(0x169) CASEMBC(0x16b) CASEMBC(0x16d) CASEMBC(0x16f) + CASEMBC(0x171) CASEMBC(0x173) CASEMBC(0x1b0) CASEMBC(0x1d4) + CASEMBC(0x1ee7) regmbc('u'); regmbc('\371'); regmbc('\372'); regmbc('\373'); regmbc('\374'); + REGMBC(0x169) REGMBC(0x16b) REGMBC(0x16d) + REGMBC(0x16f) REGMBC(0x171) REGMBC(0x173) + REGMBC(0x1b0) REGMBC(0x1d4) REGMBC(0x1ee7) + return; + case 'v': CASEMBC(0x1e7d) + regmbc('v'); REGMBC(0x1e7d) + return; + case 'w': CASEMBC(0x175) CASEMBC(0x1e81) CASEMBC(0x1e83) + CASEMBC(0x1e85) CASEMBC(0x1e87) CASEMBC(0x1e98) + regmbc('w'); REGMBC(0x175) REGMBC(0x1e81) + REGMBC(0x1e83) REGMBC(0x1e85) REGMBC(0x1e87) + REGMBC(0x1e98) + return; + case 'x': CASEMBC(0x1e8b) CASEMBC(0x1e8d) + regmbc('x'); REGMBC(0x1e8b) REGMBC(0x1e8d) return; case 'y': case '\375': case '\377': + CASEMBC(0x177) CASEMBC(0x1e8f) CASEMBC(0x1e99) + CASEMBC(0x1ef3) CASEMBC(0x1ef7) CASEMBC(0x1ef9) regmbc('y'); regmbc('\375'); regmbc('\377'); + REGMBC(0x177) REGMBC(0x1e8f) REGMBC(0x1e99) + REGMBC(0x1ef3) REGMBC(0x1ef7) REGMBC(0x1ef9) + return; + case 'z': CASEMBC(0x17a) CASEMBC(0x17c) CASEMBC(0x17e) + CASEMBC(0x1b6) CASEMBC(0x1e91) CASEMBC(0x1e95) + regmbc('z'); REGMBC(0x17a) REGMBC(0x17c) + REGMBC(0x17e) REGMBC(0x1b6) REGMBC(0x1e91) + REGMBC(0x1e95) return; } #endif @@ -2468,6 +2699,8 @@ regmbc(c) int c; { + if (!has_mbyte && c > 0xff) + return; if (regcode == JUST_CALC_SIZE) regsize += (*mb_char2len)(c); else @@ -2588,7 +2821,7 @@ else offset = (int)(val - scan); /* When the offset uses more than 16 bits it can no longer fit in the two - * bytes avaliable. Use a global flag to avoid having to check return + * bytes available. Use a global flag to avoid having to check return * values in too many places. */ if (offset > 0xffff) reg_toolong = TRUE; @@ -3538,6 +3771,7 @@ regline = line; reglnum = 0; + reg_toolong = FALSE; /* Simplest case: Anchored match need be tried only once. */ if (prog->reganch) @@ -6871,6 +7105,7 @@ static regmmatch_T *submatch_mmatch; static linenr_T submatch_firstlnum; static linenr_T submatch_maxline; +static int submatch_line_lbr; #endif #if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO) @@ -6997,6 +7232,7 @@ submatch_mmatch = reg_mmatch; submatch_firstlnum = reg_firstlnum; submatch_maxline = reg_maxline; + submatch_line_lbr = reg_line_lbr; save_reg_win = reg_win; save_ireg_ic = ireg_ic; can_f_submatch = TRUE; @@ -7008,9 +7244,10 @@ for (s = eval_result; *s != NUL; mb_ptr_adv(s)) { - /* Change NL to CR, so that it becomes a line break. + /* Change NL to CR, so that it becomes a line break, + * unless called from vim_regexec_nl(). * Skip over a backslashed character. */ - if (*s == NL) + if (*s == NL && !submatch_line_lbr) *s = CAR; else if (*s == '\\' && s[1] != NUL) { @@ -7019,8 +7256,9 @@ * :s/abc\\\ndef/\="aaa\\\nbbb"/ on text: * abc\ * def + * Not when called from vim_regexec_nl(). */ - if (*s == NL) + if (*s == NL && !submatch_line_lbr) *s = CAR; had_backslash = TRUE; } @@ -7043,6 +7281,7 @@ reg_mmatch = submatch_mmatch; reg_firstlnum = submatch_firstlnum; reg_maxline = submatch_maxline; + reg_line_lbr = submatch_line_lbr; reg_win = save_reg_win; ireg_ic = save_ireg_ic; can_f_submatch = FALSE; diff -Naur vim73.orig/src/screen.c vim73/src/screen.c --- vim73.orig/src/screen.c 2010-08-13 13:21:27.000000000 +0000 +++ vim73/src/screen.c 2012-07-20 20:31:18.064311652 +0000 @@ -89,6 +89,9 @@ #include "vim.h" +#define MB_FILLER_CHAR '<' /* character used when a double-width character + * doesn't fit. */ + /* * The attributes that are actually active for writing to the screen. */ @@ -516,8 +519,10 @@ # endif # ifdef FEAT_CLIPBOARD /* When Visual area changed, may have to update selection. */ - if (clip_star.available && clip_isautosel()) - clip_update_selection(); + if (clip_star.available && clip_isautosel_star()) + clip_update_selection(&clip_star); + if (clip_plus.available && clip_isautosel_plus()) + clip_update_selection(&clip_plus); # endif #ifdef FEAT_GUI /* Remove the cursor before starting to do anything, because @@ -764,9 +769,13 @@ doit = TRUE; } - /* Return when there is nothing to do or screen updating already - * happening. */ - if (!doit || updating_screen) + /* Return when there is nothing to do, screen updating is already + * happening (recursive call) or still starting up. */ + if (!doit || updating_screen +#ifdef FEAT_GUI + || gui.starting +#endif + || starting) return; /* update all windows that need updating */ @@ -807,8 +816,10 @@ #ifdef FEAT_CLIPBOARD /* When Visual area changed, may have to update selection. */ - if (clip_star.available && clip_isautosel()) - clip_update_selection(); + if (clip_star.available && clip_isautosel_star()) + clip_update_selection(&clip_star); + if (clip_plus.available && clip_isautosel_plus()) + clip_update_selection(&clip_plus); #endif win_update(wp); @@ -1633,11 +1644,11 @@ * When at start of changed lines: May scroll following lines * up or down to minimize redrawing. * Don't do this when the change continues until the end. - * Don't scroll when dollar_vcol is non-zero, keep the "$". + * Don't scroll when dollar_vcol >= 0, keep the "$". */ if (lnum == mod_top && mod_bot != MAXLNUM - && !(dollar_vcol != 0 && mod_bot == mod_top + 1)) + && !(dollar_vcol >= 0 && mod_bot == mod_top + 1)) { int old_rows = 0; int new_rows = 0; @@ -1864,12 +1875,12 @@ if (row > wp->w_height) /* past end of screen */ { /* we may need the size of that too long line later on */ - if (dollar_vcol == 0) + if (dollar_vcol == -1) wp->w_lines[idx].wl_size = plines_win(wp, lnum, TRUE); ++idx; break; } - if (dollar_vcol == 0) + if (dollar_vcol == -1) wp->w_lines[idx].wl_size = row - srow; ++idx; #ifdef FEAT_FOLDING @@ -1986,7 +1997,7 @@ } #endif } - else if (dollar_vcol == 0) + else if (dollar_vcol == -1) wp->w_botline = lnum; /* make sure the rest of the screen is blank */ @@ -2001,7 +2012,7 @@ wp->w_old_botfill = wp->w_botfill; #endif - if (dollar_vcol == 0) + if (dollar_vcol == -1) { /* * There is a trick with w_botline. If we invalidate it on each @@ -2317,7 +2328,7 @@ num = (long)lnum; else /* 'relativenumber', don't use negative numbers */ - num = (long)abs((int)get_cursor_rel_lnum(wp, lnum)); + num = labs((long)get_cursor_rel_lnum(wp, lnum)); sprintf((char *)buf, "%*ld ", w, num); #ifdef FEAT_RIGHTLEFT @@ -2531,7 +2542,9 @@ /* Visual block mode: highlight the chars part of the block */ if (wp->w_old_cursor_fcol + txtcol < (colnr_T)W_WIDTH(wp)) { - if (wp->w_old_cursor_lcol + txtcol < (colnr_T)W_WIDTH(wp)) + if (wp->w_old_cursor_lcol != MAXCOL + && wp->w_old_cursor_lcol + txtcol + < (colnr_T)W_WIDTH(wp)) len = wp->w_old_cursor_lcol; else len = W_WIDTH(wp) - txtcol; @@ -2991,7 +3004,10 @@ area_highlighting = TRUE; attr = hl_attr(HLF_V); #if defined(FEAT_CLIPBOARD) && defined(FEAT_X11) - if (clip_star.available && !clip_star.owned && clip_isautosel()) + if ((clip_star.available && !clip_star.owned + && clip_isautosel_star()) + || (clip_plus.available && !clip_plus.owned + && clip_isautosel_plus())) attr = hl_attr(HLF_VNC); #endif } @@ -3222,8 +3238,7 @@ /* 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) - - line + 1); + word_end = (int)(spell_to_word_end(ptr, wp) - line + 1); } else { @@ -3405,9 +3420,9 @@ # endif ) { - int_u text_sign; + int text_sign; # ifdef FEAT_SIGN_ICONS - int_u icon_sign; + int icon_sign; # endif /* Draw two cells with the sign value or blank. */ @@ -3475,8 +3490,7 @@ num = (long)lnum; else /* 'relativenumber', don't use negative numbers */ - num = (long)abs((int)get_cursor_rel_lnum(wp, - lnum)); + num = labs((long)get_cursor_rel_lnum(wp, lnum)); sprintf((char *)extra, "%*ld ", number_width(wp), num); @@ -3496,9 +3510,11 @@ char_attr = hl_attr(HLF_N); #ifdef FEAT_SYN_HL /* When 'cursorline' is set highlight the line number of - * the current line differently. */ + * the current line differently. + * TODO: Can we use CursorLine instead of CursorLineNr + * when CursorLineNr isn't set? */ if (wp->w_p_cul && lnum == wp->w_cursor.lnum) - char_attr = hl_combine_attr(hl_attr(HLF_CUL), char_attr); + char_attr = hl_attr(HLF_CLN); #endif } } @@ -3559,7 +3575,7 @@ } /* When still displaying '$' of change command, stop at cursor */ - if (dollar_vcol != 0 && wp == curwin + if (dollar_vcol >= 0 && wp == curwin && lnum == wp->w_cursor.lnum && vcol >= (long)wp->w_virtcol #ifdef FEAT_DIFF && filler_todo <= 0 @@ -4010,7 +4026,7 @@ if (n_skip > 0 && mb_l > 1 && n_extra == 0) { n_extra = 1; - c_extra = '<'; + c_extra = MB_FILLER_CHAR; c = ' '; if (area_attr == 0 && search_attr == 0) { @@ -4253,7 +4269,7 @@ { /* tab amount depends on current column */ n_extra = (int)wp->w_buffer->b_p_ts - - vcol % (int)wp->w_buffer->b_p_ts - 1; + - VCOL_HLC % (int)wp->w_buffer->b_p_ts - 1; #ifdef FEAT_MBYTE mb_utf8 = FALSE; /* don't draw as UTF-8 */ #endif @@ -4570,6 +4586,15 @@ c = lcs_prec; lcs_prec_todo = NUL; #ifdef FEAT_MBYTE + if (has_mbyte && (*mb_char2cells)(mb_c) > 1) + { + /* Double-width character being overwritten by the "precedes" + * character, need to fill up half the character. */ + c_extra = MB_FILLER_CHAR; + n_extra = 1; + n_attr = 2; + extra_attr = hl_attr(HLF_AT); + } mb_c = c; if (enc_utf8 && (*mb_char2len)(c) > 1) { @@ -5366,6 +5391,12 @@ # define CHAR_CELLS 1 #endif + /* Check for illegal row and col, just in case. */ + if (row >= Rows) + row = Rows - 1; + if (endcol > Columns) + endcol = Columns; + # ifdef FEAT_CLIPBOARD clip_may_clear_selection(row, row); # endif @@ -6436,6 +6467,8 @@ struct stl_hlrec hltab[STL_MAX_ITEM]; struct stl_hlrec tabtab[STL_MAX_ITEM]; int use_sandbox = FALSE; + win_T *ewp; + int p_crb_save; /* setup environment for the task at hand */ if (wp == NULL) @@ -6514,16 +6547,31 @@ if (maxwidth <= 0) return; + /* Temporarily reset 'cursorbind', we don't want a side effect from moving + * the cursor away and back. */ + ewp = wp == NULL ? curwin : wp; + p_crb_save = ewp->w_p_crb; + ewp->w_p_crb = FALSE; + /* Make a copy, because the statusline may include a function call that * might change the option value and free the memory. */ stl = vim_strsave(stl); - width = build_stl_str_hl(wp == NULL ? curwin : wp, - buf, sizeof(buf), + width = build_stl_str_hl(ewp, buf, sizeof(buf), stl, use_sandbox, fillchar, maxwidth, hltab, tabtab); vim_free(stl); - len = (int)STRLEN(buf); + ewp->w_p_crb = p_crb_save; + /* Make all characters printable. */ + p = transstr(buf); + if (p != NULL) + { + vim_strncpy(buf, p, sizeof(buf) - 1); + vim_free(p); + } + + /* fill up with "fillchar" */ + len = (int)STRLEN(buf); while (width < maxwidth && len < (int)sizeof(buf) - 1) { #ifdef FEAT_MBYTE @@ -6591,16 +6639,17 @@ int row, col; int attr; { -#ifdef FEAT_MBYTE char_u buf[MB_MAXBYTES + 1]; - buf[(*mb_char2bytes)(c, buf)] = NUL; -#else - char_u buf[2]; - - buf[0] = c; - buf[1] = NUL; +#ifdef FEAT_MBYTE + if (has_mbyte) + buf[(*mb_char2bytes)(c, buf)] = NUL; + else #endif + { + buf[0] = c; + buf[1] = NUL; + } screen_puts(buf, row, col, attr); } @@ -7827,15 +7876,15 @@ /* * screen_valid - allocate screen buffers if size changed - * If "clear" is TRUE: clear screen if it has been resized. + * If "doclear" is TRUE: clear screen if it has been resized. * Returns TRUE if there is a valid screen to write to. * Returns FALSE when starting up and screen not initialized yet. */ int -screen_valid(clear) - int clear; +screen_valid(doclear) + int doclear; { - screenalloc(clear); /* allocate screen buffers if size changed */ + screenalloc(doclear); /* allocate screen buffers if size changed */ return (ScreenLines != NULL); } @@ -7850,8 +7899,8 @@ * final size of the shell is needed. */ void -screenalloc(clear) - int clear; +screenalloc(doclear) + int doclear; { int new_row, old_row; #ifdef FEAT_GUI @@ -8047,7 +8096,7 @@ * (used when resizing the window at the "--more--" prompt or when * executing an external command, for the GUI). */ - if (!clear) + if (!doclear) { (void)vim_memset(new_ScreenLines + new_row * Columns, ' ', (size_t)Columns * sizeof(schar_T)); @@ -8137,7 +8186,7 @@ screen_Columns = Columns; must_redraw = CLEAR; /* need to clear the screen later */ - if (clear) + if (doclear) screenclear2(); #ifdef FEAT_GUI @@ -9018,7 +9067,7 @@ || (wp != NULL && wp->w_width != Columns) # endif ) - clip_clear_selection(); + clip_clear_selection(&clip_star); else clip_scroll_selection(-line_count); #endif @@ -9239,7 +9288,7 @@ || (wp != NULL && wp->w_width != Columns) # endif ) - clip_clear_selection(); + clip_clear_selection(&clip_star); else clip_scroll_selection(line_count); #endif diff -Naur vim73.orig/src/search.c vim73/src/search.c --- vim73.orig/src/search.c 2010-07-14 14:49:41.000000000 +0000 +++ vim73/src/search.c 2012-07-20 20:31:18.304311823 +0000 @@ -1161,12 +1161,20 @@ { if (spats[RE_SEARCH].pat == NULL) /* no previous pattern */ { - EMSG(_(e_noprevre)); - retval = 0; - goto end_do_search; + pat = spats[RE_SUBST].pat; + if (pat == NULL) + { + EMSG(_(e_noprevre)); + retval = 0; + goto end_do_search; + } + searchstr = pat; + } + else + { + /* make search_regcomp() use spats[RE_SEARCH].pat */ + searchstr = (char_u *)""; } - /* make search_regcomp() use spats[RE_SEARCH].pat */ - searchstr = (char_u *)""; } if (pat != NULL && *pat != NUL) /* look for (new) offset */ @@ -1538,8 +1546,9 @@ int col; char_u *p; int len; + int stop = TRUE; #ifdef FEAT_MBYTE - static char_u bytes[MB_MAXBYTES]; + static char_u bytes[MB_MAXBYTES + 1]; static int bytelen = 1; /* >1 for multi-byte char */ #endif @@ -1572,6 +1581,12 @@ t_cmd = last_t_cmd; c = lastc; /* For multi-byte re-use last bytes[] and bytelen. */ + + /* Force a move of at least one char, so ";" and "," will move the + * cursor, even if the cursor is right in front of char we are looking + * at. */ + if (vim_strchr(p_cpo, CPO_SCOLON) == NULL && count == 1 && t_cmd) + stop = FALSE; } if (dir == BACKWARD) @@ -1604,14 +1619,15 @@ } if (bytelen == 1) { - if (p[col] == c) + if (p[col] == c && stop) break; } else { - if (vim_memcmp(p + col, bytes, bytelen) == 0) + if (vim_memcmp(p + col, bytes, bytelen) == 0 && stop) break; } + stop = TRUE; } } else @@ -1621,8 +1637,9 @@ { if ((col += dir) < 0 || col >= len) return FAIL; - if (p[col] == c) + if (p[col] == c && stop) break; + stop = TRUE; } } } @@ -2385,24 +2402,24 @@ { if (vim_strchr(p, ';') != NULL) /* there may be comments */ { - int instr = FALSE; /* inside of string */ + int in_str = FALSE; /* inside of string */ p = line; /* scan from start */ while ((p = vim_strpbrk(p, (char_u *)"\";")) != NULL) { if (*p == '"') { - if (instr) + if (in_str) { if (*(p - 1) != '\\') /* skip escaped quote */ - instr = FALSE; + in_str = FALSE; } else if (p == line || ((p - line) >= 2 /* skip #\" form */ && *(p - 1) != '\\' && *(p - 2) != '#')) - instr = TRUE; + in_str = TRUE; } - else if (!instr && ((p - line) < 2 + else if (!in_str && ((p - line) < 2 || (*(p - 1) != '\\' && *(p - 2) != '#'))) break; /* found! */ ++p; @@ -2484,8 +2501,8 @@ save_siso = p_siso; /* Handle "$" in 'cpo': If the ')' is typed on top of the "$", * stop displaying the "$". */ - if (dollar_vcol > 0 && dollar_vcol == curwin->w_virtcol) - dollar_vcol = 0; + if (dollar_vcol >= 0 && dollar_vcol == curwin->w_virtcol) + dollar_vcol = -1; ++curwin->w_virtcol; /* do display ')' just before "$" */ update_screen(VALID); /* show the new char first */ @@ -3901,7 +3918,7 @@ curwin->w_cursor = old_pos; goto theend; } - spat = alloc(len + 29); + spat = alloc(len + 31); epat = alloc(len + 9); if (spat == NULL || epat == NULL) { @@ -3910,7 +3927,7 @@ curwin->w_cursor = old_pos; goto theend; } - sprintf((char *)spat, "<%.*s\\%%(\\_[^>]\\{-}[^/]>\\|>\\)\\c", len, p); + sprintf((char *)spat, "<%.*s\\>\\%%(\\s\\_[^>]\\{-}[^/]>\\|>\\)\\c", len, p); sprintf((char *)epat, "\\c", len, p); r = do_searchpair(spat, (char_u *)"", epat, FORWARD, (char_u *)"", @@ -4527,7 +4544,7 @@ #if defined(FEAT_FIND_ID) || defined(PROTO) /* * Find identifiers or defines in included files. - * if p_ic && (compl_cont_status & CONT_SOL) then ptr must be in lowercase. + * If p_ic && (compl_cont_status & CONT_SOL) then ptr must be in lowercase. */ void find_pattern_in_path(ptr, dir, len, whole, skip_comments, @@ -4573,9 +4590,6 @@ char_u *already = NULL; char_u *startp = NULL; char_u *inc_opt = NULL; -#ifdef RISCOS - int previous_munging = __riscosify_control; -#endif #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX) win_T *curwin_save = NULL; #endif @@ -4588,11 +4602,6 @@ if (file_line == NULL) return; -#ifdef RISCOS - /* UnixLib knows best how to munge c file names - turn munging back on. */ - int __riscosify_control = 0; -#endif - if (type != CHECK_PATH && type != FIND_DEFINE #ifdef FEAT_INS_EXPAND /* when CONT_SOL is set compare "ptr" with the beginning of the line @@ -4892,7 +4901,7 @@ #ifdef FEAT_COMMENTS if ((*line != '#' || STRNCMP(skipwhite(line + 1), "define", 6) != 0) - && get_leader_len(line, NULL, FALSE)) + && get_leader_len(line, NULL, FALSE, TRUE)) matched = FALSE; /* @@ -5075,9 +5084,7 @@ if (win_split(0, 0) == FAIL) #endif break; -#ifdef FEAT_SCROLLBIND - curwin->w_p_scb = FALSE; -#endif + RESET_BINDING(curwin); } if (depth == -1) { @@ -5134,7 +5141,7 @@ && !(compl_cont_status & CONT_SOL) #endif && *startp != NUL - && *(p = startp + 1) != NUL) + && *(p = startp + MB_PTR2LEN(startp)) != NUL) goto search_line; } line_breakcheck(); @@ -5222,11 +5229,6 @@ vim_free(regmatch.regprog); vim_free(incl_regmatch.regprog); vim_free(def_regmatch.regprog); - -#ifdef RISCOS - /* Restore previous file munging state. */ - __riscosify_control = previous_munging; -#endif } static void diff -Naur vim73.orig/src/spell.c vim73/src/spell.c --- vim73.orig/src/spell.c 2010-08-01 13:43:01.000000000 +0000 +++ vim73/src/spell.c 2012-07-20 20:31:17.387644502 +0000 @@ -303,10 +303,6 @@ * few bytes as possible, see offset2bytes()) */ -#if defined(MSDOS) || defined(WIN16) || defined(WIN32) || defined(_WIN64) -# include "vimio.h" /* for lseek(), must be before vim.h */ -#endif - #include "vim.h" #if defined(FEAT_SPELL) || defined(PROTO) @@ -327,6 +323,16 @@ typedef long idx_T; #endif +#ifdef VMS +# define SPL_FNAME_TMPL "%s_%s.spl" +# define SPL_FNAME_ADD "_add." +# define SPL_FNAME_ASCII "_ascii." +#else +# define SPL_FNAME_TMPL "%s.%s.spl" +# define SPL_FNAME_ADD ".add." +# define SPL_FNAME_ASCII ".ascii." +#endif + /* Flags used for a word. Only the lowest byte can be used, the region byte * comes above it. */ #define WF_REGION 0x01 /* region byte follows */ @@ -2471,14 +2477,24 @@ * Find the first spell file for "lang" in 'runtimepath' and load it. */ vim_snprintf((char *)fname_enc, sizeof(fname_enc) - 5, - "spell/%s.%s.spl", lang, spell_enc()); +#ifdef VMS + "spell/%s_%s.spl", +#else + "spell/%s.%s.spl", +#endif + lang, spell_enc()); r = do_in_runtimepath(fname_enc, FALSE, spell_load_cb, &sl); if (r == FAIL && *sl.sl_lang != NUL) { /* Try loading the ASCII version. */ vim_snprintf((char *)fname_enc, sizeof(fname_enc) - 5, - "spell/%s.ascii.spl", lang); +#ifdef VMS + "spell/%s_ascii.spl", +#else + "spell/%s.ascii.spl", +#endif + lang); r = do_in_runtimepath(fname_enc, FALSE, spell_load_cb, &sl); #ifdef FEAT_AUTOCMD @@ -2496,7 +2512,12 @@ if (r == FAIL) { - smsg((char_u *)_("Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\""), + smsg((char_u *) +#ifdef VMS + _("Warning: Cannot find word list \"%s_%s.spl\" or \"%s_ascii.spl\""), +#else + _("Warning: Cannot find word list \"%s.%s.spl\" or \"%s.ascii.spl\""), +#endif lang, spell_enc(), lang); } else if (sl.sl_slang != NULL) @@ -2530,7 +2551,7 @@ int_wordlist_spl(fname) char_u *fname; { - vim_snprintf((char *)fname, MAXPATHL, "%s.%s.spl", + vim_snprintf((char *)fname, MAXPATHL, SPL_FNAME_TMPL, int_wordlist, spell_enc()); } @@ -2785,8 +2806,8 @@ if (lp->sl_fname == NULL) goto endFAIL; - /* Check for .add.spl. */ - lp->sl_add = strstr((char *)gettail(fname), ".add.") != NULL; + /* Check for .add.spl (_add.spl for VMS). */ + lp->sl_add = strstr((char *)gettail(fname), SPL_FNAME_ADD) != NULL; } else lp = old_lp; @@ -3613,7 +3634,7 @@ } /* Add all flags to "sl_compallflags". */ - if (vim_strchr((char_u *)"+*[]/", c) == NULL + if (vim_strchr((char_u *)"?*+[]/", c) == NULL && !byte_in_str(slang->sl_compallflags, c)) { *ap++ = c; @@ -3643,7 +3664,7 @@ /* Copy flag to "sl_comprules", unless we run into a wildcard. */ if (crp != NULL) { - if (c == '+' || c == '*') + if (c == '?' || c == '+' || c == '*') { vim_free(slang->sl_comprules); slang->sl_comprules = NULL; @@ -3661,8 +3682,8 @@ } else /* normal char, "[abc]" and '*' are copied as-is */ { - if (c == '+' || c == '~') - *pp++ = '\\'; /* "a+" becomes "a\+" */ + if (c == '?' || c == '+' || c == '~') + *pp++ = '\\'; /* "a?" becomes "a\?", "a+" becomes "a\+" */ #ifdef FEAT_MBYTE if (enc_utf8) pp += mb_char2bytes(c, pp); @@ -4679,7 +4700,7 @@ buf_T *buf; char_u fname[MAXPATHL]; - /* Go through all buffers and handle 'spelllang'. */ // + /* Go through all buffers and handle 'spelllang'. */ for (buf = firstbuf; buf != NULL; buf = buf->b_next) ga_clear(&buf->b_s.b_langp); @@ -4700,8 +4721,6 @@ int_wordlist = NULL; } - init_spell_chartab(); - vim_free(repl_to); repl_to = NULL; vim_free(repl_from); @@ -4930,6 +4949,8 @@ sblock_T *si_blocks; /* memory blocks used */ long si_blocks_cnt; /* memory blocks allocated */ + int si_did_emsg; /* TRUE when ran out of memory */ + long si_compress_cnt; /* words to add before lowering compression limit */ wordnode_T *si_first_free; /* List of nodes that have been freed during @@ -4951,7 +4972,7 @@ char_u *si_info; /* info text chars or NULL */ int si_region_count; /* number of regions supported (1 when there are no regions) */ - char_u si_region_name[16]; /* region names; used only if + char_u si_region_name[17]; /* region names; used only if * si_region_count > 1) */ garray_T si_rep; /* list of fromto_T entries from REP lines */ @@ -4997,7 +5018,6 @@ static int str_equal __ARGS((char_u *s1, char_u *s2)); static void add_fromto __ARGS((spellinfo_T *spin, garray_T *gap, char_u *from, char_u *to)); static int sal_to_bool __ARGS((char_u *s)); -static int has_non_ascii __ARGS((char_u *s)); static void spell_free_aff __ARGS((afffile_T *aff)); static int spell_read_dic __ARGS((spellinfo_T *spin, char_u *fname, afffile_T *affile)); static int get_affix_flags __ARGS((afffile_T *affile, char_u *afflist)); @@ -5027,7 +5047,7 @@ static int offset2bytes __ARGS((int nr, char_u *buf)); static int bytes2offset __ARGS((char_u **pp)); static void sug_write __ARGS((spellinfo_T *spin, char_u *fname)); -static void mkspell __ARGS((int fcount, char_u **fnames, int ascii, int overwrite, int added_word)); +static void mkspell __ARGS((int fcount, char_u **fnames, int ascii, int over_write, int added_word)); static void spell_message __ARGS((spellinfo_T *spin, char_u *str)); static void init_spellfile __ARGS((void)); @@ -5456,21 +5476,25 @@ } else if (is_aff_rule(items, itemcnt, "COMPOUNDRULE", 2)) { - /* Concatenate this string to previously defined ones, using a - * slash to separate them. */ - l = (int)STRLEN(items[1]) + 1; - if (compflags != NULL) - l += (int)STRLEN(compflags) + 1; - p = getroom(spin, l, FALSE); - if (p != NULL) + /* Don't use the first rule if it is a number. */ + if (compflags != NULL || *skipdigits(items[1]) != NUL) { + /* Concatenate this string to previously defined ones, + * using a slash to separate them. */ + l = (int)STRLEN(items[1]) + 1; if (compflags != NULL) + l += (int)STRLEN(compflags) + 1; + p = getroom(spin, l, FALSE); + if (p != NULL) { - STRCPY(p, compflags); - STRCAT(p, "/"); + if (compflags != NULL) + { + STRCPY(p, compflags); + STRCAT(p, "/"); + } + STRCAT(p, items[1]); + compflags = p; } - STRCAT(p, items[1]); - compflags = p; } } else if (is_aff_rule(items, itemcnt, "COMPOUNDWORDMAX", 2) @@ -6270,7 +6294,7 @@ for (p = compflags; *p != NUL; ) { - if (vim_strchr((char_u *)"/*+[]", *p) != NULL) + if (vim_strchr((char_u *)"/?*+[]", *p) != NULL) /* Copy non-flag characters directly. */ *tp++ = *p++; else @@ -6299,7 +6323,7 @@ { check_renumber(spin); id = spin->si_newcompID--; - } while (vim_strchr((char_u *)"/+*[]\\-^", id) != NULL); + } while (vim_strchr((char_u *)"/?*+[]\\-^", id) != NULL); ci->ci_newID = id; hash_add(&aff->af_comp, ci->ci_key); } @@ -6458,23 +6482,6 @@ } /* - * Return TRUE if string "s" contains a non-ASCII character (128 or higher). - * When "s" is NULL FALSE is returned. - */ - static int -has_non_ascii(s) - char_u *s; -{ - char_u *p; - - if (s != NULL) - for (p = s; *p != NUL; ++p) - if (*p >= 128) - return TRUE; - return FALSE; -} - -/* * Free the structure filled by spell_read_aff(). */ static void @@ -6930,7 +6937,7 @@ if (ae->ae_add == NULL) *newword = NUL; else - STRCPY(newword, ae->ae_add); + vim_strncpy(newword, ae->ae_add, MAXWLEN - 1); p = word; if (ae->ae_chop != NULL) { @@ -6951,7 +6958,7 @@ else { /* suffix: chop/add at the end of the word */ - STRCPY(newword, word); + vim_strncpy(newword, word, MAXWLEN - 1); if (ae->ae_chop != NULL) { /* Remove chop string. */ @@ -7343,10 +7350,21 @@ if (bl == NULL || bl->sb_used + len > SBLOCKSIZE) { - /* Allocate a block of memory. This is not freed until much later. */ - bl = (sblock_T *)alloc_clear((unsigned)(sizeof(sblock_T) + SBLOCKSIZE)); + if (len >= SBLOCKSIZE) + bl = NULL; + else + /* Allocate a block of memory. It is not freed until much later. */ + bl = (sblock_T *)alloc_clear( + (unsigned)(sizeof(sblock_T) + SBLOCKSIZE)); if (bl == NULL) + { + if (!spin->si_did_emsg) + { + EMSG(_("E845: Insufficient memory, word list will be incomplete")); + spin->si_did_emsg = TRUE; + } return NULL; + } bl->sb_next = spin->si_blocks; spin->si_blocks = bl; bl->sb_used = 0; @@ -7361,6 +7379,7 @@ /* * Make a copy of a string into memory allocated with getroom(). + * Returns NULL when out of memory. */ static char_u * getroom_save(spin, s) @@ -7395,6 +7414,7 @@ /* * Allocate the root of a word tree. + * Returns NULL when out of memory. */ static wordnode_T * wordtree_alloc(spin) @@ -7679,6 +7699,7 @@ /* * Get a wordnode_T, either from the list of previously freed nodes or * allocate a new one. + * Returns NULL when out of memory. */ static wordnode_T * get_wordnode(spin) @@ -7696,7 +7717,8 @@ --spin->si_free_count; } #ifdef SPELL_PRINTTREE - n->wn_nr = ++spin->si_wordnode_nr; + if (n != NULL) + n->wn_nr = ++spin->si_wordnode_nr; #endif return n; } @@ -8531,7 +8553,7 @@ } /* Expand all the remaining arguments (e.g., $VIMRUNTIME). */ - if (get_arglist_exp(arg, &fcount, &fnames) == OK) + if (get_arglist_exp(arg, &fcount, &fnames, FALSE) == OK) { mkspell(fcount, fnames, ascii, eap->forceit, FALSE); FreeWild(fcount, fnames); @@ -8548,7 +8570,7 @@ spellinfo_T *spin; char_u *wfname; { - char_u fname[MAXPATHL]; + char_u *fname = NULL; int len; slang_T *slang; int free_slang = FALSE; @@ -8612,13 +8634,17 @@ * Write the .sug file. * Make the file name by changing ".spl" to ".sug". */ - STRCPY(fname, wfname); + fname = alloc(MAXPATHL); + if (fname == NULL) + goto theend; + vim_strncpy(fname, wfname, MAXPATHL - 1); len = (int)STRLEN(fname); fname[len - 2] = 'u'; fname[len - 1] = 'g'; sug_write(spin, fname); theend: + vim_free(fname); if (free_slang) slang_free(slang); free_blocks(spin->si_blocks); @@ -9057,15 +9083,15 @@ * and ".spl" is appended to make the output file name. */ static void -mkspell(fcount, fnames, ascii, overwrite, added_word) +mkspell(fcount, fnames, ascii, over_write, added_word) int fcount; char_u **fnames; int ascii; /* -ascii argument given */ - int overwrite; /* overwrite existing output file */ + int over_write; /* overwrite existing output file */ int added_word; /* invoked through "zg" */ { - char_u fname[MAXPATHL]; - char_u wfname[MAXPATHL]; + char_u *fname = NULL; + char_u *wfname; char_u **innames; int incount; afffile_T *(afile[8]); @@ -9093,6 +9119,10 @@ innames = &fnames[1]; incount = fcount - 1; + wfname = alloc(MAXPATHL); + if (wfname == NULL) + return; + if (fcount >= 1) { len = (int)STRLEN(fnames[0]); @@ -9102,32 +9132,32 @@ * "path/en.latin1.add.spl". */ innames = &fnames[0]; incount = 1; - vim_snprintf((char *)wfname, sizeof(wfname), "%s.spl", fnames[0]); + vim_snprintf((char *)wfname, MAXPATHL, "%s.spl", fnames[0]); } else if (fcount == 1) { /* For ":mkspell path/vim" output file is "path/vim.latin1.spl". */ innames = &fnames[0]; incount = 1; - vim_snprintf((char *)wfname, sizeof(wfname), "%s.%s.spl", fnames[0], - spin.si_ascii ? (char_u *)"ascii" : spell_enc()); + vim_snprintf((char *)wfname, MAXPATHL, SPL_FNAME_TMPL, + fnames[0], spin.si_ascii ? (char_u *)"ascii" : spell_enc()); } else if (len > 4 && STRCMP(fnames[0] + len - 4, ".spl") == 0) { /* Name ends in ".spl", use as the file name. */ - vim_strncpy(wfname, fnames[0], sizeof(wfname) - 1); + vim_strncpy(wfname, fnames[0], MAXPATHL - 1); } else /* Name should be language, make the file name from it. */ - vim_snprintf((char *)wfname, sizeof(wfname), "%s.%s.spl", fnames[0], - spin.si_ascii ? (char_u *)"ascii" : spell_enc()); + vim_snprintf((char *)wfname, MAXPATHL, SPL_FNAME_TMPL, + fnames[0], spin.si_ascii ? (char_u *)"ascii" : spell_enc()); /* Check for .ascii.spl. */ - if (strstr((char *)gettail(wfname), ".ascii.") != NULL) + if (strstr((char *)gettail(wfname), SPL_FNAME_ASCII) != NULL) spin.si_ascii = TRUE; /* Check for .add.spl. */ - if (strstr((char *)gettail(wfname), ".add.") != NULL) + if (strstr((char *)gettail(wfname), SPL_FNAME_ADD) != NULL) spin.si_add = TRUE; } @@ -9141,17 +9171,21 @@ { /* Check for overwriting before doing things that may take a lot of * time. */ - if (!overwrite && mch_stat((char *)wfname, &st) >= 0) + if (!over_write && mch_stat((char *)wfname, &st) >= 0) { EMSG(_(e_exists)); - return; + goto theend; } if (mch_isdir(wfname)) { EMSG2(_(e_isadir2), wfname); - return; + goto theend; } + fname = alloc(MAXPATHL); + if (fname == NULL) + goto theend; + /* * Init the aff and dic pointers. * Get the region names if there are more than 2 arguments. @@ -9167,7 +9201,7 @@ || innames[i][len - 3] != '_') { EMSG2(_("E755: Invalid region in %s"), innames[i]); - return; + goto theend; } spin.si_region_name[i * 2] = TOLOWER_ASC(innames[i][len - 2]); spin.si_region_name[i * 2 + 1] = @@ -9184,7 +9218,7 @@ || spin.si_prefroot == NULL) { free_blocks(spin.si_blocks); - return; + goto theend; } /* When not producing a .add.spl file clear the character table when @@ -9205,7 +9239,7 @@ spin.si_conv.vc_type = CONV_NONE; spin.si_region = 1 << i; - vim_snprintf((char *)fname, sizeof(fname), "%s.aff", innames[i]); + vim_snprintf((char *)fname, MAXPATHL, "%s.aff", innames[i]); if (mch_stat((char *)fname, &st) >= 0) { /* Read the .aff file. Will init "spin->si_conv" based on the @@ -9216,7 +9250,7 @@ else { /* Read the .dic file and store the words in the trees. */ - vim_snprintf((char *)fname, sizeof(fname), "%s.dic", + vim_snprintf((char *)fname, MAXPATHL, "%s.dic", innames[i]); if (spell_read_dic(&spin, fname, afile[i]) == FAIL) error = TRUE; @@ -9298,6 +9332,10 @@ spell_make_sugfile(&spin, wfname); } + +theend: + vim_free(fname); + vim_free(wfname); } /* @@ -9350,7 +9388,7 @@ buf_T *buf = NULL; int new_spf = FALSE; char_u *fname; - char_u fnamebuf[MAXPATHL]; + char_u *fnamebuf = NULL; char_u line[MAXWLEN * 2]; long fpos, fpos_next = 0; int i; @@ -9380,6 +9418,9 @@ EMSG2(_(e_notset), "spellfile"); return; } + fnamebuf = alloc(MAXPATHL); + if (fnamebuf == NULL) + return; for (spf = curwin->w_s->b_p_spf, i = 1; *spf != NUL; ++i) { @@ -9389,6 +9430,7 @@ if (*spf == NUL) { EMSGN(_("E765: 'spellfile' does not have %ld entries"), idx); + vim_free(fnamebuf); return; } } @@ -9400,6 +9442,7 @@ if (buf != NULL && bufIsChanged(buf)) { EMSG(_(e_bufloaded)); + vim_free(fnamebuf); return; } @@ -9494,6 +9537,7 @@ redraw_all_later(SOME_VALID); } + vim_free(fnamebuf); } /* @@ -9502,7 +9546,7 @@ static void init_spellfile() { - char_u buf[MAXPATHL]; + char_u *buf; int l; char_u *fname; char_u *rtp; @@ -9512,6 +9556,10 @@ if (*curwin->w_s->b_p_spl != NUL && curwin->w_s->b_langp.ga_len > 0) { + buf = alloc(MAXPATHL); + if (buf == NULL) + return; + /* Find the end of the language name. Exclude the region. If there * is a path separator remember the start of the tail. */ for (lend = curwin->w_s->b_p_spl; *lend != NUL @@ -9530,7 +9578,8 @@ if (aspath) /* Use directory of an entry with path, e.g., for * "/dir/lg.utf-8.spl" use "/dir". */ - vim_strncpy(buf, curbuf->b_s.b_p_spl, lstart - curbuf->b_s.b_p_spl - 1); + vim_strncpy(buf, curbuf->b_s.b_p_spl, + lstart - curbuf->b_s.b_p_spl - 1); else /* Copy the path from 'runtimepath' to buf[]. */ copy_option_part(&rtp, buf, MAXPATHL, ","); @@ -9539,13 +9588,14 @@ /* Use the first language name from 'spelllang' and the * encoding used in the first loaded .spl file. */ if (aspath) - vim_strncpy(buf, curbuf->b_s.b_p_spl, lend - curbuf->b_s.b_p_spl); + vim_strncpy(buf, curbuf->b_s.b_p_spl, + lend - curbuf->b_s.b_p_spl); else { /* Create the "spell" directory if it doesn't exist yet. */ l = (int)STRLEN(buf); vim_snprintf((char *)buf + l, MAXPATHL - l, "/spell"); - if (!filewritable(buf) != 2) + if (filewritable(buf) != 2) vim_mkdir(buf, 0755); l = (int)STRLEN(buf); @@ -9553,7 +9603,8 @@ "/%.*s", (int)(lend - lstart), lstart); } l = (int)STRLEN(buf); - fname = LANGP_ENTRY(curwin->w_s->b_langp, 0)->lp_slang->sl_fname; + fname = LANGP_ENTRY(curwin->w_s->b_langp, 0) + ->lp_slang->sl_fname; vim_snprintf((char *)buf + l, MAXPATHL - l, ".%s.add", fname != NULL && strstr((char *)gettail(fname), ".ascii.") != NULL @@ -9563,6 +9614,8 @@ } aspath = FALSE; } + + vim_free(buf); } } @@ -9837,10 +9890,7 @@ { /* be quick for ASCII */ if (wp->w_s->b_spell_ismw[*p]) - { s = p + 1; /* skip a mid-word character */ - l = MB_BYTE2LEN(*s); - } } else { @@ -9848,10 +9898,7 @@ if (c < 256 ? wp->w_s->b_spell_ismw[c] : (wp->w_s->b_spell_ismw_mb != NULL && vim_strchr(wp->w_s->b_spell_ismw_mb, c) != NULL)) - { s = p + l; - l = MB_BYTE2LEN(*s); - } } c = mb_ptr2char(s); @@ -10223,7 +10270,7 @@ /* The suggested word may replace only part of the bad word, add * the not replaced part. */ - STRCPY(wcopy, stp->st_word); + vim_strncpy(wcopy, stp->st_word, MAXWLEN); if (sug.su_badlen > stp->st_orglen) vim_strncpy(wcopy + stp->st_wordlen, sug.su_badptr + stp->st_orglen, @@ -11130,7 +11177,7 @@ c = *s++; #ifdef FEAT_MBYTE - /* We only change ß to SS when we are certain latin1 is used. It + /* We only change 0xdf to SS when we are certain latin1 is used. It * would cause weird errors in other 8-bit encodings. */ if (enc_latin1like && c == 0xdf) { @@ -13124,7 +13171,7 @@ pbad = badsound2; } - if (lendiff > 0) + if (lendiff > 0 && stp->st_wordlen + lendiff < MAXWLEN) { /* Add part of the bad word to the good word, so that we soundfold * what replaces the bad word. */ @@ -13645,7 +13692,7 @@ { int m1, m2; #ifdef FEAT_MBYTE - char_u buf[MB_MAXBYTES]; + char_u buf[MB_MAXBYTES + 1]; hashitem_T *hi; if (c1 >= 256) @@ -13811,11 +13858,8 @@ su->su_sfmaxscore = cleanup_suggestions(gap, su->su_sfmaxscore, SUG_CLEAN_COUNT(su)); else - { - i = su->su_maxscore; su->su_maxscore = cleanup_suggestions(gap, su->su_maxscore, SUG_CLEAN_COUNT(su)); - } } } } @@ -13840,7 +13884,7 @@ for (i = gap->ga_len - 1; i >= 0; --i) { /* Need to append what follows to check for "the the". */ - STRCPY(longword, stp[i].st_word); + vim_strncpy(longword, stp[i].st_word, MAXWLEN); len = stp[i].st_wordlen; vim_strncpy(longword + len, su->su_badptr + stp[i].st_orglen, MAXWLEN - len); @@ -14186,7 +14230,7 @@ *t = NUL; } else - STRCPY(word, s); + vim_strncpy(word, s, MAXWLEN - 1); smp = (salitem_T *)slang->sl_sal.ga_data; @@ -14448,13 +14492,15 @@ int p0 = -333; int c0; int did_white = FALSE; + int wordlen; + /* * Convert the multi-byte string to a wide-character string. * Remove accents, if wanted. We actually remove all non-word characters. * But keep white space. */ - n = 0; + wordlen = 0; for (s = inword; *s != NUL; ) { t = s; @@ -14475,12 +14521,12 @@ continue; } } - word[n++] = c; + word[wordlen++] = c; } - word[n] = NUL; + word[wordlen] = NUL; /* - * This comes from Aspell phonet.cpp. + * This algorithm comes from Aspell phonet.cpp. * Converted from C++ to C. Added support for multi-byte chars. * Changed to keep spaces. */ @@ -14665,7 +14711,7 @@ } if (k > k0) mch_memmove(word + i + k0, word + i + k, - sizeof(int) * (STRLEN(word + i + k) + 1)); + sizeof(int) * (wordlen - (i + k) + 1)); /* new "actual letter" */ c = word[i]; @@ -14693,7 +14739,7 @@ if (c != NUL) wres[reslen++] = c; mch_memmove(word, word + i + 1, - sizeof(int) * (STRLEN(word + i + 1) + 1)); + sizeof(int) * (wordlen - (i + 1) + 1)); i = 0; z0 = 1; } diff -Naur vim73.orig/src/structs.h vim73/src/structs.h --- vim73.orig/src/structs.h 2010-08-07 14:59:27.000000000 +0000 +++ vim73/src/structs.h 2012-07-20 20:31:18.260978460 +0000 @@ -378,6 +378,35 @@ typedef long blocknr_T; /* + * mf_hashtab_T is a chained hashtable with blocknr_T key and arbitrary + * structures as items. This is an intrusive data structure: we require + * that items begin with mf_hashitem_T which contains the key and linked + * list pointers. List of items in each bucket is doubly-linked. + */ + +typedef struct mf_hashitem_S mf_hashitem_T; + +struct mf_hashitem_S +{ + mf_hashitem_T *mhi_next; + mf_hashitem_T *mhi_prev; + blocknr_T mhi_key; +}; + +#define MHT_INIT_SIZE 64 + +typedef struct mf_hashtab_S +{ + long_u mht_mask; /* mask used for hash value (nr of items + * in array is "mht_mask" + 1) */ + long_u mht_count; /* nr of items inserted into hashtable */ + mf_hashitem_T **mht_buckets; /* points to mht_small_buckets or + *dynamically allocated array */ + mf_hashitem_T *mht_small_buckets[MHT_INIT_SIZE]; /* initial buckets */ + char mht_fixed; /* non-zero value forbids growth */ +} mf_hashtab_T; + +/* * for each (previously) used block in the memfile there is one block header. * * The block may be linked in the used list OR in the free list. @@ -394,11 +423,11 @@ struct block_hdr { + mf_hashitem_T bh_hashitem; /* header for hash table and key */ +#define bh_bnum bh_hashitem.mhi_key /* block number, part of bh_hashitem */ + bhdr_T *bh_next; /* next block_hdr in free or used list */ bhdr_T *bh_prev; /* previous block_hdr in used list */ - bhdr_T *bh_hash_next; /* next block_hdr in hash list */ - bhdr_T *bh_hash_prev; /* previous block_hdr in hash list */ - blocknr_T bh_bnum; /* block number */ char_u *bh_data; /* pointer to memory (for used block) */ int bh_page_count; /* number of pages in this block */ @@ -417,9 +446,9 @@ struct nr_trans { - NR_TRANS *nt_next; /* next nr_trans in hash list */ - NR_TRANS *nt_prev; /* previous nr_trans in hash list */ - blocknr_T nt_old_bnum; /* old, negative, number */ + mf_hashitem_T nt_hashitem; /* header for hash table and key */ +#define nt_old_bnum nt_hashitem.mhi_key /* old, negative, number */ + blocknr_T nt_new_bnum; /* new, positive, number */ }; @@ -499,12 +528,6 @@ typedef struct file_buffer buf_T; /* forward declaration */ -/* - * Simplistic hashing scheme to quickly locate the blocks in the used list. - * 64 blocks are found directly (64 * 4K = 256K, most files are smaller). - */ -#define MEMHASHSIZE 64 -#define MEMHASH(nr) ((nr) & (MEMHASHSIZE - 1)) #define MF_SEED_LEN 8 struct memfile @@ -517,8 +540,8 @@ bhdr_T *mf_used_last; /* lru block_hdr in used list */ unsigned mf_used_count; /* number of pages in used list */ unsigned mf_used_count_max; /* maximum number of pages in memory */ - bhdr_T *mf_hash[MEMHASHSIZE]; /* array of hash lists */ - NR_TRANS *mf_trans[MEMHASHSIZE]; /* array of trans lists */ + mf_hashtab_T mf_hash; /* hash lists */ + mf_hashtab_T mf_trans; /* trans lists */ blocknr_T mf_blocknr_max; /* highest positive block number + 1*/ blocknr_T mf_blocknr_min; /* lowest negative block number - 1 */ blocknr_T mf_neg_count; /* number of negative blocks numbers */ @@ -979,9 +1002,10 @@ struct mapblock { mapblock_T *m_next; /* next mapblock in list */ - char_u *m_keys; /* mapped from */ + char_u *m_keys; /* mapped from, lhs */ int m_keylen; /* strlen(m_keys) */ - char_u *m_str; /* mapped to */ + char_u *m_str; /* mapped to, rhs */ + char_u *m_orig_str; /* rhs as entered by the user */ int m_mode; /* valid mode */ int m_noremap; /* if non-zero no re-mapping for m_str */ char m_silent; /* used, don't echo commands */ @@ -1082,6 +1106,11 @@ #define VAR_DICT 5 /* "v_dict" is used */ #define VAR_FLOAT 6 /* "v_float" is used */ +/* Values for "dv_scope". */ +#define VAR_SCOPE 1 /* a:, v:, s:, etc. scope dictionaries */ +#define VAR_DEF_SCOPE 2 /* l:, g: scope dictionaries: here funcrefs are not + allowed to mask existing functions */ + /* Values for "v_lock". */ #define VAR_LOCKED 1 /* locked with lock(), can use unlock() */ #define VAR_FIXED 2 /* locked forever */ @@ -1157,6 +1186,7 @@ int dv_copyID; /* ID used by deepcopy() */ dict_T *dv_copydict; /* copied dict used by deepcopy() */ char dv_lock; /* zero, VAR_LOCKED, VAR_FIXED */ + char dv_scope; /* zero, VAR_SCOPE, VAR_DEF_SCOPE */ dict_T *dv_used_next; /* next dict in used dicts list */ dict_T *dv_used_prev; /* previous dict in used dicts list */ }; @@ -1177,6 +1207,10 @@ typedef struct qf_info_S qf_info_T; #endif +/* + * These are items normally related to a buffer. But when using ":ownsyntax" + * a window may have its own instance. + */ typedef struct { #ifdef FEAT_SYN_HL hashtab_T b_keywtab; /* syntax keywords hash table */ @@ -1266,6 +1300,10 @@ int b_nwindows; /* nr of windows open on this buffer */ int b_flags; /* various BF_ flags */ +#ifdef FEAT_AUTOCMD + int b_closing; /* buffer is being closed, don't let + autocommands close it too. */ +#endif /* * b_ffname has the full path of the file (NULL for no name). @@ -1506,9 +1544,6 @@ int b_p_ml_nobin; /* b_p_ml saved for binary mode */ int b_p_ma; /* 'modifiable' */ char_u *b_p_nf; /* 'nrformats' */ -#ifdef FEAT_OSFILETYPE - char_u *b_p_oft; /* 'osfiletype' */ -#endif int b_p_pi; /* 'preserveindent' */ #ifdef FEAT_TEXTOBJ char_u *b_p_qe; /* 'quoteescape' */ @@ -1563,6 +1598,9 @@ /* end of buffer options */ + linenr_T b_no_eol_lnum; /* non-zero lnum when last line of next binary + * write should not have an end-of-line */ + int b_start_eol; /* last line had eol when it was read */ int b_start_ffc; /* first char of 'ff' when edit started */ #ifdef FEAT_MBYTE @@ -1822,13 +1860,17 @@ often, keep it the first item!) */ #if defined(FEAT_SYN_HL) || defined(FEAT_SPELL) - synblock_T *w_s; + synblock_T *w_s; /* for :ownsyntax */ #endif #ifdef FEAT_WINDOWS win_T *w_prev; /* link to previous window */ win_T *w_next; /* link to next window */ #endif +#ifdef FEAT_AUTOCMD + int w_closing; /* window is being closed, don't let + autocommands close it too. */ +#endif frame_T *w_frame; /* frame containing this window */ @@ -2339,11 +2381,6 @@ MenuHandle menu_handle; MenuHandle submenu_handle; #endif -#ifdef RISCOS - int *id; /* Not used, but gui.c needs it */ - int greyed_out; /* Flag */ - int hidden; -#endif #ifdef FEAT_GUI_PHOTON PtWidget_t *id; PtWidget_t *submenu_id; diff -Naur vim73.orig/src/syntax.c vim73/src/syntax.c --- vim73.orig/src/syntax.c 2010-08-08 13:17:03.000000000 +0000 +++ vim73/src/syntax.c 2012-07-20 20:31:18.317645167 +0000 @@ -68,6 +68,8 @@ #define HL_TABLE() ((struct hl_group *)((highlight_ga.ga_data))) +#define MAX_HL_ID 20000 /* maximum value for a highlight ID. */ + #ifdef FEAT_CMDL_COMPL /* Flags to indicate an additional string for highlight name completion. */ static int include_none = 0; /* when 1 include "None" */ @@ -219,16 +221,19 @@ /* * Syntax group IDs have different types: - * 0 - 9999 normal syntax groups - * 10000 - 14999 ALLBUT indicator (current_syn_inc_tag added) - * 15000 - 19999 TOP indicator (current_syn_inc_tag added) - * 20000 - 24999 CONTAINED indicator (current_syn_inc_tag added) - * >= 25000 cluster IDs (subtract SYNID_CLUSTER for the cluster ID) - */ -#define SYNID_ALLBUT 10000 /* syntax group ID for contains=ALLBUT */ -#define SYNID_TOP 15000 /* syntax group ID for contains=TOP */ -#define SYNID_CONTAINED 20000 /* syntax group ID for contains=CONTAINED */ -#define SYNID_CLUSTER 25000 /* first syntax group ID for clusters */ + * 0 - 19999 normal syntax groups + * 20000 - 20999 ALLBUT indicator (current_syn_inc_tag added) + * 21000 - 21999 TOP indicator (current_syn_inc_tag added) + * 22000 - 22999 CONTAINED indicator (current_syn_inc_tag added) + * 23000 - 32767 cluster IDs (subtract SYNID_CLUSTER for the cluster ID) + */ +#define SYNID_ALLBUT MAX_HL_ID /* syntax group ID for contains=ALLBUT */ +#define SYNID_TOP 21000 /* syntax group ID for contains=TOP */ +#define SYNID_CONTAINED 22000 /* syntax group ID for contains=CONTAINED */ +#define SYNID_CLUSTER 23000 /* first syntax group ID for clusters */ + +#define MAX_SYN_INC_TAG 999 /* maximum before the above overflow */ +#define MAX_CLUSTER_ID (32767 - SYNID_CLUSTER) /* * Annoying Hack(TM): ":syn include" needs this pointer to pass to @@ -554,7 +559,13 @@ if (INVALID_STATE(¤t_state)) { syn_sync(wp, lnum, last_valid); - first_stored = current_lnum + syn_block->b_syn_sync_minlines; + if (current_lnum == 1) + /* First line is always valid, no matter "minlines". */ + first_stored = 1; + else + /* Need to parse "minlines" lines before state can be considered + * valid to store. */ + first_stored = current_lnum + syn_block->b_syn_sync_minlines; } else first_stored = current_lnum; @@ -985,7 +996,10 @@ * previous line and regions that have "keepend". */ if (current_state.ga_len > 0) + { syn_update_ends(TRUE); + check_state_ends(); + } next_match_idx = -1; ++current_line_id; @@ -1059,7 +1073,6 @@ } } check_keepend(); - check_state_ends(); } /**************************************** @@ -2528,7 +2541,7 @@ check_state_ends() { stateitem_T *cur_si; - int had_extend = FALSE; + int had_extend; cur_si = &CUR_STATE(current_state.ga_len - 1); for (;;) @@ -2561,6 +2574,9 @@ #endif update_si_attr(current_state.ga_len - 1); + /* nextgroup= should not match in the end pattern */ + current_next_list = NULL; + /* what matches next may be different now, clear it */ next_match_idx = 0; next_match_col = MAXCOL; @@ -2578,8 +2594,7 @@ /* When the ended item has "extend", another item with * "keepend" now needs to check for its end. */ - if (cur_si->si_flags & HL_EXTEND) - had_extend = TRUE; + had_extend = (cur_si->si_flags & HL_EXTEND); pop_current_state(); @@ -3442,6 +3457,9 @@ /* free the stored states */ syn_stack_free_all(block); invalidate_current_state(); + + /* Reset the counter for ":syn include" */ + running_syn_inc_tag = 0; } /* @@ -3988,17 +4006,17 @@ } static void -syn_list_flags(nl, flags, attr) - struct name_list *nl; +syn_list_flags(nlist, flags, attr) + struct name_list *nlist; int flags; int attr; { int i; - for (i = 0; nl[i].flag != 0; ++i) - if (flags & nl[i].flag) + for (i = 0; nlist[i].flag != 0; ++i) + if (flags & nlist[i].flag) { - msg_puts_attr((char_u *)nl[i].name, attr); + msg_puts_attr((char_u *)nlist[i].name, attr); msg_putchar(' '); } } @@ -4537,6 +4555,13 @@ ; #endif } +#ifdef FEAT_CONCEAL + if (!vim_isprintc_strict(*conceal_char)) + { + EMSG(_("E844: invalid cchar value")); + return NULL; + } +#endif arg = skipwhite(arg + 7); } else @@ -4654,6 +4679,8 @@ return; } sgl_id = syn_check_cluster(arg, (int)(group_name_end - arg)); + if (sgl_id == 0) + return; /* separate_nextcmd() and expand_filename() depend on this */ eap->arg = rest; } @@ -4682,6 +4709,11 @@ * Save and restore the existing top-level grouplist id and ":syn * include" tag around the actual inclusion. */ + if (running_syn_inc_tag >= MAX_SYN_INC_TAG) + { + EMSG((char_u *)_("E847: Too many syntax includes")); + return; + } prev_syn_inc_tag = current_syn_inc_tag; current_syn_inc_tag = ++running_syn_inc_tag; prev_toplvl_grp = curwin->w_s->b_syn_topgrp; @@ -4705,7 +4737,7 @@ char_u *group_name_end; int syn_id; char_u *rest; - char_u *keyword_copy; + char_u *keyword_copy = NULL; char_u *p; char_u *kw; syn_opt_arg_T syn_opt_arg; @@ -4717,9 +4749,9 @@ if (rest != NULL) { syn_id = syn_check_group(arg, (int)(group_name_end - arg)); - - /* allocate a buffer, for removing the backslashes in the keyword */ - keyword_copy = alloc((unsigned)STRLEN(rest) + 1); + if (syn_id != 0) + /* allocate a buffer, for removing backslashes in the keyword */ + keyword_copy = alloc((unsigned)STRLEN(rest) + 1); if (keyword_copy != NULL) { syn_opt_arg.flags = 0; @@ -5126,7 +5158,8 @@ (item == ITEM_SKIP) ? SPTYPE_SKIP : SPTYPE_END; SYN_ITEMS(curwin->w_s)[idx].sp_flags |= syn_opt_arg.flags; SYN_ITEMS(curwin->w_s)[idx].sp_syn.id = syn_id; - SYN_ITEMS(curwin->w_s)[idx].sp_syn.inc_tag = current_syn_inc_tag; + SYN_ITEMS(curwin->w_s)[idx].sp_syn.inc_tag = + current_syn_inc_tag; SYN_ITEMS(curwin->w_s)[idx].sp_syn_match_id = ppp->pp_matchgroup_id; #ifdef FEAT_CONCEAL @@ -5419,6 +5452,14 @@ curwin->w_s->b_syn_clusters.ga_growsize = 10; } + len = curwin->w_s->b_syn_clusters.ga_len; + if (len >= MAX_CLUSTER_ID) + { + EMSG((char_u *)_("E848: Too many syntax clusters")); + vim_free(name); + return 0; + } + /* * Make room for at least one other cluster entry. */ @@ -5427,7 +5468,6 @@ vim_free(name); return 0; } - len = curwin->w_s->b_syn_clusters.ga_len; vim_memset(&(SYN_CLSTR(curwin->w_s)[len]), 0, sizeof(syn_cluster_T)); SYN_CLSTR(curwin->w_s)[len].scl_name = name; @@ -5469,8 +5509,10 @@ if (rest != NULL) { - scl_id = syn_check_cluster(arg, (int)(group_name_end - arg)) - - SYNID_CLUSTER; + scl_id = syn_check_cluster(arg, (int)(group_name_end - arg)); + if (scl_id == 0) + return; + scl_id -= SYNID_CLUSTER; for (;;) { @@ -5509,7 +5551,7 @@ if (got_clstr) { redraw_curbuf_later(SOME_VALID); - syn_stack_free_all(curwin->w_s); /* Need to recompute all syntax. */ + syn_stack_free_all(curwin->w_s); /* Need to recompute all. */ } } @@ -6431,7 +6473,6 @@ #endif /* FEAT_SYN_HL */ - /************************************** * Highlighting stuff * **************************************/ @@ -6475,8 +6516,6 @@ "DiffText term=reverse cterm=bold ctermbg=Red gui=bold guibg=Red"), #endif #ifdef FEAT_INS_EXPAND - CENT("PmenuThumb cterm=reverse", - "PmenuThumb cterm=reverse gui=reverse"), CENT("PmenuSbar ctermbg=Grey", "PmenuSbar ctermbg=Grey guibg=Grey"), #endif @@ -6499,6 +6538,8 @@ "Directory term=bold ctermfg=DarkBlue guifg=Blue"), CENT("LineNr term=underline ctermfg=Brown", "LineNr term=underline ctermfg=Brown guifg=Brown"), + CENT("CursorLineNr term=bold ctermfg=Brown", + "CursorLineNr term=bold ctermfg=Brown gui=bold guifg=Brown"), CENT("MoreMsg term=bold ctermfg=DarkGreen", "MoreMsg term=bold ctermfg=DarkGreen gui=bold guifg=SeaGreen"), CENT("Question term=standout ctermfg=DarkGreen", @@ -6516,10 +6557,12 @@ "SpellLocal term=underline ctermbg=Cyan guisp=DarkCyan gui=undercurl"), #endif #ifdef FEAT_INS_EXPAND - CENT("Pmenu ctermbg=LightMagenta", - "Pmenu ctermbg=LightMagenta guibg=LightMagenta"), - CENT("PmenuSel ctermbg=LightGrey", - "PmenuSel ctermbg=LightGrey guibg=Grey"), + CENT("PmenuThumb ctermbg=Black", + "PmenuThumb ctermbg=Black guibg=Black"), + CENT("Pmenu ctermbg=LightMagenta ctermfg=Black", + "Pmenu ctermbg=LightMagenta ctermfg=Black guibg=LightMagenta"), + CENT("PmenuSel ctermbg=LightGrey ctermfg=Black", + "PmenuSel ctermbg=LightGrey ctermfg=Black guibg=Grey"), #endif CENT("SpecialKey term=bold ctermfg=DarkBlue", "SpecialKey term=bold ctermfg=DarkBlue guifg=Blue"), @@ -6585,6 +6628,8 @@ "Directory term=bold ctermfg=LightCyan guifg=Cyan"), CENT("LineNr term=underline ctermfg=Yellow", "LineNr term=underline ctermfg=Yellow guifg=Yellow"), + CENT("CursorLineNr term=bold ctermfg=Yellow", + "CursorLineNr term=bold ctermfg=Yellow gui=bold guifg=Yellow"), CENT("MoreMsg term=bold ctermfg=LightGreen", "MoreMsg term=bold ctermfg=LightGreen gui=bold guifg=SeaGreen"), CENT("Question term=standout ctermfg=LightGreen", @@ -6604,10 +6649,12 @@ "SpellLocal term=underline ctermbg=Cyan guisp=Cyan gui=undercurl"), #endif #ifdef FEAT_INS_EXPAND - CENT("Pmenu ctermbg=Magenta", - "Pmenu ctermbg=Magenta guibg=Magenta"), - CENT("PmenuSel ctermbg=DarkGrey", - "PmenuSel ctermbg=DarkGrey guibg=DarkGrey"), + CENT("PmenuThumb ctermbg=White", + "PmenuThumb ctermbg=White guibg=White"), + CENT("Pmenu ctermbg=Magenta ctermfg=Black", + "Pmenu ctermbg=Magenta ctermfg=Black guibg=Magenta"), + CENT("PmenuSel ctermbg=Black ctermfg=DarkGrey", + "PmenuSel ctermbg=Black ctermfg=DarkGrey guibg=DarkGrey"), #endif CENT("Title term=bold ctermfg=LightMagenta", "Title term=bold ctermfg=LightMagenta gui=bold guifg=Magenta"), @@ -7600,10 +7647,10 @@ /* * Copy characters from arg[] to buf[], translating <> codes. */ - for (p = arg, off = 0; off < 100 && *p; ) + for (p = arg, off = 0; off < 100 - 6 && *p; ) { len = trans_special(&p, buf + off, FALSE); - if (len) /* recognized special char */ + if (len > 0) /* recognized special char */ off += len; else /* copy as normal char */ buf[off++] = *p++; @@ -8545,8 +8592,8 @@ if (iarg & hl_attr_table[i]) { if (buf[0] != NUL) - STRCAT(buf, ","); - STRCAT(buf, hl_name_table[i]); + vim_strcat(buf, (char_u *)",", 100); + vim_strcat(buf, (char_u *)hl_name_table[i], 100); iarg &= ~hl_attr_table[i]; /* don't want "inverse" */ } } @@ -8965,6 +9012,13 @@ highlight_ga.ga_growsize = 10; } + if (highlight_ga.ga_len >= MAX_HL_ID) + { + EMSG(_("E849: Too many highlight and syntax groups")); + vim_free(name); + return 0; + } + /* * Make room for at least one other syntax_highlight entry. */ @@ -9422,7 +9476,7 @@ int cnt; int attr; { - msg_puts_attr((char_u *)("N \bI \b! \b" + cnt / 11), attr); + msg_puts_attr((char_u *)&("N \bI \b! \b"[cnt / 11]), attr); msg_clr_eos(); out_flush(); ui_delay(cnt == 99 ? 40L : (long)cnt * 50L, FALSE); diff -Naur vim73.orig/src/tag.c vim73/src/tag.c --- vim73.orig/src/tag.c 2010-08-10 07:25:22.000000000 +0000 +++ vim73/src/tag.c 2012-07-20 20:31:14.130975501 +0000 @@ -11,10 +11,6 @@ * Code to handle tags and the tag stack */ -#if defined(MSDOS) || defined(WIN16) || defined(WIN32) || defined(_WIN64) -# include "vimio.h" /* for lseek(), must be before vim.h */ -#endif - #include "vim.h" /* @@ -208,7 +204,7 @@ else { #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX) - if (g_do_tagpreview) + if (g_do_tagpreview != 0) use_tagstack = FALSE; else #endif @@ -226,7 +222,7 @@ )) { #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX) - if (g_do_tagpreview) + if (g_do_tagpreview != 0) { if (ptag_entry.tagname != NULL && STRCMP(ptag_entry.tagname, tag) == 0) @@ -282,7 +278,7 @@ { if ( #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX) - g_do_tagpreview ? ptag_entry.tagname == NULL : + g_do_tagpreview != 0 ? ptag_entry.tagname == NULL : #endif tagstacklen == 0) { @@ -365,7 +361,7 @@ ) { #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX) - if (g_do_tagpreview) + if (g_do_tagpreview != 0) { cur_match = ptag_entry.cur_match; cur_fnum = ptag_entry.cur_fnum; @@ -403,7 +399,7 @@ prevtagstackidx = tagstackidx; #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX) - if (g_do_tagpreview) + if (g_do_tagpreview != 0) { cur_match = ptag_entry.cur_match; cur_fnum = ptag_entry.cur_fnum; @@ -441,7 +437,7 @@ } #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX) - if (g_do_tagpreview) + if (g_do_tagpreview != 0) { if (type != DT_SELECT && type != DT_JUMP) { @@ -496,7 +492,7 @@ if (use_tagstack) name = tagstack[tagstackidx].tagname; #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX) - else if (g_do_tagpreview) + else if (g_do_tagpreview != 0) name = ptag_entry.tagname; #endif else @@ -624,7 +620,7 @@ parse_match(matches[i], &tagp); if (!new_tag && ( #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX) - (g_do_tagpreview + (g_do_tagpreview != 0 && i == ptag_entry.cur_match) || #endif (use_tagstack @@ -779,17 +775,25 @@ { list_T *list; char_u tag_name[128 + 1]; - char_u fname[MAXPATHL + 1]; - char_u cmd[CMDBUFFSIZE + 1]; + char_u *fname; + char_u *cmd; /* * Add the matching tags to the location list for the current * window. */ + fname = alloc(MAXPATHL + 1); + cmd = alloc(CMDBUFFSIZE + 1); list = list_alloc(); - if (list == NULL) + if (list == NULL || fname == NULL || cmd == NULL) + { + vim_free(cmd); + vim_free(fname); + if (list != NULL) + list_free(list, TRUE); goto end_do_tag; + } for (i = 0; i < num_matches; ++i) { @@ -810,7 +814,7 @@ p = tag_full_fname(&tagp); if (p == NULL) continue; - STRCPY(fname, p); + vim_strncpy(fname, p, MAXPATHL); vim_free(p); /* @@ -915,6 +919,8 @@ set_errorlist(curwin, list, ' ', IObuff); list_free(list, TRUE); + vim_free(fname); + vim_free(cmd); cur_match = 0; /* Jump to the first tag */ } @@ -966,7 +972,7 @@ ++tagstackidx; } #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX) - else if (g_do_tagpreview) + else if (g_do_tagpreview != 0) { ptag_entry.cur_match = cur_match; ptag_entry.cur_fnum = cur_fnum; @@ -1271,6 +1277,7 @@ { FILE *fp; char_u *lbuf; /* line buffer */ + int lbuf_size = LSIZE; /* length of lbuf */ char_u *tag_fname; /* name of tag file */ tagname_T tn; /* info for get_tagfname() */ int first_file; /* trying first tag file */ @@ -1285,6 +1292,7 @@ char_u *s; int i; #ifdef FEAT_TAG_BINS + int tag_file_sorted = NUL; /* !_TAG_FILE_SORTED value */ struct tag_search_info /* Binary search file offsets */ { off_t low_offset; /* offset for first char of first line that @@ -1345,7 +1353,6 @@ int match_count = 0; /* number of matches found */ char_u **matches; int mtt; - int len; int help_save; #ifdef FEAT_MULTI_LANG int help_pri = 0; @@ -1354,13 +1361,8 @@ char_u *saved_pat = NULL; /* copy of pat[] */ #endif - /* Use two sets of variables for the pattern: "orgpat" holds the values - * for the original pattern and "convpat" converted from 'encoding' to - * encoding of the tags file. "pats" point to either one of these. */ - pat_T *pats; pat_T orgpat; /* holds unconverted pattern info */ #ifdef FEAT_MBYTE - pat_T convpat; /* holds converted pattern info */ vimconv_T vimconv; #endif @@ -1384,7 +1386,6 @@ help_save = curbuf->b_help; orgpat.pat = pat; - pats = &orgpat; #ifdef FEAT_MBYTE vimconv.vc_type = CONV_NONE; #endif @@ -1392,7 +1393,7 @@ /* * Allocate memory for the buffers that are used */ - lbuf = alloc(LSIZE); + lbuf = alloc(lbuf_size); tag_fname = alloc(MAXPATHL + 1); #ifdef FEAT_EMACS_TAGS ebuf = alloc(LSIZE); @@ -1418,30 +1419,30 @@ if (help_only) /* want tags from help file */ curbuf->b_help = TRUE; /* will be restored later */ - pats->len = (int)STRLEN(pat); + orgpat.len = (int)STRLEN(pat); #ifdef FEAT_MULTI_LANG if (curbuf->b_help) { /* When "@ab" is specified use only the "ab" language, otherwise * search all languages. */ - if (pats->len > 3 && pat[pats->len - 3] == '@' - && ASCII_ISALPHA(pat[pats->len - 2]) - && ASCII_ISALPHA(pat[pats->len - 1])) + if (orgpat.len > 3 && pat[orgpat.len - 3] == '@' + && ASCII_ISALPHA(pat[orgpat.len - 2]) + && ASCII_ISALPHA(pat[orgpat.len - 1])) { - saved_pat = vim_strnsave(pat, pats->len - 3); + saved_pat = vim_strnsave(pat, orgpat.len - 3); if (saved_pat != NULL) { - help_lang_find = &pat[pats->len - 2]; - pats->pat = saved_pat; - pats->len -= 3; + help_lang_find = &pat[orgpat.len - 2]; + orgpat.pat = saved_pat; + orgpat.len -= 3; } } } #endif - if (p_tl != 0 && pats->len > p_tl) /* adjust for 'taglength' */ - pats->len = p_tl; + if (p_tl != 0 && orgpat.len > p_tl) /* adjust for 'taglength' */ + orgpat.len = p_tl; - prepare_pats(pats, has_re); + prepare_pats(&orgpat, has_re); #ifdef FEAT_TAG_BINS /* This is only to avoid a compiler warning for using search_info @@ -1460,13 +1461,13 @@ * Only ignore case when TAG_NOIC not used or 'ignorecase' set. */ #ifdef FEAT_TAG_BINS - pats->regmatch.rm_ic = ((p_ic || !noic) - && (findall || pats->headlen == 0 || !p_tbs)); + orgpat.regmatch.rm_ic = ((p_ic || !noic) + && (findall || orgpat.headlen == 0 || !p_tbs)); for (round = 1; round <= 2; ++round) { - linear = (pats->headlen == 0 || !p_tbs || round == 2); + linear = (orgpat.headlen == 0 || !p_tbs || round == 2); #else - pats->regmatch.rm_ic = (p_ic || !noic); + orgpat.regmatch.rm_ic = (p_ic || !noic); #endif /* @@ -1695,6 +1696,36 @@ } line_read_in: +#ifdef FEAT_MBYTE + if (vimconv.vc_type != CONV_NONE) + { + char_u *conv_line; + int len; + + /* Convert every line. Converting the pattern from 'enc' to + * the tags file encoding doesn't work, because characters are + * not recognized. */ + conv_line = string_convert(&vimconv, lbuf, NULL); + if (conv_line != NULL) + { + /* Copy or swap lbuf and conv_line. */ + len = (int)STRLEN(conv_line) + 1; + if (len > lbuf_size) + { + vim_free(lbuf); + lbuf = conv_line; + lbuf_size = len; + } + else + { + STRCPY(lbuf, conv_line); + vim_free(conv_line); + } + } + } +#endif + + #ifdef FEAT_EMACS_TAGS /* * Emacs tags line with CTRL-L: New file name on next line. @@ -1764,6 +1795,33 @@ */ if (state == TS_START) { + if (STRNCMP(lbuf, "!_TAG_", 6) <= 0) + { + /* + * Read header line. + */ +#ifdef FEAT_TAG_BINS + if (STRNCMP(lbuf, "!_TAG_FILE_SORTED\t", 18) == 0) + tag_file_sorted = lbuf[18]; +#endif +#ifdef FEAT_MBYTE + if (STRNCMP(lbuf, "!_TAG_FILE_ENCODING\t", 20) == 0) + { + /* Prepare to convert every line from the specified + * encoding to 'encoding'. */ + for (p = lbuf + 20; *p > ' ' && *p < 127; ++p) + ; + *p = NUL; + convert_setup(&vimconv, lbuf + 20, p_enc); + } +#endif + + /* Read the next line. Unrecognized flags are ignored. */ + continue; + } + + /* Headers ends. */ + #ifdef FEAT_TAG_BINS /* * When there is no tag head, or ignoring case, need to do a @@ -1780,26 +1838,22 @@ if (linear) # endif state = TS_LINEAR; - else if (STRNCMP(lbuf, "!_TAG_", 6) > 0) + else if (tag_file_sorted == NUL) state = TS_BINARY; - else if (STRNCMP(lbuf, "!_TAG_FILE_SORTED\t", 18) == 0) - { - /* Check sorted flag */ - if (lbuf[18] == '1') - state = TS_BINARY; - else if (lbuf[18] == '2') - { + else if (tag_file_sorted == '1') state = TS_BINARY; - sortic = TRUE; - pats->regmatch.rm_ic = (p_ic || !noic); - } - else - state = TS_LINEAR; + else if (tag_file_sorted == '2') + { + state = TS_BINARY; + sortic = TRUE; + orgpat.regmatch.rm_ic = (p_ic || !noic); } + else + state = TS_LINEAR; - if (state == TS_BINARY && pats->regmatch.rm_ic && !sortic) + if (state == TS_BINARY && orgpat.regmatch.rm_ic && !sortic) { - /* binary search won't work for ignoring case, use linear + /* Binary search won't work for ignoring case, use linear * search. */ linear = TRUE; state = TS_LINEAR; @@ -1837,40 +1891,12 @@ #endif } -#ifdef FEAT_MBYTE - if (lbuf[0] == '!' && pats == &orgpat - && STRNCMP(lbuf, "!_TAG_FILE_ENCODING\t", 20) == 0) - { - /* Convert the search pattern from 'encoding' to the - * specified encoding. */ - for (p = lbuf + 20; *p > ' ' && *p < 127; ++p) - ; - *p = NUL; - convert_setup(&vimconv, p_enc, lbuf + 20); - if (vimconv.vc_type != CONV_NONE) - { - convpat.pat = string_convert(&vimconv, pats->pat, NULL); - if (convpat.pat != NULL) - { - pats = &convpat; - pats->len = (int)STRLEN(pats->pat); - prepare_pats(pats, has_re); - pats->regmatch.rm_ic = orgpat.regmatch.rm_ic; - } - } - - /* Prepare for converting a match the other way around. */ - convert_setup(&vimconv, lbuf + 20, p_enc); - continue; - } -#endif - /* * Figure out where the different strings are in this line. * For "normal" tags: Do a quick check if the tag matches. * This speeds up tag searching a lot! */ - if (pats->headlen + if (orgpat.headlen #ifdef FEAT_EMACS_TAGS && !is_etag #endif @@ -1879,12 +1905,39 @@ tagp.tagname = lbuf; #ifdef FEAT_TAG_ANYWHITE tagp.tagname_end = skiptowhite(lbuf); - if (*tagp.tagname_end == NUL) /* corrupted tag line */ + if (*tagp.tagname_end == NUL) #else tagp.tagname_end = vim_strchr(lbuf, TAB); - if (tagp.tagname_end == NULL) /* corrupted tag line */ + if (tagp.tagname_end == NULL) #endif { + if (vim_strchr(lbuf, NL) == NULL) + { + /* Truncated line, ignore it. Has been reported for + * Mozilla JS with extremely long names. */ + if (p_verbose >= 5) + { + verbose_enter(); + MSG(_("Ignoring long line in tags file")); + verbose_leave(); + } +#ifdef FEAT_TAG_BINS + if (state != TS_LINEAR) + { + /* Avoid getting stuck. */ + linear = TRUE; + state = TS_LINEAR; +# ifdef HAVE_FSEEKO + fseeko(fp, search_info.low_offset, SEEK_SET); +# else + fseek(fp, (long)search_info.low_offset, SEEK_SET); +# endif + } +#endif + continue; + } + + /* Corrupted tag line. */ line_error = TRUE; break; } @@ -1927,9 +1980,9 @@ cmplen = (int)(tagp.tagname_end - tagp.tagname); if (p_tl != 0 && cmplen > p_tl) /* adjust for 'taglength' */ cmplen = p_tl; - if (has_re && pats->headlen < cmplen) - cmplen = pats->headlen; - else if (state == TS_LINEAR && pats->headlen != cmplen) + if (has_re && orgpat.headlen < cmplen) + cmplen = orgpat.headlen; + else if (state == TS_LINEAR && orgpat.headlen != cmplen) continue; #ifdef FEAT_TAG_BINS @@ -1948,10 +2001,10 @@ * Compare the current tag with the searched tag. */ if (sortic) - tagcmp = tag_strnicmp(tagp.tagname, pats->head, + tagcmp = tag_strnicmp(tagp.tagname, orgpat.head, (size_t)cmplen); else - tagcmp = STRNCMP(tagp.tagname, pats->head, cmplen); + tagcmp = STRNCMP(tagp.tagname, orgpat.head, cmplen); /* * A match with a shorter tag means to search forward. @@ -1959,9 +2012,9 @@ */ if (tagcmp == 0) { - if (cmplen < pats->headlen) + if (cmplen < orgpat.headlen) tagcmp = -1; - else if (cmplen > pats->headlen) + else if (cmplen > orgpat.headlen) tagcmp = 1; } @@ -2005,7 +2058,7 @@ } else if (state == TS_SKIP_BACK) { - if (MB_STRNICMP(tagp.tagname, pats->head, cmplen) != 0) + if (MB_STRNICMP(tagp.tagname, orgpat.head, cmplen) != 0) state = TS_STEP_FORWARD; else /* Have to skip back more. Restore the curr_offset @@ -2015,7 +2068,7 @@ } else if (state == TS_STEP_FORWARD) { - if (MB_STRNICMP(tagp.tagname, pats->head, cmplen) != 0) + if (MB_STRNICMP(tagp.tagname, orgpat.head, cmplen) != 0) { if ((off_t)ftell(fp) > search_info.match_offset) break; /* past last match */ @@ -2026,7 +2079,7 @@ else #endif /* skip this match if it can't match */ - if (MB_STRNICMP(tagp.tagname, pats->head, cmplen) != 0) + if (MB_STRNICMP(tagp.tagname, orgpat.head, cmplen) != 0) continue; /* @@ -2077,41 +2130,41 @@ if (p_tl != 0 && cmplen > p_tl) /* adjust for 'taglength' */ cmplen = p_tl; /* if tag length does not match, don't try comparing */ - if (pats->len != cmplen) + if (orgpat.len != cmplen) match = FALSE; else { - if (pats->regmatch.rm_ic) + if (orgpat.regmatch.rm_ic) { - match = (MB_STRNICMP(tagp.tagname, pats->pat, cmplen) == 0); + match = (MB_STRNICMP(tagp.tagname, orgpat.pat, cmplen) == 0); if (match) - match_no_ic = (STRNCMP(tagp.tagname, pats->pat, + match_no_ic = (STRNCMP(tagp.tagname, orgpat.pat, cmplen) == 0); } else - match = (STRNCMP(tagp.tagname, pats->pat, cmplen) == 0); + match = (STRNCMP(tagp.tagname, orgpat.pat, cmplen) == 0); } /* * Has a regexp: Also find tags matching regexp. */ match_re = FALSE; - if (!match && pats->regmatch.regprog != NULL) + if (!match && orgpat.regmatch.regprog != NULL) { int cc; cc = *tagp.tagname_end; *tagp.tagname_end = NUL; - match = vim_regexec(&pats->regmatch, tagp.tagname, (colnr_T)0); + match = vim_regexec(&orgpat.regmatch, tagp.tagname, (colnr_T)0); if (match) { - matchoff = (int)(pats->regmatch.startp[0] - tagp.tagname); - if (pats->regmatch.rm_ic) + matchoff = (int)(orgpat.regmatch.startp[0] - tagp.tagname); + if (orgpat.regmatch.rm_ic) { - pats->regmatch.rm_ic = FALSE; - match_no_ic = vim_regexec(&pats->regmatch, tagp.tagname, + orgpat.regmatch.rm_ic = FALSE; + match_no_ic = vim_regexec(&orgpat.regmatch, tagp.tagname, (colnr_T)0); - pats->regmatch.rm_ic = TRUE; + orgpat.regmatch.rm_ic = TRUE; } } *tagp.tagname_end = cc; @@ -2168,7 +2221,7 @@ else mtt = MT_GL_OTH; } - if (pats->regmatch.rm_ic && !match_no_ic) + if (orgpat.regmatch.rm_ic && !match_no_ic) mtt += MT_IC_OFF; if (match_re) mtt += MT_RE_OFF; @@ -2181,35 +2234,8 @@ */ if (ga_grow(&ga_match[mtt], 1) == OK) { -#ifdef FEAT_MBYTE - char_u *conv_line = NULL; - char_u *lbuf_line = lbuf; + int len; - if (vimconv.vc_type != CONV_NONE) - { - /* Convert the tag line from the encoding of the tags - * file to 'encoding'. Then parse the line again. */ - conv_line = string_convert(&vimconv, lbuf, NULL); - if (conv_line != NULL) - { - if (parse_tag_line(conv_line, -#ifdef FEAT_EMACS_TAGS - is_etag, -#endif - &tagp) == OK) - lbuf_line = conv_line; - else - /* doesn't work, go back to unconverted line. */ - (void)parse_tag_line(lbuf, -#ifdef FEAT_EMACS_TAGS - is_etag, -#endif - &tagp); - } - } -#else -# define lbuf_line lbuf -#endif if (help_only) { #ifdef FEAT_MULTI_LANG @@ -2301,7 +2327,7 @@ * without Emacs tags: */ len = (int)STRLEN(tag_fname) - + (int)STRLEN(lbuf_line) + 3; + + (int)STRLEN(lbuf) + 3; #ifdef FEAT_EMACS_TAGS if (is_etag) len += (int)STRLEN(ebuf) + 1; @@ -2331,7 +2357,7 @@ else *s++ = NUL; #endif - STRCPY(s, lbuf_line); + STRCPY(s, lbuf); } } @@ -2367,10 +2393,6 @@ else vim_free(mfp); } -#ifdef FEAT_MBYTE - /* Note: this makes the values in "tagp" invalid! */ - vim_free(conv_line); -#endif } else /* Out of memory! Just forget about the rest. */ { @@ -2409,19 +2431,12 @@ } #endif #ifdef FEAT_MBYTE - if (pats == &convpat) - { - /* Go back from converted pattern to original pattern. */ - vim_free(pats->pat); - vim_free(pats->regmatch.regprog); - orgpat.regmatch.rm_ic = pats->regmatch.rm_ic; - pats = &orgpat; - } if (vimconv.vc_type != CONV_NONE) convert_setup(&vimconv, NULL, NULL); #endif #ifdef FEAT_TAG_BINS + tag_file_sorted = NUL; if (sort_error) { EMSG2(_("E432: Tags file not sorted: %s"), tag_fname); @@ -2455,13 +2470,13 @@ #ifdef FEAT_TAG_BINS /* stop searching when already did a linear search, or when TAG_NOIC * used, and 'ignorecase' not set or already did case-ignore search */ - if (stop_searching || linear || (!p_ic && noic) || pats->regmatch.rm_ic) + if (stop_searching || linear || (!p_ic && noic) || orgpat.regmatch.rm_ic) break; # ifdef FEAT_CSCOPE if (use_cscope) break; # endif - pats->regmatch.rm_ic = TRUE; /* try another time while ignoring case */ + orgpat.regmatch.rm_ic = TRUE; /* try another time while ignoring case */ } #endif @@ -2474,7 +2489,7 @@ findtag_end: vim_free(lbuf); - vim_free(pats->regmatch.regprog); + vim_free(orgpat.regmatch.regprog); vim_free(tag_fname); #ifdef FEAT_EMACS_TAGS vim_free(ebuf); @@ -3114,7 +3129,7 @@ #endif #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX) - if (g_do_tagpreview) + if (g_do_tagpreview != 0) { postponed_split = 0; /* don't split again below */ curwin_save = curwin; /* Save current window */ @@ -3143,9 +3158,7 @@ { win_split(postponed_split > 0 ? postponed_split : 0, postponed_split_flags); -# ifdef FEAT_SCROLLBIND - curwin->w_p_scb = FALSE; -# endif + RESET_BINDING(curwin); } #endif @@ -3154,7 +3167,7 @@ /* A :ta from a help file will keep the b_help flag set. For ":ptag" * we need to use the flag from the window where we came from. */ #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX) - if (g_do_tagpreview) + if (g_do_tagpreview != 0) keep_help_flag = curwin_save->w_buffer->b_help; else #endif @@ -3328,7 +3341,8 @@ } #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX) - if (g_do_tagpreview && curwin != curwin_save && win_valid(curwin_save)) + if (g_do_tagpreview != 0 + && curwin != curwin_save && win_valid(curwin_save)) { /* Return cursor to where we were */ validate_cursor(); @@ -3782,8 +3796,9 @@ char_u *start; /* start of the value */ char_u *end; /* after the value; can be NULL */ { - char_u buf[MAXPATHL]; + char_u *buf; int len = 0; + int retval; /* check that the field name doesn't exist yet */ if (dict_find(dict, (char_u *)field_name, -1) != NULL) @@ -3796,6 +3811,9 @@ } return FAIL; } + buf = alloc(MAXPATHL); + if (buf == NULL) + return FAIL; if (start != NULL) { if (end == NULL) @@ -3805,12 +3823,14 @@ --end; } len = (int)(end - start); - if (len > (int)sizeof(buf) - 1) - len = sizeof(buf) - 1; + if (len > MAXPATHL - 1) + len = MAXPATHL - 1; vim_strncpy(buf, start, len); } buf[len] = NUL; - return dict_add_nr_str(dict, field_name, 0L, buf); + retval = dict_add_nr_str(dict, field_name, 0L, buf); + vim_free(buf); + return retval; } /* diff -Naur vim73.orig/src/term.c vim73/src/term.c --- vim73.orig/src/term.c 2010-07-25 13:30:31.000000000 +0000 +++ vim73/src/term.c 2012-07-20 20:31:14.584309160 +0000 @@ -52,7 +52,7 @@ /* * Here are the builtin termcap entries. They are not stored as complete - * Tcarr structures, as such a structure is too big. + * structures with all entries, as such a structure is too big. * * The entries are compact, therefore they normally are included even when * HAVE_TGETENT is defined. When HAVE_TGETENT is defined, the builtin entries @@ -199,71 +199,6 @@ #endif #ifndef NO_BUILTIN_TCAPS -# if defined(RISCOS) || defined(ALL_BUILTIN_TCAPS) -/* - * Default for the Acorn. - */ - {(int)KS_NAME, "riscos"}, - {(int)KS_CL, "\014"}, /* Cls and Home Cursor */ - {(int)KS_CM, "\001%d\001%d\002"}, /* Position cursor */ - - {(int)KS_CCO, "16"}, /* Allow 16 colors */ - - {(int)KS_CAF, "\001%d\021"}, /* Set foreground colour */ - {(int)KS_CAB, "\001%d\022"}, /* Set background colour */ - - - {(int)KS_ME, "\004"}, /* Normal mode */ - {(int)KS_MR, "\005"}, /* Reverse */ - - {(int)KS_VI, "\016"}, /* Cursor invisible */ - {(int)KS_VE, "\017"}, /* Cursor visible */ - {(int)KS_VS, "\020"}, /* Cursor very visible */ - - {(int)KS_CS, "\001%d\001%d\003"}, /* Set scroll region */ - {(int)KS_SR, "\023"}, /* Scroll text down */ - {K_UP, "\217"}, - {K_DOWN, "\216"}, - {K_LEFT, "\214"}, - {K_RIGHT, "\215"}, - {K_S_UP, "\237"}, - {K_S_DOWN, "\236"}, - {K_S_LEFT, "\234"}, - {K_S_RIGHT, "\235"}, - - {K_F1, "\201"}, - {K_F2, "\202"}, - {K_F3, "\203"}, - {K_F4, "\204"}, - {K_F5, "\205"}, - {K_F6, "\206"}, - {K_F7, "\207"}, - {K_F8, "\210"}, - {K_F9, "\211"}, - {K_F10, "\312"}, - {K_F11, "\313"}, - {K_F12, "\314"}, - {K_S_F1, "\221"}, - {K_S_F2, "\222"}, - {K_S_F3, "\223"}, - {K_S_F4, "\224"}, - {K_S_F5, "\225"}, - {K_S_F6, "\226"}, - {K_S_F7, "\227"}, - {K_S_F8, "\230"}, - {K_S_F9, "\231"}, - {K_S_F10, "\332"}, - {K_S_F11, "\333"}, - {K_S_F12, "\334"}, - {K_BS, "\010"}, - {K_INS, "\315"}, - {K_DEL, "\177"}, - {K_HOME, "\036"}, - {K_END, "\213"}, - {K_PAGEUP, "\237"}, - {K_PAGEDOWN, "\236"}, -# endif /* Acorn terminal */ - # if defined(AMIGA) || defined(ALL_BUILTIN_TCAPS) /* @@ -1399,10 +1334,6 @@ /* * DEFAULT_TERM is used, when no terminal is specified with -T option or $TERM. */ -#ifdef RISCOS -# define DEFAULT_TERM (char_u *)"riscos" -#endif - #ifdef AMIGA # define DEFAULT_TERM (char_u *)"amiga" #endif @@ -2065,6 +1996,7 @@ # define HMT_DEC 4 # define HMT_JSBTERM 8 # define HMT_PTERM 16 +# define HMT_URXVT 32 static int has_mouse_termcode = 0; # endif @@ -2100,6 +2032,11 @@ has_mouse_termcode |= HMT_PTERM; else # endif +# ifdef FEAT_MOUSE_URXVT + if (n == KS_URXVT_MOUSE) + has_mouse_termcode |= HMT_URXVT; + else +# endif has_mouse_termcode |= HMT_NORMAL; # endif } @@ -2137,6 +2074,11 @@ has_mouse_termcode &= ~HMT_PTERM; else # endif +# ifdef FEAT_MOUSE_URXVT + if (n == KS_URXVT_MOUSE) + has_mouse_termcode &= ~HMT_URXVT; + else +# endif has_mouse_termcode &= ~HMT_NORMAL; # endif } @@ -3053,10 +2995,13 @@ int old_Rows = Rows; int old_Columns = Columns; - (void)ui_get_shellsize(); - check_shellsize(); - if (old_Rows != Rows || old_Columns != Columns) - shell_resized(); + if (!exiting) + { + (void)ui_get_shellsize(); + check_shellsize(); + if (old_Rows != Rows || old_Columns != Columns) + shell_resized(); + } } /* @@ -3083,12 +3028,20 @@ if (width < 0 || height < 0) /* just checking... */ return; - if (State == HITRETURN || State == SETWSIZE) /* postpone the resizing */ + if (State == HITRETURN || State == SETWSIZE) { + /* postpone the resizing */ State = SETWSIZE; return; } + /* curwin->w_buffer can be NULL when we are closing a window and the + * buffer has already been closed and removing a scrollbar causes a resize + * event. Don't resize then, it will happen after entering another buffer. + */ + if (curwin->w_buffer == NULL) + return; + ++busy; #ifdef AMIGA @@ -3828,23 +3781,27 @@ * Check from typebuf.tb_buf[typebuf.tb_off] to typebuf.tb_buf[typebuf.tb_off * + max_offset]. * Return 0 for no match, -1 for partial match, > 0 for full match. + * Return KEYLEN_REMOVED when a key code was deleted. * With a match, the match is removed, the replacement code is inserted in * typebuf.tb_buf[] and the number of characters in typebuf.tb_buf[] is * returned. - * When "buf" is not NULL, it is used instead of typebuf.tb_buf[]. "buflen" is - * then the length of the string in buf[]. + * When "buf" is not NULL, buf[bufsize] is used instead of typebuf.tb_buf[]. + * "buflen" is then the length of the string in buf[] and is updated for + * inserts and deletes. */ int -check_termcode(max_offset, buf, buflen) +check_termcode(max_offset, buf, bufsize, buflen) int max_offset; char_u *buf; - int buflen; + int bufsize; + int *buflen; { char_u *tp; char_u *p; int slen = 0; /* init for GCC */ int modslen; int len; + int retval = 0; int offset; char_u key_name[2]; int modifiers; @@ -3909,10 +3866,10 @@ } else { - if (offset >= buflen) + if (offset >= *buflen) break; tp = buf + offset; - len = buflen - offset; + len = *buflen - offset; } /* @@ -4064,7 +4021,9 @@ } #ifdef FEAT_TERMRESPONSE - if (key_name[0] == NUL) + if (key_name[0] == NUL + /* URXVT mouse uses [#;#;#M, but we are matching [ */ + || key_name[0] == KS_URXVT_MOUSE) { /* Check for xterm version string: "[>{x};{vers};{y}c". Also * eat other possible responses to t_RV, rxvt returns @@ -4103,7 +4062,11 @@ if (tp[1 + (tp[0] != CSI)] == '>' && j == 2) { /* if xterm version >= 95 use mouse dragging */ - if (extra >= 95) + if (extra >= 95 +# ifdef TTYM_URXVT + && ttym_flags != TTYM_URXVT +# endif + ) set_option_value((char_u *)"ttym", 0L, (char_u *)"xterm2", 0); /* if xterm version >= 141 try to get termcap codes */ @@ -4197,6 +4160,9 @@ # ifdef FEAT_MOUSE_PTERM || key_name[0] == (int)KS_PTERM_MOUSE # endif +# ifdef FEAT_MOUSE_URXVT + || key_name[0] == (int)KS_URXVT_MOUSE +# endif ) { is_click = is_drag = FALSE; @@ -4275,7 +4241,69 @@ else break; } + } +# ifdef FEAT_MOUSE_URXVT + if (key_name[0] == (int)KS_URXVT_MOUSE) + { + for (;;) + { + /* URXVT 1015 mouse reporting mode: + * Almost identical to xterm mouse mode, except the values + * are decimal instead of bytes. + * + * \033[%d;%d;%dM + * ^-- row + * ^----- column + * ^-------- code + */ + p = tp + slen; + + mouse_code = getdigits(&p); + if (*p++ != ';') + return -1; + + mouse_col = getdigits(&p) - 1; + if (*p++ != ';') + return -1; + + mouse_row = getdigits(&p) - 1; + if (*p++ != 'M') + return -1; + + slen += (int)(p - (tp + slen)); + + /* skip this one if next one has same code (like xterm + * case) */ + j = termcodes[idx].len; + if (STRNCMP(tp, tp + slen, (size_t)j) == 0) { + /* check if the command is complete by looking for the + * M */ + int slen2; + int cmd_complete = 0; + for (slen2 = slen; slen2 < len; slen2++) { + if (tp[slen2] == 'M') { + cmd_complete = 1; + break; + } + } + p += j; + if (cmd_complete && getdigits(&p) == mouse_code) { + slen += j; /* skip the \033[ */ + continue; + } + } + break; + } + } +# endif + + if (key_name[0] == (int)KS_MOUSE +#ifdef FEAT_MOUSE_URXVT + || key_name[0] == (int)KS_URXVT_MOUSE +#endif + ) + { # if !defined(MSWIN) && !defined(MSDOS) /* * Handle mouse events. @@ -4940,6 +4968,13 @@ #endif string[new_slen++] = key_name[1]; } + else if (new_slen == 0 && key_name[0] == KS_EXTRA + && key_name[1] == KE_IGNORE) + { + /* Do not put K_IGNORE into the buffer, do return KEYLEN_REMOVED + * to indicate what happened. */ + retval = KEYLEN_REMOVED; + } else { string[new_slen++] = K_SPECIAL; @@ -4969,14 +5004,20 @@ if (extra < 0) /* remove matched characters */ mch_memmove(buf + offset, buf + offset - extra, - (size_t)(buflen + offset + extra)); + (size_t)(*buflen + offset + extra)); else if (extra > 0) - /* insert the extra space we need */ + { + /* Insert the extra space we need. If there is insufficient + * space return -1. */ + if (*buflen + extra + new_slen >= bufsize) + return -1; mch_memmove(buf + offset + extra, buf + offset, - (size_t)(buflen - offset)); + (size_t)(*buflen - offset)); + } mch_memmove(buf + offset, string, (size_t)new_slen); + *buflen = *buflen + extra + new_slen; } - return (len + extra + offset); + return retval == 0 ? (len + extra + offset) : retval; } return 0; /* no match found */ @@ -5219,12 +5260,12 @@ char_u *src; { int i; - int slen; + int slen = (int)STRLEN(src); for (i = 0; i < tc_len; ++i) { - slen = termcodes[i].len; - if (slen > 1 && STRNCMP(termcodes[i].code, src, (size_t)slen) == 0) + if (slen == termcodes[i].len + && STRNCMP(termcodes[i].code, src, (size_t)slen) == 0) return i; } return -1; diff -Naur vim73.orig/src/termlib.c vim73/src/termlib.c --- vim73.orig/src/termlib.c 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/termlib.c 2012-07-20 20:31:10.824306455 +0000 @@ -13,7 +13,7 @@ #include "vim.h" #include "termlib.pro" -#if !defined(AMIGA) && !defined(VMS) && !defined(MACOS) && !defined(RISCOS) +#if !defined(AMIGA) && !defined(VMS) && !defined(MACOS) # include #endif diff -Naur vim73.orig/src/testdir/Make_amiga.mak vim73/src/testdir/Make_amiga.mak --- vim73.orig/src/testdir/Make_amiga.mak 2010-08-04 14:34:34.000000000 +0000 +++ vim73/src/testdir/Make_amiga.mak 2012-07-20 20:31:17.337644466 +0000 @@ -13,6 +13,8 @@ # test25 uses symbolic link # test27 can't edit file with "*" # test52 only for Win32 +# test85 no Lua interface +# test86, 87 no Python interface SCRIPTS = test1.out test3.out test4.out test5.out test6.out \ test7.out test8.out test9.out \ @@ -27,7 +29,9 @@ test56.out test57.out test58.out test59.out test60.out \ test61.out test62.out test63.out test64.out test65.out \ test66.out test67.out test68.out test69.out test70.out \ - test71.out test72.out test73.out + test71.out test72.out test73.out test74.out test75.out \ + test76.out test77.out test78.out test79.out test80.out \ + test81.out test82.out test83.out test84.out .SUFFIXES: .in .out @@ -120,3 +124,14 @@ test71.out: test71.in test72.out: test72.in test73.out: test73.in +test74.out: test74.in +test75.out: test75.in +test76.out: test76.in +test77.out: test77.in +test78.out: test78.in +test79.out: test79.in +test80.out: test80.in +test81.out: test81.in +test82.out: test82.in +test83.out: test83.in +test84.out: test84.in diff -Naur vim73.orig/src/testdir/Make_dos.mak vim73/src/testdir/Make_dos.mak --- vim73.orig/src/testdir/Make_dos.mak 2010-08-13 16:27:19.000000000 +0000 +++ vim73/src/testdir/Make_dos.mak 2012-07-20 20:31:17.337644466 +0000 @@ -27,7 +27,10 @@ test30.out test31.out test32.out test33.out test34.out \ test37.out test38.out test39.out test40.out test41.out \ test42.out test52.out test65.out test66.out test67.out \ - test68.out test69.out test71.out test72.out test73.out + test68.out test69.out test71.out test72.out test73.out \ + test74.out test75.out test76.out test77.out test78.out \ + test79.out test80.out test81.out test82.out test83.out \ + test84.out test85.out test86.out test87.out SCRIPTS32 = test50.out test70.out @@ -49,7 +52,8 @@ fixff: -$(VIMPROG) -u dos.vim --noplugin "+argdo set ff=dos|upd" +q *.in *.ok - -$(VIMPROG) -u dos.vim --noplugin "+argdo set ff=unix|upd" +q dotest.in + -$(VIMPROG) -u dos.vim --noplugin "+argdo set ff=unix|upd" +q \ + dotest.in test60.ok test71.ok test74.ok clean: -del *.out diff -Naur vim73.orig/src/testdir/Make_ming.mak vim73/src/testdir/Make_ming.mak --- vim73.orig/src/testdir/Make_ming.mak 2010-08-04 14:34:47.000000000 +0000 +++ vim73/src/testdir/Make_ming.mak 2012-07-20 20:31:17.337644466 +0000 @@ -47,7 +47,10 @@ test30.out test31.out test32.out test33.out test34.out \ test37.out test38.out test39.out test40.out test41.out \ test42.out test52.out test65.out test66.out test67.out \ - test68.out test69.out test71.out test72.out test72.out + test68.out test69.out test71.out test72.out test73.out \ + test74.out test75.out test76.out test77.out test78.out \ + test79.out test80.out test81.out test82.out test83.out \ + test84.out test85.out test86.out test87.out SCRIPTS32 = test50.out test70.out @@ -72,6 +75,8 @@ fixff: -$(VIMPROG) -u dos.vim --noplugin "+argdo set ff=dos|upd" +q *.in *.ok + -$(VIMPROG) -u dos.vim --noplugin "+argdo set ff=unix|upd" +q \ + dotest.in test60.ok test71.ok test74.ok clean: -$(DEL) *.out diff -Naur vim73.orig/src/testdir/Make_os2.mak vim73/src/testdir/Make_os2.mak --- vim73.orig/src/testdir/Make_os2.mak 2010-08-04 14:34:55.000000000 +0000 +++ vim73/src/testdir/Make_os2.mak 2012-07-20 20:31:17.337644466 +0000 @@ -13,6 +13,8 @@ # test25 uses symbolic link # test27 can't edit file with "*" in file name # test52 only for Win32 +# test85 no Lua interface +# test86, 87 no Python interface SCRIPTS = test1.out test3.out test4.out test5.out test6.out \ test7.out test8.out test9.out \ @@ -27,7 +29,9 @@ test56.out test57.out test58.out test59.out test60.out \ test61.out test62.out test63.out test64.out test65.out \ test66.out test67.out test68.out test69.out test70.out \ - test71.out test72.out test73.out + test71.out test72.out test73.out test74.out test75.out \ + test76.out test77.out test78.out test79.out test80.out \ + test81.out test82.out test83.out test84.out .SUFFIXES: .in .out diff -Naur vim73.orig/src/testdir/Make_vms.mms vim73/src/testdir/Make_vms.mms --- vim73.orig/src/testdir/Make_vms.mms 2010-08-04 14:35:46.000000000 +0000 +++ vim73/src/testdir/Make_vms.mms 2012-07-20 20:31:15.700976626 +0000 @@ -4,7 +4,7 @@ # Authors: Zoltan Arpadffy, # Sandor Kopanyi, # -# Last change: 2010 Aug 04 +# Last change: 2012 Apr 05 # # This has been tested on VMS 6.2 to 8.3 on DEC Alpha, VAX and IA64. # Edit the lines in the Configuration section below to select. @@ -74,7 +74,9 @@ test56.out test57.out test60.out \ test61.out test62.out test63.out test64.out test65.out \ test66.out test67.out test68.out test69.out \ - test71.out test72.out + test71.out test72.out test74.out test75.out test76.out \ + test77.out test78.out test79.out test80.out test81.out \ + test82.out test83.out test84.out # Known problems: # Test 30: a problem around mac format - unknown reason @@ -87,6 +89,7 @@ # with too many dots). # # Test 72: unknown reason +# Test 85: no Lua interface .IFDEF WANT_GUI SCRIPT_GUI = test16.out diff -Naur vim73.orig/src/testdir/Makefile vim73/src/testdir/Makefile --- vim73.orig/src/testdir/Makefile 2010-08-15 12:56:30.000000000 +0000 +++ vim73/src/testdir/Makefile 2012-07-20 20:31:17.337644466 +0000 @@ -10,6 +10,7 @@ # This will make testing about 10 times as slow. # VALGRIND = valgrind --tool=memcheck --leak-check=yes --num-callers=15 --log-file=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 \ @@ -23,7 +24,10 @@ test54.out test55.out test56.out test57.out test58.out \ test59.out test60.out test61.out test62.out test63.out \ test64.out test65.out test66.out test67.out test68.out \ - test69.out test70.out test71.out test72.out test73.out + test69.out test70.out test71.out test72.out test73.out \ + test74.out test75.out test76.out test77.out test78.out \ + test79.out test80.out test81.out test82.out test83.out \ + test84.out test85.out test86.out test87.out SCRIPTS_GUI = test16.out @@ -44,7 +48,7 @@ $(SCRIPTS) $(SCRIPTS_GUI): $(VIMPROG) clean: - -rm -rf *.out *.failed *.rej *.orig test.log tiny.vim small.vim mbyte.vim mzscheme.vim test.ok X* valgrind.pid* viminfo + -rm -rf *.out *.failed *.rej *.orig test.log tiny.vim small.vim mbyte.vim mzscheme.vim test.ok X* valgrind.* viminfo test1.out: test1.in -rm -f $*.failed tiny.vim small.vim mbyte.vim mzscheme.vim test.ok X* viminfo @@ -69,7 +73,7 @@ fi \ else echo $* NO OUTPUT >>test.log; \ fi" - -rm -rf X* test.ok viminfo +# -rm -rf X* test.ok viminfo test49.out: test49.vim diff -Naur vim73.orig/src/testdir/main.aap vim73/src/testdir/main.aap --- vim73.orig/src/testdir/main.aap 2010-07-30 20:03:23.000000000 +0000 +++ vim73/src/testdir/main.aap 2012-07-20 20:31:07.820970952 +0000 @@ -13,7 +13,7 @@ test33.out test34.out test35.out test36.out test37.out test38.out test39.out test40.out test41.out test42.out test43.out test44.out test45.out test46.out test47.out - test48.out test49.out + test48.out test49.out test74.out ScriptsGUI = test16.out diff -Naur vim73.orig/src/testdir/test1.in vim73/src/testdir/test1.in --- vim73.orig/src/testdir/test1.in 2010-08-04 14:06:24.000000000 +0000 +++ vim73/src/testdir/test1.in 2012-07-20 20:31:15.697643290 +0000 @@ -15,6 +15,7 @@ be set like small.vim above. mbyte.vim is sourced by tests that require the +multi_byte feature. Similar logic is applied to the +mzscheme feature, using mzscheme.vim. +Similar logic is applied to the +lua feature, using lua.vim. STARTTEST :" Write a single line to test.out to check if testing works at all. @@ -28,10 +29,17 @@ qa! :w! mbyte.vim :w! mzscheme.vim +:w! lua.vim +:" :" If +multi_byte feature supported, make mbyte.vim empty. :if has("multi_byte") | sp another | w! mbyte.vim | q | endif +:" :" If +mzscheme feature supported, make mzscheme.vim empty. :if has("mzscheme") | sp another | w! mzscheme.vim | q | endif +:" +:" If +lua feature supported, make lua.vim empty. +:if has("lua") | sp another | w! lua.vim | q | endif +:" :" If +eval feature supported quit here, leaving tiny.vim and small.vim empty. :" Otherwise write small.vim to skip the test. :if 1 | q! | endif diff -Naur vim73.orig/src/testdir/test10.in vim73/src/testdir/test10.in --- vim73.orig/src/testdir/test10.in 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/testdir/test10.in 2012-07-20 20:31:16.547643900 +0000 @@ -2,56 +2,113 @@ STARTTEST :so small.vim -:/start of errorfile/,/end of errorfile/w! Xerrorfile +:" Also test a BOM is ignored. +:so mbyte.vim +:set encoding=utf-8 +:7/start of errorfile/,/end of errorfile/w! Xerrorfile1 +:7/start of errorfile/,/end of errorfile/-1w! Xerrorfile2 :/start of testfile/,/end of testfile/w! Xtestfile -:cf Xerrorfile -rA +:set efm+==%f=\\,\ line\ %l%*\\D%v%*[^\ ]\ %m +:set efm^=%AError\ in\ \"%f\"\ at\ line\ %l:,%Z%p^,%C%m +:cf Xerrorfile2 +:clast +:copen +:let a=w:quickfix_title +:wincmd p +lgR=a  +:cf Xerrorfile1 +grA :cn -rB +gRLINE 6, COL 19 :cn -rC +gRNO COLUMN SPECIFIED :cn -rD +gRAGAIN NO COLUMN :cn -rE +gRCOL 1 +:cn +gRCOL 2 +:cn +gRCOL 10 +:cn +gRVCOL 10 +:cn +grI +:cn +gR. SPACE POINTER +:cn +gR. DOT POINTER +:cn +gR. DASH POINTER +:cn +gR. TAB-SPACE POINTER +:clast +:cprev +:cprev +:wincmd w +:let a=w:quickfix_title +:wincmd p +lgR=a  :w! test.out " Write contents of this file :qa! ENDTEST start of errorfile "Xtestfile", line 4.12: 1506-045 (S) Undeclared identifier fd_set. -"Xtestfile", line 7 col 19; this is an error +"Xtestfile", line 6 col 19; this is an error gcc -c -DHAVE_CONFIsing-prototypes -I/usr/X11R6/include version.c -Xtestfile:13: parse error before `asd' +Xtestfile:9: parse error before `asd' make: *** [vim] Error 1 -in file "Xtestfile" linenr 16: there is an error +in file "Xtestfile" linenr 10: there is an error 2 returned -"Xtestfile", linenr 19: yet another problem +"Xtestfile", line 11 col 1; this is an error +"Xtestfile", line 12 col 2; this is another error +"Xtestfile", line 14:10; this is an error in column 10 +=Xtestfile=, line 15:10; this is another error, but in vcol 10 this time +"Xtestfile", linenr 16: yet another problem +Error in "Xtestfile" at line 17: +x should be a dot + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 17 + ^ +Error in "Xtestfile" at line 18: +x should be a dot + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 18 +.............^ +Error in "Xtestfile" at line 19: +x should be a dot + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 19 +--------------^ +Error in "Xtestfile" at line 20: +x should be a dot + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 20 + ^ Does anyone know what is the problem and how to correction it? +"Xtestfile", line 21 col 9: What is the title of the quickfix window? +"Xtestfile", line 22 col 9: What is the title of the quickfix window? end of errorfile start of testfile -line 2 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 4 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 6 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 8 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 10 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 11 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 12 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 13 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 14 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 15 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 16 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 17 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 18 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 19 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 20 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 21 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 22 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 2 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 3 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 4 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 5 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 6 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 7 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 8 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 9 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 10 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 11 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 12 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 13 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 14 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 15 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 16 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 17 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 18 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 19 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 20 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 21 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 22 end of testfile diff -Naur vim73.orig/src/testdir/test10.ok vim73/src/testdir/test10.ok --- vim73.orig/src/testdir/test10.ok 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/testdir/test10.ok 2012-07-20 20:31:16.550977236 +0000 @@ -1,23 +1,23 @@ start of testfile -line 2 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 4 xxxAxxxxxxxxxxxxxxxxxxxxxxxxxx -line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 6 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 7 xxxxxxxxxxBxxxxxxxxxxxxxxxxxxx -line 8 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 10 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 11 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 12 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -Cine 13 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 14 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 15 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -Dine 16 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 17 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 18 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -Eine 19 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 20 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 21 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -line 22 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 2 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 3 + xxxxxxxxxxAxxxxxxxxxxxxxxxxxxx line 4 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 5 + xxxxxxxxxxxxxxxxxLINE 6, COL 19 line 6 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 7 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 8 + NO COLUMN SPECIFIEDxxxxxxxxxxx line 9 + AGAIN NO COLUMNxxxxxxxxxxxxxxx line 10 +COL 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 11 + COL 2xxxxxxxxxxxxxxxxxxxxxxxxx line 12 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 13 + xxxxxxxxCOL 10xxxxxxxxxxxxxxxx line 14 + xVCOL 10xxxxxxxxxxxxxxxxxxxxxx line 15 + Ixxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 16 + xxxx. SPACE POINTERxxxxxxxxxxx line 17 + xxxxx. DOT POINTERxxxxxxxxxxxx line 18 + xxxxxx. DASH POINTERxxxxxxxxxx line 19 + xxxxxxx. TAB-SPACE POINTERxxxx line 20 + xxxxxxxx:cf Xerrorfile1xxxxxxx line 21 + xxxxxxxx:cf Xerrorfile2xxxxxxx line 22 end of testfile diff -Naur vim73.orig/src/testdir/test19.in vim73/src/testdir/test19.in --- vim73.orig/src/testdir/test19.in 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/testdir/test19.in 2012-07-20 20:31:12.597641065 +0000 @@ -1,6 +1,7 @@ Tests for "r" with 'smarttab' and 'expandtab' set/not set. STARTTEST +:so small.vim :set smarttab expandtab ts=8 sw=4 :" make sure that backspace works, no matter what termcap is used :set t_kD=x7f t_kb=x08 @@ -12,7 +13,10 @@ 0wR  :" Test replacing with Tabs 0wR  -:?^start?,$w! test.out +:" Test that copyindent works with expandtab set +:set expandtab smartindent copyindent ts=8 sw=8 sts=8 +o{ +x:?^start?,$w! test.out :qa! ENDTEST diff -Naur vim73.orig/src/testdir/test19.ok vim73/src/testdir/test19.ok --- vim73.orig/src/testdir/test19.ok 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/testdir/test19.ok 2012-07-20 20:31:12.590974393 +0000 @@ -5,3 +5,5 @@ a cde hi test text +{ + x diff -Naur vim73.orig/src/testdir/test29.in vim73/src/testdir/test29.in --- vim73.orig/src/testdir/test29.in 2010-08-01 13:38:24.000000000 +0000 +++ vim73/src/testdir/test29.in 2012-07-20 20:31:16.864310793 +0000 @@ -4,16 +4,17 @@ and with 'cpoptions' flag 'j' set or not STARTTEST +:so small.vim :set nocompatible viminfo+=nviminfo :set nojoinspaces :set cpoptions-=j /firstline/ -j"tdGpJjJjJjJjJjJjJjJjJjJjJjJjJjJj05lmx2j06lmy2k4Jy3l$p`xyl$p`yy2l$p:set cpoptions+=j +j"td/^STARTTEST/-1 +PJjJjJjJjJjJjJjJjJjJjJjJjJjJj05lmx2j06lmy2k4Jy3l$p`xyl$p`yy2l$p:set cpoptions+=j j05lmx2j06lmy2k4Jy3l$p`xyl$p`yy2l$p:set cpoptions-=j joinspaces j"tpJjJjJjJjJjJjJjJjJjJjJjJjJjJj05lmx2j06lmy2k4Jy3l$p`xyl$p`yy2l$p:set cpoptions+=j j05lmx2j06lmy2k4Jy3l$p`xyl$p`yy2l$p:set cpoptions-=j nojoinspaces compatible -j"tpJjJjJjJjJjJjJjJjJjJjJjJjJjJj4Jy3l$pjdG:?firstline?+1,$w! test.out -:qa! +j"tpJjJjJjJjJjJjJjJjJjJjJjJjJjJj4Jy3l$pjd/STARTTEST/-2 ENDTEST firstline @@ -54,3 +55,148 @@ hjkl iop! ert +STARTTEST +/^{/+1 +:set comments=s1:/*,mb:*,ex:*/,:// +:set nojoinspaces fo=j +:set backspace=eol,start +:.,+3join +j4J +:.,+2join +j3J +:.,+2join +j3J +:.,+2join +jj3J +ENDTEST + +{ + +/* + * Make sure the previous comment leader is not removed. + */ + +/* + * Make sure the previous comment leader is not removed. + */ + +// Should the next comment leader be left alone? +// Yes. + +// Should the next comment leader be left alone? +// Yes. + +/* Here the comment leader should be left intact. */ +// And so should this one. + +/* Here the comment leader should be left intact. */ +// And so should this one. + +if (condition) // Remove the next comment leader! + // OK, I will. + action(); + +if (condition) // Remove the next comment leader! + // OK, I will. + action(); +} + +STARTTEST +/^{/+1 +:set comments=sO:*\ -,mO:*\ \ ,exO:*/ +:set comments+=s1:/*,mb:*,ex:*/,:// +:set comments+=s1:>#,mb:#,ex:#<,:< +:set cpoptions-=j joinspaces fo=j +:set backspace=eol,start +:.,+3join +j4J +:.,+8join +j9J +:.,+2join +j3J +:.,+2join +j3J +:.,+2join +jj3J +j:.,+2join +jj3J +j:.,+5join +j6J +oSome code! // Make sure backspacing does not remove this comment leader.0i +ENDTEST + +{ + +/* + * Make sure the previous comment leader is not removed. + */ + +/* + * Make sure the previous comment leader is not removed. + */ + +/* List: + * - item1 + * foo bar baz + * foo bar baz + * - item2 + * foo bar baz + * foo bar baz + */ + +/* List: + * - item1 + * foo bar baz + * foo bar baz + * - item2 + * foo bar baz + * foo bar baz + */ + +// Should the next comment leader be left alone? +// Yes. + +// Should the next comment leader be left alone? +// Yes. + +/* Here the comment leader should be left intact. */ +// And so should this one. + +/* Here the comment leader should be left intact. */ +// And so should this one. + +if (condition) // Remove the next comment leader! + // OK, I will. + action(); + +if (condition) // Remove the next comment leader! + // OK, I will. + action(); + +int i = 7 /* foo *// 3 + // comment + ; + +int i = 7 /* foo *// 3 + // comment + ; + +># Note that the last character of the ending comment leader (left angle + # bracket) is a comment leader itself. Make sure that this comment leader is + # not removed from the next line #< +< On this line a new comment is opened which spans 2 lines. This comment should +< retain its comment leader. + +># Note that the last character of the ending comment leader (left angle + # bracket) is a comment leader itself. Make sure that this comment leader is + # not removed from the next line #< +< On this line a new comment is opened which spans 2 lines. This comment should +< retain its comment leader. + +} + +STARTTEST +:g/^STARTTEST/.,/^ENDTEST/d +:?firstline?+1,$w! test.out +:qa! +ENDTEST diff -Naur vim73.orig/src/testdir/test29.ok vim73/src/testdir/test29.ok --- vim73.orig/src/testdir/test29.ok 2010-07-10 12:08:18.000000000 +0000 +++ vim73/src/testdir/test29.ok 2012-07-20 20:31:16.867644128 +0000 @@ -47,3 +47,42 @@ asdfasdf asdf asdfasdf asdf zx cvn. as dfg? hjkl iop! ert a + + +{ +/* Make sure the previous comment leader is not removed. */ +/* Make sure the previous comment leader is not removed. */ +// Should the next comment leader be left alone? Yes. +// Should the next comment leader be left alone? Yes. +/* Here the comment leader should be left intact. */ // And so should this one. +/* Here the comment leader should be left intact. */ // And so should this one. +if (condition) // Remove the next comment leader! OK, I will. + action(); +if (condition) // Remove the next comment leader! OK, I will. + action(); +} + + +{ +/* Make sure the previous comment leader is not removed. */ +/* Make sure the previous comment leader is not removed. */ +/* List: item1 foo bar baz foo bar baz item2 foo bar baz foo bar baz */ +/* List: item1 foo bar baz foo bar baz item2 foo bar baz foo bar baz */ +// Should the next comment leader be left alone? Yes. +// Should the next comment leader be left alone? Yes. +/* Here the comment leader should be left intact. */ // And so should this one. +/* Here the comment leader should be left intact. */ // And so should this one. +if (condition) // Remove the next comment leader! OK, I will. + action(); +if (condition) // Remove the next comment leader! OK, I will. + action(); +int i = 7 /* foo *// 3 // comment + ; +int i = 7 /* foo *// 3 // comment + ; +># Note that the last character of the ending comment leader (left angle bracket) is a comment leader itself. Make sure that this comment leader is not removed from the next line #< < On this line a new comment is opened which spans 2 lines. This comment should retain its comment leader. +># Note that the last character of the ending comment leader (left angle bracket) is a comment leader itself. Make sure that this comment leader is not removed from the next line #< < On this line a new comment is opened which spans 2 lines. This comment should retain its comment leader. + +Some code!// Make sure backspacing does not remove this comment leader. +} + diff -Naur vim73.orig/src/testdir/test3.in vim73/src/testdir/test3.in --- vim73.orig/src/testdir/test3.in 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/testdir/test3.in 2012-07-20 20:31:16.854310787 +0000 @@ -299,18 +299,25 @@ enum soppie { - yes = 0, - no, - maybe +yes = 0, +no, +maybe }; typedef enum soppie { - yes = 0, - no, - maybe +yes = 0, +no, +maybe }; +static enum +{ +yes = 0, +no, +maybe +} soppie; + { int a, b; @@ -799,6 +806,69 @@ df */ hello } + +/* valid namespaces with normal indent */ +namespace +{ +{ + 111111111111; +} +} +namespace /* test */ +{ + 11111111111111111; +} +namespace // test +{ + 111111111111111111; +} +namespace +{ + 111111111111111111; +} +namespace test +{ + 111111111111111111; +} +namespace{ + 111111111111111111; +} +namespace test{ + 111111111111111111; +} +namespace { + 111111111111111111; +} +namespace test { + 111111111111111111; +namespace test2 { + 22222222222222222; +} +} + +/* invalid namespaces use block indent */ +namespace test test2 { + 111111111111111111111; +} +namespace11111111111 { + 111111111111; +} +namespace() { + 1111111111111; +} +namespace() +{ + 111111111111111111; +} +namespace test test2 +{ + 1111111111111111111; +} +namespace111111111 +{ + 111111111111111111; +} + /* end of AUTO */ STARTTEST @@ -907,6 +977,24 @@ STARTTEST :set cin +:set cino=es,n0s +/main +=][ +ENDTEST + +main(void) +{ + /* Make sure that cino=X0s is not parsed like cino=Xs. */ + if (cond) + foo(); + else + { + bar(); + } +} + +STARTTEST +:set cin :set cino= ]]=][ ENDTEST @@ -1246,6 +1334,20 @@ }; STARTTEST +:set cino=(0,gs,hs +2kdd]]=][ +ENDTEST + +class Foo : public Bar +{ +public: +virtual void method1(void) = 0; +virtual void method2(int arg1, +int arg2, +int arg3) = 0; +}; + +STARTTEST :set cino=+20 2kdd]]=][ ENDTEST @@ -1315,6 +1417,626 @@ } STARTTEST +:set cino=(0,ts +2kdd=][ +ENDTEST + +void func(int a +#if defined(FOO) + , int b + , int c +#endif + ) +{ +} + +STARTTEST +:set cino=(0 +2kdd=][ +ENDTEST + +void +func(int a +#if defined(FOO) + , int b + , int c +#endif + ) +{ +} + +STARTTEST +:set cino& +2kdd=7][ +ENDTEST + +void func(void) +{ + if(x==y) + if(y==z) + foo=1; + else { bar=1; + baz=2; + } + printf("Foo!\n"); +} + +void func1(void) +{ + char* tab[] = {"foo", "bar", + "baz", "quux", + "this line used", "to be indented incorrectly"}; + foo(); +} + +void func2(void) +{ + int tab[] = + {1, 2, + 3, 4, + 5, 6}; + + printf("This line used to be indented incorrectly.\n"); +} + +int foo[] +#ifdef BAR + += { 1, 2, 3, + 4, 5, 6 } + +#endif +; + int baz; + +void func3(void) +{ + int tab[] = { + 1, 2, + 3, 4, + 5, 6}; + +printf("Don't you dare indent this line incorrectly!\n"); +} + +void +func4(a, b, + c) +int a; +int b; +int c; +{ +} + +void +func5( + int a, + int b) +{ +} + +void +func6( + int a) +{ +} + +STARTTEST +:set cino& +:set cino+=l1 +2kdd=][ +ENDTEST + +void func(void) +{ + int tab[] = + { + 1, 2, 3, + 4, 5, 6}; + + printf("Indent this line correctly!\n"); + + switch (foo) + { + case bar: + printf("bar"); + break; + case baz: { + printf("baz"); + break; + } + case quux: +printf("But don't break the indentation of this instruction\n"); +break; + } +} + +STARTTEST +:set cino& +2kdd=][ +ENDTEST + +void func(void) +{ + cout << "a" + << "b" + << ") :" + << "c"; +} + +STARTTEST +:set com=s1:/*,m:*,ex:*/ +]]3jofoo(); +ENDTEST + +void func(void) +{ + /* + * This is a comment. + */ +} + +STARTTEST +:set cino& +2kdd=][ +ENDTEST + +void func(void) +{ + for (int i = 0; i < 10; ++i) + if (i & 1) { + foo(1); + } else + foo(0); +baz(); +} + +STARTTEST +:set cino=k2s,(0 +2kdd3j=][ +ENDTEST + +void func(void) +{ + if (condition1 + && condition2) + action(); + function(argument1 + && argument2); + + if (c1 && (c2 || + c3)) + foo; + if (c1 && + (c2 || c3)) + { + } + + if ( c1 + && ( c2 + || c3)) + foo; + func( c1 + && ( c2 + || c3)) + foo; +} + +STARTTEST +:set cino=k2s,(s +2kdd3j=][ +ENDTEST + +void func(void) +{ + if (condition1 + && condition2) + action(); + function(argument1 + && argument2); + + if (c1 && (c2 || + c3)) + foo; + if (c1 && + (c2 || c3)) + { + } + + if ( c1 + && ( c2 + || c3)) + foo; + func( c1 + && ( c2 + || c3)) + foo; +} + +STARTTEST +:set cino=k2s,(s,U1 +2kdd3j=][ +ENDTEST + +void func(void) +{ + if (condition1 + && condition2) + action(); + function(argument1 + && argument2); + + if (c1 && (c2 || + c3)) + foo; + if (c1 && + (c2 || c3)) + { + } + if (c123456789 + && (c22345 + || c3)) + printf("foo\n"); + + c = c1 && + ( + c2 || + c3 + ) && c4; +} + +STARTTEST +:set cino=k2s,(0,W4 +2kdd3j=][ +ENDTEST + +void func(void) +{ + if (condition1 + && condition2) + action(); + function(argument1 + && argument2); + + if (c1 && (c2 || + c3)) + foo; + if (c1 && + (c2 || c3)) + { + } + if (c123456789 + && (c22345 + || c3)) + printf("foo\n"); + + if ( c1 + && ( c2 + || c3)) + foo; + + a_long_line( + argument, + argument); + a_short_line(argument, + argument); +} + +STARTTEST +:set cino=k2s,u2 +2kdd3j=][ +ENDTEST + +void func(void) +{ + if (condition1 + && condition2) + action(); + function(argument1 + && argument2); + + if (c1 && (c2 || + c3)) + foo; + if (c1 && + (c2 || c3)) + { + } + if (c123456789 + && (c22345 + || c3)) + printf("foo\n"); +} + +STARTTEST +:set cino=k2s,(0,w1 +2kdd3j=][ +ENDTEST + +void func(void) +{ + if (condition1 + && condition2) + action(); + function(argument1 + && argument2); + + if (c1 && (c2 || + c3)) + foo; + if (c1 && + (c2 || c3)) + { + } + if (c123456789 + && (c22345 + || c3)) + printf("foo\n"); + + if ( c1 + && ( c2 + || c3)) + foo; + func( c1 + && ( c2 + || c3)) + foo; +} + +STARTTEST +:set cino=k2,(s +2kdd3j=][ +ENDTEST + +void func(void) +{ + if (condition1 + && condition2) + action(); + function(argument1 + && argument2); + + if (c1 && (c2 || + c3)) + foo; + if (c1 && + (c2 || c3)) + { + } +} + +STARTTEST +:set cino=N-s +/^NAMESPACESTART +=/^NAMESPACEEND +ENDTEST + +NAMESPACESTART +/* valid namespaces with normal indent */ +namespace +{ + { + 111111111111; +} +} +namespace /* test */ +{ + 11111111111111111; +} +namespace // test +{ + 111111111111111111; +} +namespace +{ + 111111111111111111; +} +namespace test +{ + 111111111111111111; +} +namespace{ + 111111111111111111; +} +namespace test{ + 111111111111111111; +} +namespace { + 111111111111111111; +} +namespace test { + 111111111111111111; +namespace test2 { + 22222222222222222; +} +} + +/* invalid namespaces use block indent */ +namespace test test2 { + 111111111111111111111; +} +namespace11111111111 { + 111111111111; +} +namespace() { + 1111111111111; +} +namespace() +{ + 111111111111111111; +} +namespace test test2 +{ + 1111111111111111111; +} +namespace111111111 +{ + 111111111111111111; +} +NAMESPACEEND + + +STARTTEST +:set cino=j1,J1 +/^JSSTART +=/^JSEND +ENDTEST + +JSSTART +var bar = { +foo: { +that: this, +some: ok, +}, +"bar":{ +a : 2, +b: "123abc", +x: 4, +"y": 5 +} +} +JSEND + +STARTTEST +:set cino=j1,J1 +/^JSSTART +=/^JSEND +ENDTEST + +JSSTART +var foo = [ +1, // indent 8 more +2, +3 +]; // indent 8 less +JSEND + +STARTTEST +:set cino=j1,J1 +/^JSSTART +=/^JSEND +ENDTEST + +JSSTART +function bar() { +var foo = [ +1, +2, +3 +]; // indent 16 less +} +JSEND + +STARTTEST +:set cino=j1,J1 +/^JSSTART +=/^JSEND +ENDTEST + +JSSTART +(function($){ + +var class_name='myclass'; + +function private_method() { +} + +var public_method={ +method: function(options,args){ +private_method(); +} +} + +function init(options) { + +$(this).data(class_name+'_public',$.extend({},{ +foo: 'bar', +bar: 2, // indent 8 more +foobar: [ // indent 8 more +1, // indent 8 more +2, // indent 16 more +3 // indent 16 more +], +callback: function(){ // indent 8 more +return true; // indent 8 more +} // indent 8 more +}, options||{})); +} + +$.fn[class_name]=function() { + +var _arguments=arguments; +return this.each(function(){ + +var options=$(this).data(class_name+'_public'); +if (!options) { +init.apply(this,_arguments); + +} else { +var method=public_method[_arguments[0]]; + +if (typeof(method)!='function') { +console.log(class_name+' has no method "'+_arguments[0]+'"'); +return false; +} +_arguments[0]=options; +method.apply(this,_arguments); +} +}); +} + +})(jQuery); +JSEND + +STARTTEST +:set cino=j1,J1 +/^JSSTART +=/^JSEND +ENDTEST + +JSSTART +function init(options) { +$(this).data(class_name+'_public',$.extend({},{ +foo: 'bar', +bar: 2, +foobar: [ +1, // indent 8 more +2, // indent 8 more +3 // indent 8 more +], +callback: function(){ +return true; +} +}, options||{})); +} +JSEND + +STARTTEST +:set cino=j1,J1 +/^JSSTART +=/^JSEND +ENDTEST + +JSSTART +(function($){ +function init(options) { +$(this).data(class_name+'_public',$.extend({},{ +foo: 'bar', +bar: 2, // indent 8 more +foobar: [ // indent 8 more +1, // indent 8 more +2, // indent 16 more +3 // indent 16 more +], +callback: function(){ // indent 8 more +return true; // indent 8 more +} // indent 8 more +}, options||{})); +} +})(jQuery); +JSEND + +STARTTEST :g/^STARTTEST/.,/^ENDTEST/d :1;/start of AUTO/,$wq! test.out ENDTEST diff -Naur vim73.orig/src/testdir/test3.ok vim73/src/testdir/test3.ok --- vim73.orig/src/testdir/test3.ok 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/testdir/test3.ok 2012-07-20 20:31:16.854310787 +0000 @@ -299,6 +299,13 @@ maybe }; +static enum +{ + yes = 0, + no, + maybe +} soppie; + { int a, b; @@ -787,6 +794,69 @@ df */ hello } + +/* valid namespaces with normal indent */ +namespace +{ + { + 111111111111; + } +} +namespace /* test */ +{ + 11111111111111111; +} +namespace // test +{ + 111111111111111111; +} +namespace +{ + 111111111111111111; +} +namespace test +{ + 111111111111111111; +} +namespace{ + 111111111111111111; +} +namespace test{ + 111111111111111111; +} +namespace { + 111111111111111111; +} +namespace test { + 111111111111111111; + namespace test2 { + 22222222222222222; + } +} + +/* invalid namespaces use block indent */ +namespace test test2 { + 111111111111111111111; +} +namespace11111111111 { + 111111111111; +} +namespace() { + 1111111111111; +} +namespace() +{ + 111111111111111111; +} +namespace test test2 +{ + 1111111111111111111; +} +namespace111111111 +{ + 111111111111111111; +} + /* end of AUTO */ @@ -870,6 +940,18 @@ } +main(void) +{ + /* Make sure that cino=X0s is not parsed like cino=Xs. */ + if (cond) + foo(); + else + { + bar(); + } +} + + { do { @@ -1127,6 +1209,16 @@ }; +class Foo : public Bar +{ + public: + virtual void method1(void) = 0; + virtual void method2(int arg1, + int arg2, + int arg3) = 0; +}; + + void foo() { @@ -1183,3 +1275,532 @@ foo; } + +void func(int a +#if defined(FOO) + , int b + , int c +#endif + ) +{ +} + + + void +func(int a +#if defined(FOO) + , int b + , int c +#endif + ) +{ +} + + +void func(void) +{ + if(x==y) + if(y==z) + foo=1; + else { bar=1; + baz=2; + } + printf("Foo!\n"); +} + +void func1(void) +{ + char* tab[] = {"foo", "bar", + "baz", "quux", + "this line used", "to be indented incorrectly"}; + foo(); +} + +void func2(void) +{ + int tab[] = + {1, 2, + 3, 4, + 5, 6}; + + printf("This line used to be indented incorrectly.\n"); +} + +int foo[] +#ifdef BAR + += { 1, 2, 3, + 4, 5, 6 } + +#endif + ; +int baz; + +void func3(void) +{ + int tab[] = { + 1, 2, + 3, 4, + 5, 6}; + + printf("Don't you dare indent this line incorrectly!\n"); +} + + void +func4(a, b, + c) + int a; + int b; + int c; +{ +} + + void +func5( + int a, + int b) +{ +} + + void +func6( + int a) +{ +} + + +void func(void) +{ + int tab[] = + { + 1, 2, 3, + 4, 5, 6}; + + printf("Indent this line correctly!\n"); + + switch (foo) + { + case bar: + printf("bar"); + break; + case baz: { + printf("baz"); + break; + } + case quux: + printf("But don't break the indentation of this instruction\n"); + break; + } +} + + +void func(void) +{ + cout << "a" + << "b" + << ") :" + << "c"; +} + + +void func(void) +{ + /* + * This is a comment. + */ + foo(); +} + + +void func(void) +{ + for (int i = 0; i < 10; ++i) + if (i & 1) { + foo(1); + } else + foo(0); + baz(); +} + + +void func(void) +{ + if (condition1 + && condition2) + action(); + function(argument1 + && argument2); + + if (c1 && (c2 || + c3)) + foo; + if (c1 && + (c2 || c3)) + { + } + + if ( c1 + && ( c2 + || c3)) + foo; + func( c1 + && ( c2 + || c3)) + foo; +} + + +void func(void) +{ + if (condition1 + && condition2) + action(); + function(argument1 + && argument2); + + if (c1 && (c2 || + c3)) + foo; + if (c1 && + (c2 || c3)) + { + } + + if ( c1 + && ( c2 + || c3)) + foo; + func( c1 + && ( c2 + || c3)) + foo; +} + + +void func(void) +{ + if (condition1 + && condition2) + action(); + function(argument1 + && argument2); + + if (c1 && (c2 || + c3)) + foo; + if (c1 && + (c2 || c3)) + { + } + if (c123456789 + && (c22345 + || c3)) + printf("foo\n"); + + c = c1 && + ( + c2 || + c3 + ) && c4; +} + + +void func(void) +{ + if (condition1 + && condition2) + action(); + function(argument1 + && argument2); + + if (c1 && (c2 || + c3)) + foo; + if (c1 && + (c2 || c3)) + { + } + if (c123456789 + && (c22345 + || c3)) + printf("foo\n"); + + if ( c1 + && ( c2 + || c3)) + foo; + + a_long_line( + argument, + argument); + a_short_line(argument, + argument); +} + + +void func(void) +{ + if (condition1 + && condition2) + action(); + function(argument1 + && argument2); + + if (c1 && (c2 || + c3)) + foo; + if (c1 && + (c2 || c3)) + { + } + if (c123456789 + && (c22345 + || c3)) + printf("foo\n"); +} + + +void func(void) +{ + if (condition1 + && condition2) + action(); + function(argument1 + && argument2); + + if (c1 && (c2 || + c3)) + foo; + if (c1 && + (c2 || c3)) + { + } + if (c123456789 + && (c22345 + || c3)) + printf("foo\n"); + + if ( c1 + && ( c2 + || c3)) + foo; + func( c1 + && ( c2 + || c3)) + foo; +} + + +void func(void) +{ + if (condition1 + && condition2) + action(); + function(argument1 + && argument2); + + if (c1 && (c2 || + c3)) + foo; + if (c1 && + (c2 || c3)) + { + } +} + + +NAMESPACESTART +/* valid namespaces with normal indent */ +namespace +{ +{ + 111111111111; +} +} +namespace /* test */ +{ +11111111111111111; +} +namespace // test +{ +111111111111111111; +} +namespace +{ +111111111111111111; +} +namespace test +{ +111111111111111111; +} +namespace{ +111111111111111111; +} +namespace test{ +111111111111111111; +} +namespace { +111111111111111111; +} +namespace test { +111111111111111111; +namespace test2 { +22222222222222222; +} +} + +/* invalid namespaces use block indent */ +namespace test test2 { + 111111111111111111111; +} +namespace11111111111 { + 111111111111; +} +namespace() { + 1111111111111; +} +namespace() +{ + 111111111111111111; +} +namespace test test2 +{ + 1111111111111111111; +} +namespace111111111 +{ + 111111111111111111; +} +NAMESPACEEND + + + +JSSTART +var bar = { + foo: { + that: this, + some: ok, + }, + "bar":{ + a : 2, + b: "123abc", + x: 4, + "y": 5 + } +} +JSEND + + +JSSTART +var foo = [ +1, // indent 8 more + 2, + 3 + ]; // indent 8 less +JSEND + + +JSSTART +function bar() { + var foo = [ + 1, + 2, + 3 + ]; // indent 16 less +} +JSEND + + +JSSTART +(function($){ + + var class_name='myclass'; + + function private_method() { + } + + var public_method={ + method: function(options,args){ + private_method(); + } + } + + function init(options) { + + $(this).data(class_name+'_public',$.extend({},{ + foo: 'bar', + bar: 2, // indent 8 more + foobar: [ // indent 8 more + 1, // indent 8 more + 2, // indent 16 more + 3 // indent 16 more + ], + callback: function(){ // indent 8 more + return true; // indent 8 more + } // indent 8 more + }, options||{})); + } + + $.fn[class_name]=function() { + + var _arguments=arguments; + return this.each(function(){ + + var options=$(this).data(class_name+'_public'); + if (!options) { + init.apply(this,_arguments); + + } else { + var method=public_method[_arguments[0]]; + + if (typeof(method)!='function') { + console.log(class_name+' has no method "'+_arguments[0]+'"'); + return false; + } + _arguments[0]=options; + method.apply(this,_arguments); + } + }); + } + +})(jQuery); +JSEND + + +JSSTART +function init(options) { + $(this).data(class_name+'_public',$.extend({},{ + foo: 'bar', + bar: 2, + foobar: [ + 1, // indent 8 more + 2, // indent 8 more + 3 // indent 8 more + ], + callback: function(){ + return true; + } + }, options||{})); +} +JSEND + + +JSSTART +(function($){ + function init(options) { + $(this).data(class_name+'_public',$.extend({},{ + foo: 'bar', + bar: 2, // indent 8 more + foobar: [ // indent 8 more + 1, // indent 8 more + 2, // indent 16 more + 3 // indent 16 more + ], + callback: function(){ // indent 8 more + return true; // indent 8 more + } // indent 8 more + }, options||{})); + } +})(jQuery); +JSEND + diff -Naur vim73.orig/src/testdir/test31.in vim73/src/testdir/test31.in --- vim73.orig/src/testdir/test31.in 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/testdir/test31.in 2012-07-20 20:31:14.857642689 +0000 @@ -63,6 +63,12 @@ :" write "testtext 1" A 3:close! :w >>test.out +:set nohidden +:" test ":all!" hides changed buffer; write "testtext 2 2 2" +:sp Xtest4 +GA 4:all! +:1wincmd w +:w >>test.out :qa! ENDTEST diff -Naur vim73.orig/src/testdir/test31.ok vim73/src/testdir/test31.ok --- vim73.orig/src/testdir/test31.ok 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/testdir/test31.ok 2012-07-20 20:31:14.857642689 +0000 @@ -9,3 +9,4 @@ testtext 1 testtext 3 3 3 testtext 1 +testtext 2 2 2 diff -Naur vim73.orig/src/testdir/test34.in vim73/src/testdir/test34.in --- vim73.orig/src/testdir/test34.in 2010-05-29 13:09:55.000000000 +0000 +++ vim73/src/testdir/test34.in 2012-07-20 20:31:18.260978460 +0000 @@ -1,5 +1,6 @@ Test for user functions. Also test an mapping calling a function. +Also test that a builtin function cannot be replaced. STARTTEST :so small.vim @@ -58,7 +59,10 @@ ---*--- (one (two -[(one again:$-5,$w! test.out +[(one again:call append(line('$'), max([1, 2, 3])) +:call extend(g:, {'max': function('min')}) +:call append(line('$'), max([1, 2, 3])) +:$-7,$w! test.out :delfunc Table :delfunc Compute :delfunc Expr1 diff -Naur vim73.orig/src/testdir/test34.ok vim73/src/testdir/test34.ok --- vim73.orig/src/testdir/test34.ok 2010-05-29 13:11:12.000000000 +0000 +++ vim73/src/testdir/test34.ok 2012-07-20 20:31:18.260978460 +0000 @@ -1,6 +1,8 @@ xxx4asdf fail nop ok 9 333 -XX111XX +XX111-XX ---222--- 1. one 2. two 1. one again +3 +3 diff -Naur vim73.orig/src/testdir/test43.in vim73/src/testdir/test43.in --- vim73.orig/src/testdir/test43.in 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/testdir/test43.in 2012-07-20 20:31:14.397642358 +0000 @@ -1,6 +1,7 @@ Tests for regexp with various magic settings. STARTTEST +:so small.vim :set nocompatible viminfo+=nviminfo /^1 /a*b\{2}c\+/e @@ -13,7 +14,11 @@ x:set magic /\v(a)(b)\2\1\1/e x/\V[ab]\(\[xy]\)\1 -x:?^1?,$w! test.out +x:$ +:set undolevels=100 +dv?bar? +Yup:" +:?^1?,$w! test.out :qa! ENDTEST @@ -25,3 +30,5 @@ 6 x ^aa$ x 7 (a)(b) abbaa 8 axx [ab]xx +9 foobar + diff -Naur vim73.orig/src/testdir/test43.ok vim73/src/testdir/test43.ok --- vim73.orig/src/testdir/test43.ok 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/testdir/test43.ok 2012-07-20 20:31:13.914308679 +0000 @@ -6,3 +6,6 @@ 6 x aa$ x 7 (a)(b) abba 8 axx ab]xx +9 foobar +9 foo + diff -Naur vim73.orig/src/testdir/test44.in vim73/src/testdir/test44.in --- vim73.orig/src/testdir/test44.in 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/testdir/test44.in 2012-07-20 20:31:12.114307384 +0000 @@ -27,6 +27,8 @@ x/\%U12345678 x/[\U1234abcd\u1234\uabcd] x/\%d21879b +x/ [[=A=]]* [[=B=]]* [[=C=]]* [[=D=]]* [[=E=]]* [[=F=]]* [[=G=]]* [[=H=]]* [[=I=]]* [[=J=]]* [[=K=]]* [[=L=]]* [[=M=]]* [[=N=]]* [[=O=]]* [[=P=]]* [[=Q=]]* [[=R=]]* [[=S=]]* [[=T=]]* [[=U=]]* [[=V=]]* [[=W=]]* [[=X=]]* [[=Y=]]* [[=Z=]]*/e +x/ [[=a=]]* [[=b=]]* [[=c=]]* [[=d=]]* [[=e=]]* [[=f=]]* [[=g=]]* [[=h=]]* [[=i=]]* [[=j=]]* [[=k=]]* [[=l=]]* [[=m=]]* [[=n=]]* [[=o=]]* [[=p=]]* [[=q=]]* [[=r=]]* [[=s=]]* [[=t=]]* [[=u=]]* [[=v=]]* [[=w=]]* [[=x=]]* [[=y=]]* [[=z=]]*/e x:?^1?,$w! test.out :e! test.out G:put =matchstr(\"×בגד\", \".\", 0, 2) " ב @@ -53,3 +55,5 @@ e ü’…™¸y f ü’Š¯z g aå•·bb +h AÀÃÂÃÄÅĀĂĄÇǞǠẢ BḂḆ CÇĆĈĊČ DÄŽÄḊḎḠEÈÉÊËĒĔĖĘĚẺẼ FḞ GĜĞĠĢǤǦǴḠ HĤĦḢḦḨ IÃŒÃÃŽÃĨĪĬĮİÇỈ JÄ´ KĶǨḰḴ LĹĻĽĿÅḺ MḾṀ NÑŃŅŇṄṈ OÒÓÔÕÖØŌŎÅƠǑǪǬỎ PṔṖ Q RŔŖŘṘṞ SŚŜŞŠṠ TŢŤŦṪṮ UÙÚÛÜŨŪŬŮŰŲƯǓỦ Vá¹¼ WŴẀẂẄẆ XẊẌ YÃŶŸẎỲỶỸ ZŹŻŽƵáºáº” +i aàáâãäåÄăąǎǟǡả bḃḇ cÃ§Ä‡Ä‰Ä‹Ä dÄđḋá¸á¸‘ eèéêëēĕėęěẻẽ fḟ gÄğġģǥǧǵḡ hĥħḣḧḩẖ iìíîïĩīĭįÇỉ jĵǰ kķǩḱḵ lĺļľŀłḻ mḿṠnñńņňʼnṅṉ oòóôõöøÅÅÅ‘Æ¡Ç’Ç«Ç­á» pṕṗ q rŕŗřṙṟ sÅ›Åşšṡ tţťŧṫṯẗ uùúûüũūŭůűųưǔủ vá¹½ wŵáºáºƒáº…ẇẘ xẋẠyýÿŷáºáº™á»³á»·á»¹ zźżžƶẑẕ diff -Naur vim73.orig/src/testdir/test44.ok vim73/src/testdir/test44.ok --- vim73.orig/src/testdir/test44.ok 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/testdir/test44.ok 2012-07-20 20:31:12.117640720 +0000 @@ -14,6 +14,8 @@ e y f z g abb +h AÀÃÂÃÄÅĀĂĄÇǞǠẢ BḂḆ CÇĆĈĊČ DÄŽÄḊḎḠEÈÉÊËĒĔĖĘĚẺẼ FḞ GĜĞĠĢǤǦǴḠ HĤĦḢḦḨ IÃŒÃÃŽÃĨĪĬĮİÇỈ JÄ´ KĶǨḰḴ LĹĻĽĿÅḺ MḾṀ NÑŃŅŇṄṈ OÒÓÔÕÖØŌŎÅƠǑǪǬỎ PṔṖ Q RŔŖŘṘṞ SŚŜŞŠṠ TŢŤŦṪṮ UÙÚÛÜŨŪŬŮŰŲƯǓỦ Vá¹¼ WŴẀẂẄẆ XẊẌ YÃŶŸẎỲỶỸ ZŹŻŽƵẠ+i aàáâãäåÄăąǎǟǡả bḃḇ cÃ§Ä‡Ä‰Ä‹Ä dÄđḋá¸á¸‘ eèéêëēĕėęěẻẽ fḟ gÄğġģǥǧǵḡ hĥħḣḧḩẖ iìíîïĩīĭįÇỉ jĵǰ kķǩḱḵ lĺļľŀłḻ mḿṠnñńņňʼnṅṉ oòóôõöøÅÅÅ‘Æ¡Ç’Ç«Ç­á» pṕṗ q rŕŗřṙṟ sÅ›Åşšṡ tţťŧṫṯẗ uùúûüũūŭůűųưǔủ vá¹½ wŵáºáºƒáº…ẇẘ xẋẠyýÿŷáºáº™á»³á»·á»¹ zźżžƶẑ ב בג × diff -Naur vim73.orig/src/testdir/test49.vim vim73/src/testdir/test49.vim --- vim73.orig/src/testdir/test49.vim 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/testdir/test49.vim 2012-07-20 20:31:07.597637458 +0000 @@ -1,6 +1,6 @@ " Vim script language tests " Author: Servatius Brandt -" Last Change: 2006 Apr 28 +" Last Change: 2010 Sep 29 "------------------------------------------------------------------------------- " Test environment {{{1 @@ -8711,7 +8711,7 @@ endif else if cmd == "let" - let match = MATCH(0, thrmsg, 'E106', "Unknown variable") + let match = MATCH(0, thrmsg, 'E121', "Undefined variable") elseif cmd == "unlet" let match = MATCH(0, thrmsg, 'E108', "No such variable") endif diff -Naur vim73.orig/src/testdir/test55.in vim73/src/testdir/test55.in --- vim73.orig/src/testdir/test55.in 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/testdir/test55.in 2012-07-20 20:31:16.110976920 +0000 @@ -342,7 +342,36 @@ :$put =(d == d) :$put =(l != deepcopy(l)) :$put =(d != deepcopy(d)) +:" +:" compare complex recursively linked list and dict +:let l = [] +:call add(l, l) +:let dict4 = {"l": l} +:call add(dict4.l, dict4) +:let lcopy = deepcopy(l) +:let dict4copy = deepcopy(dict4) +:$put =(l == lcopy) +:$put =(dict4 == dict4copy) +:" +:" Pass the same List to extend() +:let l = [1, 2, 3, 4, 5] +:call extend(l, l) +:$put =string(l) +:" +:" Pass the same Dict to extend() +:let d = { 'a': {'b': 'B'}} +:call extend(d, d) +:$put =string(d) +:" +:" Pass the same Dict to extend() with "error" +:try +: call extend(d, d, "error") +:catch +: $put =v:exception[:15] . v:exception[-1:-1] +:endtry +:$put =string(d) :endfun +:" :call Test(1, 2, [3, 4], {5: 6}) " This may take a while :" :delfunc Test diff -Naur vim73.orig/src/testdir/test55.ok vim73/src/testdir/test55.ok --- vim73.orig/src/testdir/test55.ok 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/testdir/test55.ok 2012-07-20 20:31:16.110976920 +0000 @@ -109,3 +109,9 @@ 1 0 0 +1 +1 +[1, 2, 3, 4, 5, 1, 2, 3, 4, 5] +{'a': {'b': 'B'}} +Vim(call):E737: a +{'a': {'b': 'B'}} diff -Naur vim73.orig/src/testdir/test57.in vim73/src/testdir/test57.in --- vim73.orig/src/testdir/test57.in 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/testdir/test57.in 2012-07-20 20:31:07.790970931 +0000 @@ -53,15 +53,19 @@ t02: numeric abc ab -a a321 a123 a122 +a +x-22 b321 b123 + c123d +-24 123b c321d +0 b322b b321 b321b diff -Naur vim73.orig/src/testdir/test57.ok vim73/src/testdir/test57.ok --- vim73.orig/src/testdir/test57.ok 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/testdir/test57.ok 2012-07-20 20:31:07.790970931 +0000 @@ -21,6 +21,10 @@ a + +-24 +x-22 +0 a122 a123 b123 diff -Naur vim73.orig/src/testdir/test61.in vim73/src/testdir/test61.in --- vim73.orig/src/testdir/test61.in 2010-06-27 03:07:58.000000000 +0000 +++ vim73/src/testdir/test61.in 2012-07-20 20:31:07.427637334 +0000 @@ -4,6 +4,10 @@ Also tests :earlier and :later. STARTTEST +:echo undotree().entries +ENDTEST + +STARTTEST :" Delete three characters and undo Gx:set ul=100 x:set ul=100 diff -Naur vim73.orig/src/testdir/test62.in vim73/src/testdir/test62.in --- vim73.orig/src/testdir/test62.in 2010-05-31 19:22:55.000000000 +0000 +++ vim73/src/testdir/test62.in 2012-07-20 20:31:17.930978224 +0000 @@ -49,6 +49,77 @@ :tabclose :call append(line('$'), test_status) :" +:if has('gui') || has('clientserver') +:" Test for ":tab drop exist-file" to keep current window. +:sp test1 +:tab drop test1 +:let test_status = 'tab drop 1: fail' +:if tabpagenr('$') == 1 && winnr('$') == 2 && winnr() == 1 +: let test_status = 'tab drop 1: pass' +:endif +:close +:call append(line('$'), test_status) +:" +:" +:" Test for ":tab drop new-file" to keep current window of tabpage 1. +:split +:tab drop newfile +:let test_status = 'tab drop 2: fail' +:if tabpagenr('$') == 2 && tabpagewinnr(1, '$') == 2 && tabpagewinnr(1) == 1 +: let test_status = 'tab drop 2: pass' +:endif +:tabclose +:q +:call append(line('$'), test_status) +:" +:" +:" Test for ":tab drop multi-opend-file" to keep current tabpage and window. +:new test1 +:tabnew +:new test1 +:tab drop test1 +:let test_status = 'tab drop 3: fail' +:if tabpagenr() == 2 && tabpagewinnr(2, '$') == 2 && tabpagewinnr(2) == 1 +: let test_status = 'tab drop 3: pass' +:endif +:tabclose +:q +:call append(line('$'), test_status) +:else +:" :drop not supported +:call append(line('$'), 'tab drop 1: pass') +:call append(line('$'), 'tab drop 2: pass') +:call append(line('$'), 'tab drop 3: pass') +:endif +:" +:" +:for i in range(9) | tabnew | endfor +1gt +Go=tabpagenr()  +:tabmove 5 +i=tabpagenr()  +:tabmove -2 +i=tabpagenr()  +:tabmove +4 +i=tabpagenr()  +:tabmove +i=tabpagenr()  +:tabmove -20 +i=tabpagenr()  +:tabmove +20 +i=tabpagenr()  +:3tabmove +i=tabpagenr()  +:7tabmove 5 +i=tabpagenr()  +:let a='No error caught.' +:try +:tabmove foo +:catch E474 +:let a='E474 caught.' +:endtry +i=a  +:" :" :/^Results/,$w! test.out :qa! diff -Naur vim73.orig/src/testdir/test62.ok vim73/src/testdir/test62.ok --- vim73.orig/src/testdir/test62.ok 2010-05-31 19:22:55.000000000 +0000 +++ vim73/src/testdir/test62.ok 2012-07-20 20:31:17.930978224 +0000 @@ -5,3 +5,16 @@ this is tab page 4 gettabvar: pass settabvar: pass +tab drop 1: pass +tab drop 2: pass +tab drop 3: pass +1 +6 +4 +8 +10 +1 +10 +4 +6 +E474 caught. diff -Naur vim73.orig/src/testdir/test65.in vim73/src/testdir/test65.in --- vim73.orig/src/testdir/test65.in 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/testdir/test65.in 2012-07-20 20:31:13.614308463 +0000 @@ -1,4 +1,4 @@ -Test for floating point. +Test for floating point and logical operators. STARTTEST :so small.vim @@ -72,6 +72,23 @@ :$put ='float2nr' :$put =float2nr(123.456) :$put =float2nr(-123.456) +:$put ='AND' +:$put =and(127, 127) +:$put =and(127, 16) +:$put =and(127, 128) +:$put ='OR' +:$put =or(16, 7) +:$put =or(8, 7) +:$put =or(0, 123) +:$put ='XOR' +:$put =xor(127, 127) +:$put =xor(127, 16) +:$put =xor(127, 128) +:$put ='invert' +:$put =and(invert(127), 65535) +:$put =and(invert(16), 65535) +:$put =and(invert(128), 65535) +:$put =invert(1.0) :/^Results/,$wq! test.out ENDTEST diff -Naur vim73.orig/src/testdir/test65.ok vim73/src/testdir/test65.ok --- vim73.orig/src/testdir/test65.ok 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/testdir/test65.ok 2012-07-20 20:31:13.614308463 +0000 @@ -54,3 +54,20 @@ float2nr 123 -123 +AND +127 +16 +0 +OR +23 +15 +123 +XOR +0 +111 +255 +invert +65408 +65519 +65407 +0 diff -Naur vim73.orig/src/testdir/test68.in vim73/src/testdir/test68.in --- vim73.orig/src/testdir/test68.in 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/testdir/test68.in 2012-07-20 20:31:17.610977994 +0000 @@ -51,6 +51,57 @@ } STARTTEST +/^{/+1 +:set tw=5 fo=tcn comments=:# +A bjA b +ENDTEST + +{ + 1 a +# 1 a +} + +STARTTEST +/^{/+1 +:set tw=5 fo=qn comments=:# +gwap +ENDTEST + +{ +# 1 a b +} + +STARTTEST +/^{/+1 +:set tw=5 fo=q2 comments=:# +gwap +ENDTEST + +{ +# x +# a b +} + +STARTTEST +/^{/+2 +:set tw& fo=a +I^^ +ENDTEST + +{ + 1aa + 2bb +} + +STARTTEST +/^#/ +:setl tw=12 fo=tqnc comments=:# +A foobar +ENDTEST + +# 1 xxxxx + +STARTTEST :g/^STARTTEST/.,/^ENDTEST/d :1;/^Results/,$wq! test.out ENDTEST diff -Naur vim73.orig/src/testdir/test68.ok vim73/src/testdir/test68.ok --- vim73.orig/src/testdir/test68.ok 2010-05-15 11:04:10.000000000 +0000 +++ vim73/src/testdir/test68.ok 2012-07-20 20:31:17.807644801 +0000 @@ -33,3 +33,30 @@ #a b } + +{ + 1 a + b +# 1 a +# b +} + + +{ +# 1 a +# b +} + + +{ +# x a +# b +} + + +{ 1aa ^^2bb } + + +# 1 xxxxx +# foobar + diff -Naur vim73.orig/src/testdir/test72.in vim73/src/testdir/test72.in --- vim73.orig/src/testdir/test72.in 2010-08-07 11:26:43.000000000 +0000 +++ vim73/src/testdir/test72.in 2012-07-20 20:31:13.880975322 +0000 @@ -51,6 +51,12 @@ :e Xtestfile uuu:w >>test.out :" +:" Test that reading the undofiles when setting undofile works +:set noundofile ul=0 +i +u:e! Xtestfile +:set undofile ul=100 +uuuuuu:w >>test.out :" And now with encryption, cryptmethod=zip :e! Xtestfile :set undofile cm=zip diff -Naur vim73.orig/src/testdir/test72.ok vim73/src/testdir/test72.ok --- vim73.orig/src/testdir/test72.ok 2010-05-30 20:39:12.000000000 +0000 +++ vim73/src/testdir/test72.ok 2012-07-20 20:31:13.880975322 +0000 @@ -7,6 +7,16 @@ eight nine ten +one +two +three +four +five +six +seven +eight +nine +ten monday wednesday thursday diff -Naur vim73.orig/src/testdir/test74.in vim73/src/testdir/test74.in --- vim73.orig/src/testdir/test74.in 1970-01-01 00:00:00.000000000 +0000 +++ vim73/src/testdir/test74.in 2012-07-20 20:31:07.824304288 +0000 @@ -0,0 +1,36 @@ +" Tests for storing global variables in the .viminfo file vim: set ft=vim: + +STARTTEST +:so small.vim +:" Do all test in a separate window to avoid E211 when we recursively +:" delete the Xfind directory during cleanup +:" +:" This will cause a few errors, do it silently. +:set visualbell +:set nocp viminfo+=!,nviminfo +:let MY_GLOBAL_DICT={'foo': 1, 'bar': 0, 'longvarible': 1000} +:" store a really long list, so line wrapping will occur in viminfo file +:let MY_GLOBAL_LIST=range(1,100) +:wv! Xviminfo +:unlet MY_GLOBAL_DICT +:unlet MY_GLOBAL_LIST +:rv! Xviminfo +:call delete('Xviminfo') +:if exists("MY_GLOBAL_DICT") +:redir >> test.out +:echo MY_GLOBAL_DICT +:redir end +:endif +:if exists("MY_GLOBAL_LIST") +:redir >> test.out +:echo MY_GLOBAL_LIST +:redir end +:endif +:redir >> test.out +:echo "foobar" +:redir end +:endif +:qa! +ENDTEST + +eof diff -Naur vim73.orig/src/testdir/test74.ok vim73/src/testdir/test74.ok --- vim73.orig/src/testdir/test74.ok 1970-01-01 00:00:00.000000000 +0000 +++ vim73/src/testdir/test74.ok 2012-07-20 20:31:07.824304288 +0000 @@ -0,0 +1,5 @@ + +{'foo': 1, 'longvarible': 1000, 'bar': 0} +[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100] + +foobar diff -Naur vim73.orig/src/testdir/test75.in vim73/src/testdir/test75.in --- vim73.orig/src/testdir/test75.in 1970-01-01 00:00:00.000000000 +0000 +++ vim73/src/testdir/test75.in 2012-07-20 20:31:12.414307600 +0000 @@ -0,0 +1,22 @@ +" Tests for functions. + +STARTTEST +:so small.vim +:set cpo-=< +:" Test maparg() with a string result +:map foo isfoo +:vnoremap