# HG changeset patch # User Bram Moolenaar # Date 1275772927 -7200 # Node ID 1bac28a53fae13cf3449c5e4d462233f826e0c6f # Parent 6d3d35ff2c2bc0c84a6b8f773f856e0e95987bf5 Add the conceal patch from Vince Negri. diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1163,6 +1163,13 @@ b:changedtick The total number of change 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 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1707,6 +1707,25 @@ A jump table for the options with a shor 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 shor 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 shor 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 shor |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 shor 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 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -35,7 +35,8 @@ 12. Highlight command |:highlight| 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 thre 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 "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 group '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 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -134,6 +134,8 @@ '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 @@ '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 @@ '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 @@ '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 @@ +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 @@ 90.5 usr_90.txt /*90.5* :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 @@ 90.5 usr_90.txt /*90.5* :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_che 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 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-curso 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 --- 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 --- a/runtime/doc/various.txt +++ b/runtime/doc/various.txt @@ -293,8 +293,10 @@ N *+cmdline_compl* command line complet 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 --- a/runtime/optwin.vim +++ b/runtime/optwin.vim @@ -373,6 +373,11 @@ if has("linebreak") call append("$", "\t(local to window)") call OptionL("nuw") endif +if has("conceal") + call append("$", "conceallevel\tcontrols whether concealable elements are hidden") + call append("$", "\t(local to window)") + call OptionL("conc") +endif call Header("syntax, highlighting and spelling") diff --git a/src/buffer.c b/src/buffer.c --- 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 --- 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 --- 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, 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 --- 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 --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -3411,6 +3411,14 @@ do_ecmd(fnum, ffname, sfname, eap, newln else #endif { +#ifdef FEAT_SYN_HL + /* + * 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, newln #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 --- 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 --- 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 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -235,6 +235,7 @@ static void ex_popup __ARGS((exarg_T *ea #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 --- 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 --- 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_("E1 #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 --- 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 --- 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 --- 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 U 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 U 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 conte 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 *f 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 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 *filena 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, 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 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, v 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, v #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 --- 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 --- 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 --- 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 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 --- 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(( 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 #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)) - { - l = (int)STRLEN(curbuf->b_p_spf); - if (l > 0 && (l < 4 || STRCMP(curbuf->b_p_spf + l - 4, + if (varp == &(curbuf->b_s.b_p_spf)) + { + 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 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 } } /* When 'spellcapcheck' is set compile the regexp program. */ - else if (varp == &(curbuf->b_p_spc)) - { - errmsg = compile_cap_prog(curbuf); + else if (varp == &(curwin->w_s->b_p_spc)) + { + 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 } #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 * 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; -{ - regprog_T *rp = buf->b_cap_prog; +compile_cap_prog(synblock) + synblock_T *synblock; +{ + 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) - { - buf->b_cap_prog = rp; /* restore the previous program */ + synblock->b_cap_prog = vim_regcomp(re, RE_MAGIC); + if (synblock->b_cap_prog == NULL) + { + 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, op { 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, err 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 --- 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 --- 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 --- 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 --- a/src/proto/screen.pro +++ b/src/proto/screen.pro @@ -46,5 +46,6 @@ void get_trans_bufname __ARGS((buf_T *bu 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 --- 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 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 --- 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 --- 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)) - { - mod_top -= buf->b_syn_sync_linebreaks; + if (syntax_present(wp)) + { + 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, noc 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, noc 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, noc 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, noc #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, noc /* 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, noc 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 : -# endif - NULL, FALSE); + has_spell ? &can_spell : +# endif + 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, noc } #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, noc } #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, noc ++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, noc || (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 --- a/src/search.c +++ b/src/search.c @@ -1077,6 +1077,9 @@ do_search(oap, dirc, pat, count, options 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 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 --- 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_ 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, doco 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, doco /* 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)); - - if (capcol != NULL && *capcol == 0 && wp->w_buffer->b_cap_prog != NULL) + } while (*mi.mi_fend != NUL && spell_iswordp(mi.mi_fend, wp)); + + 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, doco 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, doco * 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) - { - mi.mi_lp = LANGP_ENTRY(wp->w_buffer->b_langp, lpi); + for (lpi = 0; lpi < wp->w_s->b_langp.ga_len; ++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, doco * 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, doco * 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 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, s } /* - * 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; -{ - vim_memset(buf->b_spell_ismw, 0, 256); -#ifdef FEAT_MBYTE - vim_free(buf->b_spell_ismw_mb); - buf->b_spell_ismw_mb = NULL; +clear_midword(wp) + win_T *wp; +{ + vim_memset(wp->w_s->b_spell_ismw, 0, 256); +#ifdef FEAT_MBYTE + 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'. */ // 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) - { - FOR_ALL_WINDOWS(wp) - if (wp->w_buffer == buf && wp->w_p_spell) - { - (void)did_set_spelllang(buf); + if (*wp->w_s->b_p_spl != NUL) + { + if (wp->w_p_spell) + { + (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; - - if (*curbuf->b_p_spl != NUL && curbuf->b_langp.ga_len > 0) + char_u *lstart = curbuf->b_s.b_p_spl; + + 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, m * 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) - { - lp = LANGP_ENTRY(curbuf->b_langp, i); + for (i = 0; i < curbuf->b_s.b_langp.ga_len; ++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) - { - lp = LANGP_ENTRY(curbuf->b_langp, lpi); + for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++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) - { - lp = LANGP_ENTRY(curbuf->b_langp, lpi); + for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++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, soundfo 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, soundfo * 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, soundfo /* 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, soundfo 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, soundfo { 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, soundfo 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, soundfo { 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, soundfo ++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) - { - lp = LANGP_ENTRY(curbuf->b_langp, lpi); + for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++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) - { - lp = LANGP_ENTRY(curbuf->b_langp, lpi); + for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++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) - { - lp = LANGP_ENTRY(curbuf->b_langp, lpi); + for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++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) - { - lp = LANGP_ENTRY(curbuf->b_langp, lpi); + for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++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) - { - lp = LANGP_ENTRY(curbuf->b_langp, lpi); + for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++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) - { - lp = LANGP_ENTRY(curbuf->b_langp, lpi); + for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++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) - { - lp = LANGP_ENTRY(curbuf->b_langp, lpi); + for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len && !got_int; ++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, dump /* 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) - { - lp = LANGP_ENTRY(buf->b_langp, lpi); + for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++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, dump /* * Loop over all files loaded for the entries in 'spelllang'. */ - for (lpi = 0; lpi < buf->b_langp.ga_len; ++lpi) - { - lp = LANGP_ENTRY(buf->b_langp, lpi); + for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++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, dum * 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 --- 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 --- 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 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_extmat */ 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_ 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 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_ 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, 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) - { - 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) + if (find_start_comment((int)syn_block->b_syn_sync_maxlines) != NULL) + { + 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) - { - 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; + else if (syn_block->b_syn_sync_flags & SF_MATCH) + { + 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) - { - regmatch.rmm_ic = syn_buf->b_syn_linecont_ic; - regmatch.regprog = syn_buf->b_syn_linecont_prog; + if (syn_block->b_syn_linecont_prog != NULL) + { + 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; -{ - synstate_T *p; +syn_stack_free_all(block) + synblock_T *block; +{ 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; ) - { - if (p->sst_lnum + buf->b_syn_sync_linebreaks > buf->b_mod_top) + for (p = block->b_sst_first; p != NULL; ) + { + 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_sta 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_sta ++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, ca 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, ca /* 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, ca 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, ca , 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, ca 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, ca /* * 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, ca */ 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, ca /* 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, ca 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, ca 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, ca * 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, ca * 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, ca 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; - - spp = &(SYN_ITEMS(syn_buf)[next_match_idx]); +#ifdef FEAT_CONCEAL + int save_flags; +#endif + + 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_ * 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_ */ 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_ * 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_ * 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 */ 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 *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 } /* + * 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); - - curbuf->b_syn_sync_flags = 0; - curbuf->b_syn_sync_minlines = 0; - curbuf->b_syn_sync_maxlines = 0; - curbuf->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; - - syn_stack_free_all(curbuf); /* Need to recompute all syntax. */ + 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); + + 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(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(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; -#endif - syn_clear_pattern(buf, idx); + --block->b_syn_folditems; +#endif + 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) - { - 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); + if (i == 0 || SYN_ITEMS(block)[i - 1].sp_type != SPTYPE_START) + { + 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; ) - { - spp = &(SYN_ITEMS(curbuf)[idx]); + for (idx = curwin->w_s->b_syn_patterns.ga_len; --idx >= 0; ) + { + 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)) - { - if (curbuf->b_syn_sync_minlines == 0) + else if (!(curwin->w_s->b_syn_sync_flags & SF_MATCH)) + { + 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) - { - spp = &(SYN_ITEMS(curbuf)[idx]); + for (idx = 0; idx < curwin->w_s->b_syn_patterns.ga_len && !got_int; ++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) - { - put_id_list((char_u *)"cluster", SYN_CLSTR(curbuf)[id].scl_list, + if (SYN_CLSTR(curwin->w_s)[id].scl_list != NULL) + { + 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_lis 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_lis 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) - { - curbuf->b_syn_clusters.ga_itemsize = sizeof(syn_cluster_T); - curbuf->b_syn_clusters.ga_growsize = 10; + if (curwin->w_s->b_syn_clusters.ga_data == NULL) + { + 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; - - 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; + len = curwin->w_s->b_syn_clusters.ga_len; + + vim_memset(&(SYN_CLSTR(curwin->w_s)[len]), 0, sizeof(syn_cluster_T)); + SYN_CLSTR(curwin->w_s)[len].scl_name = name; + 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; -{ - 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); +syntax_present(win) + win_T *win; +{ + 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, || 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 diff --git a/src/ui.c b/src/ui.c --- a/src/ui.c +++ b/src/ui.c @@ -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 --- 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 diff --git a/src/vim.h b/src/vim.h --- a/src/vim.h +++ b/src/vim.h @@ -853,6 +853,27 @@ extern char *(*dyn_libintl_textdomain)(c # 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 --- 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 --- 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); }