# HG changeset patch # User vimboss # Date 1109062151 0 # Node ID 4d9eabb1396e3c94692e5afe77f2a2713e5c53dc # Parent c93c9cad961808120973bed1fb52e6ab8ebab666 updated for version 7.0051 diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt --- a/runtime/doc/autocmd.txt +++ b/runtime/doc/autocmd.txt @@ -1,4 +1,4 @@ -*autocmd.txt* For Vim version 7.0aa. Last change: 2005 Feb 07 +*autocmd.txt* For Vim version 7.0aa. Last change: 2005 Feb 21 VIM REFERENCE MANUAL by Bram Moolenaar @@ -204,10 +204,12 @@ FilterReadPre Before reading a file fr the current buffer, not the name of the temporary file that is the output of the filter command. + Not triggered when 'shelltemp' is off. *FilterReadPost* FilterReadPost After reading a file from a filter command. Vim checks the pattern against the name of the current buffer as with FilterReadPre. + Not triggered when 'shelltemp' is off. *FileType* FileType When the 'filetype' option has been set. can be used for the name of the file @@ -270,11 +272,13 @@ FilterWritePre Before writing a file f the current buffer, not the name of the temporary file that is the output of the filter command. + Not triggered when 'shelltemp' is off. *FilterWritePost* FilterWritePost After writing a file for a filter command or making a diff. Vim checks the pattern against the name of the current buffer as with FilterWritePre. + Not triggered when 'shelltemp' is off. *FileChangedShell* FileChangedShell When Vim notices that the modification time of a file has changed since editing started. diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt --- a/runtime/doc/change.txt +++ b/runtime/doc/change.txt @@ -1,4 +1,4 @@ -*change.txt* For Vim version 7.0aa. Last change: 2005 Feb 08 +*change.txt* For Vim version 7.0aa. Last change: 2005 Feb 21 VIM REFERENCE MANUAL by Bram Moolenaar @@ -112,19 +112,22 @@ gJ Join [count] lines, with a minimum Vi} *:j* *:join* -:[range]j[oin][!] Join [range] lines. Same as "J", except with [!] +:[range]j[oin][!] [flags] + Join [range] lines. Same as "J", except with [!] the join does not insert or delete any spaces. If a [range] has equal start and end values, this command does nothing. The default behavior is to join the current line with the line below it. {not in Vi: !} + See |ex-flags| for [flags]. -:[range]j[oin][!] {count} +:[range]j[oin][!] {count} [flags] Join {count} lines, starting with [range] (default: current line |cmdline-ranges|). Same as "J", except with [!] the join does not insert or delete any spaces. {not in Vi: !} + See |ex-flags| for [flags]. These commands delete the between lines. This has the effect of joining multiple lines into one line. You can repeat these commands (except ":j") and @@ -236,10 +239,12 @@ If you prefer "cw" to include the space :map cw dwi < *:c* *:ch* *:change* -:{range}c[hange] Replace lines of text with some different text. +:{range}c[hange][!] Replace lines of text with some different text. Type a line containing only "." to stop replacing. Without {range}, this command changes only the current line. + Adding [!] toggles 'autoindent' for the time this + command is executed. ============================================================================== 3. Simple changes *simple-change* @@ -424,12 +429,15 @@ SHIFTING LINES LEFT OR RIGHT *shift-l lines to [indent] (default 0). {not in Vi} *:>* -:[range]> Shift {count} [range] lines one 'shiftwidth' right. +:[range]> [flags] Shift {count} [range] lines one 'shiftwidth' right. Repeat '>' for shifting multiple 'shiftwidth's. + See |ex-flags| for [flags]. -:[range]> {count} Shift {count} lines one 'shiftwidth' right, starting +:[range]> {count} [flags] + Shift {count} lines one 'shiftwidth' right, starting with [range] (default current line |cmdline-ranges|). Repeat '>' for shifting multiple 'shiftwidth's. + See |ex-flags| for [flags]. The ">" and "<" commands are handy for changing the indentation within programs. Use the 'shiftwidth' option to set the size of the white space @@ -519,7 +527,7 @@ comment (starting with '"') after the ": 4.2 Substitute *:substitute* *:s* *:su* -:[range]s[ubstitute]/{pattern}/{string}/[&][c][e][g][p][r][i][I] [count] +:[range]s[ubstitute]/{pattern}/{string}/[&][#][c][e][g][p][r][i][I] [count] For each line in [range] replace a match of {pattern} with {string}. For the {pattern} see |pattern|. @@ -533,8 +541,8 @@ 4.2 Substitute *:substitute* Also see |cmdline-ranges|. See |:s_flags| for the flags. -:[range]s[ubstitute] [c][e][g][p][r][i][I] [count] -:[range]&[&][c][e][g][p][r][i][I] [count] *:&* +:[range]s[ubstitute] [#][c][e][g][p][r][i][I] [count] +:[range]&[&][#][c][e][g][p][r][i][I] [count] *:&* Repeat last :substitute with same search pattern and substitute string, but without the same flags. You may add extra flags (see |:s_flags|). @@ -544,7 +552,7 @@ 4.2 Substitute *:substitute* 'r' flags isn't required, but in scripts it's a good idea to keep it to avoid confusion. -:[range]~[&][c][e][g][p][r][i][I] [count] *:~* +:[range]~[&][#][c][e][g][p][r][i][I] [count] *:~* Repeat last substitute with same substitute string but with last used search pattern. This is like ":&r". See |:s_flags| for the flags. @@ -622,7 +630,10 @@ The flags that you can use for the subst {not in Vi} [p] Print the line containing the last substitute. - {not in Vi} + +[#] Like [p] and prepend the line number. + +[l] Like [l] but print the text like |:list|. [r] Only useful in combination with ":&" or ":s" without arguments. ":&r" works the same way as ":~": When the search pattern is empty, use the @@ -668,6 +679,9 @@ For the definition of a pattern, see |pa When the {string} starts with "\=" it is evaluated as an expression, see |sub-replace-expression|. Otherwise these characters in {string} have a special meaning: + *:s%* +When {string} is equal to "%" and '/' is included with the 'cpotions' option, +then the {string} of the previous substitute command is used. |cpo-/| magic nomagic action ~ & \& replaced with the whole matched pattern *s/\&* diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 7.0aa. Last change: 2005 Feb 11 +*eval.txt* For Vim version 7.0aa. Last change: 2005 Feb 21 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1484,13 +1484,16 @@ matchstr( {expr}, {pat}[, {start}[, {cou String {count}'th match of {pat} in {expr} max({list}) Number maximum value of items in {list} min({list}) Number minumum value of items in {list} +mkdir({name} [, {path} [, {prot}]]) + Number create directory {name} mode() String current editing mode nextnonblank( {lnum}) Number line nr of non-blank line >= {lnum} nr2char( {expr}) String single char with ASCII value {expr} prevnonblank( {lnum}) Number line nr of non-blank line <= {lnum} range( {expr} [, {max} [, {stride}]]) List items from {expr} to {max} -readfile({fname} [, {binary}]) List get list of lines from file {fname} +readfile({fname} [, {binary} [, {max}]]) + List get list of lines from file {fname} remote_expr( {server}, {string} [, {idvar}]) String send expression remote_foreground( {server}) Number bring Vim server to the foreground @@ -3099,6 +3102,19 @@ min({list}) Return the minumum value of be used as a Number this results in an error. An empty List results in zero. + *mkdir()* *E749* +mkdir({name} [, {path} [, {prot}]]) + Create directory {name}. + If {path} is "p" then intermediate directories are created as + necessary. Otherwise it must be "". + If {prot} is given it is used to set the protection bits of + the new directory. The default is 0755 (rwxr-xr-x: r/w for + the user readable for others). Use 0700 to make it unreadable + for others. + This function is not available in the |sandbox|. + Not available on all systems. To check use: > + :if exists("*mkdir") +< *mode()* mode() Return a string that indicates the current mode: n Normal @@ -3158,7 +3174,7 @@ range({expr} [, {max} [, {stride}]]) range(2, -2, -1) " [2, 1, 0, -1, -2] < *readfile()* -readfile({fname} [, {binary}]) +readfile({fname} [, {binary} [, {max}]]) Read file {fname} and return a List, each line of the file as an item. Lines broken at NL characters. Macintosh files separated with CR will result in a single long line (unless a @@ -3171,9 +3187,16 @@ readfile({fname} [, {binary}]) - CR characters that appear before a NL are removed. - Whether the last line ends in a NL or not does not matter. All NUL characters are replaced with a NL character. - Note that the whole file is read into memory and there is no - recognition of encoding. Read a file into a buffer if you - need to. + When {max} is given this specifies the maximum number of lines + to be read. Useful if you only want to check the first ten + lines of a file: > + :for line in readfile(fname, '', 10) + : if line =~ 'Date' | echo line | endif + :endfor +< When {max} is zero or negative the result is an empty list. + Note that without {max} the whole file is read into memory. + Also note that there is no recognition of encoding. Read a + file into a buffer if you need to. When the file can't be opened an error message is given and the result is an empty list. Also see |writefile()|. @@ -3997,6 +4020,8 @@ extra_search Compiled with support for |'hlsearch'| farsi Compiled with Farsi support |farsi|. file_in_path Compiled with support for |gf| and || +filterpipe When 'shelltemp' is off pipes are used for shell + read/write/filter commands find_in_path Compiled with support for include file searches |+find_in_path|. fname_case Case in file names matters (for Amiga, MS-DOS, and @@ -4374,7 +4399,7 @@ The file "~/vim/bufnetfuncs.vim" should Using an autoload script ~ - + *autoload* *E746* Using a script in the "autoload" directory is simpler, but requires using exactly the right file name. A function that can be autoloaded has a name like this: > @@ -4404,9 +4429,24 @@ Vim will look for the file "autoload/foo The name before the first colon must be at least two characters long, otherwise it looks like a scope, such as "s:". +This also works when reading a variable that has not been set yet: > + + :let l = foo:bar:lvar + +When assigning a value to such a variable nothing special happens. This can +be used to pass settings to the autoload script before it's loaded: > + + :let foo:bar:toggle = 1 + :call foo:bar:func() + Note that when you make a mistake and call a function that is supposed to be defined in an autoload script, but the script doesn't actually define the function, the script will be sourced every time you try to call the function. +And you will get an error message every time. + +Also note that if you have two script files, and one calls a function in the +other and vise versa, before the used function is defined, it won't work. +Avoid using the autoload functionality at the toplevel. ============================================================================== 6. Curly braces names *curly-braces-names* diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1,4 +1,4 @@ -*options.txt* For Vim version 7.0aa. Last change: 2005 Feb 10 +*options.txt* For Vim version 7.0aa. Last change: 2005 Feb 21 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1745,9 +1745,11 @@ A jump table for the options with a shor enables cancelling the mapping by typing . *cpo-l* l Backslash in a [] range in a search pattern is taken - literally, only "\]" is special See |/[]| + literally, only "\]", "\^", "\-" and "\\" are special. + See |/[]| 'l' included: "/[ \t]" finds , '\' and 't' 'l' excluded: "/[ \t]" finds and + Also see |cpo-\|. *cpo-L* L When the 'list' option is set, 'wrapmargin', 'textwidth', 'softtabstop' and Virtual Replace mode @@ -1895,17 +1897,31 @@ A jump table for the options with a shor contains behavior ~ *cpo-#* # A count before "D", "o" and "O" has no effect. + *cpo-&* + & When ":preserve" was used keep the swap file when + exiting normally while this buffer is still loaded. + This flag is tested when exiting. + *cpo-\* + \ Backslash in a [] range in a search pattern is taken + literally, only "\]" is special See |/[]| + 'l' included: "/[ \t]" finds , '\' and 't' + 'l' excluded: "/[ \t]" finds and + Also see |cpo-\|. + *cpo-/* + / When "%" is used as the replacement string in a |:s| + command, use the previous replacement string. |:s%| *cpo-{* { The |{| and |}| commands also stop at a "{" character at the start of a line. + *cpo-.* + . The ":chdir" and ":cd" commands fail if the current + buffer is modified, unless ! is used. Vim doesn't + need this, since it remembers the full path of an + opened file. *cpo-bar* | The value of the $LINES and $COLUMNS environment variables overrule the terminal size values obtained with system specific functions. - *cpo-&* - & When ":preserve" was used keep the swap file when - exiting normally while this buffer is still loaded. - This flag is tested when exiting. *'cscopepathcomp'* *'cspc'* @@ -1972,6 +1988,9 @@ A jump table for the options with a shor When set to "msg", error messages that would otherwise be omitted will be given anyway. This is useful when debugging 'foldexpr' or 'indentexpr'. + When set to "beep", a message will be given when otherwise only a beep + would be produced. + The values can be combined, separated by a comma. *'define'* *'def'* 'define' 'def' string (default "^\s*#\s*define") @@ -4708,6 +4727,11 @@ A jump table for the options with a shor List of items that control the format of the output of |:hardcopy|. See |popt-option|. + *'prompt'* *'noprompt'* +'prompt' boolean (default on) + global + When on a ":" prompt is used in Ex mode. + *'quoteescape'* *'qe'* 'quoteescape' 'qe' string (default "\") local to buffer @@ -5239,6 +5263,22 @@ A jump table for the options with a shor separator. To test if this is so use: > if exists('+shellslash') < + *'shelltemp'* *'stmp'* *'noshelltemp'* *'nostmp'* +'shelltemp' 'stmp' boolean (Vi default off, Vim default on) + global + {not in Vi} + When on, use temp files for shell commands. When off use a pipe. + When using a pipe is not possible temp files are used anyway. + Currently a pipe is only supported on Unix. You can check it with: > + :if has("filterpipe") +< The advantage of using a pipe is that nobody can read the temp file + and the 'shell' command does not need to support redirection. + The advantage of using a temp file is that the file type and encoding + can be detected. + The |FilterReadPre|, |FilterReadPost| and |FilterWritePre|, + |FilterWritePost| autocommands event are not triggered when + 'shelltemp' is off. + *'shelltype'* *'st'* 'shelltype' 'st' number (default 0) global @@ -5288,7 +5328,8 @@ A jump table for the options with a shor |'cindent'|, |>>|, |<<|, etc. *'shortmess'* *'shm'* -'shortmess' 'shm' string (Vim default "filnxtToO", Vi default: "") +'shortmess' 'shm' string (Vim default "filnxtToO", Vi default: "", + POSIX default: "A") global {not in Vi} This option helps to avoid all the |hit-enter| prompts caused by file diff --git a/runtime/doc/pattern.txt b/runtime/doc/pattern.txt --- a/runtime/doc/pattern.txt +++ b/runtime/doc/pattern.txt @@ -1,4 +1,4 @@ -*pattern.txt* For Vim version 7.0aa. Last change: 2005 Jan 26 +*pattern.txt* For Vim version 7.0aa. Last change: 2005 Feb 20 VIM REFERENCE MANUAL by Bram Moolenaar @@ -522,11 +522,6 @@ An atom can be followed by an indication matched and in what way. This is called a multi. See |/multi| for an overview. -It is not possible to use a multi that can match more than one time after an -atom that can match an empty string. That's because this could result in an -endless loop. If you try it, you will get this error message: > - *, \+ or \{ operand could be empty -< */star* */\star* *E56* * (use \* when 'magic' is not set) Matches 0 or more of the preceding atom, as many as possible. @@ -577,7 +572,7 @@ endless loop. If you try it, you will g \{-} matches 0 or more of the preceding atom, as few as possible {Vi does not have any of these} - n and m are positive decimal numbers + n and m are positive decimal numbers or zero If a "-" appears immediately after the "{", then a shortest match first algorithm is used (see example below). In particular, "\{-}" is @@ -982,6 +977,17 @@ x A single character, with no special me a list of at least one character, each of which is either '-', '.', '/', alphabetic, numeric, '_' or '~'. These items only work for 8-bit characters. + */[[=* *[==]* + - An equivalence class. This means that characters are matched that + have almost the same meaning, e.g., when ignoring accents. The form + is: + [=a=] + Currrently this is only implemented for latin1. Also works for the + latin1 characters in utf-8 and latin9. + */[[.* *[..]* + - A collation element. This currently simply accepts a single + character in the form: + [.a.] */\]* - To include a literal ']', '^', '-' or '\' in the collection, put a backslash before it: "[xyz\]]", "[\^xyz]", "[xy\-z]" and "[xyz\\]". diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt --- a/runtime/doc/repeat.txt +++ b/runtime/doc/repeat.txt @@ -1,4 +1,4 @@ -*repeat.txt* For Vim version 7.0aa. Last change: 2005 Jan 28 +*repeat.txt* For Vim version 7.0aa. Last change: 2005 Feb 19 VIM REFERENCE MANUAL by Bram Moolenaar @@ -81,6 +81,11 @@ This replaces all occurrences of "pat" w :%s/pat/PAT/g Which is two characters shorter! +A special case is using ":visual" as a command. This will move to a matching +line, go to Normal mode to let you execute commands there until you use |Q| to +return to Ex mode. This will be repeated for each matching line. While doing +this you cannot use ":global". + ============================================================================== 3. Complex repeats *complex-repeat* @@ -102,7 +107,7 @@ q Stops recording. (Implementation no expression. The result of the expression is then executed. See also |@:|. {Vi: only named registers} - *@@* + *@@* *E748* @@ Repeat the previous @{0-9a-z":*} [count] times. :[addr]*{0-9a-z".=} *:@* *:star* diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt --- a/runtime/doc/starting.txt +++ b/runtime/doc/starting.txt @@ -1,4 +1,4 @@ -*starting.txt* For Vim version 7.0aa. Last change: 2005 Feb 10 +*starting.txt* For Vim version 7.0aa. Last change: 2005 Feb 19 VIM REFERENCE MANUAL by Bram Moolenaar @@ -263,8 +263,14 @@ a slash. Thus "-R" means recovery and " To be used when Vim is used to execute Ex commands from a file instead of a terminal. Switches off most prompts and informative messages. Also warnings and error messages. - But ":print" output is displayed. And when 'verbose' is - non-zero messages are printed (for debugging). + The output of these commands is displayed (to stdout): + :print + :list + :number + :set to display option values. + When 'verbose' is non-zero messages are printed (for + debugging, to stderr). + 'term' and $TERM are not used. If Vim appears to be stuck try typing "qa!". You don't get a prompt thus you can't see Vim is waiting for you to type something. diff --git a/runtime/doc/tags b/runtime/doc/tags --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -506,6 +506,7 @@ 'nopi' options.txt /*'nopi'* 'nopreserveindent' options.txt /*'nopreserveindent'* 'nopreviewwindow' options.txt /*'nopreviewwindow'* +'noprompt' options.txt /*'noprompt'* 'nopvw' options.txt /*'nopvw'* 'noreadonly' options.txt /*'noreadonly'* 'noremap' options.txt /*'noremap'* @@ -528,6 +529,7 @@ 'nosecure' options.txt /*'nosecure'* 'nosft' options.txt /*'nosft'* 'noshellslash' options.txt /*'noshellslash'* +'noshelltemp' options.txt /*'noshelltemp'* 'noshiftround' options.txt /*'noshiftround'* 'noshortname' options.txt /*'noshortname'* 'noshowcmd' options.txt /*'noshowcmd'* @@ -549,6 +551,7 @@ 'nossl' options.txt /*'nossl'* 'nosta' options.txt /*'nosta'* 'nostartofline' options.txt /*'nostartofline'* +'nostmp' options.txt /*'nostmp'* 'noswapfile' options.txt /*'noswapfile'* 'noswf' options.txt /*'noswf'* 'nota' options.txt /*'nota'* @@ -633,7 +636,7 @@ 'printmbcharset' options.txt /*'printmbcharset'* 'printmbfont' options.txt /*'printmbfont'* 'printoptions' options.txt /*'printoptions'* -'prompt' vi_diff.txt /*'prompt'* +'prompt' options.txt /*'prompt'* 'pt' options.txt /*'pt'* 'pvh' options.txt /*'pvh'* 'pvw' options.txt /*'pvw'* @@ -687,6 +690,7 @@ 'shellquote' options.txt /*'shellquote'* 'shellredir' options.txt /*'shellredir'* 'shellslash' options.txt /*'shellslash'* +'shelltemp' options.txt /*'shelltemp'* 'shelltype' options.txt /*'shelltype'* 'shellxquote' options.txt /*'shellxquote'* 'shiftround' options.txt /*'shiftround'* @@ -732,6 +736,7 @@ 'startofline' options.txt /*'startofline'* 'statusline' options.txt /*'statusline'* 'stl' options.txt /*'stl'* +'stmp' options.txt /*'stmp'* 'sts' options.txt /*'sts'* 'su' options.txt /*'su'* 'sua' options.txt /*'sua'* @@ -1213,6 +1218,8 @@ /. pattern.txt /*\/.* //; pattern.txt /*\/\/;* / pattern.txt /*\/* +/[[. pattern.txt /*\/[[.* +/[[= pattern.txt /*\/[[=* /[] pattern.txt /*\/[]* /\ pattern.txt /*\/\\* /\$ pattern.txt /*\/\\$* @@ -1848,7 +1855,7 @@ 90.5 usr_90.txt /*90.5* :display change.txt /*:display* :dj tagsrch.txt /*:dj* :djump tagsrch.txt /*:djump* -:dl tagsrch.txt /*:dl* +:dli tagsrch.txt /*:dli* :dlist tagsrch.txt /*:dlist* :do autocmd.txt /*:do* :doau autocmd.txt /*:doau* @@ -2280,6 +2287,7 @@ 90.5 usr_90.txt /*90.5* :rv starting.txt /*:rv* :rviminfo starting.txt /*:rviminfo* :s change.txt /*:s* +:s% change.txt /*:s%* :sN windows.txt /*:sN* :sNext windows.txt /*:sNext* :s\= change.txt /*:s\\=* @@ -2840,6 +2848,7 @@ CTRL-M motion.txt /*CTRL-M* CTRL-N motion.txt /*CTRL-N* CTRL-O motion.txt /*CTRL-O* CTRL-P motion.txt /*CTRL-P* +CTRL-Q gui_w32.txt /*CTRL-Q* CTRL-R undo.txt /*CTRL-R* CTRL-T tagsrch.txt /*CTRL-T* CTRL-U scroll.txt /*CTRL-U* @@ -3653,6 +3662,10 @@ E742 eval.txt /*E742* E743 eval.txt /*E743* E744 netbeans.txt /*E744* E745 eval.txt /*E745* +E746 eval.txt /*E746* +E747 syntax.txt /*E747* +E748 repeat.txt /*E748* +E749 eval.txt /*E749* E75 vi_diff.txt /*E75* E76 pattern.txt /*E76* E77 message.txt /*E77* @@ -3922,6 +3935,7 @@ ZZ editing.txt /*ZZ* [( motion.txt /*[(* [++opt] editing.txt /*[++opt]* [+cmd] editing.txt /*[+cmd]* +[..] pattern.txt /*[..]* [/ motion.txt /*[\/* [:alnum:] pattern.txt /*[:alnum:]* [:alpha:] pattern.txt /*[:alpha:]* @@ -3940,6 +3954,7 @@ ZZ editing.txt /*ZZ* [:upper:] pattern.txt /*[:upper:]* [:xdigit:] pattern.txt /*[:xdigit:]* [ change.txt /*[* +[==] pattern.txt /*[==]* [D tagsrch.txt /*[D* [I tagsrch.txt /*[I* [M motion.txt /*[M* @@ -4121,6 +4136,7 @@ autocmds-kept version5.txt /*autocmds-ke autocommand autocmd.txt /*autocommand* autocommand-events autocmd.txt /*autocommand-events* autocommand-pattern autocmd.txt /*autocommand-pattern* +autoload eval.txt /*autoload* autoload-functions eval.txt /*autoload-functions* avoid-hit-enter version5.txt /*avoid-hit-enter* aw motion.txt /*aw* @@ -4385,6 +4401,8 @@ cpo-% options.txt /*cpo-%* cpo-& options.txt /*cpo-&* cpo-+ options.txt /*cpo-+* cpo-- options.txt /*cpo--* +cpo-. options.txt /*cpo-.* +cpo-/ options.txt /*cpo-\/* cpo-< options.txt /*cpo-<* cpo-> options.txt /*cpo->* cpo-A options.txt /*cpo-A* @@ -4404,6 +4422,8 @@ cpo-R options.txt /*cpo-R* cpo-S options.txt /*cpo-S* cpo-W options.txt /*cpo-W* cpo-X options.txt /*cpo-X* +cpo-Z options.txt /*cpo-Z* +cpo-\ options.txt /*cpo-\\* cpo-a options.txt /*cpo-a* cpo-b options.txt /*cpo-b* cpo-bar options.txt /*cpo-bar* @@ -4655,6 +4675,7 @@ evim.vim starting.txt /*evim.vim* ex starting.txt /*ex* ex-cmd-index index.txt /*ex-cmd-index* ex-edit-index index.txt /*ex-edit-index* +ex-flags cmdline.txt /*ex-flags* ex: options.txt /*ex:* except-autocmd eval.txt /*except-autocmd* except-autocmd-Cmd eval.txt /*except-autocmd-Cmd* @@ -5048,7 +5069,6 @@ hebrew hebrew.txt /*hebrew* hebrew.txt hebrew.txt /*hebrew.txt* help various.txt /*help* help-context help.txt /*help-context* -help-tags tags 1 help-translated various.txt /*help-translated* help-xterm-window various.txt /*help-xterm-window* help.txt help.txt /*help.txt* @@ -5503,8 +5523,8 @@ messages message.txt /*messages* meta intro.txt /*meta* min() eval.txt /*min()* minimal-features os_msdos.txt /*minimal-features* -missing-commands vi_diff.txt /*missing-commands* missing-options vi_diff.txt /*missing-options* +mkdir() eval.txt /*mkdir()* mlang.txt mlang.txt /*mlang.txt* mode() eval.txt /*mode()* mode-Ex intro.txt /*mode-Ex* @@ -6132,6 +6152,7 @@ sign.txt sign.txt /*sign.txt* signs sign.txt /*signs* simple-change change.txt /*simple-change* simplify() eval.txt /*simplify()* +simulated-command vi_diff.txt /*simulated-command* single-repeat repeat.txt /*single-repeat* skeleton autocmd.txt /*skeleton* slow-fast-terminal term.txt /*slow-fast-terminal* @@ -6206,6 +6227,7 @@ swap-file recover.txt /*swap-file* swapfile-changed version4.txt /*swapfile-changed* syn-sync-grouphere syntax.txt /*syn-sync-grouphere* syn-sync-groupthere syntax.txt /*syn-sync-groupthere* +syn-sync-linecont syntax.txt /*syn-sync-linecont* synID() eval.txt /*synID()* synIDattr() eval.txt /*synIDattr()* synIDtrans() eval.txt /*synIDtrans()* diff --git a/runtime/doc/windows.txt b/runtime/doc/windows.txt --- a/runtime/doc/windows.txt +++ b/runtime/doc/windows.txt @@ -1,4 +1,4 @@ -*windows.txt* For Vim version 7.0aa. Last change: 2005 Jan 26 +*windows.txt* For Vim version 7.0aa. Last change: 2005 Feb 18 VIM REFERENCE MANUAL by Bram Moolenaar @@ -587,7 +587,7 @@ can also get to them with the buffer lis not split. Also see |++opt| and |+cmd|. *:sfir* *:sfirst* -:sfir[st [++opt] [+cmd] +:sfir[st] [++opt] [+cmd] Same as ":srewind". *:sla* *:slast* diff --git a/runtime/filetype.vim b/runtime/filetype.vim --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1,7 +1,7 @@ " Vim support file to detect file types " " Maintainer: Bram Moolenaar -" Last Change: 2005 Jan 27 +" Last Change: 2005 Feb 18 " Listen very carefully, I will say this only once if exists("did_load_filetypes") @@ -512,6 +512,9 @@ au BufNewFile,BufRead *.erl setf erlan " Elm Filter Rules file au BufNewFile,BufRead filter-rules setf elmfilt +" ESMTP rc file +au BufNewFile,BufRead *esmtprc setf esmtprc + " ESQL-C au BufNewFile,BufRead *.ec,*.EC setf esqlc diff --git a/runtime/ftplugin/vim.vim b/runtime/ftplugin/vim.vim --- a/runtime/ftplugin/vim.vim +++ b/runtime/ftplugin/vim.vim @@ -1,7 +1,7 @@ " Vim filetype plugin " Language: Vim " Maintainer: Bram Moolenaar -" Last Change: 2004 Sep 13 +" Last Change: 2005 Feb 14 " Only do this when not done yet for this buffer if exists("b:did_ftplugin") @@ -58,4 +58,6 @@ if exists("loaded_matchit") endif let &cpo = cpo_save -setlocal cpo+=M " makes \%( match \) + +" removed this, because 'cpoptions' is a global option. +" setlocal cpo+=M " makes \%( match \) diff --git a/src/ex_getln.c b/src/ex_getln.c --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -681,16 +681,29 @@ getcmdline(firstc, count, indent) if (c == '\n' || c == '\r' || c == K_KENTER || (c == ESC && (!KeyTyped || vim_strchr(p_cpo, CPO_ESC) != NULL))) { - gotesc = FALSE; /* Might have typed ESC previously, don't - truncate the cmdline now. */ - if (ccheck_abbr(c + ABBR_OFF)) - goto cmdline_changed; - if (!cmd_silent) + /* In Ex mode a backslash escapes a newline. */ + if (exmode_active + && c != ESC + && ccline.cmdpos > 0 + && ccline.cmdpos == ccline.cmdlen + && ccline.cmdbuff[ccline.cmdpos - 1] == '\\') + { + if (c == K_KENTER) + c = '\n'; + } + else { - windgoto(msg_row, 0); - out_flush(); + gotesc = FALSE; /* Might have typed ESC previously, don't + truncate the cmdline now. */ + if (ccheck_abbr(c + ABBR_OFF)) + goto cmdline_changed; + if (!cmd_silent) + { + windgoto(msg_row, 0); + out_flush(); + } + break; } - break; } /* @@ -1879,25 +1892,24 @@ getexline(c, dummy, indent) * Get an Ex command line for Ex mode. * In Ex mode we only use the OS supplied line editing features and no * mappings or abbreviations. + * Returns a string in allocated memory or NULL. */ /* ARGSUSED */ char_u * -getexmodeline(c, dummy, indent) - int c; /* normally ':', NUL for ":append" */ +getexmodeline(promptc, dummy, indent) + int promptc; /* normally ':', NUL for ":append" and '?' for + :s prompt */ void *dummy; /* cookie not used */ int indent; /* indent for inside conditionals */ { - garray_T line_ga; - int len; - int off = 0; - char_u *pend; - int finished = FALSE; -#if defined(FEAT_GUI) || defined(NO_COOKED_INPUT) - int startcol = 0; - int c1; - int escaped = FALSE; /* CTRL-V typed */ - int vcol = 0; -#endif + garray_T line_ga; + char_u *pend; + int startcol = 0; + int c1; + int escaped = FALSE; /* CTRL-V typed */ + int vcol = 0; + char_u *p; + int prev_char = 0; /* Switch cursor on now. This avoids that it happens after the "\n", which * confuses the system function that computes tabstops. */ @@ -1905,27 +1917,24 @@ getexmodeline(c, dummy, indent) /* always start in column 0; write a newline if necessary */ compute_cmdrow(); - if (msg_col) + if ((msg_col || msg_didout) && promptc != '?') msg_putchar('\n'); - if (c == ':') + if (promptc == ':') { /* indent that is only displayed, not in the line itself */ - msg_putchar(':'); + if (p_prompt) + msg_putchar(':'); while (indent-- > 0) msg_putchar(' '); -#if defined(FEAT_GUI) || defined(NO_COOKED_INPUT) startcol = msg_col; -#endif } ga_init2(&line_ga, 1, 30); /* autoindent for :insert and :append is in the line itself */ - if (c <= 0) + if (promptc <= 0) { -#if defined(FEAT_GUI) || defined(NO_COOKED_INPUT) vcol = indent; -#endif while (indent >= 8) { ga_append(&line_ga, TAB); @@ -1938,198 +1947,180 @@ getexmodeline(c, dummy, indent) msg_putchar(' '); } } + ++no_mapping; + ++allow_keys; /* * Get the line, one character at a time. */ got_int = FALSE; - while (!got_int && !finished) + while (!got_int) { if (ga_grow(&line_ga, 40) == FAIL) break; pend = (char_u *)line_ga.ga_data + line_ga.ga_len; - /* Get one character (inchar gets a third of maxlen characters!) */ - len = inchar(pend + off, 3, -1L, 0); - if (len < 0) - continue; /* end of input script reached */ - /* for a special character, we need at least three characters */ - if ((*pend == K_SPECIAL || *pend == CSI) && off + len < 3) - { - off += len; - continue; - } - len += off; - off = 0; + /* Get one character at a time. Don't use inchar(), it can't handle + * special characters. */ + c1 = vgetc(); /* - * When using the GUI, and for systems that don't have cooked input, - * handle line editing here. + * Handle line editing. + * Previously this was left to the system, putting the terminal in + * cooked mode, but then CTRL-D and CTRL-T can't be used properly. */ -#if defined(FEAT_GUI) || defined(NO_COOKED_INPUT) -# ifndef NO_COOKED_INPUT - if (gui.in_use) -# endif + if (got_int) + { + msg_putchar('\n'); + break; + } + + if (!escaped) { - if (got_int) + /* CR typed means "enter", which is NL */ + if (c1 == '\r') + c1 = '\n'; + + if (c1 == BS || c1 == K_BS + || c1 == DEL || c1 == K_DEL || c1 == K_KDEL) { - msg_putchar('\n'); - break; + if (line_ga.ga_len > 0) + { + --line_ga.ga_len; + goto redraw; + } + continue; } - while (len > 0) + if (c1 == Ctrl_U) { - c1 = *pend++; - --len; - if ((c1 == K_SPECIAL -# if !defined(NO_COOKED_INPUT) || defined(FEAT_GUI) - || c1 == CSI -# endif - ) && len >= 2) + msg_col = startcol; + msg_clr_eos(); + line_ga.ga_len = 0; + continue; + } + + if (c1 == Ctrl_T) + { + p = (char_u *)line_ga.ga_data; + p[line_ga.ga_len] = NUL; + indent = get_indent_str(p, 8); + indent += curbuf->b_p_sw - indent % curbuf->b_p_sw; +add_indent: + while (get_indent_str(p, 8) < indent) { - c1 = TO_SPECIAL(pend[0], pend[1]); - pend += 2; - len -= 2; + char_u *s = skipwhite(p); + + ga_grow(&line_ga, 1); + mch_memmove(s + 1, s, line_ga.ga_len - (s - p) + 1); + *s = ' '; + ++line_ga.ga_len; } - - if (!escaped) +redraw: + /* redraw the line */ + msg_col = startcol; + windgoto(msg_row, msg_col); + vcol = 0; + for (p = (char_u *)line_ga.ga_data; + p < (char_u *)line_ga.ga_data + line_ga.ga_len; ++p) { - /* CR typed means "enter", which is NL */ - if (c1 == '\r') - c1 = '\n'; - - if (c1 == BS || c1 == K_BS - || c1 == DEL || c1 == K_DEL || c1 == K_KDEL) + if (*p == TAB) { - if (line_ga.ga_len > 0) + do { - int i, v; - char_u *q; - - --line_ga.ga_len; - /* compute column that cursor should be in */ - v = 0; - q = ((char_u *)line_ga.ga_data); - for (i = 0; i < line_ga.ga_len; ++i) - { - if (*q == TAB) - v += 8 - v % 8; - else - v += ptr2cells(q); - ++q; - } - /* erase characters to position cursor */ - while (vcol > v) - { - msg_putchar('\b'); - msg_putchar(' '); - msg_putchar('\b'); - --vcol; - } - } - continue; + msg_putchar(' '); + } while (++vcol % 8); } - - if (c1 == Ctrl_U) - { - msg_col = startcol; - msg_clr_eos(); - line_ga.ga_len = 0; - continue; - } - - if (c1 == Ctrl_T) - c1 = TAB; /* very simplistic... */ - - if (c1 == Ctrl_D) + else { - char_u *p; - - /* Delete one shiftwidth. */ - p = (char_u *)line_ga.ga_data; - p[line_ga.ga_len] = NUL; - indent = get_indent_str(p, 8); - --indent; - indent -= indent % 8; - while (get_indent_str(p, 8) > indent) - { - char_u *s = skipwhite(p); - - mch_memmove(s - 1, s, line_ga.ga_len - (s - p) + 1); - --line_ga.ga_len; - } - msg_col = startcol; - for (vcol = 0; *p != NUL; ++p) - { - if (*p == TAB) - { - do - { - msg_putchar(' '); - } while (++vcol % 8); - } - else - { - msg_outtrans_len(p, 1); - vcol += char2cells(*p); - } - } - msg_clr_eos(); - continue; - } - - if (c1 == Ctrl_V) - { - escaped = TRUE; - continue; + msg_outtrans_len(p, 1); + vcol += char2cells(*p); } } - - if (IS_SPECIAL(c1)) - c1 = '?'; - ((char_u *)line_ga.ga_data)[line_ga.ga_len] = c1; - if (c1 == '\n') - msg_putchar('\n'); - else if (c1 == TAB) + msg_clr_eos(); + continue; + } + + if (c1 == Ctrl_D) + { + /* Delete one shiftwidth. */ + p = (char_u *)line_ga.ga_data; + if (prev_char == '0' || prev_char == '^') { - /* Don't use chartabsize(), 'ts' can be different */ - do - { - msg_putchar(' '); - } while (++vcol % 8); + if (prev_char == '^') + ex_keep_indent = TRUE; + indent = 0; + p[--line_ga.ga_len] = NUL; } else { - msg_outtrans_len( - ((char_u *)line_ga.ga_data) + line_ga.ga_len, 1); - vcol += char2cells(c1); + p[line_ga.ga_len] = NUL; + indent = get_indent_str(p, 8); + --indent; + indent -= indent % curbuf->b_p_sw; + } + while (get_indent_str(p, 8) > indent) + { + char_u *s = skipwhite(p); + + mch_memmove(s - 1, s, line_ga.ga_len - (s - p) + 1); + --line_ga.ga_len; } - ++line_ga.ga_len; - escaped = FALSE; + goto add_indent; + } + + if (c1 == Ctrl_V || c1 == Ctrl_Q) + { + escaped = TRUE; + continue; } - windgoto(msg_row, msg_col); + + /* Ignore special key codes: mouse movement, K_IGNORE, etc. */ + if (IS_SPECIAL(c1)) + continue; } -# ifndef NO_COOKED_INPUT + + if (IS_SPECIAL(c1)) + c1 = '?'; + ((char_u *)line_ga.ga_data)[line_ga.ga_len] = c1; + prev_char = c1; + if (c1 == '\n') + msg_putchar('\n'); + else if (c1 == TAB) + { + /* Don't use chartabsize(), 'ts' can be different */ + do + { + msg_putchar(' '); + } while (++vcol % 8); + } else -# endif -#endif -#ifndef NO_COOKED_INPUT { - line_ga.ga_len += len; + msg_outtrans_len( + ((char_u *)line_ga.ga_data) + line_ga.ga_len, 1); + vcol += char2cells(c1); } -#endif + ++line_ga.ga_len; + escaped = FALSE; + + windgoto(msg_row, msg_col); pend = (char_u *)(line_ga.ga_data) + line_ga.ga_len; - if (line_ga.ga_len && pend[-1] == '\n') + + /* we are done when a NL is entered, but not when it comes after a + * backslash */ + if (line_ga.ga_len > 0 && pend[-1] == '\n' + && (line_ga.ga_len <= 1 || pend[-2] != '\\')) { - finished = TRUE; --line_ga.ga_len; --pend; *pend = NUL; + break; } } - /* note that cursor has moved, because of the echoed */ - screen_down(); + --no_mapping; + --allow_keys; + /* make following messages go to the next line */ msg_didout = FALSE; msg_col = 0; @@ -3797,10 +3788,10 @@ addstar(fname, len, context) set_expand_context(xp) expand_T *xp; { - /* only expansion for ':' and '>' commands */ + /* only expansion for ':', '>' and '=' command-lines */ if (ccline.cmdfirstc != ':' #ifdef FEAT_EVAL - && ccline.cmdfirstc != '>' + && ccline.cmdfirstc != '>' && ccline.cmdfirstc != '=' #endif ) { @@ -3828,8 +3819,16 @@ set_cmd_context(xp, str, len, col) old_char = str[col]; str[col] = NUL; nextcomm = str; - while (nextcomm != NULL) - nextcomm = set_one_cmd_context(xp, nextcomm); + +#ifdef FEAT_EVAL + if (ccline.cmdfirstc == '=') + /* pass CMD_SIZE because there is no real command */ + set_context_for_expression(xp, str, CMD_SIZE); + else +#endif + while (nextcomm != NULL) + nextcomm = set_one_cmd_context(xp, nextcomm); + str[col] = old_char; } @@ -5477,7 +5476,7 @@ ex_window() * Call the main loop until or CTRL-C is typed. */ cmdwin_result = 0; - main_loop(TRUE); + main_loop(TRUE, FALSE); RedrawingDisabled = i; diff --git a/src/gui_mac.c b/src/gui_mac.c --- a/src/gui_mac.c +++ b/src/gui_mac.c @@ -91,6 +91,19 @@ static OSType _ftype = 'TEXT'; static EventHandlerUPP mouseWheelHandlerUPP = NULL; #endif +#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE) +# define USE_CARBONKEYHANDLER +static EventHandlerUPP keyEventHandlerUPP = NULL; +/* Defined in os_mac_conv.c */ +extern char_u *mac_utf16_to_enc __ARGS((UniChar *from, size_t fromLen, size_t *actualLen)); +extern UniChar *mac_enc_to_utf16 __ARGS((char_u *from, size_t fromLen, size_t *actualLen)); +extern CFStringRef mac_enc_to_cfstring __ARGS((char_u *from, size_t fromLen)); +#endif + +#ifdef MACOS_X +SInt32 gMacSystemVersion; +#endif + /* Debugging feature: start Vim window OFFSETed */ #undef USE_OFFSETED_WINDOW @@ -213,6 +226,12 @@ static struct } gFontPanelInfo = { 0, 0, 0, false }; #endif +#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE) +# define USE_ATSUI_DRAWING +ATSUStyle gFontStyle; +Boolean gIsFontFallbackSet; +#endif + /* * The Quickdraw global is predefined in CodeWarior * but is not in Apple MPW @@ -504,6 +523,63 @@ points_to_pixels(char_u *str, char_u **e return pixels; } +#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE) +/* + * Deletes all traces of any Windows-style mnemonic text (including any + * parentheses) from a menu item and returns the cleaned menu item title. + * The caller is responsible for releasing the returned string. + */ + static CFStringRef +menu_title_removing_mnemonic(menu) + vimmenu_T *menu; +{ + CFStringRef name; + size_t menuTitleLen; + CFIndex displayLen; + CFRange mnemonicStart; + CFRange mnemonicEnd; + CFMutableStringRef cleanedName; + + menuTitleLen = STRLEN(menu->dname); + name = mac_enc_to_cfstring(menu->dname, menuTitleLen); + + if (name) + { + /* Simple mnemonic-removal algorithm, assumes single parenthesized + * mnemonic character towards the end of the menu text */ + mnemonicStart = CFStringFind(name, CFSTR("("), kCFCompareBackwards); + displayLen = CFStringGetLength(name); + + if (mnemonicStart.location != kCFNotFound + && (mnemonicStart.location + 2) < displayLen + && CFStringGetCharacterAtIndex(name, + mnemonicStart.location + 1) == (UniChar)menu->mnemonic) + { + if (CFStringFindWithOptions(name, CFSTR(")"), + CFRangeMake(mnemonicStart.location + 1, + displayLen - mnemonicStart.location - 1), + kCFCompareBackwards, &mnemonicEnd) && + (mnemonicStart.location + 2) == mnemonicEnd.location) + { + cleanedName = CFStringCreateMutableCopy(NULL, 0, name); + if (cleanedName) + { + CFStringDelete(cleanedName, + CFRangeMake(mnemonicStart.location, + mnemonicEnd.location + 1 - + mnemonicStart.location)); + + CFRelease(name); + name = cleanedName; + } + } + } + } + + return name; +} +#endif + /* * Convert a list of FSSpec aliases into a list of fullpathname * character strings. @@ -1231,20 +1307,19 @@ HandleODocAE(const AppleEvent *theAEvent /* Select the text if possible */ if (gotPosition) { - VIsual_active = TRUE; - VIsual_select = FALSE; - if (thePosition.lineNum < 0) + VIsual_active = TRUE; + VIsual_select = FALSE; + VIsual = curwin->w_cursor; + if (thePosition.lineNum < 0) { - VIsual_mode = 'v'; - VIsual = curwin->w_cursor; - goto_byte(thePosition.endRange); - } - else + VIsual_mode = 'v'; + goto_byte(thePosition.endRange); + } + else { - VIsual_mode = 'V'; - VIsual = curwin->w_cursor; - VIsual.col = 0; - } + VIsual_mode = 'V'; + VIsual.col = 0; + } } #endif setcursor(); @@ -1541,25 +1616,47 @@ InstallFontPanelHandler() * Fill the buffer pointed to by outName with the name and size * of the font currently selected in the Font Panel. */ +#define FONT_STYLE_BUFFER_SIZE 32 static void GetFontPanelSelection(char_u* outName) { - Str255 buf; - Boolean isBold = false, isItalic = false; + Str255 buf; + ByteCount fontNameLen = 0; + ATSUFontID fid; + char_u styleString[FONT_STYLE_BUFFER_SIZE]; if (!outName) return; - (void)FMGetFontFamilyName(gFontPanelInfo.family, buf); - p2cstrcpy(outName, buf); - -#if 0 /* TODO: enable when styles are supported in gui_mac_find_font() */ - isBold = (gFontPanelInfo.style & bold); - isItalic = (gFontPanelInfo.style & italic); -#endif - - sprintf(&outName[buf[0]], ":h%d%s%s", gFontPanelInfo.size, - (isBold ? ":b" : ""), (isItalic ? ":i" : "")); + if (FMGetFontFamilyName(gFontPanelInfo.family, buf) == noErr) + { + /* Canonicalize localized font names */ + if (FMGetFontFromFontFamilyInstance(gFontPanelInfo.family, + gFontPanelInfo.style, &fid, NULL) != noErr) + return; + + /* Request font name with Mac encoding (otherwise we could + * get an unwanted utf-16 name) */ + if (ATSUFindFontName(fid, kFontFullName, kFontMacintoshPlatform, + kFontNoScriptCode, kFontNoLanguageCode, + 255, outName, &fontNameLen, NULL) != noErr) + return; + + /* Only encode font size, because style (bold, italic, etc) is + * already part of the font full name */ + snprintf(styleString, FONT_STYLE_BUFFER_SIZE, ":h%d", + gFontPanelInfo.size/*, + ((gFontPanelInfo.style & bold)!=0 ? ":b" : ""), + ((gFontPanelInfo.style & italic)!=0 ? ":i" : ""), + ((gFontPanelInfo.style & underline)!=0 ? ":u" : "")*/); + + if ((fontNameLen + STRLEN(styleString)) < 255) + STRCPY(outName + fontNameLen, styleString); + } + else + { + *outName = NULL; + } } #endif @@ -2213,7 +2310,187 @@ gui_mac_doSuspendEvent(event) /* * Handle the key */ - +#ifdef USE_CARBONKEYHANDLER +# define INLINE_KEY_BUFFER_SIZE 80 + static pascal OSStatus +gui_mac_doKeyEventCarbon(EventHandlerCallRef nextHandler, EventRef theEvent, + void *data) +{ + /* Multibyte-friendly key event handler */ + OSStatus e = -1; + UInt32 actualSize; + UniChar *text; + char_u result[INLINE_KEY_BUFFER_SIZE]; + short len = 0; + UInt32 key_sym; + char charcode; + int key_char; + UInt32 modifiers; + size_t encLen; + char_u *to = NULL; + Boolean isSpecial = FALSE; + int i; + + /* Mask the mouse (as per user setting) */ + if (p_mh) + ObscureCursor(); + + do + { + if (noErr != GetEventParameter(theEvent, kEventParamTextInputSendText, + typeUnicodeText, NULL, 0, &actualSize, NULL)) + break; + + text = (UniChar *)alloc(actualSize); + + if (text) + { + do + { + if (noErr != GetEventParameter(theEvent, + kEventParamTextInputSendText, + typeUnicodeText, NULL, actualSize, NULL, text)) + break; + EventRef keyEvent; + if (noErr != GetEventParameter(theEvent, + kEventParamTextInputSendKeyboardEvent, + typeEventRef, NULL, sizeof(EventRef), NULL, &keyEvent)) + break; + if (noErr != GetEventParameter(keyEvent, + kEventParamKeyModifiers, + typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers)) + break; + if (noErr != GetEventParameter(keyEvent, + kEventParamKeyCode, + typeUInt32, NULL, sizeof(UInt32), NULL, &key_sym)) + break; + if (noErr != GetEventParameter(keyEvent, + kEventParamKeyMacCharCodes, + typeChar, NULL, sizeof(char), NULL, &charcode)) + break; + + key_char = charcode; + + if (modifiers & controlKey) + { + if ((modifiers & ~(controlKey|shiftKey)) == 0 + && (key_char == '2' || key_char == '6')) + { + /* CTRL-^ and CTRL-@ don't work in the normal way. */ + if (key_char == '2') + key_char = Ctrl_AT; + else + key_char = Ctrl_HAT; + + text[0] = (UniChar)key_char; + modifiers = 0; + } + } + + if (modifiers & cmdKey) +#ifndef USE_CMD_KEY + break; /* Let system handle Cmd+... */ +#else + { + /* Intercept CMD-. */ + if (key_char == '.') + got_int = TRUE; + + /* Convert the modifiers */ + modifiers = EventModifiers2VimModifiers(modifiers); + + /* Following code to simplify and consolidate modifiers + * taken liberally from gui_w48.c */ + + key_char = simplify_key(key_char, (int *)&modifiers); + + /* remove SHIFT for keys that are already shifted, e.g., + * '(' and '*' */ + if (key_char < 0x100 && + !isalpha(key_char) && isprint(key_char)) + modifiers &= ~MOD_MASK_SHIFT; + + /* Interpret META, include SHIFT, etc. */ + key_char = extract_modifiers(key_char, (int *)&modifiers); + if (key_char == CSI) + key_char = K_CSI; + + if (modifiers) + { + result[len++] = CSI; + result[len++] = KS_MODIFIER; + result[len++] = modifiers; + } + + isSpecial = TRUE; + } +#endif + else + { + /* Find the special key (eg., for cursor keys) */ + if (!(actualSize > sizeof(UniChar)) && + ((text[0] < 0x20) || (text[0] == 0x7f))) + { + for (i = 0; special_keys[i].key_sym != (KeySym)0; ++i) + if (special_keys[i].key_sym == key_sym) + { + key_char = TO_SPECIAL(special_keys[i].vim_code0, + special_keys[i].vim_code1); + key_char = simplify_key(key_char, + (int *)&modifiers); + isSpecial = TRUE; + break; + } + } + } + + if (isSpecial && IS_SPECIAL(key_char)) + { + result[len++] = CSI; + result[len++] = K_SECOND(key_char); + result[len++] = K_THIRD(key_char); + } + else + { + encLen = actualSize; + to = mac_utf16_to_enc(text, actualSize, &encLen); + } + + if (to) + { + /* This is basically add_to_input_buf_csi() */ + for (i = 0; i < encLen && len < (INLINE_KEY_BUFFER_SIZE-1); ++i) + { + result[len++] = to[i]; + if (to[i] == CSI) + { + result[len++] = KS_EXTRA; + result[len++] = (int)KE_CSI; + } + } + vim_free(to); + } + + add_to_input_buf(result, len); + e = noErr; + } + while (0); + + vim_free(text); + if (e == noErr) + { + /* Fake event to wake up WNE (required to get + * key repeat working */ + PostEvent(keyUp, 0); + return noErr; + } + } + } + while (0); + + return CallNextEventHandler(nextHandler, theEvent); +} +#else void gui_mac_doKeyEvent(EventRecord *theEvent) { @@ -2387,6 +2664,7 @@ gui_mac_doKeyEvent(EventRecord *theEvent add_to_input_buf(string, len); } +#endif /* * Handle MouseClick @@ -2664,11 +2942,12 @@ gui_mac_handle_event(event) /* Handle normal event */ switch (event->what) { +#ifndef USE_CARBONKEYHANDLER case (keyDown): case (autoKey): gui_mac_doKeyEvent(event); break; - +#endif case (keyUp): /* We don't care about when the key get release */ break; @@ -2747,7 +3026,27 @@ gui_mac_find_font(font_name) pFontName[0] = STRLEN(font_name); *p = c; + /* Get the font name, minus the style suffix (:h, etc) */ +#if defined(MACOS_X) && defined(USE_CARBONIZED) + char_u fontName[256]; + char_u *styleStart = vim_strchr(font_name, ':'); + size_t fontNameLen = styleStart ? styleStart - font_name : STRLEN(fontName); + vim_strncpy(fontName, font_name, fontNameLen); + + ATSUFontID fontRef; + FMFontStyle fontStyle; + font_id = 0; + + if (ATSUFindFontFromName(&pFontName[1], pFontName[0], kFontFullName, + kFontMacintoshPlatform, kFontNoScriptCode, kFontNoLanguageCode, + &fontRef) == noErr) + { + if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr) + font_id = 0; + } +#else GetFNum(pFontName, &font_id); +#endif if (font_id == 0) { @@ -2767,7 +3066,17 @@ gui_mac_find_font(font_name) } } if (changed) +#if defined(MACOS_X) && defined(USE_CARBONIZED) + if (ATSUFindFontFromName(&pFontName[1], pFontName[0], + kFontFullName, kFontNoPlatformCode, kFontNoScriptCode, + kFontNoLanguageCode, &fontRef) == noErr) + { + if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr) + font_id = 0; + } +#else GetFNum(pFontName, &font_id); +#endif } #else @@ -2782,7 +3091,12 @@ gui_mac_find_font(font_name) { /* Oups, the system font was it the one the user want */ +#if defined(MACOS_X) && defined(USE_CARBONIZED) + if (FMGetFontFamilyName(systemFont, systemFontname) != noErr) + return NOFONT; +#else GetFontName(0, systemFontname); +#endif if (!EqualString(pFontName, systemFontname, false, false)) return NOFONT; } @@ -3079,6 +3393,15 @@ gui_mch_init() EventTypeSpec eventTypeSpec; EventHandlerRef mouseWheelHandlerRef; #endif +#ifdef USE_CARBONKEYHANDLER + EventHandlerRef keyEventHandlerRef; +#endif + +#ifdef MACOS_X + if (Gestalt(gestaltSystemVersion, &gMacSystemVersion) != noErr) + gMacSystemVersion = 0x1000; /* Default to minimum sensible value */ +#endif + #if 1 InitCursor(); @@ -3238,9 +3561,24 @@ gui_mch_init() } #endif +#ifdef USE_CARBONKEYHANDLER + eventTypeSpec.eventClass = kEventClassTextInput; + eventTypeSpec.eventKind = kEventUnicodeForKeyEvent; + keyEventHandlerUPP = NewEventHandlerUPP(gui_mac_doKeyEventCarbon); + if (noErr != InstallApplicationEventHandler(keyEventHandlerUPP, 1, + &eventTypeSpec, NULL, &keyEventHandlerRef)) + { + keyEventHandlerRef = NULL; + DisposeEventHandlerUPP(keyEventHandlerUPP); + keyEventHandlerUPP = NULL; + } +#endif + +/* #ifdef FEAT_MBYTE - set_option_value((char_u *)"termencoding", 0L, (char_u *)"macroman", 0); -#endif + set_option_value((char_u *)"encoding", 0L, (char_u *)"utf-8", 0); +#endif +*/ /* TODO: Load bitmap if using TOOLBAR */ return OK; @@ -3290,11 +3628,21 @@ gui_mch_exit(int rc) /* TODO: find out all what is missing here? */ DisposeRgn(cursorRgn); +#ifdef USE_CARBONKEYHANDLER + if (keyEventHandlerUPP) + DisposeEventHandlerUPP(keyEventHandlerUPP); +#endif + #ifdef USE_MOUSEWHEEL if (mouseWheelHandlerUPP != NULL) DisposeEventHandlerUPP(mouseWheelHandlerUPP); #endif +#ifdef USE_ATSUI_DRAWING + if (gFontStyle) + ATSUDisposeStyle(gFontStyle); +#endif + /* Exit to shell? */ exit(rc); } @@ -3466,6 +3814,14 @@ gui_mch_init_font(font_name, fontset) GuiFont font; char_u used_font_name[512]; +#ifdef USE_ATSUI_DRAWING + if (gFontStyle == NULL) + { + if (ATSUCreateStyle(&gFontStyle) != noErr) + gFontStyle = NULL; + } +#endif + if (font_name == NULL) { /* First try to get the suggested font */ @@ -3523,6 +3879,54 @@ gui_mch_init_font(font_name, fontset) TextSize(font >> 16); TextFont(font & 0xFFFF); +#ifdef USE_ATSUI_DRAWING + ATSUFontID fontID; + Fixed fontSize; + ATSStyleRenderingOptions fontOptions; + + if (gFontStyle) + { + fontID = font & 0xFFFF; + fontSize = Long2Fix(font >> 16); + + /* No antialiasing by default (do not attempt to touch antialising + * options on pre-Jaguar) */ + fontOptions = +#ifdef MACOS_X + (gMacSystemVersion >= 0x1020) ? + kATSStyleNoAntiAliasing : +#endif + kATSStyleNoOptions; + + ATSUAttributeTag attribTags[] = + { + kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag, + kATSUMaxATSUITagValue+1 + }; + ByteCount attribSizes[] = + { + sizeof(ATSUFontID), sizeof(Fixed), + sizeof(ATSStyleRenderingOptions), sizeof font + }; + ATSUAttributeValuePtr attribValues[] = + { + &fontID, &fontSize, &fontOptions, &font + }; + + /* Convert font id to ATSUFontID */ + if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr) + { + if (ATSUSetAttributes(gFontStyle, + (sizeof attribTags)/sizeof(ATSUAttributeTag), + attribTags, attribSizes, attribValues) != noErr) + { + ATSUDisposeStyle(gFontStyle); + gFontStyle = NULL; + } + } + } +#endif + GetFontInfo(&font_info); gui.char_ascent = font_info.ascent; @@ -3592,9 +3996,99 @@ gui_mch_get_fontname(font, name) gui_mch_set_font(font) GuiFont font; { - /* - * TODO: maybe avoid set again the current font. - */ +#ifdef USE_ATSUI_DRAWING + GuiFont currFont; + ByteCount actualFontByteCount; + ATSUFontID fontID; + Fixed fontSize; + ATSStyleRenderingOptions fontOptions; + + if (gFontStyle) + { + /* Avoid setting same font again */ + if (ATSUGetAttribute(gFontStyle, kATSUMaxATSUITagValue+1, sizeof font, + &currFont, &actualFontByteCount) == noErr && + actualFontByteCount == (sizeof font)) + { + if (currFont == font) + return; + } + + fontID = font & 0xFFFF; + fontSize = Long2Fix(font >> 16); + /* Respect p_antialias setting only for wide font. + * The reason for doing this at the moment is a bit complicated, + * but it's mainly because a) latin (non-wide) aliased fonts + * look bad in OS X 10.3.x and below (due to a bug in ATS), and + * b) wide multibyte input does not suffer from that problem. */ + fontOptions = +#ifdef MACOS_X + (p_antialias && (font == gui.wide_font)) ? + kATSStyleNoOptions : kATSStyleNoAntiAliasing; +#else + kATSStyleNoOptions; +#endif + + ATSUAttributeTag attribTags[] = + { + kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag, + kATSUMaxATSUITagValue+1 + }; + ByteCount attribSizes[] = + { + sizeof(ATSUFontID), sizeof(Fixed), + sizeof(ATSStyleRenderingOptions), sizeof font + }; + ATSUAttributeValuePtr attribValues[] = + { + &fontID, &fontSize, &fontOptions, &font + }; + + if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr) + { + if (ATSUSetAttributes(gFontStyle, + (sizeof attribTags)/sizeof(ATSUAttributeTag), + attribTags, attribSizes, attribValues) != noErr) + { +#ifndef NDEBUG + fprintf(stderr, "couldn't set font style\n"); +#endif + ATSUDisposeStyle(gFontStyle); + gFontStyle = NULL; + } + } + + } + + if (!gIsFontFallbackSet) + { + /* Setup automatic font substitution. The user's guifontwide + * is tried first, then the system tries other fonts. */ +/* + ATSUAttributeTag fallbackTags[] = { kATSULineFontFallbacksTag }; + ByteCount fallbackSizes[] = { sizeof(ATSUFontFallbacks) }; + ATSUCreateFontFallbacks(&gFontFallbacks); + ATSUSetObjFontFallbacks(gFontFallbacks, ); +*/ + if (gui.wide_font) + { + ATSUFontID fallbackFonts; + gIsFontFallbackSet = TRUE; + + if (FMGetFontFromFontFamilyInstance( + (gui.wide_font & 0xFFFF), + 0, + &fallbackFonts, + NULL) == noErr) + { + ATSUSetFontFallbacks((sizeof fallbackFonts)/sizeof(ATSUFontID), &fallbackFonts, kATSUSequentialFallbacksPreferred); + } +/* + ATSUAttributeValuePtr fallbackValues[] = { }; +*/ + } + } +#endif TextSize(font >> 16); TextFont(font & 0xFFFF); } @@ -3820,9 +4314,17 @@ gui_mch_draw_string(row, col, s, len, fl int flags; { #if defined(FEAT_GUI) && defined(MACOS_X) +#ifndef USE_ATSUI_DRAWING SInt32 sys_version; #endif +#endif #ifdef FEAT_MBYTE +#ifdef USE_ATSUI_DRAWING + /* ATSUI requires utf-16 strings */ + UniCharCount utf16_len; + UniChar *tofree = mac_enc_to_utf16(s, len, (size_t *)&utf16_len); + utf16_len /= sizeof(UniChar); +#else char_u *tofree = NULL; if (output_conv.vc_type != CONV_NONE) @@ -3832,8 +4334,11 @@ gui_mch_draw_string(row, col, s, len, fl s = tofree; } #endif +#endif #if defined(FEAT_GUI) && defined(MACOS_X) + /* ATSUI automatically antialiases text */ +#ifndef USE_ATSUI_DRAWING /* * On OS X, try using Quartz-style text antialiasing. */ @@ -3845,8 +4350,9 @@ gui_mch_draw_string(row, col, s, len, fl /* Quartz antialiasing is available only in OS 10.2 and later. */ UInt32 qd_flags = (p_antialias ? kQDUseCGTextRendering | kQDUseCGTextMetrics : 0); - (void)SwapQDTextFlags(qd_flags); + QDSwapTextFlags(qd_flags); } +#endif /* * When antialiasing we're using srcOr mode, we have to clear the block @@ -3857,18 +4363,37 @@ gui_mch_draw_string(row, col, s, len, fl * The following is like calling gui_mch_clear_block(row, col, row, col + * len - 1), but without setting the bg color to gui.back_pixel. */ +#ifdef USE_ATSUI_DRAWING + if ((flags & DRAW_TRANSP) == 0) +#else if (((sys_version >= 0x1020 && p_antialias) || p_linespace != 0) && !(flags & DRAW_TRANSP)) +#endif { Rect rc; rc.left = FILL_X(col); rc.top = FILL_Y(row); +#ifdef FEAT_MBYTE + /* Multibyte computation taken from gui_w32.c */ + if (has_mbyte) + { + int cell_len = 0; + int n; + + /* Compute the length in display cells. */ + for (n = 0; n < len; n += MB_BYTE2LEN(s[n])) + cell_len += (*mb_ptr2cells)(s + n); + rc.right = FILL_X(col + cell_len); + } + else +#endif rc.right = FILL_X(col + len) + (col + len == Columns); rc.bottom = FILL_Y(row + 1); EraseRect(&rc); } +#ifndef USE_ATSUI_DRAWING if (sys_version >= 0x1020 && p_antialias) { StyleParameter face; @@ -3888,6 +4413,7 @@ gui_mch_draw_string(row, col, s, len, fl } else #endif +#endif { /* Use old-style, non-antialiased QuickDraw text rendering. */ TextMode(srcCopy); @@ -3901,6 +4427,25 @@ gui_mch_draw_string(row, col, s, len, fl } MoveTo(TEXT_X(col), TEXT_Y(row)); +#ifdef USE_ATSUI_DRAWING + ATSUTextLayout textLayout; + + if (ATSUCreateTextLayoutWithTextPtr(tofree, + kATSUFromTextBeginning, kATSUToTextEnd, + utf16_len, + (gFontStyle ? 1 : 0), &utf16_len, + (gFontStyle ? &gFontStyle : NULL), + &textLayout) == noErr) + { + ATSUSetTransientFontMatching(textLayout, TRUE); + + ATSUDrawText(textLayout, + kATSUFromTextBeginning, kATSUToTextEnd, + kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc); + + ATSUDisposeTextLayout(textLayout); + } +#else DrawText((char *)s, 0, len); @@ -3916,6 +4461,7 @@ gui_mch_draw_string(row, col, s, len, fl MoveTo(FILL_X(col), FILL_Y(row + 1) - 1); LineTo(FILL_X(col + len) - 1, FILL_Y(row + 1) - 1); } +#endif } #ifdef FEAT_MBYTE @@ -4021,14 +4567,16 @@ gui_mch_draw_hollow_cursor(color) { Rect rc; - gui_mch_set_fg_color(color); - /* * Note: FrameRect() excludes right and bottom of rectangle. */ rc.left = FILL_X(gui.col); rc.top = FILL_Y(gui.row); rc.right = rc.left + gui.char_width; +#ifdef FEAT_MBYTE + if (mb_lefthalve(gui.row, gui.col)) + rc.right += gui.char_width; +#endif rc.bottom = rc.top + gui.char_height; gui_mch_set_fg_color(color); @@ -4060,7 +4608,8 @@ gui_mch_draw_part_cursor(w, h, color) gui_mch_set_fg_color(color); - PaintRect(&rc); + FrameRect(&rc); +// PaintRect(&rc); } @@ -4346,11 +4895,11 @@ clip_mch_request_selection(cbd) if (flavor == 0) { - error = GetScrapFlavorFlags(scrap, kScrapFlavorTypeText, &scrapFlags); + error = GetScrapFlavorFlags(scrap, kScrapFlavorTypeUnicode, &scrapFlags); if (error != noErr) return; - error = GetScrapFlavorSize(scrap, kScrapFlavorTypeText, &scrapSize); + error = GetScrapFlavorSize(scrap, kScrapFlavorTypeUnicode, &scrapSize); if (error != noErr) return; } @@ -4374,7 +4923,7 @@ clip_mch_request_selection(cbd) HLock(textOfClip); #ifdef USE_CARBONIZED error = GetScrapFlavorData(scrap, - flavor ? VIMSCRAPFLAVOR : kScrapFlavorTypeText, + flavor ? VIMSCRAPFLAVOR : kScrapFlavorTypeUnicode, &scrapSize, *textOfClip); #else scrapSize = GetScrap(textOfClip, 'TEXT', &scrapOffset); @@ -4387,7 +4936,11 @@ clip_mch_request_selection(cbd) type = (strchr(*textOfClip, '\r') != NULL) ? MLINE : MCHAR; tempclip = lalloc(scrapSize + 1, TRUE); +#if defined(FEAT_MBYTE) && defined(USE_CARBONIZED) + mch_memmove(tempclip, *textOfClip + flavor, scrapSize); +#else STRNCPY(tempclip, *textOfClip + flavor, scrapSize); +#endif tempclip[scrapSize] = 0; searchCR = (char *)tempclip; @@ -4400,19 +4953,15 @@ clip_mch_request_selection(cbd) } -#ifdef FEAT_MBYTE - if (input_conv.vc_type != CONV_NONE) +#if defined(FEAT_MBYTE) && defined(USE_CARBONIZED) + /* Convert from utf-16 (clipboard) */ + size_t encLen = 0; + char_u *to = mac_utf16_to_enc((UniChar *)tempclip, scrapSize, &encLen); + if (to) { - char_u *to; - int l = scrapSize; - - to = string_convert(&input_conv, tempclip, &l); - if (to != NULL) - { - vim_free(tempclip); - tempclip = to; - scrapSize = l; - } + scrapSize = encLen; + vim_free(tempclip); + tempclip = to; } #endif clip_yank_selection(type, tempclip, scrapSize, cbd); @@ -4471,19 +5020,14 @@ clip_mch_set_selection(cbd) type = clip_convert_selection(&str, (long_u *) &scrapSize, cbd); -#ifdef FEAT_MBYTE - if (str != NULL && output_conv.vc_type != CONV_NONE) +#if defined(FEAT_MBYTE) && defined(USE_CARBONIZED) + size_t utf16_len = 0; + UniChar *to = mac_enc_to_utf16(str, scrapSize, &utf16_len); + if (to) { - char_u *to; - int l = scrapSize; - - to = string_convert(&output_conv, str, &l); - if (to != NULL) - { - vim_free(str); - str = to; - scrapSize = l; - } + scrapSize = utf16_len; + vim_free(str); + str = (char_u *)to; } #endif @@ -4504,9 +5048,9 @@ clip_mch_set_selection(cbd) #ifdef USE_CARBONIZED **textOfClip = type; - STRNCPY(*textOfClip + 1, str, scrapSize); + mch_memmove(*textOfClip + 1, str, scrapSize); GetCurrentScrap(&scrap); - PutScrapFlavor(scrap, kScrapFlavorTypeText, kScrapFlavorMaskNone, + PutScrapFlavor(scrap, kScrapFlavorTypeUnicode, kScrapFlavorMaskNone, scrapSize, *textOfClip + 1); PutScrapFlavor(scrap, VIMSCRAPFLAVOR, kScrapFlavorMaskNone, scrapSize + 1, *textOfClip); @@ -4599,7 +5143,11 @@ gui_mch_add_menu(menu, idx) */ static long next_avail_id = 128; long menu_after_me = 0; /* Default to the end */ +#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE) + CFStringRef name; +#else char_u *name; +#endif short index; vimmenu_T *parent = menu->parent; vimmenu_T *brother = menu->next; @@ -4625,13 +5173,21 @@ gui_mch_add_menu(menu, idx) menu_after_me = hierMenu; /* Convert the name */ +#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE) + name = menu_title_removing_mnemonic(menu); +#else name = C2Pascal_save(menu->dname); +#endif if (name == NULL) return; /* Create the menu unless it's the help menu */ #ifdef USE_HELPMENU +#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE) + if (menu->priority == 9999) +#else if (STRNCMP(name, "\4Help", 5) == 0) +#endif { menu->submenu_id = kHMHelpMenuID; menu->submenu_handle = gui.MacOSHelpMenu; @@ -4644,7 +5200,12 @@ gui_mch_add_menu(menu, idx) * OSStatus SetMenuTitle(MenuRef, ConstStr255Param title); */ menu->submenu_id = next_avail_id; +#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE) + if (CreateNewMenu(menu->submenu_id, 0, (MenuRef *)&menu->submenu_handle) == noErr) + SetMenuTitleWithCFString((MenuRef)menu->submenu_handle, name); +#else menu->submenu_handle = NewMenu(menu->submenu_id, name); +#endif next_avail_id++; } @@ -4676,13 +5237,21 @@ gui_mch_add_menu(menu, idx) * to avoid special character recognition by InsertMenuItem */ InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */ +#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE) + SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name); +#else SetMenuItemText(parent->submenu_handle, idx+1, name); +#endif SetItemCmd(parent->submenu_handle, idx+1, 0x1B); SetItemMark(parent->submenu_handle, idx+1, menu->submenu_id); InsertMenu(menu->submenu_handle, hierMenu); } +#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE) + CFRelease(name); +#else vim_free(name); +#endif #if 0 /* Done by Vim later on */ @@ -4698,7 +5267,11 @@ gui_mch_add_menu_item(menu, idx) vimmenu_T *menu; int idx; { +#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE) + CFStringRef name; +#else char_u *name; +#endif vimmenu_T *parent = menu->parent; int menu_inserted; @@ -4710,7 +5283,11 @@ gui_mch_add_menu_item(menu, idx) for older OS call GetMenuItemData (menu, item, isCommandID?, data) */ /* Convert the name */ +#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE) + name = menu_title_removing_mnemonic(menu); +#else name = C2Pascal_save(menu->dname); +#endif /* Where are just a menu item, so no handle, no id */ menu->submenu_id = 0; @@ -4796,15 +5373,23 @@ gui_mch_add_menu_item(menu, idx) if (!menu_inserted) InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */ /* Set the menu item name. */ +#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE) + SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name); +#else SetMenuItemText(parent->submenu_handle, idx+1, name); +#endif #if 0 /* Called by Vim */ DrawMenuBar(); #endif +#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE) + CFRelease(name); +#else /* TODO: Can name be freed? */ vim_free(name); +#endif } void @@ -5811,17 +6396,33 @@ gui_mch_settitle(title, icon) /* TODO: Get vim to make sure maxlen (from p_titlelen) is smaller * that 256. Even better get it to fit nicely in the titlebar. */ +#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE) + CFStringRef windowTitle; + size_t windowTitleLen; +#else char_u *pascalTitle; +#endif if (title == NULL) /* nothing to do */ return; +#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE) + windowTitleLen = STRLEN(title); + windowTitle = mac_enc_to_cfstring(title, windowTitleLen); + + if (windowTitle) + { + SetWindowTitleWithCFString(gui.VimWindow, windowTitle); + CFRelease(windowTitle); + } +#else pascalTitle = C2Pascal_save(title); if (pascalTitle != NULL) { SetWTitle(gui.VimWindow, pascalTitle); vim_free(pascalTitle); } +#endif } #endif diff --git a/src/ops.c b/src/ops.c --- a/src/ops.c +++ b/src/ops.c @@ -1105,10 +1105,20 @@ do_execreg(regname, colon, addcr) int remap; if (regname == '@') /* repeat previous one */ + { + if (lastc == NUL) + { + EMSG(_("E748: No previously used register")); + return FAIL; + } regname = lastc; + } /* check for valid regname */ if (regname == '%' || regname == '#' || !valid_yank_reg(regname, FALSE)) + { + emsg_invreg(regname); return FAIL; + } lastc = regname; #ifdef FEAT_CLIPBOARD @@ -3597,7 +3607,13 @@ error: else curbuf->b_op_end.col = 0; - if (flags & PUT_CURSEND) + if (flags & PUT_CURSLINE) + { + /* ":put": put cursor on last inserte line */ + curwin->w_cursor.lnum = lnum; + beginline(BL_WHITE | BL_FIX); + } + else if (flags & PUT_CURSEND) { /* put cursor after inserted text */ if (y_type == MLINE) @@ -3616,7 +3632,7 @@ error: } else if (y_type == MLINE) { - /* put cursor onfirst non-blank in first inserted line */ + /* put cursor on first non-blank in first inserted line */ curwin->w_cursor.col = 0; if (dir == FORWARD) ++curwin->w_cursor.lnum; @@ -5676,7 +5692,7 @@ write_reg_contents_ex(name, str, maxlen, if (!valid_yank_reg(name, TRUE)) /* check for valid reg name */ { - EMSG2(_("E354: Invalid register name: '%s'"), transchar(name)); + emsg_invreg(name); return; } diff --git a/src/option.c b/src/option.c --- a/src/option.c +++ b/src/option.c @@ -1723,8 +1723,8 @@ static struct vimoption #endif }, {"prompt", NULL, P_BOOL|P_VI_DEF, - (char_u *)NULL, PV_NONE, - {(char_u *)FALSE, (char_u *)0L}}, + (char_u *)&p_prompt, PV_NONE, + {(char_u *)TRUE, (char_u *)0L}}, {"quoteescape", "qe", P_STRING|P_ALLOCED|P_VI_DEF, #ifdef FEAT_TEXTOBJ (char_u *)&p_qe, PV_QE, @@ -1922,6 +1922,9 @@ static struct vimoption (char_u *)NULL, PV_NONE, #endif {(char_u *)FALSE, (char_u *)0L}}, + {"shelltemp", "stmp", P_BOOL, + (char_u *)&p_stmp, PV_NONE, + {(char_u *)FALSE, (char_u *)TRUE}}, {"shelltype", "st", P_NUM|P_VI_DEF, #ifdef AMIGA (char_u *)&p_st, PV_NONE, @@ -2501,7 +2504,7 @@ static char *(p_bsdir_values[]) = {"curr static char *(p_scbopt_values[]) = {"ver", "hor", "jump", NULL}; #endif static char *(p_swb_values[]) = {"useopen", "split", NULL}; -static char *(p_debug_values[]) = {"msg", NULL}; +static char *(p_debug_values[]) = {"msg", "beep", NULL}; #ifdef FEAT_VERTSPLIT static char *(p_ead_values[]) = {"both", "ver", "hor", NULL}; #endif @@ -2593,7 +2596,10 @@ set_init_1() /* Use POSIX compatibility when $VIM_POSIX is set. */ if (mch_getenv((char_u *)"VIM_POSIX") != NULL) + { set_string_default("cpo", (char_u *)CPO_ALL); + set_string_default("shm", (char_u *)"A"); + } /* * Find default value for 'shell' option. @@ -2885,6 +2891,23 @@ set_init_1() vim_setenv("LANG", buf); } } +# else +# ifdef MACOS + if (mch_getenv((char_u *)"LANG") == NULL) + { + char buf[20]; + if (LocaleRefGetPartString(NULL, + kLocaleLanguageMask | kLocaleLanguageVariantMask | + kLocaleRegionMask | kLocaleRegionVariantMask, + sizeof buf, buf) == noErr && *buf) + { + vim_setenv("LANG", buf); +# ifdef HAVE_LOCALE_H + setlocale(LC_ALL, ""); +# endif + } + } +# endif # endif /* enc_locale() will try to find the encoding of the current locale. */ @@ -3093,6 +3116,9 @@ set_init_2() * wrong when the window height changes. */ set_number_default("scroll", (long_u)Rows >> 1); + idx = findoption((char_u *)"scroll"); + if (!(options[idx].flags & P_WAS_SET)) + set_option_default(idx, OPT_LOCAL, p_cp); comp_col(); /* @@ -3423,7 +3449,8 @@ do_set(arg, opt_flags) if (*arg == NUL) { showoptions(0, opt_flags); - return OK; + did_show = TRUE; + goto theend; } while (*arg != NUL) /* loop to process all options */ @@ -3446,12 +3473,16 @@ do_set(arg, opt_flags) set_options_default(OPT_FREE | opt_flags); } else + { showoptions(1, opt_flags); + did_show = TRUE; + } } else if (STRNCMP(arg, "termcap", 7) == 0 && !(opt_flags & OPT_MODELINE)) { showoptions(2, opt_flags); show_termcodes(); + did_show = TRUE; arg += 7; } else @@ -4187,6 +4218,19 @@ skip: arg = skipwhite(arg); } +theend: + if (silent_mode && did_show) + { + /* After displaying option values in silent mode. */ + silent_mode = FALSE; + info_message = TRUE; /* use mch_msg(), not mch_errmsg() */ + msg_putchar('\n'); + cursor_on(); /* msg_start() switches it off */ + out_flush(); + silent_mode = TRUE; + info_message = FALSE; /* use mch_msg(), not mch_errmsg() */ + } + return OK; } @@ -7547,7 +7591,11 @@ showoneopt(p, opt_flags) struct vimoption *p; int opt_flags; /* OPT_LOCAL or OPT_GLOBAL */ { - char_u *varp; + char_u *varp; + int save_silent = silent_mode; + + silent_mode = FALSE; + info_message = TRUE; /* use mch_msg(), not mch_errmsg() */ varp = get_varp_scope(p, opt_flags); @@ -7567,6 +7615,9 @@ showoneopt(p, opt_flags) option_value2string(p, opt_flags); msg_outtrans(NameBuff); } + + silent_mode = save_silent; + info_message = FALSE; } /* diff --git a/src/option.h b/src/option.h --- a/src/option.h +++ b/src/option.h @@ -174,10 +174,13 @@ #define CPO_PARA '{' /* "{" is also a paragraph boundary */ #define CPO_TSIZE '|' /* $LINES and $COLUMNS overrule term size */ #define CPO_PRESERVE '&' /* keep swap file after :preserve */ +#define CPO_SUBPERCENT '/' /* % in :s string uses previous one */ +#define CPO_BACKSL '\\' /* \ is not special in [] */ +#define CPO_CHDIR '.' /* don't chdir if buffer is modified */ /* default values for Vim, Vi and POSIX */ #define CPO_VIM "aABceFs" #define CPO_VI "aAbBcCdDeEfFgHiIjJkKlLmMnoOpqrRsStuvwWxXyZ$!%*-+<>" -#define CPO_ALL "aAbBcCdDeEfFgHiIjJkKlLmMnoOpqrRsStuvwWxXyZ$!%*-+<>#{|&" +#define CPO_ALL "aAbBcCdDeEfFgHiIjJkKlLmMnoOpqrRsStuvwWxXyZ$!%*-+<>#{|&/\\." /* characters for p_ww option: */ #define WW_ALL "bshl<>[],~" @@ -479,6 +482,7 @@ EXTERN char_u *p_pfn; /* 'printfont' */ EXTERN char_u *p_popt; /* 'printoptions' */ EXTERN char_u *p_header; /* 'printheader' */ #endif +EXTERN int p_prompt; /* 'prompt' */ #ifdef FEAT_GUI EXTERN char_u *p_guifont; /* 'guifont' */ # ifdef FEAT_XFONTSET @@ -675,6 +679,7 @@ EXTERN char_u *p_srr; /* 'shellredir' * #ifdef AMIGA EXTERN long p_st; /* 'shelltype' */ #endif +EXTERN int p_stmp; /* 'shelltemp' */ #ifdef BACKSLASH_IN_FILENAME EXTERN int p_ssl; /* 'shellslash' */ #endif diff --git a/src/os_mac_conv.c b/src/os_mac_conv.c --- a/src/os_mac_conv.c +++ b/src/os_mac_conv.c @@ -21,6 +21,21 @@ extern char_u *mac_string_convert __ARGS extern int macroman2enc __ARGS((char_u *ptr, long *sizep, long real_size)); extern int enc2macroman __ARGS((char_u *from, size_t fromlen, char_u *to, int *tolenp, int maxtolen, char_u *rest, int *restlenp)); +extern void mac_conv_init __ARGS((void)); +extern void mac_conv_cleanup __ARGS((void)); +extern char_u *mac_utf16_to_enc __ARGS((UniChar *from, size_t fromLen, size_t *actualLen)); +extern UniChar *mac_enc_to_utf16 __ARGS((char_u *from, size_t fromLen, size_t *actualLen)); +extern CFStringRef mac_enc_to_cfstring __ARGS((char_u *from, size_t fromLen)); +extern char_u *mac_precompose_path __ARGS((char_u *decompPath, size_t decompLen, size_t *precompLen)); + +static char_u *mac_utf16_to_utf8 __ARGS((UniChar *from, size_t fromLen, size_t *actualLen)); +static UniChar *mac_utf8_to_utf16 __ARGS((char_u *from, size_t fromLen, size_t *actualLen)); + +/* Converter for composing decomposed HFS+ file paths */ +static TECObjectRef gPathConverter; +/* Converter used by mac_utf16_to_utf8 */ +static TECObjectRef gUTF16ToUTF8Converter; + /* * A Mac version of string_convert_ext() for special cases. */ @@ -59,6 +74,8 @@ mac_string_convert(ptr, len, lenp, fail_ *unconvlenp = 0; cfstr = CFStringCreateWithBytes(NULL, ptr, len, from, 0); + if(cfstr == NULL) + fprintf(stderr, "Encoding failed\n"); /* When conversion failed, try excluding bytes from the end, helps when * there is an incomplete byte sequence. Only do up to 6 bytes to avoid * looping a long time when there really is something unconvertable. */ @@ -70,6 +87,7 @@ mac_string_convert(ptr, len, lenp, fail_ } if (cfstr == NULL) return NULL; + if (to == kCFStringEncodingUTF8) buflen = len * 6 + 1; else @@ -80,6 +98,22 @@ mac_string_convert(ptr, len, lenp, fail_ CFRelease(cfstr); return NULL; } + +#if 0 + CFRange convertRange = CFRangeMake(0, CFStringGetLength(cfstr)); + /* Determine output buffer size */ + CFStringGetBytes(cfstr, convertRange, to, NULL, FALSE, NULL, 0, (CFIndex *)&buflen); + retval = (buflen > 0) ? alloc(buflen) : NULL; + if (retval == NULL) { + CFRelease(cfstr); + return NULL; + } + + if (lenp) + *lenp = buflen / sizeof(char_u); + + if (!CFStringGetBytes(cfstr, convertRange, to, NULL, FALSE, retval, buflen, NULL)) +#endif if (!CFStringGetCString(cfstr, retval, buflen, to)) { CFRelease(cfstr); @@ -89,6 +123,7 @@ mac_string_convert(ptr, len, lenp, fail_ return NULL; } + fprintf(stderr, "Trying char-by-char conversion...\n"); /* conversion failed for the whole string, but maybe it will work * for each character */ for (d = retval, in = 0, out = 0; in < len && out < buflen - 1;) @@ -128,6 +163,7 @@ mac_string_convert(ptr, len, lenp, fail_ CFRelease(cfstr); if (lenp != NULL) *lenp = strlen(retval); + return retval; } @@ -230,4 +266,291 @@ enc2macroman(from, fromlen, to, tolenp, return OK; } +/* + * Initializes text converters + */ + void +mac_conv_init() +{ + TextEncoding utf8_encoding; + TextEncoding utf8_hfsplus_encoding; + TextEncoding utf8_canon_encoding; + TextEncoding utf16_encoding; + + utf8_encoding = CreateTextEncoding(kTextEncodingUnicodeDefault, + kTextEncodingDefaultVariant, kUnicodeUTF8Format); + utf8_hfsplus_encoding = CreateTextEncoding(kTextEncodingUnicodeDefault, + kUnicodeHFSPlusCompVariant, kUnicodeUTF8Format); + utf8_canon_encoding = CreateTextEncoding(kTextEncodingUnicodeDefault, + kUnicodeCanonicalCompVariant, kUnicodeUTF8Format); + utf16_encoding = CreateTextEncoding(kTextEncodingUnicodeDefault, + kTextEncodingDefaultVariant, kUnicode16BitFormat); + + if (TECCreateConverter(&gPathConverter, utf8_encoding, + utf8_hfsplus_encoding) != noErr) + gPathConverter = NULL; + + if (TECCreateConverter(&gUTF16ToUTF8Converter, utf16_encoding, + utf8_canon_encoding) != noErr) + gUTF16ToUTF8Converter = NULL; +} + +/* + * Destroys text converters + */ + void +mac_conv_cleanup() +{ + if (gUTF16ToUTF8Converter) + { + TECDisposeConverter(gUTF16ToUTF8Converter); + gUTF16ToUTF8Converter = NULL; + } + + if (gPathConverter) + { + TECDisposeConverter(gPathConverter); + gPathConverter = NULL; + } +} + +/* + * Conversion from UTF-16 UniChars to 'encoding' + */ + char_u * +mac_utf16_to_enc(from, fromLen, actualLen) + UniChar *from; + size_t fromLen; + size_t *actualLen; +{ + /* Following code borrows somewhat from os_mswin.c */ + vimconv_T conv; + size_t utf8_len; + char_u *utf8_str; + char_u *result = NULL; + + /* Convert to utf-8 first, works better with iconv */ + utf8_len = 0; + utf8_str = mac_utf16_to_utf8(from, fromLen, &utf8_len); + + if (utf8_str) + { + /* We might be called before we have p_enc set up. */ + conv.vc_type = CONV_NONE; + + /* If encoding (p_enc) is any unicode, it is actually in utf-8 (vim + * internal unicode is always utf-8) so don't convert in such cases */ + + if ((enc_canon_props(p_enc) & ENC_UNICODE) == 0) + convert_setup(&conv, (char_u *)"utf-8", + p_enc? p_enc: (char_u *)"macroman"); + if (conv.vc_type == CONV_NONE) + { + /* p_enc is utf-8, so we're done. */ + result = utf8_str; + } + else + { + result = string_convert(&conv, utf8_str, (int *)&utf8_len); + vim_free(utf8_str); + } + + convert_setup(&conv, NULL, NULL); + + if (actualLen) + *actualLen = utf8_len; + } + else if (actualLen) + *actualLen = 0; + + return result; +} + +/* + * Conversion from 'encoding' to UTF-16 UniChars + */ + UniChar * +mac_enc_to_utf16(from, fromLen, actualLen) + char_u *from; + size_t fromLen; + size_t *actualLen; +{ + /* Following code borrows somewhat from os_mswin.c */ + vimconv_T conv; + size_t utf8_len; + char_u *utf8_str; + UniChar *result = NULL; + Boolean should_free_utf8 = FALSE; + + do + { + /* Use MacRoman by default, we might be called before we have p_enc + * set up. Convert to utf-8 first, works better with iconv(). Does + * nothing if 'encoding' is "utf-8". */ + conv.vc_type = CONV_NONE; + if ((enc_canon_props(p_enc) & ENC_UNICODE) == 0 && + convert_setup(&conv, p_enc ? p_enc : (char_u *)"macroman", + (char_u *)"utf-8") == FAIL) + break; + + if (conv.vc_type != CONV_NONE) + { + utf8_len = fromLen; + utf8_str = string_convert(&conv, from, (int *)&utf8_len); + should_free_utf8 = TRUE; + } + else + { + utf8_str = from; + utf8_len = fromLen; + } + + if (utf8_str == NULL) + break; + + convert_setup(&conv, NULL, NULL); + + result = mac_utf8_to_utf16(utf8_str, utf8_len, actualLen); + + if (should_free_utf8) + vim_free(utf8_str); + return result; + } + while (0); + + if (actualLen) + *actualLen = 0; + + return result; +} + +/* + * Converts from UTF-16 UniChars to CFString + */ + CFStringRef +mac_enc_to_cfstring(from, fromLen) + char_u *from; + size_t fromLen; +{ + UniChar *utf16_str; + size_t utf16_len; + CFStringRef result = NULL; + + utf16_str = mac_enc_to_utf16(from, fromLen, &utf16_len); + if (utf16_str) + { + result = CFStringCreateWithCharacters(NULL, utf16_str, utf16_len/sizeof(UniChar)); + vim_free(utf16_str); + } + + return result; +} + +/* + * Converts a decomposed HFS+ UTF-8 path to precomposed UTF-8 + */ + char_u * +mac_precompose_path(decompPath, decompLen, precompLen) + char_u *decompPath; + size_t decompLen; + size_t *precompLen; +{ + char_u *result = NULL; + size_t actualLen = 0; + + if (gPathConverter) + { + result = alloc(decompLen); + if (result) + { + if (TECConvertText(gPathConverter, decompPath, + decompLen, &decompLen, result, + decompLen, &actualLen) != noErr) + { + vim_free(result); + result = NULL; + } + } + } + + if (precompLen) + *precompLen = actualLen; + + return result; +} + +/* + * Converts from UTF-16 UniChars to precomposed UTF-8 + */ + char_u * +mac_utf16_to_utf8(from, fromLen, actualLen) + UniChar *from; + size_t fromLen; + size_t *actualLen; +{ + ByteCount utf8_len; + ByteCount inputRead; + char_u *result; + + if (gUTF16ToUTF8Converter) + { + result = alloc(fromLen * 6 + 1); + if (result && TECConvertText(gUTF16ToUTF8Converter, (ConstTextPtr)from, + fromLen, &inputRead, result, + (fromLen*6+1)*sizeof(char_u), &utf8_len) == noErr) + { + TECFlushText(gUTF16ToUTF8Converter, result, (fromLen*6+1)*sizeof(char_u), &inputRead); + utf8_len += inputRead; + } + else + { + vim_free(result); + result = NULL; + } + } + else + { + result = NULL; + } + + if (actualLen) + *actualLen = result ? utf8_len : 0; + + return result; +} + +/* + * Converts from UTF-8 to UTF-16 UniChars + */ + UniChar * +mac_utf8_to_utf16(from, fromLen, actualLen) + char_u *from; + size_t fromLen; + size_t *actualLen; +{ + CFStringRef utf8_str; + CFRange convertRange; + UniChar *result = NULL; + + utf8_str = CFStringCreateWithBytes(NULL, from, fromLen, + kCFStringEncodingUTF8, FALSE); + + if (utf8_str == NULL) { + if (actualLen) + *actualLen = 0; + return NULL; + } + + convertRange = CFRangeMake(0, CFStringGetLength(utf8_str)); + result = (UniChar *)alloc(convertRange.length * sizeof(UniChar)); + + CFStringGetCharacters(utf8_str, convertRange, result); + + CFRelease(utf8_str); + + if (actualLen) + *actualLen = convertRange.length * sizeof(UniChar); + + return result; +} #endif /* FEAT_MBYTE */ diff --git a/src/po/Make_mvc.mak b/src/po/Make_mvc.mak --- a/src/po/Make_mvc.mak +++ b/src/po/Make_mvc.mak @@ -6,9 +6,9 @@ # Please read README_mvc.txt before using this file. # -LANGUAGES = af ca cs de en_GB es fr it ja ko no pl ru sk sv uk zh_TW \ +LANGUAGES = af ca cs de en_GB es fr ga it ja ko no pl ru sk sv uk zh_TW \ zh_TW.UTF-8 zh_CN zh_CN.UTF-8 -MOFILES = af.mo ca.mo cs.mo de.mo en_GB.mo es.mo fr.mo it.mo ja.mo \ +MOFILES = af.mo ca.mo cs.mo de.mo en_GB.mo es.mo fr.mo ga.mo it.mo ja.mo \ ko.mo no.mo pl.mo ru.mo sk.mo sv.mo uk.mo \ zh_TW.mo zh_TW.UTF-8.mo zh_CN.mo zh_CN.UTF-8.mo diff --git a/src/proto/eval.pro b/src/proto/eval.pro --- a/src/proto/eval.pro +++ b/src/proto/eval.pro @@ -6,6 +6,9 @@ int *func_dbg_tick __ARGS((void *cookie) int func_level __ARGS((void *cookie)); int current_func_returned __ARGS((void)); void set_internal_string_var __ARGS((char_u *name, char_u *value)); +int var_redir_start __ARGS((char_u *name, int append)); +void var_redir_str __ARGS((char_u *value, int len)); +void var_redir_stop __ARGS((void)); int eval_charconvert __ARGS((char_u *enc_from, char_u *enc_to, char_u *fname_from, char_u *fname_to)); int eval_printexpr __ARGS((char_u *fname, char_u *args)); void eval_diff __ARGS((char_u *origfile, char_u *newfile, char_u *outfile)); diff --git a/src/screen.c b/src/screen.c --- a/src/screen.c +++ b/src/screen.c @@ -6847,18 +6847,6 @@ screen_start() } /* - * Note that the cursor has gone down to the next line, column 0. - * Used for Ex mode. - */ - void -screen_down() -{ - screen_cur_col = 0; - if (screen_cur_row < Rows - 1) - ++screen_cur_row; -} - -/* * Move the cursor to position "row","col" in the screen. * This tries to find the most efficient way to move, minimizing the number of * characters sent to the terminal. diff --git a/src/search.c b/src/search.c --- a/src/search.c +++ b/src/search.c @@ -4715,7 +4715,7 @@ show_pat_in_path(line, type, did_show, a msg_puts_attr(IObuff, hl_attr(HLF_N)); MSG_PUTS(" "); } - msg_prt_line(line); + msg_prt_line(line, FALSE); out_flush(); /* show one line at a time */ /* Definition continues until line that doesn't end with '\' */ diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -307,7 +307,8 @@ struct m_block { mblock_T *mb_next; /* pointer to next allocated block */ size_t mb_size; /* total size of all chunks in this block */ - minfo_T mb_info; /* head of free chuck list for this block */ + size_t mb_maxsize; /* size of largest fee chunk */ + minfo_T mb_info; /* head of free chunk list for this block */ }; /* @@ -1211,6 +1212,7 @@ struct file_buffer minfo_T *b_m_search; /* pointer to chunk before previously allocated/freed chunk */ mblock_T *b_mb_current; /* block where m_search points in */ + #ifdef FEAT_INS_EXPAND int b_scanned; /* ^N/^P have scanned this buffer */ #endif diff --git a/src/syntax.c b/src/syntax.c --- a/src/syntax.c +++ b/src/syntax.c @@ -4397,8 +4397,19 @@ syn_cmd_keyword(eap, syncing) add_keyword(kw, syn_id, syn_opt_arg.flags, syn_opt_arg.cont_in_list, syn_opt_arg.next_list); - if (p == NULL || p[1] == NUL || p[1] == ']') + if (p == NULL) + break; + if (p[1] == NUL) + { + EMSG2(_("E747: Missing ']': %s"), kw); + kw = p + 2; /* skip over the NUL */ break; + } + if (p[1] == ']') + { + kw = p + 1; /* skip over the "]" */ + break; + } #ifdef FEAT_MBYTE if (has_mbyte) { @@ -4418,6 +4429,8 @@ syn_cmd_keyword(eap, syncing) } vim_free(keyword_copy); + vim_free(syn_opt_arg.cont_in_list); + vim_free(syn_opt_arg.next_list); } } @@ -4426,8 +4439,6 @@ syn_cmd_keyword(eap, syncing) else EMSG2(_(e_invarg2), arg); - vim_free(syn_opt_arg.cont_in_list); - vim_free(syn_opt_arg.next_list); redraw_curbuf_later(NOT_VALID); syn_stack_free_all(curbuf); /* Need to recompute all syntax. */ } diff --git a/src/term.c b/src/term.c --- a/src/term.c +++ b/src/term.c @@ -1590,6 +1590,10 @@ set_termname(term) char_u *error_msg = NULL; char_u *bs_p, *del_p; + /* In silect mode (ex -s) we don't use the 'term' option. */ + if (silent_mode) + return OK; + detected_8bit = FALSE; /* reset 8-bit detection */ if (term_is_builtin(term)) @@ -3146,10 +3150,6 @@ settmode(tmode) if (full_screen) { - /* In Ex mode, never set to RAW */ - if (exmode_active == EXMODE_NORMAL) - tmode = TMODE_COOK; - /* * When returning after calling a shell we want to really set the * terminal to raw mode, even though we think it already is, because diff --git a/src/undo.c b/src/undo.c --- a/src/undo.c +++ b/src/undo.c @@ -41,24 +41,33 @@ * curbuf->b_u_curhead points to the header of the last undo (the next redo), * or is NULL if nothing has been undone. * - * All data is allocated with u_alloc_line(), thus it will be freed as soon as - * we switch files! + * All data is allocated with U_ALLOC_LINE(), it will be freed as soon as the + * buffer is unloaded. */ #include "vim.h" +/* See below: use malloc()/free() for memory management. */ +#define U_USE_MALLOC 1 + static u_entry_T *u_get_headentry __ARGS((void)); static void u_getbot __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((void)); static void u_undo_end __ARGS((void)); -static void u_freelist __ARGS((struct u_header *)); +static void u_freelist __ARGS((buf_T *buf, struct u_header *)); static void u_freeentry __ARGS((u_entry_T *, long)); -static char_u *u_blockalloc __ARGS((long_u)); -static void u_free_line __ARGS((char_u *, int keep)); -static char_u *u_alloc_line __ARGS((unsigned)); +#ifdef U_USE_MALLOC +# define U_FREE_LINE(ptr) vim_free(ptr) +# define U_ALLOC_LINE(size) lalloc((long_u)((size) + 1), FALSE) +#else +static void u_free_line __ARGS((char_u *ptr, int keep)); +static char_u *u_alloc_line __ARGS((unsigned size)); +# define U_FREE_LINE(ptr) u_free_line((ptr), FALSE) +# define U_ALLOC_LINE(size) u_alloc_line(size) +#endif static char_u *u_save_line __ARGS((linenr_T)); static long u_newcount, u_oldcount; @@ -227,13 +236,13 @@ u_savecommon(top, bot, newbot) * including curbuf->b_u_curhead */ while (curbuf->b_u_curhead != NULL) - u_freelist(curbuf->b_u_newhead); + u_freelist(curbuf, curbuf->b_u_newhead); /* * free headers to keep the size right */ while (curbuf->b_u_numhead > p_ul && curbuf->b_u_oldhead != NULL) - u_freelist(curbuf->b_u_oldhead); + u_freelist(curbuf, curbuf->b_u_oldhead); if (p_ul < 0) /* no undo at all */ { @@ -244,7 +253,7 @@ u_savecommon(top, bot, newbot) /* * make a new header entry */ - uhp = (struct u_header *)u_alloc_line((unsigned) + uhp = (struct u_header *)U_ALLOC_LINE((unsigned) sizeof(struct u_header)); if (uhp == NULL) goto nomem; @@ -364,7 +373,7 @@ u_savecommon(top, bot, newbot) /* * add lines in front of entry list */ - uep = (u_entry_T *)u_alloc_line((unsigned)sizeof(u_entry_T)); + uep = (u_entry_T *)U_ALLOC_LINE((unsigned)sizeof(u_entry_T)); if (uep == NULL) goto nomem; @@ -384,9 +393,9 @@ u_savecommon(top, bot, newbot) curbuf->b_u_newhead->uh_getbot_entry = uep; } - if (size) + if (size > 0) { - if ((uep->ue_array = (char_u **)u_alloc_line( + if ((uep->ue_array = (char_u **)U_ALLOC_LINE( (unsigned)(sizeof(char_u *) * size))) == NULL) { u_freeentry(uep, 0L); @@ -609,9 +618,9 @@ u_undoredo() empty_buffer = FALSE; /* delete the lines between top and bot and save them in newarray */ - if (oldsize) + if (oldsize > 0) { - if ((newarray = (char_u **)u_alloc_line( + if ((newarray = (char_u **)U_ALLOC_LINE( (unsigned)(sizeof(char_u *) * oldsize))) == NULL) { do_outofmem_msg((long_u)(sizeof(char_u *) * oldsize)); @@ -654,9 +663,9 @@ u_undoredo() ml_replace((linenr_T)1, uep->ue_array[i], TRUE); else ml_append(lnum, uep->ue_array[i], (colnr_T)0, FALSE); - u_free_line(uep->ue_array[i], FALSE); + U_FREE_LINE(uep->ue_array[i]); } - u_free_line((char_u *)uep->ue_array, FALSE); + U_FREE_LINE((char_u *)uep->ue_array); } /* adjust marks */ @@ -870,7 +879,8 @@ u_getbot() * u_freelist: free one entry list and adjust the pointers */ static void -u_freelist(uhp) +u_freelist(buf, uhp) + buf_T *buf; struct u_header *uhp; { u_entry_T *uep, *nuep; @@ -881,21 +891,21 @@ u_freelist(uhp) u_freeentry(uep, uep->ue_size); } - if (curbuf->b_u_curhead == uhp) - curbuf->b_u_curhead = NULL; + if (buf->b_u_curhead == uhp) + buf->b_u_curhead = NULL; if (uhp->uh_next == NULL) - curbuf->b_u_oldhead = uhp->uh_prev; + buf->b_u_oldhead = uhp->uh_prev; else uhp->uh_next->uh_prev = uhp->uh_prev; if (uhp->uh_prev == NULL) - curbuf->b_u_newhead = uhp->uh_next; + buf->b_u_newhead = uhp->uh_next; else uhp->uh_prev->uh_next = uhp->uh_next; - u_free_line((char_u *)uhp, FALSE); - --curbuf->b_u_numhead; + U_FREE_LINE((char_u *)uhp); + --buf->b_u_numhead; } /* @@ -907,8 +917,8 @@ u_freeentry(uep, n) long n; { while (n) - u_free_line(uep->ue_array[--n], FALSE); - u_free_line((char_u *)uep, FALSE); + U_FREE_LINE(uep->ue_array[--n]); + U_FREE_LINE((char_u *)uep); } /* @@ -955,7 +965,7 @@ u_clearline() { if (curbuf->b_u_line_ptr != NULL) { - u_free_line(curbuf->b_u_line_ptr, FALSE); + U_FREE_LINE(curbuf->b_u_line_ptr); curbuf->b_u_line_ptr = NULL; curbuf->b_u_line_lnum = 0; } @@ -993,7 +1003,7 @@ u_undoline() } ml_replace(curbuf->b_u_line_lnum, curbuf->b_u_line_ptr, TRUE); changed_bytes(curbuf->b_u_line_lnum, 0); - u_free_line(curbuf->b_u_line_ptr, FALSE); + U_FREE_LINE(curbuf->b_u_line_ptr); curbuf->b_u_line_ptr = oldp; t = curbuf->b_u_line_colnr; @@ -1004,7 +1014,40 @@ u_undoline() } /* - * storage allocation for the undo lines and blocks of the current file + * There are two implementations of the memory management for undo: + * 1. Use the standard malloc()/free() functions. + * This should be fast for allocating memory, but when a buffer is + * abandoned every single allocated chunk must be freed, which may be slow. + * 2. Allocate larger blocks of memory and keep track of chunks ourselves. + * This is fast for abandoning, but the use of linked lists is slow for + * finding a free chunk. Esp. when a lot of lines are changed or deleted. + * A bit of profiling showed that the first method is faster, especially when + * making a large number of changes, under the condition that malloc()/free() + * is implemented efficiently. + */ +#ifdef U_USE_MALLOC +/* + * Version of undo memory allocation using malloc()/free() + * + * U_FREE_LINE() and U_ALLOC_LINE() are macros that invoke vim_free() and + * lalloc() directly. + */ + +/* + * Free all allocated memory blocks for the buffer 'buf'. + */ + void +u_blockfree(buf) + buf_T *buf; +{ + while (buf->b_u_newhead != NULL) + u_freelist(buf, buf->b_u_newhead); +} + +#else +/* + * Storage allocation for the undo lines and blocks of the current file. + * Version where Vim keeps track of the available memory. */ /* @@ -1071,6 +1114,8 @@ u_undoline() # define M_OFFSET (sizeof(short_u)) #endif +static char_u *u_blockalloc __ARGS((long_u)); + /* * Allocate a block of memory and link it in the allocated block list. */ @@ -1092,6 +1137,7 @@ u_blockalloc(size) ; p->mb_next = next; /* link in block list */ p->mb_size = size; + p->mb_maxsize = 0; /* nothing free yet */ mp->mb_next = p; p->mb_info.m_next = NULL; /* clear free list */ p->mb_info.m_size = 0; @@ -1135,6 +1181,7 @@ u_free_line(ptr, keep) minfo_T *mp; mblock_T *nextb; mblock_T *prevb; + long_u maxsize; if (ptr == NULL || ptr == IObuff) return; /* illegal address can happen in out-of-memory situations */ @@ -1212,11 +1259,13 @@ u_free_line(ptr, keep) } else mp->m_next = next; + maxsize = mp->m_size; /* if *curr and *mp are concatenated, join them */ if (prev != NULL && (char_u *)curr + curr->m_size == (char_u *)mp) { curr->m_size += mp->m_size; + maxsize = curr->m_size; curr->m_next = mp->m_next; curbuf->b_m_search = prev; } @@ -1244,6 +1293,8 @@ u_free_line(ptr, keep) curbuf->b_mb_current = NULL; curbuf->b_m_search = NULL; } + else if (curbuf->b_mb_current->mb_maxsize < maxsize) + curbuf->b_mb_current->mb_maxsize = maxsize; } /* @@ -1282,48 +1333,56 @@ u_alloc_line(size) curbuf->b_m_search = &(curbuf->b_block_head.mb_info); } - /* search for space in free list */ - mprev = curbuf->b_m_search; + /* Search for a block with enough space. */ mbp = curbuf->b_mb_current; - mp = curbuf->b_m_search->m_next; - if (mp == NULL) + while (mbp->mb_maxsize < size_align) { - if (mbp->mb_next) + if (mbp->mb_next != NULL) mbp = mbp->mb_next; else mbp = &curbuf->b_block_head; - mp = curbuf->b_m_search = &(mbp->mb_info); - } - while (mp->m_size < size) - { - if (mp == curbuf->b_m_search) /* back where we started in free - chunk list */ + if (mbp == curbuf->b_mb_current) { - if (mbp->mb_next) - mbp = mbp->mb_next; - else - mbp = &curbuf->b_block_head; - mp = curbuf->b_m_search = &(mbp->mb_info); - if (mbp == curbuf->b_mb_current) /* back where we started in - block list */ - { - int n = (size_align > (MEMBLOCKSIZE / 4) - ? size_align : MEMBLOCKSIZE); + int n = (size_align > (MEMBLOCKSIZE / 4) + ? size_align : MEMBLOCKSIZE); - mp = (minfo_T *)u_blockalloc((long_u)n); - if (mp == NULL) - return (NULL); - mp->m_size = n; - u_free_line((char_u *)mp + M_OFFSET, TRUE); - mp = curbuf->b_m_search; - mbp = curbuf->b_mb_current; - } + /* Back where we started in block list: need to add a new block + * with enough space. */ + mp = (minfo_T *)u_blockalloc((long_u)n); + if (mp == NULL) + return (NULL); + mp->m_size = n; + u_free_line((char_u *)mp + M_OFFSET, TRUE); + mbp = curbuf->b_mb_current; + break; + } + } + if (mbp != curbuf->b_mb_current) + curbuf->b_m_search = &(mbp->mb_info); + + /* In this block find a chunk with enough space. */ + mprev = curbuf->b_m_search; + mp = curbuf->b_m_search->m_next; + while (1) + { + if (mp == NULL) /* at end of the list */ + mp = &(mbp->mb_info); /* wrap around to begin */ + if (mp->m_size >= size) + break; + if (mp == curbuf->b_m_search) + { + /* back where we started in free chunk list: "cannot happen" */ + EMSG2(_(e_intern2), "u_alloc_line()"); + return NULL; } mprev = mp; - if ((mp = mp->m_next) == NULL) /* at end of the list */ - mp = &(mbp->mb_info); /* wrap around to begin */ + mp = mp->m_next; } + /* when using the largest chunk adjust mb_maxsize */ + if (mp->m_size >= mbp->mb_maxsize) + mbp->mb_maxsize = 0; + /* if the chunk we found is large enough, split it up in two */ if ((long)mp->m_size - size_align >= (long)(sizeof(minfo_T) + 1)) { @@ -1340,11 +1399,18 @@ u_alloc_line(size) curbuf->b_m_search = mprev; curbuf->b_mb_current = mbp; + /* If using the largest chunk need to find the new largest chunk */ + if (mbp->mb_maxsize == 0) + for (mp2 = &(mbp->mb_info); mp2 != NULL; mp2 = mp2->m_next) + if (mbp->mb_maxsize < mp2->m_size) + mbp->mb_maxsize = mp2->m_size; + mp = (minfo_T *)((char_u *)mp + M_OFFSET); *(char_u *)mp = NUL; /* set the first byte to NUL */ return ((char_u *)mp); } +#endif /* * u_save_line(): allocate memory with u_alloc_line() and copy line 'lnum' @@ -1360,7 +1426,7 @@ u_save_line(lnum) src = ml_get(lnum); len = (unsigned)STRLEN(src); - if ((dst = u_alloc_line(len)) != NULL) + if ((dst = U_ALLOC_LINE(len)) != NULL) mch_memmove(dst, src, (size_t)(len + 1)); return (dst); } diff --git a/src/version.h b/src/version.h --- a/src/version.h +++ b/src/version.h @@ -36,5 +36,5 @@ #define VIM_VERSION_NODOT "vim70aa" #define VIM_VERSION_SHORT "7.0aa" #define VIM_VERSION_MEDIUM "7.0aa ALPHA" -#define VIM_VERSION_LONG "VIM - Vi IMproved 7.0aa ALPHA (2005 Feb 12)" -#define VIM_VERSION_LONG_DATE "VIM - Vi IMproved 7.0aa ALPHA (2005 Feb 12, compiled " +#define VIM_VERSION_LONG "VIM - Vi IMproved 7.0aa ALPHA (2005 Feb 21)" +#define VIM_VERSION_LONG_DATE "VIM - Vi IMproved 7.0aa ALPHA (2005 Feb 21, compiled "