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

📄 ops.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:
}

/*
 * display the contents of the yank registers
 */
    void
do_dis(arg)
    char_u *arg;
{
    int		    i, n;
    long	    j;
    char_u	    *p;
    struct yankreg  *yb;
    char_u	    name;
    int		    attr;

    if (arg != NULL && *arg == NUL)
	arg = NULL;
    attr = hl_attr(HLF_8);

    /* Highlight title */
    MSG_PUTS_TITLE("\n--- Registers ---");
    for (i = -1; i < NUM_REGISTERS; ++i)
    {
	if (i == -1)
	{
	    if (y_previous != NULL)
		yb = y_previous;
	    else
		yb = &(y_regs[0]);
	}
	else
	    yb = &(y_regs[i]);
	name = get_register_name(i);
	if (yb->y_array != NULL && (arg == NULL ||
					       vim_strchr(arg, name) != NULL))
	{
	    msg_putchar('\n');
	    msg_putchar('"');
	    msg_putchar(name);
	    MSG_PUTS("   ");

	    n = (int)Columns - 6;
	    for (j = 0; j < yb->y_size && n > 1; ++j)
	    {
		if (j)
		{
		    MSG_PUTS_ATTR("^J", attr);
		    n -= 2;
		}
		for (p = yb->y_array[j]; *p && (n -= charsize(*p)) >= 0; ++p)
		    msg_outtrans_len(p, 1);
	    }
	    if (n > 1 && yb->y_type == MLINE)
		MSG_PUTS_ATTR("^J", attr);
	    out_flush();		    /* show one line at a time */
	}
    }

    /*
     * display last inserted text
     */
    if ((p = get_last_insert()) != NULL &&
	(arg == NULL || vim_strchr(arg, '.') != NULL))
    {
	MSG_PUTS("\n\".   ");
	dis_msg(p, TRUE);
    }

    /*
     * display last command line
     */
    if (last_cmdline != NULL && (arg == NULL || vim_strchr(arg, ':') != NULL))
    {
	MSG_PUTS("\n\":   ");
	dis_msg(last_cmdline, FALSE);
    }

    /*
     * display current file name
     */
    if (curbuf->b_fname != NULL &&
				(arg == NULL || vim_strchr(arg, '%') != NULL))
    {
	MSG_PUTS("\n\"%   ");
	dis_msg(curbuf->b_fname, FALSE);
    }

    /*
     * display alternate file name
     */
    if (arg == NULL || vim_strchr(arg, '%') != NULL)
    {
	char_u	    *fname;
	linenr_t    dummy;

	if (buflist_name_nr(0, &fname, &dummy) != FAIL)
	{
	    MSG_PUTS("\n\"#   ");
	    dis_msg(fname, FALSE);
	}
    }

#ifdef WANT_EVAL
    /*
     * display last used expression
     */
    if (expr_line != NULL && (arg == NULL || vim_strchr(arg, '=') != NULL))
    {
	MSG_PUTS("\n\"=   ");
	dis_msg(expr_line, FALSE);
    }
#endif
}

/*
 * display a string for do_dis()
 * truncate at end of screen line
 */
    void
dis_msg(p, skip_esc)
    char_u	*p;
    int		skip_esc;	    /* if TRUE, ignore trailing ESC */
{
    int	    n;

    n = (int)Columns - 6;
    while (*p && !(*p == ESC && skip_esc && *(p + 1) == NUL) &&
			(n -= charsize(*p)) >= 0)
	msg_outtrans_len(p++, 1);
}

/*
 * join 'count' lines (minimal 2), including u_save()
 */
    void
do_do_join(count, insert_space, redraw)
    long    count;
    int	    insert_space;
    int	    redraw;		    /* can redraw, curwin->w_wcol valid */
{
    if (u_save((linenr_t)(curwin->w_cursor.lnum - 1),
		    (linenr_t)(curwin->w_cursor.lnum + count)) == FAIL)
	return;

    if (count > 10)
	redraw = FALSE;		    /* don't redraw each small change */
    while (--count > 0)
    {
	line_breakcheck();
	if (got_int || do_join(insert_space, redraw) == FAIL)
	{
	    beep_flush();
	    break;
	}
    }
    redraw_later(VALID_TO_CURSCHAR);

    /*
     * Need to update the screen if the line where the cursor is became too
     * long to fit on the screen.
     */
    update_topline_redraw();
}

/*
 * Join two lines at the cursor position.
 * "redraw" is TRUE when the screen should be updated.
 *
 * return FAIL for failure, OK ohterwise
 */
    int
do_join(insert_space, redraw)
    int		insert_space;
    int		redraw;
{
    char_u	*curr;
    char_u	*next;
    char_u	*newp;
    int		endcurr1, endcurr2;
    int		currsize;	/* size of the current line */
    int		nextsize;	/* size of the next line */
    int		spaces;		/* number of spaces to insert */
    int		rows_to_del = 0;/* number of rows on screen to delete */
    linenr_t	t;

    if (curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count)
	return FAIL;		/* can't join on last line */

    if (redraw)
    {
	/*
	 * Check if we can really redraw:  w_cline_row and w_cline_height need
	 * to be valid.  Try to make them valid by calling may_validate_crow()
	 */
	if (may_validate_crow() == OK)
	    rows_to_del = plines_m(curwin->w_cursor.lnum,
						   curwin->w_cursor.lnum + 1);
	else
	    redraw = FALSE;
    }

    curr = ml_get_curline();
    currsize = STRLEN(curr);
    endcurr1 = endcurr2 = NUL;
    if (currsize > 0)
    {
	endcurr1 = *(curr + currsize - 1);
	if (currsize > 1)
	    endcurr2 = *(curr + currsize - 2);
    }

    next = ml_get((linenr_t)(curwin->w_cursor.lnum + 1));
    spaces = 0;
    if (insert_space)
    {
	next = skipwhite(next);
	if (*next != ')' && currsize != 0 && endcurr1 != TAB)
	{
	    /* don't add a space if the line is inding in a space */
	    if (endcurr1 == ' ')
		endcurr1 = endcurr2;
	    else
		++spaces;
	    /* extra space when 'joinspaces' set and line ends in '.' */
	    if (       p_js
		    && (endcurr1 == '.'
			|| (vim_strchr(p_cpo, CPO_JOINSP) == NULL
			    && (endcurr1 == '?' || endcurr1 == '!'))))
		++spaces;
	}
    }
    nextsize = STRLEN(next);

    newp = alloc_check((unsigned)(currsize + nextsize + spaces + 1));
    if (newp == NULL)
	return FAIL;

    /*
     * Insert the next line first, because we already have that pointer.
     * Curr has to be obtained again, because getting next will have
     * invalidated it.
     */
    mch_memmove(newp + currsize + spaces, next, (size_t)(nextsize + 1));

    curr = ml_get_curline();
    mch_memmove(newp, curr, (size_t)currsize);

    copy_spaces(newp + currsize, (size_t)spaces);

    ml_replace(curwin->w_cursor.lnum, newp, FALSE);

#ifdef SYNTAX_HL
    /* recompute syntax hl. for current line */
    syn_changed(curwin->w_cursor.lnum);
#endif

    /*
     * Delete the following line. To do this we move the cursor there
     * briefly, and then move it back. After del_lines() the cursor may
     * have moved up (last line deleted), so the current lnum is kept in t.
     */
    t = curwin->w_cursor.lnum;
    ++curwin->w_cursor.lnum;
    del_lines(1L, FALSE, FALSE);
    curwin->w_cursor.lnum = t;

    /*
     * the number of rows on the screen is reduced by the difference
     * in number of rows of the two old lines and the one new line
     */
    if (redraw)
    {
	rows_to_del -= plines(curwin->w_cursor.lnum);
	if (rows_to_del > 0)
	    win_del_lines(curwin, curwin->w_cline_row + curwin->w_cline_height,
						     rows_to_del, TRUE, TRUE);
    }

    /*
     * go to first character of the joined line
     */
    if (currsize == 0)
	curwin->w_cursor.col = 0;
    else
    {
	curwin->w_cursor.col = currsize - 1;
	(void)oneright();
    }
    changed();

    return OK;
}

/*
 * Return TRUE if the two comment leaders given are the same.  The cursor is
 * in the first line.  White-space is ignored.	Note that the whole of
 * 'leader1' must match 'leader2_len' characters from 'leader2' -- webb
 */
    static int
same_leader(leader1_len, leader1_flags, leader2_len, leader2_flags)
    int	    leader1_len;
    char_u  *leader1_flags;
    int	    leader2_len;
    char_u  *leader2_flags;
{
    int	    idx1 = 0, idx2 = 0;
    char_u  *p;
    char_u  *line1;
    char_u  *line2;

    if (leader1_len == 0)
	return (leader2_len == 0);

    /*
     * If first leader has 'f' flag, the lines can be joined only if the
     * second line does not have a leader.
     * If first leader has 'e' flag, the lines can never be joined.
     * If fist leader has 's' flag, the lines can only be joined if there is
     * some text after it and the second line has the 'm' flag.
     */
    if (leader1_flags != NULL)
    {
	for (p = leader1_flags; *p && *p != ':'; ++p)
	{
	    if (*p == COM_FIRST)
		return (leader2_len == 0);
	    if (*p == COM_END)
		return FALSE;
	    if (*p == COM_START)
	    {
		if (*(ml_get_curline() + leader1_len) == NUL)
		    return FALSE;
		if (leader2_flags == NULL || leader2_len == 0)
		    return FALSE;
		for (p = leader2_flags; *p && *p != ':'; ++p)
		    if (*p == COM_MIDDLE)
			return TRUE;
		return FALSE;
	    }
	}
    }

    /*
     * Get current line and next line, compare the leaders.
     * The first line has to be saved, only one line can be locked at a time.
     */
    line1 = vim_strsave(ml_get_curline());
    if (line1 != NULL)
    {
	for (idx1 = 0; vim_iswhite(line1[idx1]); ++idx1)
	    ;
	line2 = ml_get(curwin->w_cursor.lnum + 1);
	for (idx2 = 0; idx2 < leader2_len; ++idx2)
	{
	    if (!vim_iswhite(line2[idx2]))
	    {
		if (line1[idx1++] != line2[idx2])
		    break;
	    }
	    else
		while (vim_iswhite(line1[idx1]))
		    ++idx1;
	}
	vim_free(line1);
    }
    return (idx2 == leader2_len && idx1 == leader1_len);
}

/*
 * implementation of the format operator 'gq'
 */
    void
op_format(oap)
    OPARG	*oap;
{
    long	old_line_count = curbuf->b_ml.ml_line_count;
    int		is_not_par;		/* current line not part of parag. */
    int		next_is_not_par;	/* next line not part of paragraph */
    int		is_end_par;		/* at end of paragraph */
    int		prev_is_end_par = FALSE;/* prev. line not part of parag. */
    int		leader_len = 0;		/* leader len of current line */
    int		next_leader_len;	/* leader len of next line */
    char_u	*leader_flags = NULL;	/* flags for leader of current line */
    char_u	*next_leader_flags;	/* flags for leader of next line */
    int		advance = TRUE;
    int		second_indent = -1;
    int		do_second_indent;
    int		first_par_line = TRUE;
    int		smd_save;
    long	count;
    int		need_set_indent = TRUE;	/* set indent of next paragraph */
    int		force_format = FALSE;
    int		max_len;
    int		screenlines = -1;

    if (u_save((linenr_t)(oap->start.lnum - 1),
				       (linenr_t)(oap->end.lnum + 1)) == FAIL)
	return;

    /* When formatting less than a screenfull, will try to speed up redrawing
     * by inserting/deleting screen lines */
    if (oap->end.lnum - oap->start.lnum < Rows)
	screenlines = plines_m(oap->start.lnum, oap->end.lnum);

    /* length of a line to force formatting: 3 * 'tw' */
    max_len = comp_textwidth(TRUE) * 3;

    /* Set '[ mark at the start of the formatted area */
    curbuf->b_op_start = oap->start;

    /* check for 'q' and '2' in 'formatoptions' */
    fo_do_comments = has_format_option(FO_Q_COMS);
    do_second_indent = has_format_option(FO_Q_SECOND);

    /*
     * Get info about the previous and current line.
     */
    if (curwin->w_cursor.lnum > 1)
	is_not_par = fmt_check_par(curwin->w_cursor.lnum - 1,
						  &leader_len, &leader_flags);
    else
	is_not_par = TRUE;
    next_is_not_par = fmt_check_par(curwin->w_cursor.lnum,
					&next_leader_len, &next_leader_flags);
    is_end_par = (is_not_par || next_is_not_par);

    curwin->w_cursor.lnum--;
    for (count = oap->line_count; count > 0 && !got_int; --count)
    {
	/*
	 * Advance to next paragraph.
	 */
	if (advance)
	{
	    curwin->w_cursor.lnum++;
	    prev_is_end_par = is_end_par;
	    is_not_par = next_is_not_par;
	    leader_len = next_leader_len;
	    leader_flags = next_leader_flags;
	}

	/*
	 * The last line to be formatted.
	 */
	if (count == 1)
	{
	    next_is_not_par = TRUE;
	    next_leader_len = 0;
	    next_leader_flags = NULL;
	}
	else
	    next_is_not_par = fmt_check_par(curwin->w_cursor.lnum + 1,
					&next_leader_len, &next_leader_flags);
	advance = TRUE;
	is_end_par = (is_not_par || next_is_not_par);

	/*
	 * Skip lines that are not in a paragraph.
	 */
	if (!is_not_par)
	{
	    /*
	     * For the first line of a paragraph, check indent of second line.
	     * Don't do this for comments and empty lines.
	     */
	    if (first_par_line
		    && do_second_indent
		    && prev_is_end_par
		    && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count
		    && leader_len == 0
		    && next_leader_len == 0
		    && !lineempty(curwin->w_cursor.lnum + 1))
		second_indent = get_indent_lnum(curwin->w_cursor.lnum + 1);

	    /*
	     * When the comment leader changes, it's the end of the paragraph.
	     */
	    if (curwin->w_cursor.lnum >= curbuf->b_ml.ml_line_count
		    || !same_leader(leader_len, leader_flags,
					  next_leader_len, next_leader_flags))
		is_end_par = TRUE;

	    /*
	     * If we have got to the end of a paragraph, or the line is
	     * getting long, format it.
	     */
	    if (is_end_par || force_format)
	    {
		if (need_set_indent)
		    /* replace indent in first line with minimal number of
		     * tabs and spaces, according to current options */
		    set_indent(get_indent(), TRUE);

		/* put cursor on last non-space */
		coladvance(MAXCOL);
		while (curwin->w_cursor.col && vim_isspace(gchar_cursor()))
		    dec_cursor();

#ifdef SYNTAX_HL
		/* recompute syntax hl., starting with current line */
		syn_changed(curwin->w_cursor.lnum);
#endif
		/* do the formatting, without 'showmode' */
		State = INSERT;	/* for open_line() */
		smd_save = p_smd;
		p_smd = FALSE;
		insertchar(NUL, TRUE, second_indent, FALSE);
		State = NORMAL;
		p_smd = smd_save;
		second_indent = -1;
		/* at end of par.: need to set indent of next par. */
		need_set_indent = is_end_par;
		if (is_end_par)

⌨️ 快捷键说明

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