⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 search.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:
	     * Move forward to the end of this word.
	     */
	    if (skip_chars(cls(), FORWARD))
		return FAIL;
	}
	dec_cursor();			/* overshot - one char backward */
finished:
	stop = FALSE;			/* we move only one word less */
    }
    return OK;
}

/*
 * bckend_word(count, type) - move back to the end of the word
 *
 * If 'eol' is TRUE, stop at end of line.
 *
 * Returns FAIL if start of the file was reached.
 */
    int
bckend_word(count, type, eol)
    long	count;
    int		type;
    int		eol;
{
    int		sclass;	    /* starting class */
    int		i;

    stype = type;
    while (--count >= 0)
    {
	sclass = cls();
	if ((i = dec_cursor()) == -1)
	    return FAIL;
	if (eol && i == 1)
	    return OK;

	/*
	 * Move backward to before the start of this word.
	 */
	if (sclass != 0)
	{
	    while (cls() == sclass)
		if ((i = dec_cursor()) == -1 || (eol && i == 1))
		    return OK;
	}

	/*
	 * Move backward to end of the previous word
	 */
	while (cls() == 0)
	{
	    if (curwin->w_cursor.col == 0 && lineempty(curwin->w_cursor.lnum))
		break;
	    if ((i = dec_cursor()) == -1 || (eol && i == 1))
		return OK;
	}
    }
    return OK;
}

/*
 * Skip a row of characters of the same class.
 * Return TRUE when end-of-file reached, FALSE otherwise.
 */
    static int
skip_chars(cclass, dir)
    int	    cclass;
    int	    dir;
{
    while (cls() == cclass)
	if ((dir == FORWARD ? inc_cursor() : dec_cursor()) == -1)
	    return TRUE;
    return FALSE;
}

#ifdef TEXT_OBJECTS
/*
 * Go back to the start of the word or the start of white space
 */
    static void
back_in_line()
{
    int		sclass;		    /* starting class */

    sclass = cls();
    for (;;)
    {
	if (curwin->w_cursor.col == 0)	    /* stop at start of line */
	    break;
	--curwin->w_cursor.col;
	if (cls() != sclass)		    /* stop at start of word */
	{
	    ++curwin->w_cursor.col;
	    break;
	}
    }
}

    static void
find_first_blank(posp)
    FPOS    *posp;
{
    int	    c;

    while (decl(posp) != -1)
    {
	c = gchar(posp);
	if (!vim_iswhite(c))
	{
	    incl(posp);
	    break;
	}
    }
}

/*
 * Skip count/2 sentences and count/2 separating white spaces.
 */
    static void
findsent_forward(count, at_start_sent)
    long    count;
    int	    at_start_sent;	/* cursor is at start of sentence */
{
    while (count--)
    {
	findsent(FORWARD, 1L);
	if (at_start_sent)
	    find_first_blank(&curwin->w_cursor);
	if (count == 0 || at_start_sent)
	    decl(&curwin->w_cursor);
	at_start_sent = !at_start_sent;
    }
}

/*
 * Find word under cursor, cursor at end.
 * Used while an operator is pending, and in Visual mode.
 */
    int
current_word(oap, count, include, type)
    OPARG	*oap;
    long	count;
    int		include;    /* TRUE: include word and white space */
    int		type;	    /* FALSE == word, TRUE == WORD */
{
    FPOS	start_pos;
    FPOS	pos;
    int		inclusive = TRUE;

    stype = type;

    /* Correct cursor when 'selection' is exclusive */
    if (VIsual_active && *p_sel == 'e' && lt(VIsual, curwin->w_cursor))
	dec_cursor();

    /*
     * When Visual mode is not active, or when the VIsual area is only one
     * character, select the word and/or white space under the cursor.
     */
    if (!VIsual_active || equal(curwin->w_cursor, VIsual))
    {
	/*
	 * Go to start of current word or white space.
	 */
	back_in_line();
	start_pos = curwin->w_cursor;

	/*
	 * If the start is on white space, and white space should be included
	 * ("	word"), or start is not on white space, and white space should
	 * not be included ("word"), find end of word.
	 */
	if ((cls() == 0) == include)
	{
	    if (end_word(1L, type, TRUE, TRUE) == FAIL)
		return FAIL;
	}
	else
	{
	    /*
	     * If the start is not on white space, and white space should be
	     * included ("word	 "), or start is on white space and white
	     * space should not be included ("	 "), find start of word.
	     */
	    if (fwd_word(1L, type, TRUE) == FAIL)
		return FAIL;
	    /*
	     * If end is just past a new-line, we don't want to include the
	     * first character on the line
	     */
	    if (oneleft() == FAIL)	/* put cursor on last char of area */
		inclusive = FALSE;
	    else if (include)
	    {
		/*
		 * If we don't include white space at the end, move the start
		 * to include some white space there. This makes "daw" work
		 * better on the last word in a sentence. Don't delete white
		 * space at start of line (indent).
		 */
		if (cls() != 0)
		{
		    pos = curwin->w_cursor;	/* save cursor position */
		    curwin->w_cursor = start_pos;
		    if (oneleft() == OK)
		    {
			back_in_line();
			if (cls() == 0 && curwin->w_cursor.col > 0)
			    start_pos = curwin->w_cursor;
		    }
		    curwin->w_cursor = pos;	/* put cursor back at end */
		}
	    }
	}

	if (VIsual_active)
	{
	    /* should do something when inclusive == FALSE ! */
	    VIsual = start_pos;
	    VIsual_mode = 'v';
	    update_curbuf(NOT_VALID);	    /* update the inversion */
	}
	else
	{
	    oap->start = start_pos;
	    oap->motion_type = MCHAR;
	}
	--count;
    }

    /*
     * When count is still > 0, extend with more objects.
     */
    while (count > 0)
    {
	inclusive = TRUE;
	if (VIsual_active && lt(curwin->w_cursor, VIsual))
	{
	    /*
	     * In Visual mode, with cursor at start: move cursor back.
	     */
	    if (decl(&curwin->w_cursor) == -1)
		return FAIL;
	    if (include != (cls() != 0))
	    {
		if (bck_word(1L, type, TRUE) == FAIL)
		    return FAIL;
	    }
	    else
	    {
		if (bckend_word(1L, type, TRUE) == FAIL)
		    return FAIL;
		(void)incl(&curwin->w_cursor);
	    }
	}
	else
	{
	    /*
	     * Move cursor forward one word and/or white area.
	     */
	    if (incl(&curwin->w_cursor) == -1)
		return FAIL;
	    if (include != (cls() == 0))
	    {
		if (fwd_word(1L, type, TRUE) == FAIL)
		    return FAIL;
		/*
		 * If end is just past a new-line, we don't want to include
		 * the first character on the line
		 */
		if (oneleft() == FAIL)	/* put cursor on last char of white */
		    inclusive = FALSE;
	    }
	    else
	    {
		if (end_word(1L, type, TRUE, TRUE) == FAIL)
		    return FAIL;
	    }
	}
	--count;
    }
    if (VIsual_active)
    {
	if (*p_sel == 'e' && inclusive && lt(VIsual, curwin->w_cursor))
	    inc_cursor();
    }
    else
	oap->inclusive = inclusive;

    return OK;
}

/*
 * Find sentence(s) under the cursor, cursor at end.
 * When Visual active, extend it by one or more sentences.
 */
    int
current_sent(oap, count, include)
    OPARG   *oap;
    long    count;
    int	    include;
{
    FPOS    start_pos;
    FPOS    pos;
    int	    start_blank;
    int	    c;
    int	    at_start_sent;
    long    ncount;

    start_pos = curwin->w_cursor;
    pos = start_pos;
    findsent(FORWARD, 1L);	/* Find start of next sentence. */

    /*
     * When visual area is bigger than one character: Extend it.
     */
    if (VIsual_active && !equal(start_pos, VIsual))
    {
extend:
	if (lt(start_pos, VIsual))
	{
	    /*
	     * Cursor at start of Visual area.
	     * Find out where we are:
	     * - in the white space before a sentence
	     * - in a sentence or just after it
	     * - at the start of a sentence
	     */
	    at_start_sent = TRUE;
	    decl(&pos);
	    while (lt(pos, curwin->w_cursor))
	    {
		c = gchar(&pos);
		if (!vim_iswhite(c))
		{
		    at_start_sent = FALSE;
		    break;
		}
		incl(&pos);
	    }
	    if (!at_start_sent)
	    {
		findsent(BACKWARD, 1L);
		if (equal(curwin->w_cursor, start_pos))
		    at_start_sent = TRUE;  /* exactly at start of sentence */
		else
		    /* inside a sentence, go to its end (start of next) */
		    findsent(FORWARD, 1L);
	    }
	    if (include)	/* "as" gets twice as much as "is" */
		count *= 2;
	    while (count--)
	    {
		if (at_start_sent)
		    find_first_blank(&curwin->w_cursor);
		c = gchar_cursor();
		if (!at_start_sent || (!include && !vim_iswhite(c)))
		    findsent(BACKWARD, 1L);
		at_start_sent = !at_start_sent;
	    }
	}
	else
	{
	    /*
	     * Cursor at end of Visual area.
	     * Find out where we are:
	     * - just before a sentence
	     * - just before or in the white space before a sentence
	     * - in a sentence
	     */
	    incl(&pos);
	    at_start_sent = TRUE;
	    if (!equal(pos, curwin->w_cursor))	/* not just before a sentence */
	    {
		at_start_sent = FALSE;
		while (lt(pos, curwin->w_cursor))
		{
		    c = gchar(&pos);
		    if (!vim_iswhite(c))
		    {
			at_start_sent = TRUE;
			break;
		    }
		    incl(&pos);
		}
		if (at_start_sent)	/* in the sentence */
		    findsent(BACKWARD, 1L);
		else		/* in/before white before a sentence */
		    curwin->w_cursor = start_pos;
	    }

	    if (include)	/* "as" gets twice as much as "is" */
		count *= 2;
	    findsent_forward(count, at_start_sent);
	}
	return OK;
    }

    /*
     * If cursor started on blank, check if it is just before the start of the
     * next sentence.
     */
    while (c = gchar(&pos), vim_iswhite(c))	/* vim_iswhite() is a macro */
	incl(&pos);
    if (equal(pos, curwin->w_cursor))
    {
	start_blank = TRUE;
	find_first_blank(&start_pos);	/* go back to first blank */
    }
    else
    {
	start_blank = FALSE;
	findsent(BACKWARD, 1L);
	start_pos = curwin->w_cursor;
    }
    if (include)
	ncount = count * 2;
    else
	ncount = count;
    if (!include && start_blank)
	--ncount;
    if (ncount)
	findsent_forward(ncount, TRUE);

    if (include)
    {
	/*
	 * If the blank in front of the sentence is included, exclude the
	 * blanks at the end of the sentence, go back to the first blank.
	 * If there are no trailing blanks, try to include leading blanks.
	 */
	if (start_blank)
	    find_first_blank(&curwin->w_cursor);
	else if (c = gchar_cursor(), !vim_iswhite(c))
	    find_first_blank(&start_pos);
    }

    if (VIsual_active)
    {
	/* avoid getting stuck with "is" on a single space before a sent. */
	if (equal(start_pos, curwin->w_cursor))
	    goto extend;
	VIsual = start_pos;
	VIsual_mode = 'v';
	update_curbuf(NOT_VALID);	/* update the inversion */
    }
    else
    {
	/* include a newline after the sentence */
	incl(&curwin->w_cursor);
	oap->start = start_pos;
	oap->motion_type = MCHAR;
	oap->inclusive = FALSE;
    }
    return OK;
}

    int
current_block(oap, count, include, what, other)
    OPARG	*oap;
    long	count;
    int		include;	/* TRUE == include white space */
    int		what;		/* '(', '{', etc. */
    int		other;		/* ')', '}', etc. */
{
    FPOS	old_pos;
    FPOS	*pos = NULL;
    FPOS	start_pos;
    FPOS	*end_pos;
    FPOS	old_start, old_end;
    char_u	*save_cpo;

    old_pos = curwin->w_cursor;
    old_end = curwin->w_cursor;		    /* remember where we started */
    old_start = old_end;

    /*
     * If we start on '(', '{', ')', '}', etc., use the whole block inclusive.
     */
    if (!VIsual_active || equal(VIsual, curwin->w_cursor))
    {
	setpcmark();
	if (what == '{')		    /* ignore indent */
	    while (inindent(1))
		if (inc_cursor() != 0)
		    break;
	if (gchar_cursor() == what)	    /* cursor on '(' or '{' */
	    ++curwin->w_cursor.col;
    }
    else if (lt(VIsual, curwin->w_cursor))
    {
	old_start = VIsual;
	curwin->w_cursor = VIsual;	    /* cursor at low end of Visual */
    }
    else
	old_end = VIsual;

    /*
     * Search backwards for unclosed '(', '{', etc..
     * Put this position in start_pos.
     * Ignory quotes here.
     */
    save_cpo = p_cpo;
    p_cpo = (char_u *)"%";
    while (count-- > 0)
    {
	if ((pos = findmatch(NULL, what)) == NULL)
	    break;
	curwin->w_cursor = *pos;
	start_pos = *pos;   /* the findmatch for end_pos will overwrite *pos */
    }
    p_cpo = save_cpo;

    /*
     * Search for matching ')', '}', etc.
     * Put this position in curwin->w_cursor.
     */
    if (pos == NULL || (end_pos = findmatch(NULL, other)) == NULL)
    {
	curwin->w_cursor = old_pos;
	return FAIL;
    }
    curwin->w_cursor = *end_pos;

    /*
     * Try to exclude the '(', '

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -