Mercurial > vim
changeset 423:e40d32d8d4e7
updated for version 7.0110
author | vimboss |
---|---|
date | Tue, 19 Jul 2005 22:18:49 +0000 |
parents | 169f2a51b527 |
children | f7f16f63a19c |
files | src/search.c |
diffstat | 1 files changed, 277 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/src/search.c +++ b/src/search.c @@ -3407,6 +3407,10 @@ extend: return OK; } +/* + * Find block under the cursor, cursor at end. + * "what" and "other" are two matching parenthesis/paren/etc. + */ int current_block(oap, count, include, what, other) oparg_T *oap; @@ -3421,10 +3425,10 @@ current_block(oap, count, include, what, pos_T *end_pos; pos_T old_start, old_end; char_u *save_cpo; - int sol = FALSE; /* { at start of line */ + int sol = FALSE; /* '{' at start of line */ old_pos = curwin->w_cursor; - old_end = curwin->w_cursor; /* remember where we started */ + old_end = curwin->w_cursor; /* remember where we started */ old_start = old_end; /* @@ -3435,11 +3439,12 @@ current_block(oap, count, include, what, #endif { setpcmark(); - if (what == '{') /* ignore indent */ + if (what == '{') /* ignore indent */ while (inindent(1)) if (inc_cursor() != 0) break; - if (gchar_cursor() == what) /* cursor on '(' or '{' */ + if (gchar_cursor() == what) + /* cursor on '(' or '{', move cursor just after it */ ++curwin->w_cursor.col; } #ifdef FEAT_VISUAL @@ -3455,7 +3460,7 @@ current_block(oap, count, include, what, /* * Search backwards for unclosed '(', '{', etc.. * Put this position in start_pos. - * Ignory quotes here. + * Ignore quotes here. */ save_cpo = p_cpo; p_cpo = (char_u *)"%"; @@ -3554,6 +3559,273 @@ current_block(oap, count, include, what, return OK; } +static int in_html_tag __ARGS((int)); + +/* + * Return TRUE if the cursor is on a "<aaa>" tag. Ignore "<aaa/>". + * When "end_tag" is TRUE return TRUE if the cursor is on "</aaa>". + */ + static int +in_html_tag(end_tag) + int end_tag; +{ + char_u *line = ml_get_curline(); + char_u *p; + int c; + int lc = NUL; + pos_T pos; + +#ifdef FEAT_MBYTE + if (enc_dbcs) + { + char_u *lp = NULL; + + /* We search forward until the cursor, because searching backwards is + * very slow for DBCS encodings. */ + for (p = line; p < line + curwin->w_cursor.col; mb_ptr_adv(p)) + if (*p == '>' || *p == '<') + { + lc = *p; + lp = p; + } + if (*p != '<') /* check for '<' under cursor */ + { + if (lc != '<') + return FALSE; + p = lp; + } + } + else +#endif + { + for (p = line + curwin->w_cursor.col; p > line; ) + { + if (*p == '<') /* find '<' under/before cursor */ + break; + mb_ptr_back(line, p); + if (*p == '>') /* find '>' before cursor */ + break; + } + if (*p != '<') + return FALSE; + } + + pos.lnum = curwin->w_cursor.lnum; + pos.col = p - line; + + mb_ptr_adv(p); + if (end_tag) + /* check that there is a '/' after the '<' */ + return *p == '/'; + + /* check that there is no '/' after the '<' */ + if (*p == '/') + return FALSE; + + /* check that the matching '>' is not preceded by '/' */ + for (;;) + { + if (inc(&pos) < 0) + return FALSE; + c = *ml_get_pos(&pos); + if (c == '>') + break; + lc = c; + } + return lc != '/'; +} + +/* + * Find tag block under the cursor, cursor at end. + */ + int +current_tagblock(oap, count_arg, include) + oparg_T *oap; + long count_arg; + int include; /* TRUE == include white space */ +{ + long count = count_arg; + long n; + pos_T old_pos; + pos_T start_pos; + pos_T end_pos; + pos_T old_start, old_end; + char_u *spat, *epat; + char_u *p; + char_u *cp; + int len; + int r; + int do_include = include; + int save_p_ws = p_ws; + int retval = FAIL; + + p_ws = FALSE; + + old_pos = curwin->w_cursor; + old_end = curwin->w_cursor; /* remember where we started */ + old_start = old_end; + + /* + * If we start on "<aaa>" use the whole block inclusive. + */ +#ifdef FEAT_VISUAL + if (!VIsual_active || equalpos(VIsual, curwin->w_cursor)) +#endif + { + setpcmark(); + + /* ignore indent */ + while (inindent(1)) + if (inc_cursor() != 0) + break; + + if (in_html_tag(FALSE)) + { + /* cursor on start tag, move to just after it */ + while (*ml_get_cursor() != '>') + if (inc_cursor() < 0) + break; + } + else if (in_html_tag(TRUE)) + { + /* cursor on end tag, move to just before it */ + while (*ml_get_cursor() != '<') + if (dec_cursor() < 0) + break; + dec_cursor(); + old_end = curwin->w_cursor; + } + } +#ifdef FEAT_VISUAL + else if (lt(VIsual, curwin->w_cursor)) + { + old_start = VIsual; + curwin->w_cursor = VIsual; /* cursor at low end of Visual */ + } + else + old_end = VIsual; +#endif + +again: + /* + * Search backwards for unclosed "<aaa>". + * Put this position in start_pos. + */ + for (n = 0; n < count; ++n) + { + if (do_searchpair((char_u *)"<[^ \t>/!]\\+\\%(\\_s\\_[^>]\\{-}[^/]>\\|$\\|>\\)", + (char_u *)"", + (char_u *)"</[^>]*>", BACKWARD, (char_u *)"", 0) <= 0) + { + curwin->w_cursor = old_pos; + goto theend; + } + } + start_pos = curwin->w_cursor; + + /* + * Search for matching "</aaa>". First isolate the "aaa". + */ + inc_cursor(); + p = ml_get_cursor(); + for (cp = p; *cp != NUL && *cp != '>' && !vim_iswhite(*cp); mb_ptr_adv(cp)) + ; + len = cp - p; + if (len == 0) + { + curwin->w_cursor = old_pos; + goto theend; + } + spat = alloc(len + 29); + epat = alloc(len + 9); + if (spat == NULL || epat == NULL) + { + vim_free(spat); + vim_free(epat); + curwin->w_cursor = old_pos; + goto theend; + } + sprintf((char *)spat, "<%.*s\\%%(\\_[^>]\\{-}[^/]>\\|>\\)\\c", len, p); + sprintf((char *)epat, "</%.*s>\\c", len, p); + + r = do_searchpair(spat, (char_u *)"", epat, FORWARD, (char_u *)"", 0); + + vim_free(spat); + vim_free(epat); + + if (r < 1 || lt(curwin->w_cursor, old_end)) + { + /* Can't find other end or it's before the previous end. Could be a + * HTML tag that doesn't have a matching end. Search backwards for + * another starting tag. */ + count = 1; + curwin->w_cursor = start_pos; + goto again; + } + + if (do_include || r < 1) + { + /* Include up to the '>'. */ + while (*ml_get_cursor() != '>') + if (inc_cursor() < 0) + break; + } + else + { + /* Exclude the '<' of the end tag. */ + if (*ml_get_cursor() == '<') + dec_cursor(); + } + end_pos = curwin->w_cursor; + + if (!do_include) + { + /* Exclude the start tag. */ + curwin->w_cursor = start_pos; + while (inc_cursor() >= 0) + if (*ml_get_cursor() == '>' && lt(curwin->w_cursor, end_pos)) + { + inc_cursor(); + start_pos = curwin->w_cursor; + break; + } + curwin->w_cursor = end_pos; + + /* If we now have the same start as before reset "do_include" and try + * again. */ + if (equalpos(start_pos, old_start)) + { + do_include = TRUE; + curwin->w_cursor = old_start; + count = count_arg; + goto again; + } + } + +#ifdef FEAT_VISUAL + if (VIsual_active) + { + if (*p_sel == 'e') + ++curwin->w_cursor.col; + VIsual = start_pos; + VIsual_mode = 'v'; + redraw_curbuf_later(INVERTED); /* update the inversion */ + showmode(); + } + else +#endif + { + oap->start = start_pos; + oap->motion_type = MCHAR; + oap->inclusive = TRUE; + } + retval = OK; + +theend: + p_ws = save_p_ws; + return retval; +} + int current_par(oap, count, include, type) oparg_T *oap;