Submitted By: Jim Gifford (jim at linuxfromscratch dot org) Date: 02-15-2007 Initial Package Version: 7.0 Origin: Upstream Upstream Status: Applied Description: Contains all upstream patches up to 7.0.195 The following patches were skipped 005 027 028 032 045 057 065 074 108 130 131 132 138 156 161 170 171 180 diff -Naur vim70.orig/configure vim70/configure --- vim70.orig/configure 2004-07-05 02:02:24.000000000 -0700 +++ vim70/configure 2007-02-15 21:22:24.000000000 -0800 @@ -3,4 +3,4 @@ # This is just a stub for the Unix configure script, to provide support for # doing "./configure" in the top Vim directory. -cd src && ./configure "$@" +cd src && exec ./configure "$@" diff -Naur vim70.orig/runtime/autoload/ccomplete.vim vim70/runtime/autoload/ccomplete.vim --- vim70.orig/runtime/autoload/ccomplete.vim 2006-05-03 07:35:56.000000000 -0700 +++ vim70/runtime/autoload/ccomplete.vim 2007-02-15 21:22:24.000000000 -0800 @@ -1,7 +1,7 @@ " Vim completion script " Language: C " Maintainer: Bram Moolenaar -" Last Change: 2006 May 03 +" Last Change: 2006 May 08 " This function is used for the 'omnifunc' option. @@ -458,7 +458,7 @@ " member. function! s:StructMembers(typename, items, all) " Todo: What about local structures? - let fnames = join(map(tagfiles(), 'escape(v:val, " \\")')) + let fnames = join(map(tagfiles(), 'escape(v:val, " \\#%")')) if fnames == '' return [] endif diff -Naur vim70.orig/runtime/autoload/gzip.vim vim70/runtime/autoload/gzip.vim --- vim70.orig/runtime/autoload/gzip.vim 2006-03-31 07:12:15.000000000 -0800 +++ vim70/runtime/autoload/gzip.vim 2007-02-15 21:22:25.000000000 -0800 @@ -1,6 +1,6 @@ " Vim autoload file for editing compressed files. " Maintainer: Bram Moolenaar -" Last Change: 2006 Mar 31 +" Last Change: 2006 Oct 03 " These functions are used by the gzip plugin. @@ -68,9 +68,9 @@ let tmp = tempname() let tmpe = tmp . "." . expand(":e") " write the just read lines to a temp file "'[,']w tmp.gz" - execute "silent '[,']w " . tmpe + execute "silent '[,']w " . escape(tmpe, ' ') " uncompress the temp file: call system("gzip -dn tmp.gz") - call system(a:cmd . " " . tmpe) + call system(a:cmd . " " . s:escape(tmpe)) if !filereadable(tmp) " uncompress didn't work! Keep the compressed file then. echoerr "Error: Could not read uncompressed file" @@ -127,9 +127,9 @@ let nmt = s:tempname(nm) if rename(nm, nmt) == 0 if exists("b:gzip_comp_arg") - call system(a:cmd . " " . b:gzip_comp_arg . " " . nmt) + call system(a:cmd . " " . b:gzip_comp_arg . " " . s:escape(nmt)) else - call system(a:cmd . " " . nmt) + call system(a:cmd . " " . s:escape(nmt)) endif call rename(nmt . "." . expand(":e"), nm) endif @@ -154,10 +154,10 @@ if rename(nm, nmte) == 0 if &patchmode != "" && getfsize(nm . &patchmode) == -1 " Create patchmode file by creating the decompressed file new - call system(a:cmd . " -c " . nmte . " > " . nmt) + call system(a:cmd . " -c " . s:escape(nmte) . " > " . s:escape(nmt)) call rename(nmte, nm . &patchmode) else - call system(a:cmd . " " . nmte) + call system(a:cmd . " " . s:escape(nmte)) endif call rename(nmt, nm) endif @@ -175,4 +175,12 @@ return fnamemodify(a:name, ":p:h") . "/X~=@l9q5" endfun +fun s:escape(name) + " shellescape() was added by patch 7.0.111 + if v:version > 700 || (v:version == 700 && has('patch111')) + return shellescape(a:name) + endif + return "'" . a:name . "'" +endfun + " vim: set sw=2 : diff -Naur vim70.orig/runtime/autoload/paste.vim vim70/runtime/autoload/paste.vim --- vim70.orig/runtime/autoload/paste.vim 2006-04-21 11:31:01.000000000 -0700 +++ vim70/runtime/autoload/paste.vim 2007-02-15 21:22:24.000000000 -0800 @@ -1,6 +1,6 @@ " Vim support file to help with paste mappings and menus " Maintainer: Bram Moolenaar -" Last Change: 2006 Apr 21 +" Last Change: 2006 Jun 23 " Define the string to use for items that are present both in Edit, Popup and " Toolbar menu. Also used in mswin.vim and macmap.vim. @@ -12,7 +12,7 @@ if has("virtualedit") let paste#paste_cmd = {'n': ":call paste#Paste()"} let paste#paste_cmd['v'] = '"-c' . paste#paste_cmd['n'] - let paste#paste_cmd['i'] = '' . paste#paste_cmd['n'] . 'gi' + let paste#paste_cmd['i'] = 'x' . paste#paste_cmd['n'] . 'gi' func! paste#Paste() let ove = &ve diff -Naur vim70.orig/runtime/autoload/spellfile.vim vim70/runtime/autoload/spellfile.vim --- vim70.orig/runtime/autoload/spellfile.vim 2006-02-01 04:12:24.000000000 -0800 +++ vim70/runtime/autoload/spellfile.vim 2007-02-15 21:22:25.000000000 -0800 @@ -1,9 +1,9 @@ " Vim script to download a missing spell file " Maintainer: Bram Moolenaar -" Last Change: 2006 Feb 01 +" Last Change: 2006 Aug 29 if !exists('g:spellfile_URL') - let g:spellfile_URL = 'ftp://ftp.vim.org/pub/vim/unstable/runtime/spell' + let g:spellfile_URL = 'ftp://ftp.vim.org/pub/vim/runtime/spell' endif let s:spellfile_URL = '' " Start with nothing so that s:donedict is reset. @@ -61,13 +61,13 @@ new setlocal bin echo 'Downloading ' . fname . '...' - exe 'Nread ' g:spellfile_URL . '/' . fname + call spellfile#Nread(fname) if getline(2) !~ 'VIMspell' " Didn't work, perhaps there is an ASCII one. g/^/d let fname = a:lang . '.ascii.spl' echo 'Could not find it, trying ' . fname . '...' - exe 'Nread ' g:spellfile_URL . '/' . fname + call spellfile#Nread(fname) if getline(2) !~ 'VIMspell' echo 'Sorry, downloading failed' bwipe! @@ -95,7 +95,7 @@ g/^/d let fname = substitute(fname, '\.spl$', '.sug', '') echo 'Downloading ' . fname . '...' - exe 'Nread ' g:spellfile_URL . '/' . fname + call spellfile#Nread(fname) if getline(2) !~ 'VIMsug' echo 'Sorry, downloading failed' else @@ -109,3 +109,15 @@ bwipe endif endfunc + +" Read "fname" from the server. +function! spellfile#Nread(fname) + if g:spellfile_URL =~ '^ftp://' + " for an ftp server use a default login and password to avoid a prompt + let machine = substitute(g:spellfile_URL, 'ftp://\([^/]*\).*', '\1', '') + let dir = substitute(g:spellfile_URL, 'ftp://[^/]*/\(.*\)', '\1', '') + exe 'Nread "' . machine . ' anonymous vim7user ' . dir . '/' . a:fname . '"' + else + exe 'Nread ' g:spellfile_URL . '/' . a:fname + endif +endfunc diff -Naur vim70.orig/runtime/doc/autocmd.txt vim70/runtime/doc/autocmd.txt --- vim70.orig/runtime/doc/autocmd.txt 2006-05-07 05:16:44.000000000 -0700 +++ vim70/runtime/doc/autocmd.txt 2007-02-15 21:22:27.000000000 -0800 @@ -1,4 +1,4 @@ -*autocmd.txt* For Vim version 7.0. Last change: 2006 May 06 +*autocmd.txt* For Vim version 7.0. Last change: 2007 Jan 16 VIM REFERENCE MANUAL by Bram Moolenaar @@ -279,6 +279,7 @@ |FuncUndefined| a user function is used but it isn't defined |SpellFileMissing| a spell file is used but it can't be found |SourcePre| before sourcing a Vim script +|SourceCmd| before sourcing a Vim script |Cmd-event| |VimResized| after the Vim window size changed |FocusGained| Vim got input focus @@ -690,10 +691,17 @@ Can be used to check for any changed files. *SourcePre* SourcePre Before sourcing a Vim script. |:source| + is the name of the file being sourced. + *SourceCmd* +SourceCmd When sourcing a Vim script. |:source| + is the name of the file being sourced. + The autocommand must source this file. + |Cmd-event| *SpellFileMissing* SpellFileMissing When trying to load a spell checking file and - it can't be found. is the language, - 'encoding' also matters. See + it can't be found. The pattern is matched + against the language. is the + language, 'encoding' also matters. See |spell-SpellFileMissing|. *StdinReadPost* StdinReadPost After reading from the stdin into the buffer, @@ -1219,8 +1227,8 @@ *Cmd-event* When using one of the "*Cmd" events, the matching autocommands are expected to -do the file reading or writing. This can be used when working with a special -kind of file, for example on a remote system. +do the file reading, writing or sourcing. This can be used when working with +a special kind of file, for example on a remote system. CAREFUL: If you use these events in a wrong way, it may have the effect of making it impossible to read or write the matching files! Make sure you test your autocommands properly. Best is to use a pattern that will never match a @@ -1233,9 +1241,10 @@ original file isn't needed for recovery. You might want to do this only when you expect the file to be modified. -The |v:cmdarg| variable holds the "++enc=" and "++ff=" argument that are -effective. These should be used for the command that reads/writes the file. -The |v:cmdbang| variable is one when "!" was used, zero otherwise. +For file read and write commands the |v:cmdarg| variable holds the "++enc=" +and "++ff=" argument that are effective. These should be used for the command +that reads/writes the file. The |v:cmdbang| variable is one when "!" was +used, zero otherwise. See the $VIMRUNTIME/plugin/netrw.vim for examples. diff -Naur vim70.orig/runtime/doc/eval.txt vim70/runtime/doc/eval.txt --- vim70.orig/runtime/doc/eval.txt 2006-05-07 05:16:44.000000000 -0700 +++ vim70/runtime/doc/eval.txt 2007-02-15 21:22:27.000000000 -0800 @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 7.0. Last change: 2006 May 06 +*eval.txt* For Vim version 7.0. Last change: 2006 Nov 01 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1374,6 +1374,21 @@ '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: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 @@ -1709,6 +1724,8 @@ 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}) String escape {string} for use as shell + command argument simplify( {filename}) String simplify filename as much as possible sort( {list} [, {func}]) List sort {list}, using {func} to compare soundfold( {word}) String sound-fold {word} @@ -2700,6 +2717,17 @@ 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. @@ -2869,12 +2897,14 @@ 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. + 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: > @@ -4343,7 +4373,10 @@ Non-dictionary items in {list} are ignored. Each dictionary item can contain the following entries: - filename name of a file + 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 @@ -4356,11 +4389,13 @@ 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" entry is not present or neither the "lnum" - or "pattern" entries are present, then the item will not be - handled as an 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. + 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 @@ -4434,6 +4469,21 @@ :call setwinvar(1, "&list", 0) :call setwinvar(2, "myvar", "foobar") +shellescape({string}) *shellescape()* + Escape {string} for use as shell command argument. + On MS-Windows and MS-DOS, when 'shellslash' is not set, it + will enclose {string} double quotes and double all double + quotes within {string}. + For other systems, it will enclose {string} in single quotes + and replace all "'" with "'\''". + Example: > + :echo shellescape('c:\program files\vim') +< results in: + "c:\program files\vim" ~ + Example usage: > + :call system("chmod +x -- " . 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 diff -Naur vim70.orig/runtime/doc/netbeans.txt vim70/runtime/doc/netbeans.txt --- vim70.orig/runtime/doc/netbeans.txt 2006-05-07 05:16:45.000000000 -0700 +++ vim70/runtime/doc/netbeans.txt 2007-02-15 21:22:26.000000000 -0800 @@ -1,4 +1,4 @@ -*netbeans.txt* For Vim version 7.0. Last change: 2006 Mar 09 +*netbeans.txt* For Vim version 7.0. Last change: 2006 Nov 14 VIM REFERENCE MANUAL by Gordon Prieur @@ -259,8 +259,8 @@ confusion happening again, netbeans_saved() has been renamed to netbeans_save_buffer(). -We are now at version 2.3. For the differences between 2.2 and 2.3 search for -"2.3" below. +We are now at version 2.4. For the differences between 2.3 and 2.4 search for +"2.4" below. The messages are currently sent over a socket. Since the messages are in plain UTF-8 text this protocol could also be used with any other communication @@ -605,6 +605,15 @@ getMark Not implemented. +getAnno serNum + Return the line number of the annotation in the buffer. + Argument: + serNum serial number of this placed annotation + The reply is: + 123 lnum line number of the annotation + 123 0 invalid annotation serial number + New in version 2.4. + getModified When a buffer is specified: Return zero if the buffer does not have changes, one if it does have changes. When no buffer is specified (buffer number zero): Return the diff -Naur vim70.orig/runtime/menu.vim vim70/runtime/menu.vim --- vim70.orig/runtime/menu.vim 2006-04-17 06:47:28.000000000 -0700 +++ vim70/runtime/menu.vim 2007-02-15 21:22:25.000000000 -0800 @@ -2,7 +2,7 @@ " You can also use this as a start for your own set of menus. " " Maintainer: Bram Moolenaar -" Last Change: 2006 Apr 17 +" Last Change: 2006 Sep 14 " Note that ":an" (short for ":anoremenu") is often used to make a menu work " in all modes and avoid side effects from mappings defined by the user. @@ -885,6 +885,8 @@ if exists("s:changeitem") && s:changeitem != '' call SpellDel() endif + + " Return quickly if spell checking is not enabled. if !&spell || &spelllang == '' return endif @@ -908,18 +910,18 @@ let s:fromword = w let pri = 1 for sug in s:suglist - exe 'amenu 1.5.' . pri . ' PopUp.' . s:changeitem . '.' . escape(sug, ' .') + exe 'anoremenu 1.5.' . pri . ' PopUp.' . s:changeitem . '.' . escape(sug, ' .') \ . ' :call SpellReplace(' . pri . ')' let pri += 1 endfor let s:additem = 'add\ "' . escape(w, ' .') . '"\ to\ word\ list' - exe 'amenu 1.6 PopUp.' . s:additem . ' :spellgood ' . w . '' + exe 'anoremenu 1.6 PopUp.' . s:additem . ' :spellgood ' . w . '' let s:ignoreitem = 'ignore\ "' . escape(w, ' .') . '"' - exe 'amenu 1.7 PopUp.' . s:ignoreitem . ' :spellgood! ' . w . '' + exe 'anoremenu 1.7 PopUp.' . s:ignoreitem . ' :spellgood! ' . w . '' - amenu 1.8 PopUp.-SpellSep- : + anoremenu 1.8 PopUp.-SpellSep- : endif endif endfunc @@ -938,7 +940,9 @@ let s:changeitem = '' endfun - au! MenuPopup * call SpellPopup() + augroup SpellPopupMenu + au! MenuPopup * call SpellPopup() + augroup END endif " The GUI toolbar (for MS-Windows and GTK) @@ -1013,9 +1017,9 @@ tmenu ToolBar.FindPrev Find Previous tmenu ToolBar.Replace Find / Replace... endif - tmenu ToolBar.LoadSesn Chose a session to load + tmenu ToolBar.LoadSesn Choose a session to load tmenu ToolBar.SaveSesn Save current session - tmenu ToolBar.RunScript Chose a Vim Script to run + tmenu ToolBar.RunScript Choose a Vim Script to run tmenu ToolBar.Make Make current project (:make) tmenu ToolBar.RunCtags Build tags in current directory tree (!ctags -R .) tmenu ToolBar.TagJump Jump to tag under cursor diff -Naur vim70.orig/runtime/plugin/matchparen.vim vim70/runtime/plugin/matchparen.vim --- vim70.orig/runtime/plugin/matchparen.vim 2006-04-27 06:31:26.000000000 -0700 +++ vim70/runtime/plugin/matchparen.vim 2007-02-15 21:22:25.000000000 -0800 @@ -1,6 +1,6 @@ " Vim plugin for showing matching parens " Maintainer: Bram Moolenaar -" Last Change: 2006 Apr 27 +" Last Change: 2006 Sep 09 " Exit quickly when: " - this plugin was already loaded (or disabled) @@ -44,7 +44,7 @@ let before = 0 let c = getline(c_lnum)[c_col - 1] - let plist = split(&matchpairs, ':\|,') + let plist = split(&matchpairs, '.\zs[:,]') let i = index(plist, c) if i < 0 " not found, in Insert mode try character before the cursor @@ -90,19 +90,19 @@ " Find the match. When it was just before the cursor move it there for a " moment. if before > 0 - let save_cursor = getpos('.') + let save_cursor = winsaveview() call cursor(c_lnum, c_col - before) endif " When not in a string or comment ignore matches inside them. let s_skip ='synIDattr(synID(line("."), col("."), 0), "name") ' . - \ '=~? "string\\|comment"' + \ '=~? "string\\|character\\|singlequote\\|comment"' execute 'if' s_skip '| let s_skip = 0 | endif' let [m_lnum, m_col] = searchpairpos(c, '', c2, s_flags, s_skip, stopline) if before > 0 - call setpos('.', save_cursor) + call winrestview(save_cursor) endif " If a match is found setup match highlighting. diff -Naur vim70.orig/runtime/scripts.vim vim70/runtime/scripts.vim --- vim70.orig/runtime/scripts.vim 2006-03-28 11:30:49.000000000 -0800 +++ vim70/runtime/scripts.vim 2007-02-15 21:22:24.000000000 -0800 @@ -1,7 +1,7 @@ " Vim support file to detect file types in scripts " " Maintainer: Bram Moolenaar -" Last change: 2006 Mar 28 +" Last change: 2006 Jul 08 " This file is called by an autocommand for every file that has just been " loaded into a buffer. It checks if the type of file can be recognized by @@ -54,6 +54,12 @@ let s:name = substitute(s:line1, '^#!\s*\S*[/\\]\(\i\+\).*', '\1', '') endif + " tcl scripts may have #!/bin/sh in the first line and "exec wish" in the + " third line. Suggested by Steven Atkinson. + if getline(3) =~ '^exec wish' + let s:name = 'wish' + endif + " Bourne-like shell scripts: bash bash2 ksh ksh93 sh if s:name =~ '^\(bash\d*\|\|ksh\d*\|sh\)\>' call SetFileTypeSH(s:line1) " defined in filetype.vim diff -Naur vim70.orig/runtime/tutor/Makefile vim70/runtime/tutor/Makefile --- vim70.orig/runtime/tutor/Makefile 2004-06-07 07:32:39.000000000 -0700 +++ vim70/runtime/tutor/Makefile 2007-02-15 21:22:25.000000000 -0800 @@ -2,8 +2,13 @@ # # The Japanese tutor exists in three encodings. Use the UTF-8 version as the # original and create the others with conversion. +# +# Similarly for Russian and Korean -all: tutor.ja.sjis tutor.ja.euc tutor.ko.euc +all: tutor.ja.sjis tutor.ja.euc \ + tutor.ko.euc \ + tutor.ru tutor.ru.cp1251 \ + tutor.gr tutor.gr.cp737 tutor.ja.sjis: tutor.ja.utf-8 nkf -WXs tutor.ja.utf-8 > tutor.ja.sjis @@ -13,3 +18,15 @@ tutor.ko.euc: tutor.ko.utf-8 iconv -f UTF-8 -t EUC-KR tutor.ko.utf-8 > tutor.ko.euc + +tutor.ru: tutor.ru.utf-8 + iconv -f UTF-8 -t KOI8-R tutor.ru.utf-8 > tutor.ru + +tutor.ru.cp1251: tutor.ru.utf-8 + iconv -f UTF-8 -t cp1251 tutor.ru.utf-8 > tutor.ru.cp1251 + +tutor.gr: tutor.gr.utf-8 + iconv -f UTF-8 -t ISO-8859-7 tutor.gr.utf-8 > tutor.gr + +tutor.gr.cp737: tutor.gr.utf-8 + iconv -f UTF-8 -t cp737 tutor.gr.utf-8 > tutor.gr.cp737 diff -Naur vim70.orig/runtime/tutor/tutor.gr.utf-8 vim70/runtime/tutor/tutor.gr.utf-8 --- vim70.orig/runtime/tutor/tutor.gr.utf-8 1969-12-31 16:00:00.000000000 -0800 +++ vim70/runtime/tutor/tutor.gr.utf-8 2007-02-15 21:22:25.000000000 -0800 @@ -0,0 +1,815 @@ +=============================================================================== += Κ αλ ω σ ή ρ θ α τ ε σ τ ο V I M T u t o r - Έκδοση 1.5 = +=============================================================================== + + Ο Vim είναι ένας πανίσχυρος συντάκτης που έχει πολλές εντολές, πάρα + πολλές για να εξηγήσουμε σε μία περιήγηση όπως αυτή. Αυτή η περιήγηση + σχεδιάστηκε για να περιγράψει ικανοποιητικά τις εντολές που θα σας + κάνουν να χρησιμοποιείτε εύκολα τον Vim σαν έναν γενικής χρήσης συντάκτη. + + Ο κατά προσέγγιση χρόνος που απαιτείται για να ολοκληρώσετε την περιήγηση + είναι 25-30 λεπτά, εξαρτώντας από το πόσο χρόνο θα ξοδέψετε για + πειραματισμούς. + + Οι εντολές στα μαθήματα θα τροποποιήσουν το κείμενο. Δημιουργήστε ένα + αντίγραφο αυτού του αρχείου για να εξασκηθείτε (αν ξεκινήσατε το + "Vimtutor" αυτό είναι ήδη ένα αντίγραφο). + + Είναι σημαντικό να θυμάστε ότι αυτή η περιήγηση είναι οργανωμένη έτσι + ώστε να διδάσκει μέσω της χρήσης. Αυτό σημαίνει ότι χρειάζεται να + εκτελείτε τις εντολές για να τις μάθετε σωστά. Αν διαβάζετε μόνο το + κείμενο, θα τις ξεχάσετε! + + Τώρα, βεβαιωθείτε ότι το πλήκτρο Shift-Lock ΔΕΝ είναι πατημένο και + πατήστε το πλήκτρο j αρκετές φορές για να μετακινήσετε τον δρομέα έτσι + ώστε το Μάθημα 1.1 να γεμίσει πλήρως την οθόνη. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Μάθημα 1.1: ΜΕΤΑΚΙΝΟΝΤΑΣ ΤΟΝ ΔΡΟΜΕΑ + + ** Για να κινήσετε τον δρομέα, πατήστε τα πλήκτρα h,j,k,l όπως δείχνεται. ** + ^ + k Hint: Το πλήκτρο h είναι αριστερά και κινεί στ' αριστερά. + < h l > Το πλήκτρο l είναι δεξιά και κινεί στα δεξιά. + j Το πλήκτρο j μοιάζει με βελάκι προς τα κάτω. + v + + 1. Μετακινείστε τον δρομέα τριγύρω στην οθόνη μέχρι να νοιώθετε άνετα. + + 2. Κρατήστε πατημένο το κάτω πλήκτρο (j) μέχρι να επαναληφθεί. +---> Τώρα ξέρετε πώς να μετακινηθείτε στο επόμενο μάθημα. + + 3. Χρησιμοποιώντας το κάτω πλήκτρο, μετακινηθείτε στο Μάθημα 1.2. + +Σημείωση: Αν αμφιβάλλετε για κάτι που πατήσατε, πατήστε για να βρεθείτε + στην Κανονική Κατάσταση. Μετά πατήστε ξανά την εντολή που θέλατε. + +Σημείωση: Τα πλήκτρα του δρομέα θα πρέπει επίσης να δουλεύουν. Αλλά με τα hjkl + θα μπορείτε να κινηθείτε πολύ γρηγορότερα, μόλις τα συνηθίσετε. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Μάθημα 1.2: ΜΠΑΙΝΟΝΤΑΣ ΚΑΙ ΒΓΑΙΝΟΝΤΑΣ ΣΤΟΝ VIM + + !! ΣΗΜΕΙΩΣΗ: Πριν εκτελέσετε κάποιο από τα βήματα, διαβάστε όλο το μάθημα!! + + 1. Πατήστε το πλήκτρο (για να είστε σίγουρα στην Κανονική Κατάσταση). + + 2. Πληκτρολογήστε: :q! . + +---> Αυτό εξέρχεται από τον συντάκτη ΧΩΡΙΣ να σώσει όποιες αλλαγές έχετε κάνει. + Αν θέλετε να σώσετε τις αλλαγές και να εξέρθετε πληκτρολογήστε: + :wq + + 3. Όταν δείτε την προτροπή του φλοιού, πληκτρολογήστε την εντολή με την οποία + μπήκατε σε αυτήν την περιήγηση. Μπορεί να είναι: vimtutor + Κανονικά θα χρησιμοποιούσατε: vim tutor + +---> 'vim' σημαίνει εισαγωγή στον συντάκτη vim, 'tutor' είναι το αρχείο που + θέλουμε να διορθώσουμε. + + 4. Αν έχετε απομνημονεύσει αυτά τα βήματα και έχετε αυτοπεποίθηση, εκτελέστε + τα βήματα 1 έως 3 για να βγείτε και να μπείτε ξανά στον συντάκτη. Μετά + μετακινήστε τον δρομέα κάτω στο Μάθημα 1.3. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Μάθημα 1.3: ΔΙΟΡΘΩΣΗ ΚΕΙΜΕΝΟΥ - ΔΙΑΓΡΑΦΗ + + ** Όσο είστε στην Κανονική Κατάσταση πατήστε x για να διαγράψετε τον + χαρακτήρα κάτω από τον δρομέα. ** + + 1. Μετακινείστε τον δρομέα στην παρακάτω γραμμή σημειωμένη με --->. + + 2. Για να διορθώσετε τα λάθη, κινείστε τον δρομέα μέχρι να είναι πάνω από + τον χαρακτήρα που θα διαγραφεί. + + 3. Πατήστε το πλήκτρο x για να διαγράψετε τον ανεπιθύμητο χαρακτήρα. + + 4. Επαναλάβετε τα βήματα 2 μέχρι 4 μέχρι η πρόταση να είναι σωστή. + +---> The ccow jumpedd ovverr thhe mooon. + + 5. Τώρα που η γραμμή είναι σωστή, πηγαίντε στο Μάθημα 1.4. + +ΣΗΜΕΙΩΣΗ: Καθώς διατρέχετε αυτήν την περιήγηση, προσπαθήστε να μην + απομνημονεύετε, μαθαίνετε με τη χρήση. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Μάθημα 1.4: ΔΙΟΡΘΩΣΗ ΚΕΙΜΕΝΟΥ - ΠΑΡΕΜΒΟΛΗ + + ** Όσο είστε σε Κανονική Κατάσταση πατήστε i για να παρεμβάλλετε κείμενο. ** + + 1. Μετακινείστε τον δρομέα μέχρι την πρώτη γραμμή παρακάτω σημειωμένη με --->. + + 2. Για να κάνετε την πρώτη γραμμή ίδια με την δεύτερη, μετακινείστε τον + δρομέα πάνω στον πρώτο χαρακτήρα ΜΕΤΑ από όπου θα παρεμβληθεί το κείμενο. + + 3. Πατήστε το i και πληκτρολογήστε τις απαραίτητες προσθήκες. + + 4. Καθώς διορθώνετε κάθε λάθος πατήστε για να επιστρέψετε στην + Κανονική Κατάσταση. Επαναλάβετε τα βήματα 2 μέχρι 4 για να διορθώσετε + την πρόταση. + +---> There is text misng this . +---> There is some text missing from this line. + + 5. Όταν είστε άνετοι με την παρεμβολή κειμένου μετακινηθείτε στην + παρακάτω περίληψη. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ΜΑΘΗΜΑ 1 ΠΕΡΙΛΗΨΗ + + + 1. Ο δρομέας κινείται χρησιμοποιώντας είτε τα πλήκτρα δρομέα ή τα hjkl. + h (αριστέρα) j (κάτω) k (πάνω) l (δεξιά) + + 2. Για να μπείτε στον Vim (από την προτροπή %) γράψτε: vim ΑΡΧΕΙΟ + + 3. Για να βγείτε γράψτε: :q! για απόρριψη των αλλαγών. + Ή γράψτε: :wq για αποθήκευση των αλλαγών. + + 4. Για να διαγράψετε έναν χαρακτήρα κάτω από τον δρομέα σε + Κανονική Κατάσταση πατήστε: x + + 5. Για να εισάγετε κείμενο στον δρομέα όσο είστε σε Κανονική Κατάσταση γράψτε: + i πληκτρολογήστε το κείμενο + +ΣΗΜΕΙΩΣΗ: Πατώντας θα τοποθετηθείτε στην Κανονική Κατάσταση ή θα + ακυρώσετε μία ανεπιθύμητη και μερικώς ολοκληρωμένη εντολή. + +Τώρα συνεχίστε με το Μάθημα 2. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Μάθημα 2.1: ΕΝΤΟΛΕΣ ΔΙΑΓΡΑΦΗΣ + + ** Γράψτε dw για να διαγράψετε μέχρι το τέλος μίας λέξης. ** + + 1. Πατήστε για να βεβαιωθείτε ότι είστε στην Κανονική Κατάσταση. + + 2. Μετακινείστε τον δρομέα στην παρακάτω γραμμή σημειωμένη με --->. + + 3. Πηγαίνετε τον δρομέα στην αρχή της λέξης που πρέπει να διαγραφεί. + + 4. Γράψτε dw για να κάνετε την λέξη να εξαφανιστεί. + +ΣΗΜΕΙΩΣΗ: Τα γράμματα dw θα εμφανιστούν στην τελευταία γραμμή της οθόνης όσο + τα πληκτρολογείτε. Αν γράψατε κάτι λάθος, πατήστε και + ξεκινήστε από την αρχή. + +---> There are a some words fun that don't belong paper in this sentence. + + 5. Επαναλάβετε τα βήματα 3 και 4 μέχρι η πρόταση να είναι σωστή και + πηγαίνετε στο Μάθημα 2.2. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Μάθημα 2.2: ΠΕΡΙΣΣΟΤΕΡΕΣ ΕΝΤΟΛΕΣ ΔΙΑΓΡΑΦΗΣ + + ** Πληκτρολογήστε d$ για να διαγράψετε μέχρι το τέλος της γραμμής. ** + + 1. Πατήστε για να βεβαιωθείτε ότι είστε στην Κανονική Κατάσταση. + + 2. Μετακινείστε τον δρομέα στην παρακάτω γραμμή σημειωμένη με --->. + + 3. Μετακινείστε τον δρομέα στο τέλος της σωστής γραμμής (ΜΕΤΑ την πρώτη . ). + + 4. Πατήστε d$ για να διαγράψετε μέχρι το τέλος της γραμμής. + +---> Somebody typed the end of this line twice. end of this line twice. + + 5. Πηγαίνετε στο Μάθημα 2.3 για να καταλάβετε τι συμβαίνει. + + + + + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Μάθημα 2.3: ΠΕΡΙ ΕΝΤΟΛΩΝ ΚΑΙ ΑΝΤΙΚΕΙΜΕΝΩΝ + + +Η μορφή της εντολής διαγραφής d είναι ως εξής: + + [αριθμός] d αντικείμενο Ή d [αριθμός] αντικείμενο + Όπου: + αριθμός - πόσες φορές θα εκτελεστεί η εντολή (προαιρετικό, εξ' ορισμού=1). + d - η εντολή της διαγραφής. + αντικείμενο - πάνω σε τι θα λειτουργήσει η εντολή (παρακάτω λίστα). + + Μία μικρή λίστα από αντικείμενα: + w - από τον δρομέα μέχρι το τέλος της λέξης, περιλαμβάνοντας το διάστημα. + e - από τον δρομέα μέχρι το τέλος της λέξης, ΧΩΡΙΣ το διάστημα. + $ - από τον δρομέα μέχρι το τέλος της γραμμής. + +ΣΗΜΕΙΩΣΗ: Για τους τύπους της περιπέτειας, πατώντας απλώς το αντικείμενο όσο + είστε στην Κανονική Κατάσταση χωρίς κάποια εντολή θα μετακινήσετε + τον δρομέα όπως καθορίζεται στην λίστα αντικειμένων. + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Μάθημα 2.4: ΜΙΑ ΕΞΑΙΡΕΣΗ ΣΤΗΝ 'ΕΝΤΟΛΗ-ΑΝΤΙΚΕΙΜΕΝΟ' + + ** Πληκτρολογήστε dd για να διαγράψετε όλη τη γραμμή. ** + + Εξαιτίας της συχνότητας της διαγραφής ολόκληρης γραμμής, οι σχεδιαστές + του Vim αποφάσισαν ότι θα ήταν ευκολότερο να γράφετε απλώς δύο d στη + σειρά για να διαγράψετε μία γραμμή. + + 1. Μετακινείστε τον δρομέα στη δεύτερη γραμμή της παρακάτω φράσης. + 2. Γράψτε dd για να διαγράψετε τη γραμμή. + 3. Τώρα μετακινηθείτε στην τέταρτη γραμμή. + 4. Γράψτε 2dd (θυμηθείτε αριθμός-εντολή-αντικείμενο) για να + διαγράψετε δύο γραμμές. + + 1) Roses are red, + 2) Mud is fun, + 3) Violets are blue, + 4) I have a car, + 5) Clocks tell time, + 6) Sugar is sweet + 7) And so are you. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Μάθημα 2.5: Η ΕΝΤΟΛΗ ΑΝΑΙΡΕΣΗΣ + + ** Πατήστε u για να αναιρέσετε τις τελευταίες εντολές, + U για να διορθώσετε όλη τη γραμμή. ** + + 1. Μετακινείστε τον δρομέα στην παρακάτω γραμμή σημειωμένη με ---> και + τοποθετήστε τον πάνω στο πρώτο λάθος. + 2. Πατήστε x για να διαγράψετε τον πρώτο ανεπιθύμητο χαρακτήρα. + 3. Τώρα πατήστε u για να αναιρέσετε την τελευταία εκτελεσμένη εντολή. + 4. Αυτή τη φορά διορθώστε όλα τα λάθη στη γραμμή χρησιμοποιώντας την εντολή x. + 5. Τώρα πατήστε ένα κεφαλαίο U για να επιστρέψετε τη γραμμή στην αρχική + της κατάσταση. + 6. Τώρα πατήστε u μερικές φορές για να αναιρέσετε την U και + προηγούμενες εντολές. + 7. Τώρα πατήστε CTRL-R (κρατώντας πατημένο το πλήκτρο CTRL καθώς πατάτε το R) + μερικές φορές για να επαναφέρετε τις εντολές (αναίρεση των αναιρέσεων). + +---> Fiix the errors oon thhis line and reeplace them witth undo. + + 8. Αυτές είναι πολύ χρήσιμες εντολές. Τώρα πηγαίνετε στην + Περίληψη του Μαθήματος 2. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ΜΑΘΗΜΑ 2 ΠΕΡΙΛΗΨΗ + + + 1. Για να διαγράψετε από τον δρομέα μέχρι το τέλος λέξης γράψτε: dw + + 2. Για να διαγράψετε από τον δρομέα μέχρι το τέλος γραμμής γράψτε: d$ + + 3. Για να διαγράψετε ολόκληρη τη γραμμή γράψτε: dd + + 4. Η μορφή για μία εντολή στην Κανονική Κατάσταση είναι: + + [αριθμός] εντολή αντικείμενο Ή εντολή [αριθμός] αντικείμενο + όπου: + αριθμός - πόσες φορές να επαναληφθεί η εντολή + εντολή - τι να γίνει, όπως η d για διαγραφή + αντικείμενο - πάνω σε τι να ενεργήσει η εντολή, όπως w (λέξη), + $ (τέλος της γραμμής), κτλ. + + 5. Για να αναιρέσετε προηγούμενες ενέργειες, πατήστε: u (πεζό u) + Για να αναιρέσετε όλες τις αλλαγές στη γραμμή, πατήστε: U (κεφαλαίο U) + Για να αναιρέσετε τις αναιρέσεις, πατήστε: CTRL-R + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Μάθημα 3.1: Η ΕΝΤΟΛΗ ΤΟΠΟΘΕΤΗΣΗΣ + + + ** Πατήστε p για να τοποθετήσετε την τελευταία διαγραφή μετά τον δρομέα. ** + + 1. Μετακινείστε τον δρομέα στην πρώτη γραμμή της παρακάτω ομάδας. + + 2. Πατήστε dd για να διαγράψετε τη γραμμή και να την αποθηκεύσετε σε + προσωρινή μνήμη του Vim. + + 3. Μετακινείστε τον δρομέα στη γραμμή ΠΑΝΩ από εκεί που θα πρέπει να πάει + η διαγραμμένη γραμμή. + + 4. Όσο είστε σε Κανονική Κατάσταση, πατήστε p για να βάλετε τη γραμμή. + + 5. Επαναλάβετε τα βήματα 2 έως 4 για να βάλετε όλες τις γραμμές στη + σωστή σειρά. + + d) Can you learn too? + b) Violets are blue, + c) Intelligence is learned, + a) Roses are red, + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Μάθημα 3.2: Η ΕΝΤΟΛΗ ΑΝΤΙΚΑΤΑΣΤΑΣΗΣ + + + ** Πατήστε r και χαρακτήρα για να αλλάξετε αυτόν που είναι + κάτω από τον δρομέα. ** + + 1. Μετακινείστε τον δρομέα στην πρώτη γραμμή παρακάτω σημειωμένη με --->. + + 2. Μετακινείστε τον δρομέα έτσι ώστε να είναι πάνω στο πρώτο λάθος. + + 3. Πατήστε r και μετά τον χαρακτήρα ο οποίος διορθώνει το λάθος. + + 4. Επαναλάβετε τα βήματα 2 και 3 μέχρι να είναι σωστή η πρώτη γραμμή. + +---> Whan this lime was tuoed in, someone presswd some wrojg keys! +---> When this line was typed in, someone pressed some wrong keys! + + 5. Τώρα πηγαίνετε στο Μάθημα 3.2. + +ΣΗΜΕΙΩΣΗ: Να θυμάστε ότι πρέπει να μαθαίνετε με τη χρήση, και όχι με + την απομνημόνευση. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Μάθημα 3.3: Η ΕΝΤΟΛΗ ΑΛΛΑΓΗΣ + + ** Για να αλλάξετε τμήμα ή όλη τη λέξη, πατήστε cw . ** + + 1. Μετακινείστε τον δρομέα στην πρώτη γραμμή παρακάτω σημειωμένη με --->. + + 2. Τοποθετήστε τον δρομέα πάνω στο u της λέξης lubw. + + 3. Πατήστε cw και τη σωστή λέξη (στην περίπτωση αυτή, γράψτε 'ine'.) + + 4. Πατήστε και πηγαίνετε στο επόμενο λάθος (στον πρώτο + χαρακτήρα προς αλλαγή). + + 5. Επαναλάβετε τα βήματα 3 και 4 μέχρις ότου η πρώτη πρόταση να είναι + ίδια με τη δεύτερη. + +---> This lubw has a few wptfd that mrrf changing usf the change command. +---> This line has a few words that need changing using the change command. + +Παρατηρείστε ότι η cw όχι μόνο αντικαθιστάει τη λέξη, αλλά σας εισάγει +επίσης σε παρεμβολή. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Μάθημα 3.4: ΠΕΡΙΣΣΟΤΕΡΕΣ ΑΛΛΑΓΕΣ ΜΕ c + + + ** Η εντολή αλλαγής χρησιμοποιείται με τα ίδια αντικείμενα της διαγραφής. ** + + + 1. Η εντολή αλλαγής δουλεύει με τον ίδιο τρόπο όπως η διαγραφή. Η μορφή είναι: + + [αριθμός] c αντικείμενο Ή c [αριθμός] αντικείμενο + + 2. Τα αντικείμενα είναι πάλι τα ίδια, όπως w (λέξη), $ (τέλος γραμμής), κτλ. + + 3. Μετακινηθείτε στην πρώτη γραμμή παρακάτω σημειωμένη με --->. + + 4. Μετακινείστε τον δρομέα στο πρώτο λάθος. + + 5. Γράψτε c$ για να κάνετε το υπόλοιπο της γραμμής ίδιο με τη δεύτερη + και πατήστε . + +---> The end of this line needs some help to make it like the second. +---> The end of this line needs to be corrected using the c$ command. + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ΜΑΘΗΜΑ 3 ΠΕΡΙΛΗΨΗ + + + 1. Για να τοποθετήσετε κείμενο που μόλις έχει διαγραφεί, πατήστε p . + Αυτό τοποθετεί το διαγραμμένο κείμενο ΜΕΤΑ τον δρομέα (αν διαγράφτηκε + γραμμή θα πάει μετά στη γραμμή κάτω από τον δρομέα. + + 2. Για να αντικαταστήσετε τον χαρακτήρα κάτω από τον δρομέα, πατήστε r + και μετά τον χαρακτήρα που θα αντικαταστήσει τον αρχικό. + + 3. Η εντολή αλλαγής σας επιτρέπει να αλλάξετε το καθορισμένο αντικείμενο + από τον δρομέα μέχρι το τέλος του αντικείμενο. Π.χ. γράψτε cw για να + αλλάξετε από τον δρομέα μέχρι το τέλος της λέξης, c$ για να αλλάξετε + μέχρι το τέλος γραμμής. + + 4. Η μορφή για την αλλαγή είναι: + + [αριθμός] c αντικείμενο Ή c [αριθμός] αντικείμενο + +Τώρα συνεχίστε με το επόμενο μάθημα. + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Μάθημα 4.1: ΘΕΣΗ ΚΑΙ ΚΑΤΑΣΤΑΣΗ ΑΡΧΕΙΟΥ + + + ** Πατήστε CTRL-g για να εμφανιστεί η θέση σας στο αρχείο και η κατάστασή του. + Πατήστε SHIFT-G για να πάτε σε μία γραμμή στο αρχείο. ** + + Σημείωση: Διαβάστε ολόκληρο το μάθημα πριν εκτελέσετε κάποιο από τα βήματα!! + + 1. Κρατήστε πατημένο το πλήκτρο Ctrl και πατήστε g . Μία γραμμή κατάστασης + θα εμφανιστεί στο κάτω μέρος της σελίδας με το όνομα αρχείου και τη + γραμμή που είστε. Θυμηθείτε τον αριθμό γραμμής για το Βήμα 3. + + 2. Πατήστε shift-G για να μετακινηθείτε στο τέλος του αρχείου. + + 3. Πατήστε τον αριθμό της γραμμής που ήσασταν και μετά shift-G. Αυτό θα + σας επιστρέψει στη γραμμή που ήσασταν πριν πατήσετε για πρώτη φορά Ctrl-g. + (Όταν πληκτρολογείτε τους αριθμούς, ΔΕΝ θα εμφανίζονται στην οθόνη). + + 4. Αν νοιώθετε σίγουρος για αυτό, εκτελέστε τα βήματα 1 έως 3. + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Μάθημα 4.2: Η ΕΝΤΟΛΗ ΑΝΑΖΗΤΗΣΗΣ + + + ** Πατήστε / ακολουθούμενο από τη φράση που ψάχνετε. ** + + 1. Σε Κανονική Κατάσταση πατήστε τον χαρακτήρα / . Παρατηρήστε ότι αυτός και + ο δρομέας εμφανίζονται στο κάτω μέρος της οθόνης όπως με την εντολή : . + + 2. Τώρα γράψτε 'errroor' . Αυτή είναι η λέξη που θέλετε να ψάξετε. + + 3. Για να ψάξετε ξανά για την ίδια φράση, πατήστε απλώς n . + Για να ψάξετε την ίδια φράση στην αντίθετη κατεύθυνση, πατήστε Shift-N . + + 4. Αν θέλετε να ψάξετε για μία φράση προς τα πίσω, χρησιμοποιήστε την εντολή ? αντί της / . + +---> Όταν η αναζήτηση φτάσει στο τέλος του αρχείου θα συνεχίσει από την αρχή. + + "errroor" is not the way to spell error; errroor is an error. + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Μάθημα 4.3: ΕΥΡΕΣΗ ΤΑΙΡΙΑΣΤΩΝ ΠΑΡΕΝΘΕΣΕΩΝ + + + ** Πατήστε % για να βρείτε την αντίστοιχη ), ], ή } . ** + + 1. Τοποθετήστε τον δρομέα σε κάποια (, [, ή { στην παρακάτω γραμμή + σημειωμένη με --->. + + 2. Τώρα πατήστε τον χαρακτήρα % . + + 3. Ο δρομέας θα πρέπει να είναι στην αντίστοιχη παρένθεση ή αγκύλη. + + 4. Πατήστε % για να μετακινήσετε τον δρομέα πίσω στην πρώτη αγκύλη + (του ζευγαριού). + +---> This ( is a test line with ('s, ['s ] and {'s } in it. )) + +ΣΗΜΕΙΩΣΗ: Αυτό είναι πολύ χρήσιμο στην αποσφαλμάτωση ενός προγράμματος + με μη ταιριαστές παρενθέσεις! + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Μάθημα 4.4: ΕΝΑΣ ΤΡΟΠΟΣ ΓΙΑ ΑΛΛΑΓΗ ΛΑΘΩΝ + + + ** Γράψτε :s/old/new/g για να αλλάξετε το 'new' με το 'old'. ** + + 1. Μετακινείστε τον δρομέα στην παρακάτω γραμμή σημειωμένη με --->. + + 2. Γράψτε :s/thee/the . Σημειώστε ότι αυτή η εντολή αλλάζει μόνο + την πρώτη εμφάνιση στη γραμμή. + + 3. Τώρα γράψτε :s/thee/the/g εννοώντας γενική αντικατάσταση στη + γραμμή. Αυτό αλλάζει όλες τις εμφανίσεις επί της γραμμής. + +---> thee best time to see thee flowers is in thee spring. + + 4. Για να αλλάξετε κάθε εμφάνιση μίας συμβολοσειράς μεταξύ δύο γραμμών, + γράψτε :#,#s/old/new/g όπου #,# οι αριθμοί των δύο γραμμών. + Γράψτε :%s/old/new/g για να αλλάξετε κάθε εμφάνιση σε όλο το αρχείο. + + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ΜΑΘΗΜΑ 4 ΠΕΡΙΛΗΨΗ + + + 1. Το Ctrl-g εμφανίζει τη θέση σας στο αρχείο και την κατάστασή του. + Το Shift-G πηγαίνει στο τέλος του αρχείου. Ένας αριθμός γραμμής + ακολουθούμενος από Shift-G πηγαίνει σε εκείνη τη γραμμή. + + 2. Γράφοντας / ακολουθούμενο από μία φράση ψάχνει προς τα ΜΠΡΟΣΤΑ για + τη φράση. Γράφοντας ? ακολουθούμενο από μία φράση ψάχνει προς τα ΠΙΣΩ + για τη φράση. Μετά από μία αναζήτηση πατήστε n για να βρείτε την + επόμενη εμφάνιση προς την ίδια κατεύθυνση ή Shift-N για να ψάξετε + προς την αντίθετη κατεύθυνση. + + 3. Πατώντας % όσο ο δρομέας είναι πάνω σε μία (,),[,],{, ή } εντοπίζει + το αντίστοιχο ταίρι του ζευγαριού. + + 4. Για αντικατάσταση με new του πρώτου old στη γραμμή γράψτε :s/old/new + Για αντικατάσταση με new όλων των 'old' στη γραμμή γράψτε :s/old/new/g + Για αντικατάσταση φράσεων μεταξύ δύο # γραμμών γράψτε :#,#s/old/new/g + Για αντικατάσταση όλων των εμφανίσεων στο αρχείο γράψτε :%s/old/new/g + Για ερώτηση επιβεβαίωσης κάθε φορά προσθέστε ένα 'c' "%s/old/new/gc + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Μάθημα 5.1: ΠΩΣ ΕΚΤΕΛΩ ΜΙΑ ΕΞΩΤΕΡΙΚΗ ΕΝΤΟΛΗ + + +** Γράψτε :! ακολουθούμενο από μία εξωτερική εντολή για να την εκτελέσετε. ** + + 1. Πατήστε την οικεία εντολή : για να θέσετε τον δρομέα στο κάτω μέρος + της οθόνης. Αυτό σας επιτρέπει να δώσετε μία εντολή. + + 2. Τώρα πατήστε το ! (θαυμαστικό). Αυτό σας επιτρέπει να εκτελέσετε + οποιαδήποτε εξωτερική εντολή του φλοιού. + + 3. Σαν παράδειγμα γράψτε ls μετά από το ! και πατήστε . Αυτό θα + σας εμφανίσει μία λίστα του καταλόγου σας, ακριβώς σαν να ήσασταν στην + προτροπή του φλοιού. Ή χρησιμοποιήστε :!dir αν το ls δεν δουλεύει. + +---> Σημείωση: Είναι δυνατόν να εκτελέσετε οποιαδήποτε εξωτερική εντολή + με αυτόν τον τρόπο. + +---> Σημείωση: Όλες οι εντολές : πρέπει να τερματίζονται πατώντας το . + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Μάθημα 5.2: ΠΕΡΙΣΣΟΤΕΡΑ ΠΕΡΙ ΕΓΓΡΑΦΗΣ ΑΡΧΕΙΩΝ + + + ** Για να σώσετε τις αλλάγες που κάνατε στο αρχείο, γράψτε :w ΑΡΧΕΙΟ. ** + + 1. Γράψτε :!dir ή :!ls για να πάρετε μία λίστα του καταλόγου σας. + Ήδη ξέρετε ότι πρέπει να πατήσετε μετά από αυτό. + + 2. Διαλέξτε ένα όνομα αρχείου που δεν υπάρχει ακόμα, όπως το TEST. + + 3. Τώρα γράψτε: :w TEST (όπου TEST είναι το όνομα αρχείου που διαλέξατε). + + 4. Αυτό σώζει όλο το αρχείο (vim Tutor) με το όνομα TEST. Για να το + επαληθεύσετε, γράψτε ξανά :!dir για να δείτε τον κατάλογό σας. + +---> Σημειώστε ότι αν βγαίνατε από τον Vim και μπαίνατε ξανά με το όνομα + αρχείου TEST, το αρχείο θα ήταν ακριβές αντίγραφο του tutor όταν το σώσατε. + + 5. Τώρα διαγράψτε το αρχείο γράφοντας (MS-DOS): :!del TEST + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Μάθημα 5.3: ΕΠΙΛΕΚΤΙΚΗ ΕΝΤΟΛΗ ΕΓΓΡΑΦΗΣ + + + ** Για να σώσετε τμήμα του αρχείου, γράψτε :#,# w ΑΡΧΕΙΟ ** + + 1. Άλλη μια φορά, γράψτε :!dir ή :!ls για να πάρετε μία λίστα από τον + κατάλογό σας και διαλέξτε ένα κατάλληλο όνομα αρχείου όπως το TEST. + + 2. Μετακινείστε τον δρομέα στο πάνω μέρος αυτής της σελίδας και πατήστε + Ctrl-g για να βρείτε τον αριθμό αυτής της γραμμής. + ΝΑ ΘΥΜΑΣΤΕ ΑΥΤΟΝ ΤΟΝ ΑΡΙΘΜΟ! + + 3. Τώρα πηγαίνετε στο κάτω μέρος της σελίδας και πατήστε Ctrl-g ξανά. + ΝΑ ΘΥΜΑΣΤΕ ΚΑΙ ΑΥΤΟΝ ΤΟΝ ΑΡΙΘΜΟ! + + 4. Για να σώσετε ΜΟΝΟ ένα τμήμα σε αρχείο, γράψτε :#,# w TEST + όπου #,# οι δύο αριθμοί που απομνημονεύσατε (πάνω,κάτω) και TEST το + όνομα του αρχείου σας. + + 5. Ξανά, δείτε ότι το αρχείο είναι εκεί με την :!dir αλλά ΜΗΝ το διαγράψετε. + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Μάθημα 5.4: ΑΝΑΚΤΩΝΤΑΣ ΚΑΙ ΕΝΩΝΟΝΤΑΣ ΑΡΧΕΙΑ + + + ** Για να εισάγετε τα περιεχόμενα ενός αρχείου, γράψτε :r ΑΡΧΕΙΟ ** + + 1. Γράψτε :!dir για να βεβαιωθείτε ότι το TEST υπάρχει από πριν. + + 2. Τοποθετήστε τον δρομέα στο πάνω μέρος της σελίδας. + +ΣΗΜΕΙΩΣΗ: Αφότου εκτελέσετε το Βήμα 3 θα δείτε το Μάθημα 5.3. + Μετά κινηθείτε ΚΑΤΩ ξανά προς το μάθημα αυτό. + + 3. Τώρα ανακτήστε το αρχείο σας TEST χρησιμοποιώντας την εντολή :r TEST + όπου TEST είναι το όνομα του αρχείου. + +ΣΗΜΕΙΩΣΗ: Το αρχείο που ανακτάτε τοποθετείται ξεκινώντας εκεί που βρίσκεται + ο δρομέας. + + 4. Για να επαληθεύσετε ότι το αρχείο ανακτήθηκε, πίσω τον δρομέα και + παρατηρήστε ότι υπάρχουν τώρα δύο αντίγραφα του Μαθήματος 5.3, το + αρχικό και η έκδοση του αρχείου. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ΜΑΘΗΜΑ 5 ΠΕΡΙΛΗΨΗ + + + 1. :!εντολή εκτελεί μία εξωτερική εντολή. + + Μερικά χρήσιμα παραδείγματα είναι (MS-DOS): + :!dir - εμφάνιση λίστας ενός καταλόγου. + :!del ΑΡΧΕΙΟ - διαγράφει το ΑΡΧΕΙΟ. + + 2. :w ΑΡΧΕΙΟ γράφει το τρέχων αρχείο του Vim στο δίσκο με όνομα ΑΡΧΕΙΟ. + + 3. :#,#w ΑΡΧΕΙΟ σώζει τις γραμμές από # μέχρι # στο ΑΡΧΕΙΟ. + + 4. :r ΑΡΧΕΙΟ ανακτεί το αρχείο δίσκου ΑΡΧΕΙΟ και το παρεμβάλλει μέσα + στο τρέχον αρχείο μετά από τη θέση του δρομέα. + + + + + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Μάθημα 6.1: Η ΕΝΤΟΛΗ ΑΝΟΙΓΜΑΤΟΣ + + + ** Πατήστε o για να ανοίξετε μία γραμμή κάτω από τον δρομέα και να + βρεθείτε σε Κατάσταση Κειμένου. ** + + 1. Μετακινείστε τον δρομέα στην παρακάτω γραμμή σημειωμένη με --->. + + 2. Πατήστε o (πεζό) για να ανοίξετε μία γραμμή ΚΑΤΩ από τον δρομέα και να + βρεθείτε σε Κατάσταση Κειμένου. + + 3. Τώρα αντιγράψτε τη σημειωμένη με ---> γραμμή και πατήστε για να + βγείτε από την Κατάσταση Κειμένου. + +---> After typing o the cursor is placed on the open line in Insert mode. + + 4. Για να ανοίξετε μία γραμμή ΠΑΝΩ από τον δρομέα, πατήστε απλά ένα κεφαλαίο + O, αντί για ένα πεζό o. Δοκιμάστε το στην παρακάτω γραμμή. +Ανοίγετε γραμμή πάνω από αυτήν πατώντας Shift-O όσο ο δρομέας είναι στη γραμμή + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Μάθημα 6.2: Η ΕΝΤΟΛΗ ΠΡΟΣΘΗΚΗΣ + + ** Πατήστε a για να εισάγετε κείμενο ΜΕΤΑ τον δρομέα. ** + + 1. Μετακινείστε τον δρομέα στο τέλος της πρώτης γραμμής παρακάτω + σημειωμένη με ---> πατώντας $ στην Κανονική Κατάσταση. + + 2. Πατήστε ένα a (πεζό) για να προσθέσετε κείμενο ΜΕΤΑ από τον χαρακτήρα + που είναι κάτω από τον δρομέα. (Το κεφαλαίο A προσθέτει στο τέλος + της γραμμής). + +Σημείωση: Αυτό αποφεύγει το πάτημα του i , τον τελευταίο χαρακτήρα, το + κείμενο της εισαγωγής, , δρομέα-δεξιά, και τέλος, x, μόνο και + μόνο για να προσθέσετε στο τέλος της γραμμής! + + 3. Συμπληρώστε τώρα την πρώτη γραμμή. Σημειώστε επίσης ότι η προσθήκη είναι + ακριβώς ίδια στην Κατάσταση Κειμένου με την Κατάσταση Εισαγωγής, εκτός + από τη θέση που εισάγεται το κείμενο. + +---> This line will allow you to practice +---> This line will allow you to practice appending text to the end of a line. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Μάθημα 6.3: ΑΛΛΗ ΕΚΔΟΣΗ ΤΗΣ ΑΝΤΙΚΑΤΑΣΤΑΣΗΣ + + + ** Πατήστε κεφαλαίο R για να αλλάξετε περισσότερους από έναν χαρακτήρες. ** + + 1. Μετακινείστε τον δρομέα στην πρώτη γραμμή παρακάτω σημειωμένη με --->. + + 2. Τοποθετήστε τον δρομέα στην αρχή της πρώτης λέξης που είναι διαφορετική + από τη δεύτερη γραμμή σημειωμένη με ---> (η λέξη 'last'). + + 3. Πατήστε τώρα R και αλλάξτε το υπόλοιπο του κειμένου στην πρώτη γραμμή + γράφοντας πάνω από το παλιό κείμενο ώστε να κάνετε την πρώτη γραμμή ίδια + με τη δεύτερη. + +---> To make the first line the same as the last on this page use the keys. +---> To make the first line the same as the second, type R and the new text. + + 4. Σημειώστε ότι όταν πατάτε για να βγείτε, παραμένει οποιοδήποτε + αναλλοίωτο κείμενο. + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Μάθημα 6.4: ΡΥΘΜΙΣΗ ΕΠΙΛΟΓΗΣ + + + ** Ρυθμίστε μία επιλογή έτσι ώστε η αναζήτηση ή η αντικατάσταση να αγνοεί + τη διαφορά πεζών-κεφαλαίων ** + + 1. Ψάξτε για 'ignore' εισάγοντας: + /ignore + Συνεχίστε αρκετές φορές πατώντας το πλήκτρο n. + + 2. Θέστε την επιλογή 'ic' (Ignore case) γράφοντας: + :set ic + + 3. Ψάξτε τώρα ξανά για 'ignore' πατώντας: n + Συνεχίστε την αναζήτηση μερικές ακόμα φορές πατώντας το πλήκτρο n + + 4. Θέστε τις επιλογές 'hlsearch' και 'incsearch': + :set hls is + + 5. Εισάγετε τώρα ξανά την εντολή αναζήτησης, και δείτε τι συμβαίνει + /ignore + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ΜΑΘΗΜΑ 6 ΠΕΡΙΛΗΨΗ + + + 1. Πατώντας o ανοίγει μία γραμμή ΚΑΤΩ από τον δρομέα και τοποθετεί τον + δρομέα στην ανοιχτή γραμμή σε Κατάσταση Κειμένου. + + 2. Πατήστε a για να εισάγετε κείμενο ΜΕΤΑ τον χαρακτήρα στον οποίο είναι + ο δρομέας. Πατώντας κεφαλαίο A αυτόματα προσθέτει κείμενο στο τέλος + της γραμμής. + + 3. Πατώντας κεφαλαίο R εισέρχεται στην Κατάσταη Αντικατάστασης μέχρι να + πατηθεί το και να εξέλθει. + + 4. Γράφοντας ":set xxx" ρυθμίζει την επιλογή "xxx". + + + + + + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ΜΑΘΗΜΑ 7: ON-LINE ΕΝΤΟΛΕΣ ΒΟΗΘΕΙΑΣ + + + ** Χρησιμοποιήστε το on-line σύστημα βοήθειας ** + + Ο Vim έχει ένα περιεκτικό on-line σύστημα βοήθειας. Για να ξεκινήσει, + δοκιμάστε κάποιο από τα τρία: + - πατήστε το πλήκτρο (αν έχετε κάποιο) + - πατήστε το πλήκτρο (αν έχετε κάποιο) + - γράψτε :help + + Γράψτε :q για να κλείσετε το παράθυρο της βοήθειας. + + Μπορείτε να βρείτε βοήθεια πάνω σε κάθε αντικείμενο, δίνοντας μία παράμετρο + στην εντολή ":help". Δοκιμάστε αυτά (μην ξεχνάτε να πατάτε ): + + :help w + :help c_ Клавиша l находится справа и перемещает вправо. + j Клавиша j похожа на стрелку `вниз'. + v + 1. Подвигайте курсор по экрану, пока не почувствуете себя уверенно. + + 2. Надавите клавишу `вниз' (j) пока она не начнет повторяться. +---> Теперь Вы знаете, как перейти к следующему уроку. + + 3. Используя клавишу `вниз' перейдите к Уроку 1.2. + +Замечание: Если вы пока не уверены в том, что набираете, нажмите для + перехода в обычный режим (Normal mode). После этого перенаберите + требуемую команду. + +Замечание: Обычные клавиши управления курсором (стрелки) также должны + работать. Однако, клавиши hjkl позволят Вам перемещаться + значительно быстрее, как только Вы научитесь ими пользоваться. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Урок 1.2: ЗАПУСК И ЗАВЕРШЕНИЕ РАБОТЫ С VIM + +!! ВНИМАНИЕ! Прежде, чем выполнять любой из описанных ниже шагов, прочтите + урок целиком !! + + 1. Нажмите клавишу (для того, чтобы удостовериться, что Вы в обычном + режиме (Normal mode)). + + 2. Наберите: :q! . + +---> Это позволит Вам выйти из редактора БЕЗ СОХРАНЕНИЯ любых сделанных + изменений. Если Вы хотите сохранить изменения и выйти: + :wq + + 3. Когда Вы увидите приглашение командной оболочки, наберите команду, + которая привела Вас в этот учебник. Это может быть + vimtutor ru + Обычно можно использовать: vim tutor.ru + +---> 'vim' позволяет запустить редактор vim, 'tutor.ru' --- это файл, который + Вы будете редактировать. + + 4. Если Вы уверены в том, что запомнили эти шаги, выполните шаги от 1 до 3 + чтобы выйти снова запустить редактор. Затем переместите курсор вниз к + Уроку 1.3. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Урок 1.3: РЕДАКТИРОВАНИЕ ТЕКСТА - УДАЛЕНИЕ + + +** Находясь в обычном режиме нажмите x, чтобы удалить символ под курсором. ** + + 1. Переместите курсор к строке внизу, помеченной --->. + + 2. Для исправления ошибок, переместите курсор, пока он не окажется над + удаляемым символом. + + 3. Нажмите клавишу x для удаления требуемого символа. + + 4. Повторите шаги 2--4 пока строка не будет исправлена. + +---> От тттопота копытт пппыль ппо ппполю леттитт. + + 5. Теперь, когда строка откорректирована, переходите к уроку 1.4. + +ЗАМЕЧАНИЕ: В ходе освоения этого учебника не пытайтесь запоминать, учите + в процессе использования. + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Урок 1.4: РЕДАКТИРОВАНИЕ ТЕКСТА - ВСТАВКА + + + ** Находясь в обычном режиме (Normal mode), нажмите i для вставки текста. ** + + 1. Переместите курсор к первой строке внизу, помеченной --->. + + 2. Для того, чтобы сделать первую строку идентичной второй, поместите + курсор на символ ПЕРЕД которым следует вставить текст. + + 3. Нажмите i и наберите требуемые добавления. + + 4. После исправления всех ошибок нажмите для возврата в обычный режим. + Повторите шаги 2--4, пока фраза не будет исправлена полностью. + +---> Часть текста в строке беследно . +---> Часть текста в этой строке бесследно пропала. + + 5. Когда освоите вставку текста, переходите дальше к Резюме. + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + РЕЗЮМЕ УРОКА 1 + + 1. Курсор перемещается либо клавишами со стрелками, либо клавишами hjkl. + h (влево) j (вниз) k (вверх) l (вправо) + + 2. Для запуска Vim (из приглашения % командной оболочки) наберите: + vim ИМЯ_ФАЙЛА + + 3. Для завершения работы с Vim наберите: + :q! чтобы отказаться от сохранения изменений. + Или наберите: + :wq чтобы сохранить изменения. + + 4. Для удаления символа под курсором в обычном режиме, наберите: x + + 5. Чтобы вставить текст перед курсором в обычном режиме, наберите: + i вводите текст + +ЗАМЕЧАНИЕ: Нажатие переместит Вас в обычный режим (Normal mode) либо + прервет нежелательную и частично завершенную команду. + +Теперь переходим к Уроку 2. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Урок 2.1: КОМАНДЫ УДАЛЕНИЯ + + + ** Наберите dw для удаления участка текста до конца слова. ** + + 1. Нажмите , чтобы перейти в обычный режим. + + 2. Переместите курсор вниз, к строке, помеченной --->. + + 3. Переместите курсор в начало слова, которое следует удалить. + + 4. Наберите dw , чтобы удалить это слово. + +ЗАМЕЧАНИЕ: Во время набора буквы dw появятся в последней строке экрана. Если + Вы что-то наберете неправильно, нажмите и начните сначала. + +---> Несколько слов рафинад в этом предложении автокран излишни. + + 5. Повторите шаги 3 и 4, пока не исправите все ошибки и переходите к + Уроку 2.2. + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Урок 2.2: ДОПОЛНИТЕЛЬНЫЕ КОМАНДЫ УДАЛЕНИЯ + + + ** Наберите d$ для удаления текста до конца строки. ** + + 1. Нажмите , чтобы перейти в обычный режим. + + 2. Переместите курсор вниз, к строке, помеченной --->. + + 3. Переместите курсор к концу правильной строки (ПОСЛЕ первой . ). + + 4. Чтобы удалить остаток строки, наберите d$ . + +---> Кто-то набрал окончание этой строки дважды. окончание этой строки дважды. + + + 5.Чтобы лучше разобраться в этом, переходите к Уроку 2.3. + + + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Урок 2.3: КОМАНДЫ И ОБЪЕКТЫ + + + Формат команды `удаление' d таков: + + [число] d объект ИЛИ d [число] объект + Здесь: + число - сколько раз исполнить команду (необязательно, по умолчанию=1). + d - команда удаления. + объект - с чем команда должна быть выполнена (перечислено ниже). + + Краткий список объектов: + w - от курсора до конца слова, включая завершающий пробел. + e - от курсора до конца слова, НЕ включая завершающий пробел. + $ - от курсора до конца строки. + ^ - от курсора до начала строки. + +ЗАМЕЧАНИЕ: Простое нажатие на символ объекта в обычном режиме (Normal mode) + без дополнительных команд передвинет курсор так, как указано в + списке объектов. + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Урок 2.4: ИСКЛЮЧЕНИЕ ИЗ ПРАВИЛА `КОМАНДА-ОБЪЕКТ' + + + ** Наберите dd для удаления всей строки. ** + + Вследствие частого применения операции удаления всей строки, разработчики + Vim решили, что для этого проще всего просто набрать d дважды. + + 1. Переместите курсор вниз, ко второй строке фразы. + 2. Наберите dd для удаления строки. + 3. Теперь переместитесь к четвертой строке. + 4. Наберите 2dd (вспомните правило `число-команда-объект'), чтобы удалить + две строки. + + 1) Летом я хожу на стадион, + 2) О, как внезапно кончился диван! + 3) Я болею за ``Зенит'', ``Зенит'' --- чемпион! + 4) Печально я гляжу на наше поколение! + 5) Его грядущее иль пусто иль темно... + 6) Я сижу на скамейке в ложе `Б' + 7) И играю на большой жестяной трубе. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Урок 2.5: КОМАНДА `ОТКАТ' + + + ** Нажмите u для отмены результата работы предыдущей команды, U для отмены + исправлений во всей строке. ** + + 1. Переместите курсор вниз, к строке, помеченной ---> и установите его на + первую ошибку. + 2. Нажмите x для удаления первого неправильного символа. + 3. Теперь нажмите u для отмены (отката) последней выполненной команды. + 4. Исправьте все ошибки в строке, используя команду x . + 5. Теперь нажмите заглавную U для того, чтобы вернуть всю строку в исходное + состояние. + 6. Нажмите u несколько раз для отмены команды U и предыдущих команд. + 7. Нажмите теперь CTRL-R (удерживайте клавишу CTRL нажатой в момент нажатия + R) несколько раз для возврата команд (откат отката). + +---> Испрравьте оошибки в этойй строке и вернитте их сс помощьью `отката'. + + 8. Это были очень полезные команды. Далее переходите к Резюме Урока 2. + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + РЕЗЮМЕ УРОКА 2 + + + 1. Для удаления текста от курсора до конца слова наберите: dw + + 2. Для удаления текста от курсора до конца строки наберите: d$ + + 3. Для удаления всей строки наберите: dd + + 4. Формат команды в обычном режиме имеет вид: + + [число] команда объект ИЛИ команда [число] объект + где: + число - сколько раз повторить выполнение команды + команда - что выполнить, например d для удаления + объект - на что должна воздействовать команда, например w (слово), + $ (до конца строки), и т.д. + + 5. Для отмены (отката) предшествующих действий наберите: u (строчная u) + Для отмены (отката) всех изменений в строке наберите: U (прописная U) + Для отмены отката наберите: CTRL-R + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Урок 3.1: КОМАНДА ВСТАВКИ + + + ** Наберите p для вставки последнего удаленного текста после курсора. ** + + 1. Переместите курсор вниз к последней строке из набора. + + 2. Наберите dd для удаления строки и ее сохранения в буфере Vim'а. + + 3. Переместите курсор к строке НАД тем местом, куда следует вставить + удаленную строку. + + 4. Находясь в обычном режиме наберите p для замены строки. + + 5. Повторите шаги 2--4, пока не расставите все строки в нужном порядке. + + г) И лучше выдумать не мог. + б) Когда не в шутку занемог, + в) Он уважать себя заставил + а) Мой дядя самых честных правил + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Урок 3.2: КОМАНДА ЗАМЕНЫ + + + ** Наберите r и символ, заменяющий символ под курсором. ** + + 1. Переместите курсор вниз, к строке, помеченной --->. + + 2. Установите курсор так, чтобы он находился над первой ошибкой. + + 3. Наберите r и затем символ, исправляющий ошибку. + + 4. Повторите шаги 2 и 3, пока первая строка не будет исправлена. + +---> В момегт набтра этой чтроки кое0кто с трудом попвдал по клваишам! +---> В момент набора этой строки кое-кто с трудом попадал по клавишам! + + 5. Теперь переходите к Уроку 3.2. + +ЗАМЕЧАНИЕ: Помните, что вы должны учиться в процессе работы, а не просто + запоминая. + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Урок 3.3: КОМАНДА ИЗМЕНЕНИЯ + + + ** Для изменения части слова наберите cw . ** + + 1. Переместите курсор вниз, к строке, помеченной --->. + + 2. Расположите курсор над буквой `o' в слове `сола'. + + 3. Наберите cw и исправьте слово (в данном случае, наберите `лов'.) + + 4. Нажмите и переходите к следующей ошибке (к первому символу, который + надо изменить.) + + 5. Повторите шаги 3--4 пока первое предложение не станет идентичным второму. + +---> Несколько сола в эьгц строке тпгшцбь редалзкуюиесвх. +---> Несколько слов в этой строке требуют редактирования. + +Обратите внимание, что cw не только заменяет слово, но и переводит вас в режим +вставки. + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Урок 3.4: ПРОДОЛЖАЕМ ИЗМЕНЯТЬ С КОМАНДОЙ c + + +** Команда замены используется с теми же объектами, что и команда удаления. ** + + 1. Команда изменения применяется таким же образом, как и команда удаления. + Ее формат таков: + + [число] c объект ИЛИ c [число] объект + + 2. Объекты также совпадают: w (слово), $ (конец строки) и т.п. + + 3. Переместите курсор вниз, к строке, помеченной --->. + + 4. Перейдите к первой ошибке. + + 5. Наберите c$ и отредактируйте первую строку так, чтобы она совпадала со + второй, после чего нажмите . + +---> Конец этой строки нуждается в помощи, чтобы стать похожим на второй. +---> Конец этой строки нуждается в помощи команды c$ . + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + РЕЗЮМЕ УРОКА 3 + + + 1. Для вставки текста, который только что был удален, наберите p . Эта + команда вставит удаленный текст ПОСЛЕ курсора (если была удалена строка, + то она будет помещена в строке под курсором). + + 2. Для замены символа под курсором наберите r и затем заменяющий символ. + + 3. Команда изменения позволяет Вам изменить указанный объект от курсора до + конца этого объекта. Например, наберите cw для замены от курсора до + конца слова, c$ для изменения до конца строки. + + 4. Формат команды изменения таков: + + [число] c объект ИЛИ c [число] объект + +Теперь отправляйтесь к следующему уроку. + + + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Урок 4.1: ИНФОРМАЦИЯ О ФАЙЛЕ И РАСПОЛОЖЕНИЕ В НЕМ + + + ** Наберите CTRL-g чтобы увидеть Ваше месторасположение в файле и информацию + о нем. + Наберите SHIFT-G для перемещения к заданной строке в файле. ** + + Замечание: Прочитайте весь урок прежде чем выполнять любые команды!! + + 1. Удерживая клавишу Ctrl нажмите g . Внизу экрана появится строка статуса с + именем файла и номером строки, в которой Вы находитесь. Запомните номер + строки, он потребуется на Шаге 3. + + 2. Нажмите shift-G для перемещения к концу файла. + + 3. Наберите номер строки, в которой вы находились и затем shift-G. Это + вернет Вас к строке, в которой Вы были, когда в первый раз нажали Ctrl-g. + (Когда Вы будете набирать цифры, они НЕ отобразятся на экране.) + + 4. Если Вы запомнили все вышесказанное, выполните шаги 1--3. + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Урок 4.2: КОМАНДА ПОИСКА + + ** Наберите / и затем введите искомую фразу. ** + + 1. В обычном режиме (Normal mode) наберите символ / . Обратите внимание, + что он вместе с курсором появится внизу экрана, как это происходит с + командой : . + + 2. Теперь наберите 'ошшшибка' . Это то слово, которое Вы будете + искать. + + 3. Для того, чтобы повторить поиск, просто нажмите n . + Для поиска этой фразы в обратном направлении, нажмите Shift-N . + + 4. Если Вы желаете сразу искать в обратном направлении, используйте + команду ? вместо / . + +---> Когда Вы при поиске достигнете конца файла, поиск будет продолжен с + начала. + + "ошшшибка" это не способ произнесения слова `ошибка'; ошшшибка это ошибка. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Урок 4.3: ПОИСК ПАРНЫХ СКОБОК + + + ** Наберите % для поиска парных ),] или } . ** + + 1. Поместите курсор над любой из (, [ или { в строке внизу, помеченной --->. + + 2. Теперь наберите символ % . + + 3. Курсор должен перескочить на парную скобку. + + 4. Наберите % для возврата курсора назад к первой скобке. + +---> Это ( строка, содержащая такие (, такие [ ] и такие { } скобки. )) + +Замечание: Это очень удобно при отладке программ с пропущенными скобками! + + + + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Урок 4.4: СПОСОБ ИСПРАВЛЕНИЯ ОШИБОК + + + ** Наберите :s/было/стало/g для замены 'было' на 'стало'. ** + + 1. Переместите курсор вниз, к строке, помеченной --->. + + 2. Наберите :s/уводю/увожу . Обратите внимание на то, что эта команда + заменит только первое найденное вхождение в строке. + + 3. Теперь наберите :s/уводю/увожу/g , означающее подстановку глобально во + всей строке. Это заменит все найденные в строке вхождения. + +---> Я уводю к отверженным селеньям, я уводю сквозь вековечный стон, я уводю к + забытым поколеньям. + + 4. Для замены всех вхождений последовательности символов между двумя + строками, + наберите :#,#s/было/стало/g где #,# --- номера этих строк. + Наберите :%s/было/стало/g для замены всех вхождений во всем файле. + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + РЕЗЮМЕ УРОКА 4 + 1. Ctrl-g показывает ваше положение в файле и информацию о нем. + Shift-G перемещает Вас в конец файла. Номер, за которым следует Shift-G + позволяет перейти к строке с этим номером. + + 2. Нажатие / и затем ввод строки позволяет произвести поиск этой строки + ВПЕРЕД по тексту. + Нажатие ? и затем ввод строки позволяет произвести поиск этой строки + НАЗАД по тексту. + После поиска наберите n для перехода к следующему вхождению искомой + строки в том же направлении или Shift-N для перехода в противоположном + направлении. + + 3. Нажатие % , когда курсор находится на (,),[,],{, или } позволяет найти + парную скобку. + + 4. Для подстановки `стало' вместо первого `было' в строке, наберите + :s/old/new + Для подстановки `стало' вместо всех `было' в строке, наберите + :s/old/new/g + Для замены в интервале между двумя строками, наберите + :#,#s/old/new/g + Для замены всех вхождений `было' на `стало' в файле, наберите + :%s/old/new/g + Чтобы редактор каждый раз запрашивал подтверждение, добавьте 'c' + :%s/old/new/gc +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Урок 5.1: КАК ВЫПОЛНИТЬ ВНЕШНЮЮ КОМАНДУ + + + ** Наберите :! и затем внешнюю команду, которую следует выполнить. ** + + 1. Наберите уже знакомую Вам команду : для установки курсора в командную + строку редактора. Это позволит Вам ввести команду. + + 2. Теперь наберите символ ! (восклицательный знак). Теперь можно исполнить + внешнюю команду, используя командную оболочку. + + 3. Для примера наберите ls после ! и нажмите . Эта команда выведет + список файлов в текущем каталоге, точно также, как если бы Вы ввели эту + команду в приглашении оболочки. Или попробуйте :!dir , если предыдущая + команда не сработала. + +---> Замечание: Таким способом можно выполнить любую внешнюю команду. + +---> Замечание: Все команды, начинающиеся с : , должны завершаться нажатием + . + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Урок 5.2: КАК ЗАПИСАТЬ ФАЙЛ + + +** Для сохранения изменений, произведенных в файле, наберите :w ИМЯ_ФАЙЛА. ** + + 1. Наберите :!dir или :!ls для получения списка файлов в текущем каталоге. + Как Вам уже известно, Вы должны нажать после ввода этих команд. + + 2. Придумайте название для файла, которое еще не существует, например TEST. + + 3. Теперь наберите :w TEST (где TEST --- это имя файла, придуманное Вами.) + + 4. Эта команда сохранит весь файл (Учебник по Vim) под именем TEST. Чтобы + удостовериться в этом, снова наберите :!dir и просмотрите каталог. + +---> Заметьте, что если Вы выйдете из Vim и затем запустите его снова с + файлом TEST, этот файл будет точной копией учебника в тот момент, когда + Вы его сохранили. + + 5. Теперь удалите этот файл, набрав :!del TEST + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Урок 5.3: ВЫБОРОЧНОЕ СОХРАНЕНИЕ + + + ** Для сохранения части файла, наберите :#,# w ИМЯ_ФАЙЛА ** + + 1. Еще раз наберите :!dir или :!ls для получения списка файлов в текущем + каталоге и выберите подходящее имя, например TEST. + + 2. Переместите курсор к началу этой страницы и нажмите Ctrl-g для нахождения + номера строкиto. ЗАПОМНИТЕ ЭТОТ НОМЕР! + + 3. Теперь переместитесь в конец страницы и вновь наберите Ctrl-g. ЗАПОМНИТЕ + И ЭТОТ НОМЕР ТОЖЕ! + + 4. Для сохранения ТОЛЬКО ЧАСТИ файла наберите :#,# w TEST , где #,# --- это + номера, которые Вы запомнили (начало, конец), а TEST --- имя вашего файла. + + 5. Как и прежде, убедитесь в наличии этого файла командой :!dir , но НЕ + УДАЛЯЙТЕ его. + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Урок 5.4: ЧТЕНИЕ И ОБЪЕДИНЕНИЕ ФАЙЛОВ + + ** Для вставки содержимого файла, наберите :r FILENAME ** + + 1. Наберите :!dir для того, чтобы убедиться в том, что файл TEST все еще + существует. + + 2. Установите курсор в верхней части этой страницы. + +Замечание: После выполнения шага 3 Вы увидите Урок 5.3. После этого + перемещайтесь ВНИЗ, снова к этому уроку. + + 3. Теперь прочитайте Ваш файл TEST, используя команду :r TEST , где + TEST --- это имя файла. + +Замечание: Прочитанный Вами файл будет вставлен в том месте, где находится + курсор. + + 4. Чтобы убедиться в том, что файл прочитан, переместитесь немного назад по + тексту и заметьте, что теперь существуют две копии Урока 5.3, исходная + и полученная из файла. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + РЕЗЮМЕ УРОКА 5 + + + 1. :!команда исполняет внешнюю команду. + + Некоторые полезные примеры: + :!dir --- выводит список файлов в каталоге. + :!del FILENAME --- удаляет файл FILENAME. + + 2. :w FILENAME записывает текущий редактируемый файл на диск + под именем FILENAME. + + 3. :#,#w FILENAME сохраняет строки от # до # в файл FILENAME. + + 4. :r FILENAME считывает с диска файл FILENAME и помещает его в текущий + файл следом за позицией курсора. + + + + + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Урок 6.1: КОМАНДА СОЗДАНИЯ + + + ** Наберите o чтобы создать пустую строку под курсором и перейти в режим + вставки (Insert mode) ** + + 1. Переместите курсор вниз, к строке, помеченной --->. + + 2. Наберите o (в нижнем регистре) для того, чтобы создать пустую строку + НИЖЕ курсора и перейти в режим вставки (Insert mode). + + 3. Теперь скопируйте помеченную ---> строку и нажмите для выхода из + режима вставки. + +---> После нажатия o курсор перейдет на новую пустую строку в режиме вставки. + + 4. Для создания строки ВЫШЕ курсора, просто наберите заглавную O, вместо + строчной o. Попробуйте проделать это с нижеследующей строкой. +Создайте новую строку над этой, нажав Shift-O, поместив курсор на эту строку. + + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Урок 6.2: КОМАНДА ДОБАВЛЕНИЯ + + ** Наберите a , чтобы вставить текст ПОСЛЕ курсора. ** + + 1. Переместите курсор вниз, в конец первой строки, помеченной ---> , + набрав $ в обычном режиме (Normal mode). + + 2. Наберите a (в нижнем регистре) для добавления текста ПОСЛЕ символа, + находящегося под курсором. (Заглавная A позволяет добавить в конец + строки.) + +Замечание: Это позволяет избежать нажатия i , последнего символа, текста для + вставки, , курсор-вправо, и, наконец, x , просто для того, + чтобы добавить тест в конец строки! + + 3. Теперь завершите первую строку. Заметьте также, что добавление это в + точности то же самое, что и режим вставки, за исключением позиции, в + которую будет вставлен текст. + +---> Эта строчка позволит Вам попрактиковаться +---> Эта строчка позволит Вам попрактиковаться в добавлении текста в конец + строки. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Урок 6.3: ЕЩЕ ОДИН СПОСОБ ЗАМЕНЫ + + + ** Наберите заглавную R для замены более, чем одного символа. ** + + 1. Переместите курсор вниз, к строке, помеченной --->. + + 2. Расположите курсор в начале первого слова, отличающегося от + соответствующего в следующей строке, помеченной ---> (слово 'последней'). + + 3. Теперь наберите R и замените остаток текста в первой строке, набрав + поверх старого текста так, чтобы обе строки стали одинаковыми. + +---> Первую строку можно сравнять с последней, используя клавиши. +---> Первую строку можно сравнять с второй, используя R и набрав новый текст. + + 4. Обратите внимание, что при нажатии для завершения, любой + не измененный текст сохранится. + + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Урок 6.4: УСТАНОВКА ПАРАМЕТРОВ + + +** Установим параметры так, чтобы игнорировать регистр при поиске или замене ** + + + 1. Поищите слово 'игнорировать', набрав: + /игнорировать + Повторите поиск несколько раз, нажимая клавишу n + + 2. Включите параметр 'ic' (Игнорировать регистр), набрав: + :set ic + + 3. Теперь снова сделайте поиск слова 'игнорировать', нажав: n + Повторите поиск несколько раз, нажимая клавишу n + + 4. Включите параметры 'hlsearch' и 'incsearch': + :set hls is + + 5. Теперь опять введите команду поиска и посмотрите, что получится: + /игнорировать + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + РЕЗЮМЕ УРОКА 6 + + + 1. Нажатие o создает строку НИЖЕ курсора и перемещает курсор в нее в режиме + вставки. + Нажатие заглавной O создает строку ВЫШЕ строки, в которой находится + курсор. + + 2. Наберите a для вставки текста ПОСЛЕ символа, на котором находится курсор. + Нажатие заглавной A автоматически перемещает Вас для добавления текста + в конец строки. + + 3. Нажатие заглавной R переводит Вас в режим замены до тех пор, пока не + будет нажата клавиша для завершения. + + 4. Набрав ":set xxx" вы сможете включить параметр "xxx" + + + + + + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Урок 7: КОМАНДЫ ПОЛУЧЕНИЯ ВСТРОЕННОЙ СПРАВКИ + + ** Используйте встроенную справочную систему ** + + Vim обладает мощной встроенной справочной системой. Для начала попробуйте + один из трех вариантов: + - нажмите клавишу (если таковая имеется на клавиатуре) + - нажмите клавишу (если таковая имеется на клавиатуре) + - наберите :help + + Наберите :q чтобы закрыть окно справки. + + Вы можете найти справку для любого понятия или команды, просто задав + соответствующий аргумент команде ":help". Попробуйте следующее (не забудьте + нажать ): + + :help w + :help c_, 2002. + Translator: Andrey Kiselev , 2002. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff -Naur vim70.orig/runtime/tutor/tutor.vim vim70/runtime/tutor/tutor.vim --- vim70.orig/runtime/tutor/tutor.vim 2006-03-18 12:20:36.000000000 -0800 +++ vim70/runtime/tutor/tutor.vim 2007-02-15 21:22:25.000000000 -0800 @@ -1,6 +1,6 @@ " Vim tutor support file " Author: Eduardo F. Amatria -" Last Change: 2006 Mar 18 +" Last Change: 2006 Sep 09 " This small source file is used for detecting if a translation of the " tutor file exist, i.e., a tutor.xx file, where xx is the language. @@ -93,9 +93,16 @@ endif endif -" The Greek tutor is available in two encodings, guess which one to use -if s:ext =~? '\.gr' && &enc =~ 737 - let s:ext = ".gr.cp737" +" The Greek tutor is available in three encodings, guess what to use. +" We used ".gr" (Greece) instead of ".el" (Greek); accept both. +if s:ext =~? '\.gr\|\.el' + if &enc == "iso-8859-7" + let s:ext = ".gr" + elseif &enc == "utf-8" + let s:ext = ".gr.utf-8" + elseif &enc =~ 737 + let s:ext = ".gr.cp737" + endif endif " The Slovak tutor is available in two encodings, guess which one to use @@ -103,11 +110,15 @@ let s:ext = ".sk.cp1250" endif -" The Russian tutor is available in two encodings, guess which one to use. -" This segment is from the above lines and modified by -" Alexey I. Froloff for Russian vim tutorial -if s:ext =~? '\.ru' && &enc =~ 1251 - let s:ext = ".ru.cp1251" +" The Russian tutor is available in three encodings, guess which one to use. +if s:ext =~? '\.ru' + if &enc == 'utf-8' + let s:ext = '.ru.utf-8' + elseif &enc =~ '1251' + let s:ext = '.ru.cp1251' + elseif &enc =~ 'koi8' + let s:ext = '.ru' + endif endif " Somehow ".ge" (Germany) is sometimes used for ".de" (Deutsch). diff -Naur vim70.orig/src/Makefile vim70/src/Makefile --- vim70.orig/src/Makefile 2006-05-07 06:25:27.000000000 -0700 +++ vim70/src/Makefile 2007-02-15 21:22:25.000000000 -0800 @@ -2177,6 +2177,7 @@ cd $(SHADOWDIR)/xxd; ln -s ../../xxd/*.[ch] ../../xxd/Make* . if test -d $(RSRC_DIR); then \ cd $(SHADOWDIR); \ + ln -s ../infplist.xml .; \ ln -s ../$(RSRC_DIR) ../os_mac.rsr.hqx ../dehqx.py .; \ fi mkdir $(SHADOWDIR)/testdir @@ -2260,7 +2261,7 @@ 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/\\";$$/";/' +QUOTESED = sed -e 's/[\\"]/\\&/g' -e 's/\\"/"/' -e 's/\\";$$/";/' auto/pathdef.c: Makefile auto/config.mk -@echo creating $@ -@echo '/* pathdef.c */' > $@ diff -Naur vim70.orig/src/auto/configure vim70/src/auto/configure --- vim70.orig/src/auto/configure 2006-05-04 03:46:19.000000000 -0700 +++ vim70/src/auto/configure 2007-02-15 21:22:26.000000000 -0800 @@ -4014,7 +4014,7 @@ LDFLAGS=$ldflags_save if test $perl_ok = yes; then if test "X$perlcppflags" != "X"; then - PERL_CFLAGS="$perlcppflags" + PERL_CFLAGS=`echo "$perlcppflags" | sed 's/-pipe //'` fi if test "X$perlldflags" != "X"; then LDFLAGS="$perlldflags $LDFLAGS" @@ -4256,7 +4256,7 @@ echo $ECHO_N "checking if -pthread should be used... $ECHO_C" >&6 threadsafe_flag= thread_lib= - if test "x$MACOSX" != "xyes"; then + if test "`(uname) 2>/dev/null`" != Darwin; then test "$GCC" = yes && threadsafe_flag="-pthread" if test "`(uname) 2>/dev/null`" = FreeBSD; then threadsafe_flag="-D_THREAD_SAFE" @@ -11555,8 +11555,8 @@ else echo "$as_me:$LINENO: result: empty: automatic terminal library selection" >&5 echo "${ECHO_T}empty: automatic terminal library selection" >&6 - case "`uname -s 2>/dev/null`" in - OSF1) tlibs="ncurses curses termlib termcap";; + case "`uname -s 2>/dev/null`" in + OSF1|SCO_SV) tlibs="ncurses curses termlib termcap";; *) tlibs="ncurses termlib termcap curses";; esac for libname in $tlibs; do @@ -15302,7 +15302,7 @@ && test "x$GUITYPE" != "xCARBONGUI"; then echo "$as_me:$LINENO: checking whether we need -framework Carbon" >&5 echo $ECHO_N "checking whether we need -framework Carbon... $ECHO_C" >&6 - if test "x$enable_multibyte" = "xyes" || test "x$features" == "xbig" \ + if test "x$enable_multibyte" = "xyes" || test "x$features" = "xbig" \ || test "x$features" = "xhuge"; then LIBS="$LIBS -framework Carbon" echo "$as_me:$LINENO: result: yes" >&5 diff -Naur vim70.orig/src/buffer.c vim70/src/buffer.c --- vim70.orig/src/buffer.c 2006-04-26 14:37:23.000000000 -0700 +++ vim70/src/buffer.c 2007-02-15 21:22:26.000000000 -0800 @@ -434,12 +434,8 @@ if (usingNetbeans) netbeans_file_closed(buf); #endif -#ifdef FEAT_AUTOCHDIR - /* Change directories when the acd option is set on. */ - if (p_acd && curbuf->b_ffname != NULL - && vim_chdirfile(curbuf->b_ffname) == OK) - shorten_fnames(TRUE); -#endif + /* Change directories when the 'acd' option is set. */ + DO_AUTOCHDIR /* * Remove the buffer from the list. @@ -1212,11 +1208,11 @@ { # ifdef FEAT_WINDOWS /* jump to first window containing buf if one exists ("useopen") */ - if (vim_strchr(p_swb, 'o') && buf_jump_open_win(buf)) + if (vim_strchr(p_swb, 'o') != NULL && buf_jump_open_win(buf)) return OK; /* jump to first window in any tab page containing buf if one exists * ("usetab") */ - if (vim_strchr(p_swb, 'a') && buf_jump_open_tab(buf)) + if (vim_strchr(p_swb, 'a') != NULL && buf_jump_open_tab(buf)) return OK; if (win_split(0, 0) == FAIL) # endif @@ -1390,7 +1386,8 @@ } else { - need_fileinfo = TRUE; /* display file info after redraw */ + if (!msg_silent) + need_fileinfo = TRUE; /* display file info after redraw */ (void)buf_check_timestamp(curbuf, FALSE); /* check if file changed */ #ifdef FEAT_AUTOCMD curwin->w_topline = 1; @@ -1422,12 +1419,8 @@ netbeans_file_activated(curbuf); #endif -#ifdef FEAT_AUTOCHDIR - /* Change directories when the acd option is set on. */ - if (p_acd && curbuf->b_ffname != NULL - && vim_chdirfile(curbuf->b_ffname) == OK) - shorten_fnames(TRUE); -#endif + /* Change directories when the 'acd' option is set. */ + DO_AUTOCHDIR #ifdef FEAT_KEYMAP if (curbuf->b_kmap_state & KEYMAP_INIT) @@ -1436,6 +1429,18 @@ redraw_later(NOT_VALID); } +#if defined(FEAT_AUTOCHDIR) || defined(PROTO) +/* + * Change to the directory of the current buffer. + */ + void +do_autochdir() +{ + if (curbuf->b_ffname != NULL && vim_chdirfile(curbuf->b_ffname) == OK) + shorten_fnames(TRUE); +} +#endif + /* * functions for dealing with the buffer list */ @@ -1837,13 +1842,13 @@ if (options & GETF_SWITCH) { /* use existing open window for buffer if wanted */ - if (vim_strchr(p_swb, 'o')) /* useopen */ + if (vim_strchr(p_swb, 'o') != NULL) /* useopen */ wp = buf_jump_open_win(buf); /* use existing open window in any tab page for buffer if wanted */ - if (vim_strchr(p_swb, 'a')) /* usetab */ + if (vim_strchr(p_swb, 'a') != NULL) /* usetab */ wp = buf_jump_open_tab(buf); /* split window if wanted ("split") */ - if (wp == NULL && vim_strchr(p_swb, 't') && !bufempty()) + if (wp == NULL && vim_strchr(p_swb, 'l') != NULL && !bufempty()) { if (win_split(0, 0) == FAIL) return FAIL; @@ -3324,7 +3329,7 @@ { usefmt = eval_to_string_safe(fmt + 2, NULL, use_sandbox); if (usefmt == NULL) - usefmt = (char_u *)""; + usefmt = fmt; } #endif @@ -4215,7 +4220,7 @@ /* Use the name from the associated buffer if it exists. */ bp = buflist_findnr(aep->ae_fnum); - if (bp == NULL) + if (bp == NULL || bp->b_fname == NULL) return aep->ae_fname; return bp->b_fname; } @@ -5420,11 +5425,7 @@ buf_T *newbuf; int differ = TRUE; linenr_T lnum; -#ifdef FEAT_AUTOCMD aco_save_T aco; -#else - buf_T *old_curbuf = curbuf; -#endif exarg_T ea; /* Allocate a buffer without putting it in the buffer list. */ @@ -5439,13 +5440,8 @@ return TRUE; } -#ifdef FEAT_AUTOCMD /* set curwin/curbuf to buf and save a few things */ aucmd_prepbuf(&aco, newbuf); -#else - curbuf = newbuf; - curwin->w_buffer = newbuf; -#endif if (ml_open(curbuf) == OK && readfile(buf->b_ffname, buf->b_fname, @@ -5466,13 +5462,8 @@ } vim_free(ea.cmd); -#ifdef FEAT_AUTOCMD /* restore curwin/curbuf and a few other things */ aucmd_restbuf(&aco); -#else - curbuf = old_curbuf; - curwin->w_buffer = old_curbuf; -#endif if (curbuf != newbuf) /* safety check */ wipe_buffer(newbuf, FALSE); diff -Naur vim70.orig/src/configure vim70/src/configure --- vim70.orig/src/configure 2006-05-07 07:17:49.000000000 -0700 +++ vim70/src/configure 2007-02-15 21:22:24.000000000 -0800 @@ -2,5 +2,9 @@ # run the automatically generated configure script CONFIG_STATUS=auto/config.status \ auto/configure "$@" --srcdir="${srcdir:-.}" --cache-file=auto/config.cache +result=$? + # Stupid autoconf 2.5x causes this file to be left behind. if test -f configure.lineno; then rm -f configure.lineno; fi + +exit $result diff -Naur vim70.orig/src/configure.in vim70/src/configure.in --- vim70.orig/src/configure.in 2006-05-04 03:46:11.000000000 -0700 +++ vim70/src/configure.in 2007-02-15 21:22:26.000000000 -0800 @@ -508,7 +508,8 @@ LDFLAGS=$ldflags_save if test $perl_ok = yes; then if test "X$perlcppflags" != "X"; then - PERL_CFLAGS="$perlcppflags" + dnl remove -pipe, it confuses cproto + PERL_CFLAGS=`echo "$perlcppflags" | sed 's/-pipe //'` fi if test "X$perlldflags" != "X"; then LDFLAGS="$perlldflags $LDFLAGS" @@ -680,7 +681,8 @@ AC_MSG_CHECKING([if -pthread should be used]) threadsafe_flag= thread_lib= - if test "x$MACOSX" != "xyes"; then + dnl if test "x$MACOSX" != "xyes"; then + if test "`(uname) 2>/dev/null`" != Darwin; then test "$GCC" = yes && threadsafe_flag="-pthread" if test "`(uname) 2>/dev/null`" = FreeBSD; then threadsafe_flag="-D_THREAD_SAFE" @@ -2150,8 +2152,9 @@ dnl Newer versions of ncurses are preferred over anything. 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) tlibs="ncurses curses termlib termcap";; + OSF1|SCO_SV) tlibs="ncurses curses termlib termcap";; *) tlibs="ncurses termlib termcap curses";; esac for libname in $tlibs; do @@ -2835,7 +2838,7 @@ && test "x$GUITYPE" != "xCARBONGUI"; then AC_MSG_CHECKING(whether we need -framework Carbon) dnl check for MACOSX without Carbon GUI, but with FEAT_MBYTE - if test "x$enable_multibyte" = "xyes" || test "x$features" == "xbig" \ + if test "x$enable_multibyte" = "xyes" || test "x$features" = "xbig" \ || test "x$features" = "xhuge"; then LIBS="$LIBS -framework Carbon" AC_MSG_RESULT(yes) diff -Naur vim70.orig/src/edit.c vim70/src/edit.c --- vim70.orig/src/edit.c 2006-05-07 04:48:51.000000000 -0700 +++ vim70/src/edit.c 2007-02-15 21:22:27.000000000 -0800 @@ -129,7 +129,7 @@ static void ins_ctrl_x __ARGS((void)); static int has_compl_option __ARGS((int dict_opt)); -static int ins_compl_add __ARGS((char_u *str, int len, int icase, char_u *fname, char_u **cptext, int cdir, int flags, int dup)); +static int ins_compl_add __ARGS((char_u *str, int len, int icase, char_u *fname, char_u **cptext, int cdir, int flags, int adup)); static int ins_compl_equal __ARGS((compl_T *match, char_u *str, int len)); static void ins_compl_longest_match __ARGS((compl_T *match)); static void ins_compl_add_matches __ARGS((int num_matches, char_u **matches, int icase)); @@ -707,6 +707,11 @@ lastc = c; /* remember previous char for CTRL-D */ c = safe_vgetc(); +#ifdef FEAT_AUTOCMD + /* Don't want K_CURSORHOLD for the second key, e.g., after CTRL-V. */ + did_cursorhold = TRUE; +#endif + #ifdef FEAT_RIGHTLEFT if (p_hkmap && KeyTyped) c = hkmap(c); /* Hebrew mode mapping */ @@ -719,9 +724,14 @@ #ifdef FEAT_INS_EXPAND /* * Special handling of keys while the popup menu is visible or wanted - * and the cursor is still in the completed word. + * and the cursor is still in the completed word. Only when there is + * a match, skip this when no matches were found. */ - if (compl_started && pum_wanted() && curwin->w_cursor.col >= compl_col) + if (compl_started + && pum_wanted() + && curwin->w_cursor.col >= compl_col + && (compl_shown_match == NULL + || compl_shown_match != compl_shown_match->cp_next)) { /* BS: Delete one character from "compl_leader". */ if ((c == K_BS || c == Ctrl_H) @@ -751,7 +761,7 @@ continue; } - /* Pressing CTRL-Y selects the current match. Shen + /* Pressing CTRL-Y selects the current match. When * compl_enter_selects is set the Enter key does the same. */ if (c == Ctrl_Y || (compl_enter_selects && (c == CAR || c == K_KENTER || c == NL))) @@ -877,6 +887,7 @@ /* Close the cmdline window. */ cmdwin_result = K_IGNORE; got_int = FALSE; /* don't stop executing autocommands et al. */ + nomove = TRUE; goto doESCkey; } #endif @@ -912,6 +923,7 @@ if (cmdchar != 'r' && cmdchar != 'v') apply_autocmds(EVENT_INSERTLEAVE, NULL, NULL, FALSE, curbuf); + did_cursorhold = FALSE; #endif return (c == Ctrl_O); } @@ -1383,6 +1395,12 @@ break; } /* end of switch (c) */ +#ifdef FEAT_AUTOCMD + /* If typed something may trigger CursorHoldI again. */ + if (c != K_CURSORHOLD) + did_cursorhold = FALSE; +#endif + /* If the cursor was moved we didn't just insert a space */ if (arrow_used) inserted_space = FALSE; @@ -2112,7 +2130,7 @@ * maybe because alloc() returns NULL, then FAIL is returned. */ static int -ins_compl_add(str, len, icase, fname, cptext, cdir, flags, dup) +ins_compl_add(str, len, icase, fname, cptext, cdir, flags, adup) char_u *str; int len; int icase; @@ -2120,7 +2138,7 @@ char_u **cptext; /* extra text for popup menu or NULL */ int cdir; int flags; - int dup; /* accept duplicate match */ + int adup; /* accept duplicate match */ { compl_T *match; int dir = (cdir == 0 ? compl_direction : cdir); @@ -2134,13 +2152,13 @@ /* * If the same match is already present, don't add it. */ - if (compl_first_match != NULL && !dup) + if (compl_first_match != NULL && !adup) { match = compl_first_match; do { if ( !(match->cp_flags & ORIGINAL_TEXT) - && ins_compl_equal(match, str, len) + && STRNCMP(match->cp_str, str, len) == 0 && match->cp_str[len] == NUL) return NOTDONE; match = match->cp_next; @@ -2399,7 +2417,7 @@ /* compl_pattern doesn't need to be set */ compl_orig_text = vim_strnsave(ml_get_curline() + compl_col, compl_length); if (compl_orig_text == NULL || ins_compl_add(compl_orig_text, - -1, FALSE, NULL, NULL, 0, ORIGINAL_TEXT, FALSE) != OK) + -1, p_ic, NULL, NULL, 0, ORIGINAL_TEXT, FALSE) != OK) return; /* Handle like dictionary completion. */ @@ -2409,6 +2427,7 @@ compl_matches = ins_compl_make_cyclic(); compl_started = TRUE; compl_used_match = TRUE; + compl_cont_status = 0; compl_curr_match = compl_first_match; ins_complete(Ctrl_N); @@ -2753,6 +2772,7 @@ } else # endif + if (count > 0) /* avoid warning for using "files" uninit */ { ins_compl_files(count, files, thesaurus, flags, ®match, buf, &dir); @@ -2813,7 +2833,7 @@ ptr = find_word_end(ptr); add_r = ins_compl_add_infercase(regmatch->startp[0], (int)(ptr - regmatch->startp[0]), - FALSE, files[i], *dir, 0); + p_ic, files[i], *dir, 0); if (thesaurus) { char_u *wstart; @@ -2849,7 +2869,7 @@ ptr = find_word_end(ptr); add_r = ins_compl_add_infercase(wstart, (int)(ptr - wstart), - FALSE, files[i], *dir, 0); + p_ic, files[i], *dir, 0); } } if (add_r == OK) @@ -3015,9 +3035,6 @@ if ((int)(p - line) - (int)compl_col <= 0) return K_BS; - /* For redo we need to repeat this backspace. */ - AppendCharToRedobuff(K_BS); - /* 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 @@ -3046,7 +3063,6 @@ ins_compl_delete(); ins_bytes(compl_leader + curwin->w_cursor.col - compl_col); compl_used_match = FALSE; - compl_enter_selects = FALSE; if (compl_started) ins_compl_set_original_text(compl_leader); @@ -3076,6 +3092,7 @@ compl_restarting = FALSE; } +#if 0 /* disabled, made CTRL-L, BS and typing char jump to original text. */ if (!compl_used_match) { /* Go to the original text, since none of the matches is inserted. */ @@ -3087,9 +3104,15 @@ compl_curr_match = compl_shown_match; compl_shows_dir = compl_direction; } +#endif + compl_enter_selects = !compl_used_match; /* Show the popup menu with a different set of matches. */ ins_compl_show_pum(); + + /* Don't let Enter select the original text when there is no popup menu. */ + if (compl_match_array == NULL) + compl_enter_selects = FALSE; } /* @@ -3115,10 +3138,6 @@ #endif ins_char(c); - /* For redo we need to count this character so that the number of - * backspaces is correct. */ - AppendCharToRedobuff(c); - /* If we didn't complete finding matches we must search again. */ if (compl_was_interrupted) ins_compl_restart(); @@ -3175,10 +3194,33 @@ char_u *p; int len = curwin->w_cursor.col - compl_col; int c; + compl_T *cp; p = compl_shown_match->cp_str; if ((int)STRLEN(p) <= len) /* the match is too short */ - return; + { + /* When still at the original match use the first entry that matches + * the leader. */ + if (compl_shown_match->cp_flags & ORIGINAL_TEXT) + { + p = NULL; + for (cp = compl_shown_match->cp_next; cp != NULL + && cp != compl_first_match; cp = cp->cp_next) + { + if (compl_leader == NULL + || ins_compl_equal(cp, compl_leader, + (int)STRLEN(compl_leader))) + { + p = cp->cp_str; + break; + } + } + if (p == NULL || (int)STRLEN(p) <= len) + return; + } + else + return; + } p += len; #ifdef FEAT_MBYTE c = mb_ptr2char(p); @@ -3198,7 +3240,6 @@ int c; { char_u *ptr; - int temp; int want_cindent; int retval = FALSE; @@ -3354,6 +3395,7 @@ 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 @@ -3369,16 +3411,21 @@ ptr = compl_leader; else ptr = compl_orig_text; - p = compl_orig_text; - for (temp = 0; p[temp] != NUL && p[temp] == ptr[temp]; ++temp) - ; + 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); + 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); - AppendToRedobuffLit(ptr + temp, -1); + for (p += temp; *p != NUL; mb_ptr_adv(p)) + AppendCharToRedobuff(K_BS); + } + if (ptr != NULL) + AppendToRedobuffLit(ptr + temp, -1); } #ifdef FEAT_CINDENT @@ -3578,7 +3625,7 @@ { char_u *word; int icase = FALSE; - int dup = FALSE; + int adup = FALSE; char_u *(cptext[CPT_COUNT]); if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL) @@ -3595,7 +3642,7 @@ if (get_dict_string(tv->vval.v_dict, (char_u *)"icase", FALSE) != NULL) icase = get_dict_number(tv->vval.v_dict, (char_u *)"icase"); if (get_dict_string(tv->vval.v_dict, (char_u *)"dup", FALSE) != NULL) - dup = get_dict_number(tv->vval.v_dict, (char_u *)"dup"); + adup = get_dict_number(tv->vval.v_dict, (char_u *)"dup"); } else { @@ -3604,7 +3651,7 @@ } if (word == NULL || *word == NUL) return FAIL; - return ins_compl_add(word, -1, icase, NULL, cptext, dir, 0, dup); + return ins_compl_add(word, -1, icase, NULL, cptext, dir, 0, adup); } #endif @@ -3796,7 +3843,7 @@ TAG_INS_COMP | (ctrl_x_mode ? TAG_VERBOSE : 0), TAG_MANY, curbuf->b_ffname) == OK && num_matches > 0) { - ins_compl_add_matches(num_matches, matches, FALSE); + ins_compl_add_matches(num_matches, matches, p_ic); } p_ic = save_p_ic; break; @@ -3837,7 +3884,7 @@ num_matches = expand_spelling(first_match_pos.lnum, first_match_pos.col, compl_pattern, &matches); if (num_matches > 0) - ins_compl_add_matches(num_matches, matches, FALSE); + ins_compl_add_matches(num_matches, matches, p_ic); #endif break; @@ -3862,6 +3909,8 @@ { int flags = 0; + ++msg_silent; /* Don't want messages for wrapscan. */ + /* ctrl_x_mode == CTRL_X_WHOLE_LINE || word-wise search that * has added a word that was at the beginning of the line */ if ( ctrl_x_mode == CTRL_X_WHOLE_LINE @@ -3873,6 +3922,7 @@ compl_direction, compl_pattern, 1L, SEARCH_KEEP + SEARCH_NFMSG, RE_LAST, (linenr_T)0); + --msg_silent; if (!compl_started) { /* set "compl_started" even on fail */ @@ -3971,7 +4021,7 @@ continue; } } - if (ins_compl_add_infercase(ptr, len, FALSE, + if (ins_compl_add_infercase(ptr, len, p_ic, ins_buf == curbuf ? NULL : ins_buf->b_sfname, 0, flags) != NOTDONE) { @@ -3996,7 +4046,7 @@ if (got_int) break; /* Fill the popup menu as soon as possible. */ - if (pum_wanted() && type != -1) + if (type != -1) ins_compl_check_keys(0); if ((ctrl_x_mode != 0 && ctrl_x_mode != CTRL_X_WHOLE_LINE) @@ -4100,6 +4150,21 @@ && compl_shown_match->cp_next != NULL && compl_shown_match->cp_next != compl_first_match) compl_shown_match = compl_shown_match->cp_next; + + /* If we didn't find it searching forward, and compl_shows_dir is + * backward, find the last match. */ + if (compl_shows_dir == BACKWARD + && !ins_compl_equal(compl_shown_match, + compl_leader, (int)STRLEN(compl_leader)) + && (compl_shown_match->cp_next == NULL + || compl_shown_match->cp_next == compl_first_match)) + { + while (!ins_compl_equal(compl_shown_match, + compl_leader, (int)STRLEN(compl_leader)) + && compl_shown_match->cp_prev != NULL + && compl_shown_match->cp_prev != compl_first_match) + compl_shown_match = compl_shown_match->cp_prev; + } } if (allow_get_expansion && insert_match @@ -4124,8 +4189,6 @@ { if (compl_shows_dir == FORWARD && compl_shown_match->cp_next != NULL) { - if (compl_pending != 0) - --compl_pending; compl_shown_match = compl_shown_match->cp_next; found_end = (compl_first_match != NULL && (compl_shown_match->cp_next == compl_first_match @@ -4134,14 +4197,24 @@ else if (compl_shows_dir == BACKWARD && compl_shown_match->cp_prev != NULL) { - if (compl_pending != 0) - ++compl_pending; found_end = (compl_shown_match == compl_first_match); compl_shown_match = compl_shown_match->cp_prev; found_end |= (compl_shown_match == compl_first_match); } else { + if (!allow_get_expansion) + { + if (advance) + { + if (compl_shows_dir == BACKWARD) + compl_pending -= todo + 1; + else + compl_pending += todo + 1; + } + return -1; + } + if (advance) { if (compl_shows_dir == BACKWARD) @@ -4149,14 +4222,27 @@ else ++compl_pending; } - if (!allow_get_expansion) - return -1; /* Find matches. */ num_matches = ins_compl_get_exp(&compl_startpos); - if (compl_pending != 0 && compl_direction == compl_shows_dir + + /* handle any pending completions */ + while (compl_pending != 0 && compl_direction == compl_shows_dir && advance) - compl_shown_match = compl_curr_match; + { + if (compl_pending > 0 && compl_shown_match->cp_next != NULL) + { + compl_shown_match = compl_shown_match->cp_next; + --compl_pending; + } + if (compl_pending < 0 && compl_shown_match->cp_prev != NULL) + { + compl_shown_match = compl_shown_match->cp_prev; + ++compl_pending; + } + else + break; + } found_end = FALSE; } if ((compl_shown_match->cp_flags & ORIGINAL_TEXT) == 0 @@ -4265,9 +4351,9 @@ return; count = 0; - ++no_mapping; + /* Check for a typed key. Do use mappings, otherwise vim_is_ctrl_x_key() + * can't do its work correctly. */ c = vpeekc_any(); - --no_mapping; if (c != NUL) { if (vim_is_ctrl_x_key(c) && c != Ctrl_X && c != Ctrl_R) @@ -4277,12 +4363,27 @@ (void)ins_compl_next(FALSE, ins_compl_key2count(c), c != K_UP && c != K_DOWN); } - else if (c != Ctrl_R) - compl_interrupted = TRUE; + else + { + /* Need to get the character to have KeyTyped set. We'll put it + * back with vungetc() below. */ + c = safe_vgetc(); + + /* Don't interrupt completion when the character wasn't typed, + * e.g., when doing @q to replay keys. */ + if (c != Ctrl_R && KeyTyped) + compl_interrupted = TRUE; + + vungetc(c); + } } if (compl_pending != 0 && !got_int) - (void)ins_compl_next(FALSE, compl_pending > 0 - ? compl_pending : -compl_pending, TRUE); + { + int todo = compl_pending > 0 ? compl_pending : -compl_pending; + + compl_pending = 0; + (void)ins_compl_next(FALSE, todo, TRUE); + } } /* @@ -4611,10 +4712,12 @@ (int)STRLEN(compl_pattern), curs_col); if (compl_xp.xp_context == EXPAND_UNSUCCESSFUL || compl_xp.xp_context == EXPAND_NOTHING) - return FAIL; - startcol = (int)(compl_xp.xp_pattern - compl_pattern); - compl_col = startcol; - compl_length = curs_col - startcol; + /* No completion possible, use an empty pattern to get a + * "pattern not found" message. */ + compl_col = curs_col; + else + compl_col = (int)(compl_xp.xp_pattern - compl_pattern); + compl_length = curs_col - compl_col; } else if (ctrl_x_mode == CTRL_X_FUNCTION || ctrl_x_mode == CTRL_X_OMNI) { @@ -4668,11 +4771,17 @@ else compl_col = spell_word_start(startcol); if (compl_col >= (colnr_T)startcol) - return FAIL; - spell_expand_check_cap(compl_col); + { + compl_length = 0; + compl_col = curs_col; + } + else + { + spell_expand_check_cap(compl_col); + compl_length = (int)curs_col - compl_col; + } /* Need to obtain "line" again, it may have become invalid. */ line = ml_get(curwin->w_cursor.lnum); - compl_length = (int)curs_col - compl_col; compl_pattern = vim_strnsave(line + compl_col, compl_length); if (compl_pattern == NULL) #endif @@ -4720,7 +4829,7 @@ vim_free(compl_orig_text); compl_orig_text = vim_strnsave(line + compl_col, compl_length); if (compl_orig_text == NULL || ins_compl_add(compl_orig_text, - -1, FALSE, NULL, NULL, 0, ORIGINAL_TEXT, FALSE) != OK) + -1, p_ic, NULL, NULL, 0, ORIGINAL_TEXT, FALSE) != OK) { vim_free(compl_pattern); compl_pattern = NULL; @@ -4861,16 +4970,18 @@ * just a safety check. */ if (compl_curr_match->cp_number != -1) { - /* Space for 10 text chars. + 2x10-digit no.s */ - static char_u match_ref[31]; + /* Space for 10 text chars. + 2x10-digit no.s = 31. + * Translations may need more than twice that. */ + static char_u match_ref[81]; if (compl_matches > 0) - sprintf((char *)IObuff, _("match %d of %d"), + vim_snprintf((char *)match_ref, sizeof(match_ref), + _("match %d of %d"), compl_curr_match->cp_number, compl_matches); else - sprintf((char *)IObuff, _("match %d"), - compl_curr_match->cp_number); - vim_strncpy(match_ref, IObuff, 30); + vim_snprintf((char *)match_ref, sizeof(match_ref), + _("match %d"), + compl_curr_match->cp_number); edit_submode_extra = match_ref; edit_submode_highl = HLF_R; if (dollar_vcol) @@ -5227,8 +5338,16 @@ /* Format with 'formatexpr' when it's set. Use internal formatting * when 'formatexpr' isn't set or it returns non-zero. */ #if defined(FEAT_EVAL) - if (*curbuf->b_p_fex == NUL - || fex_format(curwin->w_cursor.lnum, 1L, c) != 0) + int do_internal = TRUE; + + if (*curbuf->b_p_fex != NUL) + { + do_internal = (fex_format(curwin->w_cursor.lnum, 1L, c) != 0); + /* It may be required to save for undo again, e.g. when setline() + * was called. */ + ins_need_undo = TRUE; + } + if (do_internal) #endif internal_format(textwidth, second_indent, flags, c == NUL); } @@ -8508,7 +8627,12 @@ tpos = curwin->w_cursor; if (oneleft() == OK) { - start_arrow(&tpos); +#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK) + /* Only call start_arrow() when not busy with preediting, it will + * break undo. K_LEFT is inserted in im_correct_cursor(). */ + if (!im_is_preediting()) +#endif + start_arrow(&tpos); #ifdef FEAT_RIGHTLEFT /* If exit reversed string, position is fixed */ if (revins_scol != -1 && (int)curwin->w_cursor.col >= revins_scol) @@ -8700,7 +8824,11 @@ if (mod_mask & MOD_MASK_CTRL) { /* : tab page back */ - goto_tabpage(-1); + if (first_tabpage->tp_next != NULL) + { + start_arrow(&curwin->w_cursor); + goto_tabpage(-1); + } return; } #endif @@ -8759,7 +8887,11 @@ if (mod_mask & MOD_MASK_CTRL) { /* : tab page forward */ - goto_tabpage(0); + if (first_tabpage->tp_next != NULL) + { + start_arrow(&curwin->w_cursor); + goto_tabpage(0); + } return; } #endif @@ -9074,6 +9206,10 @@ #ifdef FEAT_CINDENT can_cindent = TRUE; #endif +#ifdef FEAT_FOLDING + /* When inserting a line the cursor line must never be in a closed fold. */ + foldOpenCursor(); +#endif return (!i); } diff -Naur vim70.orig/src/eval.c vim70/src/eval.c --- vim70.orig/src/eval.c 2006-05-05 10:15:26.000000000 -0700 +++ vim70/src/eval.c 2007-02-15 21:22:27.000000000 -0800 @@ -166,7 +166,6 @@ int uf_tm_count; /* nr of calls */ proftime_T uf_tm_total; /* time spend in function + children */ proftime_T uf_tm_self; /* time spend in function itself */ - proftime_T uf_tm_start; /* time at function call */ proftime_T uf_tm_children; /* time spent in children this call */ /* profiling the function per line */ int *uf_tml_count; /* nr of times line was executed */ @@ -191,8 +190,6 @@ #define FC_RANGE 2 /* function accepts range */ #define FC_DICT 4 /* Dict function, uses "self" */ -#define DEL_REFCOUNT 999999 /* list/dict is being deleted */ - /* * All user-defined functions are found in this hashtable. */ @@ -345,6 +342,9 @@ {VV_NAME("swapchoice", VAR_STRING), 0}, {VV_NAME("swapcommand", VAR_STRING), VV_RO}, {VV_NAME("char", VAR_STRING), VV_RO}, + {VV_NAME("mouse_win", VAR_NUMBER), 0}, + {VV_NAME("mouse_lnum", VAR_NUMBER), 0}, + {VV_NAME("mouse_col", VAR_NUMBER), 0}, }; /* shorthand */ @@ -435,7 +435,7 @@ 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 void dict_unref __ARGS((dict_T *d)); -static void dict_free __ARGS((dict_T *d)); +static void dict_free __ARGS((dict_T *d, int recurse)); static dictitem_T *dictitem_alloc __ARGS((char_u *key)); static dictitem_T *dictitem_copy __ARGS((dictitem_T *org)); static void dictitem_remove __ARGS((dict_T *dict, dictitem_T *item)); @@ -454,7 +454,7 @@ static char_u *deref_func_name __ARGS((char_u *name, int *lenp)); static int get_func_tv __ARGS((char_u *name, int len, typval_T *rettv, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict)); static int call_func __ARGS((char_u *name, int len, typval_T *rettv, int argcount, typval_T *argvars, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict)); -static void emsg_funcname __ARGS((char *msg, char_u *name)); +static void emsg_funcname __ARGS((char *ermsg, char_u *name)); static void f_add __ARGS((typval_T *argvars, typval_T *rettv)); static void f_append __ARGS((typval_T *argvars, typval_T *rettv)); @@ -622,6 +622,7 @@ static void f_setreg __ARGS((typval_T *argvars, typval_T *rettv)); static void f_settabwinvar __ARGS((typval_T *argvars, typval_T *rettv)); static void f_setwinvar __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_shellescape __ARGS((typval_T *argvars, typval_T *rettv)); static void f_simplify __ARGS((typval_T *argvars, typval_T *rettv)); static void f_sort __ARGS((typval_T *argvars, typval_T *rettv)); static void f_soundfold __ARGS((typval_T *argvars, typval_T *rettv)); @@ -701,6 +702,7 @@ static void list_one_var_a __ARGS((char_u *prefix, char_u *name, int type, char_u *string)); 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 tv_check_lock __ARGS((int lock, char_u *name)); static void copy_tv __ARGS((typval_T *from, typval_T *to)); static int item_copy __ARGS((typval_T *from, typval_T *to, int deep, int copyID)); @@ -896,6 +898,7 @@ } static lval_T *redir_lval = NULL; +static garray_T redir_ga; /* only valid when redir_lval is not NULL */ static char_u *redir_endp = NULL; static char_u *redir_varname = NULL; @@ -930,6 +933,9 @@ return FAIL; } + /* The output is stored in growarray "redir_ga" until redirection ends. */ + ga_init2(&redir_ga, (int)sizeof(char), 500); + /* Parse the variable name (can be a dict or list entry). */ redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, FALSE, FNE_CHECK_START); @@ -972,42 +978,36 @@ } /* - * Append "value[len]" to the variable set by var_redir_start(). + * Append "value[value_len]" to the variable set by var_redir_start(). + * The actual appending is postponed until redirection ends, because the value + * appended may in fact be the string we write to, changing it may cause freed + * memory to be used: + * :redir => foo + * :let foo + * :redir END */ void -var_redir_str(value, len) +var_redir_str(value, value_len) char_u *value; - int len; + int value_len; { - char_u *val; - typval_T tv; - int save_emsg; - int err; + size_t len; if (redir_lval == NULL) return; - if (len == -1) - /* Append the entire string */ - val = vim_strsave(value); + if (value_len == -1) + len = STRLEN(value); /* Append the entire string */ else - /* Append only the specified number of characters */ - val = vim_strnsave(value, len); - if (val == NULL) - return; + len = value_len; /* Append only "value_len" characters */ - tv.v_type = VAR_STRING; - tv.vval.v_string = val; - - save_emsg = did_emsg; - did_emsg = FALSE; - set_var_lval(redir_lval, redir_endp, &tv, FALSE, (char_u *)"."); - err = did_emsg; - did_emsg |= save_emsg; - if (err) + if (ga_grow(&redir_ga, (int)len) == OK) + { + mch_memmove((char *)redir_ga.ga_data + redir_ga.ga_len, value, len); + redir_ga.ga_len += len; + } + else var_redir_stop(); - - vim_free(tv.vval.v_string); } /* @@ -1016,8 +1016,19 @@ void var_redir_stop() { + typval_T tv; + if (redir_lval != NULL) { + /* Append the trailing NUL. */ + ga_append(&redir_ga, NUL); + + /* Assign the text to the variable. */ + tv.v_type = VAR_STRING; + tv.vval.v_string = redir_ga.ga_data; + set_var_lval(redir_lval, redir_endp, &tv, FALSE, (char_u *)"."); + vim_free(tv.vval.v_string); + clear_lval(redir_lval); vim_free(redir_lval); redir_lval = NULL; @@ -2260,7 +2271,7 @@ EMSG(_(e_letunexp)); else { - char_u *tofree = NULL; + char_u *ptofree = NULL; char_u *s; p = get_tv_string_chk(tv); @@ -2269,7 +2280,7 @@ s = get_reg_contents(*arg == '@' ? '"' : *arg, TRUE, TRUE); if (s != NULL) { - p = tofree = concat_str(s, p); + p = ptofree = concat_str(s, p); vim_free(s); } } @@ -2278,7 +2289,7 @@ write_reg_contents(*arg == '@' ? '"' : *arg, p, -1, FALSE); arg_end = arg + 1; } - vim_free(tofree); + vim_free(ptofree); } } @@ -3125,7 +3136,12 @@ funcdict_T fudi; tofree = trans_function_name(&arg, eap->skip, TFN_INT, &fudi); - vim_free(fudi.fd_newkey); + if (fudi.fd_newkey != NULL) + { + /* Still need to give an error message for missing key. */ + EMSG2(_(e_dictkey), fudi.fd_newkey); + vim_free(fudi.fd_newkey); + } if (tofree == NULL) return; @@ -3177,9 +3193,18 @@ failed = TRUE; break; } + + /* Handle a function returning a Funcref, Dictionary or List. */ + if (handle_subscript(&arg, &rettv, !eap->skip, TRUE) == FAIL) + { + failed = TRUE; + break; + } + clear_tv(&rettv); if (doesrange || eap->skip) break; + /* Stop when immediately aborting on error, or when an interrupt * occurred or an exception was thrown but not caught. * get_func_tv() returned OK, so that the check for trailing @@ -3364,6 +3389,8 @@ hi = hash_find(ht, varname); if (!HASHITEM_EMPTY(hi)) { + if (var_check_fixed(HI2DI(hi)->di_flags, name)) + return FAIL; if (var_check_ro(HI2DI(hi)->di_flags, name)) return FAIL; delete_var(ht, hi); @@ -4895,7 +4922,7 @@ { if (list_append_tv(l, &item->li_tv) == FAIL) { - list_free(l); + list_free(l, TRUE); return FAIL; } item = item->li_next; @@ -5295,7 +5322,7 @@ EMSG2(_("E697: Missing end of List ']': %s"), *arg); failret: if (evaluate) - list_free(l); + list_free(l, TRUE); return FAIL; } @@ -5359,8 +5386,8 @@ list_unref(l) list_T *l; { - if (l != NULL && l->lv_refcount != DEL_REFCOUNT && --l->lv_refcount <= 0) - list_free(l); + if (l != NULL && --l->lv_refcount <= 0) + list_free(l, TRUE); } /* @@ -5368,14 +5395,12 @@ * Ignores the reference count. */ void -list_free(l) - list_T *l; +list_free(l, recurse) + list_T *l; + int recurse; /* Free Lists and Dictionaries recursively. */ { listitem_T *item; - /* Avoid that recursive reference to the list frees us again. */ - l->lv_refcount = DEL_REFCOUNT; - /* Remove the list from the list of lists for garbage collection. */ if (l->lv_used_prev == NULL) first_list = l->lv_used_next; @@ -5388,7 +5413,10 @@ { /* Remove the item before deleting it. */ l->lv_first = item->li_next; - listitem_free(item); + if (recurse || (item->li_tv.v_type != VAR_LIST + && item->li_tv.v_type != VAR_DICT)) + clear_tv(&item->li_tv); + vim_free(item); } vim_free(l); } @@ -5448,6 +5476,8 @@ { listitem_T *item1, *item2; + if (l1 == l2) + return TRUE; if (list_len(l1) != list_len(l2)) return FALSE; @@ -5484,6 +5514,8 @@ dictitem_T *item2; int todo; + if (d1 == d2) + return TRUE; if (dict_len(d1) != dict_len(d2)) return FALSE; @@ -5516,19 +5548,29 @@ { char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN]; char_u *s1, *s2; + static int recursive = 0; /* cach 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) + return TRUE; switch (tv1->v_type) { case VAR_LIST: - /* recursive! */ - return list_equal(tv1->vval.v_list, tv2->vval.v_list, ic); + ++recursive; + r = list_equal(tv1->vval.v_list, tv2->vval.v_list, ic); + --recursive; + return r; case VAR_DICT: - /* recursive! */ - return dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic); + ++recursive; + r = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic); + --recursive; + return r; case VAR_FUNC: return (tv1->vval.v_string != NULL @@ -6059,6 +6101,10 @@ tabpage_T *tp; #endif + /* Only do this once. */ + want_garbage_collect = FALSE; + may_garbage_collect = FALSE; + /* * 1. Go through all accessible variables and mark all lists and dicts * with copyID. @@ -6097,7 +6143,10 @@ for (dd = first_dict; dd != NULL; ) if (dd->dv_copyID != copyID) { - dict_free(dd); + /* Free the Dictionary and ordinary items it contains, but don't + * recurse into Lists and Dictionaries, they will be in the list + * of dicts or list of lists. */ + dict_free(dd, FALSE); did_free = TRUE; /* restart, next dict may also have been freed */ @@ -6114,7 +6163,10 @@ for (ll = first_list; ll != NULL; ) if (ll->lv_copyID != copyID && ll->lv_watch == NULL) { - list_free(ll); + /* Free the List and ordinary items it contains, but don't recurse + * into Lists and Dictionaries, they will be in the list of dicts + * or list of lists. */ + list_free(ll, FALSE); did_free = TRUE; /* restart, next list may also have been freed */ @@ -6207,11 +6259,12 @@ d = (dict_T *)alloc(sizeof(dict_T)); if (d != NULL) { - /* Add the list to the hashtable for garbage collection. */ + /* Add the list to the list of dicts for garbage collection. */ if (first_dict != NULL) first_dict->dv_used_prev = d; d->dv_used_next = first_dict; d->dv_used_prev = NULL; + first_dict = d; hash_init(&d->dv_hashtab); d->dv_lock = 0; @@ -6229,8 +6282,8 @@ dict_unref(d) dict_T *d; { - if (d != NULL && d->dv_refcount != DEL_REFCOUNT && --d->dv_refcount <= 0) - dict_free(d); + if (d != NULL && --d->dv_refcount <= 0) + dict_free(d, TRUE); } /* @@ -6238,16 +6291,14 @@ * Ignores the reference count. */ static void -dict_free(d) - dict_T *d; +dict_free(d, recurse) + dict_T *d; + int recurse; /* Free Lists and Dictionaries recursively. */ { int todo; hashitem_T *hi; dictitem_T *di; - /* Avoid that recursive reference to the dict frees us again. */ - d->dv_refcount = DEL_REFCOUNT; - /* Remove the dict from the list of dicts for garbage collection. */ if (d->dv_used_prev == NULL) first_dict = d->dv_used_next; @@ -6267,7 +6318,10 @@ * something recursive causing trouble. */ di = HI2DI(hi); hash_remove(&d->dv_hashtab, hi); - dictitem_free(di); + if (recurse || (di->di_tv.v_type != VAR_LIST + && di->di_tv.v_type != VAR_DICT)) + clear_tv(&di->di_tv); + vim_free(di); --todo; } } @@ -6718,7 +6772,7 @@ EMSG2(_("E723: Missing end of Dictionary '}': %s"), *arg); failret: if (evaluate) - dict_free(d); + dict_free(d, TRUE); return FAIL; } @@ -7139,6 +7193,7 @@ {"setreg", 2, 3, f_setreg}, {"settabwinvar", 4, 4, f_settabwinvar}, {"setwinvar", 3, 3, f_setwinvar}, + {"shellescape", 1, 1, f_shellescape}, {"simplify", 1, 1, f_simplify}, {"sort", 1, 2, f_sort}, {"soundfold", 1, 1, f_soundfold}, @@ -7595,8 +7650,8 @@ * Give an error message with a function name. Handle things. */ static void -emsg_funcname(msg, name) - char *msg; +emsg_funcname(ermsg, name) + char *ermsg; char_u *name; { char_u *p; @@ -7605,7 +7660,7 @@ p = concat_str((char_u *)"", name + 3); else p = name; - EMSG2(_(msg), p); + EMSG2(_(ermsg), p); if (p != name) vim_free(p); } @@ -8252,6 +8307,12 @@ EMSG(_("E785: complete() can only be used in Insert mode")); return; } + + /* Check for undo allowed here, because if something was already inserted + * the line was already saved for undo and this check isn't done. */ + if (!undo_allowed()) + return; + if (argvars[1].v_type != VAR_LIST || argvars[1].vval.v_list == NULL) { EMSG(_(e_invarg)); @@ -9173,25 +9234,25 @@ typval_T save_key; int rem; int todo; - char_u *msg = map ? (char_u *)"map()" : (char_u *)"filter()"; + char_u *ermsg = map ? (char_u *)"map()" : (char_u *)"filter()"; int save_did_emsg; rettv->vval.v_number = 0; if (argvars[0].v_type == VAR_LIST) { if ((l = argvars[0].vval.v_list) == NULL - || (map && tv_check_lock(l->lv_lock, msg))) + || (map && tv_check_lock(l->lv_lock, ermsg))) return; } else if (argvars[0].v_type == VAR_DICT) { if ((d = argvars[0].vval.v_dict) == NULL - || (map && tv_check_lock(d->dv_lock, msg))) + || (map && tv_check_lock(d->dv_lock, ermsg))) return; } else { - EMSG2(_(e_listdictarg), msg); + EMSG2(_(e_listdictarg), ermsg); return; } @@ -9223,7 +9284,7 @@ { --todo; di = HI2DI(hi); - if (tv_check_lock(di->di_tv.v_lock, msg)) + if (tv_check_lock(di->di_tv.v_lock, ermsg)) break; vimvars[VV_KEY].vv_str = vim_strsave(di->di_key); if (filter_map_one(&di->di_tv, expr, map, &rem) == FAIL @@ -9242,7 +9303,7 @@ { for (li = l->lv_first; li != NULL; li = nli) { - if (tv_check_lock(li->li_tv.v_lock, msg)) + if (tv_check_lock(li->li_tv.v_lock, ermsg)) break; nli = li->li_next; if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL @@ -9598,7 +9659,9 @@ typval_T *argvars; typval_T *rettv; { - garbage_collect(); + /* This is postponed until we are back at the toplevel, because we may be + * using Lists and Dicts internally. E.g.: ":echo [garbagecollect()]". */ + want_garbage_collect = TRUE; } /* @@ -9792,6 +9855,9 @@ varnumber_T n; int error = FALSE; + /* Position the cursor. Needed after a message that ends in a space. */ + windgoto(msg_row, msg_col); + ++no_mapping; ++allow_keys; if (argvars[0].v_type == VAR_UNKNOWN) @@ -9809,6 +9875,10 @@ --no_mapping; --allow_keys; + vimvars[VV_MOUSE_WIN].vv_nr = 0; + vimvars[VV_MOUSE_LNUM].vv_nr = 0; + vimvars[VV_MOUSE_COL].vv_nr = 0; + rettv->vval.v_number = n; if (IS_SPECIAL(n) || mod_mask != 0) { @@ -9837,6 +9907,53 @@ temp[i++] = NUL; rettv->v_type = VAR_STRING; rettv->vval.v_string = vim_strsave(temp); + +#ifdef FEAT_MOUSE + if (n == K_LEFTMOUSE + || n == K_LEFTMOUSE_NM + || n == K_LEFTDRAG + || n == K_LEFTRELEASE + || n == K_LEFTRELEASE_NM + || n == K_MIDDLEMOUSE + || n == K_MIDDLEDRAG + || n == K_MIDDLERELEASE + || n == K_RIGHTMOUSE + || n == K_RIGHTDRAG + || n == K_RIGHTRELEASE + || n == K_X1MOUSE + || n == K_X1DRAG + || n == K_X1RELEASE + || n == K_X2MOUSE + || n == K_X2DRAG + || n == K_X2RELEASE + || n == K_MOUSEDOWN + || n == K_MOUSEUP) + { + int row = mouse_row; + int col = mouse_col; + win_T *win; + linenr_T lnum; +# ifdef FEAT_WINDOWS + win_T *wp; +# endif + int n = 1; + + if (row >= 0 && col >= 0) + { + /* Find the window at the mouse coordinates and compute the + * text position. */ + win = mouse_find_win(&row, &col); + (void)mouse_comp_pos(win, &row, &col, &lnum); +# ifdef FEAT_WINDOWS + for (wp = firstwin; wp != win; wp = wp->w_next) + ++n; +# endif + vimvars[VV_MOUSE_WIN].vv_nr = n; + vimvars[VV_MOUSE_LNUM].vv_nr = lnum; + vimvars[VV_MOUSE_COL].vv_nr = col + 1; + } + } +#endif } } @@ -10412,20 +10529,14 @@ if (win != NULL && varname != NULL) { - if (*varname == '&') /* window-local-option */ - { - /* Set curwin to be our win, temporarily. Also set curbuf, so - * that we can get buffer-local options. */ - oldcurwin = curwin; - curwin = win; - curbuf = win->w_buffer; + /* Set curwin to be our win, temporarily. Also set curbuf, so + * that we can get buffer-local options. */ + oldcurwin = curwin; + curwin = win; + curbuf = win->w_buffer; + if (*varname == '&') /* window-local-option */ get_option_tv(&varname, rettv, 1); - - /* restore previous notion of curwin */ - curwin = oldcurwin; - curbuf = curwin->w_buffer; - } else { if (*varname == NUL) @@ -10438,6 +10549,10 @@ if (v != NULL) copy_tv(&v->di_tv, rettv); } + + /* restore previous notion of curwin */ + curwin = oldcurwin; + curbuf = curwin->w_buffer; } --emsg_off; @@ -11312,14 +11427,19 @@ static int inputsecret_flag = 0; +static void get_user_input __ARGS((typval_T *argvars, typval_T *rettv, int inputdialog)); + /* - * "input()" function - * Also handles inputsecret() when inputsecret is set. + * This function is used by f_input() and f_inputdialog() functions. The third + * argument to f_input() specifies the type of completion to use at the + * prompt. The third argument to f_inputdialog() specifies the value to return + * when the user cancels the prompt. */ static void -f_input(argvars, rettv) +get_user_input(argvars, rettv, inputdialog) typval_T *argvars; typval_T *rettv; + int inputdialog; { char_u *prompt = get_tv_string_chk(&argvars[0]); char_u *p = NULL; @@ -11369,10 +11489,10 @@ if (defstr != NULL) stuffReadbuffSpec(defstr); - if (argvars[2].v_type != VAR_UNKNOWN) + if (!inputdialog && argvars[2].v_type != VAR_UNKNOWN) { char_u *xp_name; - int xp_namelen; + int xp_namelen; long argt; rettv->vval.v_string = NULL; @@ -11404,6 +11524,18 @@ } /* + * "input()" function + * Also handles inputsecret() when inputsecret is set. + */ + static void +f_input(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ + get_user_input(argvars, rettv, FALSE); +} + +/* * "inputdialog()" function */ static void @@ -11443,7 +11575,7 @@ } else #endif - f_input(argvars, rettv); + get_user_input(argvars, rettv, TRUE); } /* @@ -11471,6 +11603,7 @@ } msg_start(); + msg_row = Rows - 1; /* for when 'cmdheight' > 1 */ lines_left = Rows; /* avoid more prompt */ msg_scroll = TRUE; msg_clr_eos(); @@ -13250,7 +13383,7 @@ 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()")) + && !tv_check_lock(d->dv_lock, (char_u *)"remove() argument")) { key = get_tv_string_chk(&argvars[1]); if (key != NULL) @@ -13270,7 +13403,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()")) + && !tv_check_lock(l->lv_lock, (char_u *)"remove() argument")) { int error = FALSE; @@ -14157,11 +14290,7 @@ typval_T *rettv; { buf_T *buf; -#ifdef FEAT_AUTOCMD aco_save_T aco; -#else - buf_T *save_curbuf; -#endif char_u *varname, *bufvarname; typval_T *varp; char_u nbuf[NUMBUFLEN]; @@ -14178,12 +14307,7 @@ if (buf != NULL && varname != NULL && varp != NULL) { /* set curbuf to be our buf, temporarily */ -#ifdef FEAT_AUTOCMD aucmd_prepbuf(&aco, buf); -#else - save_curbuf = curbuf; - curbuf = buf; -#endif if (*varname == '&') { @@ -14210,11 +14334,7 @@ } /* reset notion of buffer */ -#ifdef FEAT_AUTOCMD aucmd_restbuf(&aco); -#else - curbuf = save_curbuf; -#endif } } @@ -14582,6 +14702,18 @@ } /* + * "shellescape({string})" function + */ + static void +f_shellescape(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ + rettv->vval.v_string = vim_strsave_shellescape(get_tv_string(&argvars[0])); + rettv->v_type = VAR_STRING; +} + +/* * "simplify()" function */ static void @@ -15950,6 +16082,10 @@ } } + /* add a terminating NUL */ + ga_grow(&ga, 1); + ga_append(&ga, NUL); + rettv->vval.v_string = ga.ga_data; } @@ -16173,7 +16309,7 @@ curwin->w_curswant = get_dict_number(dict, (char_u *)"curswant"); curwin->w_set_curswant = FALSE; - curwin->w_topline = get_dict_number(dict, (char_u *)"topline"); + set_topline(curwin, get_dict_number(dict, (char_u *)"topline")); #ifdef FEAT_DIFF curwin->w_topfill = get_dict_number(dict, (char_u *)"topfill"); #endif @@ -16218,6 +16354,7 @@ #ifdef FEAT_VIRTUALEDIT dict_add_nr_str(dict, "coladd", (long)curwin->w_cursor.coladd, NULL); #endif + update_curswant(); dict_add_nr_str(dict, "curswant", (long)curwin->w_curswant, NULL); dict_add_nr_str(dict, "topline", (long)curwin->w_topline, NULL); @@ -16438,9 +16575,12 @@ long i = 0; long n; - /* List must be: [fnum, lnum, col, coladd] */ - if (arg->v_type != VAR_LIST || l == NULL - || l->lv_len != (fnump == NULL ? 3 : 4)) + /* List must be: [fnum, lnum, col, coladd], where "fnum" is only there + * when "fnump" isn't NULL and "coladd" is optional. */ + if (arg->v_type != VAR_LIST + || l == NULL + || l->lv_len < (fnump == NULL ? 2 : 3) + || l->lv_len > (fnump == NULL ? 3 : 4)) return FAIL; if (fnump != NULL) @@ -16466,8 +16606,9 @@ #ifdef FEAT_VIRTUALEDIT n = list_find_nr(l, i, NULL); if (n < 0) - return FAIL; - posp->coladd = n; + posp->coladd = 0; + else + posp->coladd = n; #endif return OK; @@ -17759,6 +17900,13 @@ } else /* add a new variable */ { + /* Can't add "v:" variable. */ + if (ht == &vimvarht) + { + EMSG2(_(e_illvar), name); + return; + } + /* Make sure the variable name is valid. */ for (p = varname; *p != NUL; ++p) if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p)) @@ -17792,7 +17940,7 @@ } /* - * Return TRUE if di_flags "flags" indicate read-only variable "name". + * Return TRUE if di_flags "flags" indicates variable "name" is read-only. * Also give an error message. */ static int @@ -17814,6 +17962,23 @@ } /* + * Return TRUE if di_flags "flags" indicates variable "name" is fixed. + * Also give an error message. + */ + static int +var_check_fixed(flags, name) + int flags; + char_u *name; +{ + if (flags & DI_FLAGS_FIX) + { + EMSG2(_("E795: Cannot delete variable %s"), name); + return TRUE; + } + return FALSE; +} + +/* * Return TRUE if typeval "tv" is set to be locked (immutable). * Also give an error message, using "name". */ @@ -18396,12 +18561,14 @@ if (!eap->skip) { - /* Check the name of the function. */ + /* Check the name of the function. Unless it's a dictionary function + * (that we are overwriting). */ if (name != NULL) arg = name; else arg = fudi.fd_newkey; - if (arg != NULL) + if (arg != NULL && (fudi.fd_di == NULL + || fudi.fd_di->di_tv.v_type != VAR_FUNC)) { if (*arg == K_SPECIAL) j = 3; @@ -18786,6 +18953,7 @@ if (dict_add(fudi.fd_dict, fudi.fd_di) == FAIL) { vim_free(fudi.fd_di); + vim_free(fp); goto erret; } } @@ -18963,7 +19131,8 @@ else if (lead > 0) { lead = 3; - if (eval_fname_sid(lv.ll_exp_name != NULL ? lv.ll_exp_name : *pp)) + if ((lv.ll_exp_name != NULL && eval_fname_sid(lv.ll_exp_name)) + || eval_fname_sid(*pp)) { /* It's "s:" or "" */ if (current_SID <= 0) @@ -19618,6 +19787,7 @@ char_u *name; #ifdef FEAT_PROFILE proftime_T wait_start; + proftime_T call_start; #endif /* If depth of calling is getting too high, don't execute the function */ @@ -19685,6 +19855,7 @@ v->di_tv.vval.v_list = &fc.l_varlist; vim_memset(&fc.l_varlist, 0, sizeof(list_T)); fc.l_varlist.lv_refcount = 99999; + fc.l_varlist.lv_lock = VAR_FIXED; /* * Set a:firstline to "firstline" and a:lastline to "lastline". @@ -19761,7 +19932,7 @@ if (p_verbose >= 14) { char_u buf[MSG_BUF_LEN]; - char_u numbuf[NUMBUFLEN]; + char_u numbuf2[NUMBUFLEN]; char_u *tofree; msg_puts((char_u *)"("); @@ -19773,8 +19944,8 @@ msg_outnum((long)argvars[i].vval.v_number); else { - trunc_string(tv2string(&argvars[i], &tofree, numbuf, 0), - buf, MSG_BUF_CLEN); + trunc_string(tv2string(&argvars[i], &tofree, + numbuf2, 0), buf, MSG_BUF_CLEN); msg_puts(buf); vim_free(tofree); } @@ -19796,7 +19967,7 @@ || (fc.caller != NULL && &fc.caller->func->uf_profiling)) { ++fp->uf_tm_count; - profile_start(&fp->uf_tm_start); + profile_start(&call_start); profile_zero(&fp->uf_tm_children); } script_prof_save(&wait_start); @@ -19826,14 +19997,14 @@ if (do_profiling == PROF_YES && (fp->uf_profiling || (fc.caller != NULL && &fc.caller->func->uf_profiling))) { - profile_end(&fp->uf_tm_start); - profile_sub_wait(&wait_start, &fp->uf_tm_start); - profile_add(&fp->uf_tm_total, &fp->uf_tm_start); - profile_self(&fp->uf_tm_self, &fp->uf_tm_start, &fp->uf_tm_children); + profile_end(&call_start); + profile_sub_wait(&wait_start, &call_start); + profile_add(&fp->uf_tm_total, &call_start); + profile_self(&fp->uf_tm_self, &call_start, &fp->uf_tm_children); if (fc.caller != NULL && &fc.caller->func->uf_profiling) { - profile_add(&fc.caller->func->uf_tm_children, &fp->uf_tm_start); - profile_add(&fc.caller->func->uf_tml_children, &fp->uf_tm_start); + profile_add(&fc.caller->func->uf_tm_children, &call_start); + profile_add(&fc.caller->func->uf_tml_children, &call_start); } } #endif @@ -19852,13 +20023,13 @@ else { char_u buf[MSG_BUF_LEN]; - char_u numbuf[NUMBUFLEN]; + char_u numbuf2[NUMBUFLEN]; char_u *tofree; /* The value may be very long. Skip the middle part, so that we * have some idea how it starts and ends. smsg() would always * truncate it at the end. */ - trunc_string(tv2string(fc.rettv, &tofree, numbuf, 0), + trunc_string(tv2string(fc.rettv, &tofree, numbuf2, 0), buf, MSG_BUF_CLEN); smsg((char_u *)_("%s returning %s"), sourcing_name, buf); vim_free(tofree); diff -Naur vim70.orig/src/ex_cmds.c vim70/src/ex_cmds.c --- vim70.orig/src/ex_cmds.c 2006-04-22 11:56:56.000000000 -0700 +++ vim70/src/ex_cmds.c 2007-02-15 21:22:27.000000000 -0800 @@ -95,7 +95,10 @@ _("<%s>%s%s %d, Hex %02x, Octal %03o"), transchar(c), buf1, buf2, c, c, c); #ifdef FEAT_MBYTE - c = cc[ci++]; + if (enc_utf8) + c = cc[ci++]; + else + c = 0; #endif } @@ -108,7 +111,7 @@ if (len > 0) IObuff[len++] = ' '; IObuff[len++] = '<'; - if (utf_iscomposing(c) + if (enc_utf8 && utf_iscomposing(c) # ifdef USE_GUI && !gui.in_use # endif @@ -120,7 +123,10 @@ : _("> %d, Hex %08x, Octal %o"), c, c, c); if (ci == MAX_MCO) break; - c = cc[ci++]; + if (enc_utf8) + c = cc[ci++]; + else + c = 0; } #endif @@ -185,6 +191,7 @@ new_indent = indent; else { + has_tab = FALSE; /* avoid uninit warnings */ len = linelen(eap->cmdidx == CMD_right ? &has_tab : NULL) - get_indent(); @@ -1772,10 +1779,9 @@ ? (st_old.st_mode & 0020) : (st_old.st_mode & 0002)))) { - int tt; + int tt = msg_didany; /* avoid a wait_return for this message, it's annoying */ - tt = msg_didany; EMSG2(_("E137: Viminfo file is not writable: %s"), fname); msg_didany = tt; fclose(fp_in); @@ -2458,6 +2464,8 @@ #ifdef FEAT_AUTOCMD apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, FALSE, curbuf); #endif + /* Change directories when the 'acd' option is set. */ + DO_AUTOCHDIR } /* print full file name if :cd used */ fileinfo(FALSE, FALSE, eap->forceit); @@ -2675,8 +2683,13 @@ eap, eap->append, eap->forceit, TRUE, FALSE); /* After ":saveas fname" reset 'readonly'. */ - if (eap->cmdidx == CMD_saveas && retval == OK) - curbuf->b_p_ro = FALSE; + if (eap->cmdidx == CMD_saveas) + { + if (retval == OK) + curbuf->b_p_ro = FALSE; + /* Change directories when the 'acd' option is set. */ + DO_AUTOCHDIR + } } theend: @@ -3547,11 +3560,9 @@ foldUpdateAll(curwin); #endif -#ifdef FEAT_AUTOCHDIR - if (p_acd && curbuf->b_ffname != NULL - && vim_chdirfile(curbuf->b_ffname) == OK) - shorten_fnames(TRUE); -#endif + /* Change directories when the 'acd' option is set. */ + DO_AUTOCHDIR + /* * Careful: open_buffer() and apply_autocmds() may change the current * buffer and window. @@ -3718,12 +3729,8 @@ if (p_im) need_start_insertmode = TRUE; -#ifdef FEAT_AUTOCHDIR - /* Change directories when the acd option is set on. */ - if (p_acd && curbuf->b_ffname != NULL - && vim_chdirfile(curbuf->b_ffname) == OK) - shorten_fnames(TRUE); -#endif + /* Change directories when the 'acd' option is set. */ + DO_AUTOCHDIR #if defined(FEAT_SUN_WORKSHOP) || defined(FEAT_NETBEANS_INTG) if (gui.in_use && curbuf->b_ffname != NULL) @@ -6960,6 +6967,14 @@ */ set_arglist(eap->arg); + /* + * Expanding wildcards may result in an empty argument list. E.g. when + * editing "foo.pyc" and ".pyc" is in 'wildignore'. Assume that we + * already did an error message for this. + */ + if (ARGCOUNT == 0) + return; + # ifdef FEAT_WINDOWS if (cmdmod.tab) { diff -Naur vim70.orig/src/ex_cmds.h vim70/src/ex_cmds.h --- vim70.orig/src/ex_cmds.h 2006-04-07 02:44:46.000000000 -0700 +++ vim70/src/ex_cmds.h 2007-02-15 21:22:24.000000000 -0800 @@ -262,7 +262,7 @@ EX(CMD_comclear, "comclear", ex_comclear, TRLBAR|CMDWIN), EX(CMD_compiler, "compiler", ex_compiler, - BANG|TRLBAR|WORD1), + BANG|TRLBAR|WORD1|CMDWIN), EX(CMD_continue, "continue", ex_continue, TRLBAR|SBOXOK|CMDWIN), EX(CMD_confirm, "confirm", ex_wrongmodifier, diff -Naur vim70.orig/src/ex_cmds2.c vim70/src/ex_cmds2.c --- vim70.orig/src/ex_cmds2.c 2006-04-17 03:19:07.000000000 -0700 +++ vim70/src/ex_cmds2.c 2007-02-15 21:22:27.000000000 -0800 @@ -1242,14 +1242,22 @@ buf_T *buf; int forceit; { + int r; + if (!(p_aw || p_awa) || !p_write #ifdef FEAT_QUICKFIX - /* never autowrite a "nofile" or "nowrite" buffer */ - || bt_dontwrite(buf) + /* never autowrite a "nofile" or "nowrite" buffer */ + || bt_dontwrite(buf) #endif - || (!forceit && buf->b_p_ro) || buf->b_ffname == NULL) + || (!forceit && buf->b_p_ro) || buf->b_ffname == NULL) return FAIL; - return buf_write_all(buf, forceit); + r = buf_write_all(buf, forceit); + + /* Writing may succeed but the buffer still changed, e.g., when there is a + * conversion error. We do want to return FAIL then. */ + if (buf_valid(buf) && bufIsChanged(buf)) + r = FAIL; + return r; } /* @@ -1472,6 +1480,8 @@ 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 */ } @@ -2811,6 +2821,17 @@ } #ifdef FEAT_AUTOCMD + /* Apply SourceCmd autocommands, they should get the file and source it. */ + if (has_autocmd(EVENT_SOURCECMD, fname_exp, NULL) + && apply_autocmds(EVENT_SOURCECMD, fname_exp, fname_exp, + FALSE, curbuf)) +# ifdef FEAT_EVAL + return aborting() ? FAIL : OK; +# else + return OK; +# endif + + /* Apply SourcePre autocommands, they may get the file. */ apply_autocmds(EVENT_SOURCEPRE, fname_exp, fname_exp, FALSE, curbuf); #endif @@ -3648,13 +3669,13 @@ * Return FALSE when not sourcing a file. */ int -source_finished(getline, cookie) - char_u *(*getline) __ARGS((int, void *, int)); +source_finished(fgetline, cookie) + char_u *(*fgetline) __ARGS((int, void *, int)); void *cookie; { - return (getline_equal(getline, cookie, getsourceline) + return (getline_equal(fgetline, cookie, getsourceline) && ((struct source_cookie *)getline_cookie( - getline, cookie))->finished); + fgetline, cookie))->finished); } #endif diff -Naur vim70.orig/src/ex_docmd.c vim70/src/ex_docmd.c --- vim70.orig/src/ex_docmd.c 2006-05-05 09:33:19.000000000 -0700 +++ vim70/src/ex_docmd.c 2007-02-15 21:22:27.000000000 -0800 @@ -58,9 +58,9 @@ #endif #ifdef FEAT_EVAL -static char_u *do_one_cmd __ARGS((char_u **, int, struct condstack *, char_u *(*getline)(int, void *, int), void *cookie)); +static char_u *do_one_cmd __ARGS((char_u **, int, struct condstack *, char_u *(*fgetline)(int, void *, int), void *cookie)); #else -static char_u *do_one_cmd __ARGS((char_u **, int, char_u *(*getline)(int, void *, int), void *cookie)); +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 char_u *find_command __ARGS((exarg_T *eap, int *full)); @@ -831,10 +831,13 @@ /* * If requested, store and reset the global values controlling the - * exception handling (used when debugging). + * exception handling (used when debugging). Otherwise clear it to avoid + * a bogus compiler warning when the optimizer uses inline functions... */ - else if (flags & DOCMD_EXCRESET) + if (flags & DOCMD_EXCRESET) save_dbg_stuff(&debug_saved); + else + memset(&debug_saved, 0, 1); initial_trylevel = trylevel; @@ -1574,24 +1577,24 @@ #endif /* - * If "getline" is get_loop_line(), return TRUE if the getline it uses equals - * "func". * Otherwise return TRUE when "getline" equals "func". + * If "fgetline" is get_loop_line(), return TRUE if the getline it uses equals + * "func". * Otherwise return TRUE when "fgetline" equals "func". */ /*ARGSUSED*/ int -getline_equal(getline, cookie, func) - char_u *(*getline) __ARGS((int, void *, int)); - void *cookie; /* argument for getline() */ +getline_equal(fgetline, cookie, func) + char_u *(*fgetline) __ARGS((int, void *, int)); + void *cookie; /* argument for fgetline() */ char_u *(*func) __ARGS((int, void *, int)); { #ifdef FEAT_EVAL char_u *(*gp) __ARGS((int, void *, int)); struct loop_cookie *cp; - /* When "getline" is "get_loop_line()" use the "cookie" to find the + /* When "fgetline" is "get_loop_line()" use the "cookie" to find the * function that's orignally used to obtain the lines. This may be nested * several levels. */ - gp = getline; + gp = fgetline; cp = (struct loop_cookie *)cookie; while (gp == get_loop_line) { @@ -1600,29 +1603,29 @@ } return gp == func; #else - return getline == func; + return fgetline == func; #endif } #if defined(FEAT_EVAL) || defined(FEAT_MBYTE) || defined(PROTO) /* - * If "getline" is get_loop_line(), return the cookie used by the original + * If "fgetline" is get_loop_line(), return the cookie used by the original * getline function. Otherwise return "cookie". */ /*ARGSUSED*/ void * -getline_cookie(getline, cookie) - char_u *(*getline) __ARGS((int, void *, int)); - void *cookie; /* argument for getline() */ +getline_cookie(fgetline, cookie) + char_u *(*fgetline) __ARGS((int, void *, int)); + void *cookie; /* argument for fgetline() */ { # ifdef FEAT_EVAL char_u *(*gp) __ARGS((int, void *, int)); struct loop_cookie *cp; - /* When "getline" is "get_loop_line()" use the "cookie" to find the + /* When "fgetline" is "get_loop_line()" use the "cookie" to find the * cookie that's orignally used to obtain the lines. This may be nested * several levels. */ - gp = getline; + gp = fgetline; cp = (struct loop_cookie *)cookie; while (gp == get_loop_line) { @@ -1648,7 +1651,7 @@ * 5. parse arguments * 6. switch on command name * - * Note: "getline" can be NULL. + * Note: "fgetline" can be NULL. * * This function may be called recursively! */ @@ -1663,14 +1666,14 @@ #ifdef FEAT_EVAL cstack, #endif - getline, cookie) + fgetline, cookie) char_u **cmdlinep; int sourcing; #ifdef FEAT_EVAL struct condstack *cstack; #endif - char_u *(*getline) __ARGS((int, void *, int)); - void *cookie; /* argument for getline() */ + char_u *(*fgetline) __ARGS((int, void *, int)); + void *cookie; /* argument for fgetline() */ { char_u *p; linenr_T lnum; @@ -1698,7 +1701,7 @@ if (quitmore #ifdef FEAT_EVAL /* avoid that a function call in 'statusline' does this */ - && !getline_equal(getline, cookie, get_func_line) + && !getline_equal(fgetline, cookie, get_func_line) #endif ) --quitmore; @@ -1710,6 +1713,10 @@ save_cmdmod = cmdmod; vim_memset(&cmdmod, 0, sizeof(cmdmod)); + /* "#!anything" is handled like a comment. */ + if ((*cmdlinep)[0] == '#' && (*cmdlinep)[1] == '!') + goto doend; + /* * Repeat until no more command modifiers are found. */ @@ -1724,8 +1731,8 @@ /* in ex mode, an empty line works like :+ */ if (*ea.cmd == NUL && exmode_active - && (getline_equal(getline, cookie, getexmodeline) - || getline_equal(getline, cookie, getexline)) + && (getline_equal(fgetline, cookie, getexmodeline) + || getline_equal(fgetline, cookie, getexline)) && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) { ea.cmd = (char_u *)"+"; @@ -1914,9 +1921,9 @@ /* Count this line for profiling if ea.skip is FALSE. */ if (do_profiling == PROF_YES && !ea.skip) { - if (getline_equal(getline, cookie, get_func_line)) - func_line_exec(getline_cookie(getline, cookie)); - else if (getline_equal(getline, cookie, getsourceline)) + if (getline_equal(fgetline, cookie, get_func_line)) + func_line_exec(getline_cookie(fgetline, cookie)); + else if (getline_equal(fgetline, cookie, getsourceline)) script_line_exec(); } #endif @@ -2585,7 +2592,7 @@ * The "ea" structure holds the arguments that can be used. */ ea.cmdlinep = cmdlinep; - ea.getline = getline; + ea.getline = fgetline; ea.cookie = cookie; #ifdef FEAT_EVAL ea.cstack = cstack; @@ -2623,9 +2630,9 @@ do_throw(cstack); else if (check_cstack) { - if (source_finished(getline, cookie)) + if (source_finished(fgetline, cookie)) do_finish(&ea, TRUE); - else if (getline_equal(getline, cookie, get_func_line) + else if (getline_equal(fgetline, cookie, get_func_line) && current_func_returned()) do_return(&ea, TRUE, FALSE, NULL); } @@ -6289,7 +6296,6 @@ exarg_T *eap; { tabpage_T *tp; - int h = tabline_height(); # ifdef FEAT_CMDWIN if (cmdwin_type != 0) @@ -6321,9 +6327,6 @@ ) tabpage_close(eap->forceit); } - - if (h != tabline_height()) - shell_new_rows(); } /* @@ -6335,7 +6338,6 @@ { tabpage_T *tp; int done; - int h = tabline_height(); # ifdef FEAT_CMDWIN if (cmdwin_type != 0) @@ -6364,9 +6366,6 @@ break; } } - - if (h != tabline_height()) - shell_new_rows(); } /* @@ -6390,6 +6389,8 @@ /* * Close tab page "tp", which is not the current tab page. * Note that autocommands may make "tp" invalid. + * Also takes care of the tab pages line disappearing when closing the + * last-but-one tab page. */ void tabpage_close_other(tp, forceit) @@ -6398,6 +6399,7 @@ { int done = 0; win_T *wp; + int h = tabline_height(); /* Limit to 1000 windows, autocommands may add a window while we close * one. OK, so I'm paranoid... */ @@ -6411,7 +6413,10 @@ if (!valid_tabpage(tp) || tp->tp_firstwin == wp) break; } + redraw_tabline = TRUE; + if (h != tabline_height()) + shell_new_rows(); } /* @@ -8214,8 +8219,9 @@ c = *eap->arg; if (c == NUL || (c == '*' && *eap->cmd == '*')) c = '@'; - /* put the register in mapbuf */ - if (do_execreg(c, TRUE, vim_strchr(p_cpo, CPO_EXECBUF) != NULL) == FAIL) + /* Put the register in the typeahead buffer with the "silent" flag. */ + if (do_execreg(c, TRUE, vim_strchr(p_cpo, CPO_EXECBUF) != NULL, TRUE) + == FAIL) { beep_flush(); } @@ -8365,6 +8371,7 @@ if (ASCII_ISALPHA(*arg) # ifdef FEAT_CLIPBOARD || *arg == '*' + || *arg == '+' # endif || *arg == '"') { @@ -8375,6 +8382,7 @@ (islower(redir_reg) # ifdef FEAT_CLIPBOARD || redir_reg == '*' + || redir_reg == '+' # endif || redir_reg == '"')) { @@ -8417,6 +8425,15 @@ else EMSG2(_(e_invarg2), eap->arg); } + + /* Make sure redirection is not off. Can happen for cmdline completion + * that indirectly invokes a command to catch its output. */ + if (redir_fd != NULL +#ifdef FEAT_EVAL + || redir_reg || redir_vname +#endif + ) + redir_off = FALSE; } /* @@ -9629,7 +9646,8 @@ #endif #ifdef FEAT_SESSION -static int ses_winsizes __ARGS((FILE *fd, int restore_size)); +static int ses_winsizes __ARGS((FILE *fd, int restore_size, + win_T *tab_firstwin)); static int ses_win_rec __ARGS((FILE *fd, frame_T *fr)); static frame_T *ses_skipframe __ARGS((frame_T *fr)); static int ses_do_frame __ARGS((frame_T *fr)); @@ -9655,8 +9673,9 @@ win_T *wp; char_u *sname; win_T *edited_win = NULL; - tabpage_T *old_curtab = curtab; int tabnr; + win_T *tab_firstwin; + frame_T *tab_topframe; if (ssop_flags & SSOP_BUFFERS) only_save_windows = FALSE; /* Save ALL buffers */ @@ -9764,14 +9783,33 @@ /* * May repeat putting Windows for each tab, when "tabpages" is in * 'sessionoptions'. + * Don't use goto_tabpage(), it may change directory and trigger + * autocommands. */ + tab_firstwin = firstwin; /* first window in tab page "tabnr" */ + tab_topframe = topframe; for (tabnr = 1; ; ++tabnr) { + int need_tabnew = FALSE; + if ((ssop_flags & SSOP_TABPAGES)) { - goto_tabpage(tabnr); - if (tabnr > 1 && put_line(fd, "tabnew") == FAIL) - return FAIL; + tabpage_T *tp = find_tabpage(tabnr); + + if (tp == NULL) + break; /* done all tab pages */ + if (tp == curtab) + { + tab_firstwin = firstwin; + tab_topframe = topframe; + } + else + { + tab_firstwin = tp->tp_firstwin; + tab_topframe = tp->tp_topframe; + } + if (tabnr > 1) + need_tabnew = TRUE; } /* @@ -9779,7 +9817,7 @@ * is aborted we don't end up with a number of useless windows. * This may have side effects! (e.g., compressed or network file). */ - for (wp = firstwin; wp != NULL; wp = wp->w_next) + for (wp = tab_firstwin; wp != NULL; wp = wp->w_next) { if (ses_do_win(wp) && wp->w_buffer->b_ffname != NULL @@ -9789,21 +9827,26 @@ #endif ) { - if (fputs("edit ", fd) < 0 + if (fputs(need_tabnew ? "tabedit " : "edit ", fd) < 0 || ses_fname(fd, wp->w_buffer, &ssop_flags) == FAIL) return FAIL; + need_tabnew = FALSE; if (!wp->w_arg_idx_invalid) edited_win = wp; break; } } + /* If no file got edited create an empty tab page. */ + if (need_tabnew && put_line(fd, "tabnew") == FAIL) + return FAIL; + /* * Save current window layout. */ if (put_line(fd, "set splitbelow splitright") == FAIL) return FAIL; - if (ses_win_rec(fd, topframe) == FAIL) + if (ses_win_rec(fd, tab_topframe) == FAIL) return FAIL; if (!p_sb && put_line(fd, "set nosplitbelow") == FAIL) return FAIL; @@ -9815,7 +9858,7 @@ * Remember the window number of the current window after restoring. */ nr = 0; - for (wp = firstwin; wp != NULL; wp = W_NEXT(wp)) + for (wp = tab_firstwin; wp != NULL; wp = W_NEXT(wp)) { if (ses_do_win(wp)) ++nr; @@ -9838,13 +9881,13 @@ */ if (put_line(fd, "set winheight=1 winwidth=1") == FAIL) return FAIL; - if (nr > 1 && ses_winsizes(fd, restore_size) == FAIL) + if (nr > 1 && ses_winsizes(fd, restore_size, tab_firstwin) == FAIL) return FAIL; /* * Restore the view of the window (options, file, cursor, etc.). */ - for (wp = firstwin; wp != NULL; wp = wp->w_next) + for (wp = tab_firstwin; wp != NULL; wp = wp->w_next) { if (!ses_do_win(wp)) continue; @@ -9865,19 +9908,17 @@ * Restore window sizes again after jumping around in windows, because * the current window has a minimum size while others may not. */ - if (nr > 1 && ses_winsizes(fd, restore_size) == FAIL) + if (nr > 1 && ses_winsizes(fd, restore_size, tab_firstwin) == FAIL) return FAIL; /* Don't continue in another tab page when doing only the current one * or when at the last tab page. */ - if (!(ssop_flags & SSOP_TABPAGES) || curtab->tp_next == NULL) + if (!(ssop_flags & SSOP_TABPAGES)) break; } if (ssop_flags & SSOP_TABPAGES) { - if (valid_tabpage(old_curtab)) - goto_tabpage_tp(old_curtab); if (fprintf(fd, "tabnext %d", tabpage_index(curtab)) < 0 || put_eol(fd) == FAIL) return FAIL; @@ -9913,16 +9954,17 @@ } static int -ses_winsizes(fd, restore_size) +ses_winsizes(fd, restore_size, tab_firstwin) FILE *fd; int restore_size; + win_T *tab_firstwin; { int n = 0; win_T *wp; if (restore_size && (ssop_flags & SSOP_WINSIZE)) { - for (wp = firstwin; wp != NULL; wp = wp->w_next) + for (wp = tab_firstwin; wp != NULL; wp = wp->w_next) { if (!ses_do_win(wp)) continue; diff -Naur vim70.orig/src/ex_eval.c vim70/src/ex_eval.c --- vim70.orig/src/ex_eval.c 2006-04-22 12:22:27.000000000 -0700 +++ vim70/src/ex_eval.c 2007-02-15 21:22:26.000000000 -0800 @@ -340,7 +340,7 @@ /* If no exception is to be thrown or the conversion should be done after * returning to a previous invocation of do_one_cmd(), do nothing. */ - if (*msg_list == NULL) + if (msg_list == NULL || *msg_list == NULL) return; if (throw_exception(*msg_list, ET_ERROR, cmdname) == FAIL) @@ -2026,8 +2026,11 @@ /* If an error was about to be converted to an exception when * enter_cleanup() was called, free the message list. */ - free_msglist(*msg_list); - *msg_list = NULL; + if (msg_list != NULL) + { + free_msglist(*msg_list); + *msg_list = NULL; + } } /* diff -Naur vim70.orig/src/ex_getln.c vim70/src/ex_getln.c --- vim70.orig/src/ex_getln.c 2006-04-30 08:32:01.000000000 -0700 +++ vim70/src/ex_getln.c 2007-02-15 21:22:26.000000000 -0800 @@ -34,7 +34,7 @@ int xp_context; /* type of expansion */ # ifdef FEAT_EVAL char_u *xp_arg; /* user-defined expansion arg */ - int input_fn; /* Invoked for input() function */ + int input_fn; /* when TRUE Invoked for input() function */ # endif }; @@ -86,7 +86,7 @@ static void draw_cmdline __ARGS((int start, int len)); static void save_cmdline __ARGS((struct cmdline_info *ccp)); static void restore_cmdline __ARGS((struct cmdline_info *ccp)); -static int cmdline_paste __ARGS((int regname, int literally)); +static int cmdline_paste __ARGS((int regname, int literally, int remcr)); #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK) static void redrawcmd_preedit __ARGS((void)); #endif @@ -324,6 +324,9 @@ */ for (;;) { + redir_off = TRUE; /* Don't redirect the typed command. + Repeated, because a ":redir" inside + completion may switch it on. */ #ifdef USE_ON_FLY_SCROLL dont_scroll = FALSE; /* allow scrolling here */ #endif @@ -1113,7 +1116,7 @@ #endif if (c != ESC) /* use ESC to cancel inserting register */ { - cmdline_paste(c, i == Ctrl_R); + cmdline_paste(c, i == Ctrl_R, FALSE); #ifdef FEAT_EVAL /* When there was a serious error abort getting the @@ -1228,16 +1231,16 @@ goto cmdline_not_changed; /* Ignore mouse */ # ifdef FEAT_CLIPBOARD if (clip_star.available) - cmdline_paste('*', TRUE); + cmdline_paste('*', TRUE, TRUE); else # endif - cmdline_paste(0, TRUE); + cmdline_paste(0, TRUE, TRUE); redrawcmd(); goto cmdline_changed; # ifdef FEAT_DND case K_DROP: - cmdline_paste('~', TRUE); + cmdline_paste('~', TRUE, FALSE); redrawcmd(); goto cmdline_changed; # endif @@ -1387,7 +1390,17 @@ { c = gchar_cursor(); if (c != NUL) + { + if (c == firstc || vim_strchr((char_u *)( + p_magic ? "\\^$.*[" : "\\^$"), c) + != NULL) + { + /* put a backslash before special characters */ + stuffcharReadbuff(c); + c = '\\'; + } break; + } } goto cmdline_not_changed; } @@ -1753,6 +1766,11 @@ end_pos = curwin->w_cursor; /* shutup gcc 4 */ validate_cursor(); +# ifdef FEAT_WINDOWS + /* May redraw the status line to show the cursor position. */ + if (p_ru && curwin->w_status_height > 0) + curwin->w_redr_status = TRUE; +# endif save_cmdline(&save_ccline); update_screen(SOME_VALID); @@ -2360,7 +2378,7 @@ { if ((State & CMDLINE) && xic != NULL - && im_get_status() + /* && im_get_status() doesn't work when using SCIM */ && !p_imdisable && im_is_preediting()) { @@ -2882,9 +2900,10 @@ * return FAIL for failure, OK otherwise */ static int -cmdline_paste(regname, literally) +cmdline_paste(regname, literally, remcr) int regname; int literally; /* Insert text literally instead of "as typed" */ + int remcr; /* remove trailing CR */ { long i; char_u *arg; @@ -2960,7 +2979,7 @@ return OK; } - return cmdline_paste_reg(regname, literally); + return cmdline_paste_reg(regname, literally, remcr); } /* @@ -4521,7 +4540,9 @@ flags |= EW_FILE | EW_EXEC; /* For an absolute name we don't use $PATH. */ - if ((pat[0] == '.' && (vim_ispathsep(pat[1]) + if (mch_isFullName(pat)) + path = (char_u *)" "; + else if ((pat[0] == '.' && (vim_ispathsep(pat[1]) || (pat[1] == '.' && vim_ispathsep(pat[2]))))) path = (char_u *)"."; else @@ -4534,6 +4555,9 @@ ga_init2(&ga, (int)sizeof(char *), 10); for (s = path; *s != NUL; s = e) { + if (*s == ' ') + ++s; /* Skip space used for absolute path name. */ + #if defined(MSDOS) || defined(MSWIN) || defined(OS2) e = vim_strchr(s, ';'); #else @@ -5982,6 +6006,8 @@ typestr[0] = cmdwin_type; typestr[1] = NUL; apply_autocmds(EVENT_CMDWINENTER, typestr, typestr, FALSE, curbuf); + if (restart_edit != 0) /* autocmd with ":startinsert" */ + stuffcharReadbuff(K_NOP); # endif i = RedrawingDisabled; diff -Naur vim70.orig/src/fileio.c vim70/src/fileio.c --- vim70.orig/src/fileio.c 2006-04-30 08:28:57.000000000 -0700 +++ vim70/src/fileio.c 2007-02-15 21:22:27.000000000 -0800 @@ -316,6 +316,9 @@ * display the line. */ ex_no_reprint = TRUE; + /* don't display the file info for another buffer now */ + need_fileinfo = FALSE; + /* * For Unix: Use the short file name whenever possible. * Avoids problems with networks and when directory names are changed. @@ -6151,8 +6154,8 @@ if (retval != FAIL) { curbuf = frombuf; - while (!bufempty()) - if (ml_delete(curbuf->b_ml.ml_line_count, FALSE) == FAIL) + for (lnum = curbuf->b_ml.ml_line_count; lnum > 0; --lnum) + if (ml_delete(lnum, FALSE) == FAIL) { /* Oops! We could try putting back the saved lines, but that * might fail again... */ @@ -6450,17 +6453,10 @@ int old_ro = buf->b_p_ro; buf_T *savebuf; int saved = OK; -#ifdef FEAT_AUTOCMD aco_save_T aco; /* set curwin/curbuf for "buf" and save some things */ aucmd_prepbuf(&aco, buf); -#else - buf_T *save_curbuf = curbuf; - - curbuf = buf; - curwin->w_buffer = buf; -#endif /* We only want to read the text from the file, not reset the syntax * highlighting, clear marks, diff status, etc. Force the fileformat @@ -6573,14 +6569,9 @@ curbuf->b_p_ro |= old_ro; } -#ifdef FEAT_AUTOCMD /* restore curwin/curbuf and a few other things */ aucmd_restbuf(&aco); /* Careful: autocommands may have made "buf" invalid! */ -#else - curwin->w_buffer = save_curbuf; - curbuf = save_curbuf; -#endif } /*ARGSUSED*/ @@ -6992,6 +6983,7 @@ {"FocusLost", EVENT_FOCUSLOST}, {"FuncUndefined", EVENT_FUNCUNDEFINED}, {"GUIEnter", EVENT_GUIENTER}, + {"GUIFailed", EVENT_GUIFAILED}, {"InsertChange", EVENT_INSERTCHANGE}, {"InsertEnter", EVENT_INSERTENTER}, {"InsertLeave", EVENT_INSERTLEAVE}, @@ -7003,6 +6995,7 @@ {"ShellCmdPost", EVENT_SHELLCMDPOST}, {"ShellFilterPost", EVENT_SHELLFILTERPOST}, {"SourcePre", EVENT_SOURCEPRE}, + {"SourceCmd", EVENT_SOURCECMD}, {"SpellFileMissing",EVENT_SPELLFILEMISSING}, {"StdinReadPost", EVENT_STDINREADPOST}, {"StdinReadPre", EVENT_STDINREADPRE}, @@ -8088,6 +8081,7 @@ * Search a window for the current buffer. Save the cursor position and * screen offset. * Set "curbuf" and "curwin" to match "buf". + * When FEAT_AUTOCMD is not defined another version is used, see below. */ void aucmd_prepbuf(aco, buf) @@ -8151,6 +8145,7 @@ /* * Cleanup after executing autocommands for a (hidden) buffer. * Restore the window as it was (if possible). + * When FEAT_AUTOCMD is not defined another version is used, see below. */ void aucmd_restbuf(aco) @@ -8295,7 +8290,11 @@ { int state; - if (!did_cursorhold && has_cursorhold() && !Recording) + if (!did_cursorhold && has_cursorhold() && !Recording +#ifdef FEAT_INS_EXPAND + && !ins_compl_active() +#endif + ) { state = get_real_state(); if (state == NORMAL_BUSY || (state & INSERT) != 0) @@ -9063,8 +9062,38 @@ return retval; } +#else /* FEAT_AUTOCMD */ + +/* + * Prepare for executing commands for (hidden) buffer "buf". + * This is the non-autocommand version, it simply saves "curbuf" and sets + * "curbuf" and "curwin" to match "buf". + */ + void +aucmd_prepbuf(aco, buf) + aco_save_T *aco; /* structure to save values in */ + buf_T *buf; /* new curbuf */ +{ + aco->save_buf = buf; + curbuf = buf; + curwin->w_buffer = buf; +} + +/* + * Restore after executing commands for a (hidden) buffer. + * This is the non-autocommand version. + */ + void +aucmd_restbuf(aco) + aco_save_T *aco; /* structure holding saved values */ +{ + curbuf = aco->save_buf; + curwin->w_buffer = curbuf; +} + #endif /* FEAT_AUTOCMD */ + #if defined(FEAT_AUTOCMD) || defined(FEAT_WILDIGN) || defined(PROTO) /* * Try matching a filename with a "pattern" ("prog" is NULL), or use the diff -Naur vim70.orig/src/fold.c vim70/src/fold.c --- vim70.orig/src/fold.c 2006-04-22 12:35:56.000000000 -0700 +++ vim70/src/fold.c 2007-02-15 21:22:26.000000000 -0800 @@ -2971,7 +2971,11 @@ else flp->lvl = get_indent_buf(buf, lnum) / buf->b_p_sw; if (flp->lvl > flp->wp->w_p_fdn) + { flp->lvl = flp->wp->w_p_fdn; + if (flp->lvl < 0) + flp->lvl = 0; + } } /* foldlevelDiff() {{{2 */ diff -Naur vim70.orig/src/getchar.c vim70/src/getchar.c --- vim70.orig/src/getchar.c 2006-05-03 10:29:21.000000000 -0700 +++ vim70/src/getchar.c 2007-02-15 21:22:27.000000000 -0800 @@ -76,7 +76,7 @@ */ static mapblock_T *first_abbr = NULL; /* first entry in abbrlist */ -static int KeyNoremap = FALSE; /* remapping disabled */ +static int KeyNoremap = 0; /* remapping flags */ /* * variables used by vgetorpeek() and flush_buffers() @@ -1035,6 +1035,8 @@ /* * Put character "c" back into the typeahead buffer. * Can be used for a character obtained by vgetc() that needs to be put back. + * Uses cmd_silent, KeyTyped and KeyNoremap to restore the flags belonging to + * the char. */ void ins_char_typebuf(c) @@ -1061,7 +1063,7 @@ buf[1] = NUL; #endif } - (void)ins_typebuf(buf, REMAP_YES, 0, !KeyTyped, FALSE); + (void)ins_typebuf(buf, KeyNoremap, 0, !KeyTyped, cmd_silent); } /* @@ -1451,7 +1453,8 @@ { updatescript(0); #ifdef FEAT_EVAL - garbage_collect(); + if (may_garbage_collect) + garbage_collect(); #endif } @@ -1502,6 +1505,13 @@ int i; #endif +#ifdef FEAT_EVAL + /* Do garbage collection when garbagecollect() was called previously and + * we are now at the toplevel. */ + if (may_garbage_collect && want_garbage_collect) + garbage_collect(); +#endif + /* * If a character was put back with vungetc, it was already processed. * Return it directly. @@ -1511,13 +1521,13 @@ c = old_char; old_char = -1; mod_mask = old_mod_mask; - return c; } - - mod_mask = 0x0; - last_recorded_len = 0; - for (;;) /* this is done twice if there are modifiers */ + else { + mod_mask = 0x0; + last_recorded_len = 0; + for (;;) /* this is done twice if there are modifiers */ + { if (mod_mask) /* no mapping after modifier has been read */ { ++no_mapping; @@ -1695,8 +1705,20 @@ } #endif - return c; + break; + } } + +#ifdef FEAT_EVAL + /* + * In the main loop "may_garbage_collect" can be set to do garbage + * collection in the first next vgetc(). It's disabled after that to + * avoid internally used Lists and Dicts to be freed. + */ + may_garbage_collect = FALSE; +#endif + + return c; } /* @@ -1940,10 +1962,13 @@ c = Ctrl_C; flush_buffers(TRUE); /* flush all typeahead */ - /* Also record this character, it might be needed to - * get out of Insert mode. */ - *typebuf.tb_buf = c; - gotchars(typebuf.tb_buf, 1); + if (advance) + { + /* Also record this character, it might be needed to + * get out of Insert mode. */ + *typebuf.tb_buf = c; + gotchars(typebuf.tb_buf, 1); + } cmd_silent = FALSE; break; @@ -2247,9 +2272,8 @@ gotchars(typebuf.tb_buf + typebuf.tb_off, 1); } - KeyNoremap = (typebuf.tb_noremap[ - typebuf.tb_off] - & (RM_NONE|RM_SCRIPT)); + KeyNoremap = typebuf.tb_noremap[ + typebuf.tb_off]; del_typebuf(1, 0); } break; /* got character, break for loop */ @@ -4173,7 +4197,8 @@ if (typebuf.tb_no_abbr_cnt) /* abbrev. are not recursive */ return FALSE; - if (KeyNoremap) /* no remapping implies no abbreviation */ + if ((KeyNoremap & (RM_NONE|RM_SCRIPT)) != 0) + /* no remapping implies no abbreviation */ return FALSE; /* diff -Naur vim70.orig/src/globals.h vim70/src/globals.h --- vim70.orig/src/globals.h 2006-04-30 06:16:23.000000000 -0700 +++ vim70/src/globals.h 2007-02-15 21:22:27.000000000 -0800 @@ -166,6 +166,7 @@ EXTERN int emsg_off INIT(= 0); /* don't display errors for now, unless 'debug' is set. */ EXTERN int info_message INIT(= FALSE); /* printing informative message */ +EXTERN int msg_hist_off INIT(= FALSE); /* don't add messages to history */ #ifdef FEAT_EVAL EXTERN int emsg_skip INIT(= 0); /* don't display errors for expression that is skipped */ @@ -300,9 +301,16 @@ #endif #ifdef FEAT_EVAL -EXTERN scid_T current_SID INIT(= 0); /* ID of script being sourced or - was sourced to define the - current function. */ +/* Garbage collection can only take place when we are sure there are no Lists + * or Dictionaries being used internally. This is flagged with + * "may_garbage_collect" when we are at the toplevel. + * "want_garbage_collect" is set by the garbagecollect() function, which means + * we do garbage collection before waiting for a char at the toplevel. */ +EXTERN int may_garbage_collect INIT(= FALSE); +EXTERN int want_garbage_collect INIT(= FALSE); + +/* ID of script being sourced or was sourced to define the current function. */ +EXTERN scid_T current_SID INIT(= 0); #endif #if defined(FEAT_EVAL) || defined(FEAT_SYN_HL) @@ -547,6 +555,10 @@ EXTERN buf_T *lastbuf INIT(= NULL); /* last buffer */ EXTERN buf_T *curbuf INIT(= NULL); /* currently active buffer */ +/* Flag that is set when switching off 'swapfile'. It means that all blocks + * are to be loaded into memory. Shouldn't be global... */ +EXTERN int mf_dont_release INIT(= FALSE); /* don't release blocks */ + /* * List of files being edited (global argument list). curwin->w_alist points * to this when the window is using the global argument list. @@ -1441,7 +1453,7 @@ EXTERN char_u e_readonly[] INIT(= N_("E45: 'readonly' option is set (add ! to override)")); #ifdef FEAT_EVAL EXTERN char_u e_readonlyvar[] INIT(= N_("E46: Cannot change read-only variable \"%s\"")); -EXTERN char_u e_readonlysbx[] INIT(= N_("E46: Cannot set variable in the sandbox: \"%s\"")); +EXTERN char_u e_readonlysbx[] INIT(= N_("E794: Cannot set variable in the sandbox: \"%s\"")); #endif #ifdef FEAT_QUICKFIX EXTERN char_u e_readerrf[] INIT(= N_("E47: Error while reading errorfile")); diff -Naur vim70.orig/src/gui.c vim70/src/gui.c --- vim70.orig/src/gui.c 2006-05-03 04:00:59.000000000 -0700 +++ vim70/src/gui.c 2007-02-15 21:22:26.000000000 -0800 @@ -187,9 +187,10 @@ #endif #ifdef FEAT_AUTOCMD - /* If the GUI started successfully, trigger the GUIEnter event */ - if (gui.in_use) - apply_autocmds(EVENT_GUIENTER, NULL, NULL, FALSE, curbuf); + /* If the GUI started successfully, trigger the GUIEnter event, otherwise + * the GUIFailed event. */ + apply_autocmds(gui.in_use ? EVENT_GUIENTER : EVENT_GUIFAILED, + NULL, NULL, FALSE, curbuf); #endif --recursive; @@ -636,6 +637,7 @@ #if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_X11) || defined(FEAT_GUI_MSWIN) \ || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) || defined(PROTO) +# define NEED_GUI_UPDATE_SCREEN 1 /* * Called when the GUI shell is closed by the user. If there are no changed * files Vim exits, otherwise there will be a dialog to ask the user what to @@ -664,8 +666,7 @@ exiting = FALSE; cmdmod = save_cmdmod; - setcursor(); /* position cursor */ - out_flush(); + gui_update_screen(); /* redraw, window may show changed buffer */ } #endif @@ -2872,6 +2873,9 @@ */ if ((State == NORMAL || State == NORMAL_BUSY || (State & INSERT)) && Y_2_ROW(y) >= topframe->fr_height +# ifdef FEAT_WINDOWS + + firstwin->w_winrow +# endif && button != MOUSE_DRAG # ifdef FEAT_MOUSESHAPE && !drag_status_line @@ -3733,6 +3737,12 @@ if (dont_scroll || input_available()) return; #endif +#ifdef FEAT_INS_EXPAND + /* Disallow scrolling the current window when the completion popup menu is + * visible. */ + if ((sb->wp == NULL || sb->wp == curwin) && pum_visible()) + return; +#endif #ifdef FEAT_RIGHTLEFT if (sb->wp == NULL && curwin->w_p_rl) @@ -4207,6 +4217,12 @@ updateWindow(wp); /* update window, status line, and cmdline */ } +#ifdef FEAT_INS_EXPAND + /* May need to redraw the popup menu. */ + if (pum_visible()) + pum_redraw(); +#endif + return (wp == curwin && !equalpos(curwin->w_cursor, old_cursor)); } @@ -4515,7 +4531,7 @@ int y; { win_T *wp; - char_u st[6]; + char_u st[8]; /* Ignore this while still starting up. */ if (!gui.in_use || gui.starting) @@ -4603,11 +4619,11 @@ /* Don't move the mouse when it's left or right of the Vim window */ if (x < 0 || x > Columns * gui.char_width) return; + if (y >= 0 # ifdef FEAT_WINDOWS - if (Y_2_ROW(y) >= tabline_height()) -# else - if (y >= 0) + && Y_2_ROW(y) >= tabline_height() # endif + ) wp = xy2win(x, y); if (wp != curwin && wp != NULL) /* If in other than current window */ { @@ -4807,6 +4823,7 @@ #endif #if defined(FIND_REPLACE_DIALOG) || defined(FEAT_SUN_WORKSHOP) \ + || defined(NEED_GUI_UPDATE_SCREEN) \ || defined(PROTO) /* * Update the current window and the screen. diff -Naur vim70.orig/src/gui_at_fs.c vim70/src/gui_at_fs.c --- vim70.orig/src/gui_at_fs.c 2005-07-09 04:30:17.000000000 -0700 +++ vim70/src/gui_at_fs.c 2007-02-15 21:22:24.000000000 -0800 @@ -1861,27 +1861,27 @@ XtPointer pnew; { SFDir *dir; - int nw; + int nw = (int)(long)pnew; dir = &(SFdirs[SFdirPtr + (int)(long)n]); #ifdef FEAT_GUI_NEXTAW - if ((int)(long)pnew < 0) + if (nw < 0) { - if ((int)(long)pnew > -SFvScrollHeight) - (int)(long)pnew = -1; + if (nw > -SFvScrollHeight) + nw = -1; else - (int)(long)pnew = -SFlistSize; + nw = -SFlistSize; } - else if ((int)(long)pnew > 0) + else if (nw > 0) { - if ((int)(long)pnew < SFvScrollHeight) - (int)(long)pnew = 1; + if (nw < SFvScrollHeight) + nw = 1; else - (int)(long)pnew = SFlistSize; + nw = SFlistSize; } #endif - nw = dir->vOrigin + (int)(long)pnew; + nw += dir->vOrigin; if (nw > dir->nEntries - SFlistSize) nw = dir->nEntries - SFlistSize; @@ -1941,27 +1941,27 @@ XtPointer pnew; { SFDir *dir; - int nw; + int nw = (int)(long)pnew; dir = &(SFdirs[SFdirPtr + (int)(long)n]); #ifdef FEAT_GUI_NEXTAW - if ((int)(long)pnew < 0) + if (nw < 0) { - if ((int)(long)pnew > -SFhScrollWidth) - (int)(long)pnew = -1; + if (nw > -SFhScrollWidth) + nw = -1; else - (int)(long)pnew = -SFcharsPerEntry; + nw = -SFcharsPerEntry; } - else if ((int)(long)pnew > 0) + else if (nw > 0) { - if ((int)(long)pnew < SFhScrollWidth) - (int)(long)pnew = 1; + if (nw < SFhScrollWidth) + nw = 1; else - (int)(long)pnew = SFcharsPerEntry; + nw = SFcharsPerEntry; } #endif - nw = dir->hOrigin + (int)(long)pnew; + nw += dir->hOrigin; if (nw > dir->nChars - SFcharsPerEntry) nw = dir->nChars - SFcharsPerEntry; @@ -2038,26 +2038,26 @@ XtPointer client_data; XtPointer pnew; { - int nw; + int nw = (int)(long)pnew; float f; #ifdef FEAT_GUI_NEXTAW - if ((int)(long)pnew < 0) + if (nw < 0) { - if ((int)(long)pnew > -SFpathScrollWidth) - (int)(long)pnew = -1; + if (nw > -SFpathScrollWidth) + nw = -1; else - (int)(long)pnew = -3; + nw = -3; } - else if ((int)(long)pnew > 0) + else if (nw > 0) { - if ((int)(long)pnew < SFpathScrollWidth) - (int)(long)pnew = 1; + if (nw < SFpathScrollWidth) + nw = 1; else - (int)(long)pnew = 3; + nw = 3; } #endif - nw = SFdirPtr + (int)(long)pnew; + nw += SFdirPtr; if (nw > SFdirEnd - 3) nw = SFdirEnd - 3; diff -Naur vim70.orig/src/gui_beval.c vim70/src/gui_beval.c --- vim70.orig/src/gui_beval.c 2006-05-04 12:29:51.000000000 -0700 +++ vim70/src/gui_beval.c 2007-02-15 21:22:25.000000000 -0800 @@ -926,7 +926,7 @@ # define IS_NONPRINTABLE(c) (((c) < 0x20 && (c) != TAB && (c) != NL) \ || (c) == DEL) static void -set_printable_label_text(GtkLabel *label, char_u *msg) +set_printable_label_text(GtkLabel *label, char_u *text) { char_u *convbuf = NULL; char_u *buf; @@ -940,14 +940,14 @@ /* Convert to UTF-8 if it isn't already */ if (output_conv.vc_type != CONV_NONE) { - convbuf = string_convert(&output_conv, msg, NULL); + convbuf = string_convert(&output_conv, text, NULL); if (convbuf != NULL) - msg = convbuf; + text = convbuf; } /* First let's see how much we need to allocate */ len = 0; - for (p = msg; *p != NUL; p += charlen) + for (p = text; *p != NUL; p += charlen) { if ((*p & 0x80) == 0) /* be quick for ASCII */ { @@ -992,7 +992,7 @@ (unsigned long)pixel, &color); pdest = buf; - p = msg; + p = text; while (*p != NUL) { /* Be quick for ASCII */ diff -Naur vim70.orig/src/gui_gtk.c vim70/src/gui_gtk.c --- vim70.orig/src/gui_gtk.c 2006-05-05 04:52:52.000000000 -0700 +++ vim70/src/gui_gtk.c 2007-02-15 21:22:26.000000000 -0800 @@ -957,15 +957,15 @@ get_menu_position(vimmenu_T *menu) { vimmenu_T *node; - int index = 0; + int idx = 0; for (node = menu->parent->children; node != menu; node = node->next) { g_return_val_if_fail(node != NULL, -1); - ++index; + ++idx; } - return index; + return idx; } #endif /* FEAT_TOOLBAR && HAVE_GTK2 */ @@ -1275,18 +1275,13 @@ title = CONVERT_TO_UTF8(title); # endif - /* Concatenate "initdir" and "dflt". */ + /* GTK has a bug, it only works with an absolute path. */ if (initdir == NULL || *initdir == NUL) mch_dirname(dirbuf, MAXPATHL); - else if (STRLEN(initdir) + 2 < MAXPATHL) - STRCPY(dirbuf, initdir); - else + else if (vim_FullName(initdir, dirbuf, MAXPATHL - 2, FALSE) == FAIL) dirbuf[0] = NUL; /* Always need a trailing slash for a directory. */ add_pathsep(dirbuf); - if (dflt != NULL && *dflt != NUL - && STRLEN(dirbuf) + 2 + STRLEN(dflt) < MAXPATHL) - STRCAT(dirbuf, dflt); /* If our pointer is currently hidden, then we should show it. */ gui_mch_mousehide(FALSE); @@ -1298,8 +1293,8 @@ GTK_WINDOW(gui.mainwin), saving ? GTK_FILE_CHOOSER_ACTION_SAVE : GTK_FILE_CHOOSER_ACTION_OPEN, - saving ? GTK_STOCK_SAVE : GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + saving ? GTK_STOCK_SAVE : GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fc), (const gchar *)dirbuf); @@ -1341,6 +1336,11 @@ else gtk_window_set_title(GTK_WINDOW(gui.filedlg), (const gchar *)title); + /* Concatenate "initdir" and "dflt". */ + if (dflt != NULL && *dflt != NUL + && STRLEN(dirbuf) + 2 + STRLEN(dflt) < MAXPATHL) + STRCAT(dirbuf, dflt); + gtk_file_selection_set_filename(GTK_FILE_SELECTION(gui.filedlg), (const gchar *)dirbuf); # ifndef HAVE_GTK2 @@ -2127,7 +2127,7 @@ char **ync; /* "yes no cancel" */ char **buttons; int n_buttons = 0; - int index; + int idx; button_string = vim_strsave(button_string); /* must be writable */ if (button_string == NULL) @@ -2161,12 +2161,12 @@ * Well, apparently somebody changed his mind: with GTK 2.2.4 it works the * other way around... */ - for (index = 1; index <= n_buttons; ++index) + for (idx = 1; idx <= n_buttons; ++idx) { char *label; char_u *label8; - label = buttons[index - 1]; + label = buttons[idx - 1]; /* * Perform some guesswork to find appropriate stock items for the * buttons. We have to compare with a sample of the translated @@ -2188,7 +2188,7 @@ else if (button_equal(label, "Cancel")) label = GTK_STOCK_CANCEL; } label8 = CONVERT_TO_UTF8((char_u *)label); - gtk_dialog_add_button(dialog, (const gchar *)label8, index); + gtk_dialog_add_button(dialog, (const gchar *)label8, idx); CONVERT_TO_UTF8_FREE(label8); } diff -Naur vim70.orig/src/gui_gtk_x11.c vim70/src/gui_gtk_x11.c --- vim70.orig/src/gui_gtk_x11.c 2006-05-04 23:58:59.000000000 -0700 +++ vim70/src/gui_gtk_x11.c 2007-02-15 21:22:25.000000000 -0800 @@ -3233,12 +3233,12 @@ on_select_tab( GtkNotebook *notebook, GtkNotebookPage *page, - gint index, + gint idx, gpointer data) { if (!ignore_tabline_evt) { - if (send_tabline_event(index + 1) && gtk_main_level() > 0) + if (send_tabline_event(idx + 1) && gtk_main_level() > 0) gtk_main_quit(); } } @@ -5303,13 +5303,13 @@ # ifdef HAVE_GTK2 if (font != NOFONT) { - char *name = pango_font_description_to_string(font); + char *pangoname = pango_font_description_to_string(font); - if (name != NULL) + if (pangoname != NULL) { - char_u *s = vim_strsave((char_u *)name); + char_u *s = vim_strsave((char_u *)pangoname); - g_free(name); + g_free(pangoname); return s; } } @@ -6241,24 +6241,20 @@ { GdkGCValues values; GdkGC *invert_gc; - GdkColor foreground; - GdkColor background; if (gui.drawarea->window == NULL) return; - foreground.pixel = gui.norm_pixel ^ gui.back_pixel; - background.pixel = gui.norm_pixel ^ gui.back_pixel; - - values.foreground = foreground; - values.background = background; + values.foreground.pixel = gui.norm_pixel ^ gui.back_pixel; + values.background.pixel = gui.norm_pixel ^ gui.back_pixel; values.function = GDK_XOR; invert_gc = gdk_gc_new_with_values(gui.drawarea->window, &values, GDK_GC_FOREGROUND | GDK_GC_BACKGROUND | GDK_GC_FUNCTION); - gdk_gc_set_exposures(invert_gc, gui.visibility != GDK_VISIBILITY_UNOBSCURED); + gdk_gc_set_exposures(invert_gc, gui.visibility != + GDK_VISIBILITY_UNOBSCURED); gdk_draw_rectangle(gui.drawarea->window, invert_gc, TRUE, FILL_X(c), FILL_Y(r), diff -Naur vim70.orig/src/gui_xmebw.c vim70/src/gui_xmebw.c --- vim70.orig/src/gui_xmebw.c 2006-04-30 08:32:32.000000000 -0700 +++ vim70/src/gui_xmebw.c 2007-02-15 21:22:26.000000000 -0800 @@ -47,13 +47,13 @@ #include "gui_xmebwp.h" /* Provide some missing wrappers, which are missed from the LessTif - * implementation. + * implementation. Also missing in Motif 1.2 and earlier. * * We neither use XmeGetPixmapData or _XmGetPixmapData, since with LessTif the * pixmap will not appear in it's caches properly. We cache the interresting * values in XmEnhancedButtonPart instead ourself. */ -#ifdef LESSTIF_VERSION +#if defined(LESSTIF_VERSION) || (XmVersion <= 1002) # ifndef Lab_IsMenupane # define Lab_IsMenupane(w) (Lab_MenuType(w) == (int)XmMENU_POPUP || \ Lab_MenuType(w) == (int)XmMENU_PULLDOWN) @@ -138,6 +138,19 @@ } }; +/* This is needed to work around a bug in Lesstif 2, leaving the extension + * NULL somehow results in getting it set to an invalid pointer. */ +XmPrimitiveClassExtRec xmEnhancedButtonPrimClassExtRec = +{ + /* next_extension */ NULL, + /* record_type */ NULLQUARK, + /* version */ XmPrimitiveClassExtVersion, + /* record_size */ sizeof(XmPrimitiveClassExtRec), + /* widget_baseline */ XmInheritBaselineProc, + /* widget_display_rect */ XmInheritDisplayRectProc, + /* widget_margins */ NULL +}; + XmEnhancedButtonClassRec xmEnhancedButtonClassRec = { { @@ -184,7 +197,7 @@ /* arm and activate */ XmInheritArmAndActivate, /* synthetic resources */ NULL, /* number of syn res */ 0, - /* extension */ NULL, + /* extension */ (XtPointer)&xmEnhancedButtonPrimClassExtRec, }, /* label_class fields */ @@ -480,7 +493,7 @@ || (eb->core.height <= 2 * eb->primitive.highlight_thickness)) return; -#ifndef LESSTIF_VERSION +#if !defined(LESSTIF_VERSION) && (XmVersion > 1002) { XmDisplay dpy; @@ -641,7 +654,7 @@ GC tmp_gc = NULL; Boolean replaceGC = False; Boolean deadjusted = False; -#ifndef LESSTIF_VERSION +#if !defined(LESSTIF_VERSION) && (XmVersion > 1002) XmDisplay dpy = (XmDisplay)XmGetXmDisplay(XtDisplay(eb)); Boolean etched_in = dpy->display.enable_etched_in_menu; #else @@ -726,7 +739,7 @@ if ((((ShellWidget) XtParent(XtParent(eb)))->shell.popped_up) && _XmGetInDragMode((Widget) eb)) { -#ifndef LESSTIF_VERSION +#if !defined(LESSTIF_VERSION) && (XmVersion > 1002) XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid)); Boolean etched_in = dpy->display.enable_etched_in_menu; #else @@ -810,7 +823,7 @@ if (Lab_IsMenupane(eb)) { -#ifndef LESSTIF_VERSION +#if !defined(LESSTIF_VERSION) && (XmVersion > 1002) XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid)); Boolean etched_in = dpy->display.enable_etched_in_menu; #else @@ -1150,7 +1163,7 @@ Redisplay(Widget w, XEvent *event, Region region) { XmEnhancedButtonWidget eb = (XmEnhancedButtonWidget) w; -#ifndef LESSTIF_VERSION +#if !defined(LESSTIF_VERSION) && (XmVersion > 1002) XmDisplay dpy; XtEnum default_button_emphasis; #endif @@ -1162,7 +1175,7 @@ if (!XtIsRealized((Widget)eb)) return; -#ifndef LESSTIF_VERSION +#if !defined(LESSTIF_VERSION) && (XmVersion > 1002) dpy = (XmDisplay)XmGetXmDisplay(XtDisplay(eb)); default_button_emphasis = dpy->display.default_button_emphasis; #endif @@ -1241,7 +1254,7 @@ { int adjust = 0; -#ifndef LESSTIF_VERSION +#if !defined(LESSTIF_VERSION) && (XmVersion > 1002) /* * NOTE: PushButton has two types of shadows: primitive-shadow and * default-button-shadow. If pushbutton is in a menu only primitive @@ -1289,7 +1302,7 @@ adjust, adjust, rectwidth, rectheight, borderwidth); } -#ifndef LESSTIF_VERSION +#if !defined(LESSTIF_VERSION) && (XmVersion > 1002) switch (default_button_emphasis) { case XmINTERNAL_HIGHLIGHT: @@ -1365,7 +1378,7 @@ default_button_shadow_thickness = eb->pushbutton.default_button_shadow_thickness; -#ifndef LESSTIF_VERSION +#if !defined(LESSTIF_VERSION) && (XmVersion > 1002) /* * Compute location of bounding box to contain the * defaultButtonShadow. diff -Naur vim70.orig/src/hardcopy.c vim70/src/hardcopy.c --- vim70.orig/src/hardcopy.c 2006-05-04 03:09:58.000000000 -0700 +++ vim70/src/hardcopy.c 2007-02-15 21:22:25.000000000 -0800 @@ -1794,29 +1794,27 @@ static int prt_resfile_next_line() { - int index; + int idx; /* Move to start of next line and then find end of line */ - index = prt_resfile.line_end + 1; - while (index < prt_resfile.len) + idx = prt_resfile.line_end + 1; + while (idx < prt_resfile.len) { - if (prt_resfile.buffer[index] != PSLF && prt_resfile.buffer[index] - != PSCR) + if (prt_resfile.buffer[idx] != PSLF && prt_resfile.buffer[idx] != PSCR) break; - index++; + idx++; } - prt_resfile.line_start = index; + prt_resfile.line_start = idx; - while (index < prt_resfile.len) + while (idx < prt_resfile.len) { - if (prt_resfile.buffer[index] == PSLF || prt_resfile.buffer[index] - == PSCR) + if (prt_resfile.buffer[idx] == PSLF || prt_resfile.buffer[idx] == PSCR) break; - index++; + idx++; } - prt_resfile.line_end = index; + prt_resfile.line_end = idx; - return (index < prt_resfile.len); + return (idx < prt_resfile.len); } static int @@ -1837,14 +1835,14 @@ prt_resfile_skip_nonws(offset) int offset; { - int index; + int idx; - index = prt_resfile.line_start + offset; - while (index < prt_resfile.line_end) + idx = prt_resfile.line_start + offset; + while (idx < prt_resfile.line_end) { - if (isspace(prt_resfile.buffer[index])) - return index - prt_resfile.line_start; - index++; + if (isspace(prt_resfile.buffer[idx])) + return idx - prt_resfile.line_start; + idx++; } return -1; } @@ -1853,14 +1851,14 @@ prt_resfile_skip_ws(offset) int offset; { - int index; + int idx; - index = prt_resfile.line_start + offset; - while (index < prt_resfile.line_end) + idx = prt_resfile.line_start + offset; + while (idx < prt_resfile.line_end) { - if (!isspace(prt_resfile.buffer[index])) - return index - prt_resfile.line_start; - index++; + if (!isspace(prt_resfile.buffer[idx])) + return idx - prt_resfile.line_start; + idx++; } return -1; } @@ -2478,7 +2476,7 @@ char_u *p_encoding; struct prt_ps_encoding_S *p_mbenc; struct prt_ps_encoding_S *p_mbenc_first; - struct prt_ps_charset_S *p_mbchar; + struct prt_ps_charset_S *p_mbchar = NULL; #endif #if 0 @@ -2516,7 +2514,6 @@ if (!(props & ENC_8BIT) && ((*p_pmcs != NUL) || !(props & ENC_UNICODE))) { p_mbenc_first = NULL; - p_mbchar = NULL; for (cmap = 0; cmap < NUM_ELEMENTS(prt_ps_mbfonts); cmap++) if (prt_match_encoding((char *)p_encoding, &prt_ps_mbfonts[cmap], &p_mbenc)) diff -Naur vim70.orig/src/if_cscope.c vim70/src/if_cscope.c --- vim70.orig/src/if_cscope.c 2006-04-18 01:54:15.000000000 -0700 +++ vim70/src/if_cscope.c 2007-02-15 21:22:27.000000000 -0800 @@ -627,10 +627,11 @@ * If the database is out of date, or there's some other problem, * cscope will output error messages before the number-of-lines output. * Display/discard any output that doesn't match what we want. + * Accept "\S*cscope: X lines", also matches "mlcscope". */ if ((stok = strtok(buf, (const char *)" ")) == NULL) continue; - if (strcmp((const char *)stok, "cscope:")) + if (strstr((const char *)stok, "cscope:") == NULL) continue; if ((stok = strtok(NULL, (const char *)" ")) == NULL) @@ -989,8 +990,7 @@ { int i; char *cmd; - char **matches, **contexts; - int nummatches[CSCOPE_MAX_CONNECTIONS], totmatches, matched; + int nummatches[CSCOPE_MAX_CONNECTIONS], totmatches; #ifdef FEAT_QUICKFIX char cmdletter; char *qfpos; @@ -1009,7 +1009,7 @@ totmatches = 0; for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++) { - if (csinfo[i].fname == NULL) + if (csinfo[i].fname == NULL || csinfo[i].to_fp == NULL) continue; /* send cmd to cscope */ @@ -1101,38 +1101,44 @@ if (qfpos != NULL && *qfpos != '0' && totmatches > 0) { /* fill error list */ - FILE *f; - char_u *tmp = vim_tempname('c'); + FILE *f; + char_u *tmp = vim_tempname('c'); qf_info_T *qi = NULL; win_T *wp = NULL; f = mch_fopen((char *)tmp, "w"); - cs_file_results(f, nummatches); - fclose(f); - if (use_ll) /* Use location list */ - wp = curwin; - /* '-' starts a new error list */ - if (qf_init(wp, tmp, (char_u *)"%f%*\\t%l%*\\t%m", *qfpos == '-') > 0) + if (f == NULL) + EMSG2(_(e_notopen), tmp); + else { -# ifdef FEAT_WINDOWS - if (postponed_split != 0) + cs_file_results(f, nummatches); + fclose(f); + if (use_ll) /* Use location list */ + wp = curwin; + /* '-' starts a new error list */ + if (qf_init(wp, tmp, (char_u *)"%f%*\\t%l%*\\t%m", + *qfpos == '-') > 0) { - win_split(postponed_split > 0 ? postponed_split : 0, +# ifdef FEAT_WINDOWS + if (postponed_split != 0) + { + win_split(postponed_split > 0 ? postponed_split : 0, postponed_split_flags); # ifdef FEAT_SCROLLBIND - curwin->w_p_scb = FALSE; + curwin->w_p_scb = FALSE; # endif - postponed_split = 0; - } + postponed_split = 0; + } # endif - if (use_ll) - /* - * In the location list window, use the displayed location - * list. Otherwise, use the location list for the window. - */ - qi = (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL) ? - wp->w_llist_ref : wp->w_llist; - qf_jump(qi, 0, 0, forceit); + if (use_ll) + /* + * In the location list window, use the displayed location + * list. Otherwise, use the location list for the window. + */ + qi = (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL) + ? wp->w_llist_ref : wp->w_llist; + qf_jump(qi, 0, 0, forceit); + } } mch_remove(tmp); vim_free(tmp); @@ -1141,6 +1147,9 @@ else #endif /* FEAT_QUICKFIX */ { + char **matches = NULL, **contexts = NULL; + int matched = 0; + /* read output */ cs_fill_results((char *)pat, totmatches, nummatches, &matches, &contexts, &matched); @@ -1721,7 +1730,7 @@ continue; context = (char *)alloc((unsigned)strlen(cntx)+5); - if (context==NULL) + if (context == NULL) continue; if (strcmp(cntx, "")==0) @@ -1729,7 +1738,7 @@ else sprintf(context, "<<%s>>", cntx); - if (search==NULL) + if (search == NULL) fprintf(f, "%s\t%s\t%s\n", fullname, slno, context); else fprintf(f, "%s\t%s\t%s %s\n", fullname, slno, context, search); diff -Naur vim70.orig/src/if_perl.xs vim70/src/if_perl.xs --- vim70.orig/src/if_perl.xs 2006-03-06 10:57:16.000000000 -0800 +++ vim70/src/if_perl.xs 2007-02-15 21:22:24.000000000 -0800 @@ -155,8 +155,8 @@ static int (*perl_run)(PerlInterpreter*); static int (*perl_parse)(PerlInterpreter*, XSINIT_t, int, char**, char**); static void* (*Perl_get_context)(void); -static void (*Perl_croak)(pTHX_ const char*, ...) __attribute__((noreturn)); -static void (*Perl_croak_nocontext)(const char*, ...) __attribute__((noreturn)); +static void (*Perl_croak)(pTHX_ const char*, ...); +static void (*Perl_croak_nocontext)(const char*, ...); static I32 (*Perl_dowantarray)(pTHX); static void (*Perl_free_tmps)(pTHX); static HV* (*Perl_gv_stashpv)(pTHX_ const char*, I32); @@ -1056,7 +1056,6 @@ int i; long lnum; char *line; - buf_T *savebuf; PPCODE: if (buf_valid(vimbuf)) { @@ -1069,14 +1068,20 @@ line = SvPV(ST(i),PL_na); if (lnum > 0 && lnum <= vimbuf->b_ml.ml_line_count && line != NULL) { - savebuf = curbuf; - curbuf = vimbuf; + aco_save_T aco; + + /* set curwin/curbuf for "vimbuf" and save some things */ + aucmd_prepbuf(&aco, vimbuf); + if (u_savesub(lnum) == OK) { ml_replace(lnum, (char_u *)line, TRUE); changed_bytes(lnum, 0); } - curbuf = savebuf; + + /* restore curwin/curbuf and a few other things */ + aucmd_restbuf(&aco); + /* Careful: autocommands may have made "vimbuf" invalid! */ } } } @@ -1087,7 +1092,6 @@ PREINIT: long i, lnum = 0, count = 0; - buf_T *savebuf; PPCODE: if (buf_valid(vimbuf)) { @@ -1114,16 +1118,23 @@ { if (lnum > 0 && lnum <= vimbuf->b_ml.ml_line_count) { - savebuf = curbuf; - curbuf = vimbuf; + aco_save_T aco; + + /* set curwin/curbuf for "vimbuf" and save some things */ + aucmd_prepbuf(&aco, vimbuf); + if (u_savedel(lnum, 1) == OK) { ml_delete(lnum, 0); deleted_lines_mark(lnum, 1L); - if (savebuf == curbuf) + if (aco.save_buf == curbuf) check_cursor(); } - curbuf = savebuf; + + /* restore curwin/curbuf and a few other things */ + aucmd_restbuf(&aco); + /* Careful: autocommands may have made "vimbuf" invalid! */ + update_curbuf(VALID); } } @@ -1138,7 +1149,6 @@ int i; long lnum; char *line; - buf_T *savebuf; PPCODE: if (buf_valid(vimbuf)) { @@ -1151,14 +1161,21 @@ line = SvPV(ST(i),PL_na); if (lnum >= 0 && lnum <= vimbuf->b_ml.ml_line_count && line != NULL) { - savebuf = curbuf; - curbuf = vimbuf; + aco_save_T aco; + + /* set curwin/curbuf for "vimbuf" and save some things */ + aucmd_prepbuf(&aco, vimbuf); + if (u_inssub(lnum + 1) == OK) { ml_append(lnum, (char_u *)line, (colnr_T)0, FALSE); appended_lines_mark(lnum, 1L); } - curbuf = savebuf; + + /* restore curwin/curbuf and a few other things */ + aucmd_restbuf(&aco); + /* Careful: autocommands may have made "vimbuf" invalid! */ + update_curbuf(VALID); } } diff -Naur vim70.orig/src/if_python.c vim70/src/if_python.c --- vim70.orig/src/if_python.c 2006-04-30 08:31:36.000000000 -0700 +++ vim70/src/if_python.c 2007-02-15 21:22:25.000000000 -0800 @@ -1463,7 +1463,7 @@ if (this->buf && this->buf != INVALID_BUFFER_VALUE) this->buf->b_python_ref = NULL; - PyMem_DEL(self); + Py_DECREF(self); } static PyObject * @@ -1674,7 +1674,7 @@ bufr = (BufferObject *)BufferNew(buf); if (bufr == NULL) { - PyMem_DEL(self); + Py_DECREF(self); return NULL; } Py_INCREF(bufr); @@ -1690,7 +1690,7 @@ RangeDestructor(PyObject *self) { Py_DECREF(((RangeObject *)(self))->buf); - PyMem_DEL(self); + Py_DECREF(self); } static PyObject * @@ -1944,7 +1944,7 @@ if (this->win && this->win != INVALID_WINDOW_VALUE) this->win->w_python_ref = NULL; - PyMem_DEL(self); + Py_DECREF(self); } static int diff -Naur vim70.orig/src/if_ruby.c vim70/src/if_ruby.c --- vim70.orig/src/if_ruby.c 2006-04-30 08:37:52.000000000 -0700 +++ vim70/src/if_ruby.c 2007-02-15 21:22:24.000000000 -0800 @@ -643,11 +643,14 @@ static VALUE set_buffer_line(buf_T *buf, linenr_T n, VALUE str) { - buf_T *savebuf = curbuf; - char *line = STR2CSTR(str); + char *line = STR2CSTR(str); + aco_save_T aco; + + if (n > 0 && n <= buf->b_ml.ml_line_count && line != NULL) + { + /* set curwin/curbuf for "buf" and save some things */ + aucmd_prepbuf(&aco, buf); - if (n > 0 && n <= buf->b_ml.ml_line_count && line != NULL) { - curbuf = buf; if (u_savesub(n) == OK) { ml_replace(n, (char_u *)line, TRUE); changed(); @@ -655,10 +658,15 @@ syn_changed(n); /* recompute syntax hl. for this line */ #endif } - curbuf = savebuf; + + /* restore curwin/curbuf and a few other things */ + aucmd_restbuf(&aco); + /* Careful: autocommands may have made "buf" invalid! */ + update_curbuf(NOT_VALID); } - else { + else + { rb_raise(rb_eIndexError, "index %d out of buffer", n); return Qnil; /* For stop warning */ } @@ -676,12 +684,15 @@ static VALUE buffer_delete(VALUE self, VALUE num) { - buf_T *buf = get_buf(self); - buf_T *savebuf = curbuf; - long n = NUM2LONG(num); + buf_T *buf = get_buf(self); + long n = NUM2LONG(num); + aco_save_T aco; + + if (n > 0 && n <= buf->b_ml.ml_line_count) + { + /* set curwin/curbuf for "buf" and save some things */ + aucmd_prepbuf(&aco, buf); - if (n > 0 && n <= buf->b_ml.ml_line_count) { - curbuf = buf; if (u_savedel(n, 1) == OK) { ml_delete(n, 0); @@ -691,10 +702,15 @@ changed(); } - curbuf = savebuf; + + /* restore curwin/curbuf and a few other things */ + aucmd_restbuf(&aco); + /* Careful: autocommands may have made "buf" invalid! */ + update_curbuf(NOT_VALID); } - else { + else + { rb_raise(rb_eIndexError, "index %d out of buffer", n); } return Qnil; @@ -702,13 +718,16 @@ static VALUE buffer_append(VALUE self, VALUE num, VALUE str) { - buf_T *buf = get_buf(self); - buf_T *savebuf = curbuf; - char *line = STR2CSTR(str); - long n = NUM2LONG(num); + buf_T *buf = get_buf(self); + char *line = STR2CSTR(str); + long n = NUM2LONG(num); + aco_save_T aco; + + if (n >= 0 && n <= buf->b_ml.ml_line_count && line != NULL) + { + /* set curwin/curbuf for "buf" and save some things */ + aucmd_prepbuf(&aco, buf); - if (n >= 0 && n <= buf->b_ml.ml_line_count && line != NULL) { - curbuf = buf; if (u_inssub(n + 1) == OK) { ml_append(n, (char_u *) line, (colnr_T) 0, FALSE); @@ -718,7 +737,11 @@ changed(); } - curbuf = savebuf; + + /* restore curwin/curbuf and a few other things */ + aucmd_restbuf(&aco); + /* Careful: autocommands may have made "buf" invalid! */ + update_curbuf(NOT_VALID); } else { diff -Naur vim70.orig/src/macros.h vim70/src/macros.h --- vim70.orig/src/macros.h 2006-03-01 04:01:10.000000000 -0800 +++ vim70/src/macros.h 2007-02-15 21:22:25.000000000 -0800 @@ -276,3 +276,9 @@ # define MB_CHARLEN(p) STRLEN(p) # define PTR2CHAR(p) ((int)*(p)) #endif + +#ifdef FEAT_AUTOCHDIR +# define DO_AUTOCHDIR if (p_acd) do_autochdir(); +#else +# define DO_AUTOCHDIR +#endif diff -Naur vim70.orig/src/main.c vim70/src/main.c --- vim70.orig/src/main.c 2006-05-03 10:36:44.000000000 -0700 +++ vim70/src/main.c 2007-02-15 21:22:26.000000000 -0800 @@ -564,7 +564,11 @@ */ if (p_lpl) { +# ifdef VMS /* Somehow VMS doesn't handle the "**". */ + source_runtime((char_u *)"plugin/*.vim", TRUE); +# else source_runtime((char_u *)"plugin/**/*.vim", TRUE); +# endif TIME_MSG("loading plugins"); } #endif @@ -1126,6 +1130,16 @@ */ update_curswant(); +#ifdef FEAT_EVAL + /* + * May perform garbage collection when waiting for a character, but + * only at the very toplevel. Otherwise we may be using a List or + * Dict internally somewhere. + * "may_garbage_collect" is reset in vgetc() which is invoked through + * do_exmode() and normal_cmd(). + */ + may_garbage_collect = (!cmdwin && !noexmode); +#endif /* * If we're invoked as ex, do a round of ex commands. * Otherwise, get and execute a normal mode command. @@ -2281,7 +2295,7 @@ mparm_T *parmp; { #ifdef FEAT_WINDOWS - int rewind; + int dorewind; int done = 0; /* @@ -2338,10 +2352,10 @@ ++autocmd_no_leave; #endif #ifdef FEAT_WINDOWS - rewind = TRUE; + dorewind = TRUE; while (done++ < 1000) { - if (rewind) + if (dorewind) { if (parmp->window_layout == WIN_TABS) goto_tabpage(1); @@ -2360,7 +2374,7 @@ break; curwin = curwin->w_next; } - rewind = FALSE; + dorewind = FALSE; #endif curbuf = curwin->w_buffer; if (curbuf->b_ml.ml_mfp == NULL) @@ -2378,10 +2392,26 @@ (void)open_buffer(FALSE, NULL); /* create memfile, read file */ #if defined(HAS_SWAP_EXISTS_ACTION) - check_swap_exists_action(); + if (swap_exists_action == SEA_QUIT) + { + if (got_int || only_one_window()) + { + /* abort selected or quit and only one window */ + did_emsg = FALSE; /* avoid hit-enter prompt */ + getout(1); + } + /* We can't close the window, it would disturb what + * happens next. Clear the file name and set the arg + * index to -1 to delete it later. */ + setfname(curbuf, NULL, NULL, FALSE); + curwin->w_arg_idx = -1; + swap_exists_action = SEA_NONE; + } + else + handle_swap_exists(NULL); #endif #ifdef FEAT_AUTOCMD - rewind = TRUE; /* start again */ + dorewind = TRUE; /* start again */ #endif } #ifdef FEAT_WINDOWS @@ -2418,6 +2448,8 @@ { int arg_idx; /* index in argument list */ int i; + int advance = TRUE; + buf_T *old_curbuf; # ifdef FEAT_AUTOCMD /* @@ -2426,31 +2458,65 @@ ++autocmd_no_enter; ++autocmd_no_leave; # endif + + /* When w_arg_idx is -1 remove the window (see create_windows()). */ + if (curwin->w_arg_idx == -1) + { + win_close(curwin, TRUE); + advance = FALSE; + } + arg_idx = 1; for (i = 1; i < parmp->window_count; ++i) { - if (parmp->window_layout == WIN_TABS) + /* When w_arg_idx is -1 remove the window (see create_windows()). */ + if (curwin->w_arg_idx == -1) { - if (curtab->tp_next == NULL) /* just checking */ - break; - goto_tabpage(0); + ++arg_idx; + win_close(curwin, TRUE); + advance = FALSE; + continue; } - else + + if (advance) { - if (curwin->w_next == NULL) /* just checking */ - break; - win_enter(curwin->w_next, FALSE); + if (parmp->window_layout == WIN_TABS) + { + if (curtab->tp_next == NULL) /* just checking */ + break; + goto_tabpage(0); + } + else + { + if (curwin->w_next == NULL) /* just checking */ + break; + win_enter(curwin->w_next, FALSE); + } } + advance = TRUE; /* Only open the file if there is no file in this window yet (that can - * happen when .vimrc contains ":sall") */ + * happen when .vimrc contains ":sall"). */ if (curbuf == firstwin->w_buffer || curbuf->b_ffname == NULL) { curwin->w_arg_idx = arg_idx; - /* edit file from arg list, if there is one */ + /* Edit file from arg list, if there is one. When "Quit" selected + * at the ATTENTION prompt close the window. */ + old_curbuf = curbuf; (void)do_ecmd(0, arg_idx < GARGCOUNT ? alist_name(&GARGLIST[arg_idx]) : NULL, NULL, NULL, ECMD_LASTL, ECMD_HIDE); + if (curbuf == old_curbuf) + { + if (got_int || only_one_window()) + { + /* abort selected or quit and only one window */ + did_emsg = FALSE; /* avoid hit-enter prompt */ + getout(1); + } + win_close(curwin, TRUE); + advance = FALSE; + } if (arg_idx == GARGCOUNT - 1) arg_had_last = TRUE; ++arg_idx; @@ -3208,10 +3274,15 @@ * Register for remote command execution with :serversend and --remote * unless there was a -X or a --servername '' on the command line. * Only register nongui-vim's with an explicit --servername argument. + * When running as root --servername is also required. */ if (X_DISPLAY != NULL && parmp->servername != NULL && ( # ifdef FEAT_GUI - gui.in_use || + (gui.in_use +# ifdef UNIX + && getuid() != 0 +# endif + ) || # endif parmp->serverName_arg != NULL)) { diff -Naur vim70.orig/src/mbyte.c vim70/src/mbyte.c --- vim70.orig/src/mbyte.c 2006-04-30 04:51:01.000000000 -0700 +++ vim70/src/mbyte.c 2007-02-15 21:22:27.000000000 -0800 @@ -311,7 +311,11 @@ #define IDX_MACROMAN 57 {"macroman", ENC_8BIT + ENC_MACROMAN, 0}, /* Mac OS */ -#define IDX_COUNT 58 +#define IDX_DECMCS 58 + {"dec-mcs", ENC_8BIT, 0}, /* DEC MCS */ +#define IDX_HPROMAN8 59 + {"hp-roman8", ENC_8BIT, 0}, /* HP Roman8 */ +#define IDX_COUNT 60 }; /* @@ -359,6 +363,8 @@ {"932", IDX_CP932}, {"949", IDX_CP949}, {"936", IDX_CP936}, + {"gbk", IDX_CP936}, + {"gb18030", IDX_CP936}, /* only 99% the same */ {"950", IDX_CP950}, {"eucjp", IDX_EUC_JP}, {"unix-jis", IDX_EUC_JP}, @@ -386,6 +392,7 @@ {"950", IDX_BIG5}, #endif {"mac", IDX_MACROMAN}, + {"mac-roman", IDX_MACROMAN}, {NULL, 0} }; @@ -2287,8 +2294,14 @@ } /* 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. */ @@ -3507,6 +3520,11 @@ add_to_input_buf(delkey, (int)sizeof(delkey)); } +/* + * Move the cursor left by "num_move_back" characters. + * Note that ins_left() checks im_is_preediting() to avoid breaking undo for + * these K_LEFT keys. + */ static void im_correct_cursor(int num_move_back) { @@ -3734,8 +3752,7 @@ } else if (cursor_index == 0 && preedit_string[0] == '\0') { - if (preedit_start_col == MAXCOL) - xim_has_preediting = FALSE; + xim_has_preediting = FALSE; /* If at the start position (after typing backspace) * preedit_start_col must be reset. */ @@ -3850,13 +3867,13 @@ if (preedit_string != NULL && attr_list != NULL) { - int index; + int idx; /* Get the byte index as used by PangoAttrIterator */ - for (index = 0; col > 0 && preedit_string[index] != '\0'; --col) - index += utfc_ptr2len((char_u *)preedit_string + index); + for (idx = 0; col > 0 && preedit_string[idx] != '\0'; --col) + idx += utfc_ptr2len((char_u *)preedit_string + idx); - if (preedit_string[index] != '\0') + if (preedit_string[idx] != '\0') { PangoAttrIterator *iter; int start, end; @@ -3869,7 +3886,7 @@ { pango_attr_iterator_range(iter, &start, &end); - if (index >= start && index < end) + if (idx >= start && idx < end) char_attr |= translate_pango_attributes(iter); } while (pango_attr_iterator_next(iter)); diff -Naur vim70.orig/src/memfile.c vim70/src/memfile.c --- vim70.orig/src/memfile.c 2006-03-06 00:59:15.000000000 -0800 +++ vim70/src/memfile.c 2007-02-15 21:22:27.000000000 -0800 @@ -76,7 +76,6 @@ #define MEMFILE_PAGE_SIZE 4096 /* default page size */ static long_u total_mem_used = 0; /* total memory used for memfiles */ -static int dont_release = FALSE; /* don't release blocks */ static void mf_ins_hash __ARGS((memfile_T *, bhdr_T *)); static void mf_rem_hash __ARGS((memfile_T *, bhdr_T *)); @@ -279,10 +278,10 @@ if (getlines) { /* get all blocks in memory by accessing all lines (clumsy!) */ - dont_release = TRUE; + mf_dont_release = TRUE; for (lnum = 1; lnum <= buf->b_ml.ml_line_count; ++lnum) (void)ml_get_buf(buf, lnum, FALSE); - dont_release = FALSE; + mf_dont_release = FALSE; /* TODO: should check if all blocks are really in core */ } @@ -517,7 +516,7 @@ mf_ins_free(mfp, hp); /* put *hp in the free list */ } -#if defined(__MORPHOS__) +#if defined(__MORPHOS__) && defined(__libnix__) /* function is missing in MorphOS libnix version */ extern unsigned long *__stdfiledes; @@ -677,15 +676,19 @@ # else # if defined(_DCC) || defined(__GNUC__) || defined(__MORPHOS__) { -# if defined(__GNUC__) && !defined(__MORPHOS__) +# if defined(__GNUC__) && !defined(__MORPHOS__) && defined(__libnix__) /* Have function (in libnix at least), * but ain't got no prototype anywhere. */ extern unsigned long fdtofh(int filedescriptor); # endif +# if !defined(__libnix__) + fflush(NULL); +# else BPTR fh = (BPTR)fdtofh(mfp->mf_fd); if (fh != 0) Flush(fh); +# endif } # else /* assume Manx */ Flush(_devtab[mfp->mf_fd].fd); @@ -826,7 +829,7 @@ buf_T *buf; /* don't release while in mf_close_file() */ - if (dont_release) + if (mf_dont_release) return NULL; /* @@ -1024,12 +1027,12 @@ size = page_size * hp->bh_page_count; if (lseek(mfp->mf_fd, offset, SEEK_SET) != offset) { - EMSG(_("E294: Seek error in swap file read")); + PERROR(_("E294: Seek error in swap file read")); return FAIL; } if ((unsigned)vim_read(mfp->mf_fd, hp->bh_data, size) != size) { - EMSG(_("E295: Read error in swap file")); + PERROR(_("E295: Read error in swap file")); return FAIL; } return OK; @@ -1081,7 +1084,7 @@ offset = (off_t)page_size * nr; if (lseek(mfp->mf_fd, offset, SEEK_SET) != offset) { - EMSG(_("E296: Seek error in swap file write")); + PERROR(_("E296: Seek error in swap file write")); return FAIL; } if (hp2 == NULL) /* freed block, fill with dummy data */ diff -Naur vim70.orig/src/memline.c vim70/src/memline.c --- vim70.orig/src/memline.c 2006-04-20 14:00:21.000000000 -0700 +++ vim70/src/memline.c 2007-02-15 21:22:27.000000000 -0800 @@ -215,7 +215,7 @@ #define ML_FLUSH 0x02 /* flush locked block */ #define ML_SIMPLE(x) (x & 0x10) /* DEL, INS or FIND */ -static void ml_upd_block0 __ARGS((buf_T *buf, int setfname)); +static void ml_upd_block0 __ARGS((buf_T *buf, int set_fname)); static void set_b0_fname __ARGS((ZERO_BL *, buf_T *buf)); static void set_b0_dir_flag __ARGS((ZERO_BL *b0p, buf_T *buf)); #ifdef FEAT_MBYTE @@ -679,9 +679,9 @@ * Update the timestamp or the B0_SAME_DIR flag of the .swp file. */ static void -ml_upd_block0(buf, setfname) +ml_upd_block0(buf, set_fname) buf_T *buf; - int setfname; + int set_fname; { memfile_T *mfp; bhdr_T *hp; @@ -695,7 +695,7 @@ EMSG(_("E304: ml_upd_block0(): Didn't get block 0??")); else { - if (setfname) + if (set_fname) set_b0_fname(b0p, buf); else set_b0_dir_flag(b0p, buf); @@ -1325,7 +1325,11 @@ mf_put(mfp, hp, FALSE, FALSE); mf_close(mfp, FALSE); /* will also vim_free(mfp->mf_fname) */ } - vim_free(buf); + if (buf != NULL) + { + vim_free(buf->b_ml.ml_stack); + vim_free(buf); + } if (serious_error && called_from_main) ml_close(curbuf, TRUE); #ifdef FEAT_AUTOCMD @@ -1633,6 +1637,7 @@ int fd; struct block0 b0; time_t x = (time_t)0; + char *p; #ifdef UNIX char_u uname[B0_UNAME_SIZE]; #endif @@ -1652,8 +1657,11 @@ #endif MSG_PUTS(_(" dated: ")); x = st.st_mtime; /* Manx C can't do &st.st_mtime */ - MSG_PUTS(ctime(&x)); /* includes '\n' */ - + p = ctime(&x); /* includes '\n' */ + if (p == NULL) + MSG_PUTS("(invalid)\n"); + else + MSG_PUTS(p); } /* @@ -2040,13 +2048,21 @@ linenr_T lnum; int will_change; /* line will be changed */ { - bhdr_T *hp; - DATA_BL *dp; - char_u *ptr; + bhdr_T *hp; + DATA_BL *dp; + char_u *ptr; + static int recursive = 0; if (lnum > buf->b_ml.ml_line_count) /* invalid line number */ { - EMSGN(_("E315: ml_get: invalid lnum: %ld"), lnum); + if (recursive == 0) + { + /* Avoid giving this message for a recursive call, may happen when + * the GUI redraws part of the text. */ + ++recursive; + EMSGN(_("E315: ml_get: invalid lnum: %ld"), lnum); + --recursive; + } errorret: STRCPY(IObuff, "???"); return IObuff; @@ -2060,8 +2076,10 @@ /* * See if it is the same line as requested last time. * Otherwise may need to flush last used line. + * Don't use the last used line when 'swapfile' is reset, need to load all + * blocks. */ - if (buf->b_ml.ml_line_lnum != lnum) + if (buf->b_ml.ml_line_lnum != lnum || mf_dont_release) { ml_flush_line(buf); @@ -2072,7 +2090,14 @@ */ if ((hp = ml_find_line(buf, lnum, ML_FIND)) == NULL) { - EMSGN(_("E316: ml_get: cannot find line %ld"), lnum); + if (recursive == 0) + { + /* Avoid giving this message for a recursive call, may happen + * when the GUI redraws part of the text. */ + ++recursive; + EMSGN(_("E316: ml_get: cannot find line %ld"), lnum); + --recursive; + } goto errorret; } @@ -3186,13 +3211,16 @@ * If not, flush and release the locked block. * Don't do this for ML_INSERT_SAME, because the stack need to be updated. * Don't do this for ML_FLUSH, because we want to flush the locked block. + * Don't do this when 'swapfile' is reset, we want to load all the blocks. */ if (buf->b_ml.ml_locked) { - if (ML_SIMPLE(action) && buf->b_ml.ml_locked_low <= lnum - && buf->b_ml.ml_locked_high >= lnum) + if (ML_SIMPLE(action) + && buf->b_ml.ml_locked_low <= lnum + && buf->b_ml.ml_locked_high >= lnum + && !mf_dont_release) { - /* remember to update pointer blocks and stack later */ + /* remember to update pointer blocks and stack later */ if (action == ML_INSERT) { ++(buf->b_ml.ml_locked_lineadd); @@ -3652,6 +3680,7 @@ { struct stat st; time_t x, sx; + char *p; ++no_wait_return; (void)EMSG(_("E325: ATTENTION")); @@ -3666,7 +3695,11 @@ { MSG_PUTS(_(" dated: ")); x = st.st_mtime; /* Manx C can't do &st.st_mtime */ - MSG_PUTS(ctime(&x)); + p = ctime(&x); /* includes '\n' */ + if (p == NULL) + MSG_PUTS("(invalid)\n"); + else + MSG_PUTS(p); if (sx != 0 && x > sx) MSG_PUTS(_(" NEWER than swap file!\n")); } diff -Naur vim70.orig/src/menu.c vim70/src/menu.c --- vim70.orig/src/menu.c 2006-05-03 10:30:48.000000000 -0700 +++ vim70/src/menu.c 2007-02-15 21:22:27.000000000 -0800 @@ -511,6 +511,14 @@ * name (without mnemonic and accelerator text). */ next_name = menu_name_skip(name); dname = menu_text(name, NULL, NULL); + if (dname == NULL) + goto erret; + if (*dname == NUL) + { + /* Only a mnemonic or accelerator is not valid. */ + EMSG(_("E792: Empty menu name")); + goto erret; + } /* See if it's already there */ lower_pri = menup; @@ -704,6 +712,7 @@ parent = menu; name = next_name; vim_free(dname); + dname = NULL; if (pri_tab[pri_idx + 1] != -1) ++pri_idx; } @@ -793,6 +802,22 @@ erret: vim_free(path_name); vim_free(dname); + + /* Delete any empty submenu we added before discovering the error. Repeat + * for higher levels. */ + while (parent != NULL && parent->children == NULL) + { + if (parent->parent == NULL) + menup = &root_menu; + else + menup = &parent->parent->children; + for ( ; *menup != NULL && *menup != parent; menup = &((*menup)->next)) + ; + if (*menup == NULL) /* safety check */ + break; + parent = parent->parent; + free_menu(menup); + } return FAIL; } @@ -1753,6 +1778,27 @@ } /* + * Check that a pointer appears in the menu tree. Used to protect from using + * a menu that was deleted after it was selected but before the event was + * handled. + * Return OK or FAIL. Used recursively. + */ + int +check_menu_pointer(root, menu_to_check) + vimmenu_T *root; + vimmenu_T *menu_to_check; +{ + vimmenu_T *p; + + for (p = root; p != NULL; p = p->next) + if (p == menu_to_check + || (p->children != NULL + && check_menu_pointer(p->children, menu_to_check) == OK)) + return OK; + return FAIL; +} + +/* * After we have started the GUI, then we can create any menus that have been * defined. This is done once here. add_menu_path() may have already been * called to define these menus, and may be called again. This function calls @@ -2200,7 +2246,7 @@ { /* When executing a script or function execute the commands right now. * Otherwise put them in the typeahead buffer. */ -#ifdef FEAT_En +#ifdef FEAT_EVAL if (current_SID != 0) exec_normal_cmd(menu->strings[idx], menu->noremap[idx], menu->silent[idx]); diff -Naur vim70.orig/src/message.c vim70/src/message.c --- vim70.orig/src/message.c 2006-05-06 13:07:37.000000000 -0700 +++ vim70/src/message.c 2007-02-15 21:22:27.000000000 -0800 @@ -53,7 +53,6 @@ static struct msg_hist *first_msg_hist = NULL; static struct msg_hist *last_msg_hist = NULL; static int msg_hist_len = 0; -static int msg_hist_off = FALSE; /* don't add messages to history */ /* * When writing messages to the screen, there are many different situations. @@ -1557,7 +1556,7 @@ int c_extra = 0; char_u *p_extra = NULL; /* init to make SASC shut up */ int n; - int attr= 0; + int attr = 0; char_u *trail = NULL; #ifdef FEAT_MBYTE int l; @@ -1582,7 +1581,7 @@ while (!got_int) { - if (n_extra) + if (n_extra > 0) { --n_extra; if (c_extra) @@ -1596,7 +1595,7 @@ col += (*mb_ptr2cells)(s); mch_memmove(buf, s, (size_t)l); buf[l] = NUL; - msg_puts_attr(buf, attr); + msg_puts(buf); s += l; continue; } @@ -1636,6 +1635,9 @@ p_extra = transchar_byte(c); c_extra = NUL; c = *p_extra++; + /* Use special coloring to be able to distinguish from + * the same in plain text. */ + attr = hl_attr(HLF_8); } else if (c == ' ' && trail != NULL && s > trail) { @@ -1925,7 +1927,8 @@ * If screen is completely filled and 'more' is set then wait * for a character. */ - if (p_more && --lines_left == 0 && State != HITRETURN + --lines_left; + if (p_more && lines_left == 0 && State != HITRETURN && !msg_no_more && !exmode_active) { #ifdef FEAT_CON_DIALOG @@ -4123,8 +4126,6 @@ case 'c': case 's': length_modifier = '\0'; - zero_padding = 0; /* turn zero padding off for string - conversions */ str_arg_l = 1; switch (fmt_spec) { @@ -4175,15 +4176,16 @@ str_arg_l = 0; else { - /* memchr on HP does not like n > 2^31 !!! */ - char *q = memchr(str_arg, '\0', + /* Don't put the #if inside memchr(), it can be a + * macro. */ #if SIZEOF_INT <= 2 - precision + char *q = memchr(str_arg, '\0', precision); #else - precision <= (size_t)0x7fffffffL ? precision - : (size_t)0x7fffffffL + /* memchr on HP does not like n > 2^31 !!! */ + char *q = memchr(str_arg, '\0', + precision <= (size_t)0x7fffffffL ? precision + : (size_t)0x7fffffffL); #endif - ); str_arg_l = (q == NULL) ? precision : q - str_arg; } break; diff -Naur vim70.orig/src/misc1.c vim70/src/misc1.c --- vim70.orig/src/misc1.c 2006-04-30 08:30:02.000000000 -0700 +++ vim70/src/misc1.c 2007-02-15 21:22:26.000000000 -0800 @@ -1761,15 +1761,13 @@ * Add column offset for 'number', 'foldcolumn', etc. */ width = W_WIDTH(wp) - win_col_off(wp); - if (width > 0) - { - lines += 1; - if (col >= width) - lines += (col - width) / (width + win_col_off2(wp)); - if (lines <= wp->w_height) - return lines; - } - return (int)(wp->w_height); /* maximum length */ + if (width <= 0) + return 9999; + + lines += 1; + if (col > width) + lines += (col - width) / (width + win_col_off2(wp)) + 1; + return lines; } int @@ -2842,7 +2840,8 @@ #ifdef FEAT_AUTOCMD /* when the cursor line is changed always trigger CursorMoved */ - if (lnum <= curwin->w_cursor.lnum && lnume > curwin->w_cursor.lnum) + if (lnum <= curwin->w_cursor.lnum + && lnume + (xtra < 0 ? -xtra : xtra) > curwin->w_cursor.lnum) last_cursormoved.lnum = 0; #endif } @@ -3016,6 +3015,7 @@ int len = 0; int n; int save_mapped_ctrl_c = mapped_ctrl_c; + int waited = 0; mapped_ctrl_c = FALSE; /* mappings are not used here */ for (;;) @@ -3034,11 +3034,16 @@ /* Replace zero and CSI by a special key code. */ n = fix_input_buffer(buf + len, n, FALSE); len += n; + waited = 0; } + else if (len > 0) + ++waited; /* keep track of the waiting time */ - /* incomplete termcode: get more characters */ - if ((n = check_termcode(1, buf, len)) < 0) + /* Incomplete termcode and not timed out yet: get more characters */ + if ((n = check_termcode(1, buf, len)) < 0 + && (!p_ttimeout || waited * 100L < (p_ttm < 0 ? p_tm : p_ttm))) continue; + /* found a termcode: adjust length */ if (n > 0) len = n; @@ -3196,14 +3201,12 @@ else MSG_PUTS(_("Choice number ( cancels): ")); - /* Set the state such that text can be selected/copied/pasted. */ + /* Set the state such that text can be selected/copied/pasted and we still + * get mouse events. */ save_cmdline_row = cmdline_row; - cmdline_row = Rows - 1; + cmdline_row = 0; save_State = State; - if (mouse_used == NULL) - State = CMDLINE; - else - State = NORMAL; + State = CMDLINE; i = get_number(TRUE, mouse_used); if (KeyTyped) @@ -4492,7 +4495,7 @@ int l = mb_ptr2len(s); while (--l > 0) - *d++ = *s++; + *d++ = *++s; } # endif } @@ -8070,9 +8073,20 @@ } if (*that == '"' && *(that + 1) != NUL) { - that++; - while (*that && (*that != '"' || *(that - 1) == '\\')) - ++that; + while (*++that && *that != '"') + { + /* skipping escaped characters in the string */ + if (*that == '\\') + { + if (*++that == NUL) + break; + if (that[1] == NUL) + { + ++that; + break; + } + } + } } if (*that == '(' || *that == '[') ++parencount; diff -Naur vim70.orig/src/misc2.c vim70/src/misc2.c --- vim70.orig/src/misc2.c 2006-05-04 05:12:38.000000000 -0700 +++ vim70/src/misc2.c 2007-02-15 21:22:25.000000000 -0800 @@ -1229,6 +1229,94 @@ return escaped_string; } +#if defined(FEAT_EVAL) || defined(PROTO) +/* + * Escape "string" for use as a shell argument with system(). + * This uses single quotes, except when we know we need to use double qoutes + * (MS-DOS and MS-Windows without 'shellslash' set). + * Returns the result in allocated memory, NULL if we have run out. + */ + char_u * +vim_strsave_shellescape(string) + char_u *string; +{ + unsigned length; + char_u *p; + char_u *d; + char_u *escaped_string; + + /* First count the number of extra bytes required. */ + length = STRLEN(string) + 3; /* two quotes and the trailing NUL */ + for (p = string; *p != NUL; mb_ptr_adv(p)) + { +# if defined(WIN32) || defined(WIN16) || defined(DOS) + if (!p_ssl) + { + if (*p == '"') + ++length; /* " -> "" */ + } + else +# endif + if (*p == '\'') + length += 3; /* ' => '\'' */ + } + + /* Allocate memory for the result and fill it. */ + escaped_string = alloc(length); + if (escaped_string != NULL) + { + d = escaped_string; + + /* add opening quote */ +# if defined(WIN32) || defined(WIN16) || defined(DOS) + if (!p_ssl) + *d++ = '"'; + else +# endif + *d++ = '\''; + + for (p = string; *p != NUL; ) + { +# if defined(WIN32) || defined(WIN16) || defined(DOS) + if (!p_ssl) + { + if (*p == '"') + { + *d++ = '"'; + *d++ = '"'; + ++p; + continue; + } + } + else +# endif + if (*p == '\'') + { + *d++='\''; + *d++='\\'; + *d++='\''; + *d++='\''; + ++p; + continue; + } + + MB_COPY_CHAR(p, d); + } + + /* add terminating quote and finish with a NUL */ +# if defined(WIN32) || defined(WIN16) || defined(DOS) + if (!p_ssl) + *d++ = '"'; + else +# endif + *d++ = '\''; + *d = NUL; + } + + return escaped_string; +} +#endif + /* * Like vim_strsave(), but make all characters uppercase. * This uses ASCII lower-to-upper case translation, language independent. diff -Naur vim70.orig/src/netbeans.c vim70/src/netbeans.c --- vim70.orig/src/netbeans.c 2006-04-22 11:00:05.000000000 -0700 +++ vim70/src/netbeans.c 2007-02-15 21:22:26.000000000 -0800 @@ -61,7 +61,7 @@ /* The first implementation (working only with Netbeans) returned "1.1". The * protocol implemented here also supports A-A-P. */ -static char *ExtEdProtocolVersion = "2.3"; +static char *ExtEdProtocolVersion = "2.4"; static long pos2off __ARGS((buf_T *, pos_T *)); static pos_T *off2pos __ARGS((buf_T *, long)); @@ -103,7 +103,7 @@ static int inputHandler = -1; /* simply ret.value of WSAAsyncSelect() */ extern HWND s_hwnd; /* Gvim's Window handle */ #endif -static int cmdno; /* current command number for reply */ +static int r_cmdno; /* current command number for reply */ static int haveConnection = FALSE; /* socket is connected and initialization is done */ #ifdef FEAT_GUI_MOTIF @@ -832,11 +832,11 @@ return; } - cmdno = strtol(q, &q, 10); + r_cmdno = strtol(q, &q, 10); q = (char *)skipwhite((char_u *)q); - if (nb_do_cmd(bufno, (char_u *)verb, isfunc, cmdno, (char_u *)q) == FAIL) + if (nb_do_cmd(bufno, (char_u *)verb, isfunc, r_cmdno, (char_u *)q) == FAIL) { #ifdef NBDEBUG /* @@ -1008,11 +1008,11 @@ if (netbeansForcedQuit) { /* mark as unmodified so NetBeans won't put up dialog on "killed" */ - sprintf(buf, "%d:unmodified=%d\n", i, cmdno); + sprintf(buf, "%d:unmodified=%d\n", i, r_cmdno); nbdebug(("EVT: %s", buf)); nb_send(buf, "netbeans_end"); } - sprintf(buf, "%d:killed=%d\n", i, cmdno); + sprintf(buf, "%d:killed=%d\n", i, r_cmdno); nbdebug(("EVT: %s", buf)); /* nb_send(buf, "netbeans_end"); avoid "write failed" messages */ if (sd >= 0) @@ -1271,6 +1271,29 @@ nb_reply_text(cmdno, text); /* =====================================================================*/ } + else if (streq((char *)cmd, "getAnno")) + { + long linenum = 0; +#ifdef FEAT_SIGNS + if (buf == NULL || buf->bufp == NULL) + { + nbdebug((" null bufp in getAnno")); + EMSG("E652: null bufp in getAnno"); + retval = FAIL; + } + else + { + int serNum; + + cp = (char *)args; + serNum = strtol(cp, &cp, 10); + /* If the sign isn't found linenum will be zero. */ + linenum = (long)buf_findsign(buf->bufp, serNum); + } +#endif + nb_reply_nr(cmdno, linenum); +/* =====================================================================*/ + } else if (streq((char *)cmd, "getLength")) { long len = 0; @@ -1986,6 +2009,8 @@ if (buf->bufp != NULL) do_buffer(DOBUF_WIPE, DOBUF_FIRST, FORWARD, buf->bufp->b_fnum, TRUE); + buf->bufp = NULL; + buf->initDone = FALSE; doupdate = 1; /* =====================================================================*/ } @@ -2561,7 +2586,7 @@ if (p != NULL) { vim_snprintf(buf, sizeof(buf), - "0:balloonText=%d \"%s\"\n", cmdno, p); + "0:balloonText=%d \"%s\"\n", r_cmdno, p); vim_free(p); } nbdebug(("EVT: %s", buf)); @@ -2615,7 +2640,7 @@ if (haveConnection) { - sprintf(buf, "0:disconnect=%d\n", cmdno); + sprintf(buf, "0:disconnect=%d\n", r_cmdno); nbdebug(("EVT: %s", buf)); nb_send(buf, "netbeans_disconnect"); } @@ -2634,7 +2659,7 @@ return; sprintf(buf, "0:geometry=%d %d %d %d %d\n", - cmdno, (int)Columns, (int)Rows, new_x, new_y); + r_cmdno, (int)Columns, (int)Rows, new_x, new_y); /*nbdebug(("EVT: %s", buf)); happens too many times during a move */ nb_send(buf, "netbeans_frame_moved"); } @@ -2743,7 +2768,7 @@ if (bufno <= 0) return; - sprintf(buffer, "%d:killed=%d\n", bufno, cmdno); + sprintf(buffer, "%d:killed=%d\n", bufno, r_cmdno); nbdebug(("EVT: %s", buffer)); @@ -2817,7 +2842,8 @@ if (p != NULL) { buf = alloc(128 + 2*newlen); - sprintf((char *)buf, "%d:insert=%d %ld \"%s\"\n", bufno, cmdno, off, p); + sprintf((char *)buf, "%d:insert=%d %ld \"%s\"\n", + bufno, r_cmdno, off, p); nbdebug(("EVT: %s", buf)); nb_send((char *)buf, "netbeans_inserted"); vim_free(p); @@ -2859,7 +2885,7 @@ off = pos2off(bufp, &pos); - sprintf((char *)buf, "%d:remove=%d %ld %ld\n", bufno, cmdno, off, len); + sprintf((char *)buf, "%d:remove=%d %ld %ld\n", bufno, r_cmdno, off, len); nbdebug(("EVT: %s", buf)); nb_send((char *)buf, "netbeans_removed"); } @@ -2884,7 +2910,7 @@ nbbuf->modified = 0; - sprintf((char *)buf, "%d:unmodified=%d\n", bufno, cmdno); + sprintf((char *)buf, "%d:unmodified=%d\n", bufno, r_cmdno); nbdebug(("EVT: %s", buf)); nb_send((char *)buf, "netbeans_unmodified"); #endif @@ -2908,11 +2934,11 @@ long off = pos2off(curbuf, &curwin->w_cursor); /* sync the cursor position */ - sprintf(buf, "%d:newDotAndMark=%d %ld %ld\n", bufno, cmdno, off, off); + sprintf(buf, "%d:newDotAndMark=%d %ld %ld\n", bufno, r_cmdno, off, off); nbdebug(("EVT: %s", buf)); nb_send(buf, "netbeans_button_release[newDotAndMark]"); - sprintf(buf, "%d:buttonRelease=%d %d %ld %d\n", bufno, cmdno, + sprintf(buf, "%d:buttonRelease=%d %d %ld %d\n", bufno, r_cmdno, button, (long)curwin->w_cursor.lnum, col); nbdebug(("EVT: %s", buf)); nb_send(buf, "netbeans_button_release"); @@ -2973,7 +2999,7 @@ /* sync the cursor position */ off = pos2off(curbuf, &curwin->w_cursor); - sprintf(buf, "%d:newDotAndMark=%d %ld %ld\n", bufno, cmdno, off, off); + sprintf(buf, "%d:newDotAndMark=%d %ld %ld\n", bufno, r_cmdno, off, off); nbdebug(("EVT: %s", buf)); nb_send(buf, "netbeans_keycommand"); @@ -2984,13 +3010,13 @@ /* now send keyCommand event */ vim_snprintf(buf, sizeof(buf), "%d:keyCommand=%d \"%s\"\n", - bufno, cmdno, keyName); + bufno, r_cmdno, keyName); nbdebug(("EVT: %s", buf)); nb_send(buf, "netbeans_keycommand"); /* New: do both at once and include the lnum/col. */ vim_snprintf(buf, sizeof(buf), "%d:keyAtPos=%d \"%s\" %ld %ld/%ld\n", - bufno, cmdno, keyName, + bufno, r_cmdno, keyName, off, (long)curwin->w_cursor.lnum, (long)curwin->w_cursor.col); nbdebug(("EVT: %s", buf)); nb_send(buf, "netbeans_keycommand"); @@ -3013,7 +3039,7 @@ nbbuf->modified = 0; - sprintf((char *)buf, "%d:save=%d\n", bufno, cmdno); + sprintf((char *)buf, "%d:save=%d\n", bufno, r_cmdno); nbdebug(("EVT: %s", buf)); nb_send((char *)buf, "netbeans_save_buffer"); } @@ -3037,7 +3063,7 @@ if (nbbuf->insertDone) nbbuf->modified = 1; - sprintf((char *)buf, "%d:remove=%d 0 -1\n", bufno, cmdno); + sprintf((char *)buf, "%d:remove=%d 0 -1\n", bufno, r_cmdno); nbdebug(("EVT(suppressed): %s", buf)); /* nb_send(buf, "netbeans_deleted_all_lines"); */ } diff -Naur vim70.orig/src/normal.c vim70/src/normal.c --- vim70.orig/src/normal.c 2006-04-29 06:11:18.000000000 -0700 +++ vim70/src/normal.c 2007-02-15 21:22:27.000000000 -0800 @@ -651,9 +651,8 @@ /* Fake a "c"hange command. When "restart_edit" is set (e.g., because * 'insertmode' is set) fake a "d"elete command, Insert mode will * restart automatically. - * Insert the typed character in the typeahead buffer, so that it will - * be mapped in Insert mode. Required for ":lmap" to work. May cause - * mapping a character from ":vnoremap"... */ + * Insert the typed character in the typeahead buffer, so that it can + * be mapped in Insert mode. Required for ":lmap" to work. */ ins_char_typebuf(c); if (restart_edit != 0) c = 'd'; @@ -1477,14 +1476,17 @@ } else if (VIsual_active) { - /* Save the current VIsual area for '< and '> marks, and "gv" */ - curbuf->b_visual.vi_start = VIsual; - curbuf->b_visual.vi_end = curwin->w_cursor; - curbuf->b_visual.vi_mode = VIsual_mode; - curbuf->b_visual.vi_curswant = curwin->w_curswant; + if (!gui_yank) + { + /* Save the current VIsual area for '< and '> marks, and "gv" */ + curbuf->b_visual.vi_start = VIsual; + curbuf->b_visual.vi_end = curwin->w_cursor; + curbuf->b_visual.vi_mode = VIsual_mode; + curbuf->b_visual.vi_curswant = curwin->w_curswant; # ifdef FEAT_EVAL - curbuf->b_visual_mode_eval = VIsual_mode; + curbuf->b_visual_mode_eval = VIsual_mode; # endif + } /* In Select mode, a linewise selection is operated upon like a * characterwise selection. */ @@ -2377,11 +2379,20 @@ /* * If visual was active, yank the highlighted text and put it * before the mouse pointer position. + * In Select mode replace the highlighted text with the clipboard. */ if (VIsual_active) { - stuffcharReadbuff('y'); - stuffcharReadbuff(K_MIDDLEMOUSE); + if (VIsual_select) + { + stuffcharReadbuff(Ctrl_G); + stuffReadbuff((char_u *)"\"+p"); + } + else + { + stuffcharReadbuff('y'); + stuffcharReadbuff(K_MIDDLEMOUSE); + } do_always = TRUE; /* ignore 'mouse' setting next time */ return FALSE; } @@ -2504,7 +2515,8 @@ * NOTE: Ignore right button down and drag mouse events. * Windows only shows the popup menu on the button up event. */ -#if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_PHOTON) +#if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \ + || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) if (!is_click) return FALSE; #endif @@ -4126,7 +4138,7 @@ int save_p_ws; int save_p_scs; int retval = OK; - int incl; + int incll; if ((pat = alloc(len + 7)) == NULL) return FAIL; @@ -4146,7 +4158,7 @@ * With "gd" Search back for the start of the current function, then go * back until a blank line. If this fails go to line 1. */ - if (!locally || !findpar(&incl, BACKWARD, 1L, '{', FALSE)) + if (!locally || !findpar(&incll, BACKWARD, 1L, '{', FALSE)) { setpcmark(); /* Set in findpar() otherwise */ curwin->w_cursor.lnum = 1; @@ -8847,7 +8859,7 @@ #endif while (cap->count1-- && !got_int) { - if (do_execreg(cap->nchar, FALSE, FALSE) == FAIL) + if (do_execreg(cap->nchar, FALSE, FALSE, FALSE) == FAIL) { clearopbeep(cap->oap); break; diff -Naur vim70.orig/src/ops.c vim70/src/ops.c --- vim70.orig/src/ops.c 2006-04-30 08:13:44.000000000 -0700 +++ vim70/src/ops.c 2007-02-15 21:22:26.000000000 -0800 @@ -95,8 +95,8 @@ static void block_insert __ARGS((oparg_T *oap, char_u *s, int b_insert, struct block_def*bdp)); #endif static int stuff_yank __ARGS((int, char_u *)); -static void put_reedit_in_typebuf __ARGS((void)); -static int put_in_typebuf __ARGS((char_u *s, int colon)); +static void put_reedit_in_typebuf __ARGS((int silent)); +static int put_in_typebuf __ARGS((char_u *s, int colon, int silent)); static void stuffescaped __ARGS((char_u *arg, int literally)); #ifdef FEAT_MBYTE static void mb_adjust_opend __ARGS((oparg_T *oap)); @@ -770,6 +770,7 @@ { char_u *expr_copy; char_u *rv; + static int nested = 0; if (expr_line == NULL) return NULL; @@ -780,7 +781,14 @@ if (expr_copy == NULL) return NULL; + /* When we are invoked recursively limit the evaluation to 10 levels. + * Then return the string as-is. */ + if (nested >= 10) + return expr_copy; + + ++nested; rv = eval_to_string(expr_copy, NULL, TRUE); + --nested; vim_free(expr_copy); return rv; } @@ -1112,10 +1120,11 @@ * return FAIL for failure, OK otherwise */ int -do_execreg(regname, colon, addcr) +do_execreg(regname, colon, addcr, silent) int regname; int colon; /* insert ':' before each line */ int addcr; /* always add '\n' to end of line */ + int silent; /* set "silent" flag in typeahead buffer */ { static int lastc = NUL; long i; @@ -1165,9 +1174,9 @@ /* When in Visual mode "'<,'>" will be prepended to the command. * Remove it when it's already there. */ if (VIsual_active && STRNCMP(p, "'<,'>", 5) == 0) - retval = put_in_typebuf(p + 5, TRUE); + retval = put_in_typebuf(p + 5, TRUE, silent); else - retval = put_in_typebuf(p, TRUE); + retval = put_in_typebuf(p, TRUE, silent); } vim_free(p); } @@ -1178,7 +1187,7 @@ p = get_expr_line(); if (p == NULL) return FAIL; - retval = put_in_typebuf(p, colon); + retval = put_in_typebuf(p, colon, silent); vim_free(p); } #endif @@ -1190,7 +1199,7 @@ EMSG(_(e_noinstext)); return FAIL; } - retval = put_in_typebuf(p, colon); + retval = put_in_typebuf(p, colon, silent); vim_free(p); } else @@ -1205,20 +1214,20 @@ /* * Insert lines into typeahead buffer, from last one to first one. */ - put_reedit_in_typebuf(); + put_reedit_in_typebuf(silent); for (i = y_current->y_size; --i >= 0; ) { /* insert NL between lines and after last line if type is MLINE */ if (y_current->y_type == MLINE || i < y_current->y_size - 1 || addcr) { - if (ins_typebuf((char_u *)"\n", remap, 0, TRUE, FALSE) == FAIL) + if (ins_typebuf((char_u *)"\n", remap, 0, TRUE, silent) == FAIL) return FAIL; } - if (ins_typebuf(y_current->y_array[i], remap, 0, TRUE, FALSE) + if (ins_typebuf(y_current->y_array[i], remap, 0, TRUE, silent) == FAIL) return FAIL; - if (colon && ins_typebuf((char_u *)":", remap, 0, TRUE, FALSE) + if (colon && ins_typebuf((char_u *)":", remap, 0, TRUE, silent) == FAIL) return FAIL; } @@ -1232,7 +1241,8 @@ * used only after other typeahead has been processed. */ static void -put_reedit_in_typebuf() +put_reedit_in_typebuf(silent) + int silent; { char_u buf[3]; @@ -1249,25 +1259,26 @@ buf[0] = restart_edit == 'I' ? 'i' : restart_edit; buf[1] = NUL; } - if (ins_typebuf(buf, REMAP_NONE, 0, TRUE, FALSE) == OK) + if (ins_typebuf(buf, REMAP_NONE, 0, TRUE, silent) == OK) restart_edit = NUL; } } static int -put_in_typebuf(s, colon) +put_in_typebuf(s, colon, silent) char_u *s; int colon; /* add ':' before the line */ + int silent; { int retval = OK; - put_reedit_in_typebuf(); + put_reedit_in_typebuf(silent); if (colon) - retval = ins_typebuf((char_u *)"\n", REMAP_YES, 0, TRUE, FALSE); + retval = ins_typebuf((char_u *)"\n", REMAP_YES, 0, TRUE, silent); if (retval == OK) - retval = ins_typebuf(s, REMAP_YES, 0, TRUE, FALSE); + retval = ins_typebuf(s, REMAP_YES, 0, TRUE, silent); if (colon && retval == OK) - retval = ins_typebuf((char_u *)":", REMAP_YES, 0, TRUE, FALSE); + retval = ins_typebuf((char_u *)":", REMAP_YES, 0, TRUE, silent); return retval; } @@ -1472,9 +1483,10 @@ * return FAIL for failure, OK otherwise */ int -cmdline_paste_reg(regname, literally) +cmdline_paste_reg(regname, literally, remcr) int regname; int literally; /* Insert text literally instead of "as typed" */ + int remcr; /* don't add trailing CR */ { long i; @@ -1486,8 +1498,13 @@ { cmdline_paste_str(y_current->y_array[i], literally); - /* insert ^M between lines and after last line if type is MLINE */ - if (y_current->y_type == MLINE || i < y_current->y_size - 1) + /* Insert ^M between lines and after last line if type is MLINE. + * Don't do this when "remcr" is TRUE and the next line is empty. */ + if (y_current->y_type == MLINE + || (i < y_current->y_size - 1 + && !(remcr + && i == y_current->y_size - 2 + && *y_current->y_array[i + 1] == NUL))) cmdline_paste_str((char_u *)"\r", literally); /* Check for CTRL-C, in case someone tries to paste a few thousand @@ -2413,6 +2430,7 @@ else { curwin->w_cursor = oap->end; + check_cursor_col(); /* Works just like an 'i'nsert on the next character. */ if (!lineempty(curwin->w_cursor.lnum) @@ -3492,8 +3510,15 @@ # endif if (flags & PUT_CURSEND) { + colnr_T len; + curwin->w_cursor = curbuf->b_op_end; curwin->w_cursor.col++; + + /* in Insert mode we might be after the NUL, correct for that */ + len = (colnr_T)STRLEN(ml_get_curline()); + if (curwin->w_cursor.col > len) + curwin->w_cursor.col = len; } else curwin->w_cursor.lnum = lnum; diff -Naur vim70.orig/src/option.c vim70/src/option.c --- vim70.orig/src/option.c 2006-05-03 10:32:28.000000000 -0700 +++ vim70/src/option.c 2007-02-15 21:22:26.000000000 -0800 @@ -2294,7 +2294,7 @@ {(char_u *)0L, (char_u *)0L} #endif }, - {"spellsuggest", "sps", P_STRING|P_VI_DEF|P_EXPAND|P_SECURE, + {"spellsuggest", "sps", P_STRING|P_VI_DEF|P_EXPAND|P_SECURE|P_COMMA, #ifdef FEAT_SPELL (char_u *)&p_sps, PV_NONE, {(char_u *)"best", (char_u *)0L} @@ -3397,7 +3397,7 @@ } else if (flags & P_NUM) { - if (varp == (char_u *)PV_SCROLL) + if (options[opt_idx].indir == PV_SCROLL) win_comp_scroll(curwin); else { @@ -5227,13 +5227,13 @@ case PV_STL: return &curwin->w_p_stl_flags; #endif #ifdef FEAT_EVAL +# ifdef FEAT_FOLDING case PV_FDE: return &curwin->w_p_fde_flags; case PV_FDT: return &curwin->w_p_fdt_flags; +# endif # ifdef FEAT_BEVAL case PV_BEXPR: return &curbuf->b_p_bexpr_flags; # endif -#endif -#if defined(FEAT_EVAL) # if defined(FEAT_CINDENT) case PV_INDE: return &curbuf->b_p_inde_flags; # endif @@ -5268,45 +5268,46 @@ char_u *s; char_u **varp; int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0; + int idx = opt_idx; - if (opt_idx == -1) /* use name */ + if (idx == -1) /* use name */ { - opt_idx = findoption(name); - if (opt_idx < 0) /* not found (should not happen) */ + idx = findoption(name); + if (idx < 0) /* not found (should not happen) */ { EMSG2(_(e_intern2), "set_string_option_direct()"); return; } } - if (options[opt_idx].var == NULL) /* can't set hidden option */ + if (options[idx].var == NULL) /* can't set hidden option */ return; s = vim_strsave(val); if (s != NULL) { - varp = (char_u **)get_varp_scope(&(options[opt_idx]), + varp = (char_u **)get_varp_scope(&(options[idx]), both ? OPT_LOCAL : opt_flags); - if ((opt_flags & OPT_FREE) && (options[opt_idx].flags & P_ALLOCED)) + if ((opt_flags & OPT_FREE) && (options[idx].flags & P_ALLOCED)) free_string_option(*varp); *varp = s; /* For buffer/window local option may also set the global value. */ if (both) - set_string_option_global(opt_idx, varp); + set_string_option_global(idx, varp); - options[opt_idx].flags |= P_ALLOCED; + options[idx].flags |= P_ALLOCED; /* When setting both values of a global option with a local value, * make the local value empty, so that the global value is used. */ - if (((int)options[opt_idx].indir & PV_BOTH) && both) + if (((int)options[idx].indir & PV_BOTH) && both) { free_string_option(*varp); *varp = empty_option; } # ifdef FEAT_EVAL if (set_sid != SID_NONE) - set_option_scriptID_idx(opt_idx, opt_flags, + set_option_scriptID_idx(idx, opt_flags, set_sid == 0 ? current_SID : set_sid); # endif } @@ -6325,7 +6326,8 @@ else errmsg = check_stl_option(p_ruf); } - else + /* check 'statusline' only if it doesn't start with "%!" */ + else if (varp != &p_stl || s[0] != '%' || s[1] != '!') errmsg = check_stl_option(s); if (varp == &p_ruf && errmsg == NULL) comp_col(); @@ -7324,9 +7326,8 @@ #ifdef FEAT_AUTOCHDIR else if ((int *)varp == &p_acd) { - if (p_acd && curbuf->b_ffname != NULL - && vim_chdirfile(curbuf->b_ffname) == OK) - shorten_fnames(TRUE); + /* Change directories when the 'acd' option is set now. */ + DO_AUTOCHDIR } #endif diff -Naur vim70.orig/src/os_unix.c vim70/src/os_unix.c --- vim70.orig/src/os_unix.c 2006-05-01 01:13:15.000000000 -0700 +++ vim70/src/os_unix.c 2007-02-15 21:22:25.000000000 -0800 @@ -3934,7 +3934,7 @@ { linenr_T lnum = curbuf->b_op_start.lnum; int written = 0; - char_u *p = ml_get(lnum); + char_u *lp = ml_get(lnum); char_u *s; size_t l; @@ -3942,17 +3942,17 @@ close(fromshell_fd); for (;;) { - l = STRLEN(p + written); + l = STRLEN(lp + written); if (l == 0) len = 0; - else if (p[written] == NL) + else if (lp[written] == NL) /* NL -> NUL translation */ len = write(toshell_fd, "", (size_t)1); else { - s = vim_strchr(p + written, NL); - len = write(toshell_fd, (char *)p + written, - s == NULL ? l : s - (p + written)); + s = vim_strchr(lp + written, NL); + len = write(toshell_fd, (char *)lp + written, + s == NULL ? l : s - (lp + written)); } if (len == l) { @@ -3973,7 +3973,7 @@ toshell_fd = -1; break; } - p = ml_get(lnum); + lp = ml_get(lnum); written = 0; } else if (len > 0) @@ -5757,8 +5757,13 @@ int retval_int = 0; int success = FALSE; - /* Get a handle to the DLL module. */ + /* + * Get a handle to the DLL module. + */ # if defined(USE_DLOPEN) + /* First clear any error, it's not cleared by the dlopen() call. */ + (void)dlerror(); + hinstLib = dlopen((char *)libname, RTLD_LAZY # ifdef RTLD_LOCAL | RTLD_LOCAL diff -Naur vim70.orig/src/popupmnu.c vim70/src/popupmnu.c --- vim70.orig/src/popupmnu.c 2006-04-20 13:18:37.000000000 -0700 +++ vim70/src/popupmnu.c 2007-02-15 21:22:24.000000000 -0800 @@ -552,6 +552,9 @@ { pum_array = NULL; redraw_all_later(SOME_VALID); +#ifdef FEAT_WINDOWS + redraw_tabline = TRUE; +#endif status_redraw_all(); } diff -Naur vim70.orig/src/proto/buffer.pro vim70/src/proto/buffer.pro --- vim70.orig/src/proto/buffer.pro 2006-05-07 06:08:29.000000000 -0700 +++ vim70/src/proto/buffer.pro 2007-02-15 21:22:25.000000000 -0800 @@ -10,6 +10,7 @@ extern int do_buffer __ARGS((int action, int start, int dir, int count, int forceit)); extern void set_curbuf __ARGS((buf_T *buf, int action)); extern void enter_buffer __ARGS((buf_T *buf)); +extern void do_autochdir __ARGS((void)); extern buf_T *buflist_new __ARGS((char_u *ffname, char_u *sfname, linenr_T lnum, int flags)); extern void free_buf_options __ARGS((buf_T *buf, int free_p_ff)); extern int buflist_getfile __ARGS((int n, linenr_T lnum, int options, int forceit)); diff -Naur vim70.orig/src/proto/eval.pro vim70/src/proto/eval.pro --- vim70.orig/src/proto/eval.pro 2006-05-07 06:08:33.000000000 -0700 +++ vim70/src/proto/eval.pro 2007-02-15 21:22:26.000000000 -0800 @@ -44,7 +44,7 @@ extern char_u *get_user_var_name __ARGS((expand_T *xp, int idx)); extern list_T *list_alloc __ARGS((void)); extern void list_unref __ARGS((list_T *l)); -extern void list_free __ARGS((list_T *l)); +extern void list_free __ARGS((list_T *l, int recurse)); extern dictitem_T *dict_lookup __ARGS((hashitem_T *hi)); extern int list_append_dict __ARGS((list_T *list, dict_T *dict)); extern int garbage_collect __ARGS((void)); diff -Naur vim70.orig/src/proto/menu.pro vim70/src/proto/menu.pro --- vim70.orig/src/proto/menu.pro 2006-05-07 06:08:51.000000000 -0700 +++ vim70/src/proto/menu.pro 2007-02-15 21:22:24.000000000 -0800 @@ -10,6 +10,7 @@ extern int menu_is_child_of_popup __ARGS((vimmenu_T *menu)); extern int menu_is_toolbar __ARGS((char_u *name)); extern int menu_is_separator __ARGS((char_u *name)); +extern int check_menu_pointer __ARGS((vimmenu_T *root, vimmenu_T *menu_to_check)); extern void gui_create_initial_menus __ARGS((vimmenu_T *menu)); extern void gui_update_menus __ARGS((int modes)); extern int gui_is_menu_shortcut __ARGS((int key)); diff -Naur vim70.orig/src/proto/misc2.pro vim70/src/proto/misc2.pro --- vim70.orig/src/proto/misc2.pro 2006-05-07 06:08:54.000000000 -0700 +++ vim70/src/proto/misc2.pro 2007-02-15 21:22:25.000000000 -0800 @@ -29,6 +29,7 @@ extern char_u *vim_strnsave __ARGS((char_u *string, int len)); extern char_u *vim_strsave_escaped __ARGS((char_u *string, char_u *esc_chars)); extern char_u *vim_strsave_escaped_ext __ARGS((char_u *string, char_u *esc_chars, int cc, int bsl)); +extern char_u *vim_strsave_shellescape __ARGS((char_u *string)); extern char_u *vim_strsave_up __ARGS((char_u *string)); extern char_u *vim_strnsave_up __ARGS((char_u *string, int len)); extern void vim_strup __ARGS((char_u *p)); diff -Naur vim70.orig/src/proto/ops.pro vim70/src/proto/ops.pro --- vim70.orig/src/proto/ops.pro 2006-05-07 06:08:58.000000000 -0700 +++ vim70/src/proto/ops.pro 2007-02-15 21:22:26.000000000 -0800 @@ -17,10 +17,10 @@ extern void put_register __ARGS((int name, void *reg)); extern int yank_register_mline __ARGS((int regname)); extern int do_record __ARGS((int c)); -extern int do_execreg __ARGS((int regname, int colon, int addcr)); +extern int do_execreg __ARGS((int regname, int colon, int addcr, int silent)); extern int insert_reg __ARGS((int regname, int literally)); extern int get_spec_reg __ARGS((int regname, char_u **argp, int *allocated, int errmsg)); -extern int cmdline_paste_reg __ARGS((int regname, int literally)); +extern int cmdline_paste_reg __ARGS((int regname, int literally, int remcr)); extern void adjust_clip_reg __ARGS((int *rp)); extern int op_delete __ARGS((oparg_T *oap)); extern int op_replace __ARGS((oparg_T *oap, int c)); diff -Naur vim70.orig/src/proto/undo.pro vim70/src/proto/undo.pro --- vim70.orig/src/proto/undo.pro 2006-05-07 06:09:11.000000000 -0700 +++ vim70/src/proto/undo.pro 2007-02-15 21:22:24.000000000 -0800 @@ -4,6 +4,7 @@ extern int u_savesub __ARGS((linenr_T lnum)); extern int u_inssub __ARGS((linenr_T lnum)); extern int u_savedel __ARGS((linenr_T lnum, long nlines)); +extern int undo_allowed __ARGS((void)); extern void u_undo __ARGS((int count)); extern void u_redo __ARGS((int count)); extern void undo_time __ARGS((long step, int sec, int absolute)); diff -Naur vim70.orig/src/quickfix.c vim70/src/quickfix.c --- vim70.orig/src/quickfix.c 2006-05-03 00:47:42.000000000 -0700 +++ vim70/src/quickfix.c 2007-02-15 21:22:27.000000000 -0800 @@ -106,7 +106,7 @@ static int qf_init_ext __ARGS((qf_info_T *qi, char_u *efile, buf_T *buf, typval_T *tv, char_u *errorformat, int newlist, linenr_T lnumfirst, linenr_T lnumlast)); static void qf_new_list __ARGS((qf_info_T *qi)); -static int qf_add_entry __ARGS((qf_info_T *qi, qfline_T **prevp, char_u *dir, char_u *fname, char_u *mesg, long lnum, int col, int vis_col, char_u *pattern, int nr, int type, int valid)); +static int qf_add_entry __ARGS((qf_info_T *qi, qfline_T **prevp, char_u *dir, char_u *fname, int bufnum, char_u *mesg, long lnum, int col, int vis_col, char_u *pattern, int nr, int type, int valid)); static void qf_msg __ARGS((qf_info_T *qi)); static void qf_free __ARGS((qf_info_T *qi, int idx)); static char_u *qf_types __ARGS((int, int)); @@ -500,8 +500,6 @@ { if (tv != NULL) { - int len; - if (tv->v_type == VAR_STRING) { /* Get the next line from the supplied string */ @@ -602,13 +600,19 @@ else type = 0; /* - * Extract error message data from matched line + * Extract error message data from matched line. + * We check for an actual submatch, because "\[" and "\]" in + * the 'errorformat' may cause the wrong submatch to be used. */ if ((i = (int)fmt_ptr->addr[0]) > 0) /* %f */ { - int c = *regmatch.endp[i]; + int c; + + if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) + continue; /* Expand ~/file and $HOME/file to full path. */ + c = *regmatch.endp[i]; *regmatch.endp[i] = NUL; expand_env(regmatch.startp[i], namebuf, CMDBUFFSIZE); *regmatch.endp[i] = c; @@ -618,35 +622,63 @@ continue; } if ((i = (int)fmt_ptr->addr[1]) > 0) /* %n */ + { + if (regmatch.startp[i] == NULL) + continue; enr = (int)atol((char *)regmatch.startp[i]); + } if ((i = (int)fmt_ptr->addr[2]) > 0) /* %l */ + { + if (regmatch.startp[i] == NULL) + continue; lnum = atol((char *)regmatch.startp[i]); + } if ((i = (int)fmt_ptr->addr[3]) > 0) /* %c */ + { + if (regmatch.startp[i] == NULL) + continue; col = (int)atol((char *)regmatch.startp[i]); + } if ((i = (int)fmt_ptr->addr[4]) > 0) /* %t */ + { + if (regmatch.startp[i] == NULL) + continue; type = *regmatch.startp[i]; + } if (fmt_ptr->flags == '+' && !multiscan) /* %+ */ STRCPY(errmsg, IObuff); else if ((i = (int)fmt_ptr->addr[5]) > 0) /* %m */ { + if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) + continue; len = (int)(regmatch.endp[i] - regmatch.startp[i]); vim_strncpy(errmsg, regmatch.startp[i], len); } if ((i = (int)fmt_ptr->addr[6]) > 0) /* %r */ + { + if (regmatch.startp[i] == NULL) + continue; tail = regmatch.startp[i]; + } if ((i = (int)fmt_ptr->addr[7]) > 0) /* %p */ { + 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; } if ((i = (int)fmt_ptr->addr[8]) > 0) /* %v */ { + if (regmatch.startp[i] == NULL) + continue; col = (int)atol((char *)regmatch.startp[i]); use_viscol = TRUE; } if ((i = (int)fmt_ptr->addr[9]) > 0) /* %s */ { + if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) + continue; len = (int)(regmatch.endp[i] - regmatch.startp[i]); if (len > CMDBUFFSIZE - 5) len = CMDBUFFSIZE - 5; @@ -759,6 +791,7 @@ (*namebuf || directory) ? namebuf : ((currfile && valid) ? currfile : (char_u *)NULL), + 0, errmsg, lnum, col, @@ -904,12 +937,13 @@ * Returns OK or FAIL. */ static int -qf_add_entry(qi, prevp, dir, fname, mesg, lnum, col, vis_col, pattern, nr, type, - valid) +qf_add_entry(qi, prevp, dir, fname, bufnum, mesg, lnum, col, vis_col, pattern, + nr, type, valid) qf_info_T *qi; /* quickfix list */ qfline_T **prevp; /* pointer to previously added entry or NULL */ char_u *dir; /* optional directory name */ char_u *fname; /* file name or NULL */ + int bufnum; /* buffer number or zero */ char_u *mesg; /* message */ long lnum; /* line number */ int col; /* column */ @@ -923,7 +957,10 @@ if ((qfp = (qfline_T *)alloc((unsigned)sizeof(qfline_T))) == NULL) return FAIL; - qfp->qf_fnum = qf_get_fnum(dir, fname); + if (bufnum != 0) + qfp->qf_fnum = bufnum; + else + qfp->qf_fnum = qf_get_fnum(dir, fname); if ((qfp->qf_text = vim_strsave(mesg)) == NULL) { vim_free(qfp); @@ -1074,6 +1111,7 @@ if (qf_add_entry(to->w_llist, &prevp, NULL, NULL, + 0, from_qfp->qf_text, from_qfp->qf_lnum, from_qfp->qf_col, @@ -1554,10 +1592,30 @@ } /* - * If there is only one window, create a new one above the quickfix - * window. + * If no usable window is found and 'switchbuf' is set to 'usetab' + * then search in other tabs. + */ + if (!usable_win && vim_strchr(p_swb, 'a') != NULL) + { + tabpage_T *tp; + win_T *wp; + + FOR_ALL_TAB_WINDOWS(tp, wp) + { + if (wp->w_buffer->b_fnum == qf_ptr->qf_fnum) + { + goto_tabpage_win(tp, wp); + usable_win = 1; + break; + } + } + } + + /* + * If there is only one window and is the quickfix window, create a new + * one above the quickfix window. */ - if (firstwin == lastwin || !usable_win) + if (((firstwin == lastwin) && bt_quickfix(curbuf)) || !usable_win) { ll_ref = curwin->w_llist_ref; @@ -2429,32 +2487,19 @@ qf_info_T *qi; { buf_T *buf; -#ifdef FEAT_AUTOCMD aco_save_T aco; -#else - buf_T *save_curbuf; -#endif /* Check if a buffer for the quickfix list exists. Update it. */ buf = qf_find_buf(qi); if (buf != NULL) { -#ifdef FEAT_AUTOCMD /* set curwin/curbuf to buf and save a few things */ aucmd_prepbuf(&aco, buf); -#else - save_curbuf = curbuf; - curbuf = buf; -#endif qf_fill_buffer(qi); -#ifdef FEAT_AUTOCMD /* restore curwin/curbuf and a few other things */ aucmd_restbuf(&aco); -#else - curbuf = save_curbuf; -#endif (void)qf_win_pos_update(qi, 0); } @@ -2943,10 +2988,8 @@ #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL) char_u *save_ei = NULL; #endif -#ifndef FEAT_AUTOCMD - buf_T *save_curbuf; -#else aco_save_T aco; +#ifdef FEAT_AUTOCMD char_u *au_name = NULL; int flags = 0; colnr_T col; @@ -3097,6 +3140,7 @@ if (qf_add_entry(qi, &prevp, NULL, /* dir */ fnames[fi], + 0, ml_get_buf(buf, regmatch.startpos[0].lnum + lnum, FALSE), regmatch.startpos[0].lnum + lnum, @@ -3167,24 +3211,13 @@ * need to be done now, in that buffer. And the modelines * need to be done (again). But not the window-local * options! */ -#if defined(FEAT_AUTOCMD) aucmd_prepbuf(&aco, buf); -#else - save_curbuf = curbuf; - curbuf = buf; - curwin->w_buffer = curbuf; -#endif #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL) apply_autocmds(EVENT_FILETYPE, buf->b_p_ft, buf->b_fname, TRUE, buf); #endif do_modelines(OPT_NOWIN); -#if defined(FEAT_AUTOCMD) aucmd_restbuf(&aco); -#else - curbuf = save_curbuf; - curwin->w_buffer = curbuf; -#endif } } } @@ -3285,11 +3318,7 @@ { buf_T *newbuf; int failed = TRUE; -#ifdef FEAT_AUTOCMD aco_save_T aco; -#else - buf_T *old_curbuf = curbuf; -#endif /* Allocate a buffer without putting it in the buffer list. */ newbuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY); @@ -3299,13 +3328,8 @@ /* Init the options. */ buf_copy_options(newbuf, BCO_ENTER | BCO_NOHELP); -#ifdef FEAT_AUTOCMD /* set curwin/curbuf to buf and save a few things */ aucmd_prepbuf(&aco, newbuf); -#else - curbuf = newbuf; - curwin->w_buffer = newbuf; -#endif /* Need to set the filename for autocommands. */ (void)setfname(curbuf, fname, NULL, FALSE); @@ -3336,13 +3360,8 @@ } } -#ifdef FEAT_AUTOCMD /* restore curwin/curbuf and a few other things */ aucmd_restbuf(&aco); -#else - curbuf = old_curbuf; - curwin->w_buffer = old_curbuf; -#endif if (!buf_valid(newbuf)) return NULL; @@ -3407,6 +3426,7 @@ char_u buf[2]; qfline_T *qfp; int i; + int bufnum; if (wp != NULL) { @@ -3422,6 +3442,11 @@ qfp = qi->qf_lists[qi->qf_curlist].qf_start; for (i = 1; !got_int && i <= qi->qf_lists[qi->qf_curlist].qf_count; ++i) { + /* Handle entries with a non-existing buffer number. */ + bufnum = qfp->qf_fnum; + if (bufnum != 0 && (buflist_findnr(bufnum) == NULL)) + bufnum = 0; + if ((dict = dict_alloc()) == NULL) return FAIL; if (list_append_dict(list, dict) == FAIL) @@ -3429,13 +3454,15 @@ buf[0] = qfp->qf_type; buf[1] = NUL; - if ( dict_add_nr_str(dict, "bufnr", (long)qfp->qf_fnum, NULL) == FAIL + if ( dict_add_nr_str(dict, "bufnr", (long)bufnum, NULL) == FAIL || dict_add_nr_str(dict, "lnum", (long)qfp->qf_lnum, NULL) == FAIL || dict_add_nr_str(dict, "col", (long)qfp->qf_col, NULL) == FAIL || dict_add_nr_str(dict, "vcol", (long)qfp->qf_viscol, NULL) == FAIL || dict_add_nr_str(dict, "nr", (long)qfp->qf_nr, NULL) == FAIL - || dict_add_nr_str(dict, "pattern", 0L, qfp->qf_pattern) == FAIL - || dict_add_nr_str(dict, "text", 0L, qfp->qf_text) == FAIL + || dict_add_nr_str(dict, "pattern", 0L, + qfp->qf_pattern == NULL ? (char_u *)"" : qfp->qf_pattern) == FAIL + || dict_add_nr_str(dict, "text", 0L, + qfp->qf_text == NULL ? (char_u *)"" : qfp->qf_text) == FAIL || dict_add_nr_str(dict, "type", 0L, buf) == FAIL || dict_add_nr_str(dict, "valid", (long)qfp->qf_valid, NULL) == FAIL) return FAIL; @@ -3458,6 +3485,7 @@ listitem_T *li; dict_T *d; char_u *filename, *pattern, *text, *type; + int bufnum; long lnum; int col, nr; int vcol; @@ -3465,6 +3493,7 @@ int valid, status; int retval = OK; qf_info_T *qi = &ql_info; + int did_bufnr_emsg = FALSE; if (wp != NULL) { @@ -3494,6 +3523,7 @@ continue; filename = get_dict_string(d, (char_u *)"filename", TRUE); + bufnum = get_dict_number(d, (char_u *)"bufnr"); lnum = get_dict_number(d, (char_u *)"lnum"); col = get_dict_number(d, (char_u *)"col"); vcol = get_dict_number(d, (char_u *)"vcol"); @@ -3505,12 +3535,26 @@ text = vim_strsave((char_u *)""); valid = TRUE; - if (filename == NULL || (lnum == 0 && pattern == NULL)) + if ((filename == NULL && bufnum == 0) || (lnum == 0 && pattern == NULL)) + valid = FALSE; + + /* Mark entries with non-existing buffer number as not valid. Give the + * error message only once. */ + if (bufnum != 0 && (buflist_findnr(bufnum) == NULL)) + { + if (!did_bufnr_emsg) + { + did_bufnr_emsg = TRUE; + EMSGN(_("E92: Buffer %ld not found"), bufnum); + } valid = FALSE; + bufnum = 0; + } status = qf_add_entry(qi, &prevp, NULL, /* dir */ filename, + bufnum, text, lnum, col, @@ -3743,6 +3787,7 @@ if (qf_add_entry(qi, &prevp, NULL, /* dir */ fnames[fi], + 0, IObuff, lnum, (int)(regmatch.startp[0] - IObuff) diff -Naur vim70.orig/src/regexp.c vim70/src/regexp.c --- vim70.orig/src/regexp.c 2006-04-30 08:31:50.000000000 -0700 +++ vim70/src/regexp.c 2007-02-15 21:22:26.000000000 -0800 @@ -3777,8 +3777,8 @@ op = OP(scan); /* Check for character class with NL added. */ - if (!reg_line_lbr && WITH_NL(op) && *reginput == NUL - && reglnum <= reg_maxline) + if (!reg_line_lbr && WITH_NL(op) && REG_MULTI + && *reginput == NUL && reglnum <= reg_maxline) { reg_nextline(); } @@ -3912,7 +3912,7 @@ { colnr_T start, end; colnr_T start2, end2; - colnr_T col; + colnr_T cols; getvvcol(wp, &top, &start, NULL, &end); getvvcol(wp, &bot, &start2, NULL, &end2); @@ -3922,9 +3922,9 @@ end = end2; if (top.col == MAXCOL || bot.col == MAXCOL) end = MAXCOL; - col = win_linetabsize(wp, + cols = win_linetabsize(wp, regline, (colnr_T)(reginput - regline)); - if (col < start || col > end - (*p_sel == 'e')) + if (cols < start || cols > end - (*p_sel == 'e')) status = RA_NOMATCH; } } @@ -4253,7 +4253,7 @@ { int i, len; char_u *opnd; - int opndc, inpc; + int opndc = 0, inpc; opnd = OPERAND(scan); /* Safety check (just in case 'encoding' was changed since @@ -4855,8 +4855,8 @@ break; case NEWL: - if ((c != NUL || reglnum > reg_maxline || reg_line_lbr) - && (c != '\n' || !reg_line_lbr)) + if ((c != NUL || !REG_MULTI || reglnum > reg_maxline + || reg_line_lbr) && (c != '\n' || !reg_line_lbr)) status = RA_NOMATCH; else if (reg_line_lbr) ADVANCE_REGINPUT(); @@ -5316,8 +5316,8 @@ ++count; mb_ptr_adv(scan); } - if (!WITH_NL(OP(p)) || reglnum > reg_maxline || reg_line_lbr - || count == maxcount) + if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline + || reg_line_lbr || count == maxcount) break; ++count; /* count the line-break */ reg_nextline(); @@ -5341,7 +5341,8 @@ } else if (*scan == NUL) { - if (!WITH_NL(OP(p)) || reglnum > reg_maxline || reg_line_lbr) + if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline + || reg_line_lbr) break; reg_nextline(); scan = reginput; @@ -5370,7 +5371,8 @@ } else if (*scan == NUL) { - if (!WITH_NL(OP(p)) || reglnum > reg_maxline || reg_line_lbr) + if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline + || reg_line_lbr) break; reg_nextline(); scan = reginput; @@ -5399,7 +5401,8 @@ } else if (*scan == NUL) { - if (!WITH_NL(OP(p)) || reglnum > reg_maxline || reg_line_lbr) + if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline + || reg_line_lbr) break; reg_nextline(); scan = reginput; @@ -5424,7 +5427,8 @@ { if (*scan == NUL) { - if (!WITH_NL(OP(p)) || reglnum > reg_maxline || reg_line_lbr) + if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline + || reg_line_lbr) break; reg_nextline(); scan = reginput; @@ -5454,7 +5458,8 @@ #endif if (*scan == NUL) { - if (!WITH_NL(OP(p)) || reglnum > reg_maxline || reg_line_lbr) + if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline + || reg_line_lbr) break; reg_nextline(); scan = reginput; @@ -5617,7 +5622,8 @@ #endif if (*scan == NUL) { - if (!WITH_NL(OP(p)) || reglnum > reg_maxline || reg_line_lbr) + if (!REG_MULTI || !WITH_NL(OP(p)) || reglnum > reg_maxline + || reg_line_lbr) break; reg_nextline(); scan = reginput; @@ -5646,8 +5652,8 @@ case NEWL: while (count < maxcount - && ((*scan == NUL && reglnum <= reg_maxline && !reg_line_lbr) - || (*scan == '\n' && reg_line_lbr))) + && ((*scan == NUL && reglnum <= reg_maxline && !reg_line_lbr + && REG_MULTI) || (*scan == '\n' && reg_line_lbr))) { count++; if (reg_line_lbr) diff -Naur vim70.orig/src/screen.c vim70/src/screen.c --- vim70.orig/src/screen.c 2006-05-05 03:13:55.000000000 -0700 +++ vim70/src/screen.c 2007-02-15 21:22:26.000000000 -0800 @@ -455,6 +455,7 @@ && curwin->w_topline == curwin->w_lines[0].wl_lnum) #ifdef FEAT_VISUAL || (type == INVERTED + && VIsual_active && curwin->w_old_cursor_lnum == curwin->w_cursor.lnum && curwin->w_old_visual_mode == VIsual_mode && (curwin->w_valid & VALID_VIRTCOL) @@ -1228,7 +1229,14 @@ { mid_end = wp->w_height; if (lastwin == firstwin) + { screenclear(); +#ifdef FEAT_WINDOWS + /* The screen was cleared, redraw the tab pages line. */ + if (redraw_tabline) + draw_tabline(); +#endif + } } } else @@ -2612,7 +2620,8 @@ #ifdef FEAT_LINEBREAK int need_showbreak = FALSE; #endif -#if defined(FEAT_SIGNS) || (defined(FEAT_QUICKFIX) && defined(FEAT_WINDOWS)) +#if defined(FEAT_SIGNS) || (defined(FEAT_QUICKFIX) && defined(FEAT_WINDOWS)) \ + || defined(FEAT_SYN_HL) || defined(FEAT_DIFF) # define LINE_ATTR int line_attr = 0; /* atrribute for the whole line */ #endif @@ -2626,7 +2635,7 @@ int prev_c = 0; /* previous Arabic character */ int prev_c1 = 0; /* first composing char for prev_c */ #endif -#if defined(FEAT_DIFF) || defined(LINE_ATTR) +#if defined(LINE_ATTR) int did_line_attr = 0; #endif @@ -4116,17 +4125,12 @@ --ptr; /* put it back at the NUL */ } #endif -#if defined(FEAT_DIFF) || defined(LINE_ATTR) +#if defined(LINE_ATTR) else if (( # ifdef FEAT_DIFF - diff_hlf != (hlf_T)0 -# ifdef LINE_ATTR - || -# endif + diff_hlf != (hlf_T)0 || # endif -# ifdef LINE_ATTR line_attr != 0 -# endif ) && ( # ifdef FEAT_RIGHTLEFT wp->w_p_rl ? (col >= 0) : @@ -4237,7 +4241,7 @@ * At end of the text line or just after the last character. */ if (c == NUL -#if defined(FEAT_DIFF) || defined(LINE_ATTR) +#if defined(LINE_ATTR) || did_line_attr == 1 #endif ) @@ -4258,7 +4262,7 @@ || prevcol == (long)match_hl[0].startcol || prevcol == (long)match_hl[1].startcol || prevcol == (long)match_hl[2].startcol) -# if defined(FEAT_DIFF) || defined(LINE_ATTR) +# if defined(LINE_ATTR) && did_line_attr <= 1 # endif ) @@ -5076,15 +5080,38 @@ * character too. If we didn't skip any blanks above, then we * only redraw if the character wasn't already redrawn anyway. */ - if (gui.in_use && (col > startCol || !redraw_this) -# ifdef FEAT_MBYTE - && enc_dbcs == 0 -# endif - ) + if (gui.in_use && (col > startCol || !redraw_this)) { hl = ScreenAttrs[off_to]; if (hl > HL_ALL || (hl & HL_BOLD)) - screen_char(off_to - 1, row, col + coloff - 1); + { + int prev_cells = 1; +# ifdef FEAT_MBYTE + if (enc_utf8) + /* for utf-8, ScreenLines[char_offset + 1] == 0 means + * that its width is 2. */ + prev_cells = ScreenLines[off_to - 1] == 0 ? 2 : 1; + else if (enc_dbcs != 0) + { + /* find previous character by counting from first + * column and get its width. */ + unsigned off = LineOffset[row]; + + while (off < off_to) + { + prev_cells = (*mb_off2cells)(off); + off += prev_cells; + } + } + + if (enc_dbcs != 0 && prev_cells > 1) + screen_char_2(off_to - prev_cells, row, + col + coloff - prev_cells); + else +# endif + screen_char(off_to - prev_cells, row, + col + coloff - prev_cells); + } } #endif screen_fill(row, row + 1, col + coloff, clear_width + coloff, @@ -7103,7 +7130,7 @@ tabpage_T *tp; #endif static int entered = FALSE; /* avoid recursiveness */ - static int did_outofmem_msg = FALSE; /* did outofmem message */ + static int done_outofmem_msg = FALSE; /* did outofmem message */ /* * Allocation of the screen buffers is done only when the size changes and @@ -7133,6 +7160,12 @@ return; entered = TRUE; + /* + * Note that the window sizes are updated before reallocating the arrays, + * thus we must not redraw here! + */ + ++RedrawingDisabled; + win_new_shellsize(); /* fit the windows in the new sized shell */ comp_col(); /* recompute columns for shown command and ruler */ @@ -7205,14 +7238,14 @@ #endif || outofmem) { - if (ScreenLines != NULL || !did_outofmem_msg) + if (ScreenLines != NULL || !done_outofmem_msg) { /* guess the size */ do_outofmem_msg((long_u)((Rows + 1) * Columns)); /* Remember we did this to avoid getting outofmem messages over * and over again. */ - did_outofmem_msg = TRUE; + done_outofmem_msg = TRUE; } vim_free(new_ScreenLines); new_ScreenLines = NULL; @@ -7240,7 +7273,7 @@ } else { - did_outofmem_msg = FALSE; + done_outofmem_msg = FALSE; for (new_row = 0; new_row < Rows; ++new_row) { @@ -7367,6 +7400,7 @@ #endif entered = FALSE; + --RedrawingDisabled; #ifdef FEAT_AUTOCMD if (starting == 0) diff -Naur vim70.orig/src/search.c vim70/src/search.c --- vim70.orig/src/search.c 2006-05-05 05:12:13.000000000 -0700 +++ vim70/src/search.c 2007-02-15 21:22:27.000000000 -0800 @@ -812,7 +812,11 @@ #ifdef FEAT_MBYTE if (has_mbyte) { - ptr = ml_get_buf(buf, pos->lnum, FALSE); + /* 'e' offset may put us just below the last line */ + if (pos->lnum > buf->b_ml.ml_line_count) + ptr = (char_u *)""; + else + ptr = ml_get_buf(buf, pos->lnum, FALSE); pos->col -= (*mb_head_off)(ptr, ptr + pos->col); } #endif @@ -1259,7 +1263,7 @@ /* * Add character and/or line offset */ - if (!(options & SEARCH_NOOF) || *pat == ';') + if (!(options & SEARCH_NOOF) || (pat != NULL && *pat == ';')) { if (spats[0].off.line) /* Add the offset to the line number. */ { @@ -4688,6 +4692,7 @@ #ifdef FEAT_INS_EXPAND if (action == ACTION_EXPAND) { + msg_hist_off = TRUE; /* reset in msg_trunc_attr() */ vim_snprintf((char*)IObuff, IOSIZE, _("Scanning included file: %s"), (char *)new_fname); @@ -4826,15 +4831,20 @@ if ((compl_cont_status & CONT_ADDING) && i == compl_length) { - /* get the next line */ /* IOSIZE > compl_length, so the STRNCPY works */ STRNCPY(IObuff, aux, i); - if (!( depth < 0 - && lnum < end_lnum - && (line = ml_get(++lnum)) != NULL) - && !( depth >= 0 - && !vim_fgets(line = file_line, - LSIZE, files[depth].fp))) + + /* Get the next line: when "depth" < 0 from the current + * buffer, otherwise from the included file. Jump to + * exit_matched when past the last line. */ + if (depth < 0) + { + if (lnum >= end_lnum) + goto exit_matched; + line = ml_get(++lnum); + } + else if (vim_fgets(line = file_line, + LSIZE, files[depth].fp)) goto exit_matched; /* we read a line, set "already" to check this "line" later @@ -4871,7 +4881,7 @@ goto exit_matched; } - add_r = ins_compl_add_infercase(aux, i, FALSE, + add_r = ins_compl_add_infercase(aux, i, p_ic, curr_fname == curbuf->b_fname ? NULL : curr_fname, dir, reuse); if (add_r == OK) diff -Naur vim70.orig/src/spell.c vim70/src/spell.c --- vim70.orig/src/spell.c 2006-05-05 00:49:58.000000000 -0700 +++ vim70/src/spell.c 2007-02-15 21:22:25.000000000 -0800 @@ -1483,7 +1483,7 @@ else if ((mode == FIND_COMPOUND || mode == FIND_KEEPCOMPOUND || !word_ends)) { - /* If there is no flag or the word is shorter than + /* If there is no compound flag or the word is shorter than * COMPOUNDMIN reject it quickly. * Makes you wonder why someone puts a compound flag on a word * that's too short... Myspell compatibility requires this @@ -2043,8 +2043,8 @@ int len; # ifdef FEAT_SYN_HL int has_syntax = syntax_present(wp->w_buffer); - int col; # endif + int col; int can_spell; char_u *buf = NULL; int buflen = 0; @@ -2093,9 +2093,8 @@ capcol = (int)(skipwhite(line) - line); else if (curline && wp == curwin) { - int col = (int)(skipwhite(line) - line); - /* For spellbadword(): check if first word needs a capital. */ + col = (int)(skipwhite(line) - line); if (check_need_cap(lnum, col)) capcol = col; @@ -2108,7 +2107,8 @@ * possible. */ STRCPY(buf, line); if (lnum < wp->w_buffer->b_ml.ml_line_count) - spell_cat_line(buf + STRLEN(buf), ml_get(lnum + 1), MAXWLEN); + spell_cat_line(buf + STRLEN(buf), + ml_get_buf(wp->w_buffer, lnum + 1, FALSE), MAXWLEN); p = buf + skip; endp = buf + len; @@ -5060,7 +5060,7 @@ int do_rep; int do_repsal; int do_sal; - int do_map; + int do_mapline; int found_map = FALSE; hashitem_T *hi; int l; @@ -5098,7 +5098,7 @@ do_sal = spin->si_sal.ga_len == 0; /* Only do MAP lines when not done in another .aff file already. */ - do_map = spin->si_map.ga_len == 0; + do_mapline = spin->si_map.ga_len == 0; /* * Allocate and init the afffile_T structure. @@ -5780,7 +5780,7 @@ smsg((char_u *)_("Expected MAP count in %s line %d"), fname, lnum); } - else if (do_map) + else if (do_mapline) { int c; @@ -7507,7 +7507,7 @@ { char_u *p = p_msm; long start = 0; - long inc = 0; + long incr = 0; long added = 0; if (!VIM_ISDIGIT(*p)) @@ -7519,7 +7519,7 @@ ++p; if (!VIM_ISDIGIT(*p)) return FAIL; - inc = (getdigits(&p) * 102) / (SBLOCKSIZE / 10); + incr = (getdigits(&p) * 102) / (SBLOCKSIZE / 10); if (*p != ',') return FAIL; ++p; @@ -7529,11 +7529,11 @@ if (*p != NUL) return FAIL; - if (start == 0 || inc == 0 || added == 0 || inc > start) + if (start == 0 || incr == 0 || added == 0 || incr > start) return FAIL; compress_start = start; - compress_inc = inc; + compress_inc = incr; compress_added = added; return OK; } @@ -8291,14 +8291,14 @@ * Returns the number of nodes used. */ static int -put_node(fd, node, index, regionmask, prefixtree) +put_node(fd, node, idx, regionmask, prefixtree) FILE *fd; /* NULL when only counting */ wordnode_T *node; - int index; + int idx; int regionmask; int prefixtree; /* TRUE for PREFIXTREE */ { - int newindex = index; + int newindex = idx; int siblingcount = 0; wordnode_T *np; int flags; @@ -8308,7 +8308,7 @@ return 0; /* Store the index where this node is written. */ - node->wn_u1.index = index; + node->wn_u1.index = idx; /* Count the number of siblings. */ for (np = node; np != NULL; np = np->wn_sibling) @@ -9243,15 +9243,15 @@ * Add "word[len]" to 'spellfile' as a good or bad word. */ void -spell_add_word(word, len, bad, index, undo) +spell_add_word(word, len, bad, idx, undo) char_u *word; int len; int bad; - int index; /* "zG" and "zW": zero, otherwise index in + int idx; /* "zG" and "zW": zero, otherwise index in 'spellfile' */ int undo; /* TRUE for "zug", "zuG", "zuw" and "zuW" */ { - FILE *fd; + FILE *fd = NULL; buf_T *buf = NULL; int new_spf = FALSE; char_u *fname; @@ -9261,7 +9261,7 @@ int i; char_u *spf; - if (index == 0) /* use internal wordlist */ + if (idx == 0) /* use internal wordlist */ { if (int_wordlist == NULL) { @@ -9289,11 +9289,11 @@ for (spf = curbuf->b_p_spf, i = 1; *spf != NUL; ++i) { copy_option_part(&spf, fnamebuf, MAXPATHL, ","); - if (i == index) + if (i == idx) break; if (*spf == NUL) { - EMSGN(_("E765: 'spellfile' does not have %ld entries"), index); + EMSGN(_("E765: 'spellfile' does not have %ld entries"), idx); return; } } @@ -9336,7 +9336,10 @@ { fputc('#', fd); if (undo) + { + home_replace(NULL, fname, NameBuff, MAXPATHL, TRUE); smsg((char_u *)_("Word removed from %s"), NameBuff); + } } fseek(fd, fpos_next, SEEK_SET); } @@ -9344,20 +9347,27 @@ fclose(fd); } } - else + + if (!undo) { fd = mch_fopen((char *)fname, "a"); if (fd == NULL && new_spf) { + char_u *p; + /* We just initialized the 'spellfile' option and can't open the * file. We may need to create the "spell" directory first. We * already checked the runtime directory is writable in * init_spellfile(). */ - if (!dir_of_file_exists(fname)) + if (!dir_of_file_exists(fname) && (p = gettail_sep(fname)) != fname) { + int c = *p; + /* The directory doesn't exist. Try creating it and opening * the file again. */ - vim_mkdir(NameBuff, 0755); + *p = NUL; + vim_mkdir(fname, 0755); + *p = c; fd = mch_fopen((char *)fname, "a"); } } @@ -10070,6 +10080,7 @@ /* List the suggestions. */ msg_start(); + msg_row = Rows - 1; /* for when 'cmdheight' > 1 */ lines_left = Rows; /* avoid more prompt */ vim_snprintf((char *)IObuff, IOSIZE, _("Change \"%.*s\" to:"), sug.su_badlen, sug.su_badptr); @@ -13579,53 +13590,58 @@ * the first "the" to itself. */ return; - /* Check if the word is already there. Also check the length that is - * being replaced "thes," -> "these" is a different suggestion from - * "thes" -> "these". */ - stp = &SUG(*gap, 0); - for (i = gap->ga_len; --i >= 0; ++stp) - if (stp->st_wordlen == goodlen - && stp->st_orglen == badlen - && STRNCMP(stp->st_word, goodword, goodlen) == 0) - { - /* - * Found it. Remember the word with the lowest score. - */ - if (stp->st_slang == NULL) - stp->st_slang = slang; + if (gap->ga_len == 0) + i = -1; + else + { + /* Check if the word is already there. Also check the length that is + * being replaced "thes," -> "these" is a different suggestion from + * "thes" -> "these". */ + stp = &SUG(*gap, 0); + for (i = gap->ga_len; --i >= 0; ++stp) + if (stp->st_wordlen == goodlen + && stp->st_orglen == badlen + && STRNCMP(stp->st_word, goodword, goodlen) == 0) + { + /* + * Found it. Remember the word with the lowest score. + */ + if (stp->st_slang == NULL) + stp->st_slang = slang; - new_sug.st_score = score; - new_sug.st_altscore = altscore; - new_sug.st_had_bonus = had_bonus; + new_sug.st_score = score; + new_sug.st_altscore = altscore; + new_sug.st_had_bonus = had_bonus; + + if (stp->st_had_bonus != had_bonus) + { + /* Only one of the two had the soundalike score computed. + * Need to do that for the other one now, otherwise the + * scores can't be compared. This happens because + * suggest_try_change() doesn't compute the soundalike + * word to keep it fast, while some special methods set + * the soundalike score to zero. */ + if (had_bonus) + rescore_one(su, stp); + else + { + new_sug.st_word = stp->st_word; + new_sug.st_wordlen = stp->st_wordlen; + new_sug.st_slang = stp->st_slang; + new_sug.st_orglen = badlen; + rescore_one(su, &new_sug); + } + } - if (stp->st_had_bonus != had_bonus) - { - /* Only one of the two had the soundalike score computed. - * Need to do that for the other one now, otherwise the - * scores can't be compared. This happens because - * suggest_try_change() doesn't compute the soundalike - * word to keep it fast, while some special methods set - * the soundalike score to zero. */ - if (had_bonus) - rescore_one(su, stp); - else + if (stp->st_score > new_sug.st_score) { - new_sug.st_word = stp->st_word; - new_sug.st_wordlen = stp->st_wordlen; - new_sug.st_slang = stp->st_slang; - new_sug.st_orglen = badlen; - rescore_one(su, &new_sug); + stp->st_score = new_sug.st_score; + stp->st_altscore = new_sug.st_altscore; + stp->st_had_bonus = new_sug.st_had_bonus; } + break; } - - if (stp->st_score > new_sug.st_score) - { - stp->st_score = new_sug.st_score; - stp->st_altscore = new_sug.st_altscore; - stp->st_had_bonus = new_sug.st_had_bonus; - } - break; - } + } if (i < 0 && ga_grow(gap, 1) == OK) { @@ -15656,7 +15672,7 @@ ? MB_STRNICMP(p, pat, STRLEN(pat)) == 0 : STRNCMP(p, pat, STRLEN(pat)) == 0) && ins_compl_add_infercase(p, (int)STRLEN(p), - FALSE, NULL, *dir, 0) == OK) + p_ic, NULL, *dir, 0) == OK) /* if dir was BACKWARD then honor it just once */ *dir = FORWARD; } diff -Naur vim70.orig/src/structs.h vim70/src/structs.h --- vim70.orig/src/structs.h 2006-04-09 10:57:46.000000000 -0700 +++ vim70/src/structs.h 2007-02-15 21:22:24.000000000 -0800 @@ -2213,18 +2213,20 @@ /* * Struct to save values in before executing autocommands for a buffer that is - * not the current buffer. + * not the current buffer. Without FEAT_AUTOCMD only "curbuf" is remembered. */ typedef struct { buf_T *save_buf; /* saved curbuf */ +#ifdef FEAT_AUTOCMD buf_T *new_curbuf; /* buffer to be used */ win_T *save_curwin; /* saved curwin, NULL if it didn't change */ win_T *new_curwin; /* new curwin if save_curwin != NULL */ pos_T save_cursor; /* saved cursor pos of save_curwin */ linenr_T save_topline; /* saved topline of save_curwin */ -#ifdef FEAT_DIFF +# ifdef FEAT_DIFF int save_topfill; /* saved topfill of save_curwin */ +# endif #endif } aco_save_T; diff -Naur vim70.orig/src/syntax.c vim70/src/syntax.c --- vim70.orig/src/syntax.c 2006-04-26 05:49:45.000000000 -0700 +++ vim70/src/syntax.c 2007-02-15 21:22:27.000000000 -0800 @@ -977,6 +977,7 @@ { stateitem_T *cur_si; int i; + int seen_keepend; if (startofline) { @@ -1002,7 +1003,10 @@ /* * Need to update the end of a start/skip/end that continues from the * previous line. And regions that have "keepend", because they may - * influence contained items. + * influence contained items. If we've just removed "extend" + * (startofline == 0) then we should update ends of normal regions + * contained inside "keepend" because "extend" could have extended + * these "keepend" regions as well as contained normal regions. * Then check for items ending in column 0. */ i = current_state.ga_len - 1; @@ -1010,10 +1014,13 @@ for ( ; i > keepend_level; --i) if (CUR_STATE(i).si_flags & HL_EXTEND) break; + + seen_keepend = FALSE; for ( ; i < current_state.ga_len; ++i) { cur_si = &CUR_STATE(i); if ((cur_si->si_flags & HL_KEEPEND) + || (seen_keepend && !startofline) || (i == current_state.ga_len - 1 && startofline)) { cur_si->si_h_startpos.col = 0; /* start highl. in col 0 */ @@ -1021,6 +1028,9 @@ if (!(cur_si->si_flags & HL_MATCHCONT)) update_si_end(cur_si, (int)current_col, !startofline); + + if (!startofline && (cur_si->si_flags & HL_KEEPEND)) + seen_keepend = TRUE; } } check_keepend(); @@ -2564,6 +2574,7 @@ { int i; lpos_T maxpos; + lpos_T maxpos_h; stateitem_T *sip; /* @@ -2583,23 +2594,30 @@ break; maxpos.lnum = 0; + maxpos_h.lnum = 0; for ( ; i < current_state.ga_len; ++i) { sip = &CUR_STATE(i); if (maxpos.lnum != 0) { limit_pos_zero(&sip->si_m_endpos, &maxpos); - limit_pos_zero(&sip->si_h_endpos, &maxpos); + limit_pos_zero(&sip->si_h_endpos, &maxpos_h); limit_pos_zero(&sip->si_eoe_pos, &maxpos); sip->si_ends = TRUE; } - if (sip->si_ends - && (sip->si_flags & HL_KEEPEND) - && (maxpos.lnum == 0 + if (sip->si_ends && (sip->si_flags & HL_KEEPEND)) + { + if (maxpos.lnum == 0 || maxpos.lnum > sip->si_m_endpos.lnum || (maxpos.lnum == sip->si_m_endpos.lnum - && maxpos.col > sip->si_m_endpos.col))) - maxpos = sip->si_m_endpos; + && maxpos.col > sip->si_m_endpos.col)) + maxpos = sip->si_m_endpos; + if (maxpos_h.lnum == 0 + || maxpos_h.lnum > sip->si_h_endpos.lnum + || (maxpos_h.lnum == sip->si_h_endpos.lnum + && maxpos_h.col > sip->si_h_endpos.col)) + maxpos_h = sip->si_h_endpos; + } } } @@ -3188,7 +3206,7 @@ curbuf->b_syn_spell = SYNSPL_TOP; else if (STRNICMP(arg, "notoplevel", 10) == 0 && next - arg == 10) curbuf->b_syn_spell = SYNSPL_NOTOP; - else if (STRNICMP(arg, "default", 4) == 0 && next - arg == 4) + else if (STRNICMP(arg, "default", 7) == 0 && next - arg == 7) curbuf->b_syn_spell = SYNSPL_DEFAULT; else EMSG2(_("E390: Illegal argument: %s"), arg); @@ -6054,7 +6072,11 @@ ++level; } if (level > wp->w_p_fdn) + { level = wp->w_p_fdn; + if (level < 0) + level = 0; + } return level; } #endif diff -Naur vim70.orig/src/tag.c vim70/src/tag.c --- vim70.orig/src/tag.c 2006-04-27 06:11:21.000000000 -0700 +++ vim70/src/tag.c 2007-02-15 21:22:26.000000000 -0800 @@ -911,7 +911,7 @@ set_errorlist(curwin, list, ' '); - list_free(list); + list_free(list, TRUE); cur_match = 0; /* Jump to the first tag */ } @@ -3787,6 +3787,7 @@ { int num_matches, i, ret; char_u **matches, *p; + char_u *full_fname; dict_T *dict; tagptrs_T tp; long is_static; @@ -3809,9 +3810,10 @@ if (list_append_dict(list, dict) == FAIL) ret = FAIL; + full_fname = tag_full_fname(&tp); if (add_tag_field(dict, "name", tp.tagname, tp.tagname_end) == FAIL - || add_tag_field(dict, "filename", tp.fname, - tp.fname_end) == FAIL + || add_tag_field(dict, "filename", full_fname, + NULL) == FAIL || add_tag_field(dict, "cmd", tp.command, tp.command_end) == FAIL || add_tag_field(dict, "kind", tp.tagkind, @@ -3819,6 +3821,8 @@ || dict_add_nr_str(dict, "static", is_static, NULL) == FAIL) ret = FAIL; + vim_free(full_fname); + if (tp.command_end != NULL) { for (p = tp.command_end + 3; diff -Naur vim70.orig/src/term.c vim70/src/term.c --- vim70.orig/src/term.c 2006-05-03 10:34:57.000000000 -0700 +++ vim70/src/term.c 2007-02-15 21:22:26.000000000 -0800 @@ -3137,25 +3137,32 @@ screenalloc(FALSE); repeat_message(); } - else if (State & CMDLINE) - { - update_screen(NOT_VALID); - redrawcmdline(); - } else { - update_topline(); -#if defined(FEAT_INS_EXPAND) - if (pum_visible()) +#ifdef FEAT_SCROLLBIND + if (curwin->w_p_scb) + do_check_scrollbind(TRUE); +#endif + if (State & CMDLINE) { - redraw_later(NOT_VALID); - ins_compl_show_pum(); /* This includes the redraw. */ + update_screen(NOT_VALID); + redrawcmdline(); } else + { + update_topline(); +#if defined(FEAT_INS_EXPAND) + if (pum_visible()) + { + redraw_later(NOT_VALID); + ins_compl_show_pum(); /* This includes the redraw. */ + } + else #endif - update_screen(NOT_VALID); - if (redrawing()) - setcursor(); + update_screen(NOT_VALID); + if (redrawing()) + setcursor(); + } } cursor_on(); /* redrawing may have switched it off */ } @@ -4783,6 +4790,14 @@ return -1; current_menu = (vimmenu_T *)val; slen += num_bytes; + + /* The menu may have been deleted right after it was used, check + * for that. */ + if (check_menu_pointer(root_menu, current_menu) == FAIL) + { + key_name[0] = KS_EXTRA; + key_name[1] = (int)KE_IGNORE; + } } # endif # ifdef FEAT_GUI_TABLINE diff -Naur vim70.orig/src/testdir/test56.in vim70/src/testdir/test56.in --- vim70.orig/src/testdir/test56.in 2005-05-18 08:37:37.000000000 -0700 +++ vim70/src/testdir/test56.in 2007-02-15 21:22:25.000000000 -0800 @@ -3,7 +3,7 @@ STARTTEST :so small.vim :" -:set nocp +:set nocp viminfo+=nviminfo :/^start:/+1,/^end:/-1w! Xtest.vim :source Xtest.vim _x diff -Naur vim70.orig/src/ui.c vim70/src/ui.c --- vim70.orig/src/ui.c 2006-03-27 11:15:09.000000000 -0800 +++ vim70/src/ui.c 2007-02-15 21:22:25.000000000 -0800 @@ -1137,7 +1137,6 @@ int len; #ifdef FEAT_MBYTE char_u *p; - int i; #endif int row1 = clip_star.start.lnum; int col1 = clip_star.start.col; @@ -1218,6 +1217,8 @@ #ifdef FEAT_MBYTE if (enc_dbcs != 0) { + int i; + p = ScreenLines + LineOffset[row]; for (i = start_col; i < end_col; ++i) if (enc_dbcs == DBCS_JPNU && p[i] == 0x8e) diff -Naur vim70.orig/src/undo.c vim70/src/undo.c --- vim70.orig/src/undo.c 2006-04-21 02:30:59.000000000 -0700 +++ vim70/src/undo.c 2007-02-15 21:22:27.000000000 -0800 @@ -84,7 +84,6 @@ static void u_unch_branch __ARGS((u_header_T *uhp)); static u_entry_T *u_get_headentry __ARGS((void)); static void u_getbot __ARGS((void)); -static int undo_allowed __ARGS((void)); static int u_savecommon __ARGS((linenr_T, linenr_T, linenr_T)); static void u_doit __ARGS((int count)); static void u_undoredo __ARGS((int undo)); @@ -196,7 +195,7 @@ * Return TRUE when undo is allowed. Otherwise give an error message and * return FALSE. */ - static int + int undo_allowed() { /* Don't allow changes when 'modifiable' is off. */ @@ -342,11 +341,15 @@ uhp->uh_alt_next = old_curhead; if (old_curhead != NULL) { + uhp->uh_alt_prev = old_curhead->uh_alt_prev; + if (uhp->uh_alt_prev != NULL) + uhp->uh_alt_prev->uh_alt_next = uhp; old_curhead->uh_alt_prev = uhp; if (curbuf->b_u_oldhead == old_curhead) curbuf->b_u_oldhead = uhp; } - uhp->uh_alt_prev = NULL; + else + uhp->uh_alt_prev = NULL; if (curbuf->b_u_newhead != NULL) curbuf->b_u_newhead->uh_prev = uhp; @@ -857,6 +860,11 @@ uhp = curbuf->b_u_curhead; while (uhp != NULL) { + /* Go back to the first branch with a mark. */ + while (uhp->uh_alt_prev != NULL + && uhp->uh_alt_prev->uh_walk == mark) + uhp = uhp->uh_alt_prev; + /* Find the last branch with a mark, that's the one. */ last = uhp; while (last->uh_alt_next != NULL @@ -866,6 +874,8 @@ { /* Make the used branch the first entry in the list of * alternatives to make "u" and CTRL-R take this branch. */ + while (uhp->uh_alt_prev != NULL) + uhp = uhp->uh_alt_prev; if (last->uh_alt_next != NULL) last->uh_alt_next->uh_alt_prev = last->uh_alt_prev; last->uh_alt_prev->uh_alt_next = last->uh_alt_next; @@ -1188,7 +1198,7 @@ int did_undo; /* just did an undo */ int absolute; /* used ":undo N" */ { - char *msg; + char *msgstr; u_header_T *uhp; char_u msgbuf[80]; @@ -1206,20 +1216,20 @@ u_oldcount -= u_newcount; if (u_oldcount == -1) - msg = N_("more line"); + msgstr = N_("more line"); else if (u_oldcount < 0) - msg = N_("more lines"); + msgstr = N_("more lines"); else if (u_oldcount == 1) - msg = N_("line less"); + msgstr = N_("line less"); else if (u_oldcount > 1) - msg = N_("fewer lines"); + msgstr = N_("fewer lines"); else { u_oldcount = u_newcount; if (u_newcount == 1) - msg = N_("change"); + msgstr = N_("change"); else - msg = N_("changes"); + msgstr = N_("changes"); } if (curbuf->b_u_curhead != NULL) @@ -1245,7 +1255,7 @@ smsg((char_u *)_("%ld %s; %s #%ld %s"), u_oldcount < 0 ? -u_oldcount : u_oldcount, - _(msg), + _(msgstr), did_undo ? _("before") : _("after"), uhp == NULL ? 0L : uhp->uh_seq, msgbuf); diff -Naur vim70.orig/src/version.c vim70/src/version.c --- vim70.orig/src/version.c 2006-05-03 00:50:42.000000000 -0700 +++ vim70/src/version.c 2007-02-15 21:22:27.000000000 -0800 @@ -667,6 +667,360 @@ static int included_patches[] = { /* Add new patch number below this line */ /**/ + 195, +/**/ + 194, +/**/ + 193, +/**/ + 192, +/**/ + 191, +/**/ + 190, +/**/ + 189, +/**/ + 188, +/**/ + 187, +/**/ + 186, +/**/ + 185, +/**/ + 184, +/**/ + 183, +/**/ + 182, +/**/ + 181, +/**/ + 179, +/**/ + 178, +/**/ + 177, +/**/ + 176, +/**/ + 175, +/**/ + 174, +/**/ + 173, +/**/ + 172, +/**/ + 169, +/**/ + 168, +/**/ + 167, +/**/ + 166, +/**/ + 165, +/**/ + 164, +/**/ + 163, +/**/ + 162, +/**/ + 160, +/**/ + 159, +/**/ + 158, +/**/ + 157, +/**/ + 155, +/**/ + 154, +/**/ + 153, +/**/ + 152, +/**/ + 151, +/**/ + 150, +/**/ + 149, +/**/ + 148, +/**/ + 147, +/**/ + 146, +/**/ + 145, +/**/ + 144, +/**/ + 143, +/**/ + 142, +/**/ + 141, +/**/ + 140, +/**/ + 139, +/**/ + 137, +/**/ + 136, +/**/ + 135, +/**/ + 134, +/**/ + 133, +/**/ + 129, +/**/ + 128, +/**/ + 127, +/**/ + 126, +/**/ + 125, +/**/ + 124, +/**/ + 123, +/**/ + 122, +/**/ + 121, +/**/ + 120, +/**/ + 119, +/**/ + 118, +/**/ + 117, +/**/ + 116, +/**/ + 115, +/**/ + 114, +/**/ + 113, +/**/ + 112, +/**/ + 111, +/**/ + 110, +/**/ + 109, +/**/ + 107, +/**/ + 106, +/**/ + 105, +/**/ + 104, +/**/ + 103, +/**/ + 102, +/**/ + 101, +/**/ + 100, +/**/ + 99, +/**/ + 98, +/**/ + 97, +/**/ + 96, +/**/ + 95, +/**/ + 94, +/**/ + 93, +/**/ + 92, +/**/ + 91, +/**/ + 90, +/**/ + 89, +/**/ + 88, +/**/ + 87, +/**/ + 86, +/**/ + 85, +/**/ + 84, +/**/ + 83, +/**/ + 82, +/**/ + 81, +/**/ + 80, +/**/ + 79, +/**/ + 78, +/**/ + 77, +/**/ + 76, +/**/ + 75, +/**/ + 73, +/**/ + 72, +/**/ + 71, +/**/ + 70, +/**/ + 69, +/**/ + 68, +/**/ + 67, +/**/ + 66, +/**/ + 64, +/**/ + 63, +/**/ + 62, +/**/ + 61, +/**/ + 60, +/**/ + 59, +/**/ + 58, +/**/ + 56, +/**/ + 55, +/**/ + 54, +/**/ + 53, +/**/ + 52, +/**/ + 51, +/**/ + 50, +/**/ + 49, +/**/ + 48, +/**/ + 47, +/**/ + 46, +/**/ + 44, +/**/ + 43, +/**/ + 42, +/**/ + 41, +/**/ + 40, +/**/ + 39, +/**/ + 38, +/**/ + 37, +/**/ + 36, +/**/ + 35, +/**/ + 34, +/**/ + 33, +/**/ + 31, +/**/ + 30, +/**/ + 29, +/**/ + 26, +/**/ + 25, +/**/ + 24, +/**/ + 23, +/**/ + 22, +/**/ + 21, +/**/ + 20, +/**/ + 19, +/**/ + 18, +/**/ + 17, +/**/ + 16, +/**/ + 15, +/**/ + 14, +/**/ + 13, +/**/ + 12, +/**/ + 11, +/**/ + 10, +/**/ + 9, +/**/ + 8, +/**/ + 7, +/**/ + 6, +/**/ + 4, +/**/ + 3, +/**/ + 2, +/**/ + 1, +/**/ 0 }; @@ -731,7 +1085,11 @@ /* Only MS VC 4.1 and earlier can do Win32s */ MSG_PUTS(_("\nMS-Windows 16/32 bit GUI version")); # else +# ifdef _WIN64 + MSG_PUTS(_("\nMS-Windows 64 bit GUI version")); +# else MSG_PUTS(_("\nMS-Windows 32 bit GUI version")); +# endif # endif if (gui_is_win32s()) MSG_PUTS(_(" in Win32s mode")); diff -Naur vim70.orig/src/vim.h vim70/src/vim.h --- vim70.orig/src/vim.h 2006-04-30 08:32:38.000000000 -0700 +++ vim70/src/vim.h 2007-02-15 21:22:27.000000000 -0800 @@ -585,7 +585,6 @@ #define INSERT 0x10 /* Insert mode */ #define LANGMAP 0x20 /* Language mapping, can be combined with INSERT and CMDLINE */ -#define MAP_ALL_MODES 0x3f /* all mode bits used for mapping */ #define REPLACE_FLAG 0x40 /* Replace mode flag */ #define REPLACE (REPLACE_FLAG + INSERT) @@ -605,6 +604,9 @@ #define CONFIRM 0x800 /* ":confirm" prompt */ #define SELECTMODE 0x1000 /* Select mode, only for mappings */ +#define MAP_ALL_MODES (0x3f | SELECTMODE) /* all mode bits used for + * mapping */ + /* directions */ #define FORWARD 1 #define BACKWARD (-1) @@ -1100,7 +1102,7 @@ EVENT_COLORSCHEME, /* after loading a colorscheme */ EVENT_FILEAPPENDPOST, /* after appending to a file */ EVENT_FILEAPPENDPRE, /* before appending to a file */ - EVENT_FILEAPPENDCMD, /* appende to a file using command */ + EVENT_FILEAPPENDCMD, /* append to a file using command */ EVENT_FILECHANGEDSHELL, /* after shell command that changed file */ EVENT_FILECHANGEDSHELLPOST, /* after (not) reloading changed file */ EVENT_FILECHANGEDRO, /* before first change to read-only file */ @@ -1118,6 +1120,7 @@ EVENT_FOCUSGAINED, /* got the focus */ EVENT_FOCUSLOST, /* lost the focus to another app */ EVENT_GUIENTER, /* after starting the GUI */ + EVENT_GUIFAILED, /* after starting the GUI failed */ EVENT_INSERTCHANGE, /* when changing Insert/Replace mode */ EVENT_INSERTENTER, /* when entering Insert mode */ EVENT_INSERTLEAVE, /* when leaving Insert mode */ @@ -1144,6 +1147,7 @@ EVENT_REMOTEREPLY, /* upon string reception from a remote vim */ EVENT_SWAPEXISTS, /* found existing swap file */ EVENT_SOURCEPRE, /* before sourcing a Vim script */ + EVENT_SOURCECMD, /* sourcing a Vim script using command */ EVENT_SPELLFILEMISSING, /* spell file missing */ EVENT_CURSORMOVED, /* cursor was moved */ EVENT_CURSORMOVEDI, /* cursor was moved in Insert mode */ @@ -1666,7 +1670,10 @@ #define VV_SWAPCHOICE 46 #define VV_SWAPCOMMAND 47 #define VV_CHAR 48 -#define VV_LEN 49 /* number of v: vars */ +#define VV_MOUSE_WIN 49 +#define VV_MOUSE_LNUM 50 +#define VV_MOUSE_COL 51 +#define VV_LEN 52 /* number of v: vars */ #ifdef FEAT_CLIPBOARD diff -Naur vim70.orig/src/window.c vim70/src/window.c --- vim70.orig/src/window.c 2006-05-06 03:54:51.000000000 -0700 +++ vim70/src/window.c 2007-02-15 21:22:26.000000000 -0800 @@ -340,10 +340,10 @@ { tabpage_T *oldtab = curtab; tabpage_T *newtab; - win_T *wp = curwin; /* First create a new tab with the window, then go back to * the old tab and close the window there. */ + wp = curwin; if (win_new_tabpage((int)Prenum) == OK && valid_tabpage(oldtab)) { @@ -3954,13 +3954,8 @@ setmouse(); /* in case jumped to/from help buffer */ #endif -#ifdef FEAT_AUTOCHDIR - /* Change directories when the 'acd' option is set on and after - * switching windows. */ - if (p_acd && curbuf->b_ffname != NULL - && vim_chdirfile(curbuf->b_ffname) == OK) - shorten_fnames(TRUE); -#endif + /* Change directories when the 'acd' option is set. */ + DO_AUTOCHDIR } #endif /* FEAT_WINDOWS */ @@ -4278,7 +4273,7 @@ win_T *wp; { wp->w_lines_valid = 0; - wp->w_lines = (wline_T *)alloc((unsigned)(Rows * sizeof(wline_T))); + wp->w_lines = (wline_T *)alloc_clear((unsigned)(Rows * sizeof(wline_T))); if (wp->w_lines == NULL) return FAIL; return OK; @@ -5194,11 +5189,7 @@ int height; { linenr_T lnum; - linenr_T bot; int sline, line_size; - int space; - int did_below = FALSE; - int old_height = wp->w_height; #define FRACTION_MULT 16384L /* Don't want a negative height. Happens when splitting a tiny window. @@ -5233,54 +5224,44 @@ wp->w_wrow = ((long)wp->w_fraction * (long)height - 1L) / FRACTION_MULT; line_size = plines_win_col(wp, lnum, (long)(wp->w_cursor.col)) - 1; sline = wp->w_wrow - line_size; + + if (sline >= 0) + { + /* Make sure the whole cursor line is visible, if possible. */ + int rows = plines_win(wp, lnum, FALSE); + + if (sline > wp->w_height - rows) + { + sline = wp->w_height - rows; + wp->w_wrow -= rows - line_size; + } + } + if (sline < 0) { /* * Cursor line would go off top of screen if w_wrow was this high. + * Make cursor line the first line in the window. If not enough + * room use w_skipcol; */ wp->w_wrow = line_size; + if (wp->w_wrow >= wp->w_height + && (W_WIDTH(wp) - win_col_off(wp)) > 0) + { + wp->w_skipcol += W_WIDTH(wp) - win_col_off(wp); + --wp->w_wrow; + while (wp->w_wrow >= wp->w_height) + { + wp->w_skipcol += W_WIDTH(wp) - win_col_off(wp) + + win_col_off2(wp); + --wp->w_wrow; + } + } } else { - space = height - 1; - - while (lnum > 1) + while (sline > 0 && lnum > 1) { - /* When using "~" lines stop when at the old topline, don't - * scroll down. */ - if (did_below && height < old_height && lnum <= wp->w_topline) - sline = 0; - - space -= line_size; - if (space > 0 && sline <= 0 && !did_below) - { - /* Try to use "~" lines below the text to avoid that text - * is above the window while there are empty lines. - * Subtract the rows below the cursor from "space" and - * give the rest to "sline". */ - did_below = TRUE; - bot = wp->w_cursor.lnum; - while (space > 0) - { - if (wp->w_buffer->b_ml.ml_line_count - bot >= space) - space = 0; - else - { -#ifdef FEAT_FOLDING - hasFoldingWin(wp, bot, NULL, &bot, TRUE, NULL); -#endif - if (bot >= wp->w_buffer->b_ml.ml_line_count) - break; - ++bot; - space -= plines_win(wp, bot, TRUE); - } - } - if (bot == wp->w_buffer->b_ml.ml_line_count && space > 0) - sline += space; - } - if (sline <= 0) - break; - #ifdef FEAT_FOLDING hasFoldingWin(wp, lnum, &lnum, NULL, TRUE, NULL); if (lnum == 1)