diff options
author | Bram Moolenaar <Bram@vim.org> | 2010-06-05 23:22:07 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2010-06-05 23:22:07 +0200 |
commit | 860cae1cec85aeb06668a2b071727c43869acf15 (patch) | |
tree | 8f7b62b69f4a7d3340902178927bbc3f9d24cc3e | |
parent | 945e2dbb633ed29b697a8d4eea51672e3c11143b (diff) | |
download | vim-git-860cae1cec85aeb06668a2b071727c43869acf15.tar.gz |
Add the conceal patch from Vince Negri.
40 files changed, 1737 insertions, 698 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 7d5e6d6e0..fda756fbb 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1163,6 +1163,13 @@ b:changedtick The total number of changes to the current buffer. It is A variable name that is preceded with "w:" is local to the current window. It is deleted when the window is closed. +One local window variable is predefined: + *w:ownsyntax-variable* *ownsyntax* +w:ownsyntax Set to 1 if the window has an independent syntax installed + via the |:ownsyntax| command. The default for a window is + 0. Syntax scripts can use this to determine whether they + should set b:current_syntax or w:current_syntax. + *tabpage-variable* *t:var* A variable name that is preceded with "t:" is local to the current tab page, It is deleted when the tab page is closed. {not available when compiled @@ -5772,7 +5779,7 @@ undofile({name}) *undofile()* Return the name of the undo file that would be used for a file with name {name} when writing. This uses the 'undodir' option, finding directories that exist. It does not check if - the undo file exist. + the undo file exists. {name} is always expanded to the full path, since that is what is used internally. Useful in combination with |:wundo| and |:rundo|. diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 63efd1c24..c021edfc4 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1707,6 +1707,25 @@ A jump table for the options with a short description can be found at |Q_op|. combination with "menu" or "menuone". +'conceallevel' 'conc' *'conceallevel'* *'conc'* + number (default 0) + local to window + {not in Vi} + {not available when compiled without the |+conceal| + feature} + Determine how text with the "conceal" syntax attribute is shown: + + 'conceallevel' Effect + 0 Text is shown normally + 1 Each block of concealed text is replaced with the + character defined in 'listchars' (default is a dash) + and highlighted with the "Conceal" highlight group. + 2 Concealed text is completely hidden unless it has a + custom replacement character defined (see + |:syn-cchar|. + 3 Concealed text is completely hidden. + + *'confirm'* *'cf'* *'noconfirm'* *'nocf'* 'confirm' 'cf' boolean (default off) global @@ -2132,6 +2151,20 @@ A jump table for the options with a short description can be found at |Q_op|. Give messages when adding a cscope database. See |cscopeverbose|. NOTE: This option is reset when 'compatible' is set. + *'cursorbind'* *'crb'* *'nocursorbind'* *'nocrb'* +'cursorbind' 'crb' boolean (default off) + local to window + {not in Vi} + {not available when compiled without the |+cursorbind| + feature} + When this option is set, as the cursor in the current + window moves other cursorbound windows (windows that also have + this option set) move their cursors to the corresponding line and + column. This option is useful for viewing the + differences between two versions of a file (see 'diff'); in diff mode, + inserted and deleted lines (though not characters within a line) are + taken into account. + *'cursorcolumn'* *'cuc'* *'nocursorcolumn'* *'nocuc'* 'cursorcolumn' 'cuc' boolean (default off) @@ -3615,7 +3648,7 @@ A jump table for the options with a short description can be found at |Q_op|. f:Folded,F:FoldColumn,A:DiffAdd, C:DiffChange,D:DiffDelete,T:DiffText, >:SignColumn,B:SpellBad,P:SpellCap, - R:SpellRare,L:SpellLocal, + R:SpellRare,L:SpellLocal,-:Conceal, +:Pmenu,=:PmenuSel, x:PmenuSbar,X:PmenuThumb") global @@ -3659,6 +3692,8 @@ A jump table for the options with a short description can be found at |Q_op|. |hl-SpellCap| P word that should start with capital|spell| |hl-SpellRare| R rare word |spell| |hl-SpellLocal| L word from other region |spell| + |hl-Conceal| - the placeholders used for concealed characters + (see 'conceallevel') |hl-Pmenu| + popup menu normal line |hl-PmenuSel| = popup menu normal line |hl-PmenuSbar| x popup menu scrollbar @@ -4416,6 +4451,8 @@ A jump table for the options with a short description can be found at |Q_op|. precedes:c Character to show in the first column, when 'wrap' is off and there is text preceding the character visible in the first column. + conceal:c Character to show in place of concealed text, when + 'conceallevel' is set to 1. nbsp:c Character to show for a non-breakable space (character 0xA0, 160). Left blank when omitted. diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index 109276f40..47a1aac79 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -35,7 +35,8 @@ In the User Manual: 13. Linking groups |:highlight-link| 14. Cleaning up |:syn-clear| 15. Highlighting tags |tag-highlight| -16. Color xterms |xterm-color| +16. Window-local syntax |:ownsyntax| +17. Color xterms |xterm-color| {Vi does not have any of these commands} @@ -3115,12 +3116,14 @@ and may be mixed with patterns. Not all commands accept all arguments. This table shows which arguments can not be used for all commands: *E395* *E396* - contains oneline fold display extend ~ -:syntax keyword - - - - - -:syntax match yes - yes yes yes -:syntax region yes yes yes yes yes + contains oneline fold display extend concealends~ +:syntax keyword - - - - - - +:syntax match yes - yes yes yes - +:syntax region yes yes yes yes yes yes These arguments can be used for all three commands: + conceal + cchar contained containedin nextgroup @@ -3129,6 +3132,27 @@ These arguments can be used for all three commands: skipnl skipempty +conceal *conceal* *:syn-conceal* + +When the "conceal" argument is given, the item is marked as concealable. +Whether or not it is actually concealed depends on the setting on the +'conceallevel' option. + +concealends *:syn-concealends* + +When the "concealends" argument is given, the start and end matches of +the region, but not the contents of the region, are marked as concealable. +Whether or not they are actually concealed depends on the setting on the +'conceallevel' option. The ends of a region can only be concealed separately +in this way when they have their own highlighting via "matchgroup" + +cchar *:syn-cchar* + +The "cchar" argument defines the character shown in place of the item +when it is concealed (setting "cchar" only makes sense when the conceal +argument is given.) If "cchar" is not set then the default conceal +character defined in the 'listchars' option is used. Example: > + :syntax match Entity "&" conceal cchar=& contained *:syn-contained* @@ -3385,6 +3409,16 @@ Note that this example doesn't work for nested "if"s. You need to add "contains" arguments to make that work (omitted for simplicity of the example). +IMPLICIT CONCEAL *:syn-conceal-implicit* + +:sy[ntax] conceal [on|off] + This defines if the following ":syntax" commands will define keywords, + matches or regions with the "conceal" flag set. After ":syn conceal + on", all subsequent ":syn keyword", ":syn match" or ":syn region" + defined will have the "conceal" flag set implicitly. ":syn conceal + off" returns to the normal state where the "conceal" flag must be + given explicitly. + ============================================================================== 7. Syntax patterns *:syn-pattern* *E401* *E402* @@ -4169,6 +4203,9 @@ These are the default highlighting groups. These groups are used by the 'highlight' option default. Note that the highlighting depends on the value of 'background'. You can see the current settings with the ":highlight" command. + *hl-Conceal* +Conceal placeholder characters substituted for concealed + text (see 'conceallevel') *hl-Cursor* Cursor the character under the cursor *hl-CursorIM* @@ -4472,6 +4509,28 @@ And put these lines in your .vimrc: > autocmd BufRead,BufNewFile *.[ch] endif ============================================================================== +16. Window-local syntax *:ownsyntax* + +Normally all windows on a buffer share the same syntax settings. It is +possible, however, to set a particular window on a file to have its own +private syntax setting. A possible example would be to edit LaTeX source +with conventional highlighting in one window, while seeing the same source +highlighted differently (so as to hide control sequences and indicate bold, +italic etc regions) in another. The 'scrollbind' option is useful here. + +To set the current window to have the syntax "foo", separately from all other +windows on the buffer: > + :ownsyntax foo + +Once a window has its own syntax, syntax commands executed from other windows +on the same buffer (including :syntax clear) have no effect. Conversely, +syntax commands executed from that window do not effect other windows on the +same buffer. + +A window with its own syntax reverts to normal behaviour when another buffer +is loaded into that window. + +============================================================================== 16. Color xterms *xterm-color* *color-xterm* Most color xterms have only eight colors. If you don't get colors with the diff --git a/runtime/doc/tags b/runtime/doc/tags index 632f28845..18cd16b89 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -134,6 +134,8 @@ $VIMRUNTIME starting.txt /*$VIMRUNTIME* 'complete' options.txt /*'complete'* 'completefunc' options.txt /*'completefunc'* 'completeopt' options.txt /*'completeopt'* +'conc' options.txt /*'conc'* +'conceallevel' options.txt /*'conceallevel'* 'confirm' options.txt /*'confirm'* 'consk' options.txt /*'consk'* 'conskey' options.txt /*'conskey'* @@ -143,6 +145,7 @@ $VIMRUNTIME starting.txt /*$VIMRUNTIME* 'cpo' options.txt /*'cpo'* 'cpoptions' options.txt /*'cpoptions'* 'cpt' options.txt /*'cpt'* +'crb' options.txt /*'crb'* 'cryptmethod' options.txt /*'cryptmethod'* 'cscopepathcomp' options.txt /*'cscopepathcomp'* 'cscopeprg' options.txt /*'cscopeprg'* @@ -158,6 +161,7 @@ $VIMRUNTIME starting.txt /*$VIMRUNTIME* 'csverb' options.txt /*'csverb'* 'cuc' options.txt /*'cuc'* 'cul' options.txt /*'cul'* +'cursorbind' options.txt /*'cursorbind'* 'cursorcolumn' options.txt /*'cursorcolumn'* 'cursorline' options.txt /*'cursorline'* 'cwh' options.txt /*'cwh'* @@ -482,12 +486,14 @@ $VIMRUNTIME starting.txt /*$VIMRUNTIME* 'noconskey' options.txt /*'noconskey'* 'nocopyindent' options.txt /*'nocopyindent'* 'nocp' options.txt /*'nocp'* +'nocrb' options.txt /*'nocrb'* 'nocscopetag' options.txt /*'nocscopetag'* 'nocscopeverbose' options.txt /*'nocscopeverbose'* 'nocst' options.txt /*'nocst'* 'nocsverb' options.txt /*'nocsverb'* 'nocuc' options.txt /*'nocuc'* 'nocul' options.txt /*'nocul'* +'nocursorbind' options.txt /*'nocursorbind'* 'nocursorcolumn' options.txt /*'nocursorcolumn'* 'nocursorline' options.txt /*'nocursorline'* 'nodeco' options.txt /*'nodeco'* @@ -1120,8 +1126,10 @@ $VIMRUNTIME starting.txt /*$VIMRUNTIME* +cmdline_hist various.txt /*+cmdline_hist* +cmdline_info various.txt /*+cmdline_info* +comments various.txt /*+comments* ++conceal various.txt /*+conceal* +cryptv various.txt /*+cryptv* +cscope various.txt /*+cscope* ++cursorbind various.txt /*+cursorbind* +cursorshape various.txt /*+cursorshape* +debug various.txt /*+debug* +dialog_con various.txt /*+dialog_con* @@ -2495,6 +2503,7 @@ $VIMRUNTIME starting.txt /*$VIMRUNTIME* :ounmap map.txt /*:ounmap* :ounme gui.txt /*:ounme* :ounmenu gui.txt /*:ounmenu* +:ownsyntax syntax.txt /*:ownsyntax* :p various.txt /*:p* :pc windows.txt /*:pc* :pclose windows.txt /*:pclose* @@ -2761,8 +2770,12 @@ $VIMRUNTIME starting.txt /*$VIMRUNTIME* :syn syntax.txt /*:syn* :syn-arguments syntax.txt /*:syn-arguments* :syn-case syntax.txt /*:syn-case* +:syn-cchar syntax.txt /*:syn-cchar* :syn-clear syntax.txt /*:syn-clear* :syn-cluster syntax.txt /*:syn-cluster* +:syn-conceal syntax.txt /*:syn-conceal* +:syn-conceal-implicit syntax.txt /*:syn-conceal-implicit* +:syn-concealends syntax.txt /*:syn-concealends* :syn-contained syntax.txt /*:syn-contained* :syn-containedin syntax.txt /*:syn-containedin* :syn-contains syntax.txt /*:syn-contains* @@ -4956,6 +4969,7 @@ complete_check() eval.txt /*complete_check()* complex-change change.txt /*complex-change* complex-repeat repeat.txt /*complex-repeat* compress pi_gzip.txt /*compress* +conceal syntax.txt /*conceal* confirm() eval.txt /*confirm()* connection-refused message.txt /*connection-refused* console-menus gui.txt /*console-menus* @@ -6019,6 +6033,7 @@ hit-enter-prompt message.txt /*hit-enter-prompt* hit-return message.txt /*hit-return* hitest.vim syntax.txt /*hitest.vim* hjkl usr_02.txt /*hjkl* +hl-Conceal syntax.txt /*hl-Conceal* hl-Cursor syntax.txt /*hl-Cursor* hl-CursorColumn syntax.txt /*hl-CursorColumn* hl-CursorIM syntax.txt /*hl-CursorIM* @@ -6895,6 +6910,7 @@ os_unix.txt os_unix.txt /*os_unix.txt* os_vms.txt os_vms.txt /*os_vms.txt* os_win32.txt os_win32.txt /*os_win32.txt* other-features vi_diff.txt /*other-features* +ownsyntax eval.txt /*ownsyntax* p change.txt /*p* page-down intro.txt /*page-down* page-up intro.txt /*page-up* @@ -8200,6 +8216,7 @@ vt100-cursor-keys term.txt /*vt100-cursor-keys* vt100-function-keys term.txt /*vt100-function-keys* w motion.txt /*w* w32-clientserver remote.txt /*w32-clientserver* +w:ownsyntax-variable eval.txt /*w:ownsyntax-variable* w:var eval.txt /*w:var* warningmsg-variable eval.txt /*warningmsg-variable* white-space pattern.txt /*white-space* diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt index 27039a249..12c6b682a 100644 --- a/runtime/doc/todo.txt +++ b/runtime/doc/todo.txt @@ -1082,6 +1082,10 @@ restored. (Luc St-Louis) Vim 7.3: +- Included conceal patch. + remove w:ownsyntax, automatically set w:current_syntax to the value of + b:current_syntax after loading a syntax file. + :ownsyntax only sets w:current_syntax. - using NSIS 2.46: install on Windows 7 works, but no "Edit with Vim" menu. Use register_shell_extension()? (George Reilly, 2010 May 26) Ron's version: http://dev.ronware.org/p/vim/finfo?name=gvim.nsi @@ -1108,10 +1112,6 @@ Vim 7.3: - Create a helphelp.txt file, move instructions there to write help files from various.txt and list by Tony. Patches to include: -- Include conceal patch? - http://vince.negri.googlepages.com/ - http://vim.wikia.com/wiki/Patch_to_conceal_parts_of_lines - http://sites.google.com/site/vincenegri/conceal-ownsyntax.diff?attredirects=0 - Patch for Lisp support with ECL (Mikael Jansson, 2008 Oct 25) - Minor patches from Dominique Pelle, 2010 May 15 - Gvimext patch to support wide file names. (Szabolcs Horvat 2008 Sep 10) diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt index 3f1d061ba..63b279b32 100644 --- a/runtime/doc/various.txt +++ b/runtime/doc/various.txt @@ -293,8 +293,10 @@ N *+cmdline_compl* command line completion |cmdline-completion| N *+cmdline_hist* command line history |cmdline-history| N *+cmdline_info* |'showcmd'| and |'ruler'| N *+comments* |'comments'| support +m *+conceal* "conceal" support, see ||conceal|| |:syn-conceal| etc. N *+cryptv* encryption support |encryption| B *+cscope* |cscope| support +m *+cursorbind* |'cursorbind'| support m *+cursorshape* |termcap-cursor-shape| support m *+debug* Compiled for debugging. N *+dialog_gui* Support for |:confirm| with GUI dialog. diff --git a/runtime/optwin.vim b/runtime/optwin.vim index 0ace4cc6d..12e934f2d 100644 --- a/runtime/optwin.vim +++ b/runtime/optwin.vim @@ -373,6 +373,11 @@ if has("linebreak") call append("$", "\t(local to window)") call <SID>OptionL("nuw") endif +if has("conceal") + call append("$", "conceallevel\tcontrols whether concealable elements are hidden") + call append("$", "\t(local to window)") + call <SID>OptionL("conc") +endif call <SID>Header("syntax, highlighting and spelling") diff --git a/src/buffer.c b/src/buffer.c index 5ecb63872..cf7ecbbe9 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -581,7 +581,7 @@ buf_freeall(buf, del_buf, wipe_buf) buf->b_ml.ml_line_count = 0; /* no lines in buffer */ u_clearall(buf); /* reset all undo information */ #ifdef FEAT_SYN_HL - syntax_clear(buf); /* reset syntax info */ + syntax_clear(&buf->b_s); /* reset syntax info */ #endif buf->b_flags &= ~BF_READERR; /* a read error is no longer relevant */ } @@ -648,7 +648,7 @@ free_buffer_stuff(buf, free_options) buf->b_start_fenc = NULL; #endif #ifdef FEAT_SPELL - ga_clear(&buf->b_langp); + ga_clear(&buf->b_s.b_langp); #endif } @@ -1378,6 +1378,15 @@ enter_buffer(buf) foldUpdateAll(curwin); /* update folds (later). */ #endif +#ifdef FEAT_SYN_HL + if (curwin->w_s != &curwin->w_buffer->b_s) + { + /* Get rid of independant syntax */ + syntax_clear(curwin->w_s); + vim_free(curwin->w_s); + } + curwin->w_s = &(buf->b_s); +#endif /* Get the buffer in the current window. */ curwin->w_buffer = buf; curbuf = buf; @@ -1460,8 +1469,8 @@ enter_buffer(buf) #ifdef FEAT_SPELL /* May need to set the spell language. Can only do this after the buffer * has been properly setup. */ - if (!curbuf->b_help && curwin->w_p_spell && *curbuf->b_p_spl != NUL) - (void)did_set_spelllang(curbuf); + if (!curbuf->b_help && curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL) + (void)did_set_spelllang(curwin); #endif redraw_later(NOT_VALID); @@ -1672,8 +1681,8 @@ buflist_new(ffname, sfname, lnum, flags) init_var_dict(&buf->b_vars, &buf->b_bufvar); /* init b: variables */ #endif #ifdef FEAT_SYN_HL - hash_init(&buf->b_keywtab); - hash_init(&buf->b_keywtab_ic); + hash_init(&buf->b_s.b_keywtab); + hash_init(&buf->b_s.b_keywtab_ic); #endif buf->b_fname = buf->b_sfname; @@ -1772,11 +1781,11 @@ free_buf_options(buf, free_p_ff) clear_string_option(&buf->b_p_syn); #endif #ifdef FEAT_SPELL - clear_string_option(&buf->b_p_spc); - clear_string_option(&buf->b_p_spf); - vim_free(buf->b_cap_prog); - buf->b_cap_prog = NULL; - clear_string_option(&buf->b_p_spl); + clear_string_option(&buf->b_s.b_p_spc); + clear_string_option(&buf->b_s.b_p_spf); + vim_free(buf->b_s.b_cap_prog); + buf->b_s.b_cap_prog = NULL; + clear_string_option(&buf->b_s.b_p_spl); #endif #ifdef FEAT_SEARCHPATH clear_string_option(&buf->b_p_sua); diff --git a/src/diff.c b/src/diff.c index bf6254598..e733ccd45 100644 --- a/src/diff.c +++ b/src/diff.c @@ -1127,6 +1127,10 @@ diff_win_options(wp, addbuf) # endif wp->w_p_diff = TRUE; +#ifdef FEAT_CURSORBIND + /* Use cursorbind if it's available */ + wp->w_p_crb = TRUE; +#endif wp->w_p_scb = TRUE; wp->w_p_wrap = FALSE; # ifdef FEAT_FOLDING @@ -2473,6 +2477,77 @@ diff_move_to(dir, count) return OK; } +#if defined(FEAT_CURSORBIND) || defined(PROTO) + linenr_T +diff_get_corresponding_line(buf1, lnum1, buf2, lnum3) + buf_T *buf1; + linenr_T lnum1; + buf_T *buf2; + linenr_T lnum3; +{ + int idx1; + int idx2; + diff_T *dp; + int baseline = 0; + linenr_T lnum2; + + idx1 = diff_buf_idx(buf1); + idx2 = diff_buf_idx(buf2); + if (idx1 == DB_COUNT || idx2 == DB_COUNT || curtab->tp_first_diff == NULL) + return lnum1; + + if (curtab->tp_diff_invalid) + ex_diffupdate(NULL); /* update after a big change */ + + if (curtab->tp_first_diff == NULL) /* no diffs today */ + return lnum1; + + for (dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next) + { + if (dp->df_lnum[idx1] > lnum1) + { + lnum2 = lnum1 - baseline; + /* don't end up past the end of the file */ + if (lnum2 > buf2->b_ml.ml_line_count) + lnum2 = buf2->b_ml.ml_line_count; + + return lnum2; + } + else if ((dp->df_lnum[idx1] + dp->df_count[idx1]) > lnum1) + { + /* Inside the diffblock */ + baseline = lnum1 - dp->df_lnum[idx1]; + if (baseline > dp->df_count[idx2]) + baseline = dp->df_count[idx2]; + + return dp->df_lnum[idx2] + baseline; + } + else if ( (dp->df_lnum[idx1] == lnum1) + && (dp->df_count[idx1] == 0) + && (dp->df_lnum[idx2] <= lnum3) + && ((dp->df_lnum[idx2] + dp->df_count[idx2]) > lnum3)) + /* + * Special case: if the cursor is just after a zero-count + * block (i.e. all filler) and the target cursor is already + * inside the corresponding block, leave the target cursor + * unmoved. This makes repeated CTRL-W W operations work + * as expected. + */ + return lnum3; + baseline = (dp->df_lnum[idx1] + dp->df_count[idx1]) + - (dp->df_lnum[idx2] + dp->df_count[idx2]); + } + + /* If we get here then the cursor is after the last diff */ + lnum2 = lnum1 - baseline; + /* don't end up past the end of the file */ + if (lnum2 > buf2->b_ml.ml_line_count) + lnum2 = buf2->b_ml.ml_line_count; + + return lnum2; +} +#endif + #if defined(FEAT_FOLDING) || defined(PROTO) /* * For line "lnum" in the current window find the equivalent lnum in window diff --git a/src/edit.c b/src/edit.c index a6a28cc9a..9f7106165 100644 --- a/src/edit.c +++ b/src/edit.c @@ -698,6 +698,10 @@ edit(cmdchar, startln, count) do_check_scrollbind(TRUE); #endif +#ifdef FEAT_CURSORBIND + if (curwin->w_p_crb) + do_check_cursorbind(); +#endif update_curswant(); old_topline = curwin->w_topline; #ifdef FEAT_DIFF @@ -1277,7 +1281,7 @@ doESCkey: inserted_space = FALSE; break; -#if defined(FEAT_DIGRAPHS) || defined (FEAT_INS_EXPAND) +#if defined(FEAT_DIGRAPHS) || defined(FEAT_INS_EXPAND) case Ctrl_K: /* digraph or keyword completion */ # ifdef FEAT_INS_EXPAND if (ctrl_x_mode == CTRL_X_DICTIONARY) @@ -1470,7 +1474,7 @@ ins_redraw(ready) * highlighting is correct after making a change (e.g., inserting * a "(". The autocommand may also require a redraw, so it's done * again below, unfortunately. */ - if (syntax_present(curbuf) && must_redraw) + if (syntax_present(curwin) && must_redraw) update_screen(0); # endif apply_autocmds(EVENT_CURSORMOVEDI, NULL, NULL, FALSE, curbuf); @@ -2960,7 +2964,7 @@ ins_compl_dictionaries(dict_start, pat, flags, thesaurus) ptr = pat + 2; else ptr = pat; - spell_dump_compl(curbuf, ptr, regmatch.rm_ic, &dir, 0); + spell_dump_compl(ptr, regmatch.rm_ic, &dir, 0); } else # endif @@ -9119,6 +9123,9 @@ ins_s_right() ins_up(startcol) int startcol; /* when TRUE move to Insstart.col */ { +#ifdef FEAT_CONCEAL + linenr_T oldline = curwin->w_cursor.lnum; +#endif pos_T tpos; linenr_T old_topline = curwin->w_topline; #ifdef FEAT_DIFF @@ -9141,6 +9148,13 @@ ins_up(startcol) #ifdef FEAT_CINDENT can_cindent = TRUE; #endif +#ifdef FEAT_CONCEAL + if (curwin->w_p_conceal && oldline != curwin->w_cursor.lnum) + { + update_single_line(curwin, oldline); + update_single_line(curwin, curwin->w_cursor.lnum); + } +#endif } else vim_beep(); @@ -9182,6 +9196,10 @@ ins_pageup() ins_down(startcol) int startcol; /* when TRUE move to Insstart.col */ { +#ifdef FEAT_CONCEAL + linenr_T oldline = curwin->w_cursor.lnum; + linenr_T oldbotline = curwin->w_botline; +#endif pos_T tpos; linenr_T old_topline = curwin->w_topline; #ifdef FEAT_DIFF @@ -9204,6 +9222,16 @@ ins_down(startcol) #ifdef FEAT_CINDENT can_cindent = TRUE; #endif +#ifdef FEAT_CONCEAL + if (curwin->w_p_conceal && oldline != curwin->w_cursor.lnum) + { + update_single_line(curwin, oldline); + /* Don't do this if we've scrolled, the line is already + * drawn */ + if (oldbotline == curwin->w_botline) + update_single_line(curwin, curwin->w_cursor.lnum); + } +#endif } else vim_beep(); diff --git a/src/eval.c b/src/eval.c index e777d3255..ca9389fb3 100644 --- a/src/eval.c +++ b/src/eval.c @@ -3884,6 +3884,11 @@ get_user_var_name(xp, idx) ++hi; return cat_prefix_varname('w', hi->hi_key); } + if (wdone == ht->ht_used) + { + ++wdone; + return (char_u *)"w:ownsyntax"; + } #ifdef FEAT_WINDOWS /* t: variables */ @@ -9389,6 +9394,9 @@ f_cursor(argvars, rettv) typval_T *rettv; { long line, col; +#ifdef FEAT_CONCEAL + linenr_T oldline = curwin->w_cursor.lnum; +#endif #ifdef FEAT_VIRTUALEDIT long coladd = 0; #endif @@ -9438,6 +9446,13 @@ f_cursor(argvars, rettv) #endif curwin->w_set_curswant = TRUE; +#ifdef FEAT_CONCEAL + if (curwin->w_p_conceal && oldline != curwin->w_cursor.lnum) + { + update_single_line(curwin, oldline); + update_single_line(curwin, curwin->w_cursor.lnum); + } +#endif rettv->vval.v_number = 0; } @@ -11722,12 +11737,18 @@ f_has(argvars, rettv) #ifdef FEAT_COMMENTS "comments", #endif +#ifdef FEAT_CONCEAL + "conceal", +#endif #ifdef FEAT_CRYPT "cryptv", #endif #ifdef FEAT_CSCOPE "cscope", #endif +#ifdef FEAT_CURSORBIND + "cursorbind", +#endif #ifdef CURSOR_SHAPE "cursorshape", #endif @@ -12138,7 +12159,7 @@ f_has(argvars, rettv) #endif #ifdef FEAT_SYN_HL else if (STRICMP(name, "syntax_items") == 0) - n = syntax_present(curbuf); + n = syntax_present(curwin); #endif #if defined(WIN3264) else if (STRICMP(name, "win95") == 0) @@ -15103,6 +15124,15 @@ search_cmn(argvars, match_pos, flagsp) /* If 'n' flag is used: restore cursor position. */ if (flags & SP_NOMOVE) curwin->w_cursor = save_cursor; +#ifdef FEAT_CONCEAL + else if (curwin->w_p_conceal + && save_cursor.lnum != curwin->w_cursor.lnum) + { + curwin->w_set_curswant = TRUE; + update_single_line(curwin, save_cursor.lnum); + update_single_line(curwin, curwin->w_cursor.lnum); + } +#endif else curwin->w_set_curswant = TRUE; theend: @@ -16329,7 +16359,7 @@ f_spellbadword(argvars, rettv) if (len != 0) word = ml_get_cursor(); } - else if (curwin->w_p_spell && *curbuf->b_p_spl != NUL) + else if (curwin->w_p_spell && *curbuf->b_s.b_p_spl != NUL) { char_u *str = get_tv_string_chk(&argvars[0]); int capcol = -1; @@ -16382,7 +16412,7 @@ f_spellsuggest(argvars, rettv) return; #ifdef FEAT_SPELL - if (curwin->w_p_spell && *curbuf->b_p_spl != NUL) + if (curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL) { str = get_tv_string(&argvars[0]); if (argvars[1].v_type != VAR_UNKNOWN) @@ -18728,6 +18758,18 @@ get_var_tv(name, len, rettv, verbose) tv = &atv; } + if (STRCMP(name, "w:ownsyntax") == 0) + { + atv.v_type = VAR_NUMBER; +#ifdef FEAT_SYN_HL + atv.vval.v_number = (curwin->w_s != &curwin->w_buffer->b_s) ? 1 : 0; +#else + atv.vval.v_number = 0; +#endif + tv = &atv; + } + + /* * Check for user-defined variables. */ diff --git a/src/ex_cmds.c b/src/ex_cmds.c index 2df5a4ae8..f05a0656d 100644 --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -3411,6 +3411,14 @@ do_ecmd(fnum, ffname, sfname, eap, newlnum, flags, oldwin) else #endif { +#ifdef FEAT_SYN_HL + /* + * <VN> We could instead free the synblock + * and re-attach to buffer, perhaps. + */ + if (curwin->w_s == &(curwin->w_buffer->b_s)) + curwin->w_s = &(buf->b_s); +#endif curwin->w_buffer = buf; curbuf = buf; ++curbuf->b_nwindows; @@ -3717,8 +3725,8 @@ do_ecmd(fnum, ffname, sfname, eap, newlnum, flags, oldwin) #ifdef FEAT_SPELL /* If the window options were changed may need to set the spell language. * Can only do this after the buffer has been properly setup. */ - if (did_get_winopts && curwin->w_p_spell && *curbuf->b_p_spl != NUL) - (void)did_set_spelllang(curbuf); + if (did_get_winopts && curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL) + (void)did_set_spelllang(curwin); #endif if (command == NULL) @@ -5963,7 +5971,7 @@ fix_help_buffer() set_option_value((char_u *)"ft", 0L, (char_u *)"help", OPT_LOCAL); #ifdef FEAT_SYN_HL - if (!syntax_present(curbuf)) + if (!syntax_present(curwin)) #endif { for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum) diff --git a/src/ex_cmds.h b/src/ex_cmds.h index f41e0f449..4e0e16918 100644 --- a/src/ex_cmds.h +++ b/src/ex_cmds.h @@ -677,6 +677,8 @@ EX(CMD_ounmap, "ounmap", ex_unmap, EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN), EX(CMD_ounmenu, "ounmenu", ex_menu, EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN), +EX(CMD_ownsyntax, "ownsyntax", ex_ownsyntax, + EXTRA|NOTRLCOM|SBOXOK|CMDWIN), EX(CMD_print, "print", ex_print, RANGE|WHOLEFOLD|COUNT|EXFLAGS|TRLBAR|CMDWIN|SBOXOK), EX(CMD_pclose, "pclose", ex_pclose, diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c index e5ce640e2..f07bb4ce6 100644 --- a/src/ex_cmds2.c +++ b/src/ex_cmds2.c @@ -2824,7 +2824,7 @@ struct source_cookie FILE *fp; /* opened file for sourcing */ char_u *nextline; /* if not NULL: line that was read ahead */ int finished; /* ":finish" used */ -#if defined (USE_CRNL) || defined (USE_CR) +#if defined(USE_CRNL) || defined(USE_CR) int fileformat; /* EOL_UNKNOWN, EOL_UNIX or EOL_DOS */ int error; /* TRUE if LF found after CR-LF */ #endif diff --git a/src/ex_docmd.c b/src/ex_docmd.c index c6d0b40ec..96a3a872f 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -235,6 +235,7 @@ static void ex_popup __ARGS((exarg_T *eap)); #endif #ifndef FEAT_SYN_HL # define ex_syntax ex_ni +# define ex_ownsyntax ex_ni #endif #ifndef FEAT_SPELL # define ex_spell ex_ni diff --git a/src/feature.h b/src/feature.h index 4f35280b7..5bca7c7d7 100644 --- a/src/feature.h +++ b/src/feature.h @@ -535,10 +535,17 @@ #endif /* + * +conceal 'conceal' option. Needs syntax highlighting + * as this is how the concealed text is defined. + */ +#if defined(FEAT_BIG) && defined(FEAT_SYN_HL) +# define FEAT_CONCEAL +#endif + +/* * +spell spell checking * - * Disabled for EBCDIC: - * Doesn't work (SIGSEGV). + * Disabled for EBCDIC: * Doesn't work (SIGSEGV). */ #if (defined(FEAT_NORMAL) || defined(PROTO)) && !defined(EBCDIC) # define FEAT_SPELL @@ -730,6 +737,13 @@ #endif /* + * +cursorbind synchronization of split windows + */ +#if defined(FEAT_NORMAL) && defined(FEAT_WINDOWS) +# define FEAT_CURSORBIND +#endif + +/* * +menu ":menu" command */ #ifdef FEAT_NORMAL @@ -770,7 +784,8 @@ && (defined(FEAT_GUI_GTK) \ || (defined(FEAT_GUI_MOTIF) && defined(HAVE_XM_NOTEBOOK_H)) \ || defined(FEAT_GUI_MAC) \ - || (defined(FEAT_GUI_MSWIN) && (!defined(_MSC_VER) || _MSC_VER > 1020))) + || (defined(FEAT_GUI_MSWIN) && !defined(WIN16) \ + && (!defined(_MSC_VER) || _MSC_VER > 1020))) # define FEAT_GUI_TABLINE #endif diff --git a/src/globals.h b/src/globals.h index b085bcb73..f4ec25713 100644 --- a/src/globals.h +++ b/src/globals.h @@ -1151,6 +1151,9 @@ EXTERN int lcs_nbsp INIT(= NUL); EXTERN int lcs_tab1 INIT(= NUL); EXTERN int lcs_tab2 INIT(= NUL); EXTERN int lcs_trail INIT(= NUL); +#ifdef FEAT_CONCEAL +EXTERN int lcs_conceal INIT(= '-'); +#endif #if defined(FEAT_WINDOWS) || defined(FEAT_WILDMENU) || defined(FEAT_STL_OPT) \ || defined(FEAT_FOLDING) @@ -1412,7 +1415,7 @@ EXTERN char_u e_invexpr2[] INIT(= N_("E15: Invalid expression: %s")); #endif EXTERN char_u e_invrange[] INIT(= N_("E16: Invalid range")); EXTERN char_u e_invcmd[] INIT(= N_("E476: Invalid command")); -#if defined(UNIX) || defined(FEAT_SYN_HL) +#if defined(UNIX) || defined(FEAT_SYN_HL) || defined(FEAT_SPELL) EXTERN char_u e_isadir2[] INIT(= N_("E17: \"%s\" is a directory")); #endif #ifdef FEAT_LIBCALL diff --git a/src/hardcopy.c b/src/hardcopy.c index e70390d44..744a2a2f1 100644 --- a/src/hardcopy.c +++ b/src/hardcopy.c @@ -616,7 +616,7 @@ ex_hardcopy(eap) else settings.modec = 't'; - if (!syntax_present(curbuf)) + if (!syntax_present(curwin)) settings.do_syntax = FALSE; else if (printer_opts[OPT_PRINT_SYNTAX].present && TOLOWER_ASC(printer_opts[OPT_PRINT_SYNTAX].string[0]) != 'a') diff --git a/src/if_python.c b/src/if_python.c index 4f23ffa8b..1b0780158 100644 --- a/src/if_python.c +++ b/src/if_python.c @@ -26,7 +26,7 @@ # undef _POSIX_THREADS #endif -#if defined(_WIN32) && defined (HAVE_FCNTL_H) +#if defined(_WIN32) && defined(HAVE_FCNTL_H) # undef HAVE_FCNTL_H #endif diff --git a/src/integration.c b/src/integration.c index 4b1492c63..88962755b 100644 --- a/src/integration.c +++ b/src/integration.c @@ -86,6 +86,7 @@ static void process_menuItem(char *); static void process_toolbarButton(char *); static void workshop_set_option_first(char *name, char *value); +static size_t dummy; /* to ignore return value of write() */ #define CMDBUFSIZ 2048 @@ -183,7 +184,7 @@ messageFromEserve(XtPointer clientData UNUSED, ackNum = atoi(&cmd[4]); vim_snprintf(buf, sizeof(buf), NOCATGETS("ack %d\n"), ackNum); - (void)write(sd, buf, strlen(buf)); + dummy = write(sd, buf, strlen(buf)); } else if (strncmp(cmd, NOCATGETS("addMarkType "), 12) == 0) { int idx; @@ -280,7 +281,7 @@ messageFromEserve(XtPointer clientData UNUSED, vim_snprintf(buf, sizeof(buf), NOCATGETS("markLine %s %d %d\n"), file, markid, line); - (void)write(sd, buf, strlen(buf)); + dummy = write(sd, buf, strlen(buf)); } else if (cmd[1] == 'o' && cmd[4] == 'L' && strncmp(cmd, NOCATGETS("gotoLine "), 9) == 0) { char *file; @@ -729,10 +730,10 @@ void workshop_connect(XtAppContext context) workshop_get_editor_name(), PROTOCOL_VERSION, workshop_get_editor_version()); - (void)write(sd, buf, strlen(buf)); + dummy = write(sd, buf, strlen(buf)); vim_snprintf(buf, sizeof(buf), NOCATGETS("ack 1\n")); - (void)write(sd, buf, strlen(buf)); + dummy = write(sd, buf, strlen(buf)); } void workshop_disconnect() @@ -1059,7 +1060,7 @@ void workshop_file_closed(char *filename) char buffer[2*MAXPATHLEN]; vim_snprintf(buffer, sizeof(buffer), NOCATGETS("deletedFile %s\n"), filename); - (void)write(sd, buffer, strlen(buffer)); + dummy = write(sd, buffer, strlen(buffer)); } #endif @@ -1068,7 +1069,7 @@ void workshop_file_closed_lineno(char *filename, int lineno) char buffer[2*MAXPATHLEN]; vim_snprintf(buffer, sizeof(buffer), NOCATGETS("deletedFile %s %d\n"), filename, lineno); - (void)write(sd, buffer, strlen(buffer)); + dummy = write(sd, buffer, strlen(buffer)); } void workshop_file_opened(char *filename, int readOnly) @@ -1076,7 +1077,7 @@ void workshop_file_opened(char *filename, int readOnly) char buffer[2*MAXPATHLEN]; vim_snprintf(buffer, sizeof(buffer), NOCATGETS("loadedFile %s %d\n"), filename, readOnly); - (void)write(sd, buffer, strlen(buffer)); + dummy = write(sd, buffer, strlen(buffer)); } @@ -1085,7 +1086,7 @@ void workshop_file_saved(char *filename) char buffer[2*MAXPATHLEN]; vim_snprintf(buffer, sizeof(buffer), NOCATGETS("savedFile %s\n"), filename); - (void)write(sd, buffer, strlen(buffer)); + dummy = write(sd, buffer, strlen(buffer)); /* Let editor report any moved marks that the eserve client * should deal with (for example, moving location-based breakpoints) */ @@ -1098,7 +1099,7 @@ void workshop_file_modified(char *filename) char buffer[2*MAXPATHLEN]; vim_snprintf(buffer, sizeof(buffer), NOCATGETS("modifiedFile %s\n"), filename); - (void)write(sd, buffer, strlen(buffer)); + dummy = write(sd, buffer, strlen(buffer)); } void workshop_move_mark(char *filename, int markId, int newLineno) @@ -1106,7 +1107,7 @@ void workshop_move_mark(char *filename, int markId, int newLineno) char buffer[2*MAXPATHLEN]; vim_snprintf(buffer, sizeof(buffer), NOCATGETS("moveMark %s %d %d\n"), filename, markId, newLineno); - (void)write(sd, buffer, strlen(buffer)); + dummy = write(sd, buffer, strlen(buffer)); } #endif @@ -1119,7 +1120,7 @@ void workshop_frame_moved(int new_x, int new_y, int new_w, int new_h) vim_snprintf(buffer, sizeof(buffer), NOCATGETS("frameAt %d %d %d %d\n"), new_x, new_y, new_w, new_h); - (void)write(sd, buffer, strlen(buffer)); + dummy = write(sd, buffer, strlen(buffer)); } } @@ -1179,7 +1180,7 @@ void workshop_perform_verb(char *verb, void *clientData) selEndLine, selEndCol, selLength, selection); - (void)write(sd, buf, strlen(buf)); + dummy = write(sd, buf, strlen(buf)); if (*selection) { free(selection); } @@ -1190,7 +1191,7 @@ void workshop_perform_verb(char *verb, void *clientData) #if defined(NOHANDS_SUPPORT_FUNCTIONS) || defined(FEAT_BEVAL) void workshop_send_message(char *buf) { - (void)write(sd, buf, strlen(buf)); + dummy = write(sd, buf, strlen(buf)); } #endif diff --git a/src/mbyte.c b/src/mbyte.c index e6275899c..e4df00ad5 100644 --- a/src/mbyte.c +++ b/src/mbyte.c @@ -5222,7 +5222,7 @@ im_set_active(active) /* If 'imdisable' is set, XIM is never active. */ if (p_imdisable) active = FALSE; -#if !defined (FEAT_GUI_GTK) +#if !defined(FEAT_GUI_GTK) else if (input_style & XIMPreeditPosition) /* There is a problem in switching XIM off when preediting is used, * and it is not clear how this can be solved. For now, keep XIM on diff --git a/src/move.c b/src/move.c index cdc8c1479..3dd45c00d 100644 --- a/src/move.c +++ b/src/move.c @@ -2884,3 +2884,68 @@ halfpage(flag, Prenum) beginline(BL_SOL | BL_FIX); redraw_later(VALID); } + +#if defined(FEAT_CURSORBIND) || defined(PROTO) + void +do_check_cursorbind() +{ + linenr_T line = curwin->w_cursor.lnum; + colnr_T col = curwin->w_cursor.col; + win_T *old_curwin = curwin; + buf_T *old_curbuf = curbuf; +# ifdef FEAT_VISUAL + int old_VIsual_select = VIsual_select; + int old_VIsual_active = VIsual_active; +# endif + + /* + * loop through the cursorbound windows + */ +# ifdef FEAT_VISUAL + VIsual_select = VIsual_active = 0; +# endif + for (curwin = firstwin; curwin; curwin = curwin->w_next) + { + curbuf = curwin->w_buffer; + /* skip original window and windows with 'noscrollbind' */ + if (curwin != old_curwin && curwin->w_p_crb) + { +# ifdef FEAT_DIFF + if (curwin->w_p_diff) + curwin->w_cursor.lnum + = diff_get_corresponding_line(old_curbuf, + line, + curbuf, + curwin->w_cursor.lnum); + else +# endif + curwin->w_cursor.lnum = line; + curwin->w_cursor.col = col; + + /* Make sure the cursor is in a valid position. */ + check_cursor(); +# ifdef FEAT_MBYTE + /* Correct cursor for multi-byte character. */ + if (has_mbyte) + mb_adjust_cursor(); +# endif + + redraw_later(VALID); + update_topline(); +# ifdef FEAT_WINDOWS + curwin->w_redr_status = TRUE; +# endif + } + } + + /* + * reset current-window + */ +# ifdef FEAT_VISUAL + VIsual_select = old_VIsual_select; + VIsual_active = old_VIsual_active; +# endif + curwin = old_curwin; + curbuf = old_curbuf; +} +#endif /* FEAT_CURSORBIND */ diff --git a/src/normal.c b/src/normal.c index 3e8a492ec..002430d71 100644 --- a/src/normal.c +++ b/src/normal.c @@ -1335,6 +1335,14 @@ normal_end: } #endif +#ifdef FEAT_CURSORBIND + if (curwin->w_p_crb && toplevel) + { + validate_cursor(); /* may need to update w_leftcol */ + do_check_cursorbind(); + } +#endif + /* * May restart edit(), if we got here with CTRL-O in Insert mode (but not * if still inside a mapping that started in Visual mode). @@ -2290,6 +2298,9 @@ do_mouse(oap, c, dir, count, fixindent) int old_mode = VIsual_mode; #endif int regname; +#ifdef FEAT_CONCEAL + linenr_T oldline = curwin->w_cursor.lnum; +#endif #if defined(FEAT_FOLDING) save_cursor = curwin->w_cursor; @@ -2762,6 +2773,14 @@ do_mouse(oap, c, dir, count, fixindent) curwin->w_cursor = save_cursor; } #endif +#ifdef FEAT_CONCEAL + if (curwin->w_p_conceal && moved + && (old_curwin != curwin || oldline != curwin->w_cursor.lnum)) + { + update_single_line(old_curwin, oldline); + update_single_line(curwin, curwin->w_cursor.lnum); + } +#endif #if defined(FEAT_CLIPBOARD) && defined(FEAT_CMDWIN) if ((jump_flags & IN_OTHER_WIN) && !VIsual_active && clip_star.available) @@ -5302,7 +5321,7 @@ nv_clear(cap) #endif #ifdef FEAT_SYN_HL /* Clear all syntax states to force resyncing. */ - syn_stack_free_all(curbuf); + syn_stack_free_all(curwin->w_s); #endif redraw_later(CLEAR); } @@ -5694,6 +5713,9 @@ nv_scroll(cap) linenr_T lnum; #endif int half; +#ifdef FEAT_CONCEAL + linenr_T oldline = curwin->w_cursor.lnum; +#endif cap->oap->motion_type = MLINE; setpcmark(); @@ -5781,6 +5803,13 @@ nv_scroll(cap) cursor_correct(); /* correct for 'so' */ beginline(BL_SOL | BL_FIX); +#ifdef FEAT_CONCEAL + if (curwin->w_p_conceal && oldline != curwin->w_cursor.lnum) + { + update_single_line(curwin, oldline); + update_single_line(curwin, curwin->w_cursor.lnum); + } +#endif } /* @@ -5796,6 +5825,9 @@ nv_right(cap) #else # define PAST_LINE 0 #endif +#ifdef FEAT_CONCEAL + linenr_T oldline = curwin->w_cursor.lnum; +#endif if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) { @@ -5900,6 +5932,13 @@ nv_right(cap) && cap->oap->op_type == OP_NOP) foldOpenCursor(); #endif +#ifdef FEAT_CONCEAL + if (curwin->w_p_conceal && oldline != curwin->w_cursor.lnum) + { + update_single_line(curwin, oldline); + update_single_line(curwin, curwin->w_cursor.lnum); + } +#endif } /* @@ -5912,6 +5951,9 @@ nv_left(cap) cmdarg_T *cap; { long n; +#ifdef FEAT_CONCEAL + linenr_T oldline = curwin->w_cursor.lnum; +#endif if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) { @@ -5970,6 +6012,13 @@ nv_left(cap) && cap->oap->op_type == OP_NOP) foldOpenCursor(); #endif +#ifdef FEAT_CONCEAL + if (curwin->w_p_conceal && oldline != curwin->w_cursor.lnum) + { + update_single_line(curwin, oldline); + update_single_line(curwin, curwin->w_cursor.lnum); + } +#endif } /* @@ -5988,11 +6037,21 @@ nv_up(cap) } else { +#ifdef FEAT_CONCEAL + linenr_T oldline = curwin->w_cursor.lnum; +#endif cap->oap->motion_type = MLINE; if (cursor_up(cap->count1, cap->oap->op_type == OP_NOP) == FAIL) clearopbeep(cap->oap); else if (cap->arg) beginline(BL_WHITE | BL_FIX); +#ifdef FEAT_CONCEAL + if (curwin->w_p_conceal && oldline != curwin->w_cursor.lnum) + { + update_single_line(curwin, oldline); + update_single_line(curwin, curwin->w_cursor.lnum); + } +#endif } } @@ -6021,6 +6080,10 @@ nv_down(cap) else #endif { +#ifdef FEAT_CONCEAL + linenr_T oldline = curwin->w_cursor.lnum; + linenr_T oldbotline = curwin->w_botline; +#endif #ifdef FEAT_CMDWIN /* In the cmdline window a <CR> executes the command. */ if (cmdwin_type != 0 && cap->cmdchar == CAR) @@ -6033,6 +6096,16 @@ nv_down(cap) clearopbeep(cap->oap); else if (cap->arg) beginline(BL_WHITE | BL_FIX); +#ifdef FEAT_CONCEAL + if (curwin->w_p_conceal && oldline != curwin->w_cursor.lnum) + { + update_single_line(curwin, oldline); + /* Don't do this if we've scrolled, the line is already + * drawn */ + if (oldbotline == curwin->w_botline) + update_single_line(curwin, curwin->w_cursor.lnum); + } +#endif } } } @@ -8197,6 +8270,10 @@ nv_g_cmd(cap) n_opencmd(cap) cmdarg_T *cap; { +#ifdef FEAT_CONCEAL + linenr_T oldline = curwin->w_cursor.lnum; +#endif + if (!checkclearopq(cap->oap)) { #ifdef FEAT_FOLDING @@ -8220,6 +8297,10 @@ n_opencmd(cap) #endif 0, 0)) { +#ifdef FEAT_CONCEAL + if (curwin->w_p_conceal && oldline != curwin->w_cursor.lnum) + update_single_line(curwin, oldline); +#endif /* When '#' is in 'cpoptions' ignore the count. */ if (vim_strchr(p_cpo, CPO_HASH) != NULL) cap->count1 = 1; @@ -8424,6 +8505,9 @@ nv_pipe(cap) nv_bck_word(cap) cmdarg_T *cap; { +#ifdef FEAT_CONCEAL + linenr_T oldline = curwin->w_cursor.lnum; +#endif cap->oap->motion_type = MCHAR; cap->oap->inclusive = FALSE; curwin->w_set_curswant = TRUE; @@ -8433,6 +8517,13 @@ nv_bck_word(cap) else if ((fdo_flags & FDO_HOR) && KeyTyped && cap->oap->op_type == OP_NOP) foldOpenCursor(); #endif +#ifdef FEAT_CONCEAL + if (curwin->w_p_conceal && oldline != curwin->w_cursor.lnum) + { + update_single_line(curwin, oldline); + update_single_line(curwin, curwin->w_cursor.lnum); + } +#endif } /* @@ -8447,6 +8538,9 @@ nv_wordcmd(cap) int word_end; int flag = FALSE; pos_T startpos = curwin->w_cursor; +#ifdef FEAT_CONCEAL + linenr_T oldline = startpos.lnum; +#endif /* * Set inclusive for the "E" and "e" command. @@ -8524,6 +8618,13 @@ nv_wordcmd(cap) foldOpenCursor(); #endif } +#ifdef FEAT_CONCEAL + if (curwin->w_p_conceal && oldline != curwin->w_cursor.lnum) + { + update_single_line(curwin, oldline); + update_single_line(curwin, curwin->w_cursor.lnum); + } +#endif } /* @@ -8686,6 +8787,10 @@ nv_goto(cap) if ((fdo_flags & FDO_JUMP) && KeyTyped && cap->oap->op_type == OP_NOP) foldOpenCursor(); #endif +#ifdef FEAT_CONCEAL + if (curwin->w_p_conceal) + changed_window_setting(); +#endif } /* @@ -9111,6 +9216,9 @@ nv_put(cap) int empty = FALSE; int was_visual = FALSE; #endif +#ifdef FEAT_CONCEAL + linenr_T oldline = curwin->w_cursor.lnum; +#endif int dir; int flags = 0; @@ -9230,6 +9338,13 @@ nv_put(cap) } #endif auto_format(FALSE, TRUE); +#ifdef FEAT_CONCEAL + if (curwin->w_p_conceal && oldline != curwin->w_cursor.lnum) + { + update_single_line(curwin, oldline); + update_single_line(curwin, curwin->w_cursor.lnum); + } +#endif } } diff --git a/src/option.c b/src/option.c index b5392dd12..d06381cb8 100644 --- a/src/option.c +++ b/src/option.c @@ -243,7 +243,12 @@ # define PV_WFW OPT_WIN(WV_WFW) #endif #define PV_WRAP OPT_WIN(WV_WRAP) - +#ifdef FEAT_CURSORBIND +# define PV_CRBIND OPT_WIN(WV_CRBIND) +#endif +#ifdef FEAT_CONCEAL +# define PV_CONCEAL OPT_WIN(WV_CONCEAL) +#endif /* WV_ and BV_ values get typecasted to this for the "indir" field */ typedef enum @@ -460,8 +465,8 @@ struct vimoption * possible when compiling with few features. */ #if defined(FEAT_DIFF) || defined(FEAT_FOLDING) || defined(FEAT_SPELL) \ || defined(FEAT_VERTSPLIT) || defined(FEAT_CLIPBOARD) \ - || defined(FEAT_INS_EXPAND) || defined(FEAT_SYN_HL) -# define HIGHLIGHT_INIT "8:SpecialKey,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn,B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel,x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill,!:CursorColumn,.:CursorLine" + || defined(FEAT_INS_EXPAND) || defined(FEAT_SYN_HL) || defined(FEAT_CONCEAL) +# define HIGHLIGHT_INIT "8:SpecialKey,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn,-:Conceal,B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel,x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill,!:CursorColumn,.:CursorLine" #else # define HIGHLIGHT_INIT "8:SpecialKey,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,r:Question,s:StatusLine,S:StatusLineNC,t:Title,v:Visual,w:WarningMsg,W:WildMenu,>:SignColumn,*:TabLine,#:TabLineSel,_:TabLineFill" #endif @@ -805,6 +810,14 @@ static struct vimoption {(char_u *)0L, (char_u *)0L} #endif SCRIPTID_INIT}, + {"conceallevel","conc", P_NUM|P_RWIN|P_VI_DEF, +#ifdef FEAT_CONCEAL + (char_u *)VAR_WIN, PV_CONCEAL, +#else + (char_u *)NULL, PV_NONE, +#endif + {(char_u *)0L, (char_u *)0L} + SCRIPTID_INIT}, {"completefunc", "cfu", P_STRING|P_ALLOCED|P_VI_DEF|P_SECURE, #ifdef FEAT_COMPL_FUNC (char_u *)&p_cfu, PV_CFU, @@ -897,6 +910,13 @@ static struct vimoption (char_u *)NULL, PV_NONE, #endif {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, + {"cursorbind", "crb", P_BOOL|P_VI_DEF, +#ifdef FEAT_CURSORBIND + (char_u *)VAR_WIN, PV_CRBIND, +#else + (char_u *)NULL, PV_NONE, +#endif + {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, {"cursorcolumn", "cuc", P_BOOL|P_VI_DEF|P_RWIN, #ifdef FEAT_SYN_HL (char_u *)VAR_WIN, PV_CUC, @@ -2959,7 +2979,7 @@ static char_u *set_chars_option __ARGS((char_u **varp)); static char_u *check_clipboard_option __ARGS((void)); #endif #ifdef FEAT_SPELL -static char_u *compile_cap_prog __ARGS((buf_T *buf)); +static char_u *compile_cap_prog __ARGS((synblock_T *synblock)); #endif #ifdef FEAT_EVAL static void set_option_scriptID_idx __ARGS((int opt_idx, int opt_flags, int id)); @@ -5127,7 +5147,7 @@ didset_options() #ifdef FEAT_SPELL (void)spell_check_msm(); (void)spell_check_sps(); - (void)compile_cap_prog(curbuf); + (void)compile_cap_prog(curwin->w_s); #endif #if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_W32) (void)opt_strings_flags(p_toolbar, p_toolbar_values, &toolbar_flags, TRUE); @@ -5208,9 +5228,9 @@ check_buf_options(buf) check_string_option(&buf->b_p_syn); #endif #ifdef FEAT_SPELL - check_string_option(&buf->b_p_spc); - check_string_option(&buf->b_p_spf); - check_string_option(&buf->b_p_spl); + check_string_option(&buf->b_s.b_p_spc); + check_string_option(&buf->b_s.b_p_spf); + check_string_option(&buf->b_s.b_p_spl); #endif #ifdef FEAT_SEARCHPATH check_string_option(&buf->b_p_sua); @@ -6407,15 +6427,15 @@ did_set_string_option(opt_idx, varp, new_value_alloced, oldval, errbuf, #ifdef FEAT_SPELL /* When 'spelllang' or 'spellfile' is set and there is a window for this * buffer in which 'spell' is set load the wordlists. */ - else if (varp == &(curbuf->b_p_spl) || varp == &(curbuf->b_p_spf)) + else if (varp == &(curbuf->b_s.b_p_spl) || varp == &(curbuf->b_s.b_p_spf)) { win_T *wp; int l; - if (varp == &(curbuf->b_p_spf)) + if (varp == &(curbuf->b_s.b_p_spf)) { - l = (int)STRLEN(curbuf->b_p_spf); - if (l > 0 && (l < 4 || STRCMP(curbuf->b_p_spf + l - 4, + l = (int)STRLEN(curbuf->b_s.b_p_spf); + if (l > 0 && (l < 4 || STRCMP(curbuf->b_s.b_p_spf + l - 4, ".add") != 0)) errmsg = e_invarg; } @@ -6425,7 +6445,7 @@ did_set_string_option(opt_idx, varp, new_value_alloced, oldval, errbuf, FOR_ALL_WINDOWS(wp) if (wp->w_buffer == curbuf && wp->w_p_spell) { - errmsg = did_set_spelllang(curbuf); + errmsg = did_set_spelllang(wp); # ifdef FEAT_WINDOWS break; # endif @@ -6433,9 +6453,9 @@ did_set_string_option(opt_idx, varp, new_value_alloced, oldval, errbuf, } } /* When 'spellcapcheck' is set compile the regexp program. */ - else if (varp == &(curbuf->b_p_spc)) + else if (varp == &(curwin->w_s->b_p_spc)) { - errmsg = compile_cap_prog(curbuf); + errmsg = compile_cap_prog(curwin->w_s); } /* 'spellsuggest' */ else if (varp == &p_sps) @@ -6843,7 +6863,7 @@ did_set_string_option(opt_idx, varp, new_value_alloced, oldval, errbuf, } #endif #ifdef FEAT_SPELL - if (varp == &(curbuf->b_p_spl)) + if (varp == &(curwin->w_s->b_p_spl)) { char_u fname[200]; @@ -6853,11 +6873,11 @@ did_set_string_option(opt_idx, varp, new_value_alloced, oldval, errbuf, * Use the first name in 'spelllang' up to '_region' or * '.encoding'. */ - for (p = curbuf->b_p_spl; *p != NUL; ++p) + for (p = curwin->w_s->b_p_spl; *p != NUL; ++p) if (vim_strchr((char_u *)"_.,", *p) != NULL) break; vim_snprintf((char *)fname, 200, "spell/%.*s.vim", - (int)(p - curbuf->b_p_spl), curbuf->b_p_spl); + (int)(p - curwin->w_s->b_p_spl), curwin->w_s->b_p_spl); source_runtime(fname, TRUE); } #endif @@ -6920,6 +6940,11 @@ set_chars_option(varp) {&lcs_prec, "precedes"}, {&lcs_tab2, "tab"}, {&lcs_trail, "trail"}, +#ifdef FEAT_CONCEAL + {&lcs_conceal, "conceal"}, +#else + {NULL, "conceal"}, +#endif }; struct charstab *tab; @@ -6941,12 +6966,13 @@ set_chars_option(varp) /* first round: check for valid value, second round: assign values */ for (round = 0; round <= 1; ++round) { - if (round) + if (round > 0) { /* After checking that the value is valid: set defaults: space for * 'fillchars', NUL for 'listchars' */ for (i = 0; i < entries; ++i) - *(tab[i].cp) = (varp == &p_lcs ? NUL : ' '); + if (tab[i].cp != NULL) + *(tab[i].cp) = (varp == &p_lcs ? NUL : ' '); if (varp == &p_lcs) lcs_tab1 = NUL; #if defined(FEAT_WINDOWS) || defined(FEAT_FOLDING) @@ -6993,7 +7019,7 @@ set_chars_option(varp) lcs_tab1 = c1; lcs_tab2 = c2; } - else + else if (tab[i].cp != NULL) *(tab[i].cp) = c1; } @@ -7170,24 +7196,24 @@ check_clipboard_option() * Return error message when failed, NULL when OK. */ static char_u * -compile_cap_prog(buf) - buf_T *buf; +compile_cap_prog(synblock) + synblock_T *synblock; { - regprog_T *rp = buf->b_cap_prog; + regprog_T *rp = synblock->b_cap_prog; char_u *re; - if (*buf->b_p_spc == NUL) - buf->b_cap_prog = NULL; + if (*synblock->b_p_spc == NUL) + synblock->b_cap_prog = NULL; else { /* Prepend a ^ so that we only match at one column */ - re = concat_str((char_u *)"^", buf->b_p_spc); + re = concat_str((char_u *)"^", synblock->b_p_spc); if (re != NULL) { - buf->b_cap_prog = vim_regcomp(re, RE_MAGIC); - if (buf->b_cap_prog == NULL) + synblock->b_cap_prog = vim_regcomp(re, RE_MAGIC); + if (synblock->b_cap_prog == NULL) { - buf->b_cap_prog = rp; /* restore the previous program */ + synblock->b_cap_prog = rp; /* restore the previous program */ return e_invarg; } vim_free(re); @@ -7588,8 +7614,7 @@ set_bool_option(opt_idx, varp, value, opt_flags) { if (curwin->w_p_spell) { - char_u *errmsg = did_set_spelllang(curbuf); - + char_u *errmsg = did_set_spelllang(curwin); if (errmsg != NULL) EMSG(_(errmsg)); } @@ -8089,6 +8114,21 @@ set_num_option(opt_idx, varp, value, errbuf, errbuflen, opt_flags) if (p_uc && !old_value) ml_open_files(); } +#ifdef FEAT_CONCEAL + else if (pp == (long *)&curwin->w_p_conceal) + { + if (curwin->w_p_conceal < 0) + { + errmsg = e_positive; + curwin->w_p_conceal = 0; + } + else if (curwin->w_p_conceal > 3) + { + errmsg = e_invarg; + curwin->w_p_conceal = 3; + } + } +#endif #ifdef MZSCHEME_GUI_THREADS else if (pp == &p_mzq) mzvim_reset_timer(); @@ -9327,6 +9367,12 @@ get_varp(p) #ifdef FEAT_SCROLLBIND case PV_SCBIND: return (char_u *)&(curwin->w_p_scb); #endif +#ifdef FEAT_CURSORBIND + case PV_CRBIND: return (char_u *)&(curwin->w_p_crb); +#endif +#ifdef FEAT_CONCEAL + case PV_CONCEAL: return (char_u *)&(curwin->w_p_conceal); +#endif case PV_AI: return (char_u *)&(curbuf->b_p_ai); case PV_BIN: return (char_u *)&(curbuf->b_p_bin); @@ -9425,9 +9471,9 @@ get_varp(p) case PV_SYN: return (char_u *)&(curbuf->b_p_syn); #endif #ifdef FEAT_SPELL - case PV_SPC: return (char_u *)&(curbuf->b_p_spc); - case PV_SPF: return (char_u *)&(curbuf->b_p_spf); - case PV_SPL: return (char_u *)&(curbuf->b_p_spl); + case PV_SPC: return (char_u *)&(curwin->w_s->b_p_spc); + case PV_SPF: return (char_u *)&(curwin->w_s->b_p_spf); + case PV_SPL: return (char_u *)&(curwin->w_s->b_p_spl); #endif case PV_SW: return (char_u *)&(curbuf->b_p_sw); case PV_TS: return (char_u *)&(curbuf->b_p_ts); @@ -9750,10 +9796,10 @@ buf_copy_options(buf, flags) buf->b_p_smc = p_smc; #endif #ifdef FEAT_SPELL - buf->b_p_spc = vim_strsave(p_spc); - (void)compile_cap_prog(buf); - buf->b_p_spf = vim_strsave(p_spf); - buf->b_p_spl = vim_strsave(p_spl); + buf->b_s.b_p_spc = vim_strsave(p_spf); + (void)compile_cap_prog(&buf->b_s); + buf->b_s.b_p_spf = vim_strsave(p_spf); + buf->b_s.b_p_spl = vim_strsave(p_spl); #endif #if defined(FEAT_CINDENT) && defined(FEAT_EVAL) buf->b_p_inde = vim_strsave(p_inde); diff --git a/src/option.h b/src/option.h index f0ebc8de7..489bdb2a9 100644 --- a/src/option.h +++ b/src/option.h @@ -1021,6 +1021,12 @@ enum #ifdef FEAT_ARABIC , WV_ARAB #endif +#ifdef FEAT_CONCEAL + , WV_CONCEAL +#endif +#ifdef FEAT_CURSORBIND + , WV_CRBIND +#endif #ifdef FEAT_DIFF , WV_DIFF #endif diff --git a/src/proto/diff.pro b/src/proto/diff.pro index e45127ad0..f314fce58 100644 --- a/src/proto/diff.pro +++ b/src/proto/diff.pro @@ -22,5 +22,6 @@ void nv_diffgetput __ARGS((int put)); void ex_diffgetput __ARGS((exarg_T *eap)); int diff_mode_buf __ARGS((buf_T *buf)); int diff_move_to __ARGS((int dir, long count)); +linenr_T diff_get_corresponding_line __ARGS((buf_T *buf1, linenr_T lnum1, buf_T *buf2, linenr_T lnum2)); linenr_T diff_lnum_win __ARGS((linenr_T lnum, win_T *wp)); /* vim: set ft=c : */ diff --git a/src/proto/move.pro b/src/proto/move.pro index de51aa240..f1f3a1137 100644 --- a/src/proto/move.pro +++ b/src/proto/move.pro @@ -1,4 +1,5 @@ /* move.c */ +void do_check_cursorbind __ARGS((void)); void update_topline_redraw __ARGS((void)); void update_topline __ARGS((void)); void update_curswant __ARGS((void)); diff --git a/src/proto/screen.pro b/src/proto/screen.pro index c534a1f9e..937e4ed5a 100644 --- a/src/proto/screen.pro +++ b/src/proto/screen.pro @@ -46,5 +46,6 @@ void get_trans_bufname __ARGS((buf_T *buf)); int redrawing __ARGS((void)); int messaging __ARGS((void)); void showruler __ARGS((int always)); +void update_single_line __ARGS((win_T *buf, linenr_T lnum)); int number_width __ARGS((win_T *wp)); /* vim: set ft=c : */ diff --git a/src/proto/spell.pro b/src/proto/spell.pro index 8ab544dbf..9ed775b53 100644 --- a/src/proto/spell.pro +++ b/src/proto/spell.pro @@ -2,14 +2,10 @@ int spell_check __ARGS((win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, int docount)); int spell_move_to __ARGS((win_T *wp, int dir, int allwords, int curline, hlf_T *attrp)); void spell_cat_line __ARGS((char_u *buf, char_u *line, int maxlen)); -int get2c __ARGS((FILE *fd)); -int get3c __ARGS((FILE *fd)); -int get4c __ARGS((FILE *fd)); -char_u *did_set_spelllang __ARGS((buf_T *buf)); +char_u *did_set_spelllang __ARGS((win_T *wp)); void spell_free_all __ARGS((void)); void spell_reload __ARGS((void)); int spell_check_msm __ARGS((void)); -int put_bytes __ARGS((FILE *fd, long_u nr, int len)); void ex_mkspell __ARGS((exarg_T *eap)); void ex_spell __ARGS((exarg_T *eap)); void spell_add_word __ARGS((char_u *word, int len, int bad, int idx, int undo)); @@ -21,8 +17,8 @@ void spell_suggest_list __ARGS((garray_T *gap, char_u *word, int maxcount, int n char_u *eval_soundfold __ARGS((char_u *word)); void ex_spellinfo __ARGS((exarg_T *eap)); void ex_spelldump __ARGS((exarg_T *eap)); -void spell_dump_compl __ARGS((buf_T *buf, char_u *pat, int ic, int *dir, int dumpflags_arg)); -char_u *spell_to_word_end __ARGS((char_u *start, buf_T *buf)); +void spell_dump_compl __ARGS((char_u *pat, int ic, int *dir, int dumpflags_arg)); +char_u *spell_to_word_end __ARGS((char_u *start, win_T *win)); int spell_word_start __ARGS((int startcol)); void spell_expand_check_cap __ARGS((colnr_T col)); int expand_spelling __ARGS((linenr_T lnum, char_u *pat, char_u ***matchp)); diff --git a/src/proto/syntax.pro b/src/proto/syntax.pro index c27769198..0e484cbc6 100644 --- a/src/proto/syntax.pro +++ b/src/proto/syntax.pro @@ -1,18 +1,20 @@ /* syntax.c */ void syntax_start __ARGS((win_T *wp, linenr_T lnum)); -void syn_stack_free_all __ARGS((buf_T *buf)); +void syn_stack_free_all __ARGS((synblock_T *block)); void syn_stack_apply_changes __ARGS((buf_T *buf)); void syntax_end_parsing __ARGS((linenr_T lnum)); int syntax_check_changed __ARGS((linenr_T lnum)); -int get_syntax_attr __ARGS((colnr_T col, int *can_spell, int keep_state)); -void syntax_clear __ARGS((buf_T *buf)); +int get_syntax_attr __ARGS((colnr_T col, int *p_flags, int *can_spell, int keep_state)); +void syntax_clear __ARGS((synblock_T *block)); void ex_syntax __ARGS((exarg_T *eap)); -int syntax_present __ARGS((buf_T *buf)); +void ex_ownsyntax __ARGS((exarg_T *eap)); +int syntax_present __ARGS((win_T *win)); void reset_expand_highlight __ARGS((void)); void set_context_in_echohl_cmd __ARGS((expand_T *xp, char_u *arg)); void set_context_in_syntax_cmd __ARGS((expand_T *xp, char_u *arg)); char_u *get_syntax_name __ARGS((expand_T *xp, int idx)); int syn_get_id __ARGS((win_T *wp, long lnum, colnr_T col, int trans, int *spellp, int keep_state)); +int syn_get_sub_char __ARGS((void)); int syn_get_stack_item __ARGS((int i)); int syn_get_foldlevel __ARGS((win_T *wp, long lnum)); void init_highlight __ARGS((int both, int reset)); diff --git a/src/screen.c b/src/screen.c index df5489f8b..3205d3d48 100644 --- a/src/screen.c +++ b/src/screen.c @@ -485,7 +485,7 @@ update_screen(type) # ifdef FEAT_WINDOWS wwp == wp && # endif - syntax_present(wp->w_buffer)) + syntax_present(wp)) syn_stack_apply_changes(wp->w_buffer); } } @@ -585,6 +585,54 @@ update_screen(type) #endif } +#if defined(FEAT_CONCEAL) || defined(PROTO) + void +update_single_line(wp, lnum) + win_T *wp; + linenr_T lnum; +{ + int row; + int j; + + if (lnum >= wp->w_topline && lnum < wp->w_botline + && foldedCount(wp, lnum, NULL) == 0) + { +# ifdef FEAT_GUI + /* Remove the cursor before starting to do anything, because scrolling + * may make it difficult to redraw the text under it. */ + if (gui.in_use) + gui_undraw_cursor(); +# endif + row = 0; + for (j = 0; j < wp->w_lines_valid; ++j) + { + if (lnum == wp->w_lines[j].wl_lnum) + { + screen_start(); /* not sure of screen cursor */ +# if defined(FEAT_SEARCH_EXTRA) + start_search_hl(); + prepare_search_hl(wp, lnum); +# endif + win_line(wp, lnum, row, row + wp->w_lines[j].wl_size, FALSE); +# if defined(FEAT_SEARCH_EXTRA) + end_search_hl(); +# endif + break; + } + row += wp->w_lines[j].wl_size; + } +# ifdef FEAT_GUI + /* Redraw the cursor */ + if (gui.in_use) + { + out_flush(); /* required before updating the cursor */ + gui_update_cursor(FALSE, FALSE); + } +# endif + } +} +#endif + #if defined(FEAT_SIGNS) || defined(FEAT_GUI) static void update_prepare __ARGS((void)); static void update_finish __ARGS((void)); @@ -917,9 +965,9 @@ win_update(wp) #ifdef FEAT_SYN_HL /* Need to redraw lines above the change that may be included * in a pattern match. */ - if (syntax_present(buf)) + if (syntax_present(wp)) { - mod_top -= buf->b_syn_sync_linebreaks; + mod_top -= buf->b_s.b_syn_sync_linebreaks; if (mod_top < 1) mod_top = 1; } @@ -1010,7 +1058,7 @@ win_update(wp) if (mod_bot > wp->w_topline) mod_top = wp->w_topline; #ifdef FEAT_SYN_HL - else if (syntax_present(buf)) + else if (syntax_present(wp)) top_end = 1; #endif } @@ -1545,7 +1593,7 @@ win_update(wp) #ifdef FEAT_SYN_HL || did_update == DID_FOLD || (did_update == DID_LINE - && syntax_present(buf) + && syntax_present(wp) && ( # ifdef FEAT_FOLDING (foldmethodIsSyntax(wp) @@ -1771,7 +1819,7 @@ win_update(wp) #ifdef FEAT_SYN_HL /* Let the syntax stuff know we skipped a few lines. */ if (syntax_last_parsed != 0 && syntax_last_parsed + 1 < lnum - && syntax_present(buf)) + && syntax_present(wp)) syntax_end_parsing(syntax_last_parsed + 1); #endif @@ -1843,7 +1891,7 @@ win_update(wp) /* * Let the syntax stuff know we stop parsing here. */ - if (syntax_last_parsed != 0 && syntax_present(buf)) + if (syntax_last_parsed != 0 && syntax_present(wp)) syntax_end_parsing(syntax_last_parsed + 1); #endif @@ -2726,6 +2774,14 @@ win_line(wp, lnum, startrow, endrow, nochange) int feedback_old_attr = -1; #endif +#ifdef FEAT_CONCEAL + int syntax_flags = 0; + int conceal_attr = hl_attr(HLF_CONCEAL); + int first_conceal = (wp->w_p_conceal != 3); + int is_concealing = FALSE; + int boguscols = 0; /* nonexistent columns added to force + wrapping */ +#endif if (startrow > endrow) /* past the end already! */ return startrow; @@ -2743,7 +2799,7 @@ win_line(wp, lnum, startrow, endrow, nochange) extra_check = 0; #endif #ifdef FEAT_SYN_HL - if (syntax_present(wp->w_buffer) && !wp->w_buffer->b_syn_error) + if (syntax_present(wp) && !wp->w_s->b_syn_error) { /* Prepare for syntax highlighting in this line. When there is an * error, stop syntax highlighting. */ @@ -2751,7 +2807,7 @@ win_line(wp, lnum, startrow, endrow, nochange) did_emsg = FALSE; syntax_start(wp, lnum); if (did_emsg) - wp->w_buffer->b_syn_error = TRUE; + wp->w_s->b_syn_error = TRUE; else { did_emsg = save_did_emsg; @@ -2763,9 +2819,9 @@ win_line(wp, lnum, startrow, endrow, nochange) #ifdef FEAT_SPELL if (wp->w_p_spell - && *wp->w_buffer->b_p_spl != NUL - && wp->w_buffer->b_langp.ga_len > 0 - && *(char **)(wp->w_buffer->b_langp.ga_data) != NULL) + && *wp->w_s->b_p_spl != NUL + && wp->w_s->b_langp.ga_len > 0 + && *(char **)(wp->w_s->b_langp.ga_data) != NULL) { /* Prepare for spell checking. */ has_spell = TRUE; @@ -3113,7 +3169,7 @@ win_line(wp, lnum, startrow, endrow, nochange) /* no bad word found at line start, don't check until end of a * word */ spell_hlf = HLF_COUNT; - word_end = (int)(spell_to_word_end(ptr, wp->w_buffer) + word_end = (int)(spell_to_word_end(ptr, wp) - line + 1); } else @@ -3962,14 +4018,19 @@ win_line(wp, lnum, startrow, endrow, nochange) did_emsg = FALSE; syntax_attr = get_syntax_attr((colnr_T)v - 1, +# ifdef FEAT_CONCEAL + &syntax_flags, +# else + NULL, +# endif # ifdef FEAT_SPELL - has_spell ? &can_spell : + has_spell ? &can_spell : # endif - NULL, FALSE); + NULL, FALSE); if (did_emsg) { - wp->w_buffer->b_syn_error = TRUE; + wp->w_s->b_syn_error = TRUE; has_syntax = FALSE; } else @@ -4304,6 +4365,74 @@ win_line(wp, lnum, startrow, endrow, nochange) } #endif } + +#ifdef FEAT_CONCEAL + if ( wp->w_p_conceal + && (!area_highlighting) + && ((lnum != wp->w_cursor.lnum) + || (curwin != wp) || (wp->w_buffer->b_p_ma == FALSE)) + && ((syntax_flags & HL_CONCEAL) != 0)) + + { + char_attr = conceal_attr; + if (first_conceal + && (syn_get_sub_char() != NUL || wp->w_p_conceal == 1)) + { + if (syn_get_sub_char() != NUL) + c = syn_get_sub_char(); + else if (lcs_conceal != NUL) + c = lcs_conceal; + else + c = ' '; + + first_conceal = FALSE; + +# ifdef FEAT_HLCOLUMN + if (hlc > 0 && n_extra > 0) + hlc += n_extra; +# endif + vcol += n_extra; + if (wp->w_p_wrap && n_extra > 0) + { +# ifdef FEAT_RIGHTLEFT + if (wp->w_p_rl) + { + col -= n_extra; + boguscols -= n_extra; + } + else +# endif + { + boguscols += n_extra; + col += n_extra; + } + } + n_extra = 0; + n_attr = 0; + } + else if (n_skip == 0) + { + is_concealing = TRUE; + n_skip = 1; + } +# ifdef FEAT_MBYTE + mb_c = c; + if (enc_utf8 && (*mb_char2len)(c) > 1) + { + mb_utf8 = TRUE; + u8cc[0] = 0; + c = 0xc0; + } + else + mb_utf8 = FALSE; /* don't draw as UTF-8 */ +# endif + } + else + { + first_conceal = (wp->w_p_conceal != 3); + is_concealing = FALSE; + } +#endif /* FEAT_CONCEAL */ } /* Don't override visual selection highlighting. */ @@ -4570,8 +4699,14 @@ win_line(wp, lnum, startrow, endrow, nochange) } #endif - SCREEN_LINE(screen_row, W_WINCOL(wp), col, (int)W_WIDTH(wp), - wp->w_p_rl); +#ifdef FEAT_CONCEAL + SCREEN_LINE(screen_row, W_WINCOL(wp), col - boguscols, + (int)W_WIDTH(wp), wp->w_p_rl); + boguscols = 0; +#else + SCREEN_LINE(screen_row, W_WINCOL(wp), col, + (int)W_WIDTH(wp), wp->w_p_rl); +#endif row++; /* @@ -4730,6 +4865,97 @@ win_line(wp, lnum, startrow, endrow, nochange) ++col; } } +#ifdef FEAT_CONCEAL + else if (wp->w_p_conceal && is_concealing) + { + --n_skip; +# ifdef FEAT_HLCOLUMN + if (hlc) + { + ++hlc; + if (n_extra > 0) + hlc += n_extra; + } +# endif + if (wp->w_p_wrap) + { + /* + * Special voodoo required if 'wrap' is on. + * + * Advance the column indicator to force the line + * drawing to wrap early. This will make the line + * take up the same screen space when parts are concealed, + * so that cursor line computations aren't messed up. + * + * To avoid the fictitious advance of 'col' causing + * trailing junk to be written out of the screen line + * we are building, 'boguscols' keeps track of the number + * of bad columns we have advanced. + */ + if (n_extra > 0) + { + vcol += n_extra; +# ifdef FEAT_RIGHTLEFT + if (wp->w_p_rl) + { + col -= n_extra; + boguscols -= n_extra; + } + else +# endif + { + col += n_extra; + boguscols += n_extra; + } + n_extra = 0; + n_attr = 0; + } + + +# ifdef FEAT_MBYTE + if (has_mbyte && (*mb_char2cells)(mb_c) > 1) + { + /* Need to fill two screen columns. */ +# ifdef FEAT_RIGHTLEFT + if (wp->w_p_rl) + { + --boguscols; + --col; + } + else +# endif + { + ++boguscols; + ++col; + } + } +# endif + +# ifdef FEAT_RIGHTLEFT + if (wp->w_p_rl) + { + --boguscols; + --col; + } + else +# endif + { + ++boguscols; + ++col; + } + } + else + { + if (n_extra > 0) + { + vcol += n_extra; + n_extra = 0; + n_attr = 0; + } + } + + } +#endif /* FEAT_CONCEAL */ else --n_skip; @@ -4772,8 +4998,14 @@ win_line(wp, lnum, startrow, endrow, nochange) || (n_extra != 0 && (c_extra != NUL || *p_extra != NUL))) ) { - SCREEN_LINE(screen_row, W_WINCOL(wp), col, (int)W_WIDTH(wp), - wp->w_p_rl); +#ifdef FEAT_CONCEAL + SCREEN_LINE(screen_row, W_WINCOL(wp), col - boguscols, + (int)W_WIDTH(wp), wp->w_p_rl); + boguscols = 0; +#else + SCREEN_LINE(screen_row, W_WINCOL(wp), col, + (int)W_WIDTH(wp), wp->w_p_rl); +#endif ++row; ++screen_row; diff --git a/src/search.c b/src/search.c index 3ad9140c1..76ba6607e 100644 --- a/src/search.c +++ b/src/search.c @@ -1077,6 +1077,9 @@ do_search(oap, dirc, pat, count, options, tm) char_u *dircp; char_u *strcopy = NULL; char_u *ps; +#ifdef FEAT_CONCEAL + linenr_T oldline = curwin->w_cursor.lnum; +#endif /* * A line offset is not remembered, this is vi compatible. @@ -1422,6 +1425,13 @@ do_search(oap, dirc, pat, count, options, tm) setpcmark(); curwin->w_cursor = pos; curwin->w_set_curswant = TRUE; +#ifdef FEAT_CONCEAL + if (curwin->w_p_conceal && oldline != curwin->w_cursor.lnum) + { + update_single_line(curwin, oldline); + update_single_line(curwin, curwin->w_cursor.lnum); + } +#endif end_do_search: if (options & SEARCH_KEEP) diff --git a/src/spell.c b/src/spell.c index fbf5c910b..b4d6ca72d 100644 --- a/src/spell.c +++ b/src/spell.c @@ -720,7 +720,7 @@ typedef struct matchinf_S /* others */ int mi_result; /* result so far: SP_BAD, SP_OK, etc. */ int mi_capflags; /* WF_ONECAP WF_ALLCAP WF_KEEPCAP */ - buf_T *mi_buf; /* buffer being checked */ + win_T *mi_win; /* buffer being checked */ /* for NOBREAK */ int mi_result2; /* "mi_resul" without following word */ @@ -747,11 +747,11 @@ static int did_set_spelltab; static void clear_spell_chartab __ARGS((spelltab_T *sp)); static int set_spell_finish __ARGS((spelltab_T *new_st)); -static int spell_iswordp __ARGS((char_u *p, buf_T *buf)); +static int spell_iswordp __ARGS((char_u *p, win_T *wp)); static int spell_iswordp_nmw __ARGS((char_u *p)); #ifdef FEAT_MBYTE static int spell_mb_isword_class __ARGS((int cl)); -static int spell_iswordp_w __ARGS((int *p, buf_T *buf)); +static int spell_iswordp_w __ARGS((int *p, win_T *wp)); #endif static int write_spell_prefcond __ARGS((FILE *fd, garray_T *gap)); @@ -874,9 +874,9 @@ static void set_sal_first __ARGS((slang_T *lp)); static int *mb_str2wide __ARGS((char_u *s)); #endif static int spell_read_tree __ARGS((FILE *fd, char_u **bytsp, idx_T **idxsp, int prefixtree, int prefixcnt)); -static idx_T read_tree_node __ARGS((FILE *fd, char_u *byts, idx_T *idxs, int maxidx, int startidx, int prefixtree, int maxprefcondnr)); -static void clear_midword __ARGS((buf_T *buf)); -static void use_midword __ARGS((slang_T *lp, buf_T *buf)); +static idx_T read_tree_node __ARGS((FILE *fd, char_u *byts, idx_T *idxs, int maxidx, idx_T startidx, int prefixtree, int maxprefcondnr)); +static void clear_midword __ARGS((win_T *buf)); +static void use_midword __ARGS((slang_T *lp, win_T *buf)); static int find_region __ARGS((char_u *rp, char_u *region)); static int captype __ARGS((char_u *word, char_u *end)); static int badword_captype __ARGS((char_u *word, char_u *end)); @@ -1030,7 +1030,7 @@ spell_check(wp, ptr, attrp, capcol, docount) return 1; /* Return here when loading language files failed. */ - if (wp->w_buffer->b_langp.ga_len == 0) + if (wp->w_s->b_langp.ga_len == 0) return 1; vim_memset(&mi, 0, sizeof(matchinf_T)); @@ -1050,14 +1050,14 @@ spell_check(wp, ptr, attrp, capcol, docount) /* Find the normal end of the word (until the next non-word character). */ mi.mi_word = ptr; mi.mi_fend = ptr; - if (spell_iswordp(mi.mi_fend, wp->w_buffer)) + if (spell_iswordp(mi.mi_fend, wp)) { do { mb_ptr_adv(mi.mi_fend); - } while (*mi.mi_fend != NUL && spell_iswordp(mi.mi_fend, wp->w_buffer)); + } while (*mi.mi_fend != NUL && spell_iswordp(mi.mi_fend, wp)); - if (capcol != NULL && *capcol == 0 && wp->w_buffer->b_cap_prog != NULL) + if (capcol != NULL && *capcol == 0 && wp->w_s->b_cap_prog != NULL) { /* Check word starting with capital letter. */ c = PTR2CHAR(ptr); @@ -1073,7 +1073,9 @@ spell_check(wp, ptr, attrp, capcol, docount) mi.mi_end = mi.mi_fend; /* Check caps type later. */ - mi.mi_buf = wp->w_buffer; + mi.mi_capflags = 0; + mi.mi_cend = NULL; + mi.mi_win = wp; /* case-fold the word with one non-word character, so that we can check * for the word end. */ @@ -1093,9 +1095,9 @@ spell_check(wp, ptr, attrp, capcol, docount) * We check them all, because a word may be matched longer in another * language. */ - for (lpi = 0; lpi < wp->w_buffer->b_langp.ga_len; ++lpi) + for (lpi = 0; lpi < wp->w_s->b_langp.ga_len; ++lpi) { - mi.mi_lp = LANGP_ENTRY(wp->w_buffer->b_langp, lpi); + mi.mi_lp = LANGP_ENTRY(wp->w_s->b_langp, lpi); /* If reloading fails the language is still in the list but everything * has been cleared. */ @@ -1143,12 +1145,12 @@ spell_check(wp, ptr, attrp, capcol, docount) * skip over the character (try looking for a word after it). */ else if (!spell_iswordp_nmw(ptr)) { - if (capcol != NULL && wp->w_buffer->b_cap_prog != NULL) + if (capcol != NULL && wp->w_s->b_cap_prog != NULL) { regmatch_T regmatch; /* Check for end of sentence. */ - regmatch.regprog = wp->w_buffer->b_cap_prog; + regmatch.regprog = wp->w_s->b_cap_prog; regmatch.rm_ic = FALSE; if (vim_regexec(®match, ptr, 0)) *capcol = (int)(regmatch.endp[0] - ptr); @@ -1165,14 +1167,14 @@ spell_check(wp, ptr, attrp, capcol, docount) * is a mixup in "midword". */ mb_ptr_adv(mi.mi_end); else if (mi.mi_result == SP_BAD - && LANGP_ENTRY(wp->w_buffer->b_langp, 0)->lp_slang->sl_nobreak) + && LANGP_ENTRY(wp->w_s->b_langp, 0)->lp_slang->sl_nobreak) { char_u *p, *fp; int save_result = mi.mi_result; /* First language in 'spelllang' is NOBREAK. Find first position * at which any word would be valid. */ - mi.mi_lp = LANGP_ENTRY(wp->w_buffer->b_langp, 0); + mi.mi_lp = LANGP_ENTRY(wp->w_s->b_langp, 0); if (mi.mi_lp->lp_slang->sl_fidxs != NULL) { p = mi.mi_word; @@ -1389,7 +1391,7 @@ find_word(mip, mode) if ((*mb_head_off)(ptr, ptr + wlen) > 0) continue; /* not at first byte of character */ #endif - if (spell_iswordp(ptr + wlen, mip->mi_buf)) + if (spell_iswordp(ptr + wlen, mip->mi_win)) { if (slang->sl_compprog == NULL && !slang->sl_nobreak) continue; /* next char is a word character */ @@ -1634,11 +1636,11 @@ find_word(mip, mode) /* For NOBREAK we need to try all NOBREAK languages, at least * to find the ".add" file(s). */ - for (lpi = 0; lpi < mip->mi_buf->b_langp.ga_len; ++lpi) + for (lpi = 0; lpi < mip->mi_win->w_s->b_langp.ga_len; ++lpi) { if (slang->sl_nobreak) { - mip->mi_lp = LANGP_ENTRY(mip->mi_buf->b_langp, lpi); + mip->mi_lp = LANGP_ENTRY(mip->mi_win->w_s->b_langp, lpi); if (mip->mi_lp->lp_slang->sl_fidxs == NULL || !mip->mi_lp->lp_slang->sl_nobreak) continue; @@ -2102,7 +2104,7 @@ fold_more(mip) do { mb_ptr_adv(mip->mi_fend); - } while (*mip->mi_fend != NUL && spell_iswordp(mip->mi_fend, mip->mi_buf)); + } while (*mip->mi_fend != NUL && spell_iswordp(mip->mi_fend, mip->mi_win)); /* Include the non-word character so that we can check for the word end. */ if (*mip->mi_fend != NUL) @@ -2138,8 +2140,8 @@ spell_valid_case(wordflags, treeflags) no_spell_checking(wp) win_T *wp; { - if (!wp->w_p_spell || *wp->w_buffer->b_p_spl == NUL - || wp->w_buffer->b_langp.ga_len == 0) + if (!wp->w_p_spell || *wp->w_s->b_p_spl == NUL + || wp->w_s->b_langp.ga_len == 0) { EMSG(_("E756: Spell checking is not enabled")); return TRUE; @@ -2173,7 +2175,7 @@ spell_move_to(wp, dir, allwords, curline, attrp) hlf_T attr; int len; # ifdef FEAT_SYN_HL - int has_syntax = syntax_present(wp->w_buffer); + int has_syntax = syntax_present(wp); # endif int col; int can_spell; @@ -4165,12 +4167,12 @@ read_tree_node(fd, byts, idxs, maxidx, startidx, prefixtree, maxprefcondnr) } /* - * Parse 'spelllang' and set buf->b_langp accordingly. + * Parse 'spelllang' and set w_s->b_langp accordingly. * Returns NULL if it's OK, an error message otherwise. */ char_u * -did_set_spelllang(buf) - buf_T *buf; +did_set_spelllang(wp) + win_T *wp; { garray_T ga; char_u *splp; @@ -4203,11 +4205,11 @@ did_set_spelllang(buf) recursive = TRUE; ga_init2(&ga, sizeof(langp_T), 2); - clear_midword(buf); + clear_midword(wp); /* Make a copy of 'spellang', the SpellFileMissing autocommands may change * it under our fingers. */ - spl_copy = vim_strsave(buf->b_p_spl); + spl_copy = vim_strsave(wp->w_s->b_p_spl); if (spl_copy == NULL) goto theend; @@ -4216,7 +4218,6 @@ did_set_spelllang(buf) { /* Get one language name. */ copy_option_part(&splp, lang, MAXWLEN, ","); - region = NULL; len = (int)STRLEN(lang); @@ -4283,7 +4284,7 @@ did_set_spelllang(buf) #ifdef FEAT_AUTOCMD /* SpellFileMissing autocommands may do anything, including * destroying the buffer we are using... */ - if (!buf_valid(buf)) + if (!buf_valid(wp->w_buffer)) { ret_msg = (char_u *)"E797: SpellFileMissing autocommand deleted buffer"; goto theend; @@ -4334,7 +4335,7 @@ did_set_spelllang(buf) LANGP_ENTRY(ga, ga.ga_len)->lp_slang = slang; LANGP_ENTRY(ga, ga.ga_len)->lp_region = region_mask; ++ga.ga_len; - use_midword(slang, buf); + use_midword(slang, wp); if (slang->sl_nobreak) nobreak = TRUE; } @@ -4345,7 +4346,7 @@ did_set_spelllang(buf) * round 1: load first name in 'spellfile'. * round 2: load second name in 'spellfile. * etc. */ - spf = buf->b_p_spf; + spf = curwin->w_s->b_p_spf; for (round = 0; round == 0 || *spf != NUL; ++round) { if (round == 0) @@ -4418,14 +4419,14 @@ did_set_spelllang(buf) LANGP_ENTRY(ga, ga.ga_len)->lp_replang = NULL; LANGP_ENTRY(ga, ga.ga_len)->lp_region = region_mask; ++ga.ga_len; - use_midword(slang, buf); + use_midword(slang, wp); } } } /* Everything is fine, store the new b_langp value. */ - ga_clear(&buf->b_langp); - buf->b_langp = ga; + ga_clear(&wp->w_s->b_langp); + wp->w_s->b_langp = ga; /* For each language figure out what language to use for sound folding and * REP items. If the language doesn't support it itself use another one @@ -4481,13 +4482,13 @@ theend: * Clear the midword characters for buffer "buf". */ static void -clear_midword(buf) - buf_T *buf; +clear_midword(wp) + win_T *wp; { - vim_memset(buf->b_spell_ismw, 0, 256); + vim_memset(wp->w_s->b_spell_ismw, 0, 256); #ifdef FEAT_MBYTE - vim_free(buf->b_spell_ismw_mb); - buf->b_spell_ismw_mb = NULL; + vim_free(wp->w_s->b_spell_ismw_mb); + wp->w_s->b_spell_ismw_mb = NULL; #endif } @@ -4496,9 +4497,9 @@ clear_midword(buf) * They add up to any currently used midword characters. */ static void -use_midword(lp, buf) +use_midword(lp, wp) slang_T *lp; - buf_T *buf; + win_T *wp; { char_u *p; @@ -4515,19 +4516,19 @@ use_midword(lp, buf) c = mb_ptr2char(p); l = (*mb_ptr2len)(p); if (c < 256 && l <= 2) - buf->b_spell_ismw[c] = TRUE; - else if (buf->b_spell_ismw_mb == NULL) + wp->w_s->b_spell_ismw[c] = TRUE; + else if (wp->w_s->b_spell_ismw_mb == NULL) /* First multi-byte char in "b_spell_ismw_mb". */ - buf->b_spell_ismw_mb = vim_strnsave(p, l); + wp->w_s->b_spell_ismw_mb = vim_strnsave(p, l); else { /* Append multi-byte chars to "b_spell_ismw_mb". */ - n = (int)STRLEN(buf->b_spell_ismw_mb); - bp = vim_strnsave(buf->b_spell_ismw_mb, n + l); + n = (int)STRLEN(wp->w_s->b_spell_ismw_mb); + bp = vim_strnsave(wp->w_s->b_spell_ismw_mb, n + l); if (bp != NULL) { - vim_free(buf->b_spell_ismw_mb); - buf->b_spell_ismw_mb = bp; + vim_free(wp->w_s->b_spell_ismw_mb); + wp->w_s->b_spell_ismw_mb = bp; vim_strncpy(bp + n, p, l); } } @@ -4535,7 +4536,7 @@ use_midword(lp, buf) } else #endif - buf->b_spell_ismw[*p++] = TRUE; + wp->w_s->b_spell_ismw[*p++] = TRUE; } /* @@ -4678,9 +4679,9 @@ spell_free_all() buf_T *buf; char_u fname[MAXPATHL]; - /* Go through all buffers and handle 'spelllang'. */ + /* Go through all buffers and handle 'spelllang'. */ //<VN> for (buf = firstbuf; buf != NULL; buf = buf->b_next) - ga_clear(&buf->b_langp); + ga_clear(&buf->b_s.b_langp); while (first_lang != NULL) { @@ -4716,7 +4717,6 @@ spell_free_all() void spell_reload() { - buf_T *buf; win_T *wp; /* Initialize the table for spell_iswordp(). */ @@ -4726,16 +4726,15 @@ spell_reload() spell_free_all(); /* Go through all buffers and handle 'spelllang'. */ - for (buf = firstbuf; buf != NULL; buf = buf->b_next) + for (wp = firstwin; wp != NULL; wp = wp->w_next) { /* Only load the wordlists when 'spelllang' is set and there is a * window for this buffer in which 'spell' is set. */ - if (*buf->b_p_spl != NUL) + if (*wp->w_s->b_p_spl != NUL) { - FOR_ALL_WINDOWS(wp) - if (wp->w_buffer == buf && wp->w_p_spell) + if (wp->w_p_spell) { - (void)did_set_spelllang(buf); + (void)did_set_spelllang(wp); # ifdef FEAT_WINDOWS break; # endif @@ -4772,7 +4771,7 @@ spell_reload_one(fname, added_word) /* When "zg" was used and the file wasn't loaded yet, should redo * 'spelllang' to load it now. */ if (added_word && !didit) - did_set_spelllang(curbuf); + did_set_spelllang(curwin); } @@ -9369,19 +9368,19 @@ spell_add_word(word, len, bad, idx, undo) else { /* If 'spellfile' isn't set figure out a good default value. */ - if (*curbuf->b_p_spf == NUL) + if (*curwin->w_s->b_p_spf == NUL) { init_spellfile(); new_spf = TRUE; } - if (*curbuf->b_p_spf == NUL) + if (*curwin->w_s->b_p_spf == NUL) { EMSG2(_(e_notset), "spellfile"); return; } - for (spf = curbuf->b_p_spf, i = 1; *spf != NUL; ++i) + for (spf = curwin->w_s->b_p_spf, i = 1; *spf != NUL; ++i) { copy_option_part(&spf, fnamebuf, MAXPATHL, ","); if (i == idx) @@ -9507,13 +9506,13 @@ init_spellfile() char_u *rtp; char_u *lend; int aspath = FALSE; - char_u *lstart = curbuf->b_p_spl; + char_u *lstart = curbuf->b_s.b_p_spl; - if (*curbuf->b_p_spl != NUL && curbuf->b_langp.ga_len > 0) + if (*curwin->w_s->b_p_spl != NUL && curwin->w_s->b_langp.ga_len > 0) { /* Find the end of the language name. Exclude the region. If there * is a path separator remember the start of the tail. */ - for (lend = curbuf->b_p_spl; *lend != NUL + for (lend = curwin->w_s->b_p_spl; *lend != NUL && vim_strchr((char_u *)",._", *lend) == NULL; ++lend) if (vim_ispathsep(*lend)) { @@ -9529,7 +9528,7 @@ init_spellfile() if (aspath) /* Use directory of an entry with path, e.g., for * "/dir/lg.utf-8.spl" use "/dir". */ - vim_strncpy(buf, curbuf->b_p_spl, lstart - curbuf->b_p_spl - 1); + vim_strncpy(buf, curbuf->b_s.b_p_spl, lstart - curbuf->b_s.b_p_spl - 1); else /* Copy the path from 'runtimepath' to buf[]. */ copy_option_part(&rtp, buf, MAXPATHL, ","); @@ -9538,7 +9537,7 @@ init_spellfile() /* Use the first language name from 'spelllang' and the * encoding used in the first loaded .spl file. */ if (aspath) - vim_strncpy(buf, curbuf->b_p_spl, lend - curbuf->b_p_spl); + vim_strncpy(buf, curbuf->b_s.b_p_spl, lend - curbuf->b_s.b_p_spl); else { /* Create the "spell" directory if it doesn't exist yet. */ @@ -9552,7 +9551,7 @@ init_spellfile() "/%.*s", (int)(lend - lstart), lstart); } l = (int)STRLEN(buf); - fname = LANGP_ENTRY(curbuf->b_langp, 0)->lp_slang->sl_fname; + fname = LANGP_ENTRY(curwin->w_s->b_langp, 0)->lp_slang->sl_fname; vim_snprintf((char *)buf + l, MAXPATHL - l, ".%s.add", fname != NULL && strstr((char *)gettail(fname), ".ascii.") != NULL @@ -9819,9 +9818,9 @@ set_spell_finish(new_st) * Thus this only works properly when past the first character of the word. */ static int -spell_iswordp(p, buf) +spell_iswordp(p, wp) char_u *p; - buf_T *buf; /* buffer used */ + win_T *wp; /* buffer used */ { #ifdef FEAT_MBYTE char_u *s; @@ -9835,7 +9834,7 @@ spell_iswordp(p, buf) if (l == 1) { /* be quick for ASCII */ - if (buf->b_spell_ismw[*p]) + if (wp->w_s->b_spell_ismw[*p]) { s = p + 1; /* skip a mid-word character */ l = MB_BYTE2LEN(*s); @@ -9844,9 +9843,9 @@ spell_iswordp(p, buf) else { c = mb_ptr2char(p); - if (c < 256 ? buf->b_spell_ismw[c] - : (buf->b_spell_ismw_mb != NULL - && vim_strchr(buf->b_spell_ismw_mb, c) != NULL)) + if (c < 256 ? wp->w_s->b_spell_ismw[c] + : (wp->w_s->b_spell_ismw_mb != NULL + && vim_strchr(wp->w_s->b_spell_ismw_mb, c) != NULL)) { s = p + l; l = MB_BYTE2LEN(*s); @@ -9860,7 +9859,7 @@ spell_iswordp(p, buf) } #endif - return spelltab.st_isw[buf->b_spell_ismw[*p] ? p[1] : p[0]]; + return spelltab.st_isw[wp->w_s->b_spell_ismw[*p] ? p[1] : p[0]]; } /* @@ -9903,15 +9902,15 @@ spell_mb_isword_class(cl) * Wide version of spell_iswordp(). */ static int -spell_iswordp_w(p, buf) +spell_iswordp_w(p, wp) int *p; - buf_T *buf; + win_T *wp; { int *s; - if (*p < 256 ? buf->b_spell_ismw[*p] - : (buf->b_spell_ismw_mb != NULL - && vim_strchr(buf->b_spell_ismw_mb, *p) != NULL)) + if (*p < 256 ? wp->w_s->b_spell_ismw[*p] + : (wp->w_s->b_spell_ismw_mb != NULL + && vim_strchr(wp->w_s->b_spell_ismw_mb, *p) != NULL)) s = p + 1; else s = p; @@ -10347,7 +10346,7 @@ check_need_cap(lnum, col) colnr_T endcol; regmatch_T regmatch; - if (curbuf->b_cap_prog == NULL) + if (curwin->w_s->b_cap_prog == NULL) return FALSE; line = ml_get_curline(); @@ -10378,7 +10377,7 @@ check_need_cap(lnum, col) if (endcol > 0) { /* Check if sentence ends before the bad word. */ - regmatch.regprog = curbuf->b_cap_prog; + regmatch.regprog = curwin->w_s->b_cap_prog; regmatch.rm_ic = FALSE; p = line + endcol; for (;;) @@ -10577,9 +10576,9 @@ spell_find_suggest(badptr, badlen, su, maxcount, banbadword, need_cap, interacti * one in 'spelllang' that supports sound folding. That's good for when * using multiple files for one language, it's not that bad when mixing * languages (e.g., "pl,en"). */ - for (i = 0; i < curbuf->b_langp.ga_len; ++i) + for (i = 0; i < curbuf->b_s.b_langp.ga_len; ++i) { - lp = LANGP_ENTRY(curbuf->b_langp, i); + lp = LANGP_ENTRY(curbuf->b_s.b_langp, i); if (lp->lp_sallang != NULL) { su->su_sallang = lp->lp_sallang; @@ -10862,9 +10861,9 @@ suggest_load_files() int c; /* Do this for all languages that support sound folding. */ - for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi) + for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi) { - lp = LANGP_ENTRY(curbuf->b_langp, lpi); + lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); slang = lp->lp_slang; if (slang->sl_sugtime != 0 && !slang->sl_sugloaded) { @@ -11215,9 +11214,9 @@ suggest_try_change(su) p = su->su_badptr + su->su_badlen; (void)spell_casefold(p, (int)STRLEN(p), fword + n, MAXWLEN - n); - for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi) + for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi) { - lp = LANGP_ENTRY(curbuf->b_langp, lpi); + lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); /* If reloading a spell file fails it's still in the list but * everything has been cleared. */ @@ -11445,7 +11444,7 @@ suggest_trie_walk(su, lp, fword, soundfold) fword_ends = (fword[sp->ts_fidx] == NUL || (soundfold ? vim_iswhite(fword[sp->ts_fidx]) - : !spell_iswordp(fword + sp->ts_fidx, curbuf))); + : !spell_iswordp(fword + sp->ts_fidx, curwin))); tword[sp->ts_twordlen] = NUL; if (sp->ts_prefixdepth <= PFD_NOTSPECIAL @@ -11663,11 +11662,11 @@ suggest_trie_walk(su, lp, fword, soundfold) * char, e.g., "thes," -> "these". */ p = fword + sp->ts_fidx; mb_ptr_back(fword, p); - if (!spell_iswordp(p, curbuf)) + if (!spell_iswordp(p, curwin)) { p = preword + STRLEN(preword); mb_ptr_back(preword, p); - if (spell_iswordp(p, curbuf)) + if (spell_iswordp(p, curwin)) newscore += SCORE_NONWORD; } @@ -12270,7 +12269,7 @@ suggest_trie_walk(su, lp, fword, soundfold) /* Don't swap if the first character is not a word character. * SWAP3 etc. also don't make sense then. */ - if (!soundfold && !spell_iswordp(p, curbuf)) + if (!soundfold && !spell_iswordp(p, curwin)) { sp->ts_state = STATE_REP_INI; break; @@ -12283,7 +12282,7 @@ suggest_trie_walk(su, lp, fword, soundfold) c = mb_ptr2char(p); if (p[n] == NUL) c2 = NUL; - else if (!soundfold && !spell_iswordp(p + n, curbuf)) + else if (!soundfold && !spell_iswordp(p + n, curwin)) c2 = c; /* don't swap non-word char */ else c2 = mb_ptr2char(p + n); @@ -12293,7 +12292,7 @@ suggest_trie_walk(su, lp, fword, soundfold) { if (p[1] == NUL) c2 = NUL; - else if (!soundfold && !spell_iswordp(p + 1, curbuf)) + else if (!soundfold && !spell_iswordp(p + 1, curwin)) c2 = c; /* don't swap non-word char */ else c2 = p[1]; @@ -12375,7 +12374,7 @@ suggest_trie_walk(su, lp, fword, soundfold) c = mb_ptr2char(p); fl = mb_cptr2len(p + n); c2 = mb_ptr2char(p + n); - if (!soundfold && !spell_iswordp(p + n + fl, curbuf)) + if (!soundfold && !spell_iswordp(p + n + fl, curwin)) c3 = c; /* don't swap non-word char */ else c3 = mb_ptr2char(p + n + fl); @@ -12385,7 +12384,7 @@ suggest_trie_walk(su, lp, fword, soundfold) { c = *p; c2 = p[1]; - if (!soundfold && !spell_iswordp(p + 2, curbuf)) + if (!soundfold && !spell_iswordp(p + 2, curwin)) c3 = c; /* don't swap non-word char */ else c3 = p[2]; @@ -12458,7 +12457,7 @@ suggest_trie_walk(su, lp, fword, soundfold) ++p; } - if (!soundfold && !spell_iswordp(p, curbuf)) + if (!soundfold && !spell_iswordp(p, curwin)) { /* Middle char is not a word char, skip the rotate. First and * third char were already checked at swap and swap3. */ @@ -12934,9 +12933,9 @@ score_comp_sal(su) return; /* Use the sound-folding of the first language that supports it. */ - for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi) + for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi) { - lp = LANGP_ENTRY(curbuf->b_langp, lpi); + lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); if (lp->lp_slang->sl_sal.ga_len > 0) { /* soundfold the bad word */ @@ -12990,9 +12989,9 @@ score_combine(su) slang_T *slang = NULL; /* Add the alternate score to su_ga. */ - for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi) + for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi) { - lp = LANGP_ENTRY(curbuf->b_langp, lpi); + lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); if (lp->lp_slang->sl_sal.ga_len > 0) { /* soundfold the bad word */ @@ -13165,9 +13164,9 @@ suggest_try_soundalike_prep() /* Do this for all languages that support sound folding and for which a * .sug file has been loaded. */ - for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi) + for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi) { - lp = LANGP_ENTRY(curbuf->b_langp, lpi); + lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); slang = lp->lp_slang; if (slang->sl_sal.ga_len > 0 && slang->sl_sbyts != NULL) /* prepare the hashtable used by add_sound_suggest() */ @@ -13190,9 +13189,9 @@ suggest_try_soundalike(su) /* Do this for all languages that support sound folding and for which a * .sug file has been loaded. */ - for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi) + for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi) { - lp = LANGP_ENTRY(curbuf->b_langp, lpi); + lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); slang = lp->lp_slang; if (slang->sl_sal.ga_len > 0 && slang->sl_sbyts != NULL) { @@ -13221,9 +13220,9 @@ suggest_try_soundalike_finish() /* Do this for all languages that support sound folding and for which a * .sug file has been loaded. */ - for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi) + for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi) { - lp = LANGP_ENTRY(curbuf->b_langp, lpi); + lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); slang = lp->lp_slang; if (slang->sl_sal.ga_len > 0 && slang->sl_sbyts != NULL) { @@ -14000,11 +13999,11 @@ eval_soundfold(word) char_u sound[MAXWLEN]; int lpi; - if (curwin->w_p_spell && *curbuf->b_p_spl != NUL) + if (curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL) /* Use the sound-folding of the first language that supports it. */ - for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi) + for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi) { - lp = LANGP_ENTRY(curbuf->b_langp, lpi); + lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); if (lp->lp_slang->sl_sal.ga_len > 0) { /* soundfold the word */ @@ -14255,12 +14254,12 @@ spell_soundfold_sal(slang, inword, res) if (*s == NUL || (*s == '^' && (i == 0 || !(word[i - 1] == ' ' - || spell_iswordp(word + i - 1, curbuf))) + || spell_iswordp(word + i - 1, curwin))) && (*(s + 1) != '$' - || (!spell_iswordp(word + i + k0, curbuf)))) + || (!spell_iswordp(word + i + k0, curwin)))) || (*s == '$' && i > 0 - && spell_iswordp(word + i - 1, curbuf) - && (!spell_iswordp(word + i + k0, curbuf)))) + && spell_iswordp(word + i - 1, curwin) + && (!spell_iswordp(word + i + k0, curwin)))) { /* search for followup rules, if: */ /* followup and k > 1 and NO '-' in searchstring */ @@ -14323,7 +14322,7 @@ spell_soundfold_sal(slang, inword, res) /* *s == '^' cuts */ || (*s == '$' && !spell_iswordp(word + i + k0, - curbuf))) + curwin))) { if (k0 == k) /* this is just a piece of the string */ @@ -14547,12 +14546,12 @@ spell_soundfold_wsal(slang, inword, res) if (*s == NUL || (*s == '^' && (i == 0 || !(word[i - 1] == ' ' - || spell_iswordp_w(word + i - 1, curbuf))) + || spell_iswordp_w(word + i - 1, curwin))) && (*(s + 1) != '$' - || (!spell_iswordp_w(word + i + k0, curbuf)))) + || (!spell_iswordp_w(word + i + k0, curwin)))) || (*s == '$' && i > 0 - && spell_iswordp_w(word + i - 1, curbuf) - && (!spell_iswordp_w(word + i + k0, curbuf)))) + && spell_iswordp_w(word + i - 1, curwin) + && (!spell_iswordp_w(word + i + k0, curwin)))) { /* search for followup rules, if: */ /* followup and k > 1 and NO '-' in searchstring */ @@ -14619,7 +14618,7 @@ spell_soundfold_wsal(slang, inword, res) /* *s == '^' cuts */ || (*s == '$' && !spell_iswordp_w(word + i + k0, - curbuf))) + curwin))) { if (k0 == k) /* this is just a piece of the string */ @@ -15478,9 +15477,9 @@ ex_spellinfo(eap) return; msg_start(); - for (lpi = 0; lpi < curbuf->b_langp.ga_len && !got_int; ++lpi) + for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len && !got_int; ++lpi) { - lp = LANGP_ENTRY(curbuf->b_langp, lpi); + lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); msg_puts((char_u *)"file: "); msg_puts(lp->lp_slang->sl_fname); msg_putchar('\n'); @@ -15507,17 +15506,15 @@ ex_spellinfo(eap) ex_spelldump(eap) exarg_T *eap; { - buf_T *buf = curbuf; - if (no_spell_checking(curwin)) return; /* Create a new empty buffer by splitting the window. */ do_cmdline_cmd((char_u *)"new"); - if (!bufempty() || !buf_valid(buf)) + if (!bufempty() || !buf_valid(curbuf)) return; - spell_dump_compl(buf, NULL, 0, NULL, eap->forceit ? DUMPFLAG_COUNT : 0); + spell_dump_compl(NULL, 0, NULL, eap->forceit ? DUMPFLAG_COUNT : 0); /* Delete the empty line that we started with. */ if (curbuf->b_ml.ml_line_count > 1) @@ -15533,8 +15530,7 @@ ex_spelldump(eap) * 2. When "pat" is not NULL: add matching words to insert mode completion. */ void -spell_dump_compl(buf, pat, ic, dir, dumpflags_arg) - buf_T *buf; /* buffer with spell checking */ +spell_dump_compl(pat, ic, dir, dumpflags_arg) char_u *pat; /* leading part of the word */ int ic; /* ignore case */ int *dir; /* direction for adding matches */ @@ -15584,9 +15580,9 @@ spell_dump_compl(buf, pat, ic, dir, dumpflags_arg) /* Find out if we can support regions: All languages must support the same * regions or none at all. */ - for (lpi = 0; lpi < buf->b_langp.ga_len; ++lpi) + for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi) { - lp = LANGP_ENTRY(buf->b_langp, lpi); + lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); p = lp->lp_slang->sl_regions; if (p[0] != 0) { @@ -15614,9 +15610,9 @@ spell_dump_compl(buf, pat, ic, dir, dumpflags_arg) /* * Loop over all files loaded for the entries in 'spelllang'. */ - for (lpi = 0; lpi < buf->b_langp.ga_len; ++lpi) + for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi) { - lp = LANGP_ENTRY(buf->b_langp, lpi); + lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); slang = lp->lp_slang; if (slang->sl_fbyts == NULL) /* reloading failed */ continue; @@ -15941,13 +15937,13 @@ dump_prefixes(slang, word, pat, dir, dumpflags, flags, startlnum) * Uses the spell-checking word characters. */ char_u * -spell_to_word_end(start, buf) +spell_to_word_end(start, win) char_u *start; - buf_T *buf; + win_T *win; { char_u *p = start; - while (*p != NUL && spell_iswordp(p, buf)) + while (*p != NUL && spell_iswordp(p, win)) mb_ptr_adv(p); return p; } @@ -15985,7 +15981,7 @@ spell_word_start(startcol) { col = (int)(p - line); mb_ptr_back(line, p); - if (!spell_iswordp(p, curbuf)) + if (!spell_iswordp(p, curwin)) break; col = 0; } diff --git a/src/structs.h b/src/structs.h index daf254f31..4f72f998b 100644 --- a/src/structs.h +++ b/src/structs.h @@ -213,6 +213,14 @@ typedef struct #endif int wo_wrap; #define w_p_wrap w_onebuf_opt.wo_wrap /* 'wrap' */ +#ifdef FEAT_CONCEAL + int wo_conceal; /* 'conceal' */ +# define w_p_conceal w_onebuf_opt.wo_conceal +#endif +#ifdef FEAT_CURSORBIND + int wo_crb; +# define w_p_crb w_onebuf_opt.wo_crb /* 'cursorbind' */ +#endif #ifdef FEAT_EVAL int wo_scriptID[WV_COUNT]; /* SIDs for window-local options */ @@ -769,7 +777,8 @@ struct keyentry keyentry_T *ke_next; /* next entry with identical "keyword[]" */ struct sp_syn k_syn; /* struct passed to in_id_list() */ short *next_list; /* ID list for next match (if non-zero) */ - short flags; /* see syntax.c */ + int flags; + int k_char; /* conceal substitute character */ char_u keyword[1]; /* actually longer */ }; @@ -779,7 +788,7 @@ struct keyentry typedef struct buf_state { int bs_idx; /* index of pattern */ - long bs_flags; /* flags for pattern */ + int bs_flags; /* flags for pattern */ reg_extmatch_T *bs_extmatch; /* external matches from start pattern */ } bufstate_T; @@ -968,6 +977,11 @@ struct stl_hlrec int userhl; /* 0: no HL, 1-9: User HL, < 0 for syn ID */ }; + +/* + * Syntax items - usually buffer-specific. + */ + /* Item for a hashtable. "hi_key" can be one of three values: * NULL: Never been used * HI_KEY_REMOVED: Entry was removed @@ -1140,6 +1154,73 @@ struct dictvar_S typedef struct qf_info_S qf_info_T; #endif +typedef struct { +#ifdef FEAT_SYN_HL + hashtab_T b_keywtab; /* syntax keywords hash table */ + hashtab_T b_keywtab_ic; /* idem, ignore case */ + int b_syn_error; /* TRUE when error occured in HL */ + int b_syn_ic; /* ignore case for :syn cmds */ + int b_syn_spell; /* SYNSPL_ values */ + garray_T b_syn_patterns; /* table for syntax patterns */ + garray_T b_syn_clusters; /* table for syntax clusters */ + int b_spell_cluster_id; /* @Spell cluster ID or 0 */ + int b_nospell_cluster_id; /* @NoSpell cluster ID or 0 */ + int b_syn_containedin; /* TRUE when there is an item with a + "containedin" argument */ + int b_syn_sync_flags; /* flags about how to sync */ + short b_syn_sync_id; /* group to sync on */ + long b_syn_sync_minlines; /* minimal sync lines offset */ + long b_syn_sync_maxlines; /* maximal sync lines offset */ + long b_syn_sync_linebreaks; /* offset for multi-line pattern */ + char_u *b_syn_linecont_pat; /* line continuation pattern */ + regprog_T *b_syn_linecont_prog; /* line continuation program */ + int b_syn_linecont_ic; /* ignore-case flag for above */ + int b_syn_topgrp; /* for ":syntax include" */ +# ifdef FEAT_CONCEAL + int b_syn_conceal; /* auto-conceal for :syn cmds */ +# endif +# ifdef FEAT_FOLDING + int b_syn_folditems; /* number of patterns with the HL_FOLD + flag set */ +# endif +/* + * b_sst_array[] contains the state stack for a number of lines, for the start + * of that line (col == 0). This avoids having to recompute the syntax state + * too often. + * b_sst_array[] is allocated to hold the state for all displayed lines, and + * states for 1 out of about 20 other lines. + * b_sst_array pointer to an array of synstate_T + * b_sst_len number of entries in b_sst_array[] + * b_sst_first pointer to first used entry in b_sst_array[] or NULL + * b_sst_firstfree pointer to first free entry in b_sst_array[] or NULL + * b_sst_freecount number of free entries in b_sst_array[] + * b_sst_check_lnum entries after this lnum need to be checked for + * validity (MAXLNUM means no check needed) + */ + synstate_T *b_sst_array; + int b_sst_len; + synstate_T *b_sst_first; + synstate_T *b_sst_firstfree; + int b_sst_freecount; + linenr_T b_sst_check_lnum; + short_u b_sst_lasttick; /* last display tick */ +#endif /* FEAT_SYN_HL */ + +#ifdef FEAT_SPELL + /* for spell checking */ + garray_T b_langp; /* list of pointers to slang_T, see spell.c */ + char_u b_spell_ismw[256];/* flags: is midword char */ +# ifdef FEAT_MBYTE + char_u *b_spell_ismw_mb; /* multi-byte midword chars */ +# endif + char_u *b_p_spc; /* 'spellcapcheck' */ + regprog_T *b_cap_prog; /* program for 'spellcapcheck' */ + char_u *b_p_spf; /* 'spellfile' */ + char_u *b_p_spl; /* 'spelllang' */ +#endif +} synblock_T; + + /* * buffer: structure that holds information about one file * @@ -1427,12 +1508,6 @@ struct file_buffer long b_p_smc; /* 'synmaxcol' */ char_u *b_p_syn; /* 'syntax' */ #endif -#ifdef FEAT_SPELL - char_u *b_p_spc; /* 'spellcapcheck' */ - regprog_T *b_cap_prog; /* program for 'spellcapcheck' */ - char_u *b_p_spf; /* 'spellfile' */ - char_u *b_p_spl; /* 'spelllang' */ -#endif long b_p_ts; /* 'tabstop' */ int b_p_tx; /* 'textmode' */ long b_p_tw; /* 'textwidth' */ @@ -1528,61 +1603,10 @@ struct file_buffer void *b_ruby_ref; #endif -#ifdef FEAT_SYN_HL - hashtab_T b_keywtab; /* syntax keywords hash table */ - hashtab_T b_keywtab_ic; /* idem, ignore case */ - int b_syn_error; /* TRUE when error occured in HL */ - int b_syn_ic; /* ignore case for :syn cmds */ - int b_syn_spell; /* SYNSPL_ values */ - garray_T b_syn_patterns; /* table for syntax patterns */ - garray_T b_syn_clusters; /* table for syntax clusters */ - int b_spell_cluster_id; /* @Spell cluster ID or 0 */ - int b_nospell_cluster_id; /* @NoSpell cluster ID or 0 */ - int b_syn_containedin; /* TRUE when there is an item with a - "containedin" argument */ - int b_syn_sync_flags; /* flags about how to sync */ - short b_syn_sync_id; /* group to sync on */ - long b_syn_sync_minlines; /* minimal sync lines offset */ - long b_syn_sync_maxlines; /* maximal sync lines offset */ - long b_syn_sync_linebreaks; /* offset for multi-line pattern */ - char_u *b_syn_linecont_pat; /* line continuation pattern */ - regprog_T *b_syn_linecont_prog; /* line continuation program */ - int b_syn_linecont_ic; /* ignore-case flag for above */ - int b_syn_topgrp; /* for ":syntax include" */ -# ifdef FEAT_FOLDING - int b_syn_folditems; /* number of patterns with the HL_FOLD - flag set */ -# endif -/* - * b_sst_array[] contains the state stack for a number of lines, for the start - * of that line (col == 0). This avoids having to recompute the syntax state - * too often. - * b_sst_array[] is allocated to hold the state for all displayed lines, and - * states for 1 out of about 20 other lines. - * b_sst_array pointer to an array of synstate_T - * b_sst_len number of entries in b_sst_array[] - * b_sst_first pointer to first used entry in b_sst_array[] or NULL - * b_sst_firstfree pointer to first free entry in b_sst_array[] or NULL - * b_sst_freecount number of free entries in b_sst_array[] - * b_sst_check_lnum entries after this lnum need to be checked for - * validity (MAXLNUM means no check needed) - */ - synstate_T *b_sst_array; - int b_sst_len; - synstate_T *b_sst_first; - synstate_T *b_sst_firstfree; - int b_sst_freecount; - linenr_T b_sst_check_lnum; - short_u b_sst_lasttick; /* last display tick */ -#endif /* FEAT_SYN_HL */ - -#ifdef FEAT_SPELL - /* for spell checking */ - garray_T b_langp; /* list of pointers to slang_T, see spell.c */ - char_u b_spell_ismw[256];/* flags: is midword char */ -# ifdef FEAT_MBYTE - char_u *b_spell_ismw_mb; /* multi-byte midword chars */ -# endif +#if defined(FEAT_SYN_HL) || defined(FEAT_SPELL) + synblock_T b_s; /* Info related to syntax highlighting. w_s + * normally points to this, but some windows + * may use a different synblock_T. */ #endif #ifdef FEAT_SIGNS @@ -1767,6 +1791,10 @@ struct window_S buf_T *w_buffer; /* buffer we are a window into (used often, keep it the first item!) */ +#if defined(FEAT_SYN_HL) || defined(FEAT_SPELL) + synblock_T *w_s; +#endif + #ifdef FEAT_WINDOWS win_T *w_prev; /* link to previous window */ win_T *w_next; /* link to next window */ diff --git a/src/syntax.c b/src/syntax.c index 961348290..c19c5d964 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -140,7 +140,10 @@ typedef struct syn_pattern { char sp_type; /* see SPTYPE_ defines below */ char sp_syncing; /* this item used for syncing */ - short sp_flags; /* see HL_ defines below */ + int sp_flags; /* see HL_ defines below */ +#ifdef FEAT_CONCEAL + int sp_char; /* conceal substitute character */ +#endif struct sp_syn sp_syn; /* struct passed to in_id_list() */ short sp_syn_match_id; /* highlight group ID of pattern */ char_u *sp_pattern; /* regexp to match, pattern */ @@ -166,25 +169,6 @@ typedef struct syn_pattern #define SPTYPE_END 3 /* match a regexp, end of item */ #define SPTYPE_SKIP 4 /* match a regexp, skip within item */ -#define HL_CONTAINED 0x01 /* not used on toplevel */ -#define HL_TRANSP 0x02 /* has no highlighting */ -#define HL_ONELINE 0x04 /* match within one line only */ -#define HL_HAS_EOL 0x08 /* end pattern that matches with $ */ -#define HL_SYNC_HERE 0x10 /* sync point after this item (syncing only) */ -#define HL_SYNC_THERE 0x20 /* sync point at current line (syncing only) */ -#define HL_MATCH 0x40 /* use match ID instead of item ID */ -#define HL_SKIPNL 0x80 /* nextgroup can skip newlines */ -#define HL_SKIPWHITE 0x100 /* nextgroup can skip white space */ -#define HL_SKIPEMPTY 0x200 /* nextgroup can skip empty lines */ -#define HL_KEEPEND 0x400 /* end match always kept */ -#define HL_EXCLUDENL 0x800 /* exclude NL from match */ -#define HL_DISPLAY 0x1000 /* only used for displaying, not syncing */ -#define HL_FOLD 0x2000 /* define fold */ -#define HL_EXTEND 0x4000 /* ignore a keepend */ -/* These don't fit in a short, thus can't be used for syntax items, only for - * si_flags and bs_flags. */ -#define HL_MATCHCONT 0x8000 /* match continued from previous line */ -#define HL_TRANS_CONT 0x10000L /* transparent item without contains arg */ #define SYN_ITEMS(buf) ((synpat_T *)((buf)->b_syn_patterns.ga_data)) @@ -208,6 +192,10 @@ static int current_attr = 0; /* attr of current syntax word */ static int current_id = 0; /* ID of current char for syn_get_id() */ static int current_trans_id = 0; /* idem, transparency removed */ #endif +#ifdef FEAT_CONCEAL +static int current_flags = 0; +static int current_sub_char = 0; +#endif typedef struct syn_cluster_S { @@ -294,6 +282,9 @@ typedef struct state_item int si_attr; /* attributes in this state */ long si_flags; /* HL_HAS_EOL flag in this state, and * HL_SKIP* for si_next_list */ +#ifdef FEAT_CONCEAL + int si_char; /* substitution character for conceal */ +#endif short *si_cont_list; /* list of contained groups */ short *si_next_list; /* nextgroup IDs after this item ends */ reg_extmatch_T *si_extmatch; /* \z(...\) matches from start @@ -351,6 +342,7 @@ static reg_extmatch_T *next_match_extmatch = NULL; */ static win_T *syn_win; /* current window for highlighting */ static buf_T *syn_buf; /* current buffer for highlighting */ +static synblock_T *syn_block; /* current buffer for highlighting */ static linenr_T current_lnum = 0; /* lnum of current state */ static colnr_T current_col = 0; /* column of current state */ static int current_state_stored = 0; /* TRUE if stored current state @@ -370,7 +362,7 @@ static void syn_start_line __ARGS((void)); static void syn_update_ends __ARGS((int startofline)); static void syn_stack_alloc __ARGS((void)); static int syn_stack_cleanup __ARGS((void)); -static void syn_stack_free_entry __ARGS((buf_T *buf, synstate_T *p)); +static void syn_stack_free_entry __ARGS((synblock_T *block, synstate_T *p)); static synstate_T *syn_stack_find_entry __ARGS((linenr_T lnum)); static synstate_T *store_current_state __ARGS((void)); static void load_current_state __ARGS((synstate_T *from)); @@ -390,6 +382,7 @@ static int in_id_list __ARGS((stateitem_T *item, short *cont_list, struct sp_syn static int push_current_state __ARGS((int idx)); static void pop_current_state __ARGS((void)); +static void syn_stack_apply_changes_block __ARGS((synblock_T *block, buf_T *buf)); static void find_endpos __ARGS((int idx, lpos_T *startpos, lpos_T *m_endpos, lpos_T *hl_endpos, long *flagsp, lpos_T *end_endpos, int *end_idx, reg_extmatch_T *start_ext)); static void clear_syn_state __ARGS((synstate_T *p)); static void clear_current_state __ARGS((void)); @@ -400,14 +393,15 @@ static void syn_add_end_off __ARGS((lpos_T *result, regmmatch_T *regmatch, synpa static void syn_add_start_off __ARGS((lpos_T *result, regmmatch_T *regmatch, synpat_T *spp, int idx, int extra)); static char_u *syn_getcurline __ARGS((void)); static int syn_regexec __ARGS((regmmatch_T *rmp, linenr_T lnum, colnr_T col)); -static int check_keyword_id __ARGS((char_u *line, int startcol, int *endcol, long *flags, short **next_list, stateitem_T *cur_si)); +static int check_keyword_id __ARGS((char_u *line, int startcol, int *endcol, long *flags, short **next_list, stateitem_T *cur_si, int *ccharp)); static void syn_cmd_case __ARGS((exarg_T *eap, int syncing)); static void syn_cmd_spell __ARGS((exarg_T *eap, int syncing)); static void syntax_sync_clear __ARGS((void)); -static void syn_remove_pattern __ARGS((buf_T *buf, int idx)); -static void syn_clear_pattern __ARGS((buf_T *buf, int i)); -static void syn_clear_cluster __ARGS((buf_T *buf, int i)); +static void syn_remove_pattern __ARGS((synblock_T *block, int idx)); +static void syn_clear_pattern __ARGS((synblock_T *block, int i)); +static void syn_clear_cluster __ARGS((synblock_T *block, int i)); static void syn_cmd_clear __ARGS((exarg_T *eap, int syncing)); +static void syn_cmd_conceal __ARGS((exarg_T *eap, int syncing)); static void syn_clear_one __ARGS((int id, int syncing)); static void syn_cmd_on __ARGS((exarg_T *eap, int syncing)); static void syn_cmd_enable __ARGS((exarg_T *eap, int syncing)); @@ -418,6 +412,7 @@ static void syn_cmd_onoff __ARGS((exarg_T *eap, char *name)); static void syn_cmd_list __ARGS((exarg_T *eap, int syncing)); static void syn_lines_msg __ARGS((void)); static void syn_match_msg __ARGS((void)); +static void syn_stack_free_block __ARGS((synblock_T *block)); static void syn_list_one __ARGS((int id, int syncing, int link_only)); static void syn_list_cluster __ARGS((int id)); static void put_id_list __ARGS((char_u *name, short *list, int attr)); @@ -425,9 +420,9 @@ static void put_pattern __ARGS((char *s, int c, synpat_T *spp, int attr)); static int syn_list_keywords __ARGS((int id, hashtab_T *ht, int did_header, int attr)); static void syn_clear_keyword __ARGS((int id, hashtab_T *ht)); static void clear_keywtab __ARGS((hashtab_T *ht)); -static void add_keyword __ARGS((char_u *name, int id, int flags, short *cont_in_list, short *next_list)); +static void add_keyword __ARGS((char_u *name, int id, int flags, short *cont_in_list, short *next_list, int conceal_char)); static char_u *get_group_name __ARGS((char_u *arg, char_u **name_end)); -static char_u *get_syn_options __ARGS((char_u *arg, syn_opt_arg_T *opt)); +static char_u *get_syn_options __ARGS((char_u *arg, syn_opt_arg_T *opt, int *conceal_char)); static void syn_cmd_include __ARGS((exarg_T *eap, int syncing)); static void syn_cmd_keyword __ARGS((exarg_T *eap, int syncing)); static void syn_cmd_match __ARGS((exarg_T *eap, int syncing)); @@ -475,10 +470,11 @@ syntax_start(wp, lnum) * Also do this when a change was made, the current state may be invalid * then. */ - if (syn_buf != wp->w_buffer || changedtick != syn_buf->b_changedtick) + if (syn_block != wp->w_s || changedtick != syn_buf->b_changedtick) { invalidate_current_state(); syn_buf = wp->w_buffer; + syn_block = wp->w_s; } changedtick = syn_buf->b_changedtick; syn_win = wp; @@ -487,9 +483,9 @@ syntax_start(wp, lnum) * Allocate syntax stack when needed. */ syn_stack_alloc(); - if (syn_buf->b_sst_array == NULL) + if (syn_block->b_sst_array == NULL) return; /* out of memory */ - syn_buf->b_sst_lasttick = display_tick; + syn_block->b_sst_lasttick = display_tick; /* * If the state of the end of the previous line is useful, store it. @@ -520,17 +516,17 @@ syntax_start(wp, lnum) * Try to synchronize from a saved state in b_sst_array[]. * Only do this if lnum is not before and not to far beyond a saved state. */ - if (INVALID_STATE(¤t_state) && syn_buf->b_sst_array != NULL) + if (INVALID_STATE(¤t_state) && syn_block->b_sst_array != NULL) { /* Find last valid saved state before start_lnum. */ - for (p = syn_buf->b_sst_first; p != NULL; p = p->sst_next) + for (p = syn_block->b_sst_first; p != NULL; p = p->sst_next) { if (p->sst_lnum > lnum) break; if (p->sst_lnum <= lnum && p->sst_change_lnum == 0) { last_valid = p; - if (p->sst_lnum >= lnum - syn_buf->b_syn_sync_minlines) + if (p->sst_lnum >= lnum - syn_block->b_syn_sync_minlines) last_min_valid = p; } } @@ -545,7 +541,7 @@ syntax_start(wp, lnum) if (INVALID_STATE(¤t_state)) { syn_sync(wp, lnum, last_valid); - first_stored = current_lnum + syn_buf->b_syn_sync_minlines; + first_stored = current_lnum + syn_block->b_syn_sync_minlines; } else first_stored = current_lnum; @@ -554,10 +550,10 @@ syntax_start(wp, lnum) * Advance from the sync point or saved state until the current line. * Save some entries for syncing with later on. */ - if (syn_buf->b_sst_len <= Rows) + if (syn_block->b_sst_len <= Rows) dist = 999999; else - dist = syn_buf->b_ml.ml_line_count / (syn_buf->b_sst_len - Rows) + 1; + dist = syn_buf->b_ml.ml_line_count / (syn_block->b_sst_len - Rows) + 1; while (current_lnum < lnum) { syn_start_line(); @@ -574,7 +570,7 @@ syntax_start(wp, lnum) if (prev == NULL) prev = syn_stack_find_entry(current_lnum - 1); if (prev == NULL) - sp = syn_buf->b_sst_first; + sp = syn_block->b_sst_first; else sp = prev; while (sp != NULL && sp->sst_lnum < current_lnum) @@ -706,19 +702,19 @@ syn_sync(wp, start_lnum, last_valid) * where N is minlines * 1.5, or minlines * 2 if minlines is small. * Watch out for overflow when minlines is MAXLNUM. */ - if (syn_buf->b_syn_sync_minlines > start_lnum) + if (syn_block->b_syn_sync_minlines > start_lnum) start_lnum = 1; else { - if (syn_buf->b_syn_sync_minlines == 1) + if (syn_block->b_syn_sync_minlines == 1) lnum = 1; - else if (syn_buf->b_syn_sync_minlines < 10) - lnum = syn_buf->b_syn_sync_minlines * 2; + else if (syn_block->b_syn_sync_minlines < 10) + lnum = syn_block->b_syn_sync_minlines * 2; else - lnum = syn_buf->b_syn_sync_minlines * 3 / 2; - if (syn_buf->b_syn_sync_maxlines != 0 - && lnum > syn_buf->b_syn_sync_maxlines) - lnum = syn_buf->b_syn_sync_maxlines; + lnum = syn_block->b_syn_sync_minlines * 3 / 2; + if (syn_block->b_syn_sync_maxlines != 0 + && lnum > syn_block->b_syn_sync_maxlines) + lnum = syn_block->b_syn_sync_maxlines; if (lnum >= start_lnum) start_lnum = 1; else @@ -729,7 +725,7 @@ syn_sync(wp, start_lnum, last_valid) /* * 1. Search backwards for the end of a C-style comment. */ - if (syn_buf->b_syn_sync_flags & SF_CCOMMENT) + if (syn_block->b_syn_sync_flags & SF_CCOMMENT) { /* Need to make syn_buf the current buffer for a moment, to be able to * use find_start_comment(). */ @@ -759,11 +755,12 @@ syn_sync(wp, start_lnum, last_valid) * defines the comment. * Restrict the search for the end of a comment to b_syn_sync_maxlines. */ - if (find_start_comment((int)syn_buf->b_syn_sync_maxlines) != NULL) + if (find_start_comment((int)syn_block->b_syn_sync_maxlines) != NULL) { - for (idx = syn_buf->b_syn_patterns.ga_len; --idx >= 0; ) - if (SYN_ITEMS(syn_buf)[idx].sp_syn.id == syn_buf->b_syn_sync_id - && SYN_ITEMS(syn_buf)[idx].sp_type == SPTYPE_START) + for (idx = syn_block->b_syn_patterns.ga_len; --idx >= 0; ) + if (SYN_ITEMS(syn_block)[idx].sp_syn.id + == syn_block->b_syn_sync_id + && SYN_ITEMS(syn_block)[idx].sp_type == SPTYPE_START) { validate_current_state(); if (push_current_state(idx) == OK) @@ -781,11 +778,11 @@ syn_sync(wp, start_lnum, last_valid) /* * 2. Search backwards for given sync patterns. */ - else if (syn_buf->b_syn_sync_flags & SF_MATCH) + else if (syn_block->b_syn_sync_flags & SF_MATCH) { - if (syn_buf->b_syn_sync_maxlines != 0 - && start_lnum > syn_buf->b_syn_sync_maxlines) - break_lnum = start_lnum - syn_buf->b_syn_sync_maxlines; + if (syn_block->b_syn_sync_maxlines != 0 + && start_lnum > syn_block->b_syn_sync_maxlines) + break_lnum = start_lnum - syn_block->b_syn_sync_maxlines; else break_lnum = 0; @@ -849,7 +846,7 @@ syn_sync(wp, start_lnum, last_valid) } else { - spp = &(SYN_ITEMS(syn_buf)[cur_si->si_idx]); + spp = &(SYN_ITEMS(syn_block)[cur_si->si_idx]); found_flags = spp->sp_flags; found_match_idx = spp->sp_sync_idx; } @@ -952,10 +949,10 @@ syn_match_linecont(lnum) { regmmatch_T regmatch; - if (syn_buf->b_syn_linecont_prog != NULL) + if (syn_block->b_syn_linecont_prog != NULL) { - regmatch.rmm_ic = syn_buf->b_syn_linecont_ic; - regmatch.regprog = syn_buf->b_syn_linecont_prog; + regmatch.rmm_ic = syn_block->b_syn_linecont_ic; + regmatch.regprog = syn_block->b_syn_linecont_prog; return syn_regexec(®match, lnum, (colnr_T)0); } return FALSE; @@ -1002,7 +999,7 @@ syn_update_ends(startofline) { cur_si = &CUR_STATE(i); if (cur_si->si_idx >= 0 - && (SYN_ITEMS(syn_buf)[cur_si->si_idx]).sp_type + && (SYN_ITEMS(syn_block)[cur_si->si_idx]).sp_type == SPTYPE_MATCH && cur_si->si_m_endpos.lnum < current_lnum) { @@ -1088,30 +1085,39 @@ syn_update_ends(startofline) * number of entries SST_MAX_ENTRIES, and the distance is computed. */ + static void +syn_stack_free_block(block) + synblock_T *block; +{ + synstate_T *p; + + if (block->b_sst_array != NULL) + { + for (p = block->b_sst_first; p != NULL; p = p->sst_next) + clear_syn_state(p); + vim_free(block->b_sst_array); + block->b_sst_array = NULL; + block->b_sst_len = 0; + } +} /* * Free b_sst_array[] for buffer "buf". * Used when syntax items changed to force resyncing everywhere. */ void -syn_stack_free_all(buf) - buf_T *buf; +syn_stack_free_all(block) + synblock_T *block; { - synstate_T *p; win_T *wp; - if (buf->b_sst_array != NULL) - { - for (p = buf->b_sst_first; p != NULL; p = p->sst_next) - clear_syn_state(p); - vim_free(buf->b_sst_array); - buf->b_sst_array = NULL; - buf->b_sst_len = 0; - } + syn_stack_free_block(block); + + #ifdef FEAT_FOLDING /* When using "syntax" fold method, must update all folds. */ FOR_ALL_WINDOWS(wp) { - if (wp->w_buffer == buf && foldmethodIsSyntax(wp)) + if (wp->w_s == block && foldmethodIsSyntax(wp)) foldUpdateAll(wp); } #endif @@ -1135,7 +1141,7 @@ syn_stack_alloc() len = SST_MIN_ENTRIES; else if (len > SST_MAX_ENTRIES) len = SST_MAX_ENTRIES; - if (syn_buf->b_sst_len > len * 2 || syn_buf->b_sst_len < len) + if (syn_block->b_sst_len > len * 2 || syn_block->b_sst_len < len) { /* Allocate 50% too much, to avoid reallocating too often. */ len = syn_buf->b_ml.ml_line_count; @@ -1145,15 +1151,15 @@ syn_stack_alloc() else if (len > SST_MAX_ENTRIES) len = SST_MAX_ENTRIES; - if (syn_buf->b_sst_array != NULL) + if (syn_block->b_sst_array != NULL) { /* When shrinking the array, cleanup the existing stack. * Make sure that all valid entries fit in the new array. */ - while (syn_buf->b_sst_len - syn_buf->b_sst_freecount + 2 > len + while (syn_block->b_sst_len - syn_block->b_sst_freecount + 2 > len && syn_stack_cleanup()) ; - if (len < syn_buf->b_sst_len - syn_buf->b_sst_freecount + 2) - len = syn_buf->b_sst_len - syn_buf->b_sst_freecount + 2; + if (len < syn_block->b_sst_len - syn_block->b_sst_freecount + 2) + len = syn_block->b_sst_len - syn_block->b_sst_freecount + 2; } sstp = (synstate_T *)alloc_clear((unsigned)(len * sizeof(synstate_T))); @@ -1161,10 +1167,10 @@ syn_stack_alloc() return; to = sstp - 1; - if (syn_buf->b_sst_array != NULL) + if (syn_block->b_sst_array != NULL) { /* Move the states from the old array to the new one. */ - for (from = syn_buf->b_sst_first; from != NULL; + for (from = syn_block->b_sst_first; from != NULL; from = from->sst_next) { ++to; @@ -1175,24 +1181,24 @@ syn_stack_alloc() if (to != sstp - 1) { to->sst_next = NULL; - syn_buf->b_sst_first = sstp; - syn_buf->b_sst_freecount = len - (int)(to - sstp) - 1; + syn_block->b_sst_first = sstp; + syn_block->b_sst_freecount = len - (int)(to - sstp) - 1; } else { - syn_buf->b_sst_first = NULL; - syn_buf->b_sst_freecount = len; + syn_block->b_sst_first = NULL; + syn_block->b_sst_freecount = len; } /* Create the list of free entries. */ - syn_buf->b_sst_firstfree = to + 1; + syn_block->b_sst_firstfree = to + 1; while (++to < sstp + len) to->sst_next = to + 1; (sstp + len - 1)->sst_next = NULL; - vim_free(syn_buf->b_sst_array); - syn_buf->b_sst_array = sstp; - syn_buf->b_sst_len = len; + vim_free(syn_block->b_sst_array); + syn_block->b_sst_array = sstp; + syn_block->b_sst_len = len; } } @@ -1206,16 +1212,32 @@ syn_stack_alloc() syn_stack_apply_changes(buf) buf_T *buf; { + win_T *wp; + + syn_stack_apply_changes_block(&buf->b_s, buf); + + FOR_ALL_WINDOWS(wp) + { + if ((wp->w_buffer == buf) && (wp->w_s != &buf->b_s)) + syn_stack_apply_changes_block(wp->w_s, buf); + } +} + + static void +syn_stack_apply_changes_block(block, buf) + synblock_T *block; + buf_T *buf; +{ synstate_T *p, *prev, *np; linenr_T n; - if (buf->b_sst_array == NULL) /* nothing to do */ + if (block->b_sst_array == NULL) /* nothing to do */ return; prev = NULL; - for (p = buf->b_sst_first; p != NULL; ) + for (p = block->b_sst_first; p != NULL; ) { - if (p->sst_lnum + buf->b_syn_sync_linebreaks > buf->b_mod_top) + if (p->sst_lnum + block->b_syn_sync_linebreaks > buf->b_mod_top) { n = p->sst_lnum + buf->b_mod_xlines; if (n <= buf->b_mod_bot) @@ -1223,10 +1245,10 @@ syn_stack_apply_changes(buf) /* this state is inside the changed area, remove it */ np = p->sst_next; if (prev == NULL) - buf->b_sst_first = np; + block->b_sst_first = np; else prev->sst_next = np; - syn_stack_free_entry(buf, p); + syn_stack_free_entry(block, p); p = np; continue; } @@ -1264,28 +1286,28 @@ syn_stack_cleanup() int dist; int retval = FALSE; - if (syn_buf->b_sst_array == NULL || syn_buf->b_sst_first == NULL) + if (syn_block->b_sst_array == NULL || syn_block->b_sst_first == NULL) return retval; /* Compute normal distance between non-displayed entries. */ - if (syn_buf->b_sst_len <= Rows) + if (syn_block->b_sst_len <= Rows) dist = 999999; else - dist = syn_buf->b_ml.ml_line_count / (syn_buf->b_sst_len - Rows) + 1; + dist = syn_buf->b_ml.ml_line_count / (syn_block->b_sst_len - Rows) + 1; /* * Go through the list to find the "tick" for the oldest entry that can * be removed. Set "above" when the "tick" for the oldest entry is above * "b_sst_lasttick" (the display tick wraps around). */ - tick = syn_buf->b_sst_lasttick; + tick = syn_block->b_sst_lasttick; above = FALSE; - prev = syn_buf->b_sst_first; + prev = syn_block->b_sst_first; for (p = prev->sst_next; p != NULL; prev = p, p = p->sst_next) { if (prev->sst_lnum + dist > p->sst_lnum) { - if (p->sst_tick > syn_buf->b_sst_lasttick) + if (p->sst_tick > syn_block->b_sst_lasttick) { if (!above || p->sst_tick < tick) tick = p->sst_tick; @@ -1300,14 +1322,14 @@ syn_stack_cleanup() * Go through the list to make the entries for the oldest tick at an * interval of several lines. */ - prev = syn_buf->b_sst_first; + prev = syn_block->b_sst_first; for (p = prev->sst_next; p != NULL; prev = p, p = p->sst_next) { if (p->sst_tick == tick && prev->sst_lnum + dist > p->sst_lnum) { /* Move this entry from used list to free list */ prev->sst_next = p->sst_next; - syn_stack_free_entry(syn_buf, p); + syn_stack_free_entry(syn_block, p); p = prev; retval = TRUE; } @@ -1320,14 +1342,14 @@ syn_stack_cleanup() * Move the entry into the free list. */ static void -syn_stack_free_entry(buf, p) - buf_T *buf; +syn_stack_free_entry(block, p) + synblock_T *block; synstate_T *p; { clear_syn_state(p); - p->sst_next = buf->b_sst_firstfree; - buf->b_sst_firstfree = p; - ++buf->b_sst_freecount; + p->sst_next = block->b_sst_firstfree; + block->b_sst_firstfree = p; + ++block->b_sst_freecount; } /* @@ -1341,7 +1363,7 @@ syn_stack_find_entry(lnum) synstate_T *p, *prev; prev = NULL; - for (p = syn_buf->b_sst_first; p != NULL; prev = p, p = p->sst_next) + for (p = syn_block->b_sst_first; p != NULL; prev = p, p = p->sst_next) { if (p->sst_lnum == lnum) return p; @@ -1383,19 +1405,19 @@ store_current_state() if (sp != NULL) { /* find "sp" in the list and remove it */ - if (syn_buf->b_sst_first == sp) + if (syn_block->b_sst_first == sp) /* it's the first entry */ - syn_buf->b_sst_first = sp->sst_next; + syn_block->b_sst_first = sp->sst_next; else { /* find the entry just before this one to adjust sst_next */ - for (p = syn_buf->b_sst_first; p != NULL; p = p->sst_next) + for (p = syn_block->b_sst_first; p != NULL; p = p->sst_next) if (p->sst_next == sp) break; if (p != NULL) /* just in case */ p->sst_next = sp->sst_next; } - syn_stack_free_entry(syn_buf, sp); + syn_stack_free_entry(syn_block, sp); sp = NULL; } } @@ -1405,27 +1427,27 @@ store_current_state() * Add a new entry */ /* If no free items, cleanup the array first. */ - if (syn_buf->b_sst_freecount == 0) + if (syn_block->b_sst_freecount == 0) { (void)syn_stack_cleanup(); /* "sp" may have been moved to the freelist now */ sp = syn_stack_find_entry(current_lnum); } /* Still no free items? Must be a strange problem... */ - if (syn_buf->b_sst_freecount == 0) + if (syn_block->b_sst_freecount == 0) sp = NULL; else { /* Take the first item from the free list and put it in the used * list, after *sp */ - p = syn_buf->b_sst_firstfree; - syn_buf->b_sst_firstfree = p->sst_next; - --syn_buf->b_sst_freecount; + p = syn_block->b_sst_firstfree; + syn_block->b_sst_firstfree = p->sst_next; + --syn_block->b_sst_freecount; if (sp == NULL) { /* Insert in front of the list */ - p->sst_next = syn_buf->b_sst_first; - syn_buf->b_sst_first = p; + p->sst_next = syn_block->b_sst_first; + syn_block->b_sst_first = p; } else { @@ -1502,7 +1524,7 @@ load_current_state(from) CUR_STATE(i).si_m_lnum = 0; if (CUR_STATE(i).si_idx >= 0) CUR_STATE(i).si_next_list = - (SYN_ITEMS(syn_buf)[CUR_STATE(i).si_idx]).sp_next_list; + (SYN_ITEMS(syn_block)[CUR_STATE(i).si_idx]).sp_next_list; else CUR_STATE(i).si_next_list = NULL; update_si_attr(i); @@ -1564,7 +1586,7 @@ syn_stack_equal(sp) if (bsx->matches[j] == NULL || six->matches[j] == NULL) break; - if ((SYN_ITEMS(syn_buf)[CUR_STATE(i).si_idx]).sp_ic + if ((SYN_ITEMS(syn_block)[CUR_STATE(i).si_idx]).sp_ic ? MB_STRICMP(bsx->matches[j], six->matches[j]) != 0 : STRCMP(bsx->matches[j], six->matches[j]) != 0) @@ -1701,7 +1723,7 @@ syn_finish_line(syncing) */ cur_si = &CUR_STATE(current_state.ga_len - 1); if (cur_si->si_idx >= 0 - && (SYN_ITEMS(syn_buf)[cur_si->si_idx].sp_flags + && (SYN_ITEMS(syn_block)[cur_si->si_idx].sp_flags & (HL_SYNC_HERE|HL_SYNC_THERE))) return TRUE; @@ -1730,8 +1752,9 @@ syn_finish_line(syncing) * done. */ int -get_syntax_attr(col, can_spell, keep_state) +get_syntax_attr(col, p_flags, can_spell, keep_state) colnr_T col; + int *p_flags UNUSED; int *can_spell; int keep_state; /* keep state of char at "col" */ { @@ -1740,12 +1763,12 @@ get_syntax_attr(col, can_spell, keep_state) if (can_spell != NULL) /* Default: Only do spelling when there is no @Spell cluster or when * ":syn spell toplevel" was used. */ - *can_spell = syn_buf->b_syn_spell == SYNSPL_DEFAULT - ? (syn_buf->b_spell_cluster_id == 0) - : (syn_buf->b_syn_spell == SYNSPL_TOP); + *can_spell = syn_block->b_syn_spell == SYNSPL_DEFAULT + ? (syn_block->b_spell_cluster_id == 0) + : (syn_block->b_syn_spell == SYNSPL_TOP); /* check for out of memory situation */ - if (syn_buf->b_sst_array == NULL) + if (syn_block->b_sst_array == NULL) return 0; /* After 'synmaxcol' the attribute is always zero. */ @@ -1773,6 +1796,10 @@ get_syntax_attr(col, can_spell, keep_state) ++current_col; } +#ifdef FEAT_CONCEAL + if (p_flags != NULL) + *p_flags = current_flags; +#endif return attr; } @@ -1799,6 +1826,7 @@ syn_current_attr(syncing, displaying, can_spell, keep_state) int startcol; int endcol; long flags; + int cchar; short *next_list; int found_match; /* found usable match */ static int try_next_column = FALSE; /* must try in next col */ @@ -1854,8 +1882,8 @@ syn_current_attr(syncing, displaying, can_spell, keep_state) /* Only check for keywords when not syncing and there are some. */ do_keywords = !syncing - && (syn_buf->b_keywtab.ht_used > 0 - || syn_buf->b_keywtab_ic.ht_used > 0); + && (syn_block->b_keywtab.ht_used > 0 + || syn_block->b_keywtab_ic.ht_used > 0); /* Init the list of zero-width matches with a nextlist. This is used to * avoid matching the same item in the same position twice. */ @@ -1884,7 +1912,7 @@ syn_current_attr(syncing, displaying, can_spell, keep_state) else cur_si = NULL; - if (syn_buf->b_syn_containedin || cur_si == NULL + if (syn_block->b_syn_containedin || cur_si == NULL || cur_si->si_cont_list != NULL) { /* @@ -1905,7 +1933,8 @@ syn_current_attr(syncing, displaying, can_spell, keep_state) , syn_buf))) { syn_id = check_keyword_id(line, (int)current_col, - &endcol, &flags, &next_list, cur_si); + &endcol, &flags, &next_list, cur_si, + &cchar); if (syn_id != 0) { if (push_current_state(KEYWORD_IDX) == OK) @@ -1921,6 +1950,13 @@ syn_current_attr(syncing, displaying, can_spell, keep_state) cur_si->si_ends = TRUE; cur_si->si_end_idx = 0; cur_si->si_flags = flags; +#ifdef FEAT_CONCEAL + cur_si->si_char = cchar; + if (current_state.ga_len > 1) + cur_si->si_flags |= + CUR_STATE(current_state.ga_len - 2).si_flags + & HL_CONCEAL; +#endif cur_si->si_id = syn_id; cur_si->si_trans_id = syn_id; if (flags & HL_TRANSP) @@ -1953,7 +1989,7 @@ syn_current_attr(syncing, displaying, can_spell, keep_state) /* * 3. Check for patterns (only if no keyword found). */ - if (syn_id == 0 && syn_buf->b_syn_patterns.ga_len) + if (syn_id == 0 && syn_block->b_syn_patterns.ga_len) { /* * If we didn't check for a match yet, or we are past it, check @@ -1969,9 +2005,9 @@ syn_current_attr(syncing, displaying, can_spell, keep_state) */ next_match_idx = 0; /* no match in this line yet */ next_match_col = MAXCOL; - for (idx = syn_buf->b_syn_patterns.ga_len; --idx >= 0; ) + for (idx = syn_block->b_syn_patterns.ga_len; --idx >= 0; ) { - spp = &(SYN_ITEMS(syn_buf)[idx]); + spp = &(SYN_ITEMS(syn_block)[idx]); if ( spp->sp_syncing == syncing && (displaying || !(spp->sp_flags & HL_DISPLAY)) && (spp->sp_type == SPTYPE_MATCH @@ -2147,7 +2183,7 @@ syn_current_attr(syncing, displaying, can_spell, keep_state) /* When a zero-width item matched which has a nextgroup, * don't push the item but set nextgroup. */ - lspp = &(SYN_ITEMS(syn_buf)[next_match_idx]); + lspp = &(SYN_ITEMS(syn_block)[next_match_idx]); if (next_match_m_endpos.lnum == current_lnum && next_match_m_endpos.col == current_col && lspp->sp_next_list != NULL) @@ -2219,6 +2255,9 @@ syn_current_attr(syncing, displaying, can_spell, keep_state) current_id = 0; current_trans_id = 0; #endif +#ifdef FEAT_CONCEAL + current_flags = 0; +#endif if (cur_si != NULL) { #ifndef FEAT_EVAL @@ -2240,6 +2279,10 @@ syn_current_attr(syncing, displaying, can_spell, keep_state) current_id = sip->si_id; #endif current_trans_id = sip->si_trans_id; +#ifdef FEAT_CONCEAL + current_flags = sip->si_flags; + current_sub_char = sip->si_char; +#endif break; } } @@ -2252,16 +2295,17 @@ syn_current_attr(syncing, displaying, can_spell, keep_state) * set "can_spell" to TRUE if spell checking is supposed to be * done in the current item. */ - if (syn_buf->b_spell_cluster_id == 0) + if (syn_block->b_spell_cluster_id == 0) { /* There is no @Spell cluster: Do spelling for items without * @NoSpell cluster. */ - if (syn_buf->b_nospell_cluster_id == 0 || current_trans_id == 0) - *can_spell = (syn_buf->b_syn_spell != SYNSPL_NOTOP); + if (syn_block->b_nospell_cluster_id == 0 + || current_trans_id == 0) + *can_spell = (syn_block->b_syn_spell != SYNSPL_NOTOP); else { sps.inc_tag = 0; - sps.id = syn_buf->b_nospell_cluster_id; + sps.id = syn_block->b_nospell_cluster_id; sps.cont_in_list = NULL; *can_spell = !in_id_list(sip, sip->si_cont_list, &sps, 0); } @@ -2273,17 +2317,17 @@ syn_current_attr(syncing, displaying, can_spell, keep_state) * At the toplevel only spell check when ":syn spell toplevel" * was used. */ if (current_trans_id == 0) - *can_spell = (syn_buf->b_syn_spell == SYNSPL_TOP); + *can_spell = (syn_block->b_syn_spell == SYNSPL_TOP); else { sps.inc_tag = 0; - sps.id = syn_buf->b_spell_cluster_id; + sps.id = syn_block->b_spell_cluster_id; sps.cont_in_list = NULL; *can_spell = in_id_list(sip, sip->si_cont_list, &sps, 0); - if (syn_buf->b_nospell_cluster_id != 0) + if (syn_block->b_nospell_cluster_id != 0) { - sps.id = syn_buf->b_nospell_cluster_id; + sps.id = syn_block->b_nospell_cluster_id; if (in_id_list(sip, sip->si_cont_list, &sps, 0)) *can_spell = FALSE; } @@ -2315,9 +2359,9 @@ syn_current_attr(syncing, displaying, can_spell, keep_state) else if (can_spell != NULL) /* Default: Only do spelling when there is no @Spell cluster or when * ":syn spell toplevel" was used. */ - *can_spell = syn_buf->b_syn_spell == SYNSPL_DEFAULT - ? (syn_buf->b_spell_cluster_id == 0) - : (syn_buf->b_syn_spell == SYNSPL_TOP); + *can_spell = syn_block->b_syn_spell == SYNSPL_DEFAULT + ? (syn_block->b_spell_cluster_id == 0) + : (syn_block->b_syn_spell == SYNSPL_TOP); /* nextgroup ends at end of line, unless "skipnl" or "skipempty" present */ if (current_next_list != NULL @@ -2370,8 +2414,11 @@ push_next_match(cur_si) stateitem_T *cur_si; { synpat_T *spp; +#ifdef FEAT_CONCEAL + int save_flags; +#endif - spp = &(SYN_ITEMS(syn_buf)[next_match_idx]); + spp = &(SYN_ITEMS(syn_block)[next_match_idx]); /* * Push the item in current_state stack; @@ -2387,6 +2434,12 @@ push_next_match(cur_si) cur_si->si_m_startcol = current_col; cur_si->si_m_lnum = current_lnum; cur_si->si_flags = spp->sp_flags; +#ifdef FEAT_CONCEAL + cur_si->si_char = spp->sp_char; + if (current_state.ga_len > 1) + cur_si->si_flags |= + CUR_STATE(current_state.ga_len - 2).si_flags & HL_CONCEAL; +#endif cur_si->si_next_list = spp->sp_next_list; cur_si->si_extmatch = ref_extmatch(next_match_extmatch); if (spp->sp_type == SPTYPE_START && !(spp->sp_flags & HL_ONELINE)) @@ -2409,6 +2462,9 @@ push_next_match(cur_si) check_keepend(); update_si_attr(current_state.ga_len - 1); +#ifdef FEAT_CONCEAL + save_flags = cur_si->si_flags & (HL_CONCEAL | HL_CONCEALENDS); +#endif /* * If the start pattern has another highlight group, push another item * on the stack for the start pattern. @@ -2426,6 +2482,11 @@ push_next_match(cur_si) cur_si->si_ends = TRUE; cur_si->si_end_idx = 0; cur_si->si_flags = HL_MATCH; +#ifdef FEAT_CONCEAL + cur_si->si_flags |= save_flags; + if (cur_si->si_flags & HL_CONCEALENDS) + cur_si->si_flags |= HL_CONCEAL; +#endif cur_si->si_next_list = NULL; check_keepend(); update_si_attr(current_state.ga_len - 1); @@ -2470,6 +2531,10 @@ check_state_ends() cur_si->si_m_endpos = cur_si->si_eoe_pos; cur_si->si_h_endpos = cur_si->si_eoe_pos; cur_si->si_flags |= HL_MATCH; +#ifdef FEAT_CONCEAL + if (cur_si->si_flags & HL_CONCEALENDS) + cur_si->si_flags |= HL_CONCEAL; +#endif update_si_attr(current_state.ga_len - 1); /* what matches next may be different now, clear it */ @@ -2516,7 +2581,7 @@ check_state_ends() * - "excludenl" is used (HL_HAS_EOL won't be set) */ if (cur_si->si_idx >= 0 - && SYN_ITEMS(syn_buf)[cur_si->si_idx].sp_type + && SYN_ITEMS(syn_block)[cur_si->si_idx].sp_type == SPTYPE_START && !(cur_si->si_flags & (HL_MATCH | HL_KEEPEND))) { @@ -2549,7 +2614,7 @@ update_si_attr(idx) if (sip->si_idx < 0) return; - spp = &(SYN_ITEMS(syn_buf)[sip->si_idx]); + spp = &(SYN_ITEMS(syn_block)[sip->si_idx]); if (sip->si_flags & HL_MATCH) sip->si_id = spp->sp_syn_match_id; else @@ -2689,7 +2754,7 @@ update_si_end(sip, startcol, force) if (endpos.lnum == 0) { /* No end pattern matched. */ - if (SYN_ITEMS(syn_buf)[sip->si_idx].sp_flags & HL_ONELINE) + if (SYN_ITEMS(syn_block)[sip->si_idx].sp_flags & HL_ONELINE) { /* a "oneline" never continues in the next line */ sip->si_ends = TRUE; @@ -2791,7 +2856,7 @@ find_endpos(idx, startpos, m_endpos, hl_endpos, flagsp, end_endpos, * Can happen with a match that continues to the next line, because it * contained a region. */ - spp = &(SYN_ITEMS(syn_buf)[idx]); + spp = &(SYN_ITEMS(syn_block)[idx]); if (spp->sp_type != SPTYPE_START) { *hl_endpos = *startpos; @@ -2803,7 +2868,7 @@ find_endpos(idx, startpos, m_endpos, hl_endpos, flagsp, end_endpos, */ for (;;) { - spp = &(SYN_ITEMS(syn_buf)[idx]); + spp = &(SYN_ITEMS(syn_block)[idx]); if (spp->sp_type != SPTYPE_START) break; ++idx; @@ -2833,11 +2898,11 @@ find_endpos(idx, startpos, m_endpos, hl_endpos, flagsp, end_endpos, * Find end pattern that matches first after "matchcol". */ best_idx = -1; - for (idx = start_idx; idx < syn_buf->b_syn_patterns.ga_len; ++idx) + for (idx = start_idx; idx < syn_block->b_syn_patterns.ga_len; ++idx) { int lc_col = matchcol; - spp = &(SYN_ITEMS(syn_buf)[idx]); + spp = &(SYN_ITEMS(syn_block)[idx]); if (spp->sp_type != SPTYPE_END) /* past last END pattern */ break; lc_col -= spp->sp_offsets[SPO_LC_OFF]; @@ -2915,7 +2980,7 @@ find_endpos(idx, startpos, m_endpos, hl_endpos, flagsp, end_endpos, * Match from start pattern to end pattern. * Correct for match and highlight offset of end pattern. */ - spp = &(SYN_ITEMS(syn_buf)[best_idx]); + spp = &(SYN_ITEMS(syn_block)[best_idx]); syn_add_end_off(m_endpos, &best_regmatch, spp, SPO_ME_OFF, 1); /* can't end before the start */ if (m_endpos->lnum == startpos->lnum && m_endpos->col < startpos->col) @@ -3146,13 +3211,14 @@ syn_regexec(rmp, lnum, col) * Return it's ID if found, 0 otherwise. */ static int -check_keyword_id(line, startcol, endcolp, flagsp, next_listp, cur_si) +check_keyword_id(line, startcol, endcolp, flagsp, next_listp, cur_si, ccharp) char_u *line; int startcol; /* position in line to check for keyword */ int *endcolp; /* return: character after found keyword */ long *flagsp; /* return: flags of matching keyword */ short **next_listp; /* return: next_list of matching keyword */ stateitem_T *cur_si; /* item at the top of the stack */ + int *ccharp UNUSED; /* conceal substitution char */ { keyentry_T *kp; char_u *kwp; @@ -3193,7 +3259,7 @@ check_keyword_id(line, startcol, endcolp, flagsp, next_listp, cur_si) */ for (round = 1; round <= 2; ++round) { - ht = round == 1 ? &syn_buf->b_keywtab : &syn_buf->b_keywtab_ic; + ht = round == 1 ? &syn_block->b_keywtab : &syn_block->b_keywtab_ic; if (ht->ht_used == 0) continue; if (round == 2) /* ignore case */ @@ -3220,6 +3286,9 @@ check_keyword_id(line, startcol, endcolp, flagsp, next_listp, cur_si) *endcolp = startcol + kwlen; *flagsp = kp->flags; *next_listp = kp->next_list; +#ifdef FEAT_CONCEAL + *ccharp = kp->k_char; +#endif return kp->k_syn.id; } } @@ -3228,6 +3297,32 @@ check_keyword_id(line, startcol, endcolp, flagsp, next_listp, cur_si) } /* + * Handle ":syntax conceal" command. + */ + static void +syn_cmd_conceal(eap, syncing) + exarg_T *eap UNUSED; + int syncing UNUSED; +{ +#ifdef FEAT_CONCEAL + char_u *arg = eap->arg; + char_u *next; + + eap->nextcmd = find_nextcmd(arg); + if (eap->skip) + return; + + next = skiptowhite(arg); + if (STRNICMP(arg, "on", 2) == 0 && next - arg == 2) + curwin->w_s->b_syn_conceal = TRUE; + else if (STRNICMP(arg, "off", 3) == 0 && next - arg == 3) + curwin->w_s->b_syn_conceal = FALSE; + else + EMSG2(_("E390: Illegal argument: %s"), arg); +#endif +} + +/* * Handle ":syntax case" command. */ static void @@ -3244,9 +3339,9 @@ syn_cmd_case(eap, syncing) next = skiptowhite(arg); if (STRNICMP(arg, "match", 5) == 0 && next - arg == 5) - curbuf->b_syn_ic = FALSE; + curwin->w_s->b_syn_ic = FALSE; else if (STRNICMP(arg, "ignore", 6) == 0 && next - arg == 6) - curbuf->b_syn_ic = TRUE; + curwin->w_s->b_syn_ic = TRUE; else EMSG2(_("E390: Illegal argument: %s"), arg); } @@ -3268,11 +3363,11 @@ syn_cmd_spell(eap, syncing) next = skiptowhite(arg); if (STRNICMP(arg, "toplevel", 8) == 0 && next - arg == 8) - curbuf->b_syn_spell = SYNSPL_TOP; + curwin->w_s->b_syn_spell = SYNSPL_TOP; else if (STRNICMP(arg, "notoplevel", 10) == 0 && next - arg == 10) - curbuf->b_syn_spell = SYNSPL_NOTOP; + curwin->w_s->b_syn_spell = SYNSPL_NOTOP; else if (STRNICMP(arg, "default", 7) == 0 && next - arg == 7) - curbuf->b_syn_spell = SYNSPL_DEFAULT; + curwin->w_s->b_syn_spell = SYNSPL_DEFAULT; else EMSG2(_("E390: Illegal argument: %s"), arg); } @@ -3281,47 +3376,47 @@ syn_cmd_spell(eap, syncing) * Clear all syntax info for one buffer. */ void -syntax_clear(buf) - buf_T *buf; +syntax_clear(block) + synblock_T *block; { int i; - buf->b_syn_error = FALSE; /* clear previous error */ - buf->b_syn_ic = FALSE; /* Use case, by default */ - buf->b_syn_spell = SYNSPL_DEFAULT; /* default spell checking */ - buf->b_syn_containedin = FALSE; + block->b_syn_error = FALSE; /* clear previous error */ + block->b_syn_ic = FALSE; /* Use case, by default */ + block->b_syn_spell = SYNSPL_DEFAULT; /* default spell checking */ + block->b_syn_containedin = FALSE; /* free the keywords */ - clear_keywtab(&buf->b_keywtab); - clear_keywtab(&buf->b_keywtab_ic); + clear_keywtab(&block->b_keywtab); + clear_keywtab(&block->b_keywtab_ic); /* free the syntax patterns */ - for (i = buf->b_syn_patterns.ga_len; --i >= 0; ) - syn_clear_pattern(buf, i); - ga_clear(&buf->b_syn_patterns); + for (i = block->b_syn_patterns.ga_len; --i >= 0; ) + syn_clear_pattern(block, i); + ga_clear(&block->b_syn_patterns); /* free the syntax clusters */ - for (i = buf->b_syn_clusters.ga_len; --i >= 0; ) - syn_clear_cluster(buf, i); - ga_clear(&buf->b_syn_clusters); - buf->b_spell_cluster_id = 0; - buf->b_nospell_cluster_id = 0; - - buf->b_syn_sync_flags = 0; - buf->b_syn_sync_minlines = 0; - buf->b_syn_sync_maxlines = 0; - buf->b_syn_sync_linebreaks = 0; - - vim_free(buf->b_syn_linecont_prog); - buf->b_syn_linecont_prog = NULL; - vim_free(buf->b_syn_linecont_pat); - buf->b_syn_linecont_pat = NULL; + for (i = block->b_syn_clusters.ga_len; --i >= 0; ) + syn_clear_cluster(block, i); + ga_clear(&block->b_syn_clusters); + block->b_spell_cluster_id = 0; + block->b_nospell_cluster_id = 0; + + block->b_syn_sync_flags = 0; + block->b_syn_sync_minlines = 0; + block->b_syn_sync_maxlines = 0; + block->b_syn_sync_linebreaks = 0; + + vim_free(block->b_syn_linecont_prog); + block->b_syn_linecont_prog = NULL; + vim_free(block->b_syn_linecont_pat); + block->b_syn_linecont_pat = NULL; #ifdef FEAT_FOLDING - buf->b_syn_folditems = 0; + block->b_syn_folditems = 0; #endif /* free the stored states */ - syn_stack_free_all(buf); + syn_stack_free_all(block); invalidate_current_state(); } @@ -3334,42 +3429,42 @@ syntax_sync_clear() int i; /* free the syntax patterns */ - for (i = curbuf->b_syn_patterns.ga_len; --i >= 0; ) - if (SYN_ITEMS(curbuf)[i].sp_syncing) - syn_remove_pattern(curbuf, i); + for (i = curwin->w_s->b_syn_patterns.ga_len; --i >= 0; ) + if (SYN_ITEMS(curwin->w_s)[i].sp_syncing) + syn_remove_pattern(curwin->w_s, i); - curbuf->b_syn_sync_flags = 0; - curbuf->b_syn_sync_minlines = 0; - curbuf->b_syn_sync_maxlines = 0; - curbuf->b_syn_sync_linebreaks = 0; + curwin->w_s->b_syn_sync_flags = 0; + curwin->w_s->b_syn_sync_minlines = 0; + curwin->w_s->b_syn_sync_maxlines = 0; + curwin->w_s->b_syn_sync_linebreaks = 0; - vim_free(curbuf->b_syn_linecont_prog); - curbuf->b_syn_linecont_prog = NULL; - vim_free(curbuf->b_syn_linecont_pat); - curbuf->b_syn_linecont_pat = NULL; + vim_free(curwin->w_s->b_syn_linecont_prog); + curwin->w_s->b_syn_linecont_prog = NULL; + vim_free(curwin->w_s->b_syn_linecont_pat); + curwin->w_s->b_syn_linecont_pat = NULL; - syn_stack_free_all(curbuf); /* Need to recompute all syntax. */ + syn_stack_free_all(curwin->w_s); /* Need to recompute all syntax. */ } /* * Remove one pattern from the buffer's pattern list. */ static void -syn_remove_pattern(buf, idx) - buf_T *buf; +syn_remove_pattern(block, idx) + synblock_T *block; int idx; { synpat_T *spp; - spp = &(SYN_ITEMS(buf)[idx]); + spp = &(SYN_ITEMS(block)[idx]); #ifdef FEAT_FOLDING if (spp->sp_flags & HL_FOLD) - --buf->b_syn_folditems; + --block->b_syn_folditems; #endif - syn_clear_pattern(buf, idx); + syn_clear_pattern(block, idx); mch_memmove(spp, spp + 1, - sizeof(synpat_T) * (buf->b_syn_patterns.ga_len - idx - 1)); - --buf->b_syn_patterns.ga_len; + sizeof(synpat_T) * (block->b_syn_patterns.ga_len - idx - 1)); + --block->b_syn_patterns.ga_len; } /* @@ -3377,18 +3472,18 @@ syn_remove_pattern(buf, idx) * last to first! */ static void -syn_clear_pattern(buf, i) - buf_T *buf; +syn_clear_pattern(block, i) + synblock_T *block; int i; { - vim_free(SYN_ITEMS(buf)[i].sp_pattern); - vim_free(SYN_ITEMS(buf)[i].sp_prog); + vim_free(SYN_ITEMS(block)[i].sp_pattern); + vim_free(SYN_ITEMS(block)[i].sp_prog); /* Only free sp_cont_list and sp_next_list of first start pattern */ - if (i == 0 || SYN_ITEMS(buf)[i - 1].sp_type != SPTYPE_START) + if (i == 0 || SYN_ITEMS(block)[i - 1].sp_type != SPTYPE_START) { - vim_free(SYN_ITEMS(buf)[i].sp_cont_list); - vim_free(SYN_ITEMS(buf)[i].sp_next_list); - vim_free(SYN_ITEMS(buf)[i].sp_syn.cont_in_list); + vim_free(SYN_ITEMS(block)[i].sp_cont_list); + vim_free(SYN_ITEMS(block)[i].sp_next_list); + vim_free(SYN_ITEMS(block)[i].sp_syn.cont_in_list); } } @@ -3396,13 +3491,13 @@ syn_clear_pattern(buf, i) * Clear and free one syntax cluster. */ static void -syn_clear_cluster(buf, i) - buf_T *buf; +syn_clear_cluster(block, i) + synblock_T *block; int i; { - vim_free(SYN_CLSTR(buf)[i].scl_name); - vim_free(SYN_CLSTR(buf)[i].scl_name_u); - vim_free(SYN_CLSTR(buf)[i].scl_list); + vim_free(SYN_CLSTR(block)[i].scl_name); + vim_free(SYN_CLSTR(block)[i].scl_name_u); + vim_free(SYN_CLSTR(block)[i].scl_list); } /* @@ -3427,7 +3522,7 @@ syn_cmd_clear(eap, syncing) * Only required for Vim 5.x syntax files, 6.0 ones don't contain ":syn * clear". */ - if (curbuf->b_syn_topgrp != 0) + if (curwin->w_s->b_syn_topgrp != 0) return; if (ends_excmd(*arg)) @@ -3439,8 +3534,12 @@ syn_cmd_clear(eap, syncing) syntax_sync_clear(); else { - syntax_clear(curbuf); - do_unlet((char_u *)"b:current_syntax", TRUE); + syntax_clear(curwin->w_s); + if (curwin->w_s == &curwin->w_buffer->b_s) + do_unlet((char_u *)"b:current_syntax", TRUE); + else + do_unlet((char_u *)"w:current_syntax", TRUE); + } } else @@ -3468,8 +3567,8 @@ syn_cmd_clear(eap, syncing) */ short scl_id = id - SYNID_CLUSTER; - vim_free(SYN_CLSTR(curbuf)[scl_id].scl_list); - SYN_CLSTR(curbuf)[scl_id].scl_list = NULL; + vim_free(SYN_CLSTR(curwin->w_s)[scl_id].scl_list); + SYN_CLSTR(curwin->w_s)[scl_id].scl_list = NULL; } } else @@ -3487,7 +3586,7 @@ syn_cmd_clear(eap, syncing) } } redraw_curbuf_later(SOME_VALID); - syn_stack_free_all(curbuf); /* Need to recompute all syntax. */ + syn_stack_free_all(curwin->w_s); /* Need to recompute all syntax. */ } /* @@ -3504,17 +3603,17 @@ syn_clear_one(id, syncing) /* Clear keywords only when not ":syn sync clear group-name" */ if (!syncing) { - (void)syn_clear_keyword(id, &curbuf->b_keywtab); - (void)syn_clear_keyword(id, &curbuf->b_keywtab_ic); + (void)syn_clear_keyword(id, &curwin->w_s->b_keywtab); + (void)syn_clear_keyword(id, &curwin->w_s->b_keywtab_ic); } /* clear the patterns for "id" */ - for (idx = curbuf->b_syn_patterns.ga_len; --idx >= 0; ) + for (idx = curwin->w_s->b_syn_patterns.ga_len; --idx >= 0; ) { - spp = &(SYN_ITEMS(curbuf)[idx]); + spp = &(SYN_ITEMS(curwin->w_s)[idx]); if (spp->sp_syn.id != id || spp->sp_syncing != syncing) continue; - syn_remove_pattern(curbuf, idx); + syn_remove_pattern(curwin->w_s, idx); } } @@ -3613,7 +3712,7 @@ syn_cmd_list(eap, syncing) if (eap->skip) return; - if (!syntax_present(curbuf)) + if (!syntax_present(curwin)) { MSG(_("No Syntax items defined for this buffer")); return; @@ -3621,30 +3720,30 @@ syn_cmd_list(eap, syncing) if (syncing) { - if (curbuf->b_syn_sync_flags & SF_CCOMMENT) + if (curwin->w_s->b_syn_sync_flags & SF_CCOMMENT) { MSG_PUTS(_("syncing on C-style comments")); syn_lines_msg(); syn_match_msg(); return; } - else if (!(curbuf->b_syn_sync_flags & SF_MATCH)) + else if (!(curwin->w_s->b_syn_sync_flags & SF_MATCH)) { - if (curbuf->b_syn_sync_minlines == 0) + if (curwin->w_s->b_syn_sync_minlines == 0) MSG_PUTS(_("no syncing")); else { MSG_PUTS(_("syncing starts ")); - msg_outnum(curbuf->b_syn_sync_minlines); + msg_outnum(curwin->w_s->b_syn_sync_minlines); MSG_PUTS(_(" lines before top line")); syn_match_msg(); } return; } MSG_PUTS_TITLE(_("\n--- Syntax sync items ---")); - if (curbuf->b_syn_sync_minlines > 0 - || curbuf->b_syn_sync_maxlines > 0 - || curbuf->b_syn_sync_linebreaks > 0) + if (curwin->w_s->b_syn_sync_minlines > 0 + || curwin->w_s->b_syn_sync_maxlines > 0 + || curwin->w_s->b_syn_sync_linebreaks > 0) { MSG_PUTS(_("\nsyncing on items")); syn_lines_msg(); @@ -3660,7 +3759,7 @@ syn_cmd_list(eap, syncing) */ for (id = 1; id <= highlight_ga.ga_len && !got_int; ++id) syn_list_one(id, syncing, FALSE); - for (id = 0; id < curbuf->b_syn_clusters.ga_len && !got_int; ++id) + for (id = 0; id < curwin->w_s->b_syn_clusters.ga_len && !got_int; ++id) syn_list_cluster(id); } else @@ -3696,20 +3795,21 @@ syn_cmd_list(eap, syncing) static void syn_lines_msg() { - if (curbuf->b_syn_sync_maxlines > 0 || curbuf->b_syn_sync_minlines > 0) + if (curwin->w_s->b_syn_sync_maxlines > 0 + || curwin->w_s->b_syn_sync_minlines > 0) { MSG_PUTS("; "); - if (curbuf->b_syn_sync_minlines > 0) + if (curwin->w_s->b_syn_sync_minlines > 0) { MSG_PUTS(_("minimal ")); - msg_outnum(curbuf->b_syn_sync_minlines); - if (curbuf->b_syn_sync_maxlines) + msg_outnum(curwin->w_s->b_syn_sync_minlines); + if (curwin->w_s->b_syn_sync_maxlines) MSG_PUTS(", "); } - if (curbuf->b_syn_sync_maxlines > 0) + if (curwin->w_s->b_syn_sync_maxlines > 0) { MSG_PUTS(_("maximal ")); - msg_outnum(curbuf->b_syn_sync_maxlines); + msg_outnum(curwin->w_s->b_syn_sync_maxlines); } MSG_PUTS(_(" lines before top line")); } @@ -3718,10 +3818,10 @@ syn_lines_msg() static void syn_match_msg() { - if (curbuf->b_syn_sync_linebreaks > 0) + if (curwin->w_s->b_syn_sync_linebreaks > 0) { MSG_PUTS(_("; match ")); - msg_outnum(curbuf->b_syn_sync_linebreaks); + msg_outnum(curwin->w_s->b_syn_sync_linebreaks); MSG_PUTS(_(" line breaks")); } } @@ -3759,6 +3859,10 @@ syn_list_one(id, syncing, link_only) {HL_EXCLUDENL, "excludenl"}, {HL_TRANSP, "transparent"}, {HL_FOLD, "fold"}, +#ifdef FEAT_CONCEAL + {HL_CONCEAL, "conceal"}, + {HL_CONCEALENDS, "concealends"}, +#endif {0, NULL} }; static struct name_list namelist2[] = @@ -3774,15 +3878,15 @@ syn_list_one(id, syncing, link_only) /* list the keywords for "id" */ if (!syncing) { - did_header = syn_list_keywords(id, &curbuf->b_keywtab, FALSE, attr); - did_header = syn_list_keywords(id, &curbuf->b_keywtab_ic, + did_header = syn_list_keywords(id, &curwin->w_s->b_keywtab, FALSE, attr); + did_header = syn_list_keywords(id, &curwin->w_s->b_keywtab_ic, did_header, attr); } /* list the patterns for "id" */ - for (idx = 0; idx < curbuf->b_syn_patterns.ga_len && !got_int; ++idx) + for (idx = 0; idx < curwin->w_s->b_syn_patterns.ga_len && !got_int; ++idx) { - spp = &(SYN_ITEMS(curbuf)[idx]); + spp = &(SYN_ITEMS(curwin->w_s)[idx]); if (spp->sp_syn.id != id || spp->sp_syncing != syncing) continue; @@ -3796,13 +3900,13 @@ syn_list_one(id, syncing, link_only) } else if (spp->sp_type == SPTYPE_START) { - while (SYN_ITEMS(curbuf)[idx].sp_type == SPTYPE_START) - put_pattern("start", '=', &SYN_ITEMS(curbuf)[idx++], attr); - if (SYN_ITEMS(curbuf)[idx].sp_type == SPTYPE_SKIP) - put_pattern("skip", '=', &SYN_ITEMS(curbuf)[idx++], attr); - while (idx < curbuf->b_syn_patterns.ga_len - && SYN_ITEMS(curbuf)[idx].sp_type == SPTYPE_END) - put_pattern("end", '=', &SYN_ITEMS(curbuf)[idx++], attr); + while (SYN_ITEMS(curwin->w_s)[idx].sp_type == SPTYPE_START) + put_pattern("start", '=', &SYN_ITEMS(curwin->w_s)[idx++], attr); + if (SYN_ITEMS(curwin->w_s)[idx].sp_type == SPTYPE_SKIP) + put_pattern("skip", '=', &SYN_ITEMS(curwin->w_s)[idx++], attr); + while (idx < curwin->w_s->b_syn_patterns.ga_len + && SYN_ITEMS(curwin->w_s)[idx].sp_type == SPTYPE_END) + put_pattern("end", '=', &SYN_ITEMS(curwin->w_s)[idx++], attr); --idx; msg_putchar(' '); } @@ -3828,7 +3932,7 @@ syn_list_one(id, syncing, link_only) msg_puts_attr((char_u *)"groupthere", attr); msg_putchar(' '); if (spp->sp_sync_idx >= 0) - msg_outtrans(HL_TABLE()[SYN_ITEMS(curbuf) + msg_outtrans(HL_TABLE()[SYN_ITEMS(curwin->w_s) [spp->sp_sync_idx].sp_syn.id - 1].sg_name); else MSG_PUTS("NONE"); @@ -3873,7 +3977,7 @@ syn_list_cluster(id) /* slight hack: roughly duplicate the guts of syn_list_header() */ msg_putchar('\n'); - msg_outtrans(SYN_CLSTR(curbuf)[id].scl_name); + msg_outtrans(SYN_CLSTR(curwin->w_s)[id].scl_name); if (msg_col >= endcol) /* output at least one space */ endcol = msg_col + 1; @@ -3881,9 +3985,9 @@ syn_list_cluster(id) endcol = Columns - 1; msg_advance(endcol); - if (SYN_CLSTR(curbuf)[id].scl_list != NULL) + if (SYN_CLSTR(curwin->w_s)[id].scl_list != NULL) { - put_id_list((char_u *)"cluster", SYN_CLSTR(curbuf)[id].scl_list, + put_id_list((char_u *)"cluster", SYN_CLSTR(curwin->w_s)[id].scl_list, hl_attr(HLF_D)); } else @@ -3925,7 +4029,7 @@ put_id_list(name, list, attr) short scl_id = *p - SYNID_CLUSTER; msg_putchar('@'); - msg_outtrans(SYN_CLSTR(curbuf)[scl_id].scl_name); + msg_outtrans(SYN_CLSTR(curwin->w_s)[scl_id].scl_name); } else msg_outtrans(HL_TABLE()[*p - 1].sg_name); @@ -4190,12 +4294,13 @@ clear_keywtab(ht) * Add a keyword to the list of keywords. */ static void -add_keyword(name, id, flags, cont_in_list, next_list) +add_keyword(name, id, flags, cont_in_list, next_list, conceal_char) char_u *name; /* name of keyword */ int id; /* group ID for this keyword */ int flags; /* flags for this keyword */ short *cont_in_list; /* containedin for this keyword */ short *next_list; /* nextgroup for this keyword */ + int conceal_char; { keyentry_T *kp; hashtab_T *ht; @@ -4204,7 +4309,7 @@ add_keyword(name, id, flags, cont_in_list, next_list) long_u hash; char_u name_folded[MAXKEYWLEN + 1]; - if (curbuf->b_syn_ic) + if (curwin->w_s->b_syn_ic) name_ic = str_foldcase(name, (int)STRLEN(name), name_folded, MAXKEYWLEN + 1); else @@ -4216,15 +4321,16 @@ add_keyword(name, id, flags, cont_in_list, next_list) kp->k_syn.id = id; kp->k_syn.inc_tag = current_syn_inc_tag; kp->flags = flags; + kp->k_char = conceal_char; kp->k_syn.cont_in_list = copy_id_list(cont_in_list); if (cont_in_list != NULL) - curbuf->b_syn_containedin = TRUE; + curwin->w_s->b_syn_containedin = TRUE; kp->next_list = copy_id_list(next_list); - if (curbuf->b_syn_ic) - ht = &curbuf->b_keywtab_ic; + if (curwin->w_s->b_syn_ic) + ht = &curwin->w_s->b_keywtab_ic; else - ht = &curbuf->b_keywtab; + ht = &curwin->w_s->b_keywtab; hash = hash_hash(kp->keyword); hi = hash_lookup(ht, kp->keyword, hash); @@ -4275,9 +4381,10 @@ get_group_name(arg, name_end) * Return NULL for any error; */ static char_u * -get_syn_options(arg, opt) +get_syn_options(arg, opt, conceal_char) char_u *arg; /* next argument to be checked */ syn_opt_arg_T *opt; /* various things */ + int *conceal_char UNUSED; { char_u *gname_start, *gname; int syn_id; @@ -4303,6 +4410,9 @@ get_syn_options(arg, opt) {"gGrRoOuUpPtThHeErReE", 0, HL_SYNC_THERE}, {"dDiIsSpPlLaAyY", 0, HL_DISPLAY}, {"fFoOlLdD", 0, HL_FOLD}, + {"cCoOnNcCeEaAlL", 0, HL_CONCEAL}, + {"cCoOnNcCeEaAlLeEnNdDsS", 0, HL_CONCEALENDS}, + {"cCcChHaArR", 11, 0}, {"cCoOnNtTaAiInNsS", 1, 0}, {"cCoOnNtTaAiInNeEdDiInN", 2, 0}, {"nNeExXtTgGrRoOuUpP", 3, 0}, @@ -4312,6 +4422,11 @@ get_syn_options(arg, opt) if (arg == NULL) /* already detected error */ return NULL; +#ifdef FEAT_CONCEAL + if (curwin->w_s->b_syn_conceal) + opt->flags |= HL_CONCEAL; +#endif + for (;;) { /* @@ -4372,6 +4487,26 @@ get_syn_options(arg, opt) if (get_id_list(&arg, 9, &opt->next_list) == FAIL) return NULL; } + else if (flagtab[fidx].argtype == 11 && arg[5] == '=') + { +#ifdef FEAT_MBYTE + /* cchar=? */ + if (has_mbyte) + { +# ifdef FEAT_CONCEAL + *conceal_char = mb_ptr2char(arg + 6); +# endif + arg += mb_ptr2len(arg + 6) - 1; + } + else +#endif +#ifdef FEAT_CONCEAL + *conceal_char = arg[6]; +#else + ; +#endif + arg = skipwhite(arg + 7); + } else { opt->flags |= flagtab[fidx].flags; @@ -4397,9 +4532,9 @@ get_syn_options(arg, opt) else { syn_id = syn_name2id(gname); - for (i = curbuf->b_syn_patterns.ga_len; --i >= 0; ) - if (SYN_ITEMS(curbuf)[i].sp_syn.id == syn_id - && SYN_ITEMS(curbuf)[i].sp_type == SPTYPE_START) + for (i = curwin->w_s->b_syn_patterns.ga_len; --i >= 0; ) + if (SYN_ITEMS(curwin->w_s)[i].sp_syn.id == syn_id + && SYN_ITEMS(curwin->w_s)[i].sp_type == SPTYPE_START) { *opt->sync_idx = i; break; @@ -4437,20 +4572,20 @@ syn_incl_toplevel(id, flagsp) int id; int *flagsp; { - if ((*flagsp & HL_CONTAINED) || curbuf->b_syn_topgrp == 0) + if ((*flagsp & HL_CONTAINED) || curwin->w_s->b_syn_topgrp == 0) return; *flagsp |= HL_CONTAINED; - if (curbuf->b_syn_topgrp >= SYNID_CLUSTER) + if (curwin->w_s->b_syn_topgrp >= SYNID_CLUSTER) { /* We have to alloc this, because syn_combine_list() will free it. */ short *grp_list = (short *)alloc((unsigned)(2 * sizeof(short))); - int tlg_id = curbuf->b_syn_topgrp - SYNID_CLUSTER; + int tlg_id = curwin->w_s->b_syn_topgrp - SYNID_CLUSTER; if (grp_list != NULL) { grp_list[0] = id; grp_list[1] = 0; - syn_combine_list(&SYN_CLSTR(curbuf)[tlg_id].scl_list, &grp_list, + syn_combine_list(&SYN_CLSTR(curwin->w_s)[tlg_id].scl_list, &grp_list, CLUSTER_ADD); } } @@ -4517,12 +4652,12 @@ syn_cmd_include(eap, syncing) */ prev_syn_inc_tag = current_syn_inc_tag; current_syn_inc_tag = ++running_syn_inc_tag; - prev_toplvl_grp = curbuf->b_syn_topgrp; - curbuf->b_syn_topgrp = sgl_id; + prev_toplvl_grp = curwin->w_s->b_syn_topgrp; + curwin->w_s->b_syn_topgrp = sgl_id; if (source ? do_source(eap->arg, FALSE, DOSO_NONE) == FAIL : source_runtime(eap->arg, TRUE) == FAIL) EMSG2(_(e_notopen), eap->arg); - curbuf->b_syn_topgrp = prev_toplvl_grp; + curwin->w_s->b_syn_topgrp = prev_toplvl_grp; current_syn_inc_tag = prev_syn_inc_tag; } @@ -4543,6 +4678,7 @@ syn_cmd_keyword(eap, syncing) char_u *kw; syn_opt_arg_T syn_opt_arg; int cnt; + int conceal_char = NUL; rest = get_group_name(arg, &group_name_end); @@ -4570,7 +4706,7 @@ syn_cmd_keyword(eap, syncing) p = keyword_copy; for ( ; rest != NULL && !ends_excmd(*rest); rest = skipwhite(rest)) { - rest = get_syn_options(rest, &syn_opt_arg); + rest = get_syn_options(rest, &syn_opt_arg, &conceal_char); if (rest == NULL || ends_excmd(*rest)) break; /* Copy the keyword, removing backslashes, and add a NUL. */ @@ -4599,8 +4735,8 @@ syn_cmd_keyword(eap, syncing) if (p != NULL) *p = NUL; add_keyword(kw, syn_id, syn_opt_arg.flags, - syn_opt_arg.cont_in_list, - syn_opt_arg.next_list); + syn_opt_arg.cont_in_list, + syn_opt_arg.next_list, conceal_char); if (p == NULL) break; if (p[1] == NUL) @@ -4644,7 +4780,7 @@ syn_cmd_keyword(eap, syncing) EMSG2(_(e_invarg2), arg); redraw_curbuf_later(SOME_VALID); - syn_stack_free_all(curbuf); /* Need to recompute all syntax. */ + syn_stack_free_all(curwin->w_s); /* Need to recompute all syntax. */ } /* @@ -4665,6 +4801,7 @@ syn_cmd_match(eap, syncing) int idx; syn_opt_arg_T syn_opt_arg; int sync_idx = 0; + int conceal_char = NUL; /* Isolate the group name, check for validity */ rest = get_group_name(arg, &group_name_end); @@ -4677,7 +4814,7 @@ syn_cmd_match(eap, syncing) syn_opt_arg.cont_list = NULL; syn_opt_arg.cont_in_list = NULL; syn_opt_arg.next_list = NULL; - rest = get_syn_options(rest, &syn_opt_arg); + rest = get_syn_options(rest, &syn_opt_arg, &conceal_char); /* get the pattern. */ init_syn_patterns(); @@ -4687,7 +4824,7 @@ syn_cmd_match(eap, syncing) syn_opt_arg.flags |= HL_HAS_EOL; /* Get options after the pattern */ - rest = get_syn_options(rest, &syn_opt_arg); + rest = get_syn_options(rest, &syn_opt_arg, &conceal_char); if (rest != NULL) /* all arguments are valid */ { @@ -4697,7 +4834,7 @@ syn_cmd_match(eap, syncing) eap->nextcmd = check_nextcmd(rest); if (!ends_excmd(*rest) || eap->skip) rest = NULL; - else if (ga_grow(&curbuf->b_syn_patterns, 1) != FAIL + else if (ga_grow(&curwin->w_s->b_syn_patterns, 1) != FAIL && (syn_id = syn_check_group(arg, (int)(group_name_end - arg))) != 0) { @@ -4705,32 +4842,35 @@ syn_cmd_match(eap, syncing) /* * Store the pattern in the syn_items list */ - idx = curbuf->b_syn_patterns.ga_len; - SYN_ITEMS(curbuf)[idx] = item; - SYN_ITEMS(curbuf)[idx].sp_syncing = syncing; - SYN_ITEMS(curbuf)[idx].sp_type = SPTYPE_MATCH; - SYN_ITEMS(curbuf)[idx].sp_syn.id = syn_id; - SYN_ITEMS(curbuf)[idx].sp_syn.inc_tag = current_syn_inc_tag; - SYN_ITEMS(curbuf)[idx].sp_flags = syn_opt_arg.flags; - SYN_ITEMS(curbuf)[idx].sp_sync_idx = sync_idx; - SYN_ITEMS(curbuf)[idx].sp_cont_list = syn_opt_arg.cont_list; - SYN_ITEMS(curbuf)[idx].sp_syn.cont_in_list = + idx = curwin->w_s->b_syn_patterns.ga_len; + SYN_ITEMS(curwin->w_s)[idx] = item; + SYN_ITEMS(curwin->w_s)[idx].sp_syncing = syncing; + SYN_ITEMS(curwin->w_s)[idx].sp_type = SPTYPE_MATCH; + SYN_ITEMS(curwin->w_s)[idx].sp_syn.id = syn_id; + SYN_ITEMS(curwin->w_s)[idx].sp_syn.inc_tag = current_syn_inc_tag; + SYN_ITEMS(curwin->w_s)[idx].sp_flags = syn_opt_arg.flags; + SYN_ITEMS(curwin->w_s)[idx].sp_sync_idx = sync_idx; + SYN_ITEMS(curwin->w_s)[idx].sp_cont_list = syn_opt_arg.cont_list; + SYN_ITEMS(curwin->w_s)[idx].sp_syn.cont_in_list = syn_opt_arg.cont_in_list; +#ifdef FEAT_CONCEAL + SYN_ITEMS(curwin->w_s)[idx].sp_char = conceal_char; +#endif if (syn_opt_arg.cont_in_list != NULL) - curbuf->b_syn_containedin = TRUE; - SYN_ITEMS(curbuf)[idx].sp_next_list = syn_opt_arg.next_list; - ++curbuf->b_syn_patterns.ga_len; + curwin->w_s->b_syn_containedin = TRUE; + SYN_ITEMS(curwin->w_s)[idx].sp_next_list = syn_opt_arg.next_list; + ++curwin->w_s->b_syn_patterns.ga_len; /* remember that we found a match for syncing on */ if (syn_opt_arg.flags & (HL_SYNC_HERE|HL_SYNC_THERE)) - curbuf->b_syn_sync_flags |= SF_MATCH; + curwin->w_s->b_syn_sync_flags |= SF_MATCH; #ifdef FEAT_FOLDING if (syn_opt_arg.flags & HL_FOLD) - ++curbuf->b_syn_folditems; + ++curwin->w_s->b_syn_folditems; #endif redraw_curbuf_later(SOME_VALID); - syn_stack_free_all(curbuf); /* Need to recompute all syntax. */ + syn_stack_free_all(curwin->w_s); /* Need to recompute all syntax. */ return; /* don't free the progs and patterns now */ } } @@ -4785,6 +4925,7 @@ syn_cmd_region(eap, syncing) int success = FALSE; int idx; syn_opt_arg_T syn_opt_arg; + int conceal_char = NUL; /* Isolate the group name, check for validity */ rest = get_group_name(arg, &group_name_end); @@ -4809,7 +4950,7 @@ syn_cmd_region(eap, syncing) while (rest != NULL && !ends_excmd(*rest)) { /* Check for option arguments */ - rest = get_syn_options(rest, &syn_opt_arg); + rest = get_syn_options(rest, &syn_opt_arg, &conceal_char); if (rest == NULL || ends_excmd(*rest)) break; @@ -4933,7 +5074,7 @@ syn_cmd_region(eap, syncing) eap->nextcmd = check_nextcmd(rest); if (!ends_excmd(*rest) || eap->skip) rest = NULL; - else if (ga_grow(&(curbuf->b_syn_patterns), pat_count) != FAIL + else if (ga_grow(&(curwin->w_s->b_syn_patterns), pat_count) != FAIL && (syn_id = syn_check_group(arg, (int)(group_name_end - arg))) != 0) { @@ -4941,43 +5082,46 @@ syn_cmd_region(eap, syncing) /* * Store the start/skip/end in the syn_items list */ - idx = curbuf->b_syn_patterns.ga_len; + idx = curwin->w_s->b_syn_patterns.ga_len; for (item = ITEM_START; item <= ITEM_END; ++item) { for (ppp = pat_ptrs[item]; ppp != NULL; ppp = ppp->pp_next) { - SYN_ITEMS(curbuf)[idx] = *(ppp->pp_synp); - SYN_ITEMS(curbuf)[idx].sp_syncing = syncing; - SYN_ITEMS(curbuf)[idx].sp_type = + SYN_ITEMS(curwin->w_s)[idx] = *(ppp->pp_synp); + SYN_ITEMS(curwin->w_s)[idx].sp_syncing = syncing; + SYN_ITEMS(curwin->w_s)[idx].sp_type = (item == ITEM_START) ? SPTYPE_START : (item == ITEM_SKIP) ? SPTYPE_SKIP : SPTYPE_END; - SYN_ITEMS(curbuf)[idx].sp_flags |= syn_opt_arg.flags; - SYN_ITEMS(curbuf)[idx].sp_syn.id = syn_id; - SYN_ITEMS(curbuf)[idx].sp_syn.inc_tag = current_syn_inc_tag; - SYN_ITEMS(curbuf)[idx].sp_syn_match_id = + SYN_ITEMS(curwin->w_s)[idx].sp_flags |= syn_opt_arg.flags; + SYN_ITEMS(curwin->w_s)[idx].sp_syn.id = syn_id; + SYN_ITEMS(curwin->w_s)[idx].sp_syn.inc_tag = current_syn_inc_tag; + SYN_ITEMS(curwin->w_s)[idx].sp_syn_match_id = ppp->pp_matchgroup_id; +#ifdef FEAT_CONCEAL + SYN_ITEMS(curwin->w_s)[idx].sp_char = conceal_char; +#endif if (item == ITEM_START) { - SYN_ITEMS(curbuf)[idx].sp_cont_list = + SYN_ITEMS(curwin->w_s)[idx].sp_cont_list = syn_opt_arg.cont_list; - SYN_ITEMS(curbuf)[idx].sp_syn.cont_in_list = + SYN_ITEMS(curwin->w_s)[idx].sp_syn.cont_in_list = syn_opt_arg.cont_in_list; if (syn_opt_arg.cont_in_list != NULL) - curbuf->b_syn_containedin = TRUE; - SYN_ITEMS(curbuf)[idx].sp_next_list = + curwin->w_s->b_syn_containedin = TRUE; + SYN_ITEMS(curwin->w_s)[idx].sp_next_list = syn_opt_arg.next_list; } - ++curbuf->b_syn_patterns.ga_len; + ++curwin->w_s->b_syn_patterns.ga_len; ++idx; #ifdef FEAT_FOLDING if (syn_opt_arg.flags & HL_FOLD) - ++curbuf->b_syn_folditems; + ++curwin->w_s->b_syn_folditems; #endif } } redraw_curbuf_later(SOME_VALID); - syn_stack_free_all(curbuf); /* Need to recompute all syntax. */ + syn_stack_free_all(curwin->w_s); /* Need to recompute all syntax. */ success = TRUE; /* don't free the progs and patterns now */ } } @@ -5169,9 +5313,9 @@ syn_scl_name2id(name) name_u = vim_strsave_up(name); if (name_u == NULL) return 0; - for (i = curbuf->b_syn_clusters.ga_len; --i >= 0; ) - if (SYN_CLSTR(curbuf)[i].scl_name_u != NULL - && STRCMP(name_u, SYN_CLSTR(curbuf)[i].scl_name_u) == 0) + for (i = curwin->w_s->b_syn_clusters.ga_len; --i >= 0; ) + if (SYN_CLSTR(curwin->w_s)[i].scl_name_u != NULL + && STRCMP(name_u, SYN_CLSTR(curwin->w_s)[i].scl_name_u) == 0) break; vim_free(name_u); return (i < 0 ? 0 : i + SYNID_CLUSTER); @@ -5237,32 +5381,32 @@ syn_add_cluster(name) /* * First call for this growarray: init growing array. */ - if (curbuf->b_syn_clusters.ga_data == NULL) + if (curwin->w_s->b_syn_clusters.ga_data == NULL) { - curbuf->b_syn_clusters.ga_itemsize = sizeof(syn_cluster_T); - curbuf->b_syn_clusters.ga_growsize = 10; + curwin->w_s->b_syn_clusters.ga_itemsize = sizeof(syn_cluster_T); + curwin->w_s->b_syn_clusters.ga_growsize = 10; } /* * Make room for at least one other cluster entry. */ - if (ga_grow(&curbuf->b_syn_clusters, 1) == FAIL) + if (ga_grow(&curwin->w_s->b_syn_clusters, 1) == FAIL) { vim_free(name); return 0; } - len = curbuf->b_syn_clusters.ga_len; + len = curwin->w_s->b_syn_clusters.ga_len; - vim_memset(&(SYN_CLSTR(curbuf)[len]), 0, sizeof(syn_cluster_T)); - SYN_CLSTR(curbuf)[len].scl_name = name; - SYN_CLSTR(curbuf)[len].scl_name_u = vim_strsave_up(name); - SYN_CLSTR(curbuf)[len].scl_list = NULL; - ++curbuf->b_syn_clusters.ga_len; + vim_memset(&(SYN_CLSTR(curwin->w_s)[len]), 0, sizeof(syn_cluster_T)); + SYN_CLSTR(curwin->w_s)[len].scl_name = name; + SYN_CLSTR(curwin->w_s)[len].scl_name_u = vim_strsave_up(name); + SYN_CLSTR(curwin->w_s)[len].scl_list = NULL; + ++curwin->w_s->b_syn_clusters.ga_len; if (STRICMP(name, "Spell") == 0) - curbuf->b_spell_cluster_id = len + SYNID_CLUSTER; + curwin->w_s->b_spell_cluster_id = len + SYNID_CLUSTER; if (STRICMP(name, "NoSpell") == 0) - curbuf->b_nospell_cluster_id = len + SYNID_CLUSTER; + curwin->w_s->b_nospell_cluster_id = len + SYNID_CLUSTER; return len + SYNID_CLUSTER; } @@ -5325,7 +5469,7 @@ syn_cmd_cluster(eap, syncing) EMSG2(_(e_invarg2), rest); break; } - syn_combine_list(&SYN_CLSTR(curbuf)[scl_id].scl_list, + syn_combine_list(&SYN_CLSTR(curwin->w_s)[scl_id].scl_list, &clstr_list, list_op); got_clstr = TRUE; } @@ -5333,7 +5477,7 @@ syn_cmd_cluster(eap, syncing) if (got_clstr) { redraw_curbuf_later(SOME_VALID); - syn_stack_free_all(curbuf); /* Need to recompute all syntax. */ + syn_stack_free_all(curwin->w_s); /* Need to recompute all syntax. */ } } @@ -5349,8 +5493,8 @@ syn_cmd_cluster(eap, syncing) static void init_syn_patterns() { - curbuf->b_syn_patterns.ga_itemsize = sizeof(synpat_T); - curbuf->b_syn_patterns.ga_growsize = 10; + curwin->w_s->b_syn_patterns.ga_itemsize = sizeof(synpat_T); + curwin->w_s->b_syn_patterns.ga_growsize = 10; } /* @@ -5390,7 +5534,7 @@ get_syn_pattern(arg, ci) if (ci->sp_prog == NULL) return NULL; - ci->sp_ic = curbuf->b_syn_ic; + ci->sp_ic = curwin->w_s->b_syn_ic; /* * Check for a match, highlight or region offset. @@ -5488,17 +5632,17 @@ syn_cmd_sync(eap, syncing) if (STRCMP(key, "CCOMMENT") == 0) { if (!eap->skip) - curbuf->b_syn_sync_flags |= SF_CCOMMENT; + curwin->w_s->b_syn_sync_flags |= SF_CCOMMENT; if (!ends_excmd(*next_arg)) { arg_end = skiptowhite(next_arg); if (!eap->skip) - curbuf->b_syn_sync_id = syn_check_group(next_arg, + curwin->w_s->b_syn_sync_id = syn_check_group(next_arg, (int)(arg_end - next_arg)); next_arg = skipwhite(arg_end); } else if (!eap->skip) - curbuf->b_syn_sync_id = syn_name2id((char_u *)"Comment"); + curwin->w_s->b_syn_sync_id = syn_name2id((char_u *)"Comment"); } else if ( STRNCMP(key, "LINES", 5) == 0 || STRNCMP(key, "MINLINES", 8) == 0 @@ -5520,24 +5664,24 @@ syn_cmd_sync(eap, syncing) if (!eap->skip) { if (key[4] == 'B') - curbuf->b_syn_sync_linebreaks = n; + curwin->w_s->b_syn_sync_linebreaks = n; else if (key[1] == 'A') - curbuf->b_syn_sync_maxlines = n; + curwin->w_s->b_syn_sync_maxlines = n; else - curbuf->b_syn_sync_minlines = n; + curwin->w_s->b_syn_sync_minlines = n; } } else if (STRCMP(key, "FROMSTART") == 0) { if (!eap->skip) { - curbuf->b_syn_sync_minlines = MAXLNUM; - curbuf->b_syn_sync_maxlines = 0; + curwin->w_s->b_syn_sync_minlines = MAXLNUM; + curwin->w_s->b_syn_sync_maxlines = 0; } } else if (STRCMP(key, "LINECONT") == 0) { - if (curbuf->b_syn_linecont_pat != NULL) + if (curwin->w_s->b_syn_linecont_pat != NULL) { EMSG(_("E403: syntax sync: line continuations pattern specified twice")); finished = TRUE; @@ -5553,25 +5697,25 @@ syn_cmd_sync(eap, syncing) if (!eap->skip) { /* store the pattern and compiled regexp program */ - if ((curbuf->b_syn_linecont_pat = vim_strnsave(next_arg + 1, + if ((curwin->w_s->b_syn_linecont_pat = vim_strnsave(next_arg + 1, (int)(arg_end - next_arg - 1))) == NULL) { finished = TRUE; break; } - curbuf->b_syn_linecont_ic = curbuf->b_syn_ic; + curwin->w_s->b_syn_linecont_ic = curwin->w_s->b_syn_ic; /* Make 'cpoptions' empty, to avoid the 'l' flag */ cpo_save = p_cpo; p_cpo = (char_u *)""; - curbuf->b_syn_linecont_prog = - vim_regcomp(curbuf->b_syn_linecont_pat, RE_MAGIC); + curwin->w_s->b_syn_linecont_prog = + vim_regcomp(curwin->w_s->b_syn_linecont_pat, RE_MAGIC); p_cpo = cpo_save; - if (curbuf->b_syn_linecont_prog == NULL) + if (curwin->w_s->b_syn_linecont_prog == NULL) { - vim_free(curbuf->b_syn_linecont_pat); - curbuf->b_syn_linecont_pat = NULL; + vim_free(curwin->w_s->b_syn_linecont_pat); + curwin->w_s->b_syn_linecont_pat = NULL; finished = TRUE; break; } @@ -5601,7 +5745,7 @@ syn_cmd_sync(eap, syncing) { eap->nextcmd = check_nextcmd(arg_start); redraw_curbuf_later(SOME_VALID); - syn_stack_free_all(curbuf); /* Need to recompute all syntax. */ + syn_stack_free_all(curwin->w_s); /* Need to recompute all syntax. */ } } @@ -5862,8 +6006,8 @@ in_id_list(cur_si, list, ssp, contained) --cur_si; /* cur_si->si_idx is -1 for keywords, these never contain anything. */ if (cur_si->si_idx >= 0 && in_id_list(NULL, ssp->cont_in_list, - &(SYN_ITEMS(syn_buf)[cur_si->si_idx].sp_syn), - SYN_ITEMS(syn_buf)[cur_si->si_idx].sp_flags & HL_CONTAINED)) + &(SYN_ITEMS(syn_block)[cur_si->si_idx].sp_syn), + SYN_ITEMS(syn_block)[cur_si->si_idx].sp_flags & HL_CONTAINED)) return TRUE; } @@ -5918,7 +6062,7 @@ in_id_list(cur_si, list, ssp, contained) return retval; if (item >= SYNID_CLUSTER) { - scl_list = SYN_CLSTR(syn_buf)[item - SYNID_CLUSTER].scl_list; + scl_list = SYN_CLSTR(syn_block)[item - SYNID_CLUSTER].scl_list; /* restrict recursiveness to 30 to avoid an endless loop for a * cluster that includes itself (indirectly) */ if (scl_list != NULL && depth < 30) @@ -5946,6 +6090,7 @@ static struct subcommand subcommands[] = {"case", syn_cmd_case}, {"clear", syn_cmd_clear}, {"cluster", syn_cmd_cluster}, + {"conceal", syn_cmd_conceal}, {"enable", syn_cmd_enable}, {"include", syn_cmd_include}, {"keyword", syn_cmd_keyword}, @@ -6006,14 +6151,34 @@ ex_syntax(eap) } } + void +ex_ownsyntax(eap) + exarg_T *eap; +{ + if (curwin->w_s == &curwin->w_buffer->b_s) + { + curwin->w_s = (synblock_T *)alloc(sizeof(synblock_T)); + memset(curwin->w_s, 0, sizeof(synblock_T)); +#ifdef FEAT_SPELL + curwin->w_p_spell = FALSE; /* No spell checking */ + clear_string_option(&curwin->w_s->b_p_spc); + clear_string_option(&curwin->w_s->b_p_spf); + vim_free(curwin->w_s->b_cap_prog); + curwin->w_s->b_cap_prog = NULL; + clear_string_option(&curwin->w_s->b_p_spl); +#endif + } + apply_autocmds(EVENT_SYNTAX, eap->arg, curbuf->b_fname, TRUE, curbuf); +} + int -syntax_present(buf) - buf_T *buf; +syntax_present(win) + win_T *win; { - return (buf->b_syn_patterns.ga_len != 0 - || buf->b_syn_clusters.ga_len != 0 - || buf->b_keywtab.ht_used > 0 - || buf->b_keywtab_ic.ht_used > 0); + return (win->w_s->b_syn_patterns.ga_len != 0 + || win->w_s->b_syn_clusters.ga_len != 0 + || win->w_s->b_keywtab.ht_used > 0 + || win->w_s->b_keywtab_ic.ht_used > 0); } #if defined(FEAT_CMDL_COMPL) || defined(PROTO) @@ -6124,11 +6289,22 @@ syn_get_id(wp, lnum, col, trans, spellp, keep_state) || col < current_col) syntax_start(wp, lnum); - (void)get_syntax_attr(col, spellp, keep_state); + (void)get_syntax_attr(col, NULL, spellp, keep_state); return (trans ? current_trans_id : current_id); } +#if defined(FEAT_CONCEAL) || defined(PROTO) +/* + * Return conceal substitution character + */ + int +syn_get_sub_char() +{ + return current_sub_char; +} +#endif + #if defined(FEAT_EVAL) || defined(PROTO) /* * Return the syntax ID at position "i" in the current stack. @@ -6164,7 +6340,7 @@ syn_get_foldlevel(wp, lnum) int i; /* Return quickly when there are no fold items at all. */ - if (wp->w_buffer->b_syn_folditems != 0) + if (wp->w_s->b_syn_folditems != 0) { syntax_start(wp, lnum); @@ -6316,6 +6492,10 @@ static char *(highlight_init_light[]) = CENT("CursorLine term=underline cterm=underline", "CursorLine term=underline cterm=underline guibg=Grey90"), #endif +#ifdef FEAT_CONCEAL + CENT("Conceal ctermbg=DarkGrey ctermfg=LightGrey", + "Conceal ctermbg=DarkGrey ctermfg=LightGrey guibg=DarkGrey guifg=LightGrey"), +#endif #ifdef FEAT_AUTOCMD CENT("MatchParen term=reverse ctermbg=Cyan", "MatchParen term=reverse ctermbg=Cyan guibg=Cyan"), @@ -6400,6 +6580,10 @@ static char *(highlight_init_dark[]) = CENT("MatchParen term=reverse ctermbg=DarkCyan", "MatchParen term=reverse ctermbg=DarkCyan guibg=DarkCyan"), #endif +#ifdef FEAT_CONCEAL + CENT("Conceal ctermbg=DarkGrey ctermfg=LightGrey", + "Conceal ctermbg=DarkGrey ctermfg=LightGrey guibg=DarkGrey guifg=LightGrey"), +#endif #ifdef FEAT_GUI "Normal gui=NONE", #endif @@ -2989,7 +2989,7 @@ mouse_find_win(rowp, colp) } #endif -#if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) || defined (FEAT_GUI_MAC) \ +#if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MAC) \ || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \ || defined(FEAT_GUI_PHOTON) || defined(PROTO) /* diff --git a/src/version.c b/src/version.c index 04a33b8f1..c0026708c 100644 --- a/src/version.c +++ b/src/version.c @@ -134,6 +134,11 @@ static char *(features[]) = #else "-comments", #endif +#ifdef FEAT_CONCEAL + "+conceal", +#else + "-conceal", +#endif #ifdef FEAT_CRYPT "+cryptv", #else @@ -144,6 +149,11 @@ static char *(features[]) = #else "-cscope", #endif +#ifdef FEAT_CURSORBIND + "+cursorbind", +#else + "-cursorbind", +#endif #ifdef CURSOR_SHAPE "+cursorshape", #else @@ -935,13 +945,13 @@ list_version() # if defined(MSWIN) MSG_PUTS(_("with GUI.")); # else -# if defined (TARGET_API_MAC_CARBON) && TARGET_API_MAC_CARBON +# if defined(TARGET_API_MAC_CARBON) && TARGET_API_MAC_CARBON MSG_PUTS(_("with Carbon GUI.")); # else -# if defined (TARGET_API_MAC_OSX) && TARGET_API_MAC_OSX +# if defined(TARGET_API_MAC_OSX) && TARGET_API_MAC_OSX MSG_PUTS(_("with Cocoa GUI.")); # else -# if defined (MACOS) +# if defined(MACOS) MSG_PUTS(_("with (classic) GUI.")); # endif # endif @@ -853,6 +853,27 @@ extern char *(*dyn_libintl_textdomain)(const char *domainname); # endif # define SST_FIX_STATES 7 /* size of sst_stack[]. */ # define SST_DIST 16 /* normal distance between entries */ +# define SST_INVALID (synstate_T *)-1 /* invalid syn_state pointer */ + +# define HL_CONTAINED 0x01 /* not used on toplevel */ +# define HL_TRANSP 0x02 /* has no highlighting */ +# define HL_ONELINE 0x04 /* match within one line only */ +# define HL_HAS_EOL 0x08 /* end pattern that matches with $ */ +# define HL_SYNC_HERE 0x10 /* sync point after this item (syncing only) */ +# define HL_SYNC_THERE 0x20 /* sync point at current line (syncing only) */ +# define HL_MATCH 0x40 /* use match ID instead of item ID */ +# define HL_SKIPNL 0x80 /* nextgroup can skip newlines */ +# define HL_SKIPWHITE 0x100 /* nextgroup can skip white space */ +# define HL_SKIPEMPTY 0x200 /* nextgroup can skip empty lines */ +# define HL_KEEPEND 0x400 /* end match always kept */ +# define HL_EXCLUDENL 0x800 /* exclude NL from match */ +# define HL_DISPLAY 0x1000 /* only used for displaying, not syncing */ +# define HL_FOLD 0x2000 /* define fold */ +# define HL_EXTEND 0x4000 /* ignore a keepend */ +# define HL_MATCHCONT 0x8000 /* match continued from previous line */ +# define HL_TRANS_CONT 0x10000 /* transparent item without contains arg */ +# define HL_CONCEAL 0x20000 /* can be concealed */ +# define HL_CONCEALENDS 0x40000 /* can be concealed */ #endif /* Values for 'options' argument in do_search() and searchit() */ @@ -1292,6 +1313,7 @@ typedef enum , HLF_CHD /* Changed diff line */ , HLF_DED /* Deleted diff line */ , HLF_TXD /* Text Changed in diff line */ + , HLF_CONCEAL /* Concealed text */ , HLF_SC /* Sign column */ , HLF_SPB /* SpellBad */ , HLF_SPC /* SpellCap */ @@ -1313,7 +1335,7 @@ typedef enum * When changing this also adjust the default for 'highlight'. */ #define HL_FLAGS {'8', '@', 'd', 'e', 'h', 'i', 'l', 'm', 'M', \ 'n', 'r', 's', 'S', 'c', 't', 'v', 'V', 'w', 'W', \ - 'f', 'F', 'A', 'C', 'D', 'T', '>', \ + 'f', 'F', 'A', 'C', 'D', 'T', '-', '>', \ 'B', 'P', 'R', 'L', \ '+', '=', 'x', 'X', '*', '#', '_', '!', '.'} diff --git a/src/window.c b/src/window.c index 907101295..d6aae7c0f 100644 --- a/src/window.c +++ b/src/window.c @@ -1175,6 +1175,9 @@ win_init(newp, oldp, flags) int i; newp->w_buffer = oldp->w_buffer; +#ifdef FEAT_SYN_HL + newp->w_s = oldp->w_s; +#endif oldp->w_buffer->b_nwindows++; newp->w_cursor = oldp->w_cursor; newp->w_valid = 0; @@ -3294,6 +3297,9 @@ win_alloc_firstwin(oldwin) if (curwin == NULL || curbuf == NULL) return FAIL; curwin->w_buffer = curbuf; +#ifdef FEAT_SYN_HL + curwin->w_s = &(curbuf->b_s); +#endif curbuf->b_nwindows = 1; /* there is one window */ #ifdef FEAT_WINDOWS curwin->w_alist = &global_alist; @@ -4401,10 +4407,16 @@ win_free(wp, tp) } #endif /* FEAT_GUI */ +#ifdef FEAT_SYN_HL + /* free independent synblock */ + if (wp->w_s != &wp->w_buffer->b_s) + vim_free(wp->w_s); +#endif + #ifdef FEAT_AUTOCMD if (wp != aucmd_win) #endif - win_remove(wp, tp); + win_remove(wp, tp); vim_free(wp); #ifdef FEAT_AUTOCMD diff --git a/src/workshop.c b/src/workshop.c index 393e3d151..cd98914bc 100644 --- a/src/workshop.c +++ b/src/workshop.c @@ -1826,7 +1826,8 @@ findYourself( else if (*argv0 == '.' || strchr(argv0, '/')) { runpath = (char *) malloc(MAXPATHLEN); - (void)getcwd(runpath, MAXPATHLEN); + if (getcwd(runpath, MAXPATHLEN) == NULL) + runpath[0] = NUL; strcat(runpath, "/"); strcat(runpath, argv0); } |