Index: src/buffer.c =================================================================== RCS file: /cvsroot/vim/vim/src/buffer.c,v retrieving revision 1.113 diff -c -5 -r1.113 buffer.c *** src/buffer.c 2 Jun 2004 15:51:47 -0000 1.113 --- src/buffer.c 8 Jun 2004 08:53:25 -0000 *************** *** 560,570 **** u_blockfree(buf); /* free the memory allocated for undo */ ml_close(buf, TRUE); /* close and delete the memline/memfile */ 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 */ #endif } /* * Free a buffer structure and the things it contains related to the buffer --- 560,570 ---- u_blockfree(buf); /* free the memory allocated for undo */ ml_close(buf, TRUE); /* close and delete the memline/memfile */ 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->s); /* reset syntax info */ #endif } /* * Free a buffer structure and the things it contains related to the buffer *************** *** 1305,1314 **** --- 1305,1323 ---- /* Remove all folds in the window. */ clearFolding(curwin); foldUpdateAll(curwin); /* update folds (later). */ #endif + #ifdef FEAT_SYN_HL + if (curwin->w_s != &curwin->w_buffer->s) + { + /* Get rid of independant syntax */ + syntax_clear(curwin->w_s); + vim_free(curwin->w_s); + } + curwin->w_s = &(buf->s); + #endif /* Get the buffer in the current window. */ curwin->w_buffer = buf; curbuf = buf; ++curbuf->b_nwindows; Index: src/diff.c =================================================================== RCS file: /cvsroot/vim/vim/src/diff.c,v retrieving revision 1.38 diff -c -5 -r1.38 diff.c *** src/diff.c 8 May 2004 00:12:17 -0000 1.38 --- src/diff.c 8 Jun 2004 08:53:26 -0000 *************** *** 1009,1018 **** --- 1009,1022 ---- diff_win_options(wp, addbuf) win_T *wp; int addbuf; /* Add buffer to diff. */ { 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 { win_T *old_curwin = curwin; *************** *** 2156,2165 **** --- 2160,2244 ---- curwin->w_cursor.col = 0; return OK; } + #ifdef FEAT_CURSORBIND + 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 || first_diff == NULL) + return lnum1; + + if (diff_invalid) + ex_diffupdate(NULL); /* update after a big change */ + + if (first_diff == NULL) /* no diffs today */ + return lnum1; + + for (dp = 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]; + + lnum2 = dp->df_lnum[idx2] + baseline; + + return lnum2; + } + 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; + else + 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 * "wp", compensating for inserted/deleted lines. */ Index: src/edit.c =================================================================== RCS file: /cvsroot/vim/vim/src/edit.c,v retrieving revision 1.116 diff -c -5 -r1.116 edit.c *** src/edit.c 30 May 2004 21:41:27 -0000 1.116 --- src/edit.c 8 Jun 2004 08:53:28 -0000 *************** *** 593,602 **** --- 593,606 ---- #ifdef FEAT_SCROLLBIND if (curwin->w_p_scb) 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 old_topfill = curwin->w_topfill; #endif *************** *** 6998,7007 **** --- 7002,7014 ---- static void 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 int old_topfill = curwin->w_topfill; #endif *************** *** 7020,7029 **** --- 7027,7043 ---- redraw_later(VALID); 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 vim_beep(); } *************** *** 7047,7056 **** --- 7061,7074 ---- static void 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 int old_topfill = curwin->w_topfill; #endif *************** *** 7069,7078 **** --- 7087,7106 ---- redraw_later(VALID); 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 vim_beep(); } Index: src/eval.c =================================================================== RCS file: /cvsroot/vim/vim/src/eval.c,v retrieving revision 1.159 diff -c -5 -r1.159 eval.c *** src/eval.c 26 May 2004 15:26:02 -0000 1.159 --- src/eval.c 8 Jun 2004 08:53:30 -0000 *************** *** 1585,1594 **** --- 1585,1599 ---- && widx < curwin->w_vars.ga_len) /* skip */; if (name != NULL) return cat_prefix_varname('w', name); } + if (widx < curwin->w_vars.ga_len) + { + ++widx; + return (char_u *)"w:ownsyntax"; + } if (vidx < VV_LEN) /* Built-in variables */ return cat_prefix_varname('v', (char_u *)vimvars[vidx++].name); vim_free(varnamebuf); varnamebuf = NULL; *************** *** 4777,4792 **** --- 4782,4803 ---- "cmdline_hist", #endif #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 DEBUG "debug", #endif #ifdef FEAT_CON_DIALOG "dialog_con", *************** *** 5149,5159 **** n = gui.in_use; /* gui_mch_browse() works when GUI is running */ # endif #endif #ifdef FEAT_SYN_HL else if (STRICMP(name, "syntax_items") == 0) ! n = syntax_present(curbuf); #endif #if defined(WIN3264) else if (STRICMP(name, "win95") == 0) n = mch_windows95(); #endif --- 5160,5170 ---- n = gui.in_use; /* gui_mch_browse() works when GUI is running */ # endif #endif #ifdef FEAT_SYN_HL else if (STRICMP(name, "syntax_items") == 0) ! n = syntax_present(curwin); #endif #if defined(WIN3264) else if (STRICMP(name, "win95") == 0) n = mch_windows95(); #endif *************** *** 8046,8055 **** --- 8057,8076 ---- { type = VAR_NUMBER; number = curbuf->b_changedtick; } + if (STRCMP(name, "w:ownsyntax") == 0) + { + type = VAR_NUMBER; + #ifdef FEAT_SYN_HL + number = (curwin->w_s != &curwin->w_buffer->s) ? 1 : 0; + #else + number = 0; + #endif + } + /* * Check for built-in v: variables. */ else if ((i = find_vim_var(name, len)) >= 0) { Index: src/ex_cmds.c =================================================================== RCS file: /cvsroot/vim/vim/src/ex_cmds.c,v retrieving revision 1.128 diff -c -5 -r1.128 ex_cmds.c *** src/ex_cmds.c 7 Jun 2004 17:15:09 -0000 1.128 --- src/ex_cmds.c 8 Jun 2004 08:53:31 -0000 *************** *** 2800,2809 **** --- 2800,2817 ---- if (buf == curbuf) /* already in new buffer */ auto_buf = TRUE; else #endif { + #ifdef FEAT_SYN_HL + /* + * We could instead free the synblock + * and re-attach to buffer, perhaps. + */ + if (curwin->w_s == &(curwin->w_buffer->s)) + curwin->w_s = &(buf->s); + #endif curwin->w_buffer = buf; curbuf = buf; ++curbuf->b_nwindows; /* set 'fileformat' */ if (*p_ffs && !oldbuf) *************** *** 5005,5015 **** /* set filetype to "help". */ set_option_value((char_u *)"ft", 0L, (char_u *)"help", OPT_LOCAL); #ifdef FEAT_SYN_HL ! if (!syntax_present(curbuf)) #endif { for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum) { line = ml_get_buf(curbuf, lnum, FALSE); --- 5013,5023 ---- /* set filetype to "help". */ set_option_value((char_u *)"ft", 0L, (char_u *)"help", OPT_LOCAL); #ifdef FEAT_SYN_HL ! if (!syntax_present(curwin)) #endif { for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum) { line = ml_get_buf(curbuf, lnum, FALSE); Index: src/ex_cmds.h =================================================================== RCS file: /cvsroot/vim/vim/src/ex_cmds.h,v retrieving revision 1.59 diff -c -5 -r1.59 ex_cmds.h *** src/ex_cmds.h 31 Mar 2004 04:07:23 -0000 1.59 --- src/ex_cmds.h 8 Jun 2004 08:53:31 -0000 *************** *** 560,569 **** --- 560,571 ---- TRLBAR), 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|TRLBAR|CMDWIN), EX(CMD_pclose, "pclose", ex_pclose, BANG|TRLBAR), EX(CMD_perl, "perl", ex_perl, Index: src/ex_cmds2.c =================================================================== RCS file: /cvsroot/vim/vim/src/ex_cmds2.c,v retrieving revision 1.84 diff -c -5 -r1.84 ex_cmds2.c *** src/ex_cmds2.c 30 May 2004 21:37:07 -0000 1.84 --- src/ex_cmds2.c 8 Jun 2004 08:53:33 -0000 *************** *** 3357,3367 **** if (t_colors > 1) settings.modec = 'c'; else settings.modec = 't'; ! if (!syntax_present(curbuf)) settings.do_syntax = FALSE; else if (printer_opts[OPT_PRINT_SYNTAX].present && TOLOWER_ASC(printer_opts[OPT_PRINT_SYNTAX].string[0]) != 'a') settings.do_syntax = (TOLOWER_ASC(printer_opts[OPT_PRINT_SYNTAX].string[0]) == 'y'); --- 3357,3367 ---- if (t_colors > 1) settings.modec = 'c'; else settings.modec = 't'; ! 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') settings.do_syntax = (TOLOWER_ASC(printer_opts[OPT_PRINT_SYNTAX].string[0]) == 'y'); Index: src/ex_docmd.c =================================================================== RCS file: /cvsroot/vim/vim/src/ex_docmd.c,v retrieving revision 1.164 diff -c -5 -r1.164 ex_docmd.c *** src/ex_docmd.c 30 May 2004 21:31:22 -0000 1.164 --- src/ex_docmd.c 8 Jun 2004 08:53:35 -0000 *************** *** 217,226 **** --- 217,227 ---- # define do_scscope ex_ni # define do_cstag ex_ni #endif #ifndef FEAT_SYN_HL # define ex_syntax ex_ni + # define ex_ownsyntax ex_ni #endif #ifndef FEAT_PERL # define ex_perl ex_script_ni # define ex_perldo ex_ni #endif Index: src/feature.h =================================================================== RCS file: /cvsroot/vim/vim/src/feature.h,v retrieving revision 1.60 diff -c -5 -r1.60 feature.h *** src/feature.h 8 May 2004 00:02:51 -0000 1.60 --- src/feature.h 8 Jun 2004 08:53:35 -0000 *************** *** 486,495 **** --- 486,503 ---- #if defined(FEAT_NORMAL) || defined(PROTO) # 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 + + /* * +builtin_terms Choose one out of the following four: * * NO_BUILTIN_TCAPS Do not include any builtin termcap entries (used only * with HAVE_TGETENT defined). * *************** *** 667,676 **** --- 675,691 ---- #if defined(FEAT_NORMAL) && defined(FEAT_WINDOWS) # define FEAT_SCROLLBIND #endif /* + * +cursorbind synchronization of split windows + */ + #if defined(FEAT_NORMAL) && defined(FEAT_WINDOWS) + # define FEAT_CURSORBIND + #endif + + /* * +menu ":menu" command */ #ifdef FEAT_NORMAL # define FEAT_MENU # ifdef FEAT_GUI_W32 *************** *** 911,921 **** /* * MODIFIED_BY Name of who modified Vim. Required when distributing * a modifed version of Vim. * Also from the "--with-modified-by" configure argument. */ ! /* #define MODIFIED_BY "John Doe" */ /* * Machine dependent: * ================== */ --- 926,936 ---- /* * MODIFIED_BY Name of who modified Vim. Required when distributing * a modifed version of Vim. * Also from the "--with-modified-by" configure argument. */ ! #define MODIFIED_BY "Vince Negri ['conceal', 'cursorbind', :ownsyntax]" /* * Machine dependent: * ================== */ Index: src/globals.h =================================================================== RCS file: /cvsroot/vim/vim/src/globals.h,v retrieving revision 1.93 diff -c -5 -r1.93 globals.h *** src/globals.h 16 May 2004 18:34:18 -0000 1.93 --- src/globals.h 8 Jun 2004 08:53:35 -0000 *************** *** 1001,1010 **** --- 1001,1013 ---- EXTERN int lcs_ext INIT(= NUL); EXTERN int lcs_prec 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) /* Characters from 'fillchars' option */ EXTERN int fill_stl INIT(= ' '); Index: src/move.c =================================================================== RCS file: /cvsroot/vim/vim/src/move.c,v retrieving revision 1.33 diff -c -5 -r1.33 move.c *** src/move.c 4 Mar 2004 03:46:36 -0000 1.33 --- src/move.c 8 Jun 2004 08:53:36 -0000 *************** *** 2792,2796 **** --- 2792,2861 ---- #endif cursor_correct(); beginline(BL_SOL | BL_FIX); redraw_later(VALID); } + + #ifdef FEAT_CURSORBIND + 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 /* #ifdef FEAT_CURSORBIND */ Index: src/normal.c =================================================================== RCS file: /cvsroot/vim/vim/src/normal.c,v retrieving revision 1.153 diff -c -5 -r1.153 normal.c *** src/normal.c 5 Jun 2004 15:23:35 -0000 1.153 --- src/normal.c 8 Jun 2004 08:53:38 -0000 *************** *** 1244,1253 **** --- 1244,1261 ---- validate_cursor(); /* may need to update w_leftcol */ do_check_scrollbind(TRUE); } #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). * May switch from Visual to Select mode after CTRL-O command. */ *************** *** 2147,2156 **** --- 2155,2167 ---- int diff; int old_active = VIsual_active; 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; #endif *************** *** 2543,2552 **** --- 2554,2573 ---- /* don't move the cursor if still in the same window */ if (curwin == old_curwin) curwin->w_cursor = save_cursor; } #endif + #ifdef FEAT_CONCEAL + if (curwin->w_p_conceal) + if (moved) + if ((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) { clip_modeless(which_button, is_click, is_drag); *************** *** 4827,4837 **** */ ui_get_shellsize(); #endif #ifdef FEAT_SYN_HL /* Clear all syntax states to force resyncing. */ ! syn_stack_free_all(curbuf); #endif redraw_later(CLEAR); } } --- 4848,4858 ---- */ ui_get_shellsize(); #endif #ifdef FEAT_SYN_HL /* Clear all syntax states to force resyncing. */ ! syn_stack_free_all(curwin->w_s); #endif redraw_later(CLEAR); } } *************** *** 5407,5431 **** --- 5428,5466 ---- */ static void nv_up(cap) cmdarg_T *cap; { + #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 } /* * Cursor down commands. * cap->arg is TRUE for CR and "+": Move cursor to first non-blank. */ static void nv_down(cap) cmdarg_T *cap; { + #ifdef FEAT_CONCEAL + linenr_T oldline = curwin->w_cursor.lnum; + linenr_T oldbotline = curwin->w_botline; + #endif #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX) /* In a quickfix window a jumps to the error under the cursor. */ if (bt_quickfix(curbuf) && cap->cmdchar == '\r') do_cmdline_cmd((char_u *)".cc"); else *************** *** 5441,5450 **** --- 5476,5495 ---- cap->oap->motion_type = MLINE; if (cursor_down(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); + /* 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 } } } #ifdef FEAT_SEARCHPATH *************** *** 7525,7534 **** --- 7570,7582 ---- */ static void n_opencmd(cap) cmdarg_T *cap; { + #ifdef FEAT_CONCEAL + linenr_T oldline = curwin->w_cursor.lnum; + #endif if (!checkclearopq(cap->oap)) { #ifdef FEAT_FOLDING if (cap->cmdchar == 'O') /* Open above the first line of a folded sequence of lines */ *************** *** 7548,7557 **** --- 7596,7611 ---- #ifdef FEAT_COMMENTS has_format_option(FO_OPEN_COMS) ? OPENLINE_DO_COM : #endif 0, 0)) { + #ifdef FEAT_CONCEAL + if ((curwin->w_p_conceal) && (oldline != curwin->w_cursor.lnum)) + { + update_single_line(curwin, oldline); + } + #endif invoke_edit(cap, FALSE, cap->cmdchar, TRUE); } } } *************** *** 7944,7953 **** --- 7998,8011 ---- beginline(BL_SOL | BL_FIX); #ifdef FEAT_FOLDING 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 } /* * CTRL-\ in Normal mode. */ *************** *** 8355,8364 **** --- 8413,8425 ---- { #ifdef FEAT_VISUAL int regname = 0; void *reg1 = NULL, *reg2 = NULL; #endif + #ifdef FEAT_CONCEAL + linenr_T oldline = curwin->w_cursor.lnum; + #endif int dir; int flags = 0; if (cap->oap->op_type != OP_NOP) { *************** *** 8449,8458 **** --- 8510,8526 ---- /* If a register was saved, put it back now. */ if (reg2 != NULL) put_register(regname, reg2); #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 } } /* * "o" and "O" commands. Index: src/option.c =================================================================== RCS file: /cvsroot/vim/vim/src/option.c,v retrieving revision 1.135 diff -c -5 -r1.135 option.c *** src/option.c 15 May 2004 15:01:09 -0000 1.135 --- src/option.c 8 Jun 2004 08:53:40 -0000 *************** *** 59,69 **** --- 59,71 ---- , PV_CINK , PV_CINO , PV_CINW , PV_CMS , PV_COM + , PV_CONCEAL , PV_CPT + , PV_CRBIND , PV_DEF , PV_DICT , PV_DIFF , PV_EFM , PV_EOL *************** *** 622,631 **** --- 624,640 ---- #else (char_u *)NULL, PV_NONE, {(char_u *)0L, (char_u *)0L} #endif }, + {"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}}, {"confirm", "cf", P_BOOL|P_VI_DEF, #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) (char_u *)&p_confirm, PV_NONE, #else (char_u *)NULL, PV_NONE, *************** *** 688,697 **** --- 697,713 ---- (char_u *)&p_csverbose, PV_NONE, #else (char_u *)NULL, PV_NONE, #endif {(char_u *)0L, (char_u *)0L}}, + {"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}}, {"debug", NULL, P_STRING|P_VI_DEF, (char_u *)&p_debug, PV_NONE, {(char_u *)"", (char_u *)0L}}, {"define", "def", P_STRING|P_ALLOCED|P_VI_DEF, #ifdef FEAT_FIND_ID *************** *** 1070,1080 **** --- 1086,1100 ---- {"hidden", "hid", P_BOOL|P_VI_DEF, (char_u *)&p_hid, PV_NONE, {(char_u *)FALSE, (char_u *)0L}}, {"highlight", "hl", P_STRING|P_VI_DEF|P_RCLR|P_COMMA|P_NODUP, (char_u *)&p_hl, PV_NONE, + #ifdef FEAT_CONCEAL + {(char_u *)"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,x:Conceal", + #else {(char_u *)"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", + #endif (char_u *)0L}}, {"history", "hi", P_NUM|P_VIM, (char_u *)&p_hi, PV_NONE, {(char_u *)0L, (char_u *)20L}}, {"hkmap", "hk", P_BOOL|P_VI_DEF|P_VIM, *************** *** 5794,5803 **** --- 5814,5826 ---- {&lcs_eol, "eol"}, {&lcs_ext, "extends"}, {&lcs_prec, "precedes"}, {&lcs_tab2, "tab"}, {&lcs_trail, "trail"}, + /*#ifdef FEAT_CONCEAL*/ + {&lcs_conceal, "conceal"}, + /*#endif*/ }; struct charstab *tab; #if defined(FEAT_WINDOWS) || defined(FEAT_FOLDING) if (varp == &p_lcs) *************** *** 6764,6773 **** --- 6787,6811 ---- p_uc = 100; } 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 /* sync undo before 'undolevels' changes */ else if (pp == &p_ul) { /* use the old value, otherwise u_sync() may not work properly */ *************** *** 7840,7849 **** --- 7878,7893 ---- case PV_LBR: return (char_u *)&(curwin->w_p_lbr); #endif #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); #ifdef FEAT_MBYTE case PV_BOMB: return (char_u *)&(curbuf->b_p_bomb); Index: src/screen.c =================================================================== RCS file: /cvsroot/vim/vim/src/screen.c,v retrieving revision 1.133 diff -c -5 -r1.133 screen.c *** src/screen.c 4 Jun 2004 19:29:21 -0000 1.133 --- src/screen.c 8 Jun 2004 08:53:42 -0000 *************** *** 187,196 **** --- 187,200 ---- #if defined(FEAT_CLIPBOARD) || defined(FEAT_VERTSPLIT) /* Ugly global: overrule attribute used by screen_char() */ static int screen_char_attr = 0; #endif + #ifdef FEAT_CONCEAL + extern char_u current_sub_char; + #endif + /* * Redraw the current window later, with update_screen(type). * Set must_redraw only if not already set to a higher value. * e.g. if must_redraw is CLEAR, type NOT_VALID will do nothing. */ *************** *** 457,467 **** # endif if ( # ifdef FEAT_WINDOWS wwp == wp && # endif ! syntax_present(wp->w_buffer)) syn_stack_apply_changes(wp->w_buffer); } } #endif --- 461,471 ---- # endif if ( # ifdef FEAT_WINDOWS wwp == wp && # endif ! syntax_present(wp)) syn_stack_apply_changes(wp->w_buffer); } } #endif *************** *** 557,566 **** --- 561,619 ---- gui_update_scrollbars(FALSE); } #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); + #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)); /* *************** *** 850,862 **** { mod_top = buf->b_mod_top; #ifdef FEAT_SYN_HL /* Need to redraw lines above the change that may be included * in a pattern match. */ ! if (syntax_present(buf)) { ! mod_top -= buf->b_syn_sync_linebreaks; if (mod_top < 1) mod_top = 1; } #endif } --- 903,915 ---- { mod_top = buf->b_mod_top; #ifdef FEAT_SYN_HL /* Need to redraw lines above the change that may be included * in a pattern match. */ ! if (syntax_present(wp)) { ! mod_top -= buf->s.b_syn_sync_linebreaks; if (mod_top < 1) mod_top = 1; } #endif } *************** *** 931,941 **** if (mod_top != 0 && mod_top < wp->w_topline) { if (mod_bot > wp->w_topline) mod_top = wp->w_topline; #ifdef FEAT_SYN_HL ! else if (syntax_present(buf)) top_end = 1; #endif } } --- 984,994 ---- if (mod_top != 0 && mod_top < wp->w_topline) { if (mod_bot > wp->w_topline) mod_top = wp->w_topline; #ifdef FEAT_SYN_HL ! else if (syntax_present(wp)) top_end = 1; #endif } } *************** *** 1424,1434 **** || (lnum >= mod_top && (lnum < mod_bot #ifdef FEAT_SYN_HL || did_update == DID_FOLD || (did_update == DID_LINE ! && syntax_present(buf) && ( # ifdef FEAT_FOLDING (foldmethodIsSyntax(wp) && hasAnyFolding(wp)) || # endif --- 1477,1487 ---- || (lnum >= mod_top && (lnum < mod_bot #ifdef FEAT_SYN_HL || did_update == DID_FOLD || (did_update == DID_LINE ! && syntax_present(wp) && ( # ifdef FEAT_FOLDING (foldmethodIsSyntax(wp) && hasAnyFolding(wp)) || # endif *************** *** 1656,1666 **** prepare_search_hl(wp, lnum); #endif #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_end_parsing(syntax_last_parsed + 1); #endif /* * Display one line. --- 1709,1719 ---- prepare_search_hl(wp, lnum); #endif #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(wp)) syntax_end_parsing(syntax_last_parsed + 1); #endif /* * Display one line. *************** *** 1728,1738 **** #ifdef FEAT_SYN_HL /* * Let the syntax stuff know we stop parsing here. */ ! if (syntax_last_parsed != 0 && syntax_present(buf)) syntax_end_parsing(syntax_last_parsed + 1); #endif /* * If we didn't hit the end of the file, and we didn't finish the last --- 1781,1791 ---- #ifdef FEAT_SYN_HL /* * Let the syntax stuff know we stop parsing here. */ ! if (syntax_last_parsed != 0 && syntax_present(wp)) syntax_end_parsing(syntax_last_parsed + 1); #endif /* * If we didn't hit the end of the file, and we didn't finish the last *************** *** 2597,2606 **** --- 2650,2667 ---- #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK) int feedback_col = 0; int feedback_old_attr = -1; #endif + int syntax_flags = 0; + #ifdef FEAT_CONCEAL + 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; row = startrow; *************** *** 2614,2632 **** extra_check = wp->w_p_lbr; #else extra_check = 0; #endif #ifdef FEAT_SYN_HL ! if (syntax_present(wp->w_buffer)) { /* Prepare for syntax highlighting in this line. When there is an * error, stop syntax highlighting. */ save_did_emsg = did_emsg; did_emsg = FALSE; syntax_start(wp, lnum); if (did_emsg) ! syntax_clear(wp->w_buffer); else { did_emsg = save_did_emsg; has_syntax = TRUE; extra_check = TRUE; --- 2675,2693 ---- extra_check = wp->w_p_lbr; #else extra_check = 0; #endif #ifdef FEAT_SYN_HL ! if (syntax_present(wp)) { /* Prepare for syntax highlighting in this line. When there is an * error, stop syntax highlighting. */ save_did_emsg = did_emsg; did_emsg = FALSE; syntax_start(wp, lnum); if (did_emsg) ! syntax_clear(wp->w_s); else { did_emsg = save_did_emsg; has_syntax = TRUE; extra_check = TRUE; *************** *** 3559,3572 **** /* Get the syntax attribute for the character. If there * is an error, disable syntax highlighting. */ save_did_emsg = did_emsg; did_emsg = FALSE; ! syntax_attr = get_syntax_attr((colnr_T)v - 1); if (did_emsg) ! syntax_clear(wp->w_buffer); else did_emsg = save_did_emsg; /* Need to get the line again, a multi-line regexp may * have made it invalid. */ --- 3620,3633 ---- /* Get the syntax attribute for the character. If there * is an error, disable syntax highlighting. */ save_did_emsg = did_emsg; did_emsg = FALSE; ! syntax_attr = get_syntax_attr((colnr_T)v - 1, &syntax_flags); if (did_emsg) ! syntax_clear(wp->w_s); else did_emsg = save_did_emsg; /* Need to get the line again, a multi-line regexp may * have made it invalid. */ *************** *** 3774,3783 **** --- 3835,3905 ---- } # endif } #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 + && (current_sub_char != NUL || wp->w_p_conceal == 1)) + { + if (current_sub_char != NUL) + c = current_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_utf8 = FALSE; /* don't draw as UTF-8 */ + #endif + } + else + { + first_conceal = (wp->w_p_conceal != 3); + is_concealing = FALSE; + } + #endif } /* Don't override visual selection highlighting. */ if (n_attr > 0 && draw_state == WL_LINE *************** *** 3920,3931 **** --- 4042,4059 ---- else #endif ++col; } + #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++; /* * Update w_cline_height and w_cline_folded if the cursor line was * updated (saves a call to plines() later). *************** *** 4052,4061 **** --- 4180,4281 ---- { ++off; ++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 else --n_skip; /* Only advance the "vcol" when after the 'number' column. */ if (draw_state >= WL_SBR *************** *** 4088,4099 **** --- 4308,4325 ---- #endif || (wp->w_p_list && lcs_eol != NUL && p_extra != at_end_str) || (n_extra != 0 && (c_extra != NUL || *p_extra != NUL))) ) { + #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; /* When not wrapping and finished diff lines, or when displayed * '$' and highlighting until last column, break here. */ Index: src/structs.h =================================================================== RCS file: /cvsroot/vim/vim/src/structs.h,v retrieving revision 1.84 diff -c -5 -r1.84 structs.h *** src/structs.h 2 Jun 2004 15:46:54 -0000 1.84 --- src/structs.h 8 Jun 2004 08:53:42 -0000 *************** *** 189,198 **** --- 189,206 ---- int wo_scb; # define w_p_scb w_onebuf_opt.wo_scb /* 'scrollbind' */ #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 } winopt_T; /* * Window info stored with a buffer. * *************** *** 683,693 **** struct keyentry { keyentry_T *next; /* next keyword in the hash list */ 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 */ char_u keyword[1]; /* actually longer */ }; /* * Struct used to store one state of the state stack. --- 691,702 ---- struct keyentry { keyentry_T *next; /* next keyword in the hash list */ struct sp_syn k_syn; /* struct passed to in_id_list() */ short *next_list; /* ID list for next match (if non-zero) */ ! long flags; ! char_u k_char; char_u keyword[1]; /* actually longer */ }; /* * Struct used to store one state of the state stack. *************** *** 876,885 **** --- 885,947 ---- { char_u *start; int userhl; }; + + /* + * Syntax items - usually buffer-specific. + */ + #ifdef FEAT_SYN_HL + typedef struct { + keyentry_T **b_keywtab; /* syntax keywords hash table */ + keyentry_T **b_keywtab_ic; /* idem, ignore case */ + int b_syn_ic; /* ignore case for :syn cmds */ + garray_T b_syn_patterns; /* table for syntax patterns */ + garray_T b_syn_clusters; /* table for syntax clusters */ + 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 */ + } synblock_T; + #endif /* FEAT_SYN_HL */ + /* * buffer: structure that holds information about one file * * Several windows can share a single Buffer * A buffer is unallocated if there is no memfile for it. *************** *** 1214,1265 **** #ifdef FEAT_RUBY void *ruby_ref; #endif #ifdef FEAT_SYN_HL ! keyentry_T **b_keywtab; /* syntax keywords hash table */ ! keyentry_T **b_keywtab_ic; /* idem, ignore case */ ! int b_syn_ic; /* ignore case for :syn cmds */ ! garray_T b_syn_patterns; /* table for syntax patterns */ ! garray_T b_syn_clusters; /* table for syntax clusters */ ! 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_SIGNS signlist_T *b_signlist; /* list of signs to draw */ #endif --- 1276,1287 ---- #ifdef FEAT_RUBY void *ruby_ref; #endif #ifdef FEAT_SYN_HL ! synblock_T s; ! #endif #ifdef FEAT_SIGNS signlist_T *b_signlist; /* list of signs to draw */ #endif *************** *** 1267,1277 **** int b_netbeans_file; /* TRUE when buffer is owned by NetBeans */ int b_was_netbeans_file;/* TRUE if b_netbeans_file was once set */ #endif }; - /* * Structure to cache info for displayed lines in w_lines[]. * Each logical line has one entry. * The entry tells how the logical line is currently displayed in the window. * This is updated when displaying the window. --- 1289,1298 ---- *************** *** 1327,1336 **** --- 1348,1361 ---- struct window { buf_T *w_buffer; /* buffer we are a window into (used often, keep it the first item!) */ + #ifdef FEAT_SYN_HL + synblock_T *w_s; + #endif + #ifdef FEAT_WINDOWS win_T *w_prev; /* link to previous window */ win_T *w_next; /* link to next window */ #endif Index: src/syntax.c =================================================================== RCS file: /cvsroot/vim/vim/src/syntax.c,v retrieving revision 1.86 diff -c -5 -r1.86 syntax.c *** src/syntax.c 8 May 2004 00:03:11 -0000 1.86 --- src/syntax.c 8 Jun 2004 08:53:44 -0000 *************** *** 130,140 **** */ 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 */ 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 */ regprog_T *sp_prog; /* regexp to match, program */ int sp_ic; /* ignore-case flag for sp_prog */ --- 130,143 ---- */ typedef struct syn_pattern { char sp_type; /* see SPTYPE_ defines below */ char sp_syncing; /* this item used for syncing */ ! long sp_flags; /* see HL_ defines below */ ! #ifdef FEAT_CONCEAL ! char_u sp_char; ! #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 */ regprog_T *sp_prog; /* regexp to match, program */ int sp_ic; /* ignore-case flag for sp_prog */ *************** *** 156,184 **** #define SPTYPE_MATCH 1 /* match keyword with this group ID */ #define SPTYPE_START 2 /* match a regexp, start of item */ #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)) #define NONE_IDX -2 /* value of sp_sync_idx for "NONE" */ --- 159,168 ---- *************** *** 204,213 **** --- 188,201 ---- static int current_attr = 0; /* attr of current syntax word */ #ifdef FEAT_EVAL static int current_id = 0; /* ID of current char for syn_get_id() */ static int current_trans_id = 0; /* idem, transparancy removed */ #endif + #ifdef FEAT_CONCEAL + static int current_flags = 0; + char_u current_sub_char; + #endif struct syn_cluster { char_u *scl_name; /* syntax cluster name */ char_u *scl_name_u; /* uppercase of scl_name */ *************** *** 277,286 **** --- 265,277 ---- int si_end_idx; /* group ID for end pattern or zero */ int si_ends; /* if match ends before si_m_endpos */ 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 + char_u si_char; + #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 * pattern */ } stateitem_T; *************** *** 318,327 **** --- 309,319 ---- * The current state (within the line) of the recognition engine. * When current_state.ga_itemsize is 0 the current state is invalid. */ static win_T *syn_win; /* current window for highlighting */ static buf_T *syn_buf; /* current buffer for highlighting */ + static synblock_T *syn_buf2; /* 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 * after setting current_finished */ static int current_finished = 0; /* current line has been finished */ *************** *** 337,347 **** static int syn_match_linecont __ARGS((linenr_T lnum)); 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 synstate_T *syn_stack_find_entry __ARGS((linenr_T lnum)); static synstate_T *store_current_state __ARGS((synstate_T *sp)); static void load_current_state __ARGS((synstate_T *from)); static void invalidate_current_state __ARGS((void)); static int syn_stack_equal __ARGS((synstate_T *sp)); --- 329,339 ---- static int syn_match_linecont __ARGS((linenr_T lnum)); 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((synblock_T *block, synstate_T *p)); static synstate_T *syn_stack_find_entry __ARGS((linenr_T lnum)); static synstate_T *store_current_state __ARGS((synstate_T *sp)); static void load_current_state __ARGS((synstate_T *from)); static void invalidate_current_state __ARGS((void)); static int syn_stack_equal __ARGS((synstate_T *sp)); *************** *** 357,404 **** static short *copy_id_list __ARGS((short *list)); static int in_id_list __ARGS((stateitem_T *item, short *cont_list, struct sp_syn *ssp, int contained)); static int push_current_state __ARGS((int idx)); static void pop_current_state __ARGS((void)); 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)); static void limit_pos __ARGS((lpos_T *pos, lpos_T *limit)); static void limit_pos_zero __ARGS((lpos_T *pos, lpos_T *limit)); static void syn_add_end_off __ARGS((lpos_T *result, regmmatch_T *regmatch, synpat_T *spp, int idx, int extra)); 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 void syn_cmd_case __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_cmd_clear __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)); static void syn_cmd_reset __ARGS((exarg_T *eap, int syncing)); static void syn_cmd_manual __ARGS((exarg_T *eap, int syncing)); static void syn_cmd_off __ARGS((exarg_T *eap, int syncing)); 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_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)); static void put_pattern __ARGS((char *s, int c, synpat_T *spp, int attr)); static int syn_list_keywords __ARGS((int id, keyentry_T **ktabp, int did_header, int attr)); static void syn_clear_keyword __ARGS((int id, keyentry_T **ktabp)); static void free_keywtab __ARGS((keyentry_T **ktabp)); ! static void add_keyword __ARGS((char_u *name, int id, int flags, short *cont_in_list, short *next_list)); static int syn_khash __ARGS((char_u *p)); static char_u *get_group_name __ARGS((char_u *arg, char_u **name_end)); ! static char_u *get_syn_options __ARGS((char_u *arg, int *flagsp, int keyword, int *sync_idx, short **cont_list, short **cont_in_list, short **next_list)); 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)); static void syn_cmd_region __ARGS((exarg_T *eap, int syncing)); #ifdef __BORLANDC__ --- 349,399 ---- static short *copy_id_list __ARGS((short *list)); static int in_id_list __ARGS((stateitem_T *item, short *cont_list, struct sp_syn *ssp, int contained)); 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)); static void limit_pos __ARGS((lpos_T *pos, lpos_T *limit)); static void limit_pos_zero __ARGS((lpos_T *pos, lpos_T *limit)); static void syn_add_end_off __ARGS((lpos_T *result, regmmatch_T *regmatch, synpat_T *spp, int idx, int extra)); 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, char_u *ccharp)); static void syn_cmd_case __ARGS((exarg_T *eap, int syncing)); static void syntax_sync_clear __ARGS((void)); ! 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)); static void syn_cmd_reset __ARGS((exarg_T *eap, int syncing)); static void syn_cmd_manual __ARGS((exarg_T *eap, int syncing)); static void syn_cmd_off __ARGS((exarg_T *eap, int syncing)); 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)); static void put_pattern __ARGS((char *s, int c, synpat_T *spp, int attr)); static int syn_list_keywords __ARGS((int id, keyentry_T **ktabp, int did_header, int attr)); static void syn_clear_keyword __ARGS((int id, keyentry_T **ktabp)); static void free_keywtab __ARGS((keyentry_T **ktabp)); ! static void add_keyword __ARGS((char_u *name, int id, int flags, short *cont_in_list, short *next_list, char_u conceal_char)); static int syn_khash __ARGS((char_u *p)); static char_u *get_group_name __ARGS((char_u *arg, char_u **name_end)); ! static char_u *get_syn_options __ARGS((char_u *arg, int *flagsp, int keyword, int *sync_idx, short **cont_list, short **cont_in_list, short **next_list, char_u *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)); static void syn_cmd_region __ARGS((exarg_T *eap, int syncing)); #ifdef __BORLANDC__ *************** *** 441,464 **** reg_syn = TRUE; /* let vim_regexec() know we're using syntax */ /* * After switching buffers, invalidate current_state. */ ! if (syn_buf != wp->w_buffer) { invalidate_current_state(); syn_buf = wp->w_buffer; } syn_win = wp; /* * Allocate syntax stack when needed. */ syn_stack_alloc(); ! if (syn_buf->b_sst_array == NULL) goto theend; /* out of memory */ ! syn_buf->b_sst_lasttick = display_tick; /* * If the state of the end of the previous line is useful, store it. */ if (VALID_STATE(¤t_state) --- 436,460 ---- reg_syn = TRUE; /* let vim_regexec() know we're using syntax */ /* * After switching buffers, invalidate current_state. */ ! if (syn_buf2 != wp->w_s) { invalidate_current_state(); syn_buf = wp->w_buffer; + syn_buf2 = wp->w_s; } syn_win = wp; /* * Allocate syntax stack when needed. */ syn_stack_alloc(); ! if (syn_buf2->b_sst_array == NULL) goto theend; /* out of memory */ ! syn_buf2->b_sst_lasttick = display_tick; /* * If the state of the end of the previous line is useful, store it. */ if (VALID_STATE(¤t_state) *************** *** 485,505 **** /* * Try to synchronize from a saved state in b_sst_array[]. * Only do this if lnum is not before and not to far beyond a saved state. */ ! if (INVALID_STATE(¤t_state) && syn_buf->b_sst_array != NULL) { /* Find last valid saved state before start_lnum. */ ! for (p = syn_buf->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) last_min_valid = p; } } if (last_min_valid != NULL) load_current_state(last_min_valid); --- 481,501 ---- /* * Try to synchronize from a saved state in b_sst_array[]. * Only do this if lnum is not before and not to far beyond a saved state. */ ! if (INVALID_STATE(¤t_state) && syn_buf2->b_sst_array != NULL) { /* Find last valid saved state before start_lnum. */ ! for (p = syn_buf2->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_buf2->b_syn_sync_minlines) last_min_valid = p; } } if (last_min_valid != NULL) load_current_state(last_min_valid); *************** *** 510,529 **** * re-synchronize. */ if (INVALID_STATE(¤t_state)) { syn_sync(wp, lnum, last_valid); ! first_stored = current_lnum + syn_buf->b_syn_sync_minlines; } else first_stored = current_lnum; /* * Advance from the sync point or saved state until the current line. * Save some entries for syncing with later on. */ ! dist = syn_buf->b_ml.ml_line_count / (syn_buf->b_sst_len - Rows) + 1; prev = syn_stack_find_entry(current_lnum); while (current_lnum < lnum) { syn_start_line(); (void)syn_finish_line(FALSE); --- 506,525 ---- * re-synchronize. */ if (INVALID_STATE(¤t_state)) { syn_sync(wp, lnum, last_valid); ! first_stored = current_lnum + syn_buf2->b_syn_sync_minlines; } else first_stored = current_lnum; /* * Advance from the sync point or saved state until the current line. * Save some entries for syncing with later on. */ ! dist = syn_buf->b_ml.ml_line_count / (syn_buf2->b_sst_len - Rows) + 1; prev = syn_stack_find_entry(current_lnum); while (current_lnum < lnum) { syn_start_line(); (void)syn_finish_line(FALSE); *************** *** 535,545 **** { /* Check if the saved state entry is for the current line and is * equal to the current state. If so, then validate all saved * states that depended on a change before the parsed line. */ if (prev == NULL) ! sp = syn_buf->b_sst_first; else sp = prev->sst_next; if (sp != NULL && sp->sst_lnum == current_lnum && syn_stack_equal(sp)) --- 531,541 ---- { /* Check if the saved state entry is for the current line and is * equal to the current state. If so, then validate all saved * states that depended on a change before the parsed line. */ if (prev == NULL) ! sp = syn_buf2->b_sst_first; else sp = prev->sst_next; if (sp != NULL && sp->sst_lnum == current_lnum && syn_stack_equal(sp)) *************** *** 667,700 **** * Start further back, to avoid that scrolling backwards will result in * resyncing for every line. Now it resyncs only one out of N lines, * 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) start_lnum = 1; else { ! if (syn_buf->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 ! 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; if (lnum >= start_lnum) start_lnum = 1; else start_lnum -= lnum; } current_lnum = start_lnum; /* * 1. Search backwards for the end of a C-style comment. */ ! if (syn_buf->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(). */ curwin_save = curwin; curwin = wp; --- 663,696 ---- * Start further back, to avoid that scrolling backwards will result in * resyncing for every line. Now it resyncs only one out of N lines, * where N is minlines * 1.5, or minlines * 2 if minlines is small. * Watch out for overflow when minlines is MAXLNUM. */ ! if (syn_buf2->b_syn_sync_minlines > start_lnum) start_lnum = 1; else { ! if (syn_buf2->b_syn_sync_minlines == 1) lnum = 1; ! else if (syn_buf2->b_syn_sync_minlines < 10) ! lnum = syn_buf2->b_syn_sync_minlines * 2; else ! lnum = syn_buf2->b_syn_sync_minlines * 3 / 2; ! if (syn_buf2->b_syn_sync_maxlines != 0 ! && lnum > syn_buf2->b_syn_sync_maxlines) ! lnum = syn_buf2->b_syn_sync_maxlines; if (lnum >= start_lnum) start_lnum = 1; else start_lnum -= lnum; } current_lnum = start_lnum; /* * 1. Search backwards for the end of a C-style comment. */ ! if (syn_buf2->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(). */ curwin_save = curwin; curwin = wp; *************** *** 720,734 **** /* * If the line is inside a comment, need to find the syntax item that * defines the comment. * Restrict the search for the end of a comment to b_syn_sync_maxlines. */ ! if (find_start_comment((int)syn_buf->b_syn_sync_maxlines) != NULL) { ! for (idx = syn_buf->b_syn_patterns.ga_len; --idx >= 0; ) ! if (SYN_ITEMS(syn_buf)[idx].sp_syn.id == syn_buf->b_syn_sync_id ! && SYN_ITEMS(syn_buf)[idx].sp_type == SPTYPE_START) { validate_current_state(); if (push_current_state(idx) == OK) update_si_attr(current_state.ga_len - 1); break; --- 716,730 ---- /* * If the line is inside a comment, need to find the syntax item that * defines the comment. * Restrict the search for the end of a comment to b_syn_sync_maxlines. */ ! if (find_start_comment((int)syn_buf2->b_syn_sync_maxlines) != NULL) { ! for (idx = syn_buf2->b_syn_patterns.ga_len; --idx >= 0; ) ! if (SYN_ITEMS(syn_buf2)[idx].sp_syn.id == syn_buf2->b_syn_sync_id ! && SYN_ITEMS(syn_buf2)[idx].sp_type == SPTYPE_START) { validate_current_state(); if (push_current_state(idx) == OK) update_si_attr(current_state.ga_len - 1); break; *************** *** 742,756 **** } /* * 2. Search backwards for given sync patterns. */ ! else if (syn_buf->b_syn_sync_flags & SF_MATCH) { ! if (syn_buf->b_syn_sync_maxlines != 0 ! && start_lnum > syn_buf->b_syn_sync_maxlines) ! break_lnum = start_lnum - syn_buf->b_syn_sync_maxlines; else break_lnum = 0; end_lnum = start_lnum; lnum = start_lnum; --- 738,752 ---- } /* * 2. Search backwards for given sync patterns. */ ! else if (syn_buf2->b_syn_sync_flags & SF_MATCH) { ! if (syn_buf2->b_syn_sync_maxlines != 0 ! && start_lnum > syn_buf2->b_syn_sync_maxlines) ! break_lnum = start_lnum - syn_buf2->b_syn_sync_maxlines; else break_lnum = 0; end_lnum = start_lnum; lnum = start_lnum; *************** *** 800,810 **** { /* ignore match that goes to after where started */ current_lnum = end_lnum; break; } ! spp = &(SYN_ITEMS(syn_buf)[cur_si->si_idx]); found_flags = spp->sp_flags; found_match_idx = spp->sp_sync_idx; found_current_lnum = current_lnum; found_current_col = current_col; found_m_endpos = cur_si->si_m_endpos; --- 796,806 ---- { /* ignore match that goes to after where started */ current_lnum = end_lnum; break; } ! spp = &(SYN_ITEMS(syn_buf2)[cur_si->si_idx]); found_flags = spp->sp_flags; found_match_idx = spp->sp_sync_idx; found_current_lnum = current_lnum; found_current_col = current_col; found_m_endpos = cur_si->si_m_endpos; *************** *** 899,912 **** syn_match_linecont(lnum) linenr_T lnum; { regmmatch_T regmatch; ! if (syn_buf->b_syn_linecont_prog != NULL) { ! regmatch.rmm_ic = syn_buf->b_syn_linecont_ic; ! regmatch.regprog = syn_buf->b_syn_linecont_prog; return syn_regexec(®match, lnum, (colnr_T)0); } return FALSE; } --- 895,908 ---- syn_match_linecont(lnum) linenr_T lnum; { regmmatch_T regmatch; ! if (syn_buf2->b_syn_linecont_prog != NULL) { ! regmatch.rmm_ic = syn_buf2->b_syn_linecont_ic; ! regmatch.regprog = syn_buf2->b_syn_linecont_prog; return syn_regexec(®match, lnum, (colnr_T)0); } return FALSE; } *************** *** 948,958 **** * contained region. The match ends as soon as the region ends. */ for (i = 0; i < current_state.ga_len; ++i) { cur_si = &CUR_STATE(i); if (cur_si->si_idx >= 0 ! && (SYN_ITEMS(syn_buf)[cur_si->si_idx]).sp_type == SPTYPE_MATCH && cur_si->si_m_endpos.lnum < current_lnum) { cur_si->si_flags |= HL_MATCHCONT; cur_si->si_m_endpos.lnum = 0; --- 944,954 ---- * contained region. The match ends as soon as the region ends. */ for (i = 0; i < current_state.ga_len; ++i) { cur_si = &CUR_STATE(i); if (cur_si->si_idx >= 0 ! && (SYN_ITEMS(syn_buf2)[cur_si->si_idx]).sp_type == SPTYPE_MATCH && cur_si->si_m_endpos.lnum < current_lnum) { cur_si->si_flags |= HL_MATCHCONT; cur_si->si_m_endpos.lnum = 0; *************** *** 1025,1058 **** * entries depends on the number of lines in the buffer. For small buffers * the distance is fixed at SST_DIST, for large buffers there is a fixed * number of entries SST_MAX_ENTRIES, and the distance is computed. */ /* * Free b_sst_array[] for buffer "buf". * Used when syntax items changed to force resyncing everywhere. */ void ! syn_stack_free_all(buf) ! buf_T *buf; { - synstate_T *p; 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; ! } #ifdef FEAT_FOLDING /* When using "syntax" fold method, must update all folds. */ FOR_ALL_WINDOWS(wp) { ! if (wp->w_buffer == buf && foldmethodIsSyntax(wp)) foldUpdateAll(wp); } #endif } --- 1021,1063 ---- * entries depends on the number of lines in the buffer. For small buffers * the distance is fixed at SST_DIST, for large buffers there is a fixed * 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(block) ! synblock_T *block; { win_T *wp; ! syn_stack_free_block(block); ! ! #ifdef FEAT_FOLDING /* When using "syntax" fold method, must update all folds. */ FOR_ALL_WINDOWS(wp) { ! if (wp->w_s == block && foldmethodIsSyntax(wp)) foldUpdateAll(wp); } #endif } *************** *** 1072,1139 **** len = syn_buf->b_ml.ml_line_count / SST_DIST + Rows * 2; if (len < SST_MIN_ENTRIES) 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) { /* Allocate 50% too much, to avoid reallocating too often. */ len = syn_buf->b_ml.ml_line_count; len = (len + len / 2) / SST_DIST + Rows * 2; if (len < SST_MIN_ENTRIES) len = SST_MIN_ENTRIES; else if (len > SST_MAX_ENTRIES) len = SST_MAX_ENTRIES; ! if (syn_buf->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 && 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; } sstp = (synstate_T *)alloc_clear((unsigned)(len * sizeof(synstate_T))); if (sstp == NULL) /* out of memory! */ return; to = sstp - 1; ! if (syn_buf->b_sst_array != NULL) { /* Move the states from the old array to the new one. */ ! for (from = syn_buf->b_sst_first; from != NULL; from = from->sst_next) { ++to; *to = *from; to->sst_next = to + 1; } } if (to != sstp - 1) { to->sst_next = NULL; ! syn_buf->b_sst_first = sstp; ! syn_buf->b_sst_freecount = len - (int)(to - sstp) - 1; } else { ! syn_buf->b_sst_first = NULL; ! syn_buf->b_sst_freecount = len; } /* Create the list of free entries. */ ! syn_buf->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; } } /* * Check for changes in a buffer to affect stored syntax states. Uses the --- 1077,1144 ---- len = syn_buf->b_ml.ml_line_count / SST_DIST + Rows * 2; if (len < SST_MIN_ENTRIES) len = SST_MIN_ENTRIES; else if (len > SST_MAX_ENTRIES) len = SST_MAX_ENTRIES; ! if (syn_buf2->b_sst_len > len * 2 || syn_buf2->b_sst_len < len) { /* Allocate 50% too much, to avoid reallocating too often. */ len = syn_buf->b_ml.ml_line_count; len = (len + len / 2) / SST_DIST + Rows * 2; if (len < SST_MIN_ENTRIES) len = SST_MIN_ENTRIES; else if (len > SST_MAX_ENTRIES) len = SST_MAX_ENTRIES; ! if (syn_buf2->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_buf2->b_sst_len - syn_buf2->b_sst_freecount + 2 > len && syn_stack_cleanup()) ; ! if (len < syn_buf2->b_sst_len - syn_buf2->b_sst_freecount + 2) ! len = syn_buf2->b_sst_len - syn_buf2->b_sst_freecount + 2; } sstp = (synstate_T *)alloc_clear((unsigned)(len * sizeof(synstate_T))); if (sstp == NULL) /* out of memory! */ return; to = sstp - 1; ! if (syn_buf2->b_sst_array != NULL) { /* Move the states from the old array to the new one. */ ! for (from = syn_buf2->b_sst_first; from != NULL; from = from->sst_next) { ++to; *to = *from; to->sst_next = to + 1; } } if (to != sstp - 1) { to->sst_next = NULL; ! syn_buf2->b_sst_first = sstp; ! syn_buf2->b_sst_freecount = len - (int)(to - sstp) - 1; } else { ! syn_buf2->b_sst_first = NULL; ! syn_buf2->b_sst_freecount = len; } /* Create the list of free entries. */ ! syn_buf2->b_sst_firstfree = to + 1; while (++to < sstp + len) to->sst_next = to + 1; (sstp + len - 1)->sst_next = NULL; ! vim_free(syn_buf2->b_sst_array); ! syn_buf2->b_sst_array = sstp; ! syn_buf2->b_sst_len = len; } } /* * Check for changes in a buffer to affect stored syntax states. Uses the *************** *** 1143,1173 **** */ void syn_stack_apply_changes(buf) buf_T *buf; { synstate_T *p, *prev, *np; linenr_T n; ! if (buf->b_sst_array == NULL) /* nothing to do */ return; prev = NULL; ! for (p = buf->b_sst_first; p != NULL; ) { ! if (p->sst_lnum + syn_buf->b_syn_sync_linebreaks > buf->b_mod_top) { n = p->sst_lnum + buf->b_mod_xlines; if (n <= buf->b_mod_bot) { /* this state is inside the changed area, remove it */ np = p->sst_next; if (prev == NULL) ! buf->b_sst_first = np; else prev->sst_next = np; ! syn_stack_free_entry(buf, p); p = np; continue; } /* This state is below the changed area. Remember the line * that needs to be parsed before this entry can be made valid --- 1148,1195 ---- */ void syn_stack_apply_changes(buf) buf_T *buf; { + win_T *wp; + + syn_stack_apply_changes_block(&buf->s, buf); + + FOR_ALL_WINDOWS(wp) + { + if ((wp->w_buffer == buf) && (wp->w_s != &buf->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 (block->b_sst_array == NULL) /* nothing to do */ return; prev = NULL; ! for (p = block->b_sst_first; p != NULL; ) { ! if (p->sst_lnum + block->b_syn_sync_linebreaks > buf->b_mod_top) { n = p->sst_lnum + buf->b_mod_xlines; if (n <= buf->b_mod_bot) { /* this state is inside the changed area, remove it */ np = p->sst_next; if (prev == NULL) ! block->b_sst_first = np; else prev->sst_next = np; ! syn_stack_free_entry(block, p); p = np; continue; } /* This state is below the changed area. Remember the line * that needs to be parsed before this entry can be made valid *************** *** 1201,1229 **** disptick_T tick; int above; int dist; int retval = FALSE; ! if (syn_buf->b_sst_array == NULL || syn_buf->b_sst_first == NULL) return retval; /* Compute normal distance between non-displayed entries. */ ! dist = syn_buf->b_ml.ml_line_count / (syn_buf->b_sst_len - Rows) + 1; /* * Go throught 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; above = FALSE; ! prev = syn_buf->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 (!above || p->sst_tick < tick) tick = p->sst_tick; above = TRUE; } --- 1223,1251 ---- disptick_T tick; int above; int dist; int retval = FALSE; ! if (syn_buf2->b_sst_array == NULL || syn_buf2->b_sst_first == NULL) return retval; /* Compute normal distance between non-displayed entries. */ ! dist = syn_buf->b_ml.ml_line_count / (syn_buf2->b_sst_len - Rows) + 1; /* * Go throught 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_buf2->b_sst_lasttick; above = FALSE; ! prev = syn_buf2->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_buf2->b_sst_lasttick) { if (!above || p->sst_tick < tick) tick = p->sst_tick; above = TRUE; } *************** *** 1234,1251 **** /* * Go through the list to make the entries for the oldest tick at an * interval of several lines. */ ! prev = syn_buf->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); p = prev; retval = TRUE; } } return retval; --- 1256,1273 ---- /* * Go through the list to make the entries for the oldest tick at an * interval of several lines. */ ! prev = syn_buf2->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_buf2, p); p = prev; retval = TRUE; } } return retval; *************** *** 1254,1271 **** /* * Free the allocated memory for a syn_state item. * Move the entry into the free list. */ static void ! syn_stack_free_entry(buf, p) ! buf_T *buf; synstate_T *p; { clear_syn_state(p); ! p->sst_next = buf->b_sst_firstfree; ! buf->b_sst_firstfree = p; ! ++buf->b_sst_freecount; } /* * Find an entry in the list of state stacks at or before "lnum". * Returns NULL when there is no entry or the first entry is after "lnum". --- 1276,1293 ---- /* * Free the allocated memory for a syn_state item. * Move the entry into the free list. */ static void ! syn_stack_free_entry(block, p) ! synblock_T *block; synstate_T *p; { clear_syn_state(p); ! p->sst_next = block->b_sst_firstfree; ! block->b_sst_firstfree = p; ! ++block->b_sst_freecount; } /* * Find an entry in the list of state stacks at or before "lnum". * Returns NULL when there is no entry or the first entry is after "lnum". *************** *** 1275,1285 **** linenr_T lnum; { synstate_T *p, *prev; prev = NULL; ! for (p = syn_buf->b_sst_first; p != NULL; prev = p, p = p->sst_next) { if (p->sst_lnum == lnum) return p; if (p->sst_lnum > lnum) break; --- 1297,1307 ---- linenr_T lnum; { synstate_T *p, *prev; prev = NULL; ! for (p = syn_buf2->b_sst_first; p != NULL; prev = p, p = p->sst_next) { if (p->sst_lnum == lnum) return p; if (p->sst_lnum > lnum) break; *************** *** 1321,1372 **** if (i >= 0) { if (sp != NULL) { /* find "sp" in the list and remove it */ ! if (syn_buf->b_sst_first == sp) /* it's the first entry */ ! syn_buf->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) if (p->sst_next == sp) break; p->sst_next = sp->sst_next; } ! syn_stack_free_entry(syn_buf, sp); sp = NULL; } } else if (sp == NULL || sp->sst_lnum != current_lnum) { /* * Add a new entry */ /* If no free items, cleanup the array first. */ ! if (syn_buf->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) 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; if (sp == NULL) { /* Insert in front of the list */ ! p->sst_next = syn_buf->b_sst_first; ! syn_buf->b_sst_first = p; } else { /* insert in list after *sp */ p->sst_next = sp->sst_next; --- 1343,1394 ---- if (i >= 0) { if (sp != NULL) { /* find "sp" in the list and remove it */ ! if (syn_buf2->b_sst_first == sp) /* it's the first entry */ ! syn_buf2->b_sst_first = sp->sst_next; else { /* find the entry just before this one to adjust sst_next */ ! for (p = syn_buf2->b_sst_first; p != NULL; p = p->sst_next) if (p->sst_next == sp) break; p->sst_next = sp->sst_next; } ! syn_stack_free_entry(syn_buf2, sp); sp = NULL; } } else if (sp == NULL || sp->sst_lnum != current_lnum) { /* * Add a new entry */ /* If no free items, cleanup the array first. */ ! if (syn_buf2->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_buf2->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_buf2->b_sst_firstfree; ! syn_buf2->b_sst_firstfree = p->sst_next; ! --syn_buf2->b_sst_freecount; if (sp == NULL) { /* Insert in front of the list */ ! p->sst_next = syn_buf2->b_sst_first; ! syn_buf2->b_sst_first = p; } else { /* insert in list after *sp */ p->sst_next = sp->sst_next; *************** *** 1442,1452 **** keepend_level = i; CUR_STATE(i).si_ends = FALSE; 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; else CUR_STATE(i).si_next_list = NULL; update_si_attr(i); } current_state.ga_len = from->sst_stacksize; --- 1464,1474 ---- keepend_level = i; CUR_STATE(i).si_ends = FALSE; CUR_STATE(i).si_m_lnum = 0; if (CUR_STATE(i).si_idx >= 0) CUR_STATE(i).si_next_list = ! (SYN_ITEMS(syn_buf2)[CUR_STATE(i).si_idx]).sp_next_list; else CUR_STATE(i).si_next_list = NULL; update_si_attr(i); } current_state.ga_len = from->sst_stacksize; *************** *** 1505,1515 **** * same text. Compare the strings, ignore case when * the start item has the sp_ic flag set. */ if (bsx->matches[j] == NULL || six->matches[j] == NULL) break; ! if ((SYN_ITEMS(syn_buf)[CUR_STATE(i).si_idx]).sp_ic ? MB_STRICMP(bsx->matches[j], six->matches[j]) != 0 : STRCMP(bsx->matches[j], six->matches[j]) != 0) break; } --- 1527,1537 ---- * same text. Compare the strings, ignore case when * the start item has the sp_ic flag set. */ if (bsx->matches[j] == NULL || six->matches[j] == NULL) break; ! if ((SYN_ITEMS(syn_buf2)[CUR_STATE(i).si_idx]).sp_ic ? MB_STRICMP(bsx->matches[j], six->matches[j]) != 0 : STRCMP(bsx->matches[j], six->matches[j]) != 0) break; } *************** *** 1645,1655 **** /* * Check for match with sync item. */ 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 & (HL_SYNC_HERE|HL_SYNC_THERE))) return TRUE; /* syn_current_attr() will have skipped the check for an item * that ends here, need to do that now. */ --- 1667,1677 ---- /* * Check for match with sync item. */ cur_si = &CUR_STATE(current_state.ga_len - 1); if (cur_si->si_idx >= 0 ! && (SYN_ITEMS(syn_buf2)[cur_si->si_idx].sp_flags & (HL_SYNC_HERE|HL_SYNC_THERE))) return TRUE; /* syn_current_attr() will have skipped the check for an item * that ends here, need to do that now. */ *************** *** 1669,1685 **** * "col" is normally 0 for the first use in a line, and increments by one each * time. It's allowed to skip characters and to stop before the end of the * line. But only a "col" after a previously used column is allowed. */ int ! get_syntax_attr(col) colnr_T col; { int attr = 0; /* check for out of memory situation */ ! if (syn_buf->b_sst_array == NULL) return 0; reg_syn = TRUE; /* let vim_regexec() know we're using syntax */ /* Make sure current_state is valid */ --- 1691,1708 ---- * "col" is normally 0 for the first use in a line, and increments by one each * time. It's allowed to skip characters and to stop before the end of the * line. But only a "col" after a previously used column is allowed. */ int ! get_syntax_attr(col, p_flags) colnr_T col; + int *p_flags; /* Only filled in if FEAT_CONCEAL */ { int attr = 0; /* check for out of memory situation */ ! if (syn_buf2->b_sst_array == NULL) return 0; reg_syn = TRUE; /* let vim_regexec() know we're using syntax */ /* Make sure current_state is valid */ *************** *** 1694,1703 **** --- 1717,1730 ---- attr = syn_current_attr(FALSE, TRUE); ++current_col; } reg_syn = FALSE; + #ifdef FEAT_CONCEAL + if (p_flags != NULL) + *p_flags = current_flags; + #endif return attr; } /* * Get syntax attributes for current_lnum, current_col. *************** *** 1718,1727 **** --- 1745,1755 ---- synpat_T *spp; stateitem_T *cur_si, *sip; int startcol; int endcol; long flags; + char_u cchar; short *next_list; int found_match; /* found usable match */ static int try_next_column = FALSE; /* must try in next col */ int do_keywords; regmmatch_T regmatch; *************** *** 1773,1784 **** try_next_column = FALSE; } /* Only check for keywords when not syncing and there are some. */ do_keywords = !syncing ! && (syn_buf->b_keywtab != NULL ! || syn_buf->b_keywtab_ic != NULL); /* Init the list of zero-width matches with a nextlist. This is used to * avoid matching the same item in the same position twice. */ ga_init2(&zero_width_next_ga, (int)sizeof(int), 10); --- 1801,1812 ---- try_next_column = FALSE; } /* Only check for keywords when not syncing and there are some. */ do_keywords = !syncing ! && (syn_buf2->b_keywtab != NULL ! || syn_buf2->b_keywtab_ic != NULL); /* Init the list of zero-width matches with a nextlist. This is used to * avoid matching the same item in the same position twice. */ ga_init2(&zero_width_next_ga, (int)sizeof(int), 10); *************** *** 1803,1813 **** if (current_state.ga_len) cur_si = &CUR_STATE(current_state.ga_len - 1); else cur_si = NULL; ! if (syn_buf->b_syn_containedin || cur_si == NULL || cur_si->si_cont_list != NULL) { /* * 2. Check for keywords, if on a keyword char after a non-keyword * char. Don't do this when syncing. --- 1831,1841 ---- if (current_state.ga_len) cur_si = &CUR_STATE(current_state.ga_len - 1); else cur_si = NULL; ! if (syn_buf2->b_syn_containedin || cur_si == NULL || cur_si->si_cont_list != NULL) { /* * 2. Check for keywords, if on a keyword char after a non-keyword * char. Don't do this when syncing. *************** *** 1824,1834 **** : 0) #endif , syn_buf))) { syn_id = check_keyword_id(line, (int)current_col, ! &endcol, &flags, &next_list, cur_si); if (syn_id) { if (push_current_state(KEYWORD_IDX) == OK) { cur_si = &CUR_STATE(current_state.ga_len - 1); --- 1852,1863 ---- : 0) #endif , syn_buf))) { syn_id = check_keyword_id(line, (int)current_col, ! &endcol, &flags, &next_list, cur_si, ! &cchar); if (syn_id) { if (push_current_state(KEYWORD_IDX) == OK) { cur_si = &CUR_STATE(current_state.ga_len - 1); *************** *** 1840,1849 **** --- 1869,1881 ---- cur_si->si_h_endpos.lnum = current_lnum; cur_si->si_h_endpos.col = endcol; cur_si->si_ends = TRUE; cur_si->si_end_idx = 0; cur_si->si_flags = flags; + #ifdef FEAT_CONCEAL + cur_si->si_char = cchar; + #endif cur_si->si_id = syn_id; cur_si->si_trans_id = syn_id; if (flags & HL_TRANSP) { if (current_state.ga_len < 2) *************** *** 1872,1882 **** } /* * 3. Check for patterns (only if not found a keyword). */ ! if (syn_id == 0 && syn_buf->b_syn_patterns.ga_len) { /* * If we didn't check for a match yet, or we are past it, check * for any match with a pattern. */ --- 1904,1914 ---- } /* * 3. Check for patterns (only if not found a keyword). */ ! if (syn_id == 0 && syn_buf2->b_syn_patterns.ga_len) { /* * If we didn't check for a match yet, or we are past it, check * for any match with a pattern. */ *************** *** 1888,1900 **** * pattern takes quite a bit of time, thus we want to * avoid doing it when it's not needed. */ 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; ) { ! spp = &(SYN_ITEMS(syn_buf)[idx]); if ( spp->sp_syncing == syncing && (displaying || !(spp->sp_flags & HL_DISPLAY)) && (spp->sp_type == SPTYPE_MATCH || spp->sp_type == SPTYPE_START) && (current_next_list != NULL --- 1920,1932 ---- * pattern takes quite a bit of time, thus we want to * avoid doing it when it's not needed. */ next_match_idx = 0; /* no match in this line yet */ next_match_col = MAXCOL; ! for (idx = syn_buf2->b_syn_patterns.ga_len; --idx >= 0; ) { ! spp = &(SYN_ITEMS(syn_buf2)[idx]); if ( spp->sp_syncing == syncing && (displaying || !(spp->sp_flags & HL_DISPLAY)) && (spp->sp_type == SPTYPE_MATCH || spp->sp_type == SPTYPE_START) && (current_next_list != NULL *************** *** 2066,2076 **** { synpat_T *lspp; /* 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]); if (next_match_m_endpos.lnum == current_lnum && next_match_m_endpos.col == current_col && lspp->sp_next_list != NULL) { current_next_list = lspp->sp_next_list; --- 2098,2108 ---- { synpat_T *lspp; /* When a zero-width item matched which has a nextgroup, * don't push the item but set nextgroup. */ ! lspp = &(SYN_ITEMS(syn_buf2)[next_match_idx]); if (next_match_m_endpos.lnum == current_lnum && next_match_m_endpos.col == current_col && lspp->sp_next_list != NULL) { current_next_list = lspp->sp_next_list; *************** *** 2139,2148 **** --- 2171,2183 ---- current_attr = 0; #ifdef FEAT_EVAL current_id = 0; current_trans_id = 0; #endif + #ifdef FEAT_CONCEAL + current_flags = 0; + #endif if (cur_si != NULL) { for (idx = current_state.ga_len - 1; idx >= 0; --idx) { sip = &CUR_STATE(idx); *************** *** 2157,2166 **** --- 2192,2205 ---- current_attr = sip->si_attr; #ifdef FEAT_EVAL current_id = sip->si_id; current_trans_id = sip->si_trans_id; #endif + #ifdef FEAT_CONCEAL + current_flags = sip->si_flags; + current_sub_char = sip->si_char; + #endif break; } } /* *************** *** 2233,2243 **** push_next_match(cur_si) stateitem_T *cur_si; { synpat_T *spp; ! spp = &(SYN_ITEMS(syn_buf)[next_match_idx]); /* * Push the item in current_state stack; */ if (push_current_state(next_match_idx) == OK) --- 2272,2282 ---- push_next_match(cur_si) stateitem_T *cur_si; { synpat_T *spp; ! spp = &(SYN_ITEMS(syn_buf2)[next_match_idx]); /* * Push the item in current_state stack; */ if (push_current_state(next_match_idx) == OK) *************** *** 2249,2258 **** --- 2288,2300 ---- cur_si = &CUR_STATE(current_state.ga_len - 1); cur_si->si_h_startpos = next_match_h_startpos; 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; + #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)) { /* Try to find the end pattern in the current line */ *************** *** 2279,2297 **** --- 2321,2347 ---- */ if ( spp->sp_type == SPTYPE_START && spp->sp_syn_match_id != 0 && push_current_state(next_match_idx) == OK) { + #ifdef FEAT_CONCEAL + long save_flags = cur_si->si_flags &= (HL_CONCEAL | HL_CONCEALENDS); + #endif cur_si = &CUR_STATE(current_state.ga_len - 1); cur_si->si_h_startpos = next_match_h_startpos; cur_si->si_m_startcol = current_col; cur_si->si_m_lnum = current_lnum; cur_si->si_m_endpos = next_match_eos_pos; cur_si->si_h_endpos = next_match_eos_pos; 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); } } *************** *** 2332,2341 **** --- 2382,2395 ---- cur_si->si_idx = cur_si->si_end_idx; cur_si->si_end_idx = 0; 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); break; } else { *************** *** 2374,2384 **** * - "keepend" is used for the contained item * - not at the end of the line (could be end="x$"me=e-1). * - "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 == SPTYPE_START && !(cur_si->si_flags & (HL_MATCH | HL_KEEPEND))) { update_si_end(cur_si, (int)current_col, TRUE); check_keepend(); --- 2428,2438 ---- * - "keepend" is used for the contained item * - not at the end of the line (could be end="x$"me=e-1). * - "excludenl" is used (HL_HAS_EOL won't be set) */ if (cur_si->si_idx >= 0 ! && SYN_ITEMS(syn_buf2)[cur_si->si_idx].sp_type == SPTYPE_START && !(cur_si->si_flags & (HL_MATCH | HL_KEEPEND))) { update_si_end(cur_si, (int)current_col, TRUE); check_keepend(); *************** *** 2403,2413 **** int idx; { stateitem_T *sip = &CUR_STATE(idx); synpat_T *spp; ! spp = &(SYN_ITEMS(syn_buf)[sip->si_idx]); if (sip->si_flags & HL_MATCH) sip->si_id = spp->sp_syn_match_id; else sip->si_id = spp->sp_syn.id; sip->si_attr = syn_id2attr(sip->si_id); --- 2457,2467 ---- int idx; { stateitem_T *sip = &CUR_STATE(idx); synpat_T *spp; ! spp = &(SYN_ITEMS(syn_buf2)[sip->si_idx]); if (sip->si_flags & HL_MATCH) sip->si_id = spp->sp_syn_match_id; else sip->si_id = spp->sp_syn.id; sip->si_attr = syn_id2attr(sip->si_id); *************** *** 2527,2537 **** &(sip->si_flags), &end_endpos, &end_idx, sip->si_extmatch); if (endpos.lnum == 0) { /* No end pattern matched. */ ! if (SYN_ITEMS(syn_buf)[sip->si_idx].sp_flags & HL_ONELINE) { /* a "oneline" never continues in the next line */ sip->si_ends = TRUE; sip->si_m_endpos.lnum = current_lnum; sip->si_m_endpos.col = (colnr_T)STRLEN(syn_getcurline()); --- 2581,2591 ---- &(sip->si_flags), &end_endpos, &end_idx, sip->si_extmatch); if (endpos.lnum == 0) { /* No end pattern matched. */ ! if (SYN_ITEMS(syn_buf2)[sip->si_idx].sp_flags & HL_ONELINE) { /* a "oneline" never continues in the next line */ sip->si_ends = TRUE; sip->si_m_endpos.lnum = current_lnum; sip->si_m_endpos.col = (colnr_T)STRLEN(syn_getcurline()); *************** *** 2627,2637 **** /* * Check for being called with a START pattern. * Can happen with a match that continues to the next line, because it * contained a region. */ ! spp = &(SYN_ITEMS(syn_buf)[idx]); if (spp->sp_type != SPTYPE_START) { *hl_endpos = *startpos; return; } --- 2681,2691 ---- /* * Check for being called with a START pattern. * Can happen with a match that continues to the next line, because it * contained a region. */ ! spp = &(SYN_ITEMS(syn_buf2)[idx]); if (spp->sp_type != SPTYPE_START) { *hl_endpos = *startpos; return; } *************** *** 2639,2649 **** /* * Find the SKIP or first END pattern after the last START pattern. */ for (;;) { ! spp = &(SYN_ITEMS(syn_buf)[idx]); if (spp->sp_type != SPTYPE_START) break; ++idx; } --- 2693,2703 ---- /* * Find the SKIP or first END pattern after the last START pattern. */ for (;;) { ! spp = &(SYN_ITEMS(syn_buf2)[idx]); if (spp->sp_type != SPTYPE_START) break; ++idx; } *************** *** 2669,2683 **** { /* * Find end pattern that matches first after "matchcol". */ best_idx = -1; ! for (idx = start_idx; idx < syn_buf->b_syn_patterns.ga_len; ++idx) { int lc_col = matchcol; ! spp = &(SYN_ITEMS(syn_buf)[idx]); if (spp->sp_type != SPTYPE_END) /* past last END pattern */ break; lc_col -= spp->sp_offsets[SPO_LC_OFF]; if (lc_col < 0) lc_col = 0; --- 2723,2737 ---- { /* * Find end pattern that matches first after "matchcol". */ best_idx = -1; ! for (idx = start_idx; idx < syn_buf2->b_syn_patterns.ga_len; ++idx) { int lc_col = matchcol; ! spp = &(SYN_ITEMS(syn_buf2)[idx]); if (spp->sp_type != SPTYPE_END) /* past last END pattern */ break; lc_col -= spp->sp_offsets[SPO_LC_OFF]; if (lc_col < 0) lc_col = 0; *************** *** 2751,2761 **** /* * Match from start pattern to end pattern. * Correct for match and highlight offset of end pattern. */ ! spp = &(SYN_ITEMS(syn_buf)[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) m_endpos->col = startpos->col; --- 2805,2815 ---- /* * Match from start pattern to end pattern. * Correct for match and highlight offset of end pattern. */ ! spp = &(SYN_ITEMS(syn_buf2)[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) m_endpos->col = startpos->col; *************** *** 2937,2953 **** * Check one position in a line for a matching keyword. * The caller must check if a keyword can start at startcol. * Return it's ID if found, 0 otherwise. */ static int ! check_keyword_id(line, startcol, endcolp, flagsp, next_listp, cur_si) 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 */ { keyentry_T *ktab; char_u *p; int round; int len; --- 2991,3008 ---- * Check one position in a line for a matching keyword. * The caller must check if a keyword can start at startcol. * Return it's ID if found, 0 otherwise. */ static int ! 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 */ + char_u *ccharp; { keyentry_T *ktab; char_u *p; int round; int len; *************** *** 2983,3006 **** * 1. matching case * 2. ignoring case */ for (round = 1; round <= 2; ++round) { ! if ((round == 1 ? syn_buf->b_keywtab : syn_buf->b_keywtab_ic) == NULL) continue; if (round == 1) /* match case */ ! ktab = syn_buf->b_keywtab[syn_khash(keyword)]; else /* round == 2, ignore case */ { p = str_foldcase(keyword, (int)STRLEN(keyword)); if (p != NULL) { STRNCPY(keyword, p, MAXKEYWLEN); keyword[MAXKEYWLEN] = NUL; vim_free(p); } ! ktab = syn_buf->b_keywtab_ic[syn_khash(keyword)]; } /* * Find keywords that match. * When current_next_list is non-zero accept only that group, otherwise: --- 3038,3061 ---- * 1. matching case * 2. ignoring case */ for (round = 1; round <= 2; ++round) { ! if ((round == 1 ? syn_buf2->b_keywtab : syn_buf2->b_keywtab_ic) == NULL) continue; if (round == 1) /* match case */ ! ktab = syn_buf2->b_keywtab[syn_khash(keyword)]; else /* round == 2, ignore case */ { p = str_foldcase(keyword, (int)STRLEN(keyword)); if (p != NULL) { STRNCPY(keyword, p, MAXKEYWLEN); keyword[MAXKEYWLEN] = NUL; vim_free(p); } ! ktab = syn_buf2->b_keywtab_ic[syn_khash(keyword)]; } /* * Find keywords that match. * When current_next_list is non-zero accept only that group, otherwise: *************** *** 3017,3033 **** --- 3072,3118 ---- &ktab->k_syn, ktab->flags & HL_CONTAINED)))) { *endcolp = startcol + len; *flagsp = ktab->flags; *next_listp = ktab->next_list; + #ifdef FEAT_CONCEAL + *ccharp = ktab->k_char; + #endif return ktab->k_syn.id; } } return 0; } /* + * Handle ":syntax conceal" command. + */ + /* ARGSUSED */ + static void + syn_cmd_conceal(eap, syncing) + exarg_T *eap; + int syncing; /* not used */ + { + #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. */ /* ARGSUSED */ static void syn_cmd_case(eap, syncing) *************** *** 3041,3100 **** if (eap->skip) return; next = skiptowhite(arg); if (STRNICMP(arg, "match", 5) == 0 && next - arg == 5) ! curbuf->b_syn_ic = FALSE; else if (STRNICMP(arg, "ignore", 6) == 0 && next - arg == 6) ! curbuf->b_syn_ic = TRUE; else EMSG2(_("E390: Illegal argument: %s"), arg); } /* * Clear all syntax info for one buffer. */ void ! syntax_clear(buf) ! buf_T *buf; { int i; ! curbuf->b_syn_ic = FALSE; /* Use case, by default */ ! curbuf->b_syn_containedin = FALSE; /* free the keywords */ ! free_keywtab(buf->b_keywtab); ! buf->b_keywtab = NULL; ! free_keywtab(buf->b_keywtab_ic); ! buf->b_keywtab_ic = NULL; /* 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); /* 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_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; #ifdef FEAT_FOLDING ! buf->b_syn_folditems = 0; #endif /* free the stored states */ ! syn_stack_free_all(buf); invalidate_current_state(); } /* * Clear syncing info for one buffer. --- 3126,3185 ---- if (eap->skip) return; next = skiptowhite(arg); if (STRNICMP(arg, "match", 5) == 0 && next - arg == 5) ! curwin->w_s->b_syn_ic = FALSE; else if (STRNICMP(arg, "ignore", 6) == 0 && next - arg == 6) ! curwin->w_s->b_syn_ic = TRUE; else EMSG2(_("E390: Illegal argument: %s"), arg); } /* * Clear all syntax info for one buffer. */ void ! syntax_clear(block) ! synblock_T *block; { int i; ! block->b_syn_ic = FALSE; /* Use case, by default */ ! block->b_syn_containedin = FALSE; /* free the keywords */ ! free_keywtab(block->b_keywtab); ! block->b_keywtab = NULL; ! free_keywtab(block->b_keywtab_ic); ! block->b_keywtab_ic = NULL; /* free the syntax 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 = block->b_syn_clusters.ga_len; --i >= 0; ) ! syn_clear_cluster(block, i); ! ga_clear(&block->b_syn_clusters); ! ! 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 ! block->b_syn_folditems = 0; #endif /* free the stored states */ ! syn_stack_free_all(block); invalidate_current_state(); } /* * Clear syncing info for one buffer. *************** *** 3103,3181 **** syntax_sync_clear() { int i; /* free the syntax patterns */ ! for (i = curbuf->b_syn_patterns.ga_len; --i >= 0; ) ! if (SYN_ITEMS(curbuf)[i].sp_syncing) ! syn_remove_pattern(curbuf, i); ! ! curbuf->b_syn_sync_flags = 0; ! curbuf->b_syn_sync_minlines = 0; ! curbuf->b_syn_sync_maxlines = 0; ! curbuf->b_syn_sync_linebreaks = 0; ! ! vim_free(curbuf->b_syn_linecont_prog); ! curbuf->b_syn_linecont_prog = NULL; ! vim_free(curbuf->b_syn_linecont_pat); ! curbuf->b_syn_linecont_pat = NULL; ! syn_stack_free_all(curbuf); /* Need to recompute all syntax. */ } /* * Remove one pattern from the buffer's pattern list. */ static void ! syn_remove_pattern(buf, idx) ! buf_T *buf; int idx; { synpat_T *spp; ! spp = &(SYN_ITEMS(buf)[idx]); #ifdef FEAT_FOLDING if (spp->sp_flags & HL_FOLD) ! --buf->b_syn_folditems; #endif ! syn_clear_pattern(buf, idx); mch_memmove(spp, spp + 1, ! sizeof(synpat_T) * (buf->b_syn_patterns.ga_len - idx - 1)); ! --buf->b_syn_patterns.ga_len; ! --buf->b_syn_patterns.ga_room; } /* * Clear and free one syntax pattern. When clearing all, must be called from * last to first! */ static void ! syn_clear_pattern(buf, i) ! buf_T *buf; int i; { ! vim_free(SYN_ITEMS(buf)[i].sp_pattern); ! vim_free(SYN_ITEMS(buf)[i].sp_prog); /* Only free sp_cont_list and sp_next_list of first start pattern */ ! if (i == 0 || SYN_ITEMS(buf)[i - 1].sp_type != SPTYPE_START) { ! vim_free(SYN_ITEMS(buf)[i].sp_cont_list); ! vim_free(SYN_ITEMS(buf)[i].sp_next_list); } } /* * Clear and free one syntax cluster. */ static void ! syn_clear_cluster(buf, i) ! buf_T *buf; 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); } /* * Handle ":syntax clear" command. */ --- 3188,3266 ---- syntax_sync_clear() { int i; /* free the syntax patterns */ ! for (i = curwin->w_s->b_syn_patterns.ga_len; --i >= 0; ) ! if (SYN_ITEMS(curwin->w_s)[i].sp_syncing) ! syn_remove_pattern(curwin->w_s, i); ! ! curwin->w_s->b_syn_sync_flags = 0; ! curwin->w_s->b_syn_sync_minlines = 0; ! curwin->w_s->b_syn_sync_maxlines = 0; ! curwin->w_s->b_syn_sync_linebreaks = 0; ! ! vim_free(curwin->w_s->b_syn_linecont_prog); ! curwin->w_s->b_syn_linecont_prog = NULL; ! vim_free(curwin->w_s->b_syn_linecont_pat); ! curwin->w_s->b_syn_linecont_pat = NULL; ! syn_stack_free_all(curwin->w_s); /* Need to recompute all syntax. */ } /* * Remove one pattern from the buffer's pattern list. */ static void ! syn_remove_pattern(block, idx) ! synblock_T *block; int idx; { synpat_T *spp; ! spp = &(SYN_ITEMS(block)[idx]); #ifdef FEAT_FOLDING if (spp->sp_flags & HL_FOLD) ! --block->b_syn_folditems; #endif ! syn_clear_pattern(block, idx); mch_memmove(spp, spp + 1, ! sizeof(synpat_T) * (block->b_syn_patterns.ga_len - idx - 1)); ! --block->b_syn_patterns.ga_len; ! --block->b_syn_patterns.ga_room; } /* * Clear and free one syntax pattern. When clearing all, must be called from * last to first! */ static void ! syn_clear_pattern(block, i) ! synblock_T *block; int i; { ! 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(block)[i - 1].sp_type != SPTYPE_START) { ! vim_free(SYN_ITEMS(block)[i].sp_cont_list); ! vim_free(SYN_ITEMS(block)[i].sp_next_list); } } /* * Clear and free one syntax cluster. */ static void ! syn_clear_cluster(block, i) ! synblock_T *block; int i; { ! 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); } /* * Handle ":syntax clear" command. */ *************** *** 3196,3206 **** * We have to disable this within ":syn include @group filename", * because otherwise @group would get deleted. * Only required for Vim 5.x syntax files, 6.0 ones don't contain ":syn * clear". */ ! if (curbuf->b_syn_topgrp != 0) return; if (ends_excmd(*arg)) { /* --- 3281,3291 ---- * We have to disable this within ":syn include @group filename", * because otherwise @group would get deleted. * Only required for Vim 5.x syntax files, 6.0 ones don't contain ":syn * clear". */ ! if (curwin->w_s->b_syn_topgrp != 0) return; if (ends_excmd(*arg)) { /* *************** *** 3208,3219 **** */ if (syncing) syntax_sync_clear(); else { ! syntax_clear(curbuf); ! do_unlet((char_u *)"b:current_syntax"); } } else { /* --- 3293,3308 ---- */ if (syncing) syntax_sync_clear(); else { ! syntax_clear(curwin->w_s); ! if (curwin->w_s == &curwin->w_buffer->s) ! do_unlet((char_u *)"b:current_syntax"); ! else ! do_unlet((char_u *)"w:current_syntax"); ! } } else { /* *************** *** 3237,3248 **** * the IDs of other clusters, so we do the next best thing * and make it empty. */ short scl_id = id - SYNID_CLUSTER; ! vim_free(SYN_CLSTR(curbuf)[scl_id].scl_list); ! SYN_CLSTR(curbuf)[scl_id].scl_list = NULL; } } else { id = syn_namen2id(arg, (int)(arg_end - arg)); --- 3326,3337 ---- * the IDs of other clusters, so we do the next best thing * and make it empty. */ short scl_id = id - SYNID_CLUSTER; ! vim_free(SYN_CLSTR(curwin->w_s)[scl_id].scl_list); ! SYN_CLSTR(curwin->w_s)[scl_id].scl_list = NULL; } } else { id = syn_namen2id(arg, (int)(arg_end - arg)); *************** *** 3256,3266 **** } arg = skipwhite(arg_end); } } redraw_curbuf_later(NOT_VALID); ! syn_stack_free_all(curbuf); /* Need to recompute all syntax. */ } /* * Clear one syntax group for the current buffer. */ --- 3345,3355 ---- } arg = skipwhite(arg_end); } } redraw_curbuf_later(NOT_VALID); ! syn_stack_free_all(curwin->w_s); /* Need to recompute all syntax. */ } /* * Clear one syntax group for the current buffer. */ *************** *** 3273,3293 **** int idx; /* 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); } /* clear the patterns for "id" */ ! for (idx = curbuf->b_syn_patterns.ga_len; --idx >= 0; ) { ! spp = &(SYN_ITEMS(curbuf)[idx]); if (spp->sp_syn.id != id || spp->sp_syncing != syncing) continue; ! syn_remove_pattern(curbuf, idx); } } /* * Handle ":syntax on" command. --- 3362,3382 ---- int idx; /* Clear keywords only when not ":syn sync clear group-name" */ if (!syncing) { ! (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 = curwin->w_s->b_syn_patterns.ga_len; --idx >= 0; ) { ! spp = &(SYN_ITEMS(curwin->w_s)[idx]); if (spp->sp_syn.id != id || spp->sp_syncing != syncing) continue; ! syn_remove_pattern(curwin->w_s, idx); } } /* * Handle ":syntax on" command. *************** *** 3387,3428 **** eap->nextcmd = find_nextcmd(arg); if (eap->skip) return; ! if (!syntax_present(curbuf)) { MSG(_("No Syntax items defined for this buffer")); return; } if (syncing) { ! if (curbuf->b_syn_sync_flags & SF_CCOMMENT) { MSG_PUTS(_("syncing on C-style comments")); syn_lines_msg(); syn_match_msg(); return; } ! else if (!(curbuf->b_syn_sync_flags & SF_MATCH)) { ! if (curbuf->b_syn_sync_minlines == 0) MSG_PUTS(_("no syncing")); else { MSG_PUTS(_("syncing starts ")); ! msg_outnum(curbuf->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) { MSG_PUTS(_("\nsyncing on items")); syn_lines_msg(); syn_match_msg(); } --- 3476,3517 ---- eap->nextcmd = find_nextcmd(arg); if (eap->skip) return; ! if (!syntax_present(curwin)) { MSG(_("No Syntax items defined for this buffer")); return; } if (syncing) { ! 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 (!(curwin->w_s->b_syn_sync_flags & SF_MATCH)) { ! if (curwin->w_s->b_syn_sync_minlines == 0) MSG_PUTS(_("no syncing")); else { MSG_PUTS(_("syncing starts ")); ! msg_outnum(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 (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(); syn_match_msg(); } *************** *** 3434,3444 **** /* * No argument: List all group IDs and all syntax clusters. */ 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) syn_list_cluster(id); } else { /* --- 3523,3533 ---- /* * No argument: List all group IDs and all syntax clusters. */ for (id = 1; id <= highlight_ga.ga_len && !got_int; ++id) syn_list_one(id, syncing, FALSE); ! for (id = 0; id < curwin->w_s->b_syn_clusters.ga_len && !got_int; ++id) syn_list_cluster(id); } else { /* *************** *** 3470,3505 **** } static void syn_lines_msg() { ! if (curbuf->b_syn_sync_maxlines > 0 || curbuf->b_syn_sync_minlines > 0) { MSG_PUTS("; "); ! if (curbuf->b_syn_sync_minlines > 0) { MSG_PUTS(_("minimal ")); ! msg_outnum(curbuf->b_syn_sync_minlines); ! if (curbuf->b_syn_sync_maxlines) MSG_PUTS(", "); } ! if (curbuf->b_syn_sync_maxlines > 0) { MSG_PUTS(_("maximal ")); ! msg_outnum(curbuf->b_syn_sync_maxlines); } MSG_PUTS(_(" lines before top line")); } } static void syn_match_msg() { ! if (curbuf->b_syn_sync_linebreaks > 0) { MSG_PUTS(_("; match ")); ! msg_outnum(curbuf->b_syn_sync_linebreaks); MSG_PUTS(_(" line breaks")); } } static int last_matchgroup; --- 3559,3594 ---- } static void syn_lines_msg() { ! if (curwin->w_s->b_syn_sync_maxlines > 0 || curwin->w_s->b_syn_sync_minlines > 0) { MSG_PUTS("; "); ! if (curwin->w_s->b_syn_sync_minlines > 0) { MSG_PUTS(_("minimal ")); ! msg_outnum(curwin->w_s->b_syn_sync_minlines); ! if (curwin->w_s->b_syn_sync_maxlines) MSG_PUTS(", "); } ! if (curwin->w_s->b_syn_sync_maxlines > 0) { MSG_PUTS(_("maximal ")); ! msg_outnum(curwin->w_s->b_syn_sync_maxlines); } MSG_PUTS(_(" lines before top line")); } } static void syn_match_msg() { ! if (curwin->w_s->b_syn_sync_linebreaks > 0) { MSG_PUTS(_("; match ")); ! msg_outnum(curwin->w_s->b_syn_sync_linebreaks); MSG_PUTS(_(" line breaks")); } } static int last_matchgroup; *************** *** 3533,3542 **** --- 3622,3635 ---- {HL_KEEPEND, "keepend"}, {HL_EXTEND, "extend"}, {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[] = { {HL_SKIPWHITE, "skipwhite"}, *************** *** 3548,3566 **** attr = hl_attr(HLF_D); /* highlight like directories */ /* 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, attr); } /* list the patterns for "id" */ ! for (idx = 0; idx < curbuf->b_syn_patterns.ga_len && !got_int; ++idx) { ! spp = &(SYN_ITEMS(curbuf)[idx]); if (spp->sp_syn.id != id || spp->sp_syncing != syncing) continue; (void)syn_list_header(did_header, 999, id); did_header = TRUE; --- 3641,3659 ---- attr = hl_attr(HLF_D); /* highlight like directories */ /* list the keywords for "id" */ if (!syncing) { ! 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 < curwin->w_s->b_syn_patterns.ga_len && !got_int; ++idx) { ! spp = &(SYN_ITEMS(curwin->w_s)[idx]); if (spp->sp_syn.id != id || spp->sp_syncing != syncing) continue; (void)syn_list_header(did_header, 999, id); did_header = TRUE; *************** *** 3570,3586 **** put_pattern("match", ' ', spp, attr); msg_putchar(' '); } 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); --idx; msg_putchar(' '); } syn_list_flags(namelist1, spp->sp_flags, attr); --- 3663,3679 ---- put_pattern("match", ' ', spp, attr); msg_putchar(' '); } else if (spp->sp_type == SPTYPE_START) { ! 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(' '); } syn_list_flags(namelist1, spp->sp_flags, attr); *************** *** 3602,3612 **** msg_puts_attr((char_u *)"grouphere", attr); else msg_puts_attr((char_u *)"groupthere", attr); msg_putchar(' '); if (spp->sp_sync_idx >= 0) ! msg_outtrans(HL_TABLE()[SYN_ITEMS(curbuf) [spp->sp_sync_idx].sp_syn.id - 1].sg_name); else MSG_PUTS("NONE"); msg_putchar(' '); } --- 3695,3705 ---- msg_puts_attr((char_u *)"grouphere", attr); else msg_puts_attr((char_u *)"groupthere", attr); msg_putchar(' '); if (spp->sp_sync_idx >= 0) ! msg_outtrans(HL_TABLE()[SYN_ITEMS(curwin->w_s) [spp->sp_sync_idx].sp_syn.id - 1].sg_name); else MSG_PUTS("NONE"); msg_putchar(' '); } *************** *** 3647,3667 **** { int endcol = 15; /* slight hack: roughly duplicate the guts of syn_list_header() */ msg_putchar('\n'); ! msg_outtrans(SYN_CLSTR(curbuf)[id].scl_name); if (msg_col >= endcol) /* output at least one space */ endcol = msg_col + 1; if (Columns <= endcol) /* avoid hang for tiny window */ endcol = Columns - 1; msg_advance(endcol); ! if (SYN_CLSTR(curbuf)[id].scl_list != NULL) { ! put_id_list((char_u *)"cluster", SYN_CLSTR(curbuf)[id].scl_list, hl_attr(HLF_D)); } else { msg_puts_attr((char_u *)"cluster", hl_attr(HLF_D)); --- 3740,3760 ---- { int endcol = 15; /* slight hack: roughly duplicate the guts of syn_list_header() */ msg_putchar('\n'); ! msg_outtrans(SYN_CLSTR(curwin->w_s)[id].scl_name); if (msg_col >= endcol) /* output at least one space */ endcol = msg_col + 1; if (Columns <= endcol) /* avoid hang for tiny window */ endcol = Columns - 1; msg_advance(endcol); ! if (SYN_CLSTR(curwin->w_s)[id].scl_list != NULL) { ! put_id_list((char_u *)"cluster", SYN_CLSTR(curwin->w_s)[id].scl_list, hl_attr(HLF_D)); } else { msg_puts_attr((char_u *)"cluster", hl_attr(HLF_D)); *************** *** 3699,3709 **** else if (*p >= SYNID_CLUSTER) { short scl_id = *p - SYNID_CLUSTER; msg_putchar('@'); ! msg_outtrans(SYN_CLSTR(curbuf)[scl_id].scl_name); } else msg_outtrans(HL_TABLE()[*p - 1].sg_name); if (p[1]) msg_putchar(','); --- 3792,3802 ---- else if (*p >= SYNID_CLUSTER) { short scl_id = *p - SYNID_CLUSTER; msg_putchar('@'); ! msg_outtrans(SYN_CLSTR(curwin->w_s)[scl_id].scl_name); } else msg_outtrans(HL_TABLE()[*p - 1].sg_name); if (p[1]) msg_putchar(','); *************** *** 3943,3965 **** /* * Add a keyword to the list of keywords. */ static void ! add_keyword(name, id, flags, cont_in_list, next_list) 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 */ { keyentry_T *ktab; keyentry_T ***ktabpp; int hash; char_u *name_ic = name; ! if (curbuf->b_syn_ic) { name_ic = str_foldcase(name, (int)STRLEN(name)); if (name_ic == NULL) name_ic = name; } --- 4036,4059 ---- /* * Add a keyword to the list of keywords. */ static void ! 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 */ + char_u conceal_char; { keyentry_T *ktab; keyentry_T ***ktabpp; int hash; char_u *name_ic = name; ! if (curwin->w_s->b_syn_ic) { name_ic = str_foldcase(name, (int)STRLEN(name)); if (name_ic == NULL) name_ic = name; } *************** *** 3970,3988 **** if (name_ic != name) vim_free(name_ic); ktab->k_syn.id = id; ktab->k_syn.inc_tag = current_syn_inc_tag; ktab->flags = flags; ktab->k_syn.cont_in_list = copy_id_list(cont_in_list); if (cont_in_list != NULL) ! curbuf->b_syn_containedin = TRUE; ktab->next_list = copy_id_list(next_list); ! if (curbuf->b_syn_ic) ! ktabpp = &curbuf->b_keywtab_ic; else ! ktabpp = &curbuf->b_keywtab; if (*ktabpp == NULL) { *ktabpp = (keyentry_T **)alloc_clear( (int)(sizeof(keyentry_T *) * KHASH_SIZE)); --- 4064,4083 ---- if (name_ic != name) vim_free(name_ic); ktab->k_syn.id = id; ktab->k_syn.inc_tag = current_syn_inc_tag; ktab->flags = flags; + ktab->k_char = conceal_char; ktab->k_syn.cont_in_list = copy_id_list(cont_in_list); if (cont_in_list != NULL) ! curwin->w_s->b_syn_containedin = TRUE; ktab->next_list = copy_id_list(next_list); ! if (curwin->w_s->b_syn_ic) ! ktabpp = &curwin->w_s->b_keywtab_ic; else ! ktabpp = &curwin->w_s->b_keywtab; if (*ktabpp == NULL) { *ktabpp = (keyentry_T **)alloc_clear( (int)(sizeof(keyentry_T *) * KHASH_SIZE)); *************** *** 4049,4069 **** * Return a pointer to the next argument (which isn't an option). * Return NULL for any error; */ static char_u * get_syn_options(arg, flagsp, keyword, sync_idx, cont_list, ! cont_in_list, next_list) char_u *arg; /* next argument */ int *flagsp; /* flags for contained and transpartent */ int keyword; /* TRUE for ":syn keyword" */ int *sync_idx; /* syntax item for "grouphere" argument, NULL if not allowed */ short **cont_list; /* group IDs for "contains" argument, NULL if not allowed */ short **cont_in_list; /* group IDs for "containedin" argument, NULL if not allowed */ short **next_list; /* group IDs for "nextgroup" argument */ { int flags; char_u *gname_start, *gname; int syn_id; int len; --- 4144,4166 ---- * Return a pointer to the next argument (which isn't an option). * Return NULL for any error; */ static char_u * get_syn_options(arg, flagsp, keyword, sync_idx, cont_list, ! cont_in_list, next_list, ! conceal_char) char_u *arg; /* next argument */ int *flagsp; /* flags for contained and transpartent */ int keyword; /* TRUE for ":syn keyword" */ int *sync_idx; /* syntax item for "grouphere" argument, NULL if not allowed */ short **cont_list; /* group IDs for "contains" argument, NULL if not allowed */ short **cont_in_list; /* group IDs for "containedin" argument, NULL if not allowed */ short **next_list; /* group IDs for "nextgroup" argument */ + char_u *conceal_char; { int flags; char_u *gname_start, *gname; int syn_id; int len; *************** *** 4085,4103 **** --- 4182,4209 ---- {"skipempty", 9, HL_SKIPEMPTY}, {"grouphere", 9, HL_SYNC_HERE}, {"groupthere", 10, HL_SYNC_THERE}, {"display", 7, HL_DISPLAY}, {"fold", 4, HL_FOLD}, + /*#ifdef FEAT_CONCEAL vn: must leave this in so syntax files work on non-conceal systems*/ + {"conceal", 7, HL_CONCEAL}, + {"concealends", 11, HL_CONCEALENDS}, + /*#endif*/ }; #define MLEN 12 char lowname[MLEN]; int llen; if (arg == NULL) /* already detected error */ return NULL; flags = *flagsp; + #ifdef FEAT_CONCEAL + if (curwin->w_s->b_syn_conceal) + flags |= HL_CONCEAL; + #endif + for (;;) { /* STRNICMP() is a bit slow, change arg to lowercase first and use * STRNCMP() */ for (llen = 0; llen < MLEN; ++llen) *************** *** 4145,4157 **** if (STRCMP(gname, "NONE") == 0) *sync_idx = NONE_IDX; 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) { *sync_idx = i; break; } if (i < 0) --- 4251,4263 ---- if (STRCMP(gname, "NONE") == 0) *sync_idx = NONE_IDX; else { syn_id = syn_name2id(gname); ! 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) { *sync_idx = i; break; } if (i < 0) *************** *** 4205,4214 **** --- 4311,4328 ---- && (vim_iswhite(arg[9]) || arg[9] == '=')) { if (get_id_list(&arg, 9, next_list) == FAIL) return NULL; } + else if (llen == 5 && STRNCMP(lowname, "cchar", 5) == 0 + && ( arg[5] == '=')) + { + #ifdef FEAT_CONCEAL + *conceal_char = arg[6]; + #endif + arg = skipwhite(arg + 7); + } else break; } *flagsp = flags; *************** *** 4224,4247 **** static void syn_incl_toplevel(id, flagsp) int id; int *flagsp; { ! if ((*flagsp & HL_CONTAINED) || curbuf->b_syn_topgrp == 0) return; *flagsp |= HL_CONTAINED; ! if (curbuf->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; if (grp_list != NULL) { grp_list[0] = id; grp_list[1] = 0; ! syn_combine_list(&SYN_CLSTR(curbuf)[tlg_id].scl_list, &grp_list, CLUSTER_ADD); } } } --- 4338,4361 ---- static void syn_incl_toplevel(id, flagsp) int id; int *flagsp; { ! if ((*flagsp & HL_CONTAINED) || curwin->w_s->b_syn_topgrp == 0) return; *flagsp |= HL_CONTAINED; ! 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 = 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(curwin->w_s)[tlg_id].scl_list, &grp_list, CLUSTER_ADD); } } } *************** *** 4305,4320 **** * Save and restore the existing top-level grouplist id and ":syn * include" tag around the actual inclusion. */ 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; if (source ? do_source(eap->arg, FALSE, FALSE) == FAIL : cmd_runtime(eap->arg, TRUE) == FAIL) EMSG2(_(e_notopen), eap->arg); ! curbuf->b_syn_topgrp = prev_toplvl_grp; current_syn_inc_tag = prev_syn_inc_tag; } /* * Handle ":syntax keyword {group-name} [{option}] keyword .." command. --- 4419,4434 ---- * Save and restore the existing top-level grouplist id and ":syn * include" tag around the actual inclusion. */ prev_syn_inc_tag = current_syn_inc_tag; current_syn_inc_tag = ++running_syn_inc_tag; ! prev_toplvl_grp = curwin->w_s->b_syn_topgrp; ! curwin->w_s->b_syn_topgrp = sgl_id; if (source ? do_source(eap->arg, FALSE, FALSE) == FAIL : cmd_runtime(eap->arg, TRUE) == FAIL) EMSG2(_(e_notopen), eap->arg); ! curwin->w_s->b_syn_topgrp = prev_toplvl_grp; current_syn_inc_tag = prev_syn_inc_tag; } /* * Handle ":syntax keyword {group-name} [{option}] keyword .." command. *************** *** 4334,4343 **** --- 4448,4458 ---- char_u *first_arg; int round; int flags = 0; short *next_list = NULL; short *cont_in_list = NULL; + char_u conceal_char = NUL; rest = get_group_name(arg, &group_name_end); if (rest != NULL) { *************** *** 4361,4371 **** */ for (rest = first_arg; rest != NULL && !ends_excmd(*rest); rest = skipwhite(rest)) { rest = get_syn_options(rest, &flags, TRUE, NULL, ! NULL, &cont_in_list, &next_list); if (rest == NULL || ends_excmd(*rest)) break; p = keyword_copy; while (*rest != 0 && !vim_iswhite(*rest)) { --- 4476,4487 ---- */ for (rest = first_arg; rest != NULL && !ends_excmd(*rest); rest = skipwhite(rest)) { rest = get_syn_options(rest, &flags, TRUE, NULL, ! NULL, &cont_in_list, &next_list, ! &conceal_char); if (rest == NULL || ends_excmd(*rest)) break; p = keyword_copy; while (*rest != 0 && !vim_iswhite(*rest)) { *************** *** 4379,4389 **** for (p = vim_strchr(keyword_copy, '['); ; ) { if (p != NULL) *p = NUL; add_keyword(keyword_copy, syn_id, flags, ! cont_in_list, next_list); if (p == NULL || p[1] == NUL || p[1] == ']') break; #ifdef FEAT_MBYTE if (has_mbyte) { --- 4495,4506 ---- for (p = vim_strchr(keyword_copy, '['); ; ) { if (p != NULL) *p = NUL; add_keyword(keyword_copy, syn_id, flags, ! cont_in_list, next_list, ! conceal_char); if (p == NULL || p[1] == NUL || p[1] == ']') break; #ifdef FEAT_MBYTE if (has_mbyte) { *************** *** 4414,4424 **** EMSG2(_(e_invarg2), arg); vim_free(cont_in_list); vim_free(next_list); redraw_curbuf_later(NOT_VALID); ! syn_stack_free_all(curbuf); /* Need to recompute all syntax. */ } /* * Handle ":syntax match {name} [{options}] {pattern} [{options}]". * --- 4531,4541 ---- EMSG2(_(e_invarg2), arg); vim_free(cont_in_list); vim_free(next_list); redraw_curbuf_later(NOT_VALID); ! syn_stack_free_all(curwin->w_s); /* Need to recompute all syntax. */ } /* * Handle ":syntax match {name} [{options}] {pattern} [{options}]". * *************** *** 4438,4508 **** int flags = 0; int sync_idx = 0; short *cont_list = NULL; short *cont_in_list = NULL; short *next_list = NULL; /* Isolate the group name, check for validity */ rest = get_group_name(arg, &group_name_end); /* Get options before the pattern */ rest = get_syn_options(rest, &flags, FALSE, ! syncing ? &sync_idx : NULL, &cont_list, &cont_in_list, &next_list); /* get the pattern. */ init_syn_patterns(); vim_memset(&item, 0, sizeof(item)); rest = get_syn_pattern(rest, &item); if (vim_regcomp_had_eol() && !(flags & HL_EXCLUDENL)) flags |= HL_HAS_EOL; /* Get options after the pattern */ rest = get_syn_options(rest, &flags, FALSE, ! syncing ? &sync_idx : NULL, &cont_list, &cont_in_list, &next_list); if (rest != NULL) /* all arguments are valid */ { /* * Check for trailing command and illegal trailing arguments. */ eap->nextcmd = check_nextcmd(rest); if (!ends_excmd(*rest) || eap->skip) rest = NULL; ! else if (ga_grow(&curbuf->b_syn_patterns, 1) != FAIL && (syn_id = syn_check_group(arg, (int)(group_name_end - arg))) != 0) { syn_incl_toplevel(syn_id, &flags); /* * 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 = flags; ! SYN_ITEMS(curbuf)[idx].sp_sync_idx = sync_idx; ! SYN_ITEMS(curbuf)[idx].sp_cont_list = cont_list; ! SYN_ITEMS(curbuf)[idx].sp_syn.cont_in_list = cont_in_list; if (cont_in_list != NULL) ! curbuf->b_syn_containedin = TRUE; ! SYN_ITEMS(curbuf)[idx].sp_next_list = next_list; ! ++curbuf->b_syn_patterns.ga_len; ! --curbuf->b_syn_patterns.ga_room; /* remember that we found a match for syncing on */ if (flags & (HL_SYNC_HERE|HL_SYNC_THERE)) ! curbuf->b_syn_sync_flags |= SF_MATCH; #ifdef FEAT_FOLDING if (flags & HL_FOLD) ! ++curbuf->b_syn_folditems; #endif redraw_curbuf_later(NOT_VALID); ! syn_stack_free_all(curbuf); /* Need to recompute all syntax. */ return; /* don't free the progs and patterns now */ } } /* --- 4555,4631 ---- int flags = 0; int sync_idx = 0; short *cont_list = NULL; short *cont_in_list = NULL; short *next_list = NULL; + char_u conceal_char = NUL; /* Isolate the group name, check for validity */ rest = get_group_name(arg, &group_name_end); /* Get options before the pattern */ rest = get_syn_options(rest, &flags, FALSE, ! syncing ? &sync_idx : NULL, &cont_list, &cont_in_list, &next_list, ! &conceal_char); /* get the pattern. */ init_syn_patterns(); vim_memset(&item, 0, sizeof(item)); rest = get_syn_pattern(rest, &item); if (vim_regcomp_had_eol() && !(flags & HL_EXCLUDENL)) flags |= HL_HAS_EOL; /* Get options after the pattern */ rest = get_syn_options(rest, &flags, FALSE, ! syncing ? &sync_idx : NULL, &cont_list, &cont_in_list, &next_list, ! &conceal_char); if (rest != NULL) /* all arguments are valid */ { /* * Check for trailing command and illegal trailing arguments. */ eap->nextcmd = check_nextcmd(rest); if (!ends_excmd(*rest) || eap->skip) rest = NULL; ! else if (ga_grow(&curwin->w_s->b_syn_patterns, 1) != FAIL && (syn_id = syn_check_group(arg, (int)(group_name_end - arg))) != 0) { syn_incl_toplevel(syn_id, &flags); /* * Store the pattern in the syn_items 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 = flags; ! SYN_ITEMS(curwin->w_s)[idx].sp_sync_idx = sync_idx; ! SYN_ITEMS(curwin->w_s)[idx].sp_cont_list = cont_list; ! SYN_ITEMS(curwin->w_s)[idx].sp_syn.cont_in_list = cont_in_list; ! #ifdef FEAT_CONCEAL ! SYN_ITEMS(curwin->w_s)[idx].sp_char = conceal_char; ! #endif if (cont_in_list != NULL) ! curwin->w_s->b_syn_containedin = TRUE; ! SYN_ITEMS(curwin->w_s)[idx].sp_next_list = next_list; ! ++curwin->w_s->b_syn_patterns.ga_len; ! --curwin->w_s->b_syn_patterns.ga_room; /* remember that we found a match for syncing on */ if (flags & (HL_SYNC_HERE|HL_SYNC_THERE)) ! curwin->w_s->b_syn_sync_flags |= SF_MATCH; #ifdef FEAT_FOLDING if (flags & HL_FOLD) ! ++curwin->w_s->b_syn_folditems; #endif redraw_curbuf_later(NOT_VALID); ! syn_stack_free_all(curwin->w_s); /* Need to recompute all syntax. */ return; /* don't free the progs and patterns now */ } } /* *************** *** 4556,4565 **** --- 4679,4689 ---- int idx; int flags = 0; short *cont_list = NULL; short *cont_in_list = NULL; short *next_list = NULL; + char_u conceal_char = NUL; /* Isolate the group name, check for validity */ rest = get_group_name(arg, &group_name_end); pat_ptrs[0] = NULL; *************** *** 4573,4583 **** */ while (rest != NULL && !ends_excmd(*rest)) { /* Check for option arguments */ rest = get_syn_options(rest, &flags, FALSE, NULL, ! &cont_list, &cont_in_list, &next_list); if (rest == NULL || ends_excmd(*rest)) break; /* must be a pattern or matchgroup then */ key_end = rest; --- 4697,4707 ---- */ while (rest != NULL && !ends_excmd(*rest)) { /* Check for option arguments */ rest = get_syn_options(rest, &flags, FALSE, NULL, ! &cont_list, &cont_in_list, &next_list, &conceal_char); if (rest == NULL || ends_excmd(*rest)) break; /* must be a pattern or matchgroup then */ key_end = rest; *************** *** 4697,4750 **** * If OK, add the item. */ eap->nextcmd = check_nextcmd(rest); if (!ends_excmd(*rest) || eap->skip) rest = NULL; ! else if (ga_grow(&(curbuf->b_syn_patterns), pat_count) != FAIL && (syn_id = syn_check_group(arg, (int)(group_name_end - arg))) != 0) { syn_incl_toplevel(syn_id, &flags); /* * Store the start/skip/end in the syn_items list */ ! idx = curbuf->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 = (item == ITEM_START) ? SPTYPE_START : (item == ITEM_SKIP) ? SPTYPE_SKIP : SPTYPE_END; ! SYN_ITEMS(curbuf)[idx].sp_flags |= 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 = ppp->pp_matchgroup_id; if (item == ITEM_START) { ! SYN_ITEMS(curbuf)[idx].sp_cont_list = cont_list; ! SYN_ITEMS(curbuf)[idx].sp_syn.cont_in_list = cont_in_list; if (cont_in_list != NULL) ! curbuf->b_syn_containedin = TRUE; ! SYN_ITEMS(curbuf)[idx].sp_next_list = next_list; } ! ++curbuf->b_syn_patterns.ga_len; ! --curbuf->b_syn_patterns.ga_room; ++idx; #ifdef FEAT_FOLDING if (flags & HL_FOLD) ! ++curbuf->b_syn_folditems; #endif } } redraw_curbuf_later(NOT_VALID); ! syn_stack_free_all(curbuf); /* Need to recompute all syntax. */ success = TRUE; /* don't free the progs and patterns now */ } } /* --- 4821,4877 ---- * If OK, add the item. */ eap->nextcmd = check_nextcmd(rest); if (!ends_excmd(*rest) || eap->skip) rest = NULL; ! 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) { syn_incl_toplevel(syn_id, &flags); /* * Store the start/skip/end in the syn_items list */ ! 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(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(curwin->w_s)[idx].sp_flags |= 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(curwin->w_s)[idx].sp_cont_list = cont_list; ! SYN_ITEMS(curwin->w_s)[idx].sp_syn.cont_in_list = cont_in_list; if (cont_in_list != NULL) ! curwin->w_s->b_syn_containedin = TRUE; ! SYN_ITEMS(curwin->w_s)[idx].sp_next_list = next_list; } ! ++curwin->w_s->b_syn_patterns.ga_len; ! --curwin->w_s->b_syn_patterns.ga_room; ++idx; #ifdef FEAT_FOLDING if (flags & HL_FOLD) ! ++curwin->w_s->b_syn_folditems; #endif } } redraw_curbuf_later(NOT_VALID); ! syn_stack_free_all(curwin->w_s); /* Need to recompute all syntax. */ success = TRUE; /* don't free the progs and patterns now */ } } /* *************** *** 4932,4944 **** /* Avoid using stricmp() too much, it's slow on some systems */ 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) break; vim_free(name_u); return (i < 0 ? 0 : i + SYNID_CLUSTER); } --- 5059,5071 ---- /* Avoid using stricmp() too much, it's slow on some systems */ name_u = vim_strsave_up(name); if (name_u == NULL) return 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); } *************** *** 5000,5031 **** int len; /* * First call for this growarray: init growing array. */ ! if (curbuf->b_syn_clusters.ga_data == NULL) { ! curbuf->b_syn_clusters.ga_itemsize = sizeof(struct syn_cluster); ! curbuf->b_syn_clusters.ga_growsize = 10; } /* * Make room for at least one other cluster entry. */ ! if (ga_grow(&curbuf->b_syn_clusters, 1) == FAIL) { vim_free(name); return 0; } ! len = curbuf->b_syn_clusters.ga_len; ! vim_memset(&(SYN_CLSTR(curbuf)[len]), 0, sizeof(struct syn_cluster)); ! 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; ! --curbuf->b_syn_clusters.ga_room; return len + SYNID_CLUSTER; } /* --- 5127,5158 ---- int len; /* * First call for this growarray: init growing array. */ ! if (curwin->w_s->b_syn_clusters.ga_data == NULL) { ! curwin->w_s->b_syn_clusters.ga_itemsize = sizeof(struct syn_cluster); ! curwin->w_s->b_syn_clusters.ga_growsize = 10; } /* * Make room for at least one other cluster entry. */ ! if (ga_grow(&curwin->w_s->b_syn_clusters, 1) == FAIL) { vim_free(name); return 0; } ! len = curwin->w_s->b_syn_clusters.ga_len; ! vim_memset(&(SYN_CLSTR(curwin->w_s)[len]), 0, sizeof(struct syn_cluster)); ! 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; ! --curwin->w_s->b_syn_clusters.ga_room; return len + SYNID_CLUSTER; } /* *************** *** 5085,5103 **** if (get_id_list(&rest, opt_len, &clstr_list) == FAIL) { EMSG2(_(e_invarg2), rest); break; } ! syn_combine_list(&SYN_CLSTR(curbuf)[scl_id].scl_list, &clstr_list, list_op); got_clstr = TRUE; } if (got_clstr) { redraw_curbuf_later(NOT_VALID); ! syn_stack_free_all(curbuf); /* Need to recompute all syntax. */ } } if (!got_clstr) EMSG(_("E400: No cluster specified")); --- 5212,5230 ---- if (get_id_list(&rest, opt_len, &clstr_list) == FAIL) { EMSG2(_(e_invarg2), rest); break; } ! syn_combine_list(&SYN_CLSTR(curwin->w_s)[scl_id].scl_list, &clstr_list, list_op); got_clstr = TRUE; } if (got_clstr) { redraw_curbuf_later(NOT_VALID); ! syn_stack_free_all(curwin->w_s); /* Need to recompute all syntax. */ } } if (!got_clstr) EMSG(_("E400: No cluster specified")); *************** *** 5109,5120 **** * On first call for current buffer: Init growing array. */ static void init_syn_patterns() { ! curbuf->b_syn_patterns.ga_itemsize = sizeof(synpat_T); ! curbuf->b_syn_patterns.ga_growsize = 10; } /* * Get one pattern for a ":syntax match" or ":syntax region" command. * Stores the pattern and program in a synpat_T. --- 5236,5247 ---- * On first call for current buffer: Init growing array. */ static void init_syn_patterns() { ! curwin->w_s->b_syn_patterns.ga_itemsize = sizeof(synpat_T); ! curwin->w_s->b_syn_patterns.ga_growsize = 10; } /* * Get one pattern for a ":syntax match" or ":syntax region" command. * Stores the pattern and program in a synpat_T. *************** *** 5150,5160 **** ci->sp_prog = vim_regcomp(ci->sp_pattern, RE_MAGIC); p_cpo = cpo_save; if (ci->sp_prog == NULL) return NULL; ! ci->sp_ic = curbuf->b_syn_ic; /* * Check for a match, highlight or region offset. */ ++end; --- 5277,5287 ---- ci->sp_prog = vim_regcomp(ci->sp_pattern, RE_MAGIC); p_cpo = cpo_save; if (ci->sp_prog == NULL) return NULL; ! ci->sp_ic = curwin->w_s->b_syn_ic; /* * Check for a match, highlight or region offset. */ ++end; *************** *** 5249,5269 **** vim_free(key); key = vim_strnsave_up(arg_start, (int)(arg_end - arg_start)); if (STRCMP(key, "CCOMMENT") == 0) { if (!eap->skip) ! curbuf->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, (int)(arg_end - next_arg)); next_arg = skipwhite(arg_end); } else if (!eap->skip) ! curbuf->b_syn_sync_id = syn_name2id((char_u *)"Comment"); } else if ( STRNCMP(key, "LINES", 5) == 0 || STRNCMP(key, "MINLINES", 8) == 0 || STRNCMP(key, "MAXLINES", 8) == 0 || STRNCMP(key, "LINEBREAKS", 10) == 0) --- 5376,5396 ---- vim_free(key); key = vim_strnsave_up(arg_start, (int)(arg_end - arg_start)); if (STRCMP(key, "CCOMMENT") == 0) { if (!eap->skip) ! curwin->w_s->b_syn_sync_flags |= SF_CCOMMENT; if (!ends_excmd(*next_arg)) { arg_end = skiptowhite(next_arg); if (!eap->skip) ! 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) ! curwin->w_s->b_syn_sync_id = syn_name2id((char_u *)"Comment"); } else if ( STRNCMP(key, "LINES", 5) == 0 || STRNCMP(key, "MINLINES", 8) == 0 || STRNCMP(key, "MAXLINES", 8) == 0 || STRNCMP(key, "LINEBREAKS", 10) == 0) *************** *** 5281,5308 **** } n = getdigits(&arg_end); if (!eap->skip) { if (key[4] == 'B') ! curbuf->b_syn_sync_linebreaks = n; else if (key[1] == 'A') ! curbuf->b_syn_sync_maxlines = n; else ! curbuf->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; } } else if (STRCMP(key, "LINECONT") == 0) { ! if (curbuf->b_syn_linecont_pat != NULL) { EMSG(_("E403: syntax sync: line continuations pattern specified twice")); finished = TRUE; break; } --- 5408,5435 ---- } n = getdigits(&arg_end); if (!eap->skip) { if (key[4] == 'B') ! curwin->w_s->b_syn_sync_linebreaks = n; else if (key[1] == 'A') ! curwin->w_s->b_syn_sync_maxlines = n; else ! curwin->w_s->b_syn_sync_minlines = n; } } else if (STRCMP(key, "FROMSTART") == 0) { if (!eap->skip) { ! curwin->w_s->b_syn_sync_minlines = MAXLNUM; ! curwin->w_s->b_syn_sync_maxlines = 0; } } else if (STRCMP(key, "LINECONT") == 0) { ! if (curwin->w_s->b_syn_linecont_pat != NULL) { EMSG(_("E403: syntax sync: line continuations pattern specified twice")); finished = TRUE; break; } *************** *** 5314,5342 **** } if (!eap->skip) { /* store the pattern and compiled regexp program */ ! if ((curbuf->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; /* 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); p_cpo = cpo_save; ! if (curbuf->b_syn_linecont_prog == NULL) { ! vim_free(curbuf->b_syn_linecont_pat); ! curbuf->b_syn_linecont_pat = NULL; finished = TRUE; break; } } next_arg = skipwhite(arg_end + 1); --- 5441,5469 ---- } if (!eap->skip) { /* store the pattern and compiled regexp program */ ! if ((curwin->w_s->b_syn_linecont_pat = vim_strnsave(next_arg + 1, (int)(arg_end - next_arg - 1))) == NULL) { finished = TRUE; break; } ! 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 *)""; ! curwin->w_s->b_syn_linecont_prog = ! vim_regcomp(curwin->w_s->b_syn_linecont_pat, RE_MAGIC); p_cpo = cpo_save; ! if (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; finished = TRUE; break; } } next_arg = skipwhite(arg_end + 1); *************** *** 5362,5372 **** EMSG2(_("E404: Illegal arguments: %s"), arg_start); else if (!finished) { eap->nextcmd = check_nextcmd(arg_start); redraw_curbuf_later(NOT_VALID); ! syn_stack_free_all(curbuf); /* Need to recompute all syntax. */ } } /* * Convert a line of highlight group names into a list of group ID numbers. --- 5489,5499 ---- EMSG2(_("E404: Illegal arguments: %s"), arg_start); else if (!finished) { eap->nextcmd = check_nextcmd(arg_start); redraw_curbuf_later(NOT_VALID); ! syn_stack_free_all(curwin->w_s); /* Need to recompute all syntax. */ } } /* * Convert a line of highlight group names into a list of group ID numbers. *************** *** 5623,5634 **** while ((cur_si->si_flags & HL_TRANS_CONT) && cur_si > (stateitem_T *)(current_state.ga_data)) --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)) return TRUE; } if (list == NULL) return FALSE; --- 5750,5761 ---- while ((cur_si->si_flags & HL_TRANS_CONT) && cur_si > (stateitem_T *)(current_state.ga_data)) --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_buf2)[cur_si->si_idx].sp_syn), ! SYN_ITEMS(syn_buf2)[cur_si->si_idx].sp_flags & HL_CONTAINED)) return TRUE; } if (list == NULL) return FALSE; *************** *** 5679,5689 **** { if (item == id) return retval; if (item >= SYNID_CLUSTER) { ! scl_list = SYN_CLSTR(syn_buf)[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) { ++depth; --- 5806,5816 ---- { if (item == id) return retval; if (item >= SYNID_CLUSTER) { ! scl_list = SYN_CLSTR(syn_buf2)[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) { ++depth; *************** *** 5707,5716 **** --- 5834,5844 ---- 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}, {"list", syn_cmd_list}, {"manual", syn_cmd_manual}, *************** *** 5766,5783 **** if (eap->skip) --emsg_skip; } } int ! syntax_present(buf) ! buf_T *buf; { ! return (buf->b_syn_patterns.ga_len != 0 ! || buf->b_syn_clusters.ga_len != 0 ! || curbuf->b_keywtab != NULL ! || curbuf->b_keywtab_ic != NULL); } #if defined(FEAT_CMDL_COMPL) || defined(PROTO) static enum --- 5894,5924 ---- if (eap->skip) --emsg_skip; } } + void + ex_ownsyntax(eap) + exarg_T *eap; + { + char_u *arg = eap->arg; + + if (curwin->w_s == &curwin->w_buffer->s) { + curwin->w_s = (synblock_T *) alloc(sizeof(synblock_T)); + memset(curwin->w_s, 0, sizeof(synblock_T)); + } + apply_autocmds(EVENT_SYNTAX, arg, curbuf->b_fname, TRUE, curbuf); + } + int ! syntax_present(win) ! win_T *win; { ! return (win->w_s->b_syn_patterns.ga_len != 0 ! || win->w_s->b_syn_clusters.ga_len != 0 ! || win->w_s->b_keywtab != NULL ! || win->w_s->b_keywtab_ic != NULL); } #if defined(FEAT_CMDL_COMPL) || defined(PROTO) static enum *************** *** 5860,5870 **** if (curwin->w_buffer != syn_buf || lnum != current_lnum || col < (long)current_col) syntax_start(curwin, lnum); ! (void)get_syntax_attr((colnr_T)col); return (trans ? current_trans_id : current_id); } #endif --- 6001,6011 ---- if (curwin->w_buffer != syn_buf || lnum != current_lnum || col < (long)current_col) syntax_start(curwin, lnum); ! (void)get_syntax_attr((colnr_T)col, NULL); return (trans ? current_trans_id : current_id); } #endif *************** *** 5879,5889 **** { int level = 0; int i; /* Return quickly when there are no fold items at all. */ ! if (wp->w_buffer->b_syn_folditems != 0) { syntax_start(wp, lnum); for (i = 0; i < current_state.ga_len; ++i) if (CUR_STATE(i).si_flags & HL_FOLD) --- 6020,6030 ---- { int level = 0; int i; /* Return quickly when there are no fold items at all. */ ! if (wp->w_s->b_syn_folditems != 0) { syntax_start(wp, lnum); for (i = 0; i < current_state.ga_len; ++i) if (CUR_STATE(i).si_flags & HL_FOLD) *************** *** 5942,5951 **** --- 6083,6095 ---- "FoldColumn term=standout ctermbg=Grey ctermfg=DarkBlue guibg=Grey guifg=DarkBlue", "SignColumn term=standout ctermbg=Grey ctermfg=DarkBlue guibg=Grey guifg=DarkBlue", "DiffAdd term=bold ctermbg=LightBlue guibg=LightBlue", "DiffChange term=bold ctermbg=LightMagenta guibg=LightMagenta", "DiffDelete term=bold ctermfg=Blue ctermbg=LightCyan gui=bold guifg=Blue guibg=LightCyan", + #ifdef FEAT_CONCEAL + "Conceal ctermbg=LightGrey ctermfg=DarkGrey guibg=LightGrey guifg=DarkGrey", + #endif NULL }; static char *(highlight_init_dark[]) = { *************** *** 5963,5972 **** --- 6107,6119 ---- "FoldColumn term=standout ctermbg=DarkGrey ctermfg=Cyan guibg=Grey guifg=Cyan", "SignColumn term=standout ctermbg=DarkGrey ctermfg=Cyan guibg=Grey guifg=Cyan", "DiffAdd term=bold ctermbg=DarkBlue guibg=DarkBlue", "DiffChange term=bold ctermbg=DarkMagenta guibg=DarkMagenta", "DiffDelete term=bold ctermfg=Blue ctermbg=DarkCyan gui=bold guifg=Blue guibg=DarkCyan", + #ifdef FEAT_CONCEAL + "Conceal ctermbg=DarkGrey ctermfg=LightGrey guibg=DarkGrey guifg=LightGrey", + #endif NULL }; void init_highlight(both, reset) Index: src/version.c =================================================================== RCS file: /cvsroot/vim/vim/src/version.c,v retrieving revision 1.1710 diff -c -5 -r1.1710 version.c *** src/version.c 7 Jun 2004 17:15:22 -0000 1.1710 --- src/version.c 8 Jun 2004 08:53:44 -0000 *************** *** 131,150 **** --- 131,160 ---- #ifdef FEAT_COMMENTS "+comments", #else "-comments", #endif + #ifdef FEAT_CONCEAL + "+conceal", + #else + "-conceal", + #endif #ifdef FEAT_CRYPT "+cryptv", #else "-cryptv", #endif #ifdef FEAT_CSCOPE "+cscope", #else "-cscope", #endif + #ifdef FEAT_CURSORBIND + "+cursorbind", + #else + "-cursorbind", + #endif #if defined(FEAT_CON_DIALOG) && defined(FEAT_GUI_DIALOG) "+dialog_con_gui", #else # if defined(FEAT_CON_DIALOG) "+dialog_con", Index: src/vim.h =================================================================== RCS file: /cvsroot/vim/vim/src/vim.h,v retrieving revision 1.83 diff -c -5 -r1.83 vim.h *** src/vim.h 2 Jun 2004 15:51:48 -0000 1.83 --- src/vim.h 8 Jun 2004 08:53:45 -0000 *************** *** 674,683 **** --- 674,705 ---- # define SST_MAX_ENTRIES 1000 /* maximal size for state stack array */ # 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 */ + /* 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 HL_CONCEAL 0x20000L /* can be concealed */ + # define HL_CONCEALENDS 0x40000L /* can be concealed */ #endif /* Values for 'options' argument in do_search() and searchit() */ #define SEARCH_REV 0x01 /* go in reverse of previous dir. */ #define SEARCH_ECHO 0x02 /* echo the search command and handle options */ *************** *** 1073,1090 **** , HLF_FC /* Fold column */ , HLF_ADD /* Added diff line */ , HLF_CHD /* Changed diff line */ , HLF_DED /* Deleted diff line */ , HLF_TXD /* Text Changed in diff line */ , HLF_SC /* Sign column */ , HLF_COUNT /* MUST be the last one */ }; /* the HL_FLAGS must be in the same order as the HLF_ enums! */ #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', '>'} /* * Boolean constants */ #ifndef TRUE --- 1095,1113 ---- , HLF_FC /* Fold column */ , HLF_ADD /* Added diff line */ , 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_COUNT /* MUST be the last one */ }; /* the HL_FLAGS must be in the same order as the HLF_ enums! */ #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', 'x', '>'} /* * Boolean constants */ #ifndef TRUE Index: src/window.c =================================================================== RCS file: /cvsroot/vim/vim/src/window.c,v retrieving revision 1.70 diff -c -5 -r1.70 window.c *** src/window.c 14 May 2004 20:27:57 -0000 1.70 --- src/window.c 8 Jun 2004 08:53:46 -0000 *************** *** 769,778 **** --- 769,781 ---- /* * make the contents of the new window the same as the current one */ wp->w_buffer = curbuf; + #ifdef FEAT_SYN_HL + wp->w_s = &(curbuf->s); + #endif curbuf->b_nwindows++; wp->w_cursor = curwin->w_cursor; wp->w_valid = 0; wp->w_curswant = curwin->w_curswant; wp->w_set_curswant = curwin->w_set_curswant; *************** *** 2660,2669 **** --- 2663,2675 ---- curwin = win_alloc(NULL); curbuf = buflist_new(NULL, NULL, 1L, BLN_LISTED); if (curwin == NULL || curbuf == NULL) mch_exit(0); curwin->w_buffer = curbuf; + #ifdef FEAT_SYN_HL + curwin->w_s = &(curbuf->s); + #endif curbuf->b_nwindows = 1; /* there is one window */ #ifdef FEAT_WINDOWS curwin->w_alist = &global_alist; #endif win_init(curwin); /* init current window */ *************** *** 3151,3160 **** --- 3157,3172 ---- gui_mch_destroy_scrollbar(&wp->w_scrollbars[SBAR_LEFT]); gui_mch_destroy_scrollbar(&wp->w_scrollbars[SBAR_RIGHT]); } #endif /* FEAT_GUI */ + #ifdef FEAT_SYN_HL + /* free independent synblock */ + if (wp->w_s != &wp->w_buffer->s) + vim_free(wp->w_s); + #endif + win_remove(wp); vim_free(wp); } /* Index: src/proto/diff.pro =================================================================== RCS file: /cvsroot/vim/vim/src/proto/diff.pro,v retrieving revision 1.7 diff -c -5 -r1.7 diff.pro *** src/proto/diff.pro 4 Mar 2004 03:46:37 -0000 1.7 --- src/proto/diff.pro 8 Jun 2004 08:53:46 -0000 *************** *** 17,23 **** --- 17,24 ---- int diff_infold __ARGS((win_T *wp, linenr_T lnum)); 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: src/proto/move.pro =================================================================== RCS file: /cvsroot/vim/vim/src/proto/move.pro,v retrieving revision 1.5 diff -c -5 -r1.5 move.pro *** src/proto/move.pro 4 Mar 2004 03:46:37 -0000 1.5 --- src/proto/move.pro 8 Jun 2004 08:53:46 -0000 *************** *** 1,6 **** --- 1,7 ---- /* move.c */ + void do_check_cursorbind __ARGS((void)); void update_topline_redraw __ARGS((void)); void update_topline __ARGS((void)); void update_curswant __ARGS((void)); void check_cursor_moved __ARGS((win_T *wp)); void changed_window_setting __ARGS((void)); Index: src/proto/syntax.pro =================================================================== RCS file: /cvsroot/vim/vim/src/proto/syntax.pro,v retrieving revision 1.16 diff -c -5 -r1.16 syntax.pro *** src/proto/syntax.pro 27 Aug 2001 21:13:20 -0000 1.16 --- src/proto/syntax.pro 8 Jun 2004 08:53:46 -0000 *************** *** 1,15 **** /* syntax.c */ void syntax_start __ARGS((win_T *wp, linenr_T lnum)); ! void syn_stack_free_all __ARGS((buf_T *buf)); 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)); ! void syntax_clear __ARGS((buf_T *buf)); void ex_syntax __ARGS((exarg_T *eap)); ! int syntax_present __ARGS((buf_T *buf)); 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((long lnum, long col, int trans)); int syn_get_foldlevel __ARGS((win_T *wp, long lnum)); void init_highlight __ARGS((int both, int reset)); --- 1,16 ---- /* syntax.c */ + void ex_ownsyntax __ARGS((exarg_T *eap)); void syntax_start __ARGS((win_T *wp, linenr_T lnum)); ! 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 *p_flags)); ! void syntax_clear __ARGS((synblock_T *block)); void ex_syntax __ARGS((exarg_T *eap)); ! int syntax_present __ARGS((win_T *win)); 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((long lnum, long col, int trans)); int syn_get_foldlevel __ARGS((win_T *wp, long lnum)); void init_highlight __ARGS((int both, int reset)); Index: src/proto/screen.pro =================================================================== RCS file: /cvsroot/vim/vim/src/proto/screen.pro,v retrieving revision 1.21 diff -c -5 -r1.21 screen.pro *** src/proto/screen.pro 16 May 2003 00:32:27 -0000 1.21 --- src/proto/screen.pro 8 Jun 2004 08:53:46 -0000 *************** *** 41,46 **** --- 41,47 ---- int showmode __ARGS((void)); void unshowmode __ARGS((int force)); int redrawing __ARGS((void)); int messaging __ARGS((void)); void showruler __ARGS((int always)); + void update_single_line __ARGS((win_T *buf, linenr_T lnum)); /* vim: set ft=c : */ Index: runtime/doc/eval.txt =================================================================== RCS file: /cvsroot/vim/vim/runtime/doc/eval.txt,v retrieving revision 1.81 diff -c -5 -r1.81 eval.txt *** runtime/doc/eval.txt 7 Jun 2004 17:11:12 -0000 1.81 --- runtime/doc/eval.txt 8 Jun 2004 08:53:48 -0000 *************** *** 468,477 **** --- 468,484 ---- < *window-variable* *w:var* 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. + *global-variable* *g:var* Inside functions global variables are accessed with "g:". Omitting this will access a variable local to a function. But "g:" can also be used in any other place if you like. Index: runtime/doc/options.txt =================================================================== RCS file: /cvsroot/vim/vim/runtime/doc/options.txt,v retrieving revision 1.89 diff -c -5 -r1.89 options.txt *** runtime/doc/options.txt 7 Jun 2004 17:11:51 -0000 1.89 --- runtime/doc/options.txt 8 Jun 2004 08:53:51 -0000 *************** *** 1509,1518 **** --- 1509,1537 ---- As you can see, CTRL-N and CTRL-P can be used to do any 'iskeyword'- based expansion (eg dictionary |i_CTRL-X_CTRL-K|, included patterns |i_CTRL-X_CTRL-I|, tags |i_CTRL-X_CTRL-]| and normal expansions) + '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 {not in Vi} When 'confirm' is on, certain operations that would normally *************** *** 1831,1840 **** --- 1850,1873 ---- feature} {not in Vi} 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. + *'debug'* 'debug' string (default "") global {not in Vi} When set to "msg", error messages that would otherwise be omitted will *************** *** 3076,3086 **** M:ModeMsg,n:LineNr,r:Question, s:StatusLine,S:StatusLineNC,c:VertSplit t:Title,v:Visual,w:WarningMsg,W:WildMenu, f:Folded,F:FoldColumn,A:DiffAdd, C:DiffChange,D:DiffDelete,T:DiffText, ! >:SignColumn") global {not in Vi} This option can be used to set highlighting mode for various occasions. It is a comma separated list of character pairs. The first character in a pair gives the occasion, the second the mode to --- 3109,3119 ---- M:ModeMsg,n:LineNr,r:Question, s:StatusLine,S:StatusLineNC,c:VertSplit t:Title,v:Visual,w:WarningMsg,W:WildMenu, f:Folded,F:FoldColumn,A:DiffAdd, C:DiffChange,D:DiffDelete,T:DiffText, ! >:SignColumn,x:Conceal") global {not in Vi} This option can be used to set highlighting mode for various occasions. It is a comma separated list of character pairs. The first character in a pair gives the occasion, the second the mode to *************** *** 3108,3117 **** --- 3141,3152 ---- |xterm-clipboard|. |hl-WarningMsg| w warning messages |hl-WildMenu| W wildcard matches displayed for 'wildmenu' |hl-Folded| f line used for closed folds |hl-FoldColumn| F 'foldcolumn' + |hl-Conceal| x the placeholders used for concealed characters + (see 'conceallevel') |hl-SignColumn| > column used for |signs| The display modes are: r reverse (termcap entry "mr" and "me") i italic (termcap entry "ZH" and "ZR") *************** *** 3816,3825 **** --- 3851,3862 ---- off and the line continues beyond the right of the screen. 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. The characters ':' and ',' should not be used. UTF-8 characters can be used when 'encoding' is "utf-8", otherwise only printable characters are allowed. Index: runtime/doc/syntax.txt =================================================================== RCS file: /cvsroot/vim/vim/runtime/doc/syntax.txt,v retrieving revision 1.68 diff -c -5 -r1.68 syntax.txt *** runtime/doc/syntax.txt 7 Jun 2004 17:12:25 -0000 1.68 --- runtime/doc/syntax.txt 8 Jun 2004 08:53:53 -0000 *************** *** 33,43 **** 11. Listing syntax items |:syntax| 12. Highlight command |:highlight| 13. Linking groups |:highlight-link| 14. Cleaning up |:syn-clear| 15. Highlighting tags |tag-highlight| ! 16. Color xterms |xterm-color| {Vi does not have any of these commands} Syntax highlighting is not available when the |+syntax| feature has been disabled at compile time. --- 33,44 ---- 11. Listing syntax items |:syntax| 12. Highlight command |:highlight| 13. Linking groups |:highlight-link| 14. Cleaning up |:syn-clear| 15. Highlighting tags |tag-highlight| ! 16. Window-local syntax |:ownsyntax| ! 17. Color xterms |xterm-color| {Vi does not have any of these commands} Syntax highlighting is not available when the |+syntax| feature has been disabled at compile time. *************** *** 2733,2756 **** 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 These arguments can be used for all three commands: contained containedin nextgroup transparent skipwhite skipnl skipempty contained *:syn-contained* When the "contained" argument is given, this item will not be recognized at the top level, but only when it is mentioned in the "contains" field of --- 2734,2780 ---- 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 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 transparent skipwhite skipnl skipempty + conceal *:syn-conceal* + + When the "conceal" argument is given, the item is marked as concealable. + Whether or not it is actually concealed depends on the setting on the + 'conceallevel' option. + + concealends *:syn-concealends* + + When the "concealends" argument is given, the start and end matches of + the region, but not the contents of the region, are marked as concealable. + Whether or not they are actually concealed depends on the setting on the + 'conceallevel' option. The ends of a region can only be concealed separately + in this way when they have their own highlighting via "matchgroup" + + cchar *:syn-cchar* + + The "cchar" argument defines the character shown in place of the item + when it is concealed (setting "cchar" only makes sense when the conceal + argument is given.) If "cchar" is not set then the default conceal + character defined in the 'listchars' option is used. Example: > + :syntax match Entity "&" conceal cchar=& contained *:syn-contained* When the "contained" argument is given, this item will not be recognized at the top level, but only when it is mentioned in the "contains" field of *************** *** 3003,3012 **** --- 3027,3046 ---- precendence. 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* In the syntax commands, a pattern must be surrounded by two identical characters. This is like it works for the ":s" command. The most common to *************** *** 3753,3762 **** --- 3787,3799 ---- *highlight-groups* *highlight-default* 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* CursorIM like Cursor, but used when in IME mode |CursorIM| *hl-Directory* *************** *** 4013,4022 **** --- 4050,4081 ---- autocmd BufRead,BufNewFile *.[ch] if filereadable(fname) 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* Most color xterms have only eight colors. If you don't get colors with the default setup, it should work with these lines in your .vimrc: > :if &term =~ "xterm" Index: runtime/optwin.vim =================================================================== RCS file: /cvsroot/vim/vim/runtime/optwin.vim,v retrieving revision 1.27 diff -c -5 -r1.27 optwin.vim *** runtime/optwin.vim 8 May 2004 00:02:13 -0000 1.27 --- runtime/optwin.vim 8 Jun 2004 08:53:54 -0000 *************** *** 357,366 **** --- 357,369 ---- call append("$", "listchars\tlist of strings used for list mode") call OptionG("lcs", &lcs) call append("$", "number\tshow the line number for each line") call append("$", "\t(local to window)") call BinOptionL("nu") + call append("$", "conceallevel\tcontrols whether concealable elements are hidden") + call append("$", "\t(local to window)") + call append("$", " \tset conc=" . &conc) call Header("syntax and highlighting") call append("$", "background\t\"dark\" or \"light\"; the background color brightness") call OptionG("bg", &bg)