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

📄 ops.c

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

/*
 * execute a yank register: copy it into the stuff buffer
 *
 * return FAIL for failure, OK otherwise
 */
    int
do_execreg(regname, colon, addcr)
    int	    regname;
    int	    colon;		/* insert ':' before each line */
    int	    addcr;		/* always add '\n' to end of line */
{
    static int	lastc = NUL;
    long	i;
    char_u	*p;
    int		retval = OK;


    if (regname == '@')			/* repeat previous one */
	regname = lastc;
					/* check for valid regname */
    if (regname == '%' || regname == '#' || !valid_yank_reg(regname, FALSE))
	return FAIL;
    lastc = regname;

    if (regname == '_')			/* black hole: don't stuff anything */
	return OK;

    if (regname == ':')			/* use last command line */
    {
	if (last_cmdline == NULL)
	{
	    EMSG(e_nolastcmd);
	    return FAIL;
	}
	vim_free(new_last_cmdline); /* don't keep the cmdline containing @: */
	new_last_cmdline = NULL;
	retval = put_in_typebuf(last_cmdline, TRUE);
    }
#ifdef WANT_EVAL
    else if (regname == '=')
    {
	p = get_expr_line();
	if (p == NULL)
	    return FAIL;
	retval = put_in_typebuf(p, colon);
	vim_free(p);
    }
#endif
    else if (regname == '.')		/* use last inserted text */
    {
	p = get_last_insert_save();
	if (p == NULL)
	{
	    EMSG(e_noinstext);
	    return FAIL;
	}
	retval = put_in_typebuf(p, colon);
	vim_free(p);
    }
    else
    {
	get_yank_register(regname, FALSE);
	if (y_current->y_array == NULL)
	    return FAIL;

	/*
	 * Insert lines into typeahead buffer, from last one to first one.
	 */
	for (i = y_current->y_size; --i >= 0; )
	{
	/* insert newline between lines and after last line if type is MLINE */
	    if (y_current->y_type == MLINE || i < y_current->y_size - 1
								     || addcr)
	    {
		if (ins_typebuf((char_u *)"\n", FALSE, 0, TRUE) == FAIL)
		    return FAIL;
	    }
	    if (ins_typebuf(y_current->y_array[i], FALSE, 0, TRUE) == FAIL)
		return FAIL;
	    if (colon && ins_typebuf((char_u *)":", FALSE, 0, TRUE) == FAIL)
		return FAIL;
	}
	Exec_reg = TRUE;	/* disable the 'q' command */
    }
    return retval;
}

    static int
put_in_typebuf(s, colon)
    char_u	*s;
    int		colon;	    /* add ':' before the line */
{
    int		retval = OK;

    if (colon)
	retval = ins_typebuf((char_u *)"\n", FALSE, 0, TRUE);
    if (retval == OK)
	retval = ins_typebuf(s, FALSE, 0, TRUE);
    if (colon && retval == OK)
	retval = ins_typebuf((char_u *)":", FALSE, 0, TRUE);
    return retval;
}

/*
 * Insert a yank register: copy it into the Read buffer.
 * Used by CTRL-R command and middle mouse button in insert mode.
 *
 * return FAIL for failure, OK otherwise
 */
    int
insert_reg(regname, literally)
    int regname;
    int literally;	/* insert literally, not as if typed */
{
    long    i;
    int	    retval = OK;
    char_u  *arg;
    int	    allocated;

    /*
     * It is possible to get into an endless loop by having CTRL-R a in
     * register a and then, in insert mode, doing CTRL-R a.
     * If you hit CTRL-C, the loop will be broken here.
     */
    ui_breakcheck();
    if (got_int)
	return FAIL;

    /* check for valid regname */
    if (regname != NUL && !valid_yank_reg(regname, FALSE))
	return FAIL;

#ifdef USE_CLIPBOARD
    if (regname == '*')
	clip_get_selection();		/* may fill * register */
#endif

    if (regname == '.')			/* insert last inserted text */
	retval = stuff_inserted(NUL, 1L, TRUE);
    else if (get_spec_reg(regname, &arg, &allocated, TRUE))
    {
	if (arg == NULL)
	    return FAIL;
	if (literally)
	    stuffescaped(arg);
	else
	    stuffReadbuff(arg);
	if (allocated)
	    vim_free(arg);
    }
    else				/* name or number register */
    {
	get_yank_register(regname, FALSE);
	if (y_current->y_array == NULL)
	    retval = FAIL;
	else
	{
	    for (i = 0; i < y_current->y_size; ++i)
	    {
		if (literally)
		    stuffescaped(y_current->y_array[i]);
		else
		    stuffReadbuff(y_current->y_array[i]);
		/*
		 * Insert a newline between lines and after last line if
		 * y_type is MLINE.
		 */
		if (y_current->y_type == MLINE || i < y_current->y_size - 1)
		    stuffcharReadbuff('\n');
	    }
	}
    }

    return retval;
}

/*
 * Stuff a string into the typeahead buffer, such that edit() will insert it
 * literally.
 */
    static void
stuffescaped(arg)
    char_u	*arg;
{
    while (*arg)
    {
	if ((*arg < ' ' && *arg != TAB) || *arg > '~')
	    stuffcharReadbuff(Ctrl('V'));
	stuffcharReadbuff(*arg++);
    }
}

/*
 * If "regname" is a special register, return a pointer to its value.
 */
    static int
get_spec_reg(regname, argp, allocated, errmsg)
    int		regname;
    char_u	**argp;
    int		*allocated;
    int		errmsg;		/* give error message when failing */
{
    *argp = NULL;
    *allocated = FALSE;
    switch (regname)
    {
	case '%':		/* file name */
	    if (errmsg)
		check_fname();	/* will give emsg if not set */
	    *argp = curbuf->b_fname;
	    return TRUE;

	case '#':		/* alternate file name */
	    *argp = getaltfname(errmsg);	/* may give emsg if not set */
	    return TRUE;

#ifdef WANT_EVAL
	case '=':		/* result of expression */
	    *argp = get_expr_line();
	    *allocated = TRUE;
	    return TRUE;
#endif

	case ':':		/* last command line */
	    if (last_cmdline == NULL && errmsg)
		EMSG(e_nolastcmd);
	    *argp = last_cmdline;
	    return TRUE;

	case '.':		/* last inserted text */
	    *argp = get_last_insert_save();
	    *allocated = TRUE;
	    if (*argp == NULL && errmsg)
		EMSG(e_noinstext);
	    return TRUE;

	case '_':		/* black hole: always empty */
	    *argp = (char_u *)"";
	    return TRUE;
    }

    return FALSE;
}

/*
 * paste a yank register into the command line.
 * used by CTRL-R command in command-line mode
 * insert_reg() can't be used here, because special characters from the
 * register contents will be interpreted as commands.
 *
 * return FAIL for failure, OK otherwise
 */
    int
cmdline_paste(regname)
    int regname;
{
    long	i;
    char_u	*arg;
    int		allocated;

    if (!valid_yank_reg(regname, FALSE))	/* check for valid regname */
	return FAIL;

#ifdef USE_CLIPBOARD
    if (regname == '*')
	clip_get_selection();
#endif

    if (regname == '.')			/* insert last inserted text */
	return FAIL;			/* Unimplemented */

    if (get_spec_reg(regname, &arg, &allocated, TRUE))
    {
	if (arg == NULL)
	    return FAIL;
	i = put_on_cmdline(arg, -1, TRUE);
	if (allocated)
	    vim_free(arg);
	return (int)i;
    }

    get_yank_register(regname, FALSE);
    if (y_current->y_array == NULL)
	return FAIL;

    for (i = 0; i < y_current->y_size; ++i)
    {
	put_on_cmdline(y_current->y_array[i], -1, FALSE);

	/* insert ^M between lines and after last line if type is MLINE */
	if (y_current->y_type == MLINE || i < y_current->y_size - 1)
	    put_on_cmdline((char_u *)"\r", 1, FALSE);
    }
    return OK;
}

/*
 * op_delete - handle a delete operation
 *
 * return FAIL if undo failed, OK otherwise.
 */
    int
op_delete(oap)
    OPARG   *oap;
{
    int			n;
    linenr_t		lnum;
    char_u		*ptr;
    char_u		*newp, *oldp;
    linenr_t		old_lcount = curbuf->b_ml.ml_line_count;
    int			did_yank = FALSE;
    struct block_def	bd;

    if (curbuf->b_ml.ml_flags & ML_EMPTY)	    /* nothing to do */
	return OK;

    /* Nothing to delete, return here.	Do prepare undo, for op_change(). */
    if (oap->empty)
    {
	return u_save_cursor();
    }

#ifdef MULTI_BYTE
    if (is_dbcs)
    {
	char_u *p;

	if (oap->end.col >= oap->start.col)
	{
	    p = ml_get(oap->end.lnum);
	    if (IsTrailByte(p, p + oap->end.col + oap->inclusive))
		oap->end.col++;
	}
	else
	{
	    p = ml_get(oap->start.lnum);
	    if (IsTrailByte(p, p + oap->start.col + oap->inclusive))
		oap->start.col++;
	}
    }
#endif

/*
 * Imitate the strange Vi behaviour: If the delete spans more than one line
 * and motion_type == MCHAR and the result is a blank line, make the delete
 * linewise.  Don't do this for the change command or Visual mode.
 */
    if (       oap->motion_type == MCHAR
	    && !oap->is_VIsual
	    && oap->line_count > 1
	    && oap->op_type == OP_DELETE)
    {
	ptr = ml_get(oap->end.lnum) + oap->end.col + oap->inclusive;
	ptr = skipwhite(ptr);
	if (*ptr == NUL && inindent(0))
	    oap->motion_type = MLINE;
    }

/*
 * Check for trying to delete (e.g. "D") in an empty line.
 * Note: For the change operator it is ok.
 */
    if (       oap->motion_type == MCHAR
	    && oap->line_count == 1
	    && oap->op_type == OP_DELETE
	    && *ml_get(oap->start.lnum) == NUL)
    {
	/*
	 * It's an error to operate on an empty region, when 'E' inclucded in
	 * 'cpoptions' (Vi compatible).
	 */
	if (vim_strchr(p_cpo, CPO_EMPTYREGION) != NULL)
	    beep_flush();
	return OK;
    }

/*
 * Do a yank of whatever we're about to delete.
 * If a yank register was specified, put the deleted text into that register.
 * For the black hole register '_' don't yank anything.
 */
    if (oap->regname != '_')
    {
	if (oap->regname != 0)
	{
	    /* check for read-only register */
	    if (!valid_yank_reg(oap->regname, TRUE))
	    {
		beep_flush();
		return OK;
	    }
	    get_yank_register(oap->regname, TRUE); /* yank into specif'd reg. */
	    if (op_yank(oap, TRUE, FALSE) == OK)   /* yank without message */
		did_yank = TRUE;
	}

	/*
	 * Put deleted text into register 1 and shift number registers if the
	 * delete contains a line break, or when a regname has been specified!
	 */
	if (oap->regname != 0 || oap->motion_type == MLINE
						       || oap->line_count > 1)
	{
	    y_current = &y_regs[9];
	    free_yank_all();			/* free register nine */
	    for (n = 9; n > 1; --n)
		y_regs[n] = y_regs[n - 1];
	    y_previous = y_current = &y_regs[1];
	    y_regs[1].y_array = NULL;		/* set register one to empty */
	    oap->regname = 0;
	}
	else if (oap->regname == 0)		/* yank into unnamed register */
	{
	    oap->regname = '-';		/* use special delete register */
	    get_yank_register(oap->regname, TRUE);
	    oap->regname = 0;
	}

	if (oap->regname == 0 && op_yank(oap, TRUE, FALSE) == OK)
	    did_yank = TRUE;

	/*
	 * If there's too much stuff to fit in the yank register, then get a
	 * confirmation before doing the delete. This is crude, but simple.
	 * And it avoids doing a delete of something we can't put back if we
	 * want.
	 */
	if (!did_yank)
	{
	    if (ask_yesno((char_u *)"cannot yank; delete anyway", TRUE) != 'y')
	    {
		emsg(e_abort);
		return FAIL;
	    }
	}
    }

/*
 * block mode delete
 */
    if (oap->block_mode)
    {
	if (u_save((linenr_t)(oap->start.lnum - 1),
			       (linenr_t)(oap->end.lnum + 1)) == FAIL)
	    return FAIL;

#ifdef SYNTAX_HL
	/* recompute syntax hl., starting with this line */
	syn_changed(curwin->w_cursor.lnum);
#endif
	for (lnum = curwin->w_cursor.lnum;
			       curwin->w_cursor.lnum <= oap->end.lnum;
						      ++curwin->w_cursor.lnum)
	{
	    block_prep(oap, &bd, curwin->w_cursor.lnum, TRUE);
	    if (bd.textlen == 0)	/* nothing to delete */
		continue;

	    /* n == number of chars deleted
	     * If we delete a TAB, it may be replaced by several characters.
	     * Thus the number of characters may increase!
	     */
	    n = bd.textlen - bd.startspaces - bd.endspaces;
	    oldp = ml_get_curline();
	    newp = alloc_check((unsigned)STRLEN(oldp) + 1 - n);
	    if (newp == NULL)
		continue;
	    /* copy up to deleted part */
	    mch_memmove(newp, oldp, (size_t)bd.textcol);
	    /* insert spaces */
	    copy_spaces(newp + bd.textcol,
				     (size_t)(bd.startspaces + bd.endspaces));
	    /* copy the part after the deleted part */
	    oldp += bd.textcol + bd.textlen;
	    mch_memmove(newp + bd.textcol + bd.startspaces + bd.endspaces,
						      oldp, STRLEN(oldp) + 1);
	    /* replace the line */
	    ml_replace(curwin->w_cursor.lnum, newp, FALSE);
	}

	curwin->w_cursor.lnum = lnum;
	changed_cline_bef_curs();	/* recompute cursor pos. on screen */
	approximate_botline();		/* w_botline may be wrong now */
	adjust_cursor();

	changed();
	update_screen(VALID_TO_CURSCHAR);
	oap->line_count = 0;	    /* no lines deleted */
    }
    else if (oap->motion_type == MLINE)
    {
	if (oap->op_type == OP_CHANGE)
	{
	    /* Delete the lines except the first one.  Temporarily move the
	     * cursor to the next line.  Save the current line number, if the
	     * last line is deleted it may be changed.
	     */
	    if (oap->line_count > 1)
	    {
		lnum = curwin->w_cursor.lnum;
		++curwin->w_cursor.lnum;
		del_lines((long)(oap->line_count - 1), TRUE, TRUE);
		curwin->w_cursor.lnum = lnum;
	    }
	    if (u_save_cursor() == FAIL)
		return FAIL;
	    if (curbuf->b_p_ai)		    /* don't delete indent */
	    {
		beginline(BL_WHITE);	    /* cursor on first non-white */
		did_ai = TRUE;		    /* delete the indent when ESC hit */
	    }
	    else
		beginline(0);		    /* cursor in column 0 */
#ifdef SYNTAX_HL
	    /* recompute syntax hl., starting with current line */
	    syn_changed(curwin->w_cursor.lnum);
#endif

⌨️ 快捷键说明

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