]> granicus.if.org Git - vim/commitdiff
Add the conceal patch from Vince Negri.
authorBram Moolenaar <Bram@vim.org>
Sat, 5 Jun 2010 21:22:07 +0000 (23:22 +0200)
committerBram Moolenaar <Bram@vim.org>
Sat, 5 Jun 2010 21:22:07 +0000 (23:22 +0200)
40 files changed:
runtime/doc/eval.txt
runtime/doc/options.txt
runtime/doc/syntax.txt
runtime/doc/tags
runtime/doc/todo.txt
runtime/doc/various.txt
runtime/optwin.vim
src/buffer.c
src/diff.c
src/edit.c
src/eval.c
src/ex_cmds.c
src/ex_cmds.h
src/ex_cmds2.c
src/ex_docmd.c
src/feature.h
src/globals.h
src/hardcopy.c
src/if_python.c
src/integration.c
src/mbyte.c
src/move.c
src/normal.c
src/option.c
src/option.h
src/proto/diff.pro
src/proto/move.pro
src/proto/screen.pro
src/proto/spell.pro
src/proto/syntax.pro
src/screen.c
src/search.c
src/spell.c
src/structs.h
src/syntax.c
src/ui.c
src/version.c
src/vim.h
src/window.c
src/workshop.c

index 7d5e6d6e0be91cc951fa5e345856d3f794a1dbd0..fda756fbb9d26585c0318c7a9284b676afb4e4ac 100644 (file)
@@ -1163,6 +1163,13 @@ b:changedtick    The total number of changes to the current buffer.  It is
 A variable name that is preceded with "w:" is local to the current window.  It
 is deleted when the window is closed.
 
+One local window variable is predefined:
+                                       *w:ownsyntax-variable* *ownsyntax*
+w:ownsyntax    Set to 1 if the window has an independent syntax installed
+               via the |:ownsyntax| command. The default for a window is
+               0. Syntax scripts can use this to determine whether they
+               should set b:current_syntax or w:current_syntax.
+
                                                *tabpage-variable* *t:var*
 A variable name that is preceded with "t:" is local to the current tab page,
 It is deleted when the tab page is closed. {not available when compiled
@@ -5772,7 +5779,7 @@ undofile({name})                                  *undofile()*
                Return the name of the undo file that would be used for a file
                with name {name} when writing.  This uses the 'undodir'
                option, finding directories that exist.  It does not check if
-               the undo file exist.
+               the undo file exists.
                {name} is always expanded to the full path, since that is what
                is used internally.
                Useful in combination with |:wundo| and |:rundo|.
index 63efd1c24b9e04c6163d8fc4413f823765d20ba1..c021edfc47942d5dc4239b67ef10a1f0b37231f1 100644 (file)
@@ -1707,6 +1707,25 @@ A jump table for the options with a short description can be found at |Q_op|.
                    combination with "menu" or "menuone".
 
 
+'conceallevel' 'conc'          *'conceallevel'* *'conc'*
+                       number (default 0)
+                       local to window
+                       {not in Vi}
+                       {not available when compiled without the |+conceal|
+                       feature}
+       Determine how text with the "conceal" syntax attribute is shown:
+
+       'conceallevel'  Effect
+       0               Text is shown normally
+       1               Each block of concealed text is replaced with the
+                       character defined in 'listchars' (default is a dash)
+                       and highlighted with the "Conceal" highlight group.
+       2               Concealed text is completely hidden unless it has a
+                       custom replacement character defined (see
+                       |:syn-cchar|.
+       3               Concealed text is completely hidden.
+
+
                                *'confirm'* *'cf'* *'noconfirm'* *'nocf'*
 'confirm' 'cf'         boolean (default off)
                        global
@@ -2132,6 +2151,20 @@ A jump table for the options with a short description can be found at |Q_op|.
        Give messages when adding a cscope database.  See |cscopeverbose|.
        NOTE: This option is reset when 'compatible' is set.
 
+                       *'cursorbind'* *'crb'* *'nocursorbind'* *'nocrb'*
+'cursorbind' 'crb'     boolean  (default off)
+                       local to window
+                       {not in Vi}
+                       {not available when compiled without the |+cursorbind|
+                       feature}
+       When this option is set, as the cursor in the current
+       window moves other cursorbound windows (windows that also have
+       this option set) move their cursors to the corresponding line and
+       column.  This option is useful for viewing the
+       differences between two versions of a file (see 'diff'); in diff mode,
+       inserted and deleted lines (though not characters within a line) are
+       taken into account. 
+
 
                        *'cursorcolumn'* *'cuc'* *'nocursorcolumn'* *'nocuc'*
 'cursorcolumn' 'cuc'   boolean (default off)
@@ -3615,7 +3648,7 @@ A jump table for the options with a short description can be found at |Q_op|.
                                     f:Folded,F:FoldColumn,A:DiffAdd,
                                     C:DiffChange,D:DiffDelete,T:DiffText,
                                     >:SignColumn,B:SpellBad,P:SpellCap,
-                                    R:SpellRare,L:SpellLocal,
+                                    R:SpellRare,L:SpellLocal,-:Conceal,
                                     +:Pmenu,=:PmenuSel,
                                     x:PmenuSbar,X:PmenuThumb")
                        global
@@ -3659,6 +3692,8 @@ A jump table for the options with a short description can be found at |Q_op|.
        |hl-SpellCap|    P  word that should start with capital|spell|
        |hl-SpellRare|   R  rare word |spell|
        |hl-SpellLocal|  L  word from other region |spell|
+       |hl-Conceal|     -  the placeholders used for concealed characters
+                           (see 'conceallevel')
        |hl-Pmenu|       +  popup menu normal line
        |hl-PmenuSel|    =  popup menu normal line
        |hl-PmenuSbar|   x  popup menu scrollbar
@@ -4416,6 +4451,8 @@ A jump table for the options with a short description can be found at |Q_op|.
          precedes:c    Character to show in the first column, when 'wrap'
                        is off and there is text preceding the character
                        visible in the first column.
+         conceal:c     Character to show in place of concealed text, when
+                       'conceallevel' is set to 1.
          nbsp:c        Character to show for a non-breakable space (character
                        0xA0, 160).  Left blank when omitted.
 
index 109276f40d5dccd47abe81d8ac060048062e65f5..47a1aac797c535a3976c7b3ba0cb6e422e4e75f9 100644 (file)
@@ -35,7 +35,8 @@ In the User Manual:
 13. Linking groups             |:highlight-link|
 14. Cleaning up                        |:syn-clear|
 15. Highlighting tags          |tag-highlight|
-16. Color xterms               |xterm-color|
+16. Window-local syntax                |:ownsyntax|
+17. Color xterms               |xterm-color|
 
 {Vi does not have any of these commands}
 
@@ -3115,12 +3116,14 @@ and may be mixed with patterns.
 Not all commands accept all arguments. This table shows which arguments
 can not be used for all commands:
                                                        *E395* *E396*
-                   contains  oneline   fold  display  extend ~
-:syntax keyword                 -       -       -       -       -
-:syntax match          yes      -      yes     yes     yes
-:syntax region         yes     yes     yes     yes     yes
+                   contains  oneline   fold  display  extend concealends~
+:syntax keyword                 -       -       -       -       -      -
+:syntax match          yes      -      yes     yes     yes     -
+:syntax region         yes     yes     yes     yes     yes    yes
 
 These arguments can be used for all three commands:
+       conceal
+       cchar
        contained
        containedin
        nextgroup
@@ -3129,6 +3132,27 @@ These arguments can be used for all three commands:
        skipnl
        skipempty
 
+conceal                                                *conceal* *:syn-conceal*
+
+When the "conceal" argument is given, the item is marked as concealable.
+Whether or not it is actually concealed depends on the setting on the
+'conceallevel' option.
+
+concealends                                            *:syn-concealends*
+
+When the "concealends" argument is given, the start and end matches of
+the region, but not the contents of the region, are marked as concealable.
+Whether or not they are actually concealed depends on the setting on the
+'conceallevel' option. The ends of a region can only be concealed separately
+in this way when they have their own highlighting via "matchgroup"
+
+cchar                                                  *:syn-cchar*
+
+The "cchar" argument defines the character shown in place of the item
+when it is concealed (setting "cchar" only makes sense when the conceal
+argument is given.) If "cchar" is not set then the default conceal
+character defined in the 'listchars' option is used. Example: >
+   :syntax match Entity "&amp;" conceal cchar=&
 
 contained                                              *:syn-contained*
 
@@ -3385,6 +3409,16 @@ Note that this example doesn't work for nested "if"s.  You need to add
 "contains" arguments to make that work (omitted for simplicity of the
 example).
 
+IMPLICIT CONCEAL                                       *:syn-conceal-implicit*
+
+:sy[ntax] conceal [on|off]
+       This defines if the following ":syntax" commands will define keywords,
+       matches or regions with the "conceal" flag set. After ":syn conceal
+       on", all subsequent ":syn keyword", ":syn match" or ":syn region"
+       defined will have the "conceal" flag set implicitly. ":syn conceal
+       off" returns to the normal state where the "conceal" flag must be
+       given explicitly.
+
 ==============================================================================
 7. Syntax patterns                             *:syn-pattern* *E401* *E402*
 
@@ -4169,6 +4203,9 @@ These are the default highlighting groups.  These groups are used by the
 'highlight' option default.  Note that the highlighting depends on the value
 of 'background'.  You can see the current settings with the ":highlight"
 command.
+                                                       *hl-Conceal*
+Conceal                placeholder characters substituted for concealed
+               text (see 'conceallevel')
                                                        *hl-Cursor*
 Cursor         the character under the cursor
                                                        *hl-CursorIM*
@@ -4471,6 +4508,28 @@ And put these lines in your .vimrc: >
    autocmd BufRead,BufNewFile *.[ch]   exe 'so ' . fname
    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*
 
index 632f288458a077a24db1b42497779df126cbc5a3..18cd16b89bf8498d3ea0f05bf94c317c466b0e4a 100644 (file)
@@ -134,6 +134,8 @@ $VIMRUNTIME starting.txt    /*$VIMRUNTIME*
 'complete'     options.txt     /*'complete'*
 'completefunc' options.txt     /*'completefunc'*
 'completeopt'  options.txt     /*'completeopt'*
+'conc' options.txt     /*'conc'*
+'conceallevel' options.txt     /*'conceallevel'*
 'confirm'      options.txt     /*'confirm'*
 'consk'        options.txt     /*'consk'*
 'conskey'      options.txt     /*'conskey'*
@@ -143,6 +145,7 @@ $VIMRUNTIME starting.txt    /*$VIMRUNTIME*
 'cpo'  options.txt     /*'cpo'*
 'cpoptions'    options.txt     /*'cpoptions'*
 'cpt'  options.txt     /*'cpt'*
+'crb'  options.txt     /*'crb'*
 'cryptmethod'  options.txt     /*'cryptmethod'*
 'cscopepathcomp'       options.txt     /*'cscopepathcomp'*
 'cscopeprg'    options.txt     /*'cscopeprg'*
@@ -158,6 +161,7 @@ $VIMRUNTIME starting.txt    /*$VIMRUNTIME*
 'csverb'       options.txt     /*'csverb'*
 'cuc'  options.txt     /*'cuc'*
 'cul'  options.txt     /*'cul'*
+'cursorbind'   options.txt     /*'cursorbind'*
 'cursorcolumn' options.txt     /*'cursorcolumn'*
 'cursorline'   options.txt     /*'cursorline'*
 'cwh'  options.txt     /*'cwh'*
@@ -482,12 +486,14 @@ $VIMRUNTIME       starting.txt    /*$VIMRUNTIME*
 'noconskey'    options.txt     /*'noconskey'*
 'nocopyindent' options.txt     /*'nocopyindent'*
 'nocp' options.txt     /*'nocp'*
+'nocrb'        options.txt     /*'nocrb'*
 'nocscopetag'  options.txt     /*'nocscopetag'*
 'nocscopeverbose'      options.txt     /*'nocscopeverbose'*
 'nocst'        options.txt     /*'nocst'*
 'nocsverb'     options.txt     /*'nocsverb'*
 'nocuc'        options.txt     /*'nocuc'*
 'nocul'        options.txt     /*'nocul'*
+'nocursorbind' options.txt     /*'nocursorbind'*
 'nocursorcolumn'       options.txt     /*'nocursorcolumn'*
 'nocursorline' options.txt     /*'nocursorline'*
 'nodeco'       options.txt     /*'nodeco'*
@@ -1120,8 +1126,10 @@ $VIMRUNTIME      starting.txt    /*$VIMRUNTIME*
 +cmdline_hist  various.txt     /*+cmdline_hist*
 +cmdline_info  various.txt     /*+cmdline_info*
 +comments      various.txt     /*+comments*
++conceal       various.txt     /*+conceal*
 +cryptv        various.txt     /*+cryptv*
 +cscope        various.txt     /*+cscope*
++cursorbind    various.txt     /*+cursorbind*
 +cursorshape   various.txt     /*+cursorshape*
 +debug various.txt     /*+debug*
 +dialog_con    various.txt     /*+dialog_con*
@@ -2495,6 +2503,7 @@ $VIMRUNTIME       starting.txt    /*$VIMRUNTIME*
 :ounmap        map.txt /*:ounmap*
 :ounme gui.txt /*:ounme*
 :ounmenu       gui.txt /*:ounmenu*
+:ownsyntax     syntax.txt      /*:ownsyntax*
 :p     various.txt     /*:p*
 :pc    windows.txt     /*:pc*
 :pclose        windows.txt     /*:pclose*
@@ -2761,8 +2770,12 @@ $VIMRUNTIME      starting.txt    /*$VIMRUNTIME*
 :syn   syntax.txt      /*:syn*
 :syn-arguments syntax.txt      /*:syn-arguments*
 :syn-case      syntax.txt      /*:syn-case*
+:syn-cchar     syntax.txt      /*:syn-cchar*
 :syn-clear     syntax.txt      /*:syn-clear*
 :syn-cluster   syntax.txt      /*:syn-cluster*
+:syn-conceal   syntax.txt      /*:syn-conceal*
+:syn-conceal-implicit  syntax.txt      /*:syn-conceal-implicit*
+:syn-concealends       syntax.txt      /*:syn-concealends*
 :syn-contained syntax.txt      /*:syn-contained*
 :syn-containedin       syntax.txt      /*:syn-containedin*
 :syn-contains  syntax.txt      /*:syn-contains*
@@ -4956,6 +4969,7 @@ complete_check()  eval.txt        /*complete_check()*
 complex-change change.txt      /*complex-change*
 complex-repeat repeat.txt      /*complex-repeat*
 compress       pi_gzip.txt     /*compress*
+conceal        syntax.txt      /*conceal*
 confirm()      eval.txt        /*confirm()*
 connection-refused     message.txt     /*connection-refused*
 console-menus  gui.txt /*console-menus*
@@ -6019,6 +6033,7 @@ hit-enter-prompt  message.txt     /*hit-enter-prompt*
 hit-return     message.txt     /*hit-return*
 hitest.vim     syntax.txt      /*hitest.vim*
 hjkl   usr_02.txt      /*hjkl*
+hl-Conceal     syntax.txt      /*hl-Conceal*
 hl-Cursor      syntax.txt      /*hl-Cursor*
 hl-CursorColumn        syntax.txt      /*hl-CursorColumn*
 hl-CursorIM    syntax.txt      /*hl-CursorIM*
@@ -6895,6 +6910,7 @@ os_unix.txt       os_unix.txt     /*os_unix.txt*
 os_vms.txt     os_vms.txt      /*os_vms.txt*
 os_win32.txt   os_win32.txt    /*os_win32.txt*
 other-features vi_diff.txt     /*other-features*
+ownsyntax      eval.txt        /*ownsyntax*
 p      change.txt      /*p*
 page-down      intro.txt       /*page-down*
 page-up        intro.txt       /*page-up*
@@ -8200,6 +8216,7 @@ vt100-cursor-keys term.txt        /*vt100-cursor-keys*
 vt100-function-keys    term.txt        /*vt100-function-keys*
 w      motion.txt      /*w*
 w32-clientserver       remote.txt      /*w32-clientserver*
+w:ownsyntax-variable   eval.txt        /*w:ownsyntax-variable*
 w:var  eval.txt        /*w:var*
 warningmsg-variable    eval.txt        /*warningmsg-variable*
 white-space    pattern.txt     /*white-space*
index 27039a2492a7304a915491d993cbcd65a21055f5..12c6b682ab3c26e31d5a85777e54ca4bedd83c0c 100644 (file)
@@ -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)
index 3f1d061ba5bcbbde585518584288e3c1a8f5903f..63b279b322c7ef3ef93391e686f6c37d3569769e 100644 (file)
@@ -293,8 +293,10 @@ N  *+cmdline_compl*        command line completion |cmdline-completion|
 N  *+cmdline_hist*     command line history |cmdline-history|
 N  *+cmdline_info*     |'showcmd'| and |'ruler'|
 N  *+comments*         |'comments'| support
+m  *+conceal*          "conceal" support, see ||conceal|| |:syn-conceal| etc.
 N  *+cryptv*           encryption support |encryption|
 B  *+cscope*           |cscope| support
+m  *+cursorbind*       |'cursorbind'| support
 m  *+cursorshape*      |termcap-cursor-shape| support
 m  *+debug*            Compiled for debugging.
 N  *+dialog_gui*       Support for |:confirm| with GUI dialog.
index 0ace4cc6d4c78966af4c89e1b0b5094de80f3ab3..12e934f2dd468161ab7616ac628e612cbc5bd3f4 100644 (file)
@@ -373,6 +373,11 @@ if has("linebreak")
   call append("$", "\t(local to window)")
   call <SID>OptionL("nuw")
 endif
+if has("conceal")
+  call append("$", "conceallevel\tcontrols whether concealable elements are hidden")
+  call append("$", "\t(local to window)")
+  call <SID>OptionL("conc")
+endif
 
 
 call <SID>Header("syntax, highlighting and spelling")
index 5ecb63872732f9f8ca9344cd6c36e23d640e97dd..cf7ecbbe9517f7995af956af4f43681a882c44d9 100644 (file)
@@ -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);
index bf6254598f913639a05dafae31298ad47616ce89..e733ccd45c011d35523a0d02a851d5a31a155fc8 100644 (file)
@@ -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
index a6a28cc9a3a9f19594609c36ea26e1676dd80e07..9f7106165e93a18d299867e6d7aa8344f12130f9 100644 (file)
@@ -698,6 +698,10 @@ edit(cmdchar, startln, count)
            do_check_scrollbind(TRUE);
 #endif
 
+#ifdef FEAT_CURSORBIND
+       if (curwin->w_p_crb)
+           do_check_cursorbind();
+#endif
        update_curswant();
        old_topline = curwin->w_topline;
 #ifdef FEAT_DIFF
@@ -1277,7 +1281,7 @@ doESCkey:
            inserted_space = FALSE;
            break;
 
-#if defined(FEAT_DIGRAPHS) || defined (FEAT_INS_EXPAND)
+#if defined(FEAT_DIGRAPHS) || defined(FEAT_INS_EXPAND)
        case Ctrl_K:        /* digraph or keyword completion */
 # ifdef FEAT_INS_EXPAND
            if (ctrl_x_mode == CTRL_X_DICTIONARY)
@@ -1470,7 +1474,7 @@ ins_redraw(ready)
             * highlighting is correct after making a change (e.g., inserting
             * a "(".  The autocommand may also require a redraw, so it's done
             * again below, unfortunately. */
-           if (syntax_present(curbuf) && must_redraw)
+           if (syntax_present(curwin) && must_redraw)
                update_screen(0);
 # endif
            apply_autocmds(EVENT_CURSORMOVEDI, NULL, NULL, FALSE, curbuf);
@@ -2960,7 +2964,7 @@ ins_compl_dictionaries(dict_start, pat, flags, thesaurus)
                ptr = pat + 2;
            else
                ptr = pat;
-           spell_dump_compl(curbuf, ptr, regmatch.rm_ic, &dir, 0);
+           spell_dump_compl(ptr, regmatch.rm_ic, &dir, 0);
        }
        else
 # endif
@@ -9119,6 +9123,9 @@ ins_s_right()
 ins_up(startcol)
     int                startcol;       /* when TRUE move to Insstart.col */
 {
+#ifdef FEAT_CONCEAL
+    linenr_T   oldline = curwin->w_cursor.lnum;
+#endif
     pos_T      tpos;
     linenr_T   old_topline = curwin->w_topline;
 #ifdef FEAT_DIFF
@@ -9140,6 +9147,13 @@ ins_up(startcol)
        start_arrow(&tpos);
 #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
@@ -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
@@ -9203,6 +9221,16 @@ ins_down(startcol)
        start_arrow(&tpos);
 #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
index e777d32558f7b6520d2e5d643cac2d13bec3de22..ca9389fb390f384195770cc19058d9b4a3e1b1fc 100644 (file)
@@ -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.
      */
index 2df5a4ae8e88f946dc3d09e7961823ba5c12f064..f05a0656d47bfca54edec794305c1d44e6701a90 100644 (file)
@@ -3411,6 +3411,14 @@ do_ecmd(fnum, ffname, sfname, eap, newlnum, flags, oldwin)
                else
 #endif
                {
+#ifdef FEAT_SYN_HL
+                   /*
+                    * <VN> We could instead free the synblock
+                    * and re-attach to buffer, perhaps.
+                    */
+                   if (curwin->w_s == &(curwin->w_buffer->b_s))
+                           curwin->w_s = &(buf->b_s);
+#endif
                    curwin->w_buffer = buf;
                    curbuf = buf;
                    ++curbuf->b_nwindows;
@@ -3717,8 +3725,8 @@ do_ecmd(fnum, ffname, sfname, eap, newlnum, flags, oldwin)
 #ifdef FEAT_SPELL
     /* If the window options were changed may need to set the spell language.
      * Can only do this after the buffer has been properly setup. */
-    if (did_get_winopts && curwin->w_p_spell && *curbuf->b_p_spl != NUL)
-       (void)did_set_spelllang(curbuf);
+    if (did_get_winopts && curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL)
+       (void)did_set_spelllang(curwin);
 #endif
 
     if (command == NULL)
@@ -5963,7 +5971,7 @@ fix_help_buffer()
     set_option_value((char_u *)"ft", 0L, (char_u *)"help", OPT_LOCAL);
 
 #ifdef FEAT_SYN_HL
-    if (!syntax_present(curbuf))
+    if (!syntax_present(curwin))
 #endif
     {
        for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum)
index f41e0f449d4012a565bf0019a1db0c207eeb86de..4e0e16918089b30c2965293ebba936e213e77477 100644 (file)
@@ -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,
index e5ce640e23ad38f730d166c01d7de21c924e02d7..f07bb4ce6ea953ca905308c023fe8e95688776cf 100644 (file)
@@ -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
index c6d0b40ecb36057c0d754b4f85f0d471de6440fc..96a3a872f079ab3017d2b86971b67dab695d035a 100644 (file)
@@ -235,6 +235,7 @@ static void ex_popup __ARGS((exarg_T *eap));
 #endif
 #ifndef FEAT_SYN_HL
 # define ex_syntax             ex_ni
+# define ex_ownsyntax          ex_ni
 #endif
 #ifndef FEAT_SPELL
 # define ex_spell              ex_ni
index 4f35280b708c75c6c3962673ebefb04848aad9fa..5bca7c7d7686c1354a7260438045159047c7a737 100644 (file)
 # define FEAT_SYN_HL
 #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
 # define FEAT_SCROLLBIND
 #endif
 
+/*
+ * +cursorbind         synchronization of split windows
+ */
+#if defined(FEAT_NORMAL) && defined(FEAT_WINDOWS)
+# define FEAT_CURSORBIND
+#endif
+
 /*
  * +menu               ":menu" command
  */
     && (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
 
index b085bcb73c309d1a7b6c7813d8e137298b4cbe9e..f4ec25713c457fb89c96af72c094413d81b262bf 100644 (file)
@@ -1151,6 +1151,9 @@ EXTERN int        lcs_nbsp INIT(= NUL);
 EXTERN int     lcs_tab1 INIT(= NUL);
 EXTERN int     lcs_tab2 INIT(= NUL);
 EXTERN int     lcs_trail INIT(= NUL);
+#ifdef FEAT_CONCEAL
+EXTERN int     lcs_conceal INIT(= '-');
+#endif
 
 #if defined(FEAT_WINDOWS) || defined(FEAT_WILDMENU) || defined(FEAT_STL_OPT) \
        || defined(FEAT_FOLDING)
@@ -1412,7 +1415,7 @@ EXTERN char_u e_invexpr2[]        INIT(= N_("E15: Invalid expression: %s"));
 #endif
 EXTERN char_u e_invrange[]     INIT(= N_("E16: Invalid range"));
 EXTERN char_u e_invcmd[]       INIT(= N_("E476: Invalid command"));
-#if defined(UNIX) || defined(FEAT_SYN_HL)
+#if defined(UNIX) || defined(FEAT_SYN_HL) || defined(FEAT_SPELL)
 EXTERN char_u e_isadir2[]      INIT(= N_("E17: \"%s\" is a directory"));
 #endif
 #ifdef FEAT_LIBCALL
index e70390d4430af23ea497c1f409cc8ef2c92e2ad4..744a2a2f19e02872f787bb752b4c79fd6e33bf9c 100644 (file)
@@ -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')
index 4f23ffa8b834ca7915171bea61feb1094a532574..1b0780158ed53a42838440b028f49e63f405c005 100644 (file)
@@ -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
 
index 4b1492c63cb78123c4c0a06b4fceb9c5486a0de0..88962755bf8a14f8b90f13be016e34e8cf179b16 100644 (file)
@@ -86,6 +86,7 @@ static void process_menuItem(char *);
 static void process_toolbarButton(char *);
 static void workshop_set_option_first(char *name, char *value);
 
+static size_t dummy;  /* to ignore return value of write() */
 
 #define CMDBUFSIZ      2048
 
@@ -183,7 +184,7 @@ messageFromEserve(XtPointer clientData UNUSED,
                        ackNum = atoi(&cmd[4]);
                        vim_snprintf(buf, sizeof(buf),
                                               NOCATGETS("ack %d\n"), ackNum);
-                       (void)write(sd, buf, strlen(buf));
+                       dummy = write(sd, buf, strlen(buf));
                } else if (strncmp(cmd,
                    NOCATGETS("addMarkType "), 12) == 0) {
                        int idx;
@@ -280,7 +281,7 @@ messageFromEserve(XtPointer clientData UNUSED,
                        vim_snprintf(buf, sizeof(buf),
                                             NOCATGETS("markLine %s %d %d\n"),
                            file, markid, line);
-                       (void)write(sd, buf, strlen(buf));
+                       dummy = write(sd, buf, strlen(buf));
                } else if (cmd[1] == 'o' && cmd[4] == 'L' &&
                    strncmp(cmd, NOCATGETS("gotoLine "), 9) == 0) {
                        char *file;
@@ -729,10 +730,10 @@ void      workshop_connect(XtAppContext context)
                workshop_get_editor_name(),
                PROTOCOL_VERSION,
                workshop_get_editor_version());
-       (void)write(sd, buf, strlen(buf));
+       dummy = write(sd, buf, strlen(buf));
 
        vim_snprintf(buf, sizeof(buf), NOCATGETS("ack 1\n"));
-       (void)write(sd, buf, strlen(buf));
+       dummy = write(sd, buf, strlen(buf));
 }
 
 void   workshop_disconnect()
@@ -1059,7 +1060,7 @@ void workshop_file_closed(char *filename)
        char buffer[2*MAXPATHLEN];
        vim_snprintf(buffer, sizeof(buffer),
                        NOCATGETS("deletedFile %s\n"), filename);
-       (void)write(sd, buffer, strlen(buffer));
+       dummy = write(sd, buffer, strlen(buffer));
 }
 #endif
 
@@ -1068,7 +1069,7 @@ void workshop_file_closed_lineno(char *filename, int lineno)
        char buffer[2*MAXPATHLEN];
        vim_snprintf(buffer, sizeof(buffer),
                        NOCATGETS("deletedFile %s %d\n"), filename, lineno);
-       (void)write(sd, buffer, strlen(buffer));
+       dummy = write(sd, buffer, strlen(buffer));
 }
 
 void workshop_file_opened(char *filename, int readOnly)
@@ -1076,7 +1077,7 @@ void workshop_file_opened(char *filename, int readOnly)
        char buffer[2*MAXPATHLEN];
        vim_snprintf(buffer, sizeof(buffer),
                        NOCATGETS("loadedFile %s %d\n"), filename, readOnly);
-       (void)write(sd, buffer, strlen(buffer));
+       dummy = write(sd, buffer, strlen(buffer));
 }
 
 
@@ -1085,7 +1086,7 @@ void workshop_file_saved(char *filename)
        char buffer[2*MAXPATHLEN];
        vim_snprintf(buffer, sizeof(buffer),
                        NOCATGETS("savedFile %s\n"), filename);
-       (void)write(sd, buffer, strlen(buffer));
+       dummy = write(sd, buffer, strlen(buffer));
 
        /* Let editor report any moved marks that the eserve client
         * should deal with (for example, moving location-based breakpoints) */
@@ -1098,7 +1099,7 @@ void workshop_file_modified(char *filename)
        char buffer[2*MAXPATHLEN];
        vim_snprintf(buffer, sizeof(buffer),
                        NOCATGETS("modifiedFile %s\n"), filename);
-       (void)write(sd, buffer, strlen(buffer));
+       dummy = write(sd, buffer, strlen(buffer));
 }
 
 void workshop_move_mark(char *filename, int markId, int newLineno)
@@ -1106,7 +1107,7 @@ void workshop_move_mark(char *filename, int markId, int newLineno)
        char buffer[2*MAXPATHLEN];
        vim_snprintf(buffer, sizeof(buffer),
               NOCATGETS("moveMark %s %d %d\n"), filename, markId, newLineno);
-       (void)write(sd, buffer, strlen(buffer));
+       dummy = write(sd, buffer, strlen(buffer));
 }
 #endif
 
@@ -1119,7 +1120,7 @@ void workshop_frame_moved(int new_x, int new_y, int new_w, int new_h)
                vim_snprintf(buffer, sizeof(buffer),
                                NOCATGETS("frameAt %d %d %d %d\n"),
                                new_x, new_y, new_w, new_h);
-               (void)write(sd, buffer, strlen(buffer));
+               dummy = write(sd, buffer, strlen(buffer));
        }
 }
 
@@ -1179,7 +1180,7 @@ void workshop_perform_verb(char *verb, void *clientData)
                        selEndLine, selEndCol,
                        selLength,
                        selection);
-               (void)write(sd, buf, strlen(buf));
+               dummy = write(sd, buf, strlen(buf));
                if (*selection) {
                        free(selection);
                }
@@ -1190,7 +1191,7 @@ void workshop_perform_verb(char *verb, void *clientData)
 #if defined(NOHANDS_SUPPORT_FUNCTIONS) || defined(FEAT_BEVAL)
 void workshop_send_message(char *buf)
 {
-       (void)write(sd, buf, strlen(buf));
+       dummy = write(sd, buf, strlen(buf));
 }
 #endif
 
index e6275899c2b5fce2c962d6b1a44d3f829e4c5b86..e4df00ad5e079b4b0e9d41d5bafc6075189e9259 100644 (file)
@@ -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
index cdc8c14790eadde2f0a17b0cb9f196ecdf6fb458..3dd45c00dbb4c7a4b4aad5eb3bec304cb1fd41cf 100644 (file)
@@ -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 */
index 3e8a492ec93f16502ce6d3892a6f348fb36d1a0c..002430d712dc7e5440ddd841c85a36abbb559858 100644 (file)
@@ -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
 }
 
 /*
@@ -5795,6 +5824,9 @@ nv_right(cap)
     int                PAST_LINE;
 #else
 # define PAST_LINE 0
+#endif
+#ifdef FEAT_CONCEAL
+    linenr_T   oldline = curwin->w_cursor.lnum;
 #endif
 
     if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
@@ -5900,6 +5932,13 @@ nv_right(cap)
                                               && cap->oap->op_type == OP_NOP)
        foldOpenCursor();
 #endif
+#ifdef FEAT_CONCEAL
+    if (curwin->w_p_conceal && oldline != curwin->w_cursor.lnum)
+    {
+       update_single_line(curwin, oldline);
+       update_single_line(curwin, curwin->w_cursor.lnum);
+    }
+#endif
 }
 
 /*
@@ -5912,6 +5951,9 @@ nv_left(cap)
     cmdarg_T   *cap;
 {
     long       n;
+#ifdef FEAT_CONCEAL
+    linenr_T   oldline = curwin->w_cursor.lnum;
+#endif
 
     if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
     {
@@ -5970,6 +6012,13 @@ nv_left(cap)
                                               && cap->oap->op_type == OP_NOP)
        foldOpenCursor();
 #endif
+#ifdef FEAT_CONCEAL
+    if (curwin->w_p_conceal && oldline != curwin->w_cursor.lnum)
+    {
+       update_single_line(curwin, oldline);
+       update_single_line(curwin, curwin->w_cursor.lnum);
+    }
+#endif
 }
 
 /*
@@ -5988,11 +6037,21 @@ nv_up(cap)
     }
     else
     {
+#ifdef FEAT_CONCEAL
+       linenr_T        oldline = curwin->w_cursor.lnum;
+#endif
        cap->oap->motion_type = MLINE;
        if (cursor_up(cap->count1, cap->oap->op_type == OP_NOP) == FAIL)
            clearopbeep(cap->oap);
        else if (cap->arg)
            beginline(BL_WHITE | BL_FIX);
+#ifdef FEAT_CONCEAL
+       if (curwin->w_p_conceal && oldline != curwin->w_cursor.lnum)
+       {
+           update_single_line(curwin, oldline);
+           update_single_line(curwin, curwin->w_cursor.lnum);
+       }
+#endif
     }
 }
 
@@ -6021,6 +6080,10 @@ nv_down(cap)
     else
 #endif
     {
+#ifdef FEAT_CONCEAL
+       linenr_T        oldline = curwin->w_cursor.lnum;
+       linenr_T        oldbotline = curwin->w_botline;
+#endif
 #ifdef FEAT_CMDWIN
        /* In the cmdline window a <CR> executes the command. */
        if (cmdwin_type != 0 && cap->cmdchar == CAR)
@@ -6033,6 +6096,16 @@ nv_down(cap)
                clearopbeep(cap->oap);
            else if (cap->arg)
                beginline(BL_WHITE | BL_FIX);
+#ifdef FEAT_CONCEAL
+           if (curwin->w_p_conceal && oldline != curwin->w_cursor.lnum)
+           {
+               update_single_line(curwin, oldline);
+               /* Don't do this if we've scrolled, the line is already
+                * drawn */
+               if (oldbotline == curwin->w_botline)
+                   update_single_line(curwin, curwin->w_cursor.lnum);
+           }
+#endif
        }
     }
 }
@@ -8197,6 +8270,10 @@ nv_g_cmd(cap)
 n_opencmd(cap)
     cmdarg_T   *cap;
 {
+#ifdef FEAT_CONCEAL
+    linenr_T   oldline = curwin->w_cursor.lnum;
+#endif
+
     if (!checkclearopq(cap->oap))
     {
 #ifdef FEAT_FOLDING
@@ -8220,6 +8297,10 @@ n_opencmd(cap)
 #endif
                    0, 0))
        {
+#ifdef FEAT_CONCEAL
+           if (curwin->w_p_conceal && oldline != curwin->w_cursor.lnum)
+               update_single_line(curwin, oldline);
+#endif
            /* When '#' is in 'cpoptions' ignore the count. */
            if (vim_strchr(p_cpo, CPO_HASH) != NULL)
                cap->count1 = 1;
@@ -8424,6 +8505,9 @@ nv_pipe(cap)
 nv_bck_word(cap)
     cmdarg_T   *cap;
 {
+#ifdef FEAT_CONCEAL
+    linenr_T   oldline = curwin->w_cursor.lnum;
+#endif
     cap->oap->motion_type = MCHAR;
     cap->oap->inclusive = FALSE;
     curwin->w_set_curswant = TRUE;
@@ -8433,6 +8517,13 @@ nv_bck_word(cap)
     else if ((fdo_flags & FDO_HOR) && KeyTyped && cap->oap->op_type == OP_NOP)
        foldOpenCursor();
 #endif
+#ifdef FEAT_CONCEAL
+    if (curwin->w_p_conceal && oldline != curwin->w_cursor.lnum)
+    {
+       update_single_line(curwin, oldline);
+       update_single_line(curwin, curwin->w_cursor.lnum);
+    }
+#endif
 }
 
 /*
@@ -8447,6 +8538,9 @@ nv_wordcmd(cap)
     int                word_end;
     int                flag = FALSE;
     pos_T      startpos = curwin->w_cursor;
+#ifdef FEAT_CONCEAL
+    linenr_T   oldline = startpos.lnum;
+#endif
 
     /*
      * Set inclusive for the "E" and "e" command.
@@ -8524,6 +8618,13 @@ nv_wordcmd(cap)
            foldOpenCursor();
 #endif
     }
+#ifdef FEAT_CONCEAL
+    if (curwin->w_p_conceal && oldline != curwin->w_cursor.lnum)
+    {
+       update_single_line(curwin, oldline);
+       update_single_line(curwin, curwin->w_cursor.lnum);
+    }
+#endif
 }
 
 /*
@@ -8686,6 +8787,10 @@ nv_goto(cap)
     if ((fdo_flags & FDO_JUMP) && KeyTyped && cap->oap->op_type == OP_NOP)
        foldOpenCursor();
 #endif
+#ifdef FEAT_CONCEAL
+    if (curwin->w_p_conceal)
+       changed_window_setting();
+#endif
 }
 
 /*
@@ -9110,6 +9215,9 @@ nv_put(cap)
     void       *reg1 = NULL, *reg2 = NULL;
     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
     }
 }
 
index b5392dd12c4446f5a748d4b31393904cd902dabc..d06381cb84acd42301ee2de7ecdc2a44a3ed71d0 100644 (file)
 # define PV_WFW                OPT_WIN(WV_WFW)
 #endif
 #define PV_WRAP                OPT_WIN(WV_WRAP)
-
+#ifdef FEAT_CURSORBIND
+# define PV_CRBIND     OPT_WIN(WV_CRBIND)
+#endif
+#ifdef FEAT_CONCEAL
+# define PV_CONCEAL    OPT_WIN(WV_CONCEAL)
+#endif
 
 /* WV_ and BV_ values get typecasted to this for the "indir" field */
 typedef enum
@@ -460,8 +465,8 @@ struct vimoption
  * possible when compiling with few features. */
 #if defined(FEAT_DIFF) || defined(FEAT_FOLDING) || defined(FEAT_SPELL) \
        || defined(FEAT_VERTSPLIT) || defined(FEAT_CLIPBOARD) \
-       || defined(FEAT_INS_EXPAND) || defined(FEAT_SYN_HL)
-# define HIGHLIGHT_INIT "8:SpecialKey,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn,B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel,x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill,!:CursorColumn,.:CursorLine"
+       || defined(FEAT_INS_EXPAND) || defined(FEAT_SYN_HL) || defined(FEAT_CONCEAL)
+# define HIGHLIGHT_INIT "8:SpecialKey,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn,-:Conceal,B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel,x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill,!:CursorColumn,.:CursorLine"
 #else
 # define HIGHLIGHT_INIT "8:SpecialKey,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,r:Question,s:StatusLine,S:StatusLineNC,t:Title,v:Visual,w:WarningMsg,W:WildMenu,>:SignColumn,*:TabLine,#:TabLineSel,_:TabLineFill"
 #endif
@@ -805,6 +810,14 @@ static struct vimoption
                            {(char_u *)0L, (char_u *)0L}
 #endif
                            SCRIPTID_INIT},
+    {"conceallevel","conc", P_NUM|P_RWIN|P_VI_DEF,
+#ifdef FEAT_CONCEAL
+                           (char_u *)VAR_WIN, PV_CONCEAL,
+#else
+                           (char_u *)NULL, PV_NONE,
+#endif
+                           {(char_u *)0L, (char_u *)0L}
+                           SCRIPTID_INIT},
     {"completefunc", "cfu", P_STRING|P_ALLOCED|P_VI_DEF|P_SECURE,
 #ifdef FEAT_COMPL_FUNC
                            (char_u *)&p_cfu, PV_CFU,
@@ -897,6 +910,13 @@ static struct vimoption
                            (char_u *)NULL, PV_NONE,
 #endif
                            {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT},
+    {"cursorbind",  "crb",  P_BOOL|P_VI_DEF,
+#ifdef FEAT_CURSORBIND
+                           (char_u *)VAR_WIN, PV_CRBIND,
+#else
+                           (char_u *)NULL, PV_NONE,
+#endif
+                           {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT},
     {"cursorcolumn", "cuc", P_BOOL|P_VI_DEF|P_RWIN,
 #ifdef FEAT_SYN_HL
                            (char_u *)VAR_WIN, PV_CUC,
@@ -2959,7 +2979,7 @@ static char_u *set_chars_option __ARGS((char_u **varp));
 static char_u *check_clipboard_option __ARGS((void));
 #endif
 #ifdef FEAT_SPELL
-static char_u *compile_cap_prog __ARGS((buf_T *buf));
+static char_u *compile_cap_prog __ARGS((synblock_T *synblock));
 #endif
 #ifdef FEAT_EVAL
 static void set_option_scriptID_idx __ARGS((int opt_idx, int opt_flags, int id));
@@ -5127,7 +5147,7 @@ didset_options()
 #ifdef FEAT_SPELL
     (void)spell_check_msm();
     (void)spell_check_sps();
-    (void)compile_cap_prog(curbuf);
+    (void)compile_cap_prog(curwin->w_s);
 #endif
 #if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_W32)
     (void)opt_strings_flags(p_toolbar, p_toolbar_values, &toolbar_flags, TRUE);
@@ -5208,9 +5228,9 @@ check_buf_options(buf)
     check_string_option(&buf->b_p_syn);
 #endif
 #ifdef FEAT_SPELL
-    check_string_option(&buf->b_p_spc);
-    check_string_option(&buf->b_p_spf);
-    check_string_option(&buf->b_p_spl);
+    check_string_option(&buf->b_s.b_p_spc);
+    check_string_option(&buf->b_s.b_p_spf);
+    check_string_option(&buf->b_s.b_p_spl);
 #endif
 #ifdef FEAT_SEARCHPATH
     check_string_option(&buf->b_p_sua);
@@ -6407,15 +6427,15 @@ did_set_string_option(opt_idx, varp, new_value_alloced, oldval, errbuf,
 #ifdef FEAT_SPELL
     /* When 'spelllang' or 'spellfile' is set and there is a window for this
      * buffer in which 'spell' is set load the wordlists. */
-    else if (varp == &(curbuf->b_p_spl) || varp == &(curbuf->b_p_spf))
+    else if (varp == &(curbuf->b_s.b_p_spl) || varp == &(curbuf->b_s.b_p_spf))
     {
        win_T       *wp;
        int         l;
 
-       if (varp == &(curbuf->b_p_spf))
+       if (varp == &(curbuf->b_s.b_p_spf))
        {
-           l = (int)STRLEN(curbuf->b_p_spf);
-           if (l > 0 && (l < 4 || STRCMP(curbuf->b_p_spf + l - 4,
+           l = (int)STRLEN(curbuf->b_s.b_p_spf);
+           if (l > 0 && (l < 4 || STRCMP(curbuf->b_s.b_p_spf + l - 4,
                                                                ".add") != 0))
                errmsg = e_invarg;
        }
@@ -6425,7 +6445,7 @@ did_set_string_option(opt_idx, varp, new_value_alloced, oldval, errbuf,
            FOR_ALL_WINDOWS(wp)
                if (wp->w_buffer == curbuf && wp->w_p_spell)
                {
-                   errmsg = did_set_spelllang(curbuf);
+                   errmsg = did_set_spelllang(wp);
 # ifdef FEAT_WINDOWS
                    break;
 # endif
@@ -6433,9 +6453,9 @@ did_set_string_option(opt_idx, varp, new_value_alloced, oldval, errbuf,
        }
     }
     /* When 'spellcapcheck' is set compile the regexp program. */
-    else if (varp == &(curbuf->b_p_spc))
+    else if (varp == &(curwin->w_s->b_p_spc))
     {
-       errmsg = compile_cap_prog(curbuf);
+       errmsg = compile_cap_prog(curwin->w_s);
     }
     /* 'spellsuggest' */
     else if (varp == &p_sps)
@@ -6843,7 +6863,7 @@ did_set_string_option(opt_idx, varp, new_value_alloced, oldval, errbuf,
        }
 #endif
 #ifdef FEAT_SPELL
-       if (varp == &(curbuf->b_p_spl))
+       if (varp == &(curwin->w_s->b_p_spl))
        {
            char_u      fname[200];
 
@@ -6853,11 +6873,11 @@ did_set_string_option(opt_idx, varp, new_value_alloced, oldval, errbuf,
             * Use the first name in 'spelllang' up to '_region' or
             * '.encoding'.
             */
-           for (p = curbuf->b_p_spl; *p != NUL; ++p)
+           for (p = curwin->w_s->b_p_spl; *p != NUL; ++p)
                if (vim_strchr((char_u *)"_.,", *p) != NULL)
                    break;
            vim_snprintf((char *)fname, 200, "spell/%.*s.vim",
-                                (int)(p - curbuf->b_p_spl), curbuf->b_p_spl);
+                                (int)(p - curwin->w_s->b_p_spl), curwin->w_s->b_p_spl);
            source_runtime(fname, TRUE);
        }
 #endif
@@ -6920,6 +6940,11 @@ set_chars_option(varp)
        {&lcs_prec,     "precedes"},
        {&lcs_tab2,     "tab"},
        {&lcs_trail,    "trail"},
+#ifdef FEAT_CONCEAL
+       {&lcs_conceal,  "conceal"},
+#else
+       {NULL,          "conceal"},
+#endif
     };
     struct charstab *tab;
 
@@ -6941,12 +6966,13 @@ set_chars_option(varp)
     /* first round: check for valid value, second round: assign values */
     for (round = 0; round <= 1; ++round)
     {
-       if (round)
+       if (round > 0)
        {
            /* After checking that the value is valid: set defaults: space for
             * 'fillchars', NUL for 'listchars' */
            for (i = 0; i < entries; ++i)
-               *(tab[i].cp) = (varp == &p_lcs ? NUL : ' ');
+               if (tab[i].cp != NULL)
+                   *(tab[i].cp) = (varp == &p_lcs ? NUL : ' ');
            if (varp == &p_lcs)
                lcs_tab1 = NUL;
 #if defined(FEAT_WINDOWS) || defined(FEAT_FOLDING)
@@ -6993,7 +7019,7 @@ set_chars_option(varp)
                                lcs_tab1 = c1;
                                lcs_tab2 = c2;
                            }
-                           else
+                           else if (tab[i].cp != NULL)
                                *(tab[i].cp) = c1;
 
                        }
@@ -7170,24 +7196,24 @@ check_clipboard_option()
  * Return error message when failed, NULL when OK.
  */
     static char_u *
-compile_cap_prog(buf)
-    buf_T      *buf;
+compile_cap_prog(synblock)
+    synblock_T *synblock;
 {
-    regprog_T   *rp = buf->b_cap_prog;
+    regprog_T   *rp = synblock->b_cap_prog;
     char_u     *re;
 
-    if (*buf->b_p_spc == NUL)
-       buf->b_cap_prog = NULL;
+    if (*synblock->b_p_spc == NUL)
+       synblock->b_cap_prog = NULL;
     else
     {
        /* Prepend a ^ so that we only match at one column */
-       re = concat_str((char_u *)"^", buf->b_p_spc);
+       re = concat_str((char_u *)"^", synblock->b_p_spc);
        if (re != NULL)
        {
-           buf->b_cap_prog = vim_regcomp(re, RE_MAGIC);
-           if (buf->b_cap_prog == NULL)
+           synblock->b_cap_prog = vim_regcomp(re, RE_MAGIC);
+           if (synblock->b_cap_prog == NULL)
            {
-               buf->b_cap_prog = rp; /* restore the previous program */
+               synblock->b_cap_prog = rp; /* restore the previous program */
                return e_invarg;
            }
            vim_free(re);
@@ -7588,8 +7614,7 @@ set_bool_option(opt_idx, varp, value, opt_flags)
     {
        if (curwin->w_p_spell)
        {
-           char_u      *errmsg = did_set_spelllang(curbuf);
-
+           char_u      *errmsg = did_set_spelllang(curwin);
            if (errmsg != NULL)
                EMSG(_(errmsg));
        }
@@ -8089,6 +8114,21 @@ set_num_option(opt_idx, varp, value, errbuf, errbuflen, opt_flags)
        if (p_uc && !old_value)
            ml_open_files();
     }
+#ifdef FEAT_CONCEAL
+    else if (pp == (long *)&curwin->w_p_conceal)
+    {
+       if (curwin->w_p_conceal < 0)
+       {
+           errmsg = e_positive;
+           curwin->w_p_conceal = 0;
+       }
+       else if (curwin->w_p_conceal > 3)
+       {
+           errmsg = e_invarg;
+           curwin->w_p_conceal = 3;
+       }
+    }
+#endif
 #ifdef MZSCHEME_GUI_THREADS
     else if (pp == &p_mzq)
        mzvim_reset_timer();
@@ -9327,6 +9367,12 @@ get_varp(p)
 #ifdef FEAT_SCROLLBIND
        case PV_SCBIND: return (char_u *)&(curwin->w_p_scb);
 #endif
+#ifdef FEAT_CURSORBIND
+       case PV_CRBIND: return (char_u *)&(curwin->w_p_crb);
+#endif
+#ifdef FEAT_CONCEAL
+       case PV_CONCEAL:    return (char_u *)&(curwin->w_p_conceal);
+#endif
 
        case PV_AI:     return (char_u *)&(curbuf->b_p_ai);
        case PV_BIN:    return (char_u *)&(curbuf->b_p_bin);
@@ -9425,9 +9471,9 @@ get_varp(p)
        case PV_SYN:    return (char_u *)&(curbuf->b_p_syn);
 #endif
 #ifdef FEAT_SPELL
-       case PV_SPC:    return (char_u *)&(curbuf->b_p_spc);
-       case PV_SPF:    return (char_u *)&(curbuf->b_p_spf);
-       case PV_SPL:    return (char_u *)&(curbuf->b_p_spl);
+       case PV_SPC:    return (char_u *)&(curwin->w_s->b_p_spc);
+       case PV_SPF:    return (char_u *)&(curwin->w_s->b_p_spf);
+       case PV_SPL:    return (char_u *)&(curwin->w_s->b_p_spl);
 #endif
        case PV_SW:     return (char_u *)&(curbuf->b_p_sw);
        case PV_TS:     return (char_u *)&(curbuf->b_p_ts);
@@ -9750,10 +9796,10 @@ buf_copy_options(buf, flags)
            buf->b_p_smc = p_smc;
 #endif
 #ifdef FEAT_SPELL
-           buf->b_p_spc = vim_strsave(p_spc);
-           (void)compile_cap_prog(buf);
-           buf->b_p_spf = vim_strsave(p_spf);
-           buf->b_p_spl = vim_strsave(p_spl);
+           buf->b_s.b_p_spc = vim_strsave(p_spf);
+           (void)compile_cap_prog(&buf->b_s);
+           buf->b_s.b_p_spf = vim_strsave(p_spf);
+           buf->b_s.b_p_spl = vim_strsave(p_spl);
 #endif
 #if defined(FEAT_CINDENT) && defined(FEAT_EVAL)
            buf->b_p_inde = vim_strsave(p_inde);
index f0ebc8de7a7b50f07251ce00f614ece6ae505149..489bdb2a91fc9fa963c0845b83aa7ba2a2d21a5d 100644 (file)
@@ -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
index e45127ad0de2c8258348c02940b695d81dc98065..f314fce58b0fc8f163471b35cd2bfa1620889e06 100644 (file)
@@ -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 : */
index de51aa240f7610d3cde7fcc9827d5cd87b2f5b98..f1f3a11378b4e133a0b3aa45de82c7103e203ff4 100644 (file)
@@ -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));
index c534a1f9eefde6b79086e5af5a2d49fff637b4cf..937e4ed5a553f4c460aa905995aa8c648b3a9ce0 100644 (file)
@@ -46,5 +46,6 @@ void get_trans_bufname __ARGS((buf_T *buf));
 int redrawing __ARGS((void));
 int messaging __ARGS((void));
 void showruler __ARGS((int always));
+void update_single_line __ARGS((win_T *buf, linenr_T lnum));
 int number_width __ARGS((win_T *wp));
 /* vim: set ft=c : */
index 8ab544dbf021ceb630cc84df8f46f07ee81d727b..9ed775b53ebb252fc15f98bf355842621ef8887d 100644 (file)
@@ -2,14 +2,10 @@
 int spell_check __ARGS((win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, int docount));
 int spell_move_to __ARGS((win_T *wp, int dir, int allwords, int curline, hlf_T *attrp));
 void spell_cat_line __ARGS((char_u *buf, char_u *line, int maxlen));
-int get2c __ARGS((FILE *fd));
-int get3c __ARGS((FILE *fd));
-int get4c __ARGS((FILE *fd));
-char_u *did_set_spelllang __ARGS((buf_T *buf));
+char_u *did_set_spelllang __ARGS((win_T *wp));
 void spell_free_all __ARGS((void));
 void spell_reload __ARGS((void));
 int spell_check_msm __ARGS((void));
-int put_bytes __ARGS((FILE *fd, long_u nr, int len));
 void ex_mkspell __ARGS((exarg_T *eap));
 void ex_spell __ARGS((exarg_T *eap));
 void spell_add_word __ARGS((char_u *word, int len, int bad, int idx, int undo));
@@ -21,8 +17,8 @@ void spell_suggest_list __ARGS((garray_T *gap, char_u *word, int maxcount, int n
 char_u *eval_soundfold __ARGS((char_u *word));
 void ex_spellinfo __ARGS((exarg_T *eap));
 void ex_spelldump __ARGS((exarg_T *eap));
-void spell_dump_compl __ARGS((buf_T *buf, char_u *pat, int ic, int *dir, int dumpflags_arg));
-char_u *spell_to_word_end __ARGS((char_u *start, buf_T *buf));
+void spell_dump_compl __ARGS((char_u *pat, int ic, int *dir, int dumpflags_arg));
+char_u *spell_to_word_end __ARGS((char_u *start, win_T *win));
 int spell_word_start __ARGS((int startcol));
 void spell_expand_check_cap __ARGS((colnr_T col));
 int expand_spelling __ARGS((linenr_T lnum, char_u *pat, char_u ***matchp));
index c27769198b032e9a2b6cdaef9b8e682897071d11..0e484cbc6e665b5d1f3cfd7008c4b5ad88f74d93 100644 (file)
@@ -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));
index df5489f8bffed74aa66f5bdd61289d49faf09041..3205d3d4892866c2afb8a4f4250a87b3b19ba204 100644 (file)
@@ -485,7 +485,7 @@ update_screen(type)
 # ifdef FEAT_WINDOWS
                    wwp == wp &&
 # endif
-                   syntax_present(wp->w_buffer))
+                   syntax_present(wp))
                syn_stack_apply_changes(wp->w_buffer);
        }
     }
@@ -585,6 +585,54 @@ update_screen(type)
 #endif
 }
 
+#if defined(FEAT_CONCEAL) || defined(PROTO)
+    void
+update_single_line(wp, lnum)
+    win_T      *wp;
+    linenr_T   lnum;
+{
+    int                row;
+    int                j;
+
+    if (lnum >= wp->w_topline && lnum < wp->w_botline
+                                         && foldedCount(wp, lnum, NULL) == 0)
+    {
+# ifdef FEAT_GUI
+       /* Remove the cursor before starting to do anything, because scrolling
+        * may make it difficult to redraw the text under it. */
+       if (gui.in_use)
+           gui_undraw_cursor();
+# endif
+       row = 0;
+       for (j = 0; j < wp->w_lines_valid; ++j)
+       {
+           if (lnum == wp->w_lines[j].wl_lnum)
+           {
+               screen_start(); /* not sure of screen cursor */
+# if defined(FEAT_SEARCH_EXTRA)
+               start_search_hl();
+               prepare_search_hl(wp, lnum);
+# endif
+               win_line(wp, lnum, row, row + wp->w_lines[j].wl_size, FALSE);
+# if defined(FEAT_SEARCH_EXTRA)
+               end_search_hl();
+# endif
+               break;
+           }
+           row += wp->w_lines[j].wl_size;
+       }
+# ifdef FEAT_GUI
+       /* Redraw the cursor */
+       if (gui.in_use)
+       {
+           out_flush();        /* required before updating the cursor */
+           gui_update_cursor(FALSE, FALSE);
+       }
+# endif
+    }
+}
+#endif
+
 #if defined(FEAT_SIGNS) || defined(FEAT_GUI)
 static void update_prepare __ARGS((void));
 static void update_finish __ARGS((void));
@@ -917,9 +965,9 @@ win_update(wp)
 #ifdef FEAT_SYN_HL
                /* Need to redraw lines above the change that may be included
                 * in a pattern match. */
-               if (syntax_present(buf))
+               if (syntax_present(wp))
                {
-                   mod_top -= buf->b_syn_sync_linebreaks;
+                   mod_top -= buf->b_s.b_syn_sync_linebreaks;
                    if (mod_top < 1)
                        mod_top = 1;
                }
@@ -1010,7 +1058,7 @@ win_update(wp)
            if (mod_bot > wp->w_topline)
                mod_top = wp->w_topline;
 #ifdef FEAT_SYN_HL
-           else if (syntax_present(buf))
+           else if (syntax_present(wp))
                top_end = 1;
 #endif
        }
@@ -1545,7 +1593,7 @@ win_update(wp)
 #ifdef FEAT_SYN_HL
                                || did_update == DID_FOLD
                                || (did_update == DID_LINE
-                                   && syntax_present(buf)
+                                   && syntax_present(wp)
                                    && (
 # ifdef FEAT_FOLDING
                                        (foldmethodIsSyntax(wp)
@@ -1771,7 +1819,7 @@ win_update(wp)
 #ifdef FEAT_SYN_HL
                /* Let the syntax stuff know we skipped a few lines. */
                if (syntax_last_parsed != 0 && syntax_last_parsed + 1 < lnum
-                                                      && syntax_present(buf))
+                                                      && syntax_present(wp))
                    syntax_end_parsing(syntax_last_parsed + 1);
 #endif
 
@@ -1843,7 +1891,7 @@ win_update(wp)
     /*
      * Let the syntax stuff know we stop parsing here.
      */
-    if (syntax_last_parsed != 0 && syntax_present(buf))
+    if (syntax_last_parsed != 0 && syntax_present(wp))
        syntax_end_parsing(syntax_last_parsed + 1);
 #endif
 
@@ -2726,6 +2774,14 @@ win_line(wp, lnum, startrow, endrow, nochange)
     int                feedback_old_attr = -1;
 #endif
 
+#ifdef FEAT_CONCEAL
+    int                syntax_flags    = 0;
+    int                conceal_attr    = hl_attr(HLF_CONCEAL);
+    int                first_conceal   = (wp->w_p_conceal != 3);
+    int                is_concealing   = FALSE;
+    int                boguscols       = 0;    /* nonexistent columns added to force
+                                          wrapping */
+#endif
 
     if (startrow > endrow)             /* past the end already! */
        return startrow;
@@ -2743,7 +2799,7 @@ win_line(wp, lnum, startrow, endrow, nochange)
     extra_check = 0;
 #endif
 #ifdef FEAT_SYN_HL
-    if (syntax_present(wp->w_buffer) && !wp->w_buffer->b_syn_error)
+    if (syntax_present(wp) && !wp->w_s->b_syn_error)
     {
        /* Prepare for syntax highlighting in this line.  When there is an
         * error, stop syntax highlighting. */
@@ -2751,7 +2807,7 @@ win_line(wp, lnum, startrow, endrow, nochange)
        did_emsg = FALSE;
        syntax_start(wp, lnum);
        if (did_emsg)
-           wp->w_buffer->b_syn_error = TRUE;
+           wp->w_s->b_syn_error = TRUE;
        else
        {
            did_emsg = save_did_emsg;
@@ -2763,9 +2819,9 @@ win_line(wp, lnum, startrow, endrow, nochange)
 
 #ifdef FEAT_SPELL
     if (wp->w_p_spell
-           && *wp->w_buffer->b_p_spl != NUL
-           && wp->w_buffer->b_langp.ga_len > 0
-           && *(char **)(wp->w_buffer->b_langp.ga_data) != NULL)
+           && *wp->w_s->b_p_spl != NUL
+           && wp->w_s->b_langp.ga_len > 0
+           && *(char **)(wp->w_s->b_langp.ga_data) != NULL)
     {
        /* Prepare for spell checking. */
        has_spell = TRUE;
@@ -3113,7 +3169,7 @@ win_line(wp, lnum, startrow, endrow, nochange)
                /* no bad word found at line start, don't check until end of a
                 * word */
                spell_hlf = HLF_COUNT;
-               word_end = (int)(spell_to_word_end(ptr, wp->w_buffer)
+               word_end = (int)(spell_to_word_end(ptr, wp)
                                                                  - line + 1);
            }
            else
@@ -3962,14 +4018,19 @@ win_line(wp, lnum, startrow, endrow, nochange)
                    did_emsg = FALSE;
 
                    syntax_attr = get_syntax_attr((colnr_T)v - 1,
+# ifdef FEAT_CONCEAL
+                                               &syntax_flags,
+# else
+                                               NULL,
+# endif
 # ifdef FEAT_SPELL
-                                              has_spell ? &can_spell :
+                                               has_spell ? &can_spell :
 # endif
-                                              NULL, FALSE);
+                                               NULL, FALSE);
 
                    if (did_emsg)
                    {
-                       wp->w_buffer->b_syn_error = TRUE;
+                       wp->w_s->b_syn_error = TRUE;
                        has_syntax = FALSE;
                    }
                    else
@@ -4304,6 +4365,74 @@ win_line(wp, lnum, startrow, endrow, nochange)
                }
 #endif
            }
+
+#ifdef FEAT_CONCEAL
+           if (    wp->w_p_conceal
+                   && (!area_highlighting)
+                   && ((lnum != wp->w_cursor.lnum)
+                       || (curwin != wp) || (wp->w_buffer->b_p_ma == FALSE))
+                   && ((syntax_flags & HL_CONCEAL) != 0))
+
+           {
+               char_attr = conceal_attr;
+               if (first_conceal
+                       && (syn_get_sub_char() != NUL || wp->w_p_conceal == 1))
+               {
+                   if (syn_get_sub_char() != NUL)
+                       c = syn_get_sub_char();
+                   else if (lcs_conceal != NUL)
+                       c = lcs_conceal;
+                   else
+                       c = ' ';
+
+                   first_conceal = FALSE;
+
+# ifdef FEAT_HLCOLUMN
+                   if (hlc > 0 && n_extra > 0)
+                       hlc += n_extra;
+# endif
+                   vcol += n_extra;
+                   if (wp->w_p_wrap && n_extra > 0)
+                   {
+# ifdef FEAT_RIGHTLEFT
+                       if (wp->w_p_rl)
+                       {
+                           col -= n_extra;
+                           boguscols -= n_extra;
+                       }
+                       else
+# endif
+                       {
+                           boguscols += n_extra;
+                           col += n_extra;
+                       }
+                   }
+                   n_extra = 0;
+                   n_attr = 0;
+               }
+               else if (n_skip == 0)
+               {
+                   is_concealing = TRUE;
+                   n_skip = 1;
+               }
+# ifdef FEAT_MBYTE
+               mb_c = c;
+               if (enc_utf8 && (*mb_char2len)(c) > 1)
+               {
+                   mb_utf8 = TRUE;
+                   u8cc[0] = 0;
+                   c = 0xc0;
+               }
+               else
+                   mb_utf8 = FALSE;    /* don't draw as UTF-8 */
+# endif
+           }
+           else
+           {
+               first_conceal   = (wp->w_p_conceal != 3);
+               is_concealing   = FALSE;
+           }
+#endif /* FEAT_CONCEAL */
        }
 
        /* Don't override visual selection highlighting. */
@@ -4570,8 +4699,14 @@ win_line(wp, lnum, startrow, endrow, nochange)
            }
 #endif
 
-           SCREEN_LINE(screen_row, W_WINCOL(wp), col, (int)W_WIDTH(wp),
-                                                                 wp->w_p_rl);
+#ifdef FEAT_CONCEAL
+           SCREEN_LINE(screen_row, W_WINCOL(wp), col - boguscols,
+                                               (int)W_WIDTH(wp), wp->w_p_rl);
+           boguscols = 0;
+#else
+           SCREEN_LINE(screen_row, W_WINCOL(wp), col,
+                                               (int)W_WIDTH(wp), wp->w_p_rl);
+#endif
            row++;
 
            /*
@@ -4730,6 +4865,97 @@ win_line(wp, lnum, startrow, endrow, nochange)
                ++col;
            }
        }
+#ifdef FEAT_CONCEAL
+       else if (wp->w_p_conceal && is_concealing)
+       {
+           --n_skip;
+# ifdef FEAT_HLCOLUMN
+           if (hlc)
+           {
+               ++hlc;
+               if (n_extra > 0)
+                   hlc += n_extra;
+           }
+# endif
+           if (wp->w_p_wrap)
+           {
+               /*
+                * Special voodoo required if 'wrap' is on.
+                *
+                * Advance the column indicator to force the line
+                * drawing to wrap early. This will make the line
+                * take up the same screen space when parts are concealed,
+                * so that cursor line computations aren't messed up.
+                *
+                * To avoid the fictitious advance of 'col' causing
+                * trailing junk to be written out of the screen line
+                * we are building, 'boguscols' keeps track of the number
+                * of bad columns we have advanced.
+                */
+               if (n_extra > 0)
+               {
+                   vcol += n_extra;
+# ifdef FEAT_RIGHTLEFT
+                   if (wp->w_p_rl)
+                   {
+                       col -= n_extra;
+                       boguscols -= n_extra;
+                   }
+                   else
+# endif
+                   {
+                       col += n_extra;
+                       boguscols += n_extra;
+                   }
+                   n_extra = 0;
+                   n_attr = 0;
+               }
+
+
+# ifdef FEAT_MBYTE
+               if (has_mbyte && (*mb_char2cells)(mb_c) > 1)
+               {
+                   /* Need to fill two screen columns. */
+#  ifdef FEAT_RIGHTLEFT
+                   if (wp->w_p_rl)
+                   {
+                       --boguscols;
+                       --col;
+                   }
+                   else
+#  endif
+                   {
+                       ++boguscols;
+                       ++col;
+                   }
+               }
+# endif
+
+# ifdef FEAT_RIGHTLEFT
+               if (wp->w_p_rl)
+               {
+                   --boguscols;
+                   --col;
+               }
+               else
+# endif
+               {
+                   ++boguscols;
+                   ++col;
+               }
+           }
+           else
+           {
+               if (n_extra > 0)
+               {
+                   vcol += n_extra;
+                   n_extra = 0;
+                   n_attr = 0;
+               }
+           }
+
+       }
+#endif /* FEAT_CONCEAL */
        else
            --n_skip;
 
@@ -4772,8 +4998,14 @@ win_line(wp, lnum, startrow, endrow, nochange)
                    || (n_extra != 0 && (c_extra != NUL || *p_extra != NUL)))
                )
        {
-           SCREEN_LINE(screen_row, W_WINCOL(wp), col, (int)W_WIDTH(wp),
-                                                                 wp->w_p_rl);
+#ifdef FEAT_CONCEAL
+           SCREEN_LINE(screen_row, W_WINCOL(wp), col - boguscols,
+                                               (int)W_WIDTH(wp), wp->w_p_rl);
+           boguscols = 0;
+#else
+           SCREEN_LINE(screen_row, W_WINCOL(wp), col,
+                                               (int)W_WIDTH(wp), wp->w_p_rl);
+#endif
            ++row;
            ++screen_row;
 
index 3ad9140c12fff6e5bfb5dfe9a9aef8b9100f081f..76ba6607ed7a1be37327e04d55a35487ebf4e5ec 100644 (file)
@@ -1077,6 +1077,9 @@ do_search(oap, dirc, pat, count, options, tm)
     char_u         *dircp;
     char_u         *strcopy = NULL;
     char_u         *ps;
+#ifdef FEAT_CONCEAL
+    linenr_T   oldline = curwin->w_cursor.lnum;
+#endif
 
     /*
      * A line offset is not remembered, this is vi compatible.
@@ -1422,6 +1425,13 @@ do_search(oap, dirc, pat, count, options, tm)
        setpcmark();
     curwin->w_cursor = pos;
     curwin->w_set_curswant = TRUE;
+#ifdef FEAT_CONCEAL
+    if (curwin->w_p_conceal && oldline != curwin->w_cursor.lnum)
+    {
+       update_single_line(curwin, oldline);
+       update_single_line(curwin, curwin->w_cursor.lnum);
+    }
+#endif
 
 end_do_search:
     if (options & SEARCH_KEEP)
index fbf5c910b03e402febd161819029ca412af2c5c0..b4d6ca72de0d476dc6f949bd29368bb3cb97feea 100644 (file)
@@ -720,7 +720,7 @@ typedef struct matchinf_S
     /* others */
     int                mi_result;              /* result so far: SP_BAD, SP_OK, etc. */
     int                mi_capflags;            /* WF_ONECAP WF_ALLCAP WF_KEEPCAP */
-    buf_T      *mi_buf;                /* buffer being checked */
+    win_T      *mi_win;                /* buffer being checked */
 
     /* for NOBREAK */
     int                mi_result2;             /* "mi_resul" without following word */
@@ -747,11 +747,11 @@ static int            did_set_spelltab;
 
 static void clear_spell_chartab __ARGS((spelltab_T *sp));
 static int set_spell_finish __ARGS((spelltab_T *new_st));
-static int spell_iswordp __ARGS((char_u *p, buf_T *buf));
+static int spell_iswordp __ARGS((char_u *p, win_T *wp));
 static int spell_iswordp_nmw __ARGS((char_u *p));
 #ifdef FEAT_MBYTE
 static int spell_mb_isword_class __ARGS((int cl));
-static int spell_iswordp_w __ARGS((int *p, buf_T *buf));
+static int spell_iswordp_w __ARGS((int *p, win_T *wp));
 #endif
 static int write_spell_prefcond __ARGS((FILE *fd, garray_T *gap));
 
@@ -874,9 +874,9 @@ static void set_sal_first __ARGS((slang_T *lp));
 static int *mb_str2wide __ARGS((char_u *s));
 #endif
 static int spell_read_tree __ARGS((FILE *fd, char_u **bytsp, idx_T **idxsp, int prefixtree, int prefixcnt));
-static idx_T read_tree_node __ARGS((FILE *fd, char_u *byts, idx_T *idxs, int maxidx, int startidx, int prefixtree, int maxprefcondnr));
-static void clear_midword __ARGS((buf_T *buf));
-static void use_midword __ARGS((slang_T *lp, buf_T *buf));
+static idx_T read_tree_node __ARGS((FILE *fd, char_u *byts, idx_T *idxs, int maxidx, idx_T startidx, int prefixtree, int maxprefcondnr));
+static void clear_midword __ARGS((win_T *buf));
+static void use_midword __ARGS((slang_T *lp, win_T *buf));
 static int find_region __ARGS((char_u *rp, char_u *region));
 static int captype __ARGS((char_u *word, char_u *end));
 static int badword_captype __ARGS((char_u *word, char_u *end));
@@ -1030,7 +1030,7 @@ spell_check(wp, ptr, attrp, capcol, docount)
        return 1;
 
     /* Return here when loading language files failed. */
-    if (wp->w_buffer->b_langp.ga_len == 0)
+    if (wp->w_s->b_langp.ga_len == 0)
        return 1;
 
     vim_memset(&mi, 0, sizeof(matchinf_T));
@@ -1050,14 +1050,14 @@ spell_check(wp, ptr, attrp, capcol, docount)
     /* Find the normal end of the word (until the next non-word character). */
     mi.mi_word = ptr;
     mi.mi_fend = ptr;
-    if (spell_iswordp(mi.mi_fend, wp->w_buffer))
+    if (spell_iswordp(mi.mi_fend, wp))
     {
        do
        {
            mb_ptr_adv(mi.mi_fend);
-       } while (*mi.mi_fend != NUL && spell_iswordp(mi.mi_fend, wp->w_buffer));
+       } while (*mi.mi_fend != NUL && spell_iswordp(mi.mi_fend, wp));
 
-       if (capcol != NULL && *capcol == 0 && wp->w_buffer->b_cap_prog != NULL)
+       if (capcol != NULL && *capcol == 0 && wp->w_s->b_cap_prog != NULL)
        {
            /* Check word starting with capital letter. */
            c = PTR2CHAR(ptr);
@@ -1073,7 +1073,9 @@ spell_check(wp, ptr, attrp, capcol, docount)
     mi.mi_end = mi.mi_fend;
 
     /* Check caps type later. */
-    mi.mi_buf = wp->w_buffer;
+    mi.mi_capflags = 0;
+    mi.mi_cend = NULL;
+    mi.mi_win = wp;
 
     /* case-fold the word with one non-word character, so that we can check
      * for the word end. */
@@ -1093,9 +1095,9 @@ spell_check(wp, ptr, attrp, capcol, docount)
      * We check them all, because a word may be matched longer in another
      * language.
      */
-    for (lpi = 0; lpi < wp->w_buffer->b_langp.ga_len; ++lpi)
+    for (lpi = 0; lpi < wp->w_s->b_langp.ga_len; ++lpi)
     {
-       mi.mi_lp = LANGP_ENTRY(wp->w_buffer->b_langp, lpi);
+       mi.mi_lp = LANGP_ENTRY(wp->w_s->b_langp, lpi);
 
        /* If reloading fails the language is still in the list but everything
         * has been cleared. */
@@ -1143,12 +1145,12 @@ spell_check(wp, ptr, attrp, capcol, docount)
         * skip over the character (try looking for a word after it). */
        else if (!spell_iswordp_nmw(ptr))
        {
-           if (capcol != NULL && wp->w_buffer->b_cap_prog != NULL)
+           if (capcol != NULL && wp->w_s->b_cap_prog != NULL)
            {
                regmatch_T      regmatch;
 
                /* Check for end of sentence. */
-               regmatch.regprog = wp->w_buffer->b_cap_prog;
+               regmatch.regprog = wp->w_s->b_cap_prog;
                regmatch.rm_ic = FALSE;
                if (vim_regexec(&regmatch, ptr, 0))
                    *capcol = (int)(regmatch.endp[0] - ptr);
@@ -1165,14 +1167,14 @@ spell_check(wp, ptr, attrp, capcol, docount)
             * is a mixup in "midword". */
            mb_ptr_adv(mi.mi_end);
        else if (mi.mi_result == SP_BAD
-               && LANGP_ENTRY(wp->w_buffer->b_langp, 0)->lp_slang->sl_nobreak)
+               && LANGP_ENTRY(wp->w_s->b_langp, 0)->lp_slang->sl_nobreak)
        {
            char_u      *p, *fp;
            int         save_result = mi.mi_result;
 
            /* First language in 'spelllang' is NOBREAK.  Find first position
             * at which any word would be valid. */
-           mi.mi_lp = LANGP_ENTRY(wp->w_buffer->b_langp, 0);
+           mi.mi_lp = LANGP_ENTRY(wp->w_s->b_langp, 0);
            if (mi.mi_lp->lp_slang->sl_fidxs != NULL)
            {
                p = mi.mi_word;
@@ -1389,7 +1391,7 @@ find_word(mip, mode)
        if ((*mb_head_off)(ptr, ptr + wlen) > 0)
            continue;       /* not at first byte of character */
 #endif
-       if (spell_iswordp(ptr + wlen, mip->mi_buf))
+       if (spell_iswordp(ptr + wlen, mip->mi_win))
        {
            if (slang->sl_compprog == NULL && !slang->sl_nobreak)
                continue;           /* next char is a word character */
@@ -1634,11 +1636,11 @@ find_word(mip, mode)
 
                /* For NOBREAK we need to try all NOBREAK languages, at least
                 * to find the ".add" file(s). */
-               for (lpi = 0; lpi < mip->mi_buf->b_langp.ga_len; ++lpi)
+               for (lpi = 0; lpi < mip->mi_win->w_s->b_langp.ga_len; ++lpi)
                {
                    if (slang->sl_nobreak)
                    {
-                       mip->mi_lp = LANGP_ENTRY(mip->mi_buf->b_langp, lpi);
+                       mip->mi_lp = LANGP_ENTRY(mip->mi_win->w_s->b_langp, lpi);
                        if (mip->mi_lp->lp_slang->sl_fidxs == NULL
                                         || !mip->mi_lp->lp_slang->sl_nobreak)
                            continue;
@@ -2102,7 +2104,7 @@ fold_more(mip)
     do
     {
        mb_ptr_adv(mip->mi_fend);
-    } while (*mip->mi_fend != NUL && spell_iswordp(mip->mi_fend, mip->mi_buf));
+    } while (*mip->mi_fend != NUL && spell_iswordp(mip->mi_fend, mip->mi_win));
 
     /* Include the non-word character so that we can check for the word end. */
     if (*mip->mi_fend != NUL)
@@ -2138,8 +2140,8 @@ spell_valid_case(wordflags, treeflags)
 no_spell_checking(wp)
     win_T      *wp;
 {
-    if (!wp->w_p_spell || *wp->w_buffer->b_p_spl == NUL
-                                        || wp->w_buffer->b_langp.ga_len == 0)
+    if (!wp->w_p_spell || *wp->w_s->b_p_spl == NUL
+                                        || wp->w_s->b_langp.ga_len == 0)
     {
        EMSG(_("E756: Spell checking is not enabled"));
        return TRUE;
@@ -2173,7 +2175,7 @@ spell_move_to(wp, dir, allwords, curline, attrp)
     hlf_T      attr;
     int                len;
 # ifdef FEAT_SYN_HL
-    int                has_syntax = syntax_present(wp->w_buffer);
+    int                has_syntax = syntax_present(wp);
 # endif
     int                col;
     int                can_spell;
@@ -4165,12 +4167,12 @@ read_tree_node(fd, byts, idxs, maxidx, startidx, prefixtree, maxprefcondnr)
 }
 
 /*
- * Parse 'spelllang' and set buf->b_langp accordingly.
+ * Parse 'spelllang' and set w_s->b_langp accordingly.
  * Returns NULL if it's OK, an error message otherwise.
  */
     char_u *
-did_set_spelllang(buf)
-    buf_T      *buf;
+did_set_spelllang(wp)
+    win_T      *wp;
 {
     garray_T   ga;
     char_u     *splp;
@@ -4203,11 +4205,11 @@ did_set_spelllang(buf)
     recursive = TRUE;
 
     ga_init2(&ga, sizeof(langp_T), 2);
-    clear_midword(buf);
+    clear_midword(wp);
 
     /* Make a copy of 'spellang', the SpellFileMissing autocommands may change
      * it under our fingers. */
-    spl_copy = vim_strsave(buf->b_p_spl);
+    spl_copy = vim_strsave(wp->w_s->b_p_spl);
     if (spl_copy == NULL)
        goto theend;
 
@@ -4216,7 +4218,6 @@ did_set_spelllang(buf)
     {
        /* Get one language name. */
        copy_option_part(&splp, lang, MAXWLEN, ",");
-
        region = NULL;
        len = (int)STRLEN(lang);
 
@@ -4283,7 +4284,7 @@ did_set_spelllang(buf)
 #ifdef FEAT_AUTOCMD
                /* SpellFileMissing autocommands may do anything, including
                 * destroying the buffer we are using... */
-               if (!buf_valid(buf))
+               if (!buf_valid(wp->w_buffer))
                {
                    ret_msg = (char_u *)"E797: SpellFileMissing autocommand deleted buffer";
                    goto theend;
@@ -4334,7 +4335,7 @@ did_set_spelllang(buf)
                    LANGP_ENTRY(ga, ga.ga_len)->lp_slang = slang;
                    LANGP_ENTRY(ga, ga.ga_len)->lp_region = region_mask;
                    ++ga.ga_len;
-                   use_midword(slang, buf);
+                   use_midword(slang, wp);
                    if (slang->sl_nobreak)
                        nobreak = TRUE;
                }
@@ -4345,7 +4346,7 @@ did_set_spelllang(buf)
      * round 1: load first name in 'spellfile'.
      * round 2: load second name in 'spellfile.
      * etc. */
-    spf = buf->b_p_spf;
+    spf = curwin->w_s->b_p_spf;
     for (round = 0; round == 0 || *spf != NUL; ++round)
     {
        if (round == 0)
@@ -4418,14 +4419,14 @@ did_set_spelllang(buf)
                LANGP_ENTRY(ga, ga.ga_len)->lp_replang = NULL;
                LANGP_ENTRY(ga, ga.ga_len)->lp_region = region_mask;
                ++ga.ga_len;
-               use_midword(slang, buf);
+               use_midword(slang, wp);
            }
        }
     }
 
     /* Everything is fine, store the new b_langp value. */
-    ga_clear(&buf->b_langp);
-    buf->b_langp = ga;
+    ga_clear(&wp->w_s->b_langp);
+    wp->w_s->b_langp = ga;
 
     /* For each language figure out what language to use for sound folding and
      * REP items.  If the language doesn't support it itself use another one
@@ -4481,13 +4482,13 @@ theend:
  * Clear the midword characters for buffer "buf".
  */
     static void
-clear_midword(buf)
-    buf_T      *buf;
+clear_midword(wp)
+    win_T      *wp;
 {
-    vim_memset(buf->b_spell_ismw, 0, 256);
+    vim_memset(wp->w_s->b_spell_ismw, 0, 256);
 #ifdef FEAT_MBYTE
-    vim_free(buf->b_spell_ismw_mb);
-    buf->b_spell_ismw_mb = NULL;
+    vim_free(wp->w_s->b_spell_ismw_mb);
+    wp->w_s->b_spell_ismw_mb = NULL;
 #endif
 }
 
@@ -4496,9 +4497,9 @@ clear_midword(buf)
  * They add up to any currently used midword characters.
  */
     static void
-use_midword(lp, buf)
+use_midword(lp, wp)
     slang_T    *lp;
-    buf_T      *buf;
+    win_T      *wp;
 {
     char_u     *p;
 
@@ -4515,19 +4516,19 @@ use_midword(lp, buf)
            c = mb_ptr2char(p);
            l = (*mb_ptr2len)(p);
            if (c < 256 && l <= 2)
-               buf->b_spell_ismw[c] = TRUE;
-           else if (buf->b_spell_ismw_mb == NULL)
+               wp->w_s->b_spell_ismw[c] = TRUE;
+           else if (wp->w_s->b_spell_ismw_mb == NULL)
                /* First multi-byte char in "b_spell_ismw_mb". */
-               buf->b_spell_ismw_mb = vim_strnsave(p, l);
+               wp->w_s->b_spell_ismw_mb = vim_strnsave(p, l);
            else
            {
                /* Append multi-byte chars to "b_spell_ismw_mb". */
-               n = (int)STRLEN(buf->b_spell_ismw_mb);
-               bp = vim_strnsave(buf->b_spell_ismw_mb, n + l);
+               n = (int)STRLEN(wp->w_s->b_spell_ismw_mb);
+               bp = vim_strnsave(wp->w_s->b_spell_ismw_mb, n + l);
                if (bp != NULL)
                {
-                   vim_free(buf->b_spell_ismw_mb);
-                   buf->b_spell_ismw_mb = bp;
+                   vim_free(wp->w_s->b_spell_ismw_mb);
+                   wp->w_s->b_spell_ismw_mb = bp;
                    vim_strncpy(bp + n, p, l);
                }
            }
@@ -4535,7 +4536,7 @@ use_midword(lp, buf)
        }
        else
 #endif
-           buf->b_spell_ismw[*p++] = TRUE;
+           wp->w_s->b_spell_ismw[*p++] = TRUE;
 }
 
 /*
@@ -4678,9 +4679,9 @@ spell_free_all()
     buf_T      *buf;
     char_u     fname[MAXPATHL];
 
-    /* Go through all buffers and handle 'spelllang'. */
+    /* Go through all buffers and handle 'spelllang'. */ //<VN>
     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
-       ga_clear(&buf->b_langp);
+       ga_clear(&buf->b_s.b_langp);
 
     while (first_lang != NULL)
     {
@@ -4716,7 +4717,6 @@ spell_free_all()
     void
 spell_reload()
 {
-    buf_T      *buf;
     win_T      *wp;
 
     /* Initialize the table for spell_iswordp(). */
@@ -4726,16 +4726,15 @@ spell_reload()
     spell_free_all();
 
     /* Go through all buffers and handle 'spelllang'. */
-    for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+    for (wp = firstwin; wp != NULL; wp = wp->w_next)
     {
        /* Only load the wordlists when 'spelllang' is set and there is a
         * window for this buffer in which 'spell' is set. */
-       if (*buf->b_p_spl != NUL)
+       if (*wp->w_s->b_p_spl != NUL)
        {
-           FOR_ALL_WINDOWS(wp)
-               if (wp->w_buffer == buf && wp->w_p_spell)
+               if (wp->w_p_spell)
                {
-                   (void)did_set_spelllang(buf);
+                   (void)did_set_spelllang(wp);
 # ifdef FEAT_WINDOWS
                    break;
 # endif
@@ -4772,7 +4771,7 @@ spell_reload_one(fname, added_word)
     /* When "zg" was used and the file wasn't loaded yet, should redo
      * 'spelllang' to load it now. */
     if (added_word && !didit)
-       did_set_spelllang(curbuf);
+       did_set_spelllang(curwin);
 }
 
 
@@ -9369,19 +9368,19 @@ spell_add_word(word, len, bad, idx, undo)
     else
     {
        /* If 'spellfile' isn't set figure out a good default value. */
-       if (*curbuf->b_p_spf == NUL)
+       if (*curwin->w_s->b_p_spf == NUL)
        {
            init_spellfile();
            new_spf = TRUE;
        }
 
-       if (*curbuf->b_p_spf == NUL)
+       if (*curwin->w_s->b_p_spf == NUL)
        {
            EMSG2(_(e_notset), "spellfile");
            return;
        }
 
-       for (spf = curbuf->b_p_spf, i = 1; *spf != NUL; ++i)
+       for (spf = curwin->w_s->b_p_spf, i = 1; *spf != NUL; ++i)
        {
            copy_option_part(&spf, fnamebuf, MAXPATHL, ",");
            if (i == idx)
@@ -9507,13 +9506,13 @@ init_spellfile()
     char_u     *rtp;
     char_u     *lend;
     int                aspath = FALSE;
-    char_u     *lstart = curbuf->b_p_spl;
+    char_u     *lstart = curbuf->b_s.b_p_spl;
 
-    if (*curbuf->b_p_spl != NUL && curbuf->b_langp.ga_len > 0)
+    if (*curwin->w_s->b_p_spl != NUL && curwin->w_s->b_langp.ga_len > 0)
     {
        /* Find the end of the language name.  Exclude the region.  If there
         * is a path separator remember the start of the tail. */
-       for (lend = curbuf->b_p_spl; *lend != NUL
+       for (lend = curwin->w_s->b_p_spl; *lend != NUL
                        && vim_strchr((char_u *)",._", *lend) == NULL; ++lend)
            if (vim_ispathsep(*lend))
            {
@@ -9529,7 +9528,7 @@ init_spellfile()
            if (aspath)
                /* Use directory of an entry with path, e.g., for
                 * "/dir/lg.utf-8.spl" use "/dir". */
-               vim_strncpy(buf, curbuf->b_p_spl, lstart - curbuf->b_p_spl - 1);
+               vim_strncpy(buf, curbuf->b_s.b_p_spl, lstart - curbuf->b_s.b_p_spl - 1);
            else
                /* Copy the path from 'runtimepath' to buf[]. */
                copy_option_part(&rtp, buf, MAXPATHL, ",");
@@ -9538,7 +9537,7 @@ init_spellfile()
                /* Use the first language name from 'spelllang' and the
                 * encoding used in the first loaded .spl file. */
                if (aspath)
-                   vim_strncpy(buf, curbuf->b_p_spl, lend - curbuf->b_p_spl);
+                   vim_strncpy(buf, curbuf->b_s.b_p_spl, lend - curbuf->b_s.b_p_spl);
                else
                {
                    /* Create the "spell" directory if it doesn't exist yet. */
@@ -9552,7 +9551,7 @@ init_spellfile()
                                 "/%.*s", (int)(lend - lstart), lstart);
                }
                l = (int)STRLEN(buf);
-               fname = LANGP_ENTRY(curbuf->b_langp, 0)->lp_slang->sl_fname;
+               fname = LANGP_ENTRY(curwin->w_s->b_langp, 0)->lp_slang->sl_fname;
                vim_snprintf((char *)buf + l, MAXPATHL - l, ".%s.add",
                        fname != NULL
                          && strstr((char *)gettail(fname), ".ascii.") != NULL
@@ -9819,9 +9818,9 @@ set_spell_finish(new_st)
  * Thus this only works properly when past the first character of the word.
  */
     static int
-spell_iswordp(p, buf)
+spell_iswordp(p, wp)
     char_u     *p;
-    buf_T      *buf;       /* buffer used */
+    win_T      *wp;        /* buffer used */
 {
 #ifdef FEAT_MBYTE
     char_u     *s;
@@ -9835,7 +9834,7 @@ spell_iswordp(p, buf)
        if (l == 1)
        {
            /* be quick for ASCII */
-           if (buf->b_spell_ismw[*p])
+           if (wp->w_s->b_spell_ismw[*p])
            {
                s = p + 1;              /* skip a mid-word character */
                l = MB_BYTE2LEN(*s);
@@ -9844,9 +9843,9 @@ spell_iswordp(p, buf)
        else
        {
            c = mb_ptr2char(p);
-           if (c < 256 ? buf->b_spell_ismw[c]
-                   : (buf->b_spell_ismw_mb != NULL
-                          && vim_strchr(buf->b_spell_ismw_mb, c) != NULL))
+           if (c < 256 ? wp->w_s->b_spell_ismw[c]
+                   : (wp->w_s->b_spell_ismw_mb != NULL
+                          && vim_strchr(wp->w_s->b_spell_ismw_mb, c) != NULL))
            {
                s = p + l;
                l = MB_BYTE2LEN(*s);
@@ -9860,7 +9859,7 @@ spell_iswordp(p, buf)
     }
 #endif
 
-    return spelltab.st_isw[buf->b_spell_ismw[*p] ? p[1] : p[0]];
+    return spelltab.st_isw[wp->w_s->b_spell_ismw[*p] ? p[1] : p[0]];
 }
 
 /*
@@ -9903,15 +9902,15 @@ spell_mb_isword_class(cl)
  * Wide version of spell_iswordp().
  */
     static int
-spell_iswordp_w(p, buf)
+spell_iswordp_w(p, wp)
     int                *p;
-    buf_T      *buf;
+    win_T      *wp;
 {
     int                *s;
 
-    if (*p < 256 ? buf->b_spell_ismw[*p]
-                : (buf->b_spell_ismw_mb != NULL
-                            && vim_strchr(buf->b_spell_ismw_mb, *p) != NULL))
+    if (*p < 256 ? wp->w_s->b_spell_ismw[*p]
+                : (wp->w_s->b_spell_ismw_mb != NULL
+                            && vim_strchr(wp->w_s->b_spell_ismw_mb, *p) != NULL))
        s = p + 1;
     else
        s = p;
@@ -10347,7 +10346,7 @@ check_need_cap(lnum, col)
     colnr_T    endcol;
     regmatch_T regmatch;
 
-    if (curbuf->b_cap_prog == NULL)
+    if (curwin->w_s->b_cap_prog == NULL)
        return FALSE;
 
     line = ml_get_curline();
@@ -10378,7 +10377,7 @@ check_need_cap(lnum, col)
     if (endcol > 0)
     {
        /* Check if sentence ends before the bad word. */
-       regmatch.regprog = curbuf->b_cap_prog;
+       regmatch.regprog = curwin->w_s->b_cap_prog;
        regmatch.rm_ic = FALSE;
        p = line + endcol;
        for (;;)
@@ -10577,9 +10576,9 @@ spell_find_suggest(badptr, badlen, su, maxcount, banbadword, need_cap, interacti
      * one in 'spelllang' that supports sound folding.  That's good for when
      * using multiple files for one language, it's not that bad when mixing
      * languages (e.g., "pl,en"). */
-    for (i = 0; i < curbuf->b_langp.ga_len; ++i)
+    for (i = 0; i < curbuf->b_s.b_langp.ga_len; ++i)
     {
-       lp = LANGP_ENTRY(curbuf->b_langp, i);
+       lp = LANGP_ENTRY(curbuf->b_s.b_langp, i);
        if (lp->lp_sallang != NULL)
        {
            su->su_sallang = lp->lp_sallang;
@@ -10862,9 +10861,9 @@ suggest_load_files()
     int                c;
 
     /* Do this for all languages that support sound folding. */
-    for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
+    for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi)
     {
-       lp = LANGP_ENTRY(curbuf->b_langp, lpi);
+       lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
        slang = lp->lp_slang;
        if (slang->sl_sugtime != 0 && !slang->sl_sugloaded)
        {
@@ -11215,9 +11214,9 @@ suggest_try_change(su)
     p = su->su_badptr + su->su_badlen;
     (void)spell_casefold(p, (int)STRLEN(p), fword + n, MAXWLEN - n);
 
-    for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
+    for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi)
     {
-       lp = LANGP_ENTRY(curbuf->b_langp, lpi);
+       lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
 
        /* If reloading a spell file fails it's still in the list but
         * everything has been cleared. */
@@ -11445,7 +11444,7 @@ suggest_trie_walk(su, lp, fword, soundfold)
            fword_ends = (fword[sp->ts_fidx] == NUL
                           || (soundfold
                               ? vim_iswhite(fword[sp->ts_fidx])
-                              : !spell_iswordp(fword + sp->ts_fidx, curbuf)));
+                              : !spell_iswordp(fword + sp->ts_fidx, curwin)));
            tword[sp->ts_twordlen] = NUL;
 
            if (sp->ts_prefixdepth <= PFD_NOTSPECIAL
@@ -11663,11 +11662,11 @@ suggest_trie_walk(su, lp, fword, soundfold)
                     * char, e.g., "thes," -> "these". */
                    p = fword + sp->ts_fidx;
                    mb_ptr_back(fword, p);
-                   if (!spell_iswordp(p, curbuf))
+                   if (!spell_iswordp(p, curwin))
                    {
                        p = preword + STRLEN(preword);
                        mb_ptr_back(preword, p);
-                       if (spell_iswordp(p, curbuf))
+                       if (spell_iswordp(p, curwin))
                            newscore += SCORE_NONWORD;
                    }
 
@@ -12270,7 +12269,7 @@ suggest_trie_walk(su, lp, fword, soundfold)
 
            /* Don't swap if the first character is not a word character.
             * SWAP3 etc. also don't make sense then. */
-           if (!soundfold && !spell_iswordp(p, curbuf))
+           if (!soundfold && !spell_iswordp(p, curwin))
            {
                sp->ts_state = STATE_REP_INI;
                break;
@@ -12283,7 +12282,7 @@ suggest_trie_walk(su, lp, fword, soundfold)
                c = mb_ptr2char(p);
                if (p[n] == NUL)
                    c2 = NUL;
-               else if (!soundfold && !spell_iswordp(p + n, curbuf))
+               else if (!soundfold && !spell_iswordp(p + n, curwin))
                    c2 = c; /* don't swap non-word char */
                else
                    c2 = mb_ptr2char(p + n);
@@ -12293,7 +12292,7 @@ suggest_trie_walk(su, lp, fword, soundfold)
            {
                if (p[1] == NUL)
                    c2 = NUL;
-               else if (!soundfold && !spell_iswordp(p + 1, curbuf))
+               else if (!soundfold && !spell_iswordp(p + 1, curwin))
                    c2 = c; /* don't swap non-word char */
                else
                    c2 = p[1];
@@ -12375,7 +12374,7 @@ suggest_trie_walk(su, lp, fword, soundfold)
                c = mb_ptr2char(p);
                fl = mb_cptr2len(p + n);
                c2 = mb_ptr2char(p + n);
-               if (!soundfold && !spell_iswordp(p + n + fl, curbuf))
+               if (!soundfold && !spell_iswordp(p + n + fl, curwin))
                    c3 = c;     /* don't swap non-word char */
                else
                    c3 = mb_ptr2char(p + n + fl);
@@ -12385,7 +12384,7 @@ suggest_trie_walk(su, lp, fword, soundfold)
            {
                c = *p;
                c2 = p[1];
-               if (!soundfold && !spell_iswordp(p + 2, curbuf))
+               if (!soundfold && !spell_iswordp(p + 2, curwin))
                    c3 = c;     /* don't swap non-word char */
                else
                    c3 = p[2];
@@ -12458,7 +12457,7 @@ suggest_trie_walk(su, lp, fword, soundfold)
                ++p;
            }
 
-           if (!soundfold && !spell_iswordp(p, curbuf))
+           if (!soundfold && !spell_iswordp(p, curwin))
            {
                /* Middle char is not a word char, skip the rotate.  First and
                 * third char were already checked at swap and swap3. */
@@ -12934,9 +12933,9 @@ score_comp_sal(su)
        return;
 
     /* Use the sound-folding of the first language that supports it. */
-    for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
+    for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi)
     {
-       lp = LANGP_ENTRY(curbuf->b_langp, lpi);
+       lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
        if (lp->lp_slang->sl_sal.ga_len > 0)
        {
            /* soundfold the bad word */
@@ -12990,9 +12989,9 @@ score_combine(su)
     slang_T    *slang = NULL;
 
     /* Add the alternate score to su_ga. */
-    for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
+    for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi)
     {
-       lp = LANGP_ENTRY(curbuf->b_langp, lpi);
+       lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
        if (lp->lp_slang->sl_sal.ga_len > 0)
        {
            /* soundfold the bad word */
@@ -13165,9 +13164,9 @@ suggest_try_soundalike_prep()
 
     /* Do this for all languages that support sound folding and for which a
      * .sug file has been loaded. */
-    for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
+    for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi)
     {
-       lp = LANGP_ENTRY(curbuf->b_langp, lpi);
+       lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
        slang = lp->lp_slang;
        if (slang->sl_sal.ga_len > 0 && slang->sl_sbyts != NULL)
            /* prepare the hashtable used by add_sound_suggest() */
@@ -13190,9 +13189,9 @@ suggest_try_soundalike(su)
 
     /* Do this for all languages that support sound folding and for which a
      * .sug file has been loaded. */
-    for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
+    for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi)
     {
-       lp = LANGP_ENTRY(curbuf->b_langp, lpi);
+       lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
        slang = lp->lp_slang;
        if (slang->sl_sal.ga_len > 0 && slang->sl_sbyts != NULL)
        {
@@ -13221,9 +13220,9 @@ suggest_try_soundalike_finish()
 
     /* Do this for all languages that support sound folding and for which a
      * .sug file has been loaded. */
-    for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
+    for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi)
     {
-       lp = LANGP_ENTRY(curbuf->b_langp, lpi);
+       lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
        slang = lp->lp_slang;
        if (slang->sl_sal.ga_len > 0 && slang->sl_sbyts != NULL)
        {
@@ -14000,11 +13999,11 @@ eval_soundfold(word)
     char_u     sound[MAXWLEN];
     int                lpi;
 
-    if (curwin->w_p_spell && *curbuf->b_p_spl != NUL)
+    if (curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL)
        /* Use the sound-folding of the first language that supports it. */
-       for (lpi = 0; lpi < curbuf->b_langp.ga_len; ++lpi)
+       for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi)
        {
-           lp = LANGP_ENTRY(curbuf->b_langp, lpi);
+           lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
            if (lp->lp_slang->sl_sal.ga_len > 0)
            {
                /* soundfold the word */
@@ -14255,12 +14254,12 @@ spell_soundfold_sal(slang, inword, res)
                if (*s == NUL
                        || (*s == '^'
                            && (i == 0 || !(word[i - 1] == ' '
-                                     || spell_iswordp(word + i - 1, curbuf)))
+                                     || spell_iswordp(word + i - 1, curwin)))
                            && (*(s + 1) != '$'
-                               || (!spell_iswordp(word + i + k0, curbuf))))
+                               || (!spell_iswordp(word + i + k0, curwin))))
                        || (*s == '$' && i > 0
-                           && spell_iswordp(word + i - 1, curbuf)
-                           && (!spell_iswordp(word + i + k0, curbuf))))
+                           && spell_iswordp(word + i - 1, curwin)
+                           && (!spell_iswordp(word + i + k0, curwin))))
                {
                    /* search for followup rules, if:    */
                    /* followup and k > 1  and  NO '-' in searchstring */
@@ -14323,7 +14322,7 @@ spell_soundfold_sal(slang, inword, res)
                                    /* *s == '^' cuts */
                                    || (*s == '$'
                                            && !spell_iswordp(word + i + k0,
-                                                                    curbuf)))
+                                                                    curwin)))
                            {
                                if (k0 == k)
                                    /* this is just a piece of the string */
@@ -14547,12 +14546,12 @@ spell_soundfold_wsal(slang, inword, res)
                if (*s == NUL
                        || (*s == '^'
                            && (i == 0 || !(word[i - 1] == ' '
-                                   || spell_iswordp_w(word + i - 1, curbuf)))
+                                   || spell_iswordp_w(word + i - 1, curwin)))
                            && (*(s + 1) != '$'
-                               || (!spell_iswordp_w(word + i + k0, curbuf))))
+                               || (!spell_iswordp_w(word + i + k0, curwin))))
                        || (*s == '$' && i > 0
-                           && spell_iswordp_w(word + i - 1, curbuf)
-                           && (!spell_iswordp_w(word + i + k0, curbuf))))
+                           && spell_iswordp_w(word + i - 1, curwin)
+                           && (!spell_iswordp_w(word + i + k0, curwin))))
                {
                    /* search for followup rules, if:    */
                    /* followup and k > 1  and  NO '-' in searchstring */
@@ -14619,7 +14618,7 @@ spell_soundfold_wsal(slang, inword, res)
                                    /* *s == '^' cuts */
                                    || (*s == '$'
                                         && !spell_iswordp_w(word + i + k0,
-                                                                    curbuf)))
+                                                                    curwin)))
                            {
                                if (k0 == k)
                                    /* this is just a piece of the string */
@@ -15478,9 +15477,9 @@ ex_spellinfo(eap)
        return;
 
     msg_start();
-    for (lpi = 0; lpi < curbuf->b_langp.ga_len && !got_int; ++lpi)
+    for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len && !got_int; ++lpi)
     {
-       lp = LANGP_ENTRY(curbuf->b_langp, lpi);
+       lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
        msg_puts((char_u *)"file: ");
        msg_puts(lp->lp_slang->sl_fname);
        msg_putchar('\n');
@@ -15507,17 +15506,15 @@ ex_spellinfo(eap)
 ex_spelldump(eap)
     exarg_T *eap;
 {
-    buf_T      *buf = curbuf;
-
     if (no_spell_checking(curwin))
        return;
 
     /* Create a new empty buffer by splitting the window. */
     do_cmdline_cmd((char_u *)"new");
-    if (!bufempty() || !buf_valid(buf))
+    if (!bufempty() || !buf_valid(curbuf))
        return;
 
-    spell_dump_compl(buf, NULL, 0, NULL, eap->forceit ? DUMPFLAG_COUNT : 0);
+    spell_dump_compl(NULL, 0, NULL, eap->forceit ? DUMPFLAG_COUNT : 0);
 
     /* Delete the empty line that we started with. */
     if (curbuf->b_ml.ml_line_count > 1)
@@ -15533,8 +15530,7 @@ ex_spelldump(eap)
  * 2. When "pat" is not NULL: add matching words to insert mode completion.
  */
     void
-spell_dump_compl(buf, pat, ic, dir, dumpflags_arg)
-    buf_T      *buf;       /* buffer with spell checking */
+spell_dump_compl(pat, ic, dir, dumpflags_arg)
     char_u     *pat;       /* leading part of the word */
     int                ic;         /* ignore case */
     int                *dir;       /* direction for adding matches */
@@ -15584,9 +15580,9 @@ spell_dump_compl(buf, pat, ic, dir, dumpflags_arg)
 
     /* Find out if we can support regions: All languages must support the same
      * regions or none at all. */
-    for (lpi = 0; lpi < buf->b_langp.ga_len; ++lpi)
+    for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi)
     {
-       lp = LANGP_ENTRY(buf->b_langp, lpi);
+       lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
        p = lp->lp_slang->sl_regions;
        if (p[0] != 0)
        {
@@ -15614,9 +15610,9 @@ spell_dump_compl(buf, pat, ic, dir, dumpflags_arg)
     /*
      * Loop over all files loaded for the entries in 'spelllang'.
      */
-    for (lpi = 0; lpi < buf->b_langp.ga_len; ++lpi)
+    for (lpi = 0; lpi < curwin->w_s->b_langp.ga_len; ++lpi)
     {
-       lp = LANGP_ENTRY(buf->b_langp, lpi);
+       lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
        slang = lp->lp_slang;
        if (slang->sl_fbyts == NULL)        /* reloading failed */
            continue;
@@ -15941,13 +15937,13 @@ dump_prefixes(slang, word, pat, dir, dumpflags, flags, startlnum)
  * Uses the spell-checking word characters.
  */
     char_u *
-spell_to_word_end(start, buf)
+spell_to_word_end(start, win)
     char_u  *start;
-    buf_T   *buf;
+    win_T   *win;
 {
     char_u  *p = start;
 
-    while (*p != NUL && spell_iswordp(p, buf))
+    while (*p != NUL && spell_iswordp(p, win))
        mb_ptr_adv(p);
     return p;
 }
@@ -15985,7 +15981,7 @@ spell_word_start(startcol)
     {
        col = (int)(p - line);
        mb_ptr_back(line, p);
-       if (!spell_iswordp(p, curbuf))
+       if (!spell_iswordp(p, curwin))
            break;
        col = 0;
     }
index daf254f31fe06ed89b4e05762d73b898b3ed44f0..4f72f998b3aefe66de6d7a7e4f52f9b88737c6bd 100644 (file)
@@ -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
  *
@@ -1426,12 +1507,6 @@ struct file_buffer
 #ifdef FEAT_SYN_HL
     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' */
@@ -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 */
index 9613482905e44143664ac5b19cc5449d28da4833..c19c5d964d9e0358aaf47e3e662d07910ce9d0fb 100644 (file)
@@ -140,7 +140,10 @@ typedef struct syn_pattern
 {
     char        sp_type;               /* see SPTYPE_ defines below */
     char        sp_syncing;            /* this item used for syncing */
-    short       sp_flags;              /* see HL_ defines below */
+    int                 sp_flags;              /* see HL_ defines below */
+#ifdef FEAT_CONCEAL
+    int                 sp_char;               /* conceal substitute character */
+#endif
     struct sp_syn sp_syn;              /* struct passed to in_id_list() */
     short       sp_syn_match_id;       /* highlight group ID of pattern */
     char_u     *sp_pattern;            /* regexp to match, pattern */
@@ -166,25 +169,6 @@ typedef struct syn_pattern
 #define SPTYPE_END     3       /* match a regexp, end of item */
 #define SPTYPE_SKIP    4       /* match a regexp, skip within item */
 
-#define HL_CONTAINED   0x01    /* not used on toplevel */
-#define HL_TRANSP      0x02    /* has no highlighting  */
-#define HL_ONELINE     0x04    /* match within one line only */
-#define HL_HAS_EOL     0x08    /* end pattern that matches with $ */
-#define HL_SYNC_HERE   0x10    /* sync point after this item (syncing only) */
-#define HL_SYNC_THERE  0x20    /* sync point at current line (syncing only) */
-#define HL_MATCH       0x40    /* use match ID instead of item ID */
-#define HL_SKIPNL      0x80    /* nextgroup can skip newlines */
-#define HL_SKIPWHITE   0x100   /* nextgroup can skip white space */
-#define HL_SKIPEMPTY   0x200   /* nextgroup can skip empty lines */
-#define HL_KEEPEND     0x400   /* end match always kept */
-#define HL_EXCLUDENL   0x800   /* exclude NL from match */
-#define HL_DISPLAY     0x1000  /* only used for displaying, not syncing */
-#define HL_FOLD                0x2000  /* define fold */
-#define HL_EXTEND      0x4000  /* ignore a keepend */
-/* These don't fit in a short, thus can't be used for syntax items, only for
- * si_flags and bs_flags. */
-#define HL_MATCHCONT   0x8000  /* match continued from previous line */
-#define HL_TRANS_CONT  0x10000L /* transparent item without contains arg */
 
 #define SYN_ITEMS(buf) ((synpat_T *)((buf)->b_syn_patterns.ga_data))
 
@@ -208,6 +192,10 @@ static int current_attr = 0;           /* attr of current syntax word */
 static int current_id = 0;         /* ID of current char for syn_get_id() */
 static int current_trans_id = 0;    /* idem, transparency removed */
 #endif
+#ifdef FEAT_CONCEAL
+static int current_flags = 0;
+static int current_sub_char = 0;
+#endif
 
 typedef struct syn_cluster_S
 {
@@ -294,6 +282,9 @@ typedef struct state_item
     int                si_attr;                /* attributes in this state */
     long       si_flags;               /* HL_HAS_EOL flag in this state, and
                                         * HL_SKIP* for si_next_list */
+#ifdef FEAT_CONCEAL
+    int                si_char;                /* substitution character for conceal */
+#endif
     short      *si_cont_list;          /* list of contained groups */
     short      *si_next_list;          /* nextgroup IDs after this item ends */
     reg_extmatch_T *si_extmatch;       /* \z(...\) matches from start
@@ -351,6 +342,7 @@ static reg_extmatch_T *next_match_extmatch = NULL;
  */
 static win_T   *syn_win;               /* current window for highlighting */
 static buf_T   *syn_buf;               /* current buffer for highlighting */
+static synblock_T *syn_block;          /* current buffer for highlighting */
 static linenr_T current_lnum = 0;      /* lnum of current state */
 static colnr_T current_col = 0;        /* column of current state */
 static int     current_state_stored = 0; /* TRUE if stored current state
@@ -370,7 +362,7 @@ static void syn_start_line __ARGS((void));
 static void syn_update_ends __ARGS((int startofline));
 static void syn_stack_alloc __ARGS((void));
 static int syn_stack_cleanup __ARGS((void));
-static void syn_stack_free_entry __ARGS((buf_T *buf, synstate_T *p));
+static void syn_stack_free_entry __ARGS((synblock_T *block, synstate_T *p));
 static synstate_T *syn_stack_find_entry __ARGS((linenr_T lnum));
 static synstate_T *store_current_state __ARGS((void));
 static void load_current_state __ARGS((synstate_T *from));
@@ -390,6 +382,7 @@ static int in_id_list __ARGS((stateitem_T *item, short *cont_list, struct sp_syn
 static int push_current_state __ARGS((int idx));
 static void pop_current_state __ARGS((void));
 
+static void syn_stack_apply_changes_block __ARGS((synblock_T *block, buf_T *buf));
 static void find_endpos __ARGS((int idx, lpos_T *startpos, lpos_T *m_endpos, lpos_T *hl_endpos, long *flagsp, lpos_T *end_endpos, int *end_idx, reg_extmatch_T *start_ext));
 static void clear_syn_state __ARGS((synstate_T *p));
 static void clear_current_state __ARGS((void));
@@ -400,14 +393,15 @@ static void syn_add_end_off __ARGS((lpos_T *result, regmmatch_T *regmatch, synpa
 static void syn_add_start_off __ARGS((lpos_T *result, regmmatch_T *regmatch, synpat_T *spp, int idx, int extra));
 static char_u *syn_getcurline __ARGS((void));
 static int syn_regexec __ARGS((regmmatch_T *rmp, linenr_T lnum, colnr_T col));
-static int check_keyword_id __ARGS((char_u *line, int startcol, int *endcol, long *flags, short **next_list, stateitem_T *cur_si));
+static int check_keyword_id __ARGS((char_u *line, int startcol, int *endcol, long *flags, short **next_list, stateitem_T *cur_si, int *ccharp));
 static void syn_cmd_case __ARGS((exarg_T *eap, int syncing));
 static void syn_cmd_spell __ARGS((exarg_T *eap, int syncing));
 static void syntax_sync_clear __ARGS((void));
-static void syn_remove_pattern __ARGS((buf_T *buf, int idx));
-static void syn_clear_pattern __ARGS((buf_T *buf, int i));
-static void syn_clear_cluster __ARGS((buf_T *buf, int i));
+static void syn_remove_pattern __ARGS((synblock_T *block, int idx));
+static void syn_clear_pattern __ARGS((synblock_T *block, int i));
+static void syn_clear_cluster __ARGS((synblock_T *block, int i));
 static void syn_cmd_clear __ARGS((exarg_T *eap, int syncing));
+static void syn_cmd_conceal __ARGS((exarg_T *eap, int syncing));
 static void syn_clear_one __ARGS((int id, int syncing));
 static void syn_cmd_on __ARGS((exarg_T *eap, int syncing));
 static void syn_cmd_enable __ARGS((exarg_T *eap, int syncing));
@@ -418,6 +412,7 @@ static void syn_cmd_onoff __ARGS((exarg_T *eap, char *name));
 static void syn_cmd_list __ARGS((exarg_T *eap, int syncing));
 static void syn_lines_msg __ARGS((void));
 static void syn_match_msg __ARGS((void));
+static void syn_stack_free_block __ARGS((synblock_T *block));
 static void syn_list_one __ARGS((int id, int syncing, int link_only));
 static void syn_list_cluster __ARGS((int id));
 static void put_id_list __ARGS((char_u *name, short *list, int attr));
@@ -425,9 +420,9 @@ static void put_pattern __ARGS((char *s, int c, synpat_T *spp, int attr));
 static int syn_list_keywords __ARGS((int id, hashtab_T *ht, int did_header, int attr));
 static void syn_clear_keyword __ARGS((int id, hashtab_T *ht));
 static void clear_keywtab __ARGS((hashtab_T *ht));
-static void add_keyword __ARGS((char_u *name, int id, int flags, short *cont_in_list, short *next_list));
+static void add_keyword __ARGS((char_u *name, int id, int flags, short *cont_in_list, short *next_list, int conceal_char));
 static char_u *get_group_name __ARGS((char_u *arg, char_u **name_end));
-static char_u *get_syn_options __ARGS((char_u *arg, syn_opt_arg_T *opt));
+static char_u *get_syn_options __ARGS((char_u *arg, syn_opt_arg_T *opt, int *conceal_char));
 static void syn_cmd_include __ARGS((exarg_T *eap, int syncing));
 static void syn_cmd_keyword __ARGS((exarg_T *eap, int syncing));
 static void syn_cmd_match __ARGS((exarg_T *eap, int syncing));
@@ -475,10 +470,11 @@ syntax_start(wp, lnum)
      * Also do this when a change was made, the current state may be invalid
      * then.
      */
-    if (syn_buf != wp->w_buffer || changedtick != syn_buf->b_changedtick)
+    if (syn_block != wp->w_s || changedtick != syn_buf->b_changedtick)
     {
        invalidate_current_state();
        syn_buf = wp->w_buffer;
+       syn_block = wp->w_s;
     }
     changedtick = syn_buf->b_changedtick;
     syn_win = wp;
@@ -487,9 +483,9 @@ syntax_start(wp, lnum)
      * Allocate syntax stack when needed.
      */
     syn_stack_alloc();
-    if (syn_buf->b_sst_array == NULL)
+    if (syn_block->b_sst_array == NULL)
        return;         /* out of memory */
-    syn_buf->b_sst_lasttick = display_tick;
+    syn_block->b_sst_lasttick = display_tick;
 
     /*
      * If the state of the end of the previous line is useful, store it.
@@ -520,17 +516,17 @@ syntax_start(wp, lnum)
      * Try to synchronize from a saved state in b_sst_array[].
      * Only do this if lnum is not before and not to far beyond a saved state.
      */
-    if (INVALID_STATE(&current_state) && syn_buf->b_sst_array != NULL)
+    if (INVALID_STATE(&current_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(&current_state))
     {
        syn_sync(wp, lnum, last_valid);
-       first_stored = current_lnum + syn_buf->b_syn_sync_minlines;
+       first_stored = current_lnum + syn_block->b_syn_sync_minlines;
     }
     else
        first_stored = current_lnum;
@@ -554,10 +550,10 @@ syntax_start(wp, lnum)
      * Advance from the sync point or saved state until the current line.
      * Save some entries for syncing with later on.
      */
-    if (syn_buf->b_sst_len <= Rows)
+    if (syn_block->b_sst_len <= Rows)
        dist = 999999;
     else
-       dist = syn_buf->b_ml.ml_line_count / (syn_buf->b_sst_len - Rows) + 1;
+       dist = syn_buf->b_ml.ml_line_count / (syn_block->b_sst_len - Rows) + 1;
     while (current_lnum < lnum)
     {
        syn_start_line();
@@ -574,7 +570,7 @@ syntax_start(wp, lnum)
            if (prev == NULL)
                prev = syn_stack_find_entry(current_lnum - 1);
            if (prev == NULL)
-               sp = syn_buf->b_sst_first;
+               sp = syn_block->b_sst_first;
            else
                sp = prev;
            while (sp != NULL && sp->sst_lnum < current_lnum)
@@ -706,19 +702,19 @@ syn_sync(wp, start_lnum, last_valid)
      * where N is minlines * 1.5, or minlines * 2 if minlines is small.
      * Watch out for overflow when minlines is MAXLNUM.
      */
-    if (syn_buf->b_syn_sync_minlines > start_lnum)
+    if (syn_block->b_syn_sync_minlines > start_lnum)
        start_lnum = 1;
     else
     {
-       if (syn_buf->b_syn_sync_minlines == 1)
+       if (syn_block->b_syn_sync_minlines == 1)
            lnum = 1;
-       else if (syn_buf->b_syn_sync_minlines < 10)
-           lnum = syn_buf->b_syn_sync_minlines * 2;
+       else if (syn_block->b_syn_sync_minlines < 10)
+           lnum = syn_block->b_syn_sync_minlines * 2;
        else
-           lnum = syn_buf->b_syn_sync_minlines * 3 / 2;
-       if (syn_buf->b_syn_sync_maxlines != 0
-                                      && lnum > syn_buf->b_syn_sync_maxlines)
-           lnum = syn_buf->b_syn_sync_maxlines;
+           lnum = syn_block->b_syn_sync_minlines * 3 / 2;
+       if (syn_block->b_syn_sync_maxlines != 0
+                                    && lnum > syn_block->b_syn_sync_maxlines)
+           lnum = syn_block->b_syn_sync_maxlines;
        if (lnum >= start_lnum)
            start_lnum = 1;
        else
@@ -729,7 +725,7 @@ syn_sync(wp, start_lnum, last_valid)
     /*
      * 1. Search backwards for the end of a C-style comment.
      */
-    if (syn_buf->b_syn_sync_flags & SF_CCOMMENT)
+    if (syn_block->b_syn_sync_flags & SF_CCOMMENT)
     {
        /* Need to make syn_buf the current buffer for a moment, to be able to
         * use find_start_comment(). */
@@ -759,11 +755,12 @@ syn_sync(wp, start_lnum, last_valid)
         * defines the comment.
         * Restrict the search for the end of a comment to b_syn_sync_maxlines.
         */
-       if (find_start_comment((int)syn_buf->b_syn_sync_maxlines) != NULL)
+       if (find_start_comment((int)syn_block->b_syn_sync_maxlines) != NULL)
        {
-           for (idx = syn_buf->b_syn_patterns.ga_len; --idx >= 0; )
-               if (SYN_ITEMS(syn_buf)[idx].sp_syn.id == syn_buf->b_syn_sync_id
-                       && SYN_ITEMS(syn_buf)[idx].sp_type == SPTYPE_START)
+           for (idx = syn_block->b_syn_patterns.ga_len; --idx >= 0; )
+               if (SYN_ITEMS(syn_block)[idx].sp_syn.id
+                                                  == syn_block->b_syn_sync_id
+                       && SYN_ITEMS(syn_block)[idx].sp_type == SPTYPE_START)
                {
                    validate_current_state();
                    if (push_current_state(idx) == OK)
@@ -781,11 +778,11 @@ syn_sync(wp, start_lnum, last_valid)
     /*
      * 2. Search backwards for given sync patterns.
      */
-    else if (syn_buf->b_syn_sync_flags & SF_MATCH)
+    else if (syn_block->b_syn_sync_flags & SF_MATCH)
     {
-       if (syn_buf->b_syn_sync_maxlines != 0
-                                && start_lnum > syn_buf->b_syn_sync_maxlines)
-           break_lnum = start_lnum - syn_buf->b_syn_sync_maxlines;
+       if (syn_block->b_syn_sync_maxlines != 0
+                              && start_lnum > syn_block->b_syn_sync_maxlines)
+           break_lnum = start_lnum - syn_block->b_syn_sync_maxlines;
        else
            break_lnum = 0;
 
@@ -849,7 +846,7 @@ syn_sync(wp, start_lnum, last_valid)
                        }
                        else
                        {
-                           spp = &(SYN_ITEMS(syn_buf)[cur_si->si_idx]);
+                           spp = &(SYN_ITEMS(syn_block)[cur_si->si_idx]);
                            found_flags = spp->sp_flags;
                            found_match_idx = spp->sp_sync_idx;
                        }
@@ -952,10 +949,10 @@ syn_match_linecont(lnum)
 {
     regmmatch_T regmatch;
 
-    if (syn_buf->b_syn_linecont_prog != NULL)
+    if (syn_block->b_syn_linecont_prog != NULL)
     {
-       regmatch.rmm_ic = syn_buf->b_syn_linecont_ic;
-       regmatch.regprog = syn_buf->b_syn_linecont_prog;
+       regmatch.rmm_ic = syn_block->b_syn_linecont_ic;
+       regmatch.regprog = syn_block->b_syn_linecont_prog;
        return syn_regexec(&regmatch, lnum, (colnr_T)0);
     }
     return FALSE;
@@ -1002,7 +999,7 @@ syn_update_ends(startofline)
        {
            cur_si = &CUR_STATE(i);
            if (cur_si->si_idx >= 0
-                   && (SYN_ITEMS(syn_buf)[cur_si->si_idx]).sp_type
+                   && (SYN_ITEMS(syn_block)[cur_si->si_idx]).sp_type
                                                               == SPTYPE_MATCH
                    && cur_si->si_m_endpos.lnum < current_lnum)
            {
@@ -1088,30 +1085,39 @@ syn_update_ends(startofline)
  * number of entries SST_MAX_ENTRIES, and the distance is computed.
  */
 
+    static void
+syn_stack_free_block(block)
+    synblock_T *block;
+{
+    synstate_T *p;
+
+    if (block->b_sst_array != NULL)
+    {
+       for (p = block->b_sst_first; p != NULL; p = p->sst_next)
+           clear_syn_state(p);
+       vim_free(block->b_sst_array);
+       block->b_sst_array = NULL;
+       block->b_sst_len = 0;
+    }
+}
 /*
  * Free b_sst_array[] for buffer "buf".
  * Used when syntax items changed to force resyncing everywhere.
  */
     void
-syn_stack_free_all(buf)
-    buf_T      *buf;
+syn_stack_free_all(block)
+    synblock_T *block;
 {
-    synstate_T *p;
     win_T      *wp;
 
-    if (buf->b_sst_array != NULL)
-    {
-       for (p = buf->b_sst_first; p != NULL; p = p->sst_next)
-           clear_syn_state(p);
-       vim_free(buf->b_sst_array);
-       buf->b_sst_array = NULL;
-       buf->b_sst_len = 0;
-    }
+    syn_stack_free_block(block);
+
+
 #ifdef FEAT_FOLDING
     /* When using "syntax" fold method, must update all folds. */
     FOR_ALL_WINDOWS(wp)
     {
-       if (wp->w_buffer == buf && foldmethodIsSyntax(wp))
+       if (wp->w_s == block && foldmethodIsSyntax(wp))
            foldUpdateAll(wp);
     }
 #endif
@@ -1135,7 +1141,7 @@ syn_stack_alloc()
        len = SST_MIN_ENTRIES;
     else if (len > SST_MAX_ENTRIES)
        len = SST_MAX_ENTRIES;
-    if (syn_buf->b_sst_len > len * 2 || syn_buf->b_sst_len < len)
+    if (syn_block->b_sst_len > len * 2 || syn_block->b_sst_len < len)
     {
        /* Allocate 50% too much, to avoid reallocating too often. */
        len = syn_buf->b_ml.ml_line_count;
@@ -1145,15 +1151,15 @@ syn_stack_alloc()
        else if (len > SST_MAX_ENTRIES)
            len = SST_MAX_ENTRIES;
 
-       if (syn_buf->b_sst_array != NULL)
+       if (syn_block->b_sst_array != NULL)
        {
            /* When shrinking the array, cleanup the existing stack.
             * Make sure that all valid entries fit in the new array. */
-           while (syn_buf->b_sst_len - syn_buf->b_sst_freecount + 2 > len
+           while (syn_block->b_sst_len - syn_block->b_sst_freecount + 2 > len
                    && syn_stack_cleanup())
                ;
-           if (len < syn_buf->b_sst_len - syn_buf->b_sst_freecount + 2)
-               len = syn_buf->b_sst_len - syn_buf->b_sst_freecount + 2;
+           if (len < syn_block->b_sst_len - syn_block->b_sst_freecount + 2)
+               len = syn_block->b_sst_len - syn_block->b_sst_freecount + 2;
        }
 
        sstp = (synstate_T *)alloc_clear((unsigned)(len * sizeof(synstate_T)));
@@ -1161,10 +1167,10 @@ syn_stack_alloc()
            return;
 
        to = sstp - 1;
-       if (syn_buf->b_sst_array != NULL)
+       if (syn_block->b_sst_array != NULL)
        {
            /* Move the states from the old array to the new one. */
-           for (from = syn_buf->b_sst_first; from != NULL;
+           for (from = syn_block->b_sst_first; from != NULL;
                                                        from = from->sst_next)
            {
                ++to;
@@ -1175,24 +1181,24 @@ syn_stack_alloc()
        if (to != sstp - 1)
        {
            to->sst_next = NULL;
-           syn_buf->b_sst_first = sstp;
-           syn_buf->b_sst_freecount = len - (int)(to - sstp) - 1;
+           syn_block->b_sst_first = sstp;
+           syn_block->b_sst_freecount = len - (int)(to - sstp) - 1;
        }
        else
        {
-           syn_buf->b_sst_first = NULL;
-           syn_buf->b_sst_freecount = len;
+           syn_block->b_sst_first = NULL;
+           syn_block->b_sst_freecount = len;
        }
 
        /* Create the list of free entries. */
-       syn_buf->b_sst_firstfree = to + 1;
+       syn_block->b_sst_firstfree = to + 1;
        while (++to < sstp + len)
            to->sst_next = to + 1;
        (sstp + len - 1)->sst_next = NULL;
 
-       vim_free(syn_buf->b_sst_array);
-       syn_buf->b_sst_array = sstp;
-       syn_buf->b_sst_len = len;
+       vim_free(syn_block->b_sst_array);
+       syn_block->b_sst_array = sstp;
+       syn_block->b_sst_len = len;
     }
 }
 
@@ -1205,17 +1211,33 @@ syn_stack_alloc()
     void
 syn_stack_apply_changes(buf)
     buf_T      *buf;
+{
+    win_T      *wp;
+
+    syn_stack_apply_changes_block(&buf->b_s, buf);
+
+    FOR_ALL_WINDOWS(wp)
+    {
+       if ((wp->w_buffer == buf) && (wp->w_s != &buf->b_s))
+           syn_stack_apply_changes_block(wp->w_s, buf);
+    }
+}
+
+    static void
+syn_stack_apply_changes_block(block, buf)
+    synblock_T *block;
+    buf_T      *buf;
 {
     synstate_T *p, *prev, *np;
     linenr_T   n;
 
-    if (buf->b_sst_array == NULL)      /* nothing to do */
+    if (block->b_sst_array == NULL)    /* nothing to do */
        return;
 
     prev = NULL;
-    for (p = buf->b_sst_first; p != NULL; )
+    for (p = block->b_sst_first; p != NULL; )
     {
-       if (p->sst_lnum + buf->b_syn_sync_linebreaks > buf->b_mod_top)
+       if (p->sst_lnum + block->b_syn_sync_linebreaks > buf->b_mod_top)
        {
            n = p->sst_lnum + buf->b_mod_xlines;
            if (n <= buf->b_mod_bot)
@@ -1223,10 +1245,10 @@ syn_stack_apply_changes(buf)
                /* this state is inside the changed area, remove it */
                np = p->sst_next;
                if (prev == NULL)
-                   buf->b_sst_first = np;
+                   block->b_sst_first = np;
                else
                    prev->sst_next = np;
-               syn_stack_free_entry(buf, p);
+               syn_stack_free_entry(block, p);
                p = np;
                continue;
            }
@@ -1264,28 +1286,28 @@ syn_stack_cleanup()
     int                dist;
     int                retval = FALSE;
 
-    if (syn_buf->b_sst_array == NULL || syn_buf->b_sst_first == NULL)
+    if (syn_block->b_sst_array == NULL || syn_block->b_sst_first == NULL)
        return retval;
 
     /* Compute normal distance between non-displayed entries. */
-    if (syn_buf->b_sst_len <= Rows)
+    if (syn_block->b_sst_len <= Rows)
        dist = 999999;
     else
-       dist = syn_buf->b_ml.ml_line_count / (syn_buf->b_sst_len - Rows) + 1;
+       dist = syn_buf->b_ml.ml_line_count / (syn_block->b_sst_len - Rows) + 1;
 
     /*
      * Go through the list to find the "tick" for the oldest entry that can
      * be removed.  Set "above" when the "tick" for the oldest entry is above
      * "b_sst_lasttick" (the display tick wraps around).
      */
-    tick = syn_buf->b_sst_lasttick;
+    tick = syn_block->b_sst_lasttick;
     above = FALSE;
-    prev = syn_buf->b_sst_first;
+    prev = syn_block->b_sst_first;
     for (p = prev->sst_next; p != NULL; prev = p, p = p->sst_next)
     {
        if (prev->sst_lnum + dist > p->sst_lnum)
        {
-           if (p->sst_tick > syn_buf->b_sst_lasttick)
+           if (p->sst_tick > syn_block->b_sst_lasttick)
            {
                if (!above || p->sst_tick < tick)
                    tick = p->sst_tick;
@@ -1300,14 +1322,14 @@ syn_stack_cleanup()
      * Go through the list to make the entries for the oldest tick at an
      * interval of several lines.
      */
-    prev = syn_buf->b_sst_first;
+    prev = syn_block->b_sst_first;
     for (p = prev->sst_next; p != NULL; prev = p, p = p->sst_next)
     {
        if (p->sst_tick == tick && prev->sst_lnum + dist > p->sst_lnum)
        {
            /* Move this entry from used list to free list */
            prev->sst_next = p->sst_next;
-           syn_stack_free_entry(syn_buf, p);
+           syn_stack_free_entry(syn_block, p);
            p = prev;
            retval = TRUE;
        }
@@ -1320,14 +1342,14 @@ syn_stack_cleanup()
  * Move the entry into the free list.
  */
     static void
-syn_stack_free_entry(buf, p)
-    buf_T      *buf;
+syn_stack_free_entry(block, p)
+    synblock_T *block;
     synstate_T *p;
 {
     clear_syn_state(p);
-    p->sst_next = buf->b_sst_firstfree;
-    buf->b_sst_firstfree = p;
-    ++buf->b_sst_freecount;
+    p->sst_next = block->b_sst_firstfree;
+    block->b_sst_firstfree = p;
+    ++block->b_sst_freecount;
 }
 
 /*
@@ -1341,7 +1363,7 @@ syn_stack_find_entry(lnum)
     synstate_T *p, *prev;
 
     prev = NULL;
-    for (p = syn_buf->b_sst_first; p != NULL; prev = p, p = p->sst_next)
+    for (p = syn_block->b_sst_first; p != NULL; prev = p, p = p->sst_next)
     {
        if (p->sst_lnum == lnum)
            return p;
@@ -1383,19 +1405,19 @@ store_current_state()
        if (sp != NULL)
        {
            /* find "sp" in the list and remove it */
-           if (syn_buf->b_sst_first == sp)
+           if (syn_block->b_sst_first == sp)
                /* it's the first entry */
-               syn_buf->b_sst_first = sp->sst_next;
+               syn_block->b_sst_first = sp->sst_next;
            else
            {
                /* find the entry just before this one to adjust sst_next */
-               for (p = syn_buf->b_sst_first; p != NULL; p = p->sst_next)
+               for (p = syn_block->b_sst_first; p != NULL; p = p->sst_next)
                    if (p->sst_next == sp)
                        break;
                if (p != NULL)  /* just in case */
                    p->sst_next = sp->sst_next;
            }
-           syn_stack_free_entry(syn_buf, sp);
+           syn_stack_free_entry(syn_block, sp);
            sp = NULL;
        }
     }
@@ -1405,27 +1427,27 @@ store_current_state()
         * Add a new entry
         */
        /* If no free items, cleanup the array first. */
-       if (syn_buf->b_sst_freecount == 0)
+       if (syn_block->b_sst_freecount == 0)
        {
            (void)syn_stack_cleanup();
            /* "sp" may have been moved to the freelist now */
            sp = syn_stack_find_entry(current_lnum);
        }
        /* Still no free items?  Must be a strange problem... */
-       if (syn_buf->b_sst_freecount == 0)
+       if (syn_block->b_sst_freecount == 0)
            sp = NULL;
        else
        {
            /* Take the first item from the free list and put it in the used
             * list, after *sp */
-           p = syn_buf->b_sst_firstfree;
-           syn_buf->b_sst_firstfree = p->sst_next;
-           --syn_buf->b_sst_freecount;
+           p = syn_block->b_sst_firstfree;
+           syn_block->b_sst_firstfree = p->sst_next;
+           --syn_block->b_sst_freecount;
            if (sp == NULL)
            {
                /* Insert in front of the list */
-               p->sst_next = syn_buf->b_sst_first;
-               syn_buf->b_sst_first = p;
+               p->sst_next = syn_block->b_sst_first;
+               syn_block->b_sst_first = p;
            }
            else
            {
@@ -1502,7 +1524,7 @@ load_current_state(from)
            CUR_STATE(i).si_m_lnum = 0;
            if (CUR_STATE(i).si_idx >= 0)
                CUR_STATE(i).si_next_list =
-                      (SYN_ITEMS(syn_buf)[CUR_STATE(i).si_idx]).sp_next_list;
+                    (SYN_ITEMS(syn_block)[CUR_STATE(i).si_idx]).sp_next_list;
            else
                CUR_STATE(i).si_next_list = NULL;
            update_si_attr(i);
@@ -1564,7 +1586,7 @@ syn_stack_equal(sp)
                        if (bsx->matches[j] == NULL
                                || six->matches[j] == NULL)
                            break;
-                       if ((SYN_ITEMS(syn_buf)[CUR_STATE(i).si_idx]).sp_ic
+                       if ((SYN_ITEMS(syn_block)[CUR_STATE(i).si_idx]).sp_ic
                                ? MB_STRICMP(bsx->matches[j],
                                                         six->matches[j]) != 0
                                : STRCMP(bsx->matches[j], six->matches[j]) != 0)
@@ -1701,7 +1723,7 @@ syn_finish_line(syncing)
                 */
                cur_si = &CUR_STATE(current_state.ga_len - 1);
                if (cur_si->si_idx >= 0
-                       && (SYN_ITEMS(syn_buf)[cur_si->si_idx].sp_flags
+                       && (SYN_ITEMS(syn_block)[cur_si->si_idx].sp_flags
                                              & (HL_SYNC_HERE|HL_SYNC_THERE)))
                    return TRUE;
 
@@ -1730,8 +1752,9 @@ syn_finish_line(syncing)
  * done.
  */
     int
-get_syntax_attr(col, can_spell, keep_state)
+get_syntax_attr(col, p_flags, can_spell, keep_state)
     colnr_T    col;
+    int                *p_flags UNUSED;
     int                *can_spell;
     int                keep_state;     /* keep state of char at "col" */
 {
@@ -1740,12 +1763,12 @@ get_syntax_attr(col, can_spell, keep_state)
     if (can_spell != NULL)
        /* Default: Only do spelling when there is no @Spell cluster or when
         * ":syn spell toplevel" was used. */
-       *can_spell = syn_buf->b_syn_spell == SYNSPL_DEFAULT
-                   ? (syn_buf->b_spell_cluster_id == 0)
-                   : (syn_buf->b_syn_spell == SYNSPL_TOP);
+       *can_spell = syn_block->b_syn_spell == SYNSPL_DEFAULT
+                   ? (syn_block->b_spell_cluster_id == 0)
+                   : (syn_block->b_syn_spell == SYNSPL_TOP);
 
     /* check for out of memory situation */
-    if (syn_buf->b_sst_array == NULL)
+    if (syn_block->b_sst_array == NULL)
        return 0;
 
     /* After 'synmaxcol' the attribute is always zero. */
@@ -1773,6 +1796,10 @@ get_syntax_attr(col, can_spell, keep_state)
        ++current_col;
     }
 
+#ifdef FEAT_CONCEAL
+    if (p_flags != NULL)
+       *p_flags = current_flags;
+#endif
     return attr;
 }
 
@@ -1799,6 +1826,7 @@ syn_current_attr(syncing, displaying, can_spell, keep_state)
     int                startcol;
     int                endcol;
     long       flags;
+    int                cchar;
     short      *next_list;
     int                found_match;                /* found usable match */
     static int try_next_column = FALSE;    /* must try in next col */
@@ -1854,8 +1882,8 @@ syn_current_attr(syncing, displaying, can_spell, keep_state)
 
     /* Only check for keywords when not syncing and there are some. */
     do_keywords = !syncing
-                   && (syn_buf->b_keywtab.ht_used > 0
-                           || syn_buf->b_keywtab_ic.ht_used > 0);
+                   && (syn_block->b_keywtab.ht_used > 0
+                           || syn_block->b_keywtab_ic.ht_used > 0);
 
     /* Init the list of zero-width matches with a nextlist.  This is used to
      * avoid matching the same item in the same position twice. */
@@ -1884,7 +1912,7 @@ syn_current_attr(syncing, displaying, can_spell, keep_state)
        else
            cur_si = NULL;
 
-       if (syn_buf->b_syn_containedin || cur_si == NULL
+       if (syn_block->b_syn_containedin || cur_si == NULL
                                              || cur_si->si_cont_list != NULL)
        {
            /*
@@ -1905,7 +1933,8 @@ syn_current_attr(syncing, displaying, can_spell, keep_state)
                               , syn_buf)))
              {
                syn_id = check_keyword_id(line, (int)current_col,
-                                        &endcol, &flags, &next_list, cur_si);
+                                        &endcol, &flags, &next_list, cur_si,
+                                        &cchar);
                if (syn_id != 0)
                {
                    if (push_current_state(KEYWORD_IDX) == OK)
@@ -1921,6 +1950,13 @@ syn_current_attr(syncing, displaying, can_spell, keep_state)
                        cur_si->si_ends = TRUE;
                        cur_si->si_end_idx = 0;
                        cur_si->si_flags = flags;
+#ifdef FEAT_CONCEAL
+                       cur_si->si_char = cchar;
+                       if (current_state.ga_len > 1)
+                           cur_si->si_flags |=
+                                 CUR_STATE(current_state.ga_len - 2).si_flags
+                                                                & HL_CONCEAL;
+#endif
                        cur_si->si_id = syn_id;
                        cur_si->si_trans_id = syn_id;
                        if (flags & HL_TRANSP)
@@ -1953,7 +1989,7 @@ syn_current_attr(syncing, displaying, can_spell, keep_state)
            /*
             * 3. Check for patterns (only if no keyword found).
             */
-           if (syn_id == 0 && syn_buf->b_syn_patterns.ga_len)
+           if (syn_id == 0 && syn_block->b_syn_patterns.ga_len)
            {
                /*
                 * If we didn't check for a match yet, or we are past it, check
@@ -1969,9 +2005,9 @@ syn_current_attr(syncing, displaying, can_spell, keep_state)
                     */
                    next_match_idx = 0;         /* no match in this line yet */
                    next_match_col = MAXCOL;
-                   for (idx = syn_buf->b_syn_patterns.ga_len; --idx >= 0; )
+                   for (idx = syn_block->b_syn_patterns.ga_len; --idx >= 0; )
                    {
-                       spp = &(SYN_ITEMS(syn_buf)[idx]);
+                       spp = &(SYN_ITEMS(syn_block)[idx]);
                        if (       spp->sp_syncing == syncing
                                && (displaying || !(spp->sp_flags & HL_DISPLAY))
                                && (spp->sp_type == SPTYPE_MATCH
@@ -2147,7 +2183,7 @@ syn_current_attr(syncing, displaying, can_spell, keep_state)
 
                    /* When a zero-width item matched which has a nextgroup,
                     * don't push the item but set nextgroup. */
-                   lspp = &(SYN_ITEMS(syn_buf)[next_match_idx]);
+                   lspp = &(SYN_ITEMS(syn_block)[next_match_idx]);
                    if (next_match_m_endpos.lnum == current_lnum
                            && next_match_m_endpos.col == current_col
                            && lspp->sp_next_list != NULL)
@@ -2218,6 +2254,9 @@ syn_current_attr(syncing, displaying, can_spell, keep_state)
 #ifdef FEAT_EVAL
     current_id = 0;
     current_trans_id = 0;
+#endif
+#ifdef FEAT_CONCEAL
+    current_flags = 0;
 #endif
     if (cur_si != NULL)
     {
@@ -2240,6 +2279,10 @@ syn_current_attr(syncing, displaying, can_spell, keep_state)
                current_id = sip->si_id;
 #endif
                current_trans_id = sip->si_trans_id;
+#ifdef FEAT_CONCEAL
+               current_flags = sip->si_flags;
+               current_sub_char = sip->si_char;
+#endif
                break;
            }
        }
@@ -2252,16 +2295,17 @@ syn_current_attr(syncing, displaying, can_spell, keep_state)
             * set "can_spell" to TRUE if spell checking is supposed to be
             * done in the current item.
             */
-           if (syn_buf->b_spell_cluster_id == 0)
+           if (syn_block->b_spell_cluster_id == 0)
            {
                /* There is no @Spell cluster: Do spelling for items without
                 * @NoSpell cluster. */
-               if (syn_buf->b_nospell_cluster_id == 0 || current_trans_id == 0)
-                   *can_spell = (syn_buf->b_syn_spell != SYNSPL_NOTOP);
+               if (syn_block->b_nospell_cluster_id == 0
+                                                    || current_trans_id == 0)
+                   *can_spell = (syn_block->b_syn_spell != SYNSPL_NOTOP);
                else
                {
                    sps.inc_tag = 0;
-                   sps.id = syn_buf->b_nospell_cluster_id;
+                   sps.id = syn_block->b_nospell_cluster_id;
                    sps.cont_in_list = NULL;
                    *can_spell = !in_id_list(sip, sip->si_cont_list, &sps, 0);
                }
@@ -2273,17 +2317,17 @@ syn_current_attr(syncing, displaying, can_spell, keep_state)
                 * At the toplevel only spell check when ":syn spell toplevel"
                 * was used. */
                if (current_trans_id == 0)
-                   *can_spell = (syn_buf->b_syn_spell == SYNSPL_TOP);
+                   *can_spell = (syn_block->b_syn_spell == SYNSPL_TOP);
                else
                {
                    sps.inc_tag = 0;
-                   sps.id = syn_buf->b_spell_cluster_id;
+                   sps.id = syn_block->b_spell_cluster_id;
                    sps.cont_in_list = NULL;
                    *can_spell = in_id_list(sip, sip->si_cont_list, &sps, 0);
 
-                   if (syn_buf->b_nospell_cluster_id != 0)
+                   if (syn_block->b_nospell_cluster_id != 0)
                    {
-                       sps.id = syn_buf->b_nospell_cluster_id;
+                       sps.id = syn_block->b_nospell_cluster_id;
                        if (in_id_list(sip, sip->si_cont_list, &sps, 0))
                            *can_spell = FALSE;
                    }
@@ -2315,9 +2359,9 @@ syn_current_attr(syncing, displaying, can_spell, keep_state)
     else if (can_spell != NULL)
        /* Default: Only do spelling when there is no @Spell cluster or when
         * ":syn spell toplevel" was used. */
-       *can_spell = syn_buf->b_syn_spell == SYNSPL_DEFAULT
-                   ? (syn_buf->b_spell_cluster_id == 0)
-                   : (syn_buf->b_syn_spell == SYNSPL_TOP);
+       *can_spell = syn_block->b_syn_spell == SYNSPL_DEFAULT
+                   ? (syn_block->b_spell_cluster_id == 0)
+                   : (syn_block->b_syn_spell == SYNSPL_TOP);
 
     /* nextgroup ends at end of line, unless "skipnl" or "skipempty" present */
     if (current_next_list != NULL
@@ -2370,8 +2414,11 @@ push_next_match(cur_si)
     stateitem_T        *cur_si;
 {
     synpat_T   *spp;
+#ifdef FEAT_CONCEAL
+    int                 save_flags;
+#endif
 
-    spp = &(SYN_ITEMS(syn_buf)[next_match_idx]);
+    spp = &(SYN_ITEMS(syn_block)[next_match_idx]);
 
     /*
      * Push the item in current_state stack;
@@ -2387,6 +2434,12 @@ push_next_match(cur_si)
        cur_si->si_m_startcol = current_col;
        cur_si->si_m_lnum = current_lnum;
        cur_si->si_flags = spp->sp_flags;
+#ifdef FEAT_CONCEAL
+       cur_si->si_char = spp->sp_char;
+       if (current_state.ga_len > 1)
+           cur_si->si_flags |=
+                   CUR_STATE(current_state.ga_len - 2).si_flags & HL_CONCEAL;
+#endif
        cur_si->si_next_list = spp->sp_next_list;
        cur_si->si_extmatch = ref_extmatch(next_match_extmatch);
        if (spp->sp_type == SPTYPE_START && !(spp->sp_flags & HL_ONELINE))
@@ -2409,6 +2462,9 @@ push_next_match(cur_si)
        check_keepend();
        update_si_attr(current_state.ga_len - 1);
 
+#ifdef FEAT_CONCEAL
+       save_flags = cur_si->si_flags & (HL_CONCEAL | HL_CONCEALENDS);
+#endif
        /*
         * If the start pattern has another highlight group, push another item
         * on the stack for the start pattern.
@@ -2426,6 +2482,11 @@ push_next_match(cur_si)
            cur_si->si_ends = TRUE;
            cur_si->si_end_idx = 0;
            cur_si->si_flags = HL_MATCH;
+#ifdef FEAT_CONCEAL
+           cur_si->si_flags |= save_flags;
+           if (cur_si->si_flags & HL_CONCEALENDS)
+               cur_si->si_flags |= HL_CONCEAL;
+#endif
            cur_si->si_next_list = NULL;
            check_keepend();
            update_si_attr(current_state.ga_len - 1);
@@ -2470,6 +2531,10 @@ check_state_ends()
                cur_si->si_m_endpos = cur_si->si_eoe_pos;
                cur_si->si_h_endpos = cur_si->si_eoe_pos;
                cur_si->si_flags |= HL_MATCH;
+#ifdef FEAT_CONCEAL
+               if (cur_si->si_flags & HL_CONCEALENDS)
+                   cur_si->si_flags |= HL_CONCEAL;
+#endif
                update_si_attr(current_state.ga_len - 1);
 
                /* what matches next may be different now, clear it */
@@ -2516,7 +2581,7 @@ check_state_ends()
                 * - "excludenl" is used (HL_HAS_EOL won't be set)
                 */
                if (cur_si->si_idx >= 0
-                       && SYN_ITEMS(syn_buf)[cur_si->si_idx].sp_type
+                       && SYN_ITEMS(syn_block)[cur_si->si_idx].sp_type
                                                               == SPTYPE_START
                        && !(cur_si->si_flags & (HL_MATCH | HL_KEEPEND)))
                {
@@ -2549,7 +2614,7 @@ update_si_attr(idx)
     if (sip->si_idx < 0)
        return;
 
-    spp = &(SYN_ITEMS(syn_buf)[sip->si_idx]);
+    spp = &(SYN_ITEMS(syn_block)[sip->si_idx]);
     if (sip->si_flags & HL_MATCH)
        sip->si_id = spp->sp_syn_match_id;
     else
@@ -2689,7 +2754,7 @@ update_si_end(sip, startcol, force)
     if (endpos.lnum == 0)
     {
        /* No end pattern matched. */
-       if (SYN_ITEMS(syn_buf)[sip->si_idx].sp_flags & HL_ONELINE)
+       if (SYN_ITEMS(syn_block)[sip->si_idx].sp_flags & HL_ONELINE)
        {
            /* a "oneline" never continues in the next line */
            sip->si_ends = TRUE;
@@ -2791,7 +2856,7 @@ find_endpos(idx, startpos, m_endpos, hl_endpos, flagsp, end_endpos,
      * Can happen with a match that continues to the next line, because it
      * contained a region.
      */
-    spp = &(SYN_ITEMS(syn_buf)[idx]);
+    spp = &(SYN_ITEMS(syn_block)[idx]);
     if (spp->sp_type != SPTYPE_START)
     {
        *hl_endpos = *startpos;
@@ -2803,7 +2868,7 @@ find_endpos(idx, startpos, m_endpos, hl_endpos, flagsp, end_endpos,
      */
     for (;;)
     {
-       spp = &(SYN_ITEMS(syn_buf)[idx]);
+       spp = &(SYN_ITEMS(syn_block)[idx]);
        if (spp->sp_type != SPTYPE_START)
            break;
        ++idx;
@@ -2833,11 +2898,11 @@ find_endpos(idx, startpos, m_endpos, hl_endpos, flagsp, end_endpos,
         * Find end pattern that matches first after "matchcol".
         */
        best_idx = -1;
-       for (idx = start_idx; idx < syn_buf->b_syn_patterns.ga_len; ++idx)
+       for (idx = start_idx; idx < syn_block->b_syn_patterns.ga_len; ++idx)
        {
            int lc_col = matchcol;
 
-           spp = &(SYN_ITEMS(syn_buf)[idx]);
+           spp = &(SYN_ITEMS(syn_block)[idx]);
            if (spp->sp_type != SPTYPE_END)     /* past last END pattern */
                break;
            lc_col -= spp->sp_offsets[SPO_LC_OFF];
@@ -2915,7 +2980,7 @@ find_endpos(idx, startpos, m_endpos, hl_endpos, flagsp, end_endpos,
         * Match from start pattern to end pattern.
         * Correct for match and highlight offset of end pattern.
         */
-       spp = &(SYN_ITEMS(syn_buf)[best_idx]);
+       spp = &(SYN_ITEMS(syn_block)[best_idx]);
        syn_add_end_off(m_endpos, &best_regmatch, spp, SPO_ME_OFF, 1);
        /* can't end before the start */
        if (m_endpos->lnum == startpos->lnum && m_endpos->col < startpos->col)
@@ -3146,13 +3211,14 @@ syn_regexec(rmp, lnum, col)
  * Return it's ID if found, 0 otherwise.
  */
     static int
-check_keyword_id(line, startcol, endcolp, flagsp, next_listp, cur_si)
+check_keyword_id(line, startcol, endcolp, flagsp, next_listp, cur_si, ccharp)
     char_u     *line;
     int                startcol;       /* position in line to check for keyword */
     int                *endcolp;       /* return: character after found keyword */
     long       *flagsp;        /* return: flags of matching keyword */
     short      **next_listp;   /* return: next_list of matching keyword */
     stateitem_T        *cur_si;        /* item at the top of the stack */
+    int                *ccharp UNUSED; /* conceal substitution char */
 {
     keyentry_T *kp;
     char_u     *kwp;
@@ -3193,7 +3259,7 @@ check_keyword_id(line, startcol, endcolp, flagsp, next_listp, cur_si)
      */
     for (round = 1; round <= 2; ++round)
     {
-       ht = round == 1 ? &syn_buf->b_keywtab : &syn_buf->b_keywtab_ic;
+       ht = round == 1 ? &syn_block->b_keywtab : &syn_block->b_keywtab_ic;
        if (ht->ht_used == 0)
            continue;
        if (round == 2) /* ignore case */
@@ -3220,6 +3286,9 @@ check_keyword_id(line, startcol, endcolp, flagsp, next_listp, cur_si)
                    *endcolp = startcol + kwlen;
                    *flagsp = kp->flags;
                    *next_listp = kp->next_list;
+#ifdef FEAT_CONCEAL
+                   *ccharp = kp->k_char;
+#endif
                    return kp->k_syn.id;
                }
            }
@@ -3227,6 +3296,32 @@ check_keyword_id(line, startcol, endcolp, flagsp, next_listp, cur_si)
     return 0;
 }
 
+/*
+ * 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.
  */
@@ -3244,9 +3339,9 @@ syn_cmd_case(eap, syncing)
 
     next = skiptowhite(arg);
     if (STRNICMP(arg, "match", 5) == 0 && next - arg == 5)
-       curbuf->b_syn_ic = FALSE;
+       curwin->w_s->b_syn_ic = FALSE;
     else if (STRNICMP(arg, "ignore", 6) == 0 && next - arg == 6)
-       curbuf->b_syn_ic = TRUE;
+       curwin->w_s->b_syn_ic = TRUE;
     else
        EMSG2(_("E390: Illegal argument: %s"), arg);
 }
@@ -3268,11 +3363,11 @@ syn_cmd_spell(eap, syncing)
 
     next = skiptowhite(arg);
     if (STRNICMP(arg, "toplevel", 8) == 0 && next - arg == 8)
-       curbuf->b_syn_spell = SYNSPL_TOP;
+       curwin->w_s->b_syn_spell = SYNSPL_TOP;
     else if (STRNICMP(arg, "notoplevel", 10) == 0 && next - arg == 10)
-       curbuf->b_syn_spell = SYNSPL_NOTOP;
+       curwin->w_s->b_syn_spell = SYNSPL_NOTOP;
     else if (STRNICMP(arg, "default", 7) == 0 && next - arg == 7)
-       curbuf->b_syn_spell = SYNSPL_DEFAULT;
+       curwin->w_s->b_syn_spell = SYNSPL_DEFAULT;
     else
        EMSG2(_("E390: Illegal argument: %s"), arg);
 }
@@ -3281,47 +3376,47 @@ syn_cmd_spell(eap, syncing)
  * Clear all syntax info for one buffer.
  */
     void
-syntax_clear(buf)
-    buf_T      *buf;
+syntax_clear(block)
+    synblock_T *block;
 {
     int i;
 
-    buf->b_syn_error = FALSE;      /* clear previous error */
-    buf->b_syn_ic = FALSE;         /* Use case, by default */
-    buf->b_syn_spell = SYNSPL_DEFAULT; /* default spell checking */
-    buf->b_syn_containedin = FALSE;
+    block->b_syn_error = FALSE;            /* clear previous error */
+    block->b_syn_ic = FALSE;       /* Use case, by default */
+    block->b_syn_spell = SYNSPL_DEFAULT; /* default spell checking */
+    block->b_syn_containedin = FALSE;
 
     /* free the keywords */
-    clear_keywtab(&buf->b_keywtab);
-    clear_keywtab(&buf->b_keywtab_ic);
+    clear_keywtab(&block->b_keywtab);
+    clear_keywtab(&block->b_keywtab_ic);
 
     /* free the syntax patterns */
-    for (i = buf->b_syn_patterns.ga_len; --i >= 0; )
-       syn_clear_pattern(buf, i);
-    ga_clear(&buf->b_syn_patterns);
+    for (i = block->b_syn_patterns.ga_len; --i >= 0; )
+       syn_clear_pattern(block, i);
+    ga_clear(&block->b_syn_patterns);
 
     /* free the syntax clusters */
-    for (i = buf->b_syn_clusters.ga_len; --i >= 0; )
-       syn_clear_cluster(buf, i);
-    ga_clear(&buf->b_syn_clusters);
-    buf->b_spell_cluster_id = 0;
-    buf->b_nospell_cluster_id = 0;
-
-    buf->b_syn_sync_flags = 0;
-    buf->b_syn_sync_minlines = 0;
-    buf->b_syn_sync_maxlines = 0;
-    buf->b_syn_sync_linebreaks = 0;
-
-    vim_free(buf->b_syn_linecont_prog);
-    buf->b_syn_linecont_prog = NULL;
-    vim_free(buf->b_syn_linecont_pat);
-    buf->b_syn_linecont_pat = NULL;
+    for (i = block->b_syn_clusters.ga_len; --i >= 0; )
+       syn_clear_cluster(block, i);
+    ga_clear(&block->b_syn_clusters);
+    block->b_spell_cluster_id = 0;
+    block->b_nospell_cluster_id = 0;
+
+    block->b_syn_sync_flags = 0;
+    block->b_syn_sync_minlines = 0;
+    block->b_syn_sync_maxlines = 0;
+    block->b_syn_sync_linebreaks = 0;
+
+    vim_free(block->b_syn_linecont_prog);
+    block->b_syn_linecont_prog = NULL;
+    vim_free(block->b_syn_linecont_pat);
+    block->b_syn_linecont_pat = NULL;
 #ifdef FEAT_FOLDING
-    buf->b_syn_folditems = 0;
+    block->b_syn_folditems = 0;
 #endif
 
     /* free the stored states */
-    syn_stack_free_all(buf);
+    syn_stack_free_all(block);
     invalidate_current_state();
 }
 
@@ -3334,42 +3429,42 @@ syntax_sync_clear()
     int i;
 
     /* free the syntax patterns */
-    for (i = curbuf->b_syn_patterns.ga_len; --i >= 0; )
-       if (SYN_ITEMS(curbuf)[i].sp_syncing)
-           syn_remove_pattern(curbuf, i);
+    for (i = curwin->w_s->b_syn_patterns.ga_len; --i >= 0; )
+       if (SYN_ITEMS(curwin->w_s)[i].sp_syncing)
+           syn_remove_pattern(curwin->w_s, i);
 
-    curbuf->b_syn_sync_flags = 0;
-    curbuf->b_syn_sync_minlines = 0;
-    curbuf->b_syn_sync_maxlines = 0;
-    curbuf->b_syn_sync_linebreaks = 0;
+    curwin->w_s->b_syn_sync_flags = 0;
+    curwin->w_s->b_syn_sync_minlines = 0;
+    curwin->w_s->b_syn_sync_maxlines = 0;
+    curwin->w_s->b_syn_sync_linebreaks = 0;
 
-    vim_free(curbuf->b_syn_linecont_prog);
-    curbuf->b_syn_linecont_prog = NULL;
-    vim_free(curbuf->b_syn_linecont_pat);
-    curbuf->b_syn_linecont_pat = NULL;
+    vim_free(curwin->w_s->b_syn_linecont_prog);
+    curwin->w_s->b_syn_linecont_prog = NULL;
+    vim_free(curwin->w_s->b_syn_linecont_pat);
+    curwin->w_s->b_syn_linecont_pat = NULL;
 
-    syn_stack_free_all(curbuf);                /* Need to recompute all syntax. */
+    syn_stack_free_all(curwin->w_s);           /* Need to recompute all syntax. */
 }
 
 /*
  * Remove one pattern from the buffer's pattern list.
  */
     static void
-syn_remove_pattern(buf, idx)
-    buf_T      *buf;
+syn_remove_pattern(block, idx)
+    synblock_T *block;
     int                idx;
 {
     synpat_T   *spp;
 
-    spp = &(SYN_ITEMS(buf)[idx]);
+    spp = &(SYN_ITEMS(block)[idx]);
 #ifdef FEAT_FOLDING
     if (spp->sp_flags & HL_FOLD)
-       --buf->b_syn_folditems;
+       --block->b_syn_folditems;
 #endif
-    syn_clear_pattern(buf, idx);
+    syn_clear_pattern(block, idx);
     mch_memmove(spp, spp + 1,
-                  sizeof(synpat_T) * (buf->b_syn_patterns.ga_len - idx - 1));
-    --buf->b_syn_patterns.ga_len;
+                  sizeof(synpat_T) * (block->b_syn_patterns.ga_len - idx - 1));
+    --block->b_syn_patterns.ga_len;
 }
 
 /*
@@ -3377,18 +3472,18 @@ syn_remove_pattern(buf, idx)
  * last to first!
  */
     static void
-syn_clear_pattern(buf, i)
-    buf_T      *buf;
+syn_clear_pattern(block, i)
+    synblock_T *block;
     int                i;
 {
-    vim_free(SYN_ITEMS(buf)[i].sp_pattern);
-    vim_free(SYN_ITEMS(buf)[i].sp_prog);
+    vim_free(SYN_ITEMS(block)[i].sp_pattern);
+    vim_free(SYN_ITEMS(block)[i].sp_prog);
     /* Only free sp_cont_list and sp_next_list of first start pattern */
-    if (i == 0 || SYN_ITEMS(buf)[i - 1].sp_type != SPTYPE_START)
+    if (i == 0 || SYN_ITEMS(block)[i - 1].sp_type != SPTYPE_START)
     {
-       vim_free(SYN_ITEMS(buf)[i].sp_cont_list);
-       vim_free(SYN_ITEMS(buf)[i].sp_next_list);
-       vim_free(SYN_ITEMS(buf)[i].sp_syn.cont_in_list);
+       vim_free(SYN_ITEMS(block)[i].sp_cont_list);
+       vim_free(SYN_ITEMS(block)[i].sp_next_list);
+       vim_free(SYN_ITEMS(block)[i].sp_syn.cont_in_list);
     }
 }
 
@@ -3396,13 +3491,13 @@ syn_clear_pattern(buf, i)
  * Clear and free one syntax cluster.
  */
     static void
-syn_clear_cluster(buf, i)
-    buf_T      *buf;
+syn_clear_cluster(block, i)
+    synblock_T *block;
     int                i;
 {
-    vim_free(SYN_CLSTR(buf)[i].scl_name);
-    vim_free(SYN_CLSTR(buf)[i].scl_name_u);
-    vim_free(SYN_CLSTR(buf)[i].scl_list);
+    vim_free(SYN_CLSTR(block)[i].scl_name);
+    vim_free(SYN_CLSTR(block)[i].scl_name_u);
+    vim_free(SYN_CLSTR(block)[i].scl_list);
 }
 
 /*
@@ -3427,7 +3522,7 @@ syn_cmd_clear(eap, syncing)
      * Only required for Vim 5.x syntax files, 6.0 ones don't contain ":syn
      * clear".
      */
-    if (curbuf->b_syn_topgrp != 0)
+    if (curwin->w_s->b_syn_topgrp != 0)
        return;
 
     if (ends_excmd(*arg))
@@ -3439,8 +3534,12 @@ syn_cmd_clear(eap, syncing)
            syntax_sync_clear();
        else
        {
-           syntax_clear(curbuf);
-           do_unlet((char_u *)"b:current_syntax", TRUE);
+           syntax_clear(curwin->w_s);
+           if (curwin->w_s == &curwin->w_buffer->b_s)
+               do_unlet((char_u *)"b:current_syntax", TRUE);
+           else
+               do_unlet((char_u *)"w:current_syntax", TRUE);
+
        }
     }
     else
@@ -3468,8 +3567,8 @@ syn_cmd_clear(eap, syncing)
                     */
                    short scl_id = id - SYNID_CLUSTER;
 
-                   vim_free(SYN_CLSTR(curbuf)[scl_id].scl_list);
-                   SYN_CLSTR(curbuf)[scl_id].scl_list = NULL;
+                   vim_free(SYN_CLSTR(curwin->w_s)[scl_id].scl_list);
+                   SYN_CLSTR(curwin->w_s)[scl_id].scl_list = NULL;
                }
            }
            else
@@ -3487,7 +3586,7 @@ syn_cmd_clear(eap, syncing)
        }
     }
     redraw_curbuf_later(SOME_VALID);
-    syn_stack_free_all(curbuf);                /* Need to recompute all syntax. */
+    syn_stack_free_all(curwin->w_s);           /* Need to recompute all syntax. */
 }
 
 /*
@@ -3504,17 +3603,17 @@ syn_clear_one(id, syncing)
     /* Clear keywords only when not ":syn sync clear group-name" */
     if (!syncing)
     {
-       (void)syn_clear_keyword(id, &curbuf->b_keywtab);
-       (void)syn_clear_keyword(id, &curbuf->b_keywtab_ic);
+       (void)syn_clear_keyword(id, &curwin->w_s->b_keywtab);
+       (void)syn_clear_keyword(id, &curwin->w_s->b_keywtab_ic);
     }
 
     /* clear the patterns for "id" */
-    for (idx = curbuf->b_syn_patterns.ga_len; --idx >= 0; )
+    for (idx = curwin->w_s->b_syn_patterns.ga_len; --idx >= 0; )
     {
-       spp = &(SYN_ITEMS(curbuf)[idx]);
+       spp = &(SYN_ITEMS(curwin->w_s)[idx]);
        if (spp->sp_syn.id != id || spp->sp_syncing != syncing)
            continue;
-       syn_remove_pattern(curbuf, idx);
+       syn_remove_pattern(curwin->w_s, idx);
     }
 }
 
@@ -3613,7 +3712,7 @@ syn_cmd_list(eap, syncing)
     if (eap->skip)
        return;
 
-    if (!syntax_present(curbuf))
+    if (!syntax_present(curwin))
     {
        MSG(_("No Syntax items defined for this buffer"));
        return;
@@ -3621,30 +3720,30 @@ syn_cmd_list(eap, syncing)
 
     if (syncing)
     {
-       if (curbuf->b_syn_sync_flags & SF_CCOMMENT)
+       if (curwin->w_s->b_syn_sync_flags & SF_CCOMMENT)
        {
            MSG_PUTS(_("syncing on C-style comments"));
            syn_lines_msg();
            syn_match_msg();
            return;
        }
-       else if (!(curbuf->b_syn_sync_flags & SF_MATCH))
+       else if (!(curwin->w_s->b_syn_sync_flags & SF_MATCH))
        {
-           if (curbuf->b_syn_sync_minlines == 0)
+           if (curwin->w_s->b_syn_sync_minlines == 0)
                MSG_PUTS(_("no syncing"));
            else
            {
                MSG_PUTS(_("syncing starts "));
-               msg_outnum(curbuf->b_syn_sync_minlines);
+               msg_outnum(curwin->w_s->b_syn_sync_minlines);
                MSG_PUTS(_(" lines before top line"));
                syn_match_msg();
            }
            return;
        }
        MSG_PUTS_TITLE(_("\n--- Syntax sync items ---"));
-       if (curbuf->b_syn_sync_minlines > 0
-               || curbuf->b_syn_sync_maxlines > 0
-               || curbuf->b_syn_sync_linebreaks > 0)
+       if (curwin->w_s->b_syn_sync_minlines > 0
+               || curwin->w_s->b_syn_sync_maxlines > 0
+               || curwin->w_s->b_syn_sync_linebreaks > 0)
        {
            MSG_PUTS(_("\nsyncing on items"));
            syn_lines_msg();
@@ -3660,7 +3759,7 @@ syn_cmd_list(eap, syncing)
         */
        for (id = 1; id <= highlight_ga.ga_len && !got_int; ++id)
            syn_list_one(id, syncing, FALSE);
-       for (id = 0; id < curbuf->b_syn_clusters.ga_len && !got_int; ++id)
+       for (id = 0; id < curwin->w_s->b_syn_clusters.ga_len && !got_int; ++id)
            syn_list_cluster(id);
     }
     else
@@ -3696,20 +3795,21 @@ syn_cmd_list(eap, syncing)
     static void
 syn_lines_msg()
 {
-    if (curbuf->b_syn_sync_maxlines > 0 || curbuf->b_syn_sync_minlines > 0)
+    if (curwin->w_s->b_syn_sync_maxlines > 0
+                                     || curwin->w_s->b_syn_sync_minlines > 0)
     {
        MSG_PUTS("; ");
-       if (curbuf->b_syn_sync_minlines > 0)
+       if (curwin->w_s->b_syn_sync_minlines > 0)
        {
            MSG_PUTS(_("minimal "));
-           msg_outnum(curbuf->b_syn_sync_minlines);
-           if (curbuf->b_syn_sync_maxlines)
+           msg_outnum(curwin->w_s->b_syn_sync_minlines);
+           if (curwin->w_s->b_syn_sync_maxlines)
                MSG_PUTS(", ");
        }
-       if (curbuf->b_syn_sync_maxlines > 0)
+       if (curwin->w_s->b_syn_sync_maxlines > 0)
        {
            MSG_PUTS(_("maximal "));
-           msg_outnum(curbuf->b_syn_sync_maxlines);
+           msg_outnum(curwin->w_s->b_syn_sync_maxlines);
        }
        MSG_PUTS(_(" lines before top line"));
     }
@@ -3718,10 +3818,10 @@ syn_lines_msg()
     static void
 syn_match_msg()
 {
-    if (curbuf->b_syn_sync_linebreaks > 0)
+    if (curwin->w_s->b_syn_sync_linebreaks > 0)
     {
        MSG_PUTS(_("; match "));
-       msg_outnum(curbuf->b_syn_sync_linebreaks);
+       msg_outnum(curwin->w_s->b_syn_sync_linebreaks);
        MSG_PUTS(_(" line breaks"));
     }
 }
@@ -3759,6 +3859,10 @@ syn_list_one(id, syncing, link_only)
                    {HL_EXCLUDENL, "excludenl"},
                    {HL_TRANSP, "transparent"},
                    {HL_FOLD, "fold"},
+#ifdef FEAT_CONCEAL
+                   {HL_CONCEAL, "conceal"},
+                   {HL_CONCEALENDS, "concealends"},
+#endif
                    {0, NULL}
                };
     static struct name_list namelist2[] =
@@ -3774,15 +3878,15 @@ syn_list_one(id, syncing, link_only)
     /* list the keywords for "id" */
     if (!syncing)
     {
-       did_header = syn_list_keywords(id, &curbuf->b_keywtab, FALSE, attr);
-       did_header = syn_list_keywords(id, &curbuf->b_keywtab_ic,
+       did_header = syn_list_keywords(id, &curwin->w_s->b_keywtab, FALSE, attr);
+       did_header = syn_list_keywords(id, &curwin->w_s->b_keywtab_ic,
                                                            did_header, attr);
     }
 
     /* list the patterns for "id" */
-    for (idx = 0; idx < curbuf->b_syn_patterns.ga_len && !got_int; ++idx)
+    for (idx = 0; idx < curwin->w_s->b_syn_patterns.ga_len && !got_int; ++idx)
     {
-       spp = &(SYN_ITEMS(curbuf)[idx]);
+       spp = &(SYN_ITEMS(curwin->w_s)[idx]);
        if (spp->sp_syn.id != id || spp->sp_syncing != syncing)
            continue;
 
@@ -3796,13 +3900,13 @@ syn_list_one(id, syncing, link_only)
        }
        else if (spp->sp_type == SPTYPE_START)
        {
-           while (SYN_ITEMS(curbuf)[idx].sp_type == SPTYPE_START)
-               put_pattern("start", '=', &SYN_ITEMS(curbuf)[idx++], attr);
-           if (SYN_ITEMS(curbuf)[idx].sp_type == SPTYPE_SKIP)
-               put_pattern("skip", '=', &SYN_ITEMS(curbuf)[idx++], attr);
-           while (idx < curbuf->b_syn_patterns.ga_len
-                             && SYN_ITEMS(curbuf)[idx].sp_type == SPTYPE_END)
-               put_pattern("end", '=', &SYN_ITEMS(curbuf)[idx++], attr);
+           while (SYN_ITEMS(curwin->w_s)[idx].sp_type == SPTYPE_START)
+               put_pattern("start", '=', &SYN_ITEMS(curwin->w_s)[idx++], attr);
+           if (SYN_ITEMS(curwin->w_s)[idx].sp_type == SPTYPE_SKIP)
+               put_pattern("skip", '=', &SYN_ITEMS(curwin->w_s)[idx++], attr);
+           while (idx < curwin->w_s->b_syn_patterns.ga_len
+                             && SYN_ITEMS(curwin->w_s)[idx].sp_type == SPTYPE_END)
+               put_pattern("end", '=', &SYN_ITEMS(curwin->w_s)[idx++], attr);
            --idx;
            msg_putchar(' ');
        }
@@ -3828,7 +3932,7 @@ syn_list_one(id, syncing, link_only)
                msg_puts_attr((char_u *)"groupthere", attr);
            msg_putchar(' ');
            if (spp->sp_sync_idx >= 0)
-               msg_outtrans(HL_TABLE()[SYN_ITEMS(curbuf)
+               msg_outtrans(HL_TABLE()[SYN_ITEMS(curwin->w_s)
                                   [spp->sp_sync_idx].sp_syn.id - 1].sg_name);
            else
                MSG_PUTS("NONE");
@@ -3873,7 +3977,7 @@ syn_list_cluster(id)
 
     /* slight hack:  roughly duplicate the guts of syn_list_header() */
     msg_putchar('\n');
-    msg_outtrans(SYN_CLSTR(curbuf)[id].scl_name);
+    msg_outtrans(SYN_CLSTR(curwin->w_s)[id].scl_name);
 
     if (msg_col >= endcol)     /* output at least one space */
        endcol = msg_col + 1;
@@ -3881,9 +3985,9 @@ syn_list_cluster(id)
        endcol = Columns - 1;
 
     msg_advance(endcol);
-    if (SYN_CLSTR(curbuf)[id].scl_list != NULL)
+    if (SYN_CLSTR(curwin->w_s)[id].scl_list != NULL)
     {
-       put_id_list((char_u *)"cluster", SYN_CLSTR(curbuf)[id].scl_list,
+       put_id_list((char_u *)"cluster", SYN_CLSTR(curwin->w_s)[id].scl_list,
                    hl_attr(HLF_D));
     }
     else
@@ -3925,7 +4029,7 @@ put_id_list(name, list, attr)
            short scl_id = *p - SYNID_CLUSTER;
 
            msg_putchar('@');
-           msg_outtrans(SYN_CLSTR(curbuf)[scl_id].scl_name);
+           msg_outtrans(SYN_CLSTR(curwin->w_s)[scl_id].scl_name);
        }
        else
            msg_outtrans(HL_TABLE()[*p - 1].sg_name);
@@ -4190,12 +4294,13 @@ clear_keywtab(ht)
  * Add a keyword to the list of keywords.
  */
     static void
-add_keyword(name, id, flags, cont_in_list, next_list)
+add_keyword(name, id, flags, cont_in_list, next_list, conceal_char)
     char_u     *name;      /* name of keyword */
     int                id;         /* group ID for this keyword */
     int                flags;      /* flags for this keyword */
     short      *cont_in_list; /* containedin for this keyword */
     short      *next_list; /* nextgroup for this keyword */
+    int                conceal_char;
 {
     keyentry_T *kp;
     hashtab_T  *ht;
@@ -4204,7 +4309,7 @@ add_keyword(name, id, flags, cont_in_list, next_list)
     long_u     hash;
     char_u     name_folded[MAXKEYWLEN + 1];
 
-    if (curbuf->b_syn_ic)
+    if (curwin->w_s->b_syn_ic)
        name_ic = str_foldcase(name, (int)STRLEN(name),
                                                 name_folded, MAXKEYWLEN + 1);
     else
@@ -4216,15 +4321,16 @@ add_keyword(name, id, flags, cont_in_list, next_list)
     kp->k_syn.id = id;
     kp->k_syn.inc_tag = current_syn_inc_tag;
     kp->flags = flags;
+    kp->k_char = conceal_char;
     kp->k_syn.cont_in_list = copy_id_list(cont_in_list);
     if (cont_in_list != NULL)
-       curbuf->b_syn_containedin = TRUE;
+       curwin->w_s->b_syn_containedin = TRUE;
     kp->next_list = copy_id_list(next_list);
 
-    if (curbuf->b_syn_ic)
-       ht = &curbuf->b_keywtab_ic;
+    if (curwin->w_s->b_syn_ic)
+       ht = &curwin->w_s->b_keywtab_ic;
     else
-       ht = &curbuf->b_keywtab;
+       ht = &curwin->w_s->b_keywtab;
 
     hash = hash_hash(kp->keyword);
     hi = hash_lookup(ht, kp->keyword, hash);
@@ -4275,9 +4381,10 @@ get_group_name(arg, name_end)
  * Return NULL for any error;
  */
     static char_u *
-get_syn_options(arg, opt)
+get_syn_options(arg, opt, conceal_char)
     char_u         *arg;               /* next argument to be checked */
     syn_opt_arg_T   *opt;              /* various things */
+    int                    *conceal_char UNUSED;
 {
     char_u     *gname_start, *gname;
     int                syn_id;
@@ -4303,6 +4410,9 @@ get_syn_options(arg, opt)
                    {"gGrRoOuUpPtThHeErReE",    0,      HL_SYNC_THERE},
                    {"dDiIsSpPlLaAyY",          0,      HL_DISPLAY},
                    {"fFoOlLdD",                0,      HL_FOLD},
+                   {"cCoOnNcCeEaAlL",          0,      HL_CONCEAL},
+                   {"cCoOnNcCeEaAlLeEnNdDsS",  0,      HL_CONCEALENDS},
+                   {"cCcChHaArR",              11,     0},
                    {"cCoOnNtTaAiInNsS",        1,      0},
                    {"cCoOnNtTaAiInNeEdDiInN",  2,      0},
                    {"nNeExXtTgGrRoOuUpP",      3,      0},
@@ -4312,6 +4422,11 @@ get_syn_options(arg, opt)
     if (arg == NULL)           /* already detected error */
        return NULL;
 
+#ifdef FEAT_CONCEAL
+    if (curwin->w_s->b_syn_conceal)
+       opt->flags |= HL_CONCEAL;
+#endif
+
     for (;;)
     {
        /*
@@ -4372,6 +4487,26 @@ get_syn_options(arg, opt)
            if (get_id_list(&arg, 9, &opt->next_list) == FAIL)
                return NULL;
        }
+       else if (flagtab[fidx].argtype == 11 && arg[5] == '=')
+       {
+#ifdef FEAT_MBYTE
+           /* cchar=? */
+           if (has_mbyte)
+           {
+# ifdef FEAT_CONCEAL
+               *conceal_char = mb_ptr2char(arg + 6);
+# endif
+               arg += mb_ptr2len(arg + 6) - 1;
+           }
+           else
+#endif
+#ifdef FEAT_CONCEAL
+               *conceal_char = arg[6];
+#else
+               ;
+#endif
+           arg = skipwhite(arg + 7);
+       }
        else
        {
            opt->flags |= flagtab[fidx].flags;
@@ -4397,9 +4532,9 @@ get_syn_options(arg, opt)
                else
                {
                    syn_id = syn_name2id(gname);
-                   for (i = curbuf->b_syn_patterns.ga_len; --i >= 0; )
-                       if (SYN_ITEMS(curbuf)[i].sp_syn.id == syn_id
-                             && SYN_ITEMS(curbuf)[i].sp_type == SPTYPE_START)
+                   for (i = curwin->w_s->b_syn_patterns.ga_len; --i >= 0; )
+                       if (SYN_ITEMS(curwin->w_s)[i].sp_syn.id == syn_id
+                             && SYN_ITEMS(curwin->w_s)[i].sp_type == SPTYPE_START)
                        {
                            *opt->sync_idx = i;
                            break;
@@ -4437,20 +4572,20 @@ syn_incl_toplevel(id, flagsp)
     int                id;
     int                *flagsp;
 {
-    if ((*flagsp & HL_CONTAINED) || curbuf->b_syn_topgrp == 0)
+    if ((*flagsp & HL_CONTAINED) || curwin->w_s->b_syn_topgrp == 0)
        return;
     *flagsp |= HL_CONTAINED;
-    if (curbuf->b_syn_topgrp >= SYNID_CLUSTER)
+    if (curwin->w_s->b_syn_topgrp >= SYNID_CLUSTER)
     {
        /* We have to alloc this, because syn_combine_list() will free it. */
        short       *grp_list = (short *)alloc((unsigned)(2 * sizeof(short)));
-       int         tlg_id = curbuf->b_syn_topgrp - SYNID_CLUSTER;
+       int         tlg_id = curwin->w_s->b_syn_topgrp - SYNID_CLUSTER;
 
        if (grp_list != NULL)
        {
            grp_list[0] = id;
            grp_list[1] = 0;
-           syn_combine_list(&SYN_CLSTR(curbuf)[tlg_id].scl_list, &grp_list,
+           syn_combine_list(&SYN_CLSTR(curwin->w_s)[tlg_id].scl_list, &grp_list,
                         CLUSTER_ADD);
        }
     }
@@ -4517,12 +4652,12 @@ syn_cmd_include(eap, syncing)
      */
     prev_syn_inc_tag = current_syn_inc_tag;
     current_syn_inc_tag = ++running_syn_inc_tag;
-    prev_toplvl_grp = curbuf->b_syn_topgrp;
-    curbuf->b_syn_topgrp = sgl_id;
+    prev_toplvl_grp = curwin->w_s->b_syn_topgrp;
+    curwin->w_s->b_syn_topgrp = sgl_id;
     if (source ? do_source(eap->arg, FALSE, DOSO_NONE) == FAIL
                                : source_runtime(eap->arg, TRUE) == FAIL)
        EMSG2(_(e_notopen), eap->arg);
-    curbuf->b_syn_topgrp = prev_toplvl_grp;
+    curwin->w_s->b_syn_topgrp = prev_toplvl_grp;
     current_syn_inc_tag = prev_syn_inc_tag;
 }
 
@@ -4543,6 +4678,7 @@ syn_cmd_keyword(eap, syncing)
     char_u     *kw;
     syn_opt_arg_T syn_opt_arg;
     int                cnt;
+    int                conceal_char = NUL;
 
     rest = get_group_name(arg, &group_name_end);
 
@@ -4570,7 +4706,7 @@ syn_cmd_keyword(eap, syncing)
            p = keyword_copy;
            for ( ; rest != NULL && !ends_excmd(*rest); rest = skipwhite(rest))
            {
-               rest = get_syn_options(rest, &syn_opt_arg);
+               rest = get_syn_options(rest, &syn_opt_arg, &conceal_char);
                if (rest == NULL || ends_excmd(*rest))
                    break;
                /* Copy the keyword, removing backslashes, and add a NUL. */
@@ -4599,8 +4735,8 @@ syn_cmd_keyword(eap, syncing)
                        if (p != NULL)
                            *p = NUL;
                        add_keyword(kw, syn_id, syn_opt_arg.flags,
-                                                    syn_opt_arg.cont_in_list,
-                                                      syn_opt_arg.next_list);
+                               syn_opt_arg.cont_in_list,
+                                        syn_opt_arg.next_list, conceal_char);
                        if (p == NULL)
                            break;
                        if (p[1] == NUL)
@@ -4644,7 +4780,7 @@ syn_cmd_keyword(eap, syncing)
        EMSG2(_(e_invarg2), arg);
 
     redraw_curbuf_later(SOME_VALID);
-    syn_stack_free_all(curbuf);                /* Need to recompute all syntax. */
+    syn_stack_free_all(curwin->w_s);           /* Need to recompute all syntax. */
 }
 
 /*
@@ -4665,6 +4801,7 @@ syn_cmd_match(eap, syncing)
     int                idx;
     syn_opt_arg_T syn_opt_arg;
     int                sync_idx = 0;
+    int                conceal_char = NUL;
 
     /* Isolate the group name, check for validity */
     rest = get_group_name(arg, &group_name_end);
@@ -4677,7 +4814,7 @@ syn_cmd_match(eap, syncing)
     syn_opt_arg.cont_list = NULL;
     syn_opt_arg.cont_in_list = NULL;
     syn_opt_arg.next_list = NULL;
-    rest = get_syn_options(rest, &syn_opt_arg);
+    rest = get_syn_options(rest, &syn_opt_arg, &conceal_char);
 
     /* get the pattern. */
     init_syn_patterns();
@@ -4687,7 +4824,7 @@ syn_cmd_match(eap, syncing)
        syn_opt_arg.flags |= HL_HAS_EOL;
 
     /* Get options after the pattern */
-    rest = get_syn_options(rest, &syn_opt_arg);
+    rest = get_syn_options(rest, &syn_opt_arg, &conceal_char);
 
     if (rest != NULL)          /* all arguments are valid */
     {
@@ -4697,7 +4834,7 @@ syn_cmd_match(eap, syncing)
        eap->nextcmd = check_nextcmd(rest);
        if (!ends_excmd(*rest) || eap->skip)
            rest = NULL;
-       else if (ga_grow(&curbuf->b_syn_patterns, 1) != FAIL
+       else if (ga_grow(&curwin->w_s->b_syn_patterns, 1) != FAIL
                && (syn_id = syn_check_group(arg,
                                           (int)(group_name_end - arg))) != 0)
        {
@@ -4705,32 +4842,35 @@ syn_cmd_match(eap, syncing)
            /*
             * Store the pattern in the syn_items list
             */
-           idx = curbuf->b_syn_patterns.ga_len;
-           SYN_ITEMS(curbuf)[idx] = item;
-           SYN_ITEMS(curbuf)[idx].sp_syncing = syncing;
-           SYN_ITEMS(curbuf)[idx].sp_type = SPTYPE_MATCH;
-           SYN_ITEMS(curbuf)[idx].sp_syn.id = syn_id;
-           SYN_ITEMS(curbuf)[idx].sp_syn.inc_tag = current_syn_inc_tag;
-           SYN_ITEMS(curbuf)[idx].sp_flags = syn_opt_arg.flags;
-           SYN_ITEMS(curbuf)[idx].sp_sync_idx = sync_idx;
-           SYN_ITEMS(curbuf)[idx].sp_cont_list = syn_opt_arg.cont_list;
-           SYN_ITEMS(curbuf)[idx].sp_syn.cont_in_list =
+           idx = curwin->w_s->b_syn_patterns.ga_len;
+           SYN_ITEMS(curwin->w_s)[idx] = item;
+           SYN_ITEMS(curwin->w_s)[idx].sp_syncing = syncing;
+           SYN_ITEMS(curwin->w_s)[idx].sp_type = SPTYPE_MATCH;
+           SYN_ITEMS(curwin->w_s)[idx].sp_syn.id = syn_id;
+           SYN_ITEMS(curwin->w_s)[idx].sp_syn.inc_tag = current_syn_inc_tag;
+           SYN_ITEMS(curwin->w_s)[idx].sp_flags = syn_opt_arg.flags;
+           SYN_ITEMS(curwin->w_s)[idx].sp_sync_idx = sync_idx;
+           SYN_ITEMS(curwin->w_s)[idx].sp_cont_list = syn_opt_arg.cont_list;
+           SYN_ITEMS(curwin->w_s)[idx].sp_syn.cont_in_list =
                                                     syn_opt_arg.cont_in_list;
+#ifdef FEAT_CONCEAL
+           SYN_ITEMS(curwin->w_s)[idx].sp_char = conceal_char;
+#endif
            if (syn_opt_arg.cont_in_list != NULL)
-               curbuf->b_syn_containedin = TRUE;
-           SYN_ITEMS(curbuf)[idx].sp_next_list = syn_opt_arg.next_list;
-           ++curbuf->b_syn_patterns.ga_len;
+               curwin->w_s->b_syn_containedin = TRUE;
+           SYN_ITEMS(curwin->w_s)[idx].sp_next_list = syn_opt_arg.next_list;
+           ++curwin->w_s->b_syn_patterns.ga_len;
 
            /* remember that we found a match for syncing on */
            if (syn_opt_arg.flags & (HL_SYNC_HERE|HL_SYNC_THERE))
-               curbuf->b_syn_sync_flags |= SF_MATCH;
+               curwin->w_s->b_syn_sync_flags |= SF_MATCH;
 #ifdef FEAT_FOLDING
            if (syn_opt_arg.flags & HL_FOLD)
-               ++curbuf->b_syn_folditems;
+               ++curwin->w_s->b_syn_folditems;
 #endif
 
            redraw_curbuf_later(SOME_VALID);
-           syn_stack_free_all(curbuf); /* Need to recompute all syntax. */
+           syn_stack_free_all(curwin->w_s);    /* Need to recompute all syntax. */
            return;     /* don't free the progs and patterns now */
        }
     }
@@ -4785,6 +4925,7 @@ syn_cmd_region(eap, syncing)
     int                        success = FALSE;
     int                        idx;
     syn_opt_arg_T      syn_opt_arg;
+    int                        conceal_char = NUL;
 
     /* Isolate the group name, check for validity */
     rest = get_group_name(arg, &group_name_end);
@@ -4809,7 +4950,7 @@ syn_cmd_region(eap, syncing)
     while (rest != NULL && !ends_excmd(*rest))
     {
        /* Check for option arguments */
-       rest = get_syn_options(rest, &syn_opt_arg);
+       rest = get_syn_options(rest, &syn_opt_arg, &conceal_char);
        if (rest == NULL || ends_excmd(*rest))
            break;
 
@@ -4933,7 +5074,7 @@ syn_cmd_region(eap, syncing)
        eap->nextcmd = check_nextcmd(rest);
        if (!ends_excmd(*rest) || eap->skip)
            rest = NULL;
-       else if (ga_grow(&(curbuf->b_syn_patterns), pat_count) != FAIL
+       else if (ga_grow(&(curwin->w_s->b_syn_patterns), pat_count) != FAIL
                && (syn_id = syn_check_group(arg,
                                           (int)(group_name_end - arg))) != 0)
        {
@@ -4941,43 +5082,46 @@ syn_cmd_region(eap, syncing)
            /*
             * Store the start/skip/end in the syn_items list
             */
-           idx = curbuf->b_syn_patterns.ga_len;
+           idx = curwin->w_s->b_syn_patterns.ga_len;
            for (item = ITEM_START; item <= ITEM_END; ++item)
            {
                for (ppp = pat_ptrs[item]; ppp != NULL; ppp = ppp->pp_next)
                {
-                   SYN_ITEMS(curbuf)[idx] = *(ppp->pp_synp);
-                   SYN_ITEMS(curbuf)[idx].sp_syncing = syncing;
-                   SYN_ITEMS(curbuf)[idx].sp_type =
+                   SYN_ITEMS(curwin->w_s)[idx] = *(ppp->pp_synp);
+                   SYN_ITEMS(curwin->w_s)[idx].sp_syncing = syncing;
+                   SYN_ITEMS(curwin->w_s)[idx].sp_type =
                            (item == ITEM_START) ? SPTYPE_START :
                            (item == ITEM_SKIP) ? SPTYPE_SKIP : SPTYPE_END;
-                   SYN_ITEMS(curbuf)[idx].sp_flags |= syn_opt_arg.flags;
-                   SYN_ITEMS(curbuf)[idx].sp_syn.id = syn_id;
-                   SYN_ITEMS(curbuf)[idx].sp_syn.inc_tag = current_syn_inc_tag;
-                   SYN_ITEMS(curbuf)[idx].sp_syn_match_id =
+                   SYN_ITEMS(curwin->w_s)[idx].sp_flags |= syn_opt_arg.flags;
+                   SYN_ITEMS(curwin->w_s)[idx].sp_syn.id = syn_id;
+                   SYN_ITEMS(curwin->w_s)[idx].sp_syn.inc_tag = current_syn_inc_tag;
+                   SYN_ITEMS(curwin->w_s)[idx].sp_syn_match_id =
                                                        ppp->pp_matchgroup_id;
+#ifdef FEAT_CONCEAL
+                   SYN_ITEMS(curwin->w_s)[idx].sp_char = conceal_char;
+#endif
                    if (item == ITEM_START)
                    {
-                       SYN_ITEMS(curbuf)[idx].sp_cont_list =
+                       SYN_ITEMS(curwin->w_s)[idx].sp_cont_list =
                                                        syn_opt_arg.cont_list;
-                       SYN_ITEMS(curbuf)[idx].sp_syn.cont_in_list =
+                       SYN_ITEMS(curwin->w_s)[idx].sp_syn.cont_in_list =
                                                     syn_opt_arg.cont_in_list;
                        if (syn_opt_arg.cont_in_list != NULL)
-                           curbuf->b_syn_containedin = TRUE;
-                       SYN_ITEMS(curbuf)[idx].sp_next_list =
+                           curwin->w_s->b_syn_containedin = TRUE;
+                       SYN_ITEMS(curwin->w_s)[idx].sp_next_list =
                                                        syn_opt_arg.next_list;
                    }
-                   ++curbuf->b_syn_patterns.ga_len;
+                   ++curwin->w_s->b_syn_patterns.ga_len;
                    ++idx;
 #ifdef FEAT_FOLDING
                    if (syn_opt_arg.flags & HL_FOLD)
-                       ++curbuf->b_syn_folditems;
+                       ++curwin->w_s->b_syn_folditems;
 #endif
                }
            }
 
            redraw_curbuf_later(SOME_VALID);
-           syn_stack_free_all(curbuf); /* Need to recompute all syntax. */
+           syn_stack_free_all(curwin->w_s);    /* Need to recompute all syntax. */
            success = TRUE;         /* don't free the progs and patterns now */
        }
     }
@@ -5169,9 +5313,9 @@ syn_scl_name2id(name)
     name_u = vim_strsave_up(name);
     if (name_u == NULL)
        return 0;
-    for (i = curbuf->b_syn_clusters.ga_len; --i >= 0; )
-       if (SYN_CLSTR(curbuf)[i].scl_name_u != NULL
-               && STRCMP(name_u, SYN_CLSTR(curbuf)[i].scl_name_u) == 0)
+    for (i = curwin->w_s->b_syn_clusters.ga_len; --i >= 0; )
+       if (SYN_CLSTR(curwin->w_s)[i].scl_name_u != NULL
+               && STRCMP(name_u, SYN_CLSTR(curwin->w_s)[i].scl_name_u) == 0)
            break;
     vim_free(name_u);
     return (i < 0 ? 0 : i + SYNID_CLUSTER);
@@ -5237,32 +5381,32 @@ syn_add_cluster(name)
     /*
      * First call for this growarray: init growing array.
      */
-    if (curbuf->b_syn_clusters.ga_data == NULL)
+    if (curwin->w_s->b_syn_clusters.ga_data == NULL)
     {
-       curbuf->b_syn_clusters.ga_itemsize = sizeof(syn_cluster_T);
-       curbuf->b_syn_clusters.ga_growsize = 10;
+       curwin->w_s->b_syn_clusters.ga_itemsize = sizeof(syn_cluster_T);
+       curwin->w_s->b_syn_clusters.ga_growsize = 10;
     }
 
     /*
      * Make room for at least one other cluster entry.
      */
-    if (ga_grow(&curbuf->b_syn_clusters, 1) == FAIL)
+    if (ga_grow(&curwin->w_s->b_syn_clusters, 1) == FAIL)
     {
        vim_free(name);
        return 0;
     }
-    len = curbuf->b_syn_clusters.ga_len;
+    len = curwin->w_s->b_syn_clusters.ga_len;
 
-    vim_memset(&(SYN_CLSTR(curbuf)[len]), 0, sizeof(syn_cluster_T));
-    SYN_CLSTR(curbuf)[len].scl_name = name;
-    SYN_CLSTR(curbuf)[len].scl_name_u = vim_strsave_up(name);
-    SYN_CLSTR(curbuf)[len].scl_list = NULL;
-    ++curbuf->b_syn_clusters.ga_len;
+    vim_memset(&(SYN_CLSTR(curwin->w_s)[len]), 0, sizeof(syn_cluster_T));
+    SYN_CLSTR(curwin->w_s)[len].scl_name = name;
+    SYN_CLSTR(curwin->w_s)[len].scl_name_u = vim_strsave_up(name);
+    SYN_CLSTR(curwin->w_s)[len].scl_list = NULL;
+    ++curwin->w_s->b_syn_clusters.ga_len;
 
     if (STRICMP(name, "Spell") == 0)
-       curbuf->b_spell_cluster_id = len + SYNID_CLUSTER;
+       curwin->w_s->b_spell_cluster_id = len + SYNID_CLUSTER;
     if (STRICMP(name, "NoSpell") == 0)
-       curbuf->b_nospell_cluster_id = len + SYNID_CLUSTER;
+       curwin->w_s->b_nospell_cluster_id = len + SYNID_CLUSTER;
 
     return len + SYNID_CLUSTER;
 }
@@ -5325,7 +5469,7 @@ syn_cmd_cluster(eap, syncing)
                EMSG2(_(e_invarg2), rest);
                break;
            }
-           syn_combine_list(&SYN_CLSTR(curbuf)[scl_id].scl_list,
+           syn_combine_list(&SYN_CLSTR(curwin->w_s)[scl_id].scl_list,
                             &clstr_list, list_op);
            got_clstr = TRUE;
        }
@@ -5333,7 +5477,7 @@ syn_cmd_cluster(eap, syncing)
        if (got_clstr)
        {
            redraw_curbuf_later(SOME_VALID);
-           syn_stack_free_all(curbuf); /* Need to recompute all syntax. */
+           syn_stack_free_all(curwin->w_s);    /* Need to recompute all syntax. */
        }
     }
 
@@ -5349,8 +5493,8 @@ syn_cmd_cluster(eap, syncing)
     static void
 init_syn_patterns()
 {
-    curbuf->b_syn_patterns.ga_itemsize = sizeof(synpat_T);
-    curbuf->b_syn_patterns.ga_growsize = 10;
+    curwin->w_s->b_syn_patterns.ga_itemsize = sizeof(synpat_T);
+    curwin->w_s->b_syn_patterns.ga_growsize = 10;
 }
 
 /*
@@ -5390,7 +5534,7 @@ get_syn_pattern(arg, ci)
 
     if (ci->sp_prog == NULL)
        return NULL;
-    ci->sp_ic = curbuf->b_syn_ic;
+    ci->sp_ic = curwin->w_s->b_syn_ic;
 
     /*
      * Check for a match, highlight or region offset.
@@ -5488,17 +5632,17 @@ syn_cmd_sync(eap, syncing)
        if (STRCMP(key, "CCOMMENT") == 0)
        {
            if (!eap->skip)
-               curbuf->b_syn_sync_flags |= SF_CCOMMENT;
+               curwin->w_s->b_syn_sync_flags |= SF_CCOMMENT;
            if (!ends_excmd(*next_arg))
            {
                arg_end = skiptowhite(next_arg);
                if (!eap->skip)
-                   curbuf->b_syn_sync_id = syn_check_group(next_arg,
+                   curwin->w_s->b_syn_sync_id = syn_check_group(next_arg,
                                                   (int)(arg_end - next_arg));
                next_arg = skipwhite(arg_end);
            }
            else if (!eap->skip)
-               curbuf->b_syn_sync_id = syn_name2id((char_u *)"Comment");
+               curwin->w_s->b_syn_sync_id = syn_name2id((char_u *)"Comment");
        }
        else if (  STRNCMP(key, "LINES", 5) == 0
                || STRNCMP(key, "MINLINES", 8) == 0
@@ -5520,24 +5664,24 @@ syn_cmd_sync(eap, syncing)
            if (!eap->skip)
            {
                if (key[4] == 'B')
-                   curbuf->b_syn_sync_linebreaks = n;
+                   curwin->w_s->b_syn_sync_linebreaks = n;
                else if (key[1] == 'A')
-                   curbuf->b_syn_sync_maxlines = n;
+                   curwin->w_s->b_syn_sync_maxlines = n;
                else
-                   curbuf->b_syn_sync_minlines = n;
+                   curwin->w_s->b_syn_sync_minlines = n;
            }
        }
        else if (STRCMP(key, "FROMSTART") == 0)
        {
            if (!eap->skip)
            {
-               curbuf->b_syn_sync_minlines = MAXLNUM;
-               curbuf->b_syn_sync_maxlines = 0;
+               curwin->w_s->b_syn_sync_minlines = MAXLNUM;
+               curwin->w_s->b_syn_sync_maxlines = 0;
            }
        }
        else if (STRCMP(key, "LINECONT") == 0)
        {
-           if (curbuf->b_syn_linecont_pat != NULL)
+           if (curwin->w_s->b_syn_linecont_pat != NULL)
            {
                EMSG(_("E403: syntax sync: line continuations pattern specified twice"));
                finished = TRUE;
@@ -5553,25 +5697,25 @@ syn_cmd_sync(eap, syncing)
            if (!eap->skip)
            {
                /* store the pattern and compiled regexp program */
-               if ((curbuf->b_syn_linecont_pat = vim_strnsave(next_arg + 1,
+               if ((curwin->w_s->b_syn_linecont_pat = vim_strnsave(next_arg + 1,
                                      (int)(arg_end - next_arg - 1))) == NULL)
                {
                    finished = TRUE;
                    break;
                }
-               curbuf->b_syn_linecont_ic = curbuf->b_syn_ic;
+               curwin->w_s->b_syn_linecont_ic = curwin->w_s->b_syn_ic;
 
                /* Make 'cpoptions' empty, to avoid the 'l' flag */
                cpo_save = p_cpo;
                p_cpo = (char_u *)"";
-               curbuf->b_syn_linecont_prog =
-                           vim_regcomp(curbuf->b_syn_linecont_pat, RE_MAGIC);
+               curwin->w_s->b_syn_linecont_prog =
+                           vim_regcomp(curwin->w_s->b_syn_linecont_pat, RE_MAGIC);
                p_cpo = cpo_save;
 
-               if (curbuf->b_syn_linecont_prog == NULL)
+               if (curwin->w_s->b_syn_linecont_prog == NULL)
                {
-                   vim_free(curbuf->b_syn_linecont_pat);
-                   curbuf->b_syn_linecont_pat = NULL;
+                   vim_free(curwin->w_s->b_syn_linecont_pat);
+                   curwin->w_s->b_syn_linecont_pat = NULL;
                    finished = TRUE;
                    break;
                }
@@ -5601,7 +5745,7 @@ syn_cmd_sync(eap, syncing)
     {
        eap->nextcmd = check_nextcmd(arg_start);
        redraw_curbuf_later(SOME_VALID);
-       syn_stack_free_all(curbuf);     /* Need to recompute all syntax. */
+       syn_stack_free_all(curwin->w_s);        /* Need to recompute all syntax. */
     }
 }
 
@@ -5862,8 +6006,8 @@ in_id_list(cur_si, list, ssp, contained)
            --cur_si;
        /* cur_si->si_idx is -1 for keywords, these never contain anything. */
        if (cur_si->si_idx >= 0 && in_id_list(NULL, ssp->cont_in_list,
-               &(SYN_ITEMS(syn_buf)[cur_si->si_idx].sp_syn),
-                 SYN_ITEMS(syn_buf)[cur_si->si_idx].sp_flags & HL_CONTAINED))
+               &(SYN_ITEMS(syn_block)[cur_si->si_idx].sp_syn),
+                 SYN_ITEMS(syn_block)[cur_si->si_idx].sp_flags & HL_CONTAINED))
            return TRUE;
     }
 
@@ -5918,7 +6062,7 @@ in_id_list(cur_si, list, ssp, contained)
            return retval;
        if (item >= SYNID_CLUSTER)
        {
-           scl_list = SYN_CLSTR(syn_buf)[item - SYNID_CLUSTER].scl_list;
+           scl_list = SYN_CLSTR(syn_block)[item - SYNID_CLUSTER].scl_list;
            /* restrict recursiveness to 30 to avoid an endless loop for a
             * cluster that includes itself (indirectly) */
            if (scl_list != NULL && depth < 30)
@@ -5946,6 +6090,7 @@ static struct subcommand subcommands[] =
     {"case",           syn_cmd_case},
     {"clear",          syn_cmd_clear},
     {"cluster",                syn_cmd_cluster},
+    {"conceal",                syn_cmd_conceal},
     {"enable",         syn_cmd_enable},
     {"include",                syn_cmd_include},
     {"keyword",                syn_cmd_keyword},
@@ -6006,14 +6151,34 @@ ex_syntax(eap)
     }
 }
 
+    void
+ex_ownsyntax(eap)
+    exarg_T    *eap;
+{
+    if (curwin->w_s == &curwin->w_buffer->b_s)
+    {
+       curwin->w_s = (synblock_T *)alloc(sizeof(synblock_T));
+       memset(curwin->w_s, 0, sizeof(synblock_T));
+#ifdef FEAT_SPELL
+       curwin->w_p_spell = FALSE;      /* No spell checking */
+       clear_string_option(&curwin->w_s->b_p_spc);
+       clear_string_option(&curwin->w_s->b_p_spf);
+       vim_free(curwin->w_s->b_cap_prog);
+       curwin->w_s->b_cap_prog = NULL;
+       clear_string_option(&curwin->w_s->b_p_spl);
+#endif
+    }
+    apply_autocmds(EVENT_SYNTAX, eap->arg, curbuf->b_fname, TRUE, curbuf);
+}
+
     int
-syntax_present(buf)
-    buf_T      *buf;
+syntax_present(win)
+    win_T      *win;
 {
-    return (buf->b_syn_patterns.ga_len != 0
-           || buf->b_syn_clusters.ga_len != 0
-           || buf->b_keywtab.ht_used > 0
-           || buf->b_keywtab_ic.ht_used > 0);
+    return (win->w_s->b_syn_patterns.ga_len != 0
+           || win->w_s->b_syn_clusters.ga_len != 0
+           || win->w_s->b_keywtab.ht_used > 0
+           || win->w_s->b_keywtab_ic.ht_used > 0);
 }
 
 #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
@@ -6124,11 +6289,22 @@ syn_get_id(wp, lnum, col, trans, spellp, keep_state)
            || col < current_col)
        syntax_start(wp, lnum);
 
-    (void)get_syntax_attr(col, spellp, keep_state);
+    (void)get_syntax_attr(col, NULL, spellp, keep_state);
 
     return (trans ? current_trans_id : current_id);
 }
 
+#if defined(FEAT_CONCEAL) || defined(PROTO)
+/*
+ * Return conceal substitution character
+ */
+    int
+syn_get_sub_char()
+{
+    return current_sub_char;
+}
+#endif
+
 #if defined(FEAT_EVAL) || defined(PROTO)
 /*
  * Return the syntax ID at position "i" in the current stack.
@@ -6164,7 +6340,7 @@ syn_get_foldlevel(wp, lnum)
     int                i;
 
     /* Return quickly when there are no fold items at all. */
-    if (wp->w_buffer->b_syn_folditems != 0)
+    if (wp->w_s->b_syn_folditems != 0)
     {
        syntax_start(wp, lnum);
 
@@ -6316,6 +6492,10 @@ static char *(highlight_init_light[]) =
        CENT("CursorLine term=underline cterm=underline",
             "CursorLine term=underline cterm=underline guibg=Grey90"),
 #endif
+#ifdef FEAT_CONCEAL
+       CENT("Conceal ctermbg=DarkGrey ctermfg=LightGrey",
+            "Conceal ctermbg=DarkGrey ctermfg=LightGrey guibg=DarkGrey guifg=LightGrey"),
+#endif
 #ifdef FEAT_AUTOCMD
        CENT("MatchParen term=reverse ctermbg=Cyan",
             "MatchParen term=reverse ctermbg=Cyan guibg=Cyan"),
@@ -6400,6 +6580,10 @@ static char *(highlight_init_dark[]) =
        CENT("MatchParen term=reverse ctermbg=DarkCyan",
             "MatchParen term=reverse ctermbg=DarkCyan guibg=DarkCyan"),
 #endif
+#ifdef FEAT_CONCEAL
+       CENT("Conceal ctermbg=DarkGrey ctermfg=LightGrey",
+            "Conceal ctermbg=DarkGrey ctermfg=LightGrey guibg=DarkGrey guifg=LightGrey"),
+#endif
 #ifdef FEAT_GUI
        "Normal gui=NONE",
 #endif
index a755e3008460536c9cf76c692cb41a77b3a5d23e..9ca902be62d22091876c64d1e75392a115caae0c 100644 (file)
--- 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)
 /*
index 04a33b8f10481d505ce8d6d84baad5b902ce9a6e..c0026708c3a7d051a7bb69abc849c3b21f8a3a5e 100644 (file)
@@ -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
index a5d7364385e8815cedec25076f45d03f66c97d08..b340792012d62c3cded0eca7d917cbb97b859634 100644 (file)
--- a/src/vim.h
+++ b/src/vim.h
@@ -853,6 +853,27 @@ extern char *(*dyn_libintl_textdomain)(const char *domainname);
 # endif
 # define SST_FIX_STATES         7      /* size of sst_stack[]. */
 # define SST_DIST       16     /* normal distance between entries */
+# define SST_INVALID   (synstate_T *)-1        /* invalid syn_state pointer */
+
+# define HL_CONTAINED  0x01    /* not used on toplevel */
+# define HL_TRANSP     0x02    /* has no highlighting  */
+# define HL_ONELINE    0x04    /* match within one line only */
+# define HL_HAS_EOL    0x08    /* end pattern that matches with $ */
+# define HL_SYNC_HERE  0x10    /* sync point after this item (syncing only) */
+# define HL_SYNC_THERE 0x20    /* sync point at current line (syncing only) */
+# define HL_MATCH      0x40    /* use match ID instead of item ID */
+# define HL_SKIPNL     0x80    /* nextgroup can skip newlines */
+# define HL_SKIPWHITE  0x100   /* nextgroup can skip white space */
+# define HL_SKIPEMPTY  0x200   /* nextgroup can skip empty lines */
+# define HL_KEEPEND    0x400   /* end match always kept */
+# define HL_EXCLUDENL  0x800   /* exclude NL from match */
+# define HL_DISPLAY    0x1000  /* only used for displaying, not syncing */
+# define HL_FOLD       0x2000  /* define fold */
+# define HL_EXTEND     0x4000  /* ignore a keepend */
+# define HL_MATCHCONT  0x8000  /* match continued from previous line */
+# define HL_TRANS_CONT 0x10000 /* transparent item without contains arg */
+# define HL_CONCEAL    0x20000 /* can be concealed */
+# define HL_CONCEALENDS        0x40000 /* can be concealed */
 #endif
 
 /* Values for 'options' argument in do_search() and searchit() */
@@ -1292,6 +1313,7 @@ typedef enum
     , HLF_CHD      /* Changed diff line */
     , HLF_DED      /* Deleted diff line */
     , HLF_TXD      /* Text Changed in diff line */
+    , HLF_CONCEAL   /* Concealed text */
     , HLF_SC       /* Sign column */
     , HLF_SPB      /* SpellBad */
     , HLF_SPC      /* SpellCap */
@@ -1313,7 +1335,7 @@ typedef enum
  * When changing this also adjust the default for 'highlight'. */
 #define HL_FLAGS {'8', '@', 'd', 'e', 'h', 'i', 'l', 'm', 'M', \
                  'n', 'r', 's', 'S', 'c', 't', 'v', 'V', 'w', 'W', \
-                 'f', 'F', 'A', 'C', 'D', 'T', '>', \
+                 'f', 'F', 'A', 'C', 'D', 'T', '-', '>', \
                  'B', 'P', 'R', 'L', \
                  '+', '=', 'x', 'X', '*', '#', '_', '!', '.'}
 
index 9071012955b40186d63fff16ac577106a53dd1ab..d6aae7c0f35b9fd96c95813255d428d4d028e649 100644 (file)
@@ -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
index 393e3d151c98430d2568490bbaa31f63bcc44fe0..cd98914bcf2fd7700e53d990000ef1a3900d4150 100644 (file)
@@ -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);
     }