summaryrefslogtreecommitdiff
path: root/src/search.c
diff options
context:
space:
mode:
authorvimboss <devnull@localhost>2004-07-02 15:38:35 +0000
committervimboss <devnull@localhost>2004-07-02 15:38:35 +0000
commita2182662d4878eaa72e5509c8d6aa3a6274b3319 (patch)
tree7586fe6160998a4c76a48dab221e38efe55257ef /src/search.c
parent81f1313fa087e610e3431e00bb9d47eeb8f5d1dc (diff)
downloadvim-a2182662d4878eaa72e5509c8d6aa3a6274b3319.tar.gz
updated for version 7.0004
Diffstat (limited to 'src/search.c')
-rw-r--r--src/search.c262
1 files changed, 262 insertions, 0 deletions
diff --git a/src/search.c b/src/search.c
index ace8fa83..ddf2feb6 100644
--- a/src/search.c
+++ b/src/search.c
@@ -3603,7 +3603,269 @@ extend:
return OK;
}
+
+static int find_next_quote __ARGS((char_u *top_ptr, int col, int quotechar, char_u *escape));
+static int find_prev_quote __ARGS((char_u *line, int col_start, int quotechar, char_u *escape));
+
+/*
+ * Search quote char from string line[col].
+ * Quote character escaped by one of the characters in "escape" is not counted
+ * as a quote.
+ * Returns column number of "quotechar" or -1 when not found.
+ */
+ static int
+find_next_quote(line, col, quotechar, escape)
+ char_u *line;
+ int col;
+ int quotechar;
+ char_u *escape; /* escape characters, can be NULL */
+{
+ int c;
+
+ while (1)
+ {
+ c = line[col];
+ if (c == NUL)
+ return -1;
+ else if (escape != NULL && vim_strchr(escape, c))
+ ++col;
+ else if (c == quotechar)
+ break;
+#ifdef FEAT_MBYTE
+ if (has_mbyte)
+ col += (*mb_ptr2len_check)(line + col);
+ else
+#endif
+ ++col;
+ }
+ return col;
+}
+
+/*
+ * Search backwards in "line" from column "col_start" to find "quotechar".
+ * Quote character escaped by one of the characters in "escape" is not counted
+ * as a quote.
+ * Return the found column or zero.
+ */
+ static int
+find_prev_quote(line, col_start, quotechar, escape)
+ char_u *line;
+ int col_start;
+ int quotechar;
+ char_u *escape; /* escape characters, can be NULL */
+{
+ int n;
+
+ while (col_start > 0)
+ {
+ --col_start;
+#ifdef FEAT_MBYTE
+ col_start -= (*mb_head_off)(line, line + col_start);
+#endif
+ n = 0;
+ if (escape != NULL)
+ while (col_start - n > 0 && vim_strchr(escape,
+ line[col_start - n - 1]) != NULL)
+ ++n;
+ if (n & 1)
+ col_start -= n; /* uneven number of escape chars, skip it */
+ else if (line[col_start] == quotechar)
+ break;
+ }
+ return col_start;
+}
+
+/*
+ * Find quote under the cursor, cursor at end.
+ * Returns TRUE if found, else FALSE.
+ */
+ int
+current_quote(oap, count, include, quotechar)
+ oparg_T *oap;
+ long count;
+ int include; /* TRUE == include quote char */
+ int quotechar; /* Quote character */
+{
+ char_u *line = ml_get_curline();
+ int col_end;
+ int col_start = curwin->w_cursor.col;
+ int inclusive = FALSE;
+#ifdef FEAT_VISUAL
+ int vis_empty = TRUE; /* Visual selection <= 1 char */
+ int vis_bef_curs = FALSE; /* Visual starts before cursor */
+
+ /* Correct cursor when 'selection' is exclusive */
+ if (VIsual_active)
+ {
+ if (*p_sel == 'e' && vis_bef_curs)
+ dec_cursor();
+ vis_empty = equalpos(VIsual, curwin->w_cursor);
+ vis_bef_curs = lt(VIsual, curwin->w_cursor);
+ }
+ if (!vis_empty && line[col_start] == quotechar)
+ {
+ /* Already selecting something and on a quote character. Find the
+ * next quoted string. */
+ if (vis_bef_curs)
+ {
+ /* Assume we are on a closing quote: move to after the next
+ * opening quote. */
+ col_start = find_next_quote(line, col_start + 1, quotechar, NULL);
+ if (col_start < 0)
+ return FALSE;
+ col_end = find_next_quote(line, col_start + 1, quotechar,
+ curbuf->b_p_qe);
+ if (col_end < 0)
+ {
+ /* We were on a starting quote perhaps? */
+ col_end = col_start;
+ col_start = curwin->w_cursor.col;
+ }
+ }
+ else
+ {
+ col_end = find_prev_quote(line, col_start, quotechar, NULL);
+ if (line[col_end] != quotechar)
+ return FALSE;
+ col_start = find_prev_quote(line, col_end, quotechar,
+ curbuf->b_p_qe);
+ if (line[col_start] != quotechar)
+ {
+ /* We were on an ending quote perhaps? */
+ col_start = col_end;
+ col_end = curwin->w_cursor.col;
+ }
+ }
+ }
+ else
+#endif
+
+ if (line[col_start] == quotechar
+#ifdef FEAT_VISUAL
+ || !vis_empty
#endif
+ )
+ {
+ int first_col = col_start;
+
+#ifdef FEAT_VISUAL
+ if (!vis_empty)
+ {
+ if (vis_bef_curs)
+ first_col = find_next_quote(line, col_start, quotechar, NULL);
+ else
+ first_col = find_prev_quote(line, col_start, quotechar, NULL);
+ }
+#endif
+ /* The cursor is on a quote, we don't know if it's the opening or
+ * closing quote. Search from the start of the line to find out.
+ * Also do this when there is a Visual area, a' may leave the cursor
+ * in between two strings. */
+ col_start = 0;
+ while (1)
+ {
+ /* Find open quote character. */
+ col_start = find_next_quote(line, col_start, quotechar, NULL);
+ if (col_start < 0 || col_start > first_col)
+ return FALSE;
+ /* Find close quote character. */
+ col_end = find_next_quote(line, col_start + 1, quotechar,
+ curbuf->b_p_qe);
+ if (col_end < 0)
+ return FALSE;
+ /* If is cursor between start and end quote character, it is
+ * target text object. */
+ if (col_start <= first_col && first_col <= col_end)
+ break;
+ col_start = col_end + 1;
+ }
+ }
+ else
+ {
+ /* Search backward for a starting quote. */
+ col_start = find_prev_quote(line, col_start, quotechar, curbuf->b_p_qe);
+ if (line[col_start] != quotechar)
+ {
+ /* No quote before the cursor, look after the cursor. */
+ col_start = find_next_quote(line, col_start, quotechar, NULL);
+ if (col_start < 0)
+ return FALSE;
+ }
+
+ /* Find close quote character. */
+ col_end = find_next_quote(line, col_start + 1, quotechar,
+ curbuf->b_p_qe);
+ if (col_end < 0)
+ return FALSE;
+ }
+
+ /* When "include" is TRUE, include spaces after closing quote or before
+ * the starting quote. */
+ if (include)
+ {
+ if (vim_iswhite(line[col_end + 1]))
+ while (vim_iswhite(line[col_end + 1]))
+ ++col_end;
+ else
+ while (col_start > 0 && vim_iswhite(line[col_start - 1]))
+ --col_start;
+ }
+
+ /* Set start position */
+ if (!include)
+ ++col_start;
+ curwin->w_cursor.col = col_start;
+#ifdef FEAT_VISUAL
+ if (VIsual_active)
+ {
+ if (vis_empty)
+ {
+ VIsual = curwin->w_cursor;
+ redraw_curbuf_later(INVERTED);
+ }
+ }
+ else
+#endif
+ {
+ oap->start = curwin->w_cursor;
+ oap->motion_type = MCHAR;
+ }
+
+ /* Set end position. */
+ curwin->w_cursor.col = col_end;
+ if (include && inc_cursor() == 2)
+ inclusive = TRUE;
+#ifdef FEAT_VISUAL
+ if (VIsual_active)
+ {
+ if (vis_empty || vis_bef_curs)
+ {
+ /* decrement cursor when 'selection' is not exclusive */
+ if (*p_sel != 'e')
+ dec_cursor();
+ }
+ else
+ {
+ /* Cursor is at start of Visual area. */
+ curwin->w_cursor.col = col_start;
+ }
+ if (VIsual_mode == 'V')
+ {
+ VIsual_mode = 'v';
+ redraw_cmdline = TRUE; /* show mode later */
+ }
+ }
+ else
+#endif
+ {
+ /* Set inclusive and other oap's flags. */
+ oap->inclusive = inclusive;
+ }
+
+ return OK;
+}
+
+#endif /* FEAT_TEXTOBJ */
#if defined(FEAT_LISP) || defined(FEAT_CINDENT) || defined(FEAT_TEXTOBJ) \
|| defined(PROTO)