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

📄 normal.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:
	oap->line_count = oap->end.lnum - oap->start.lnum + 1;

	if (VIsual_active || redo_VIsual_busy)
	{
	    if (VIsual_mode == Ctrl('V'))	/* block mode */
	    {
		colnr_t	    start, end;

		oap->block_mode = TRUE;

		getvcol(curwin, &(oap->start),
				      &oap->start_vcol, NULL, &oap->end_vcol);
		if (!redo_VIsual_busy)
		{
		    getvcol(curwin, &(oap->end), &start, NULL, &end);
		    if (start < oap->start_vcol)
			oap->start_vcol = start;
		    if (end > oap->end_vcol)
		    {
			if (*p_sel == 'e' && start - 1 >= oap->end_vcol)
			    oap->end_vcol = start - 1;
			else
			    oap->end_vcol = end;
		    }
		}

		/* if '$' was used, get oap->end_vcol from longest line */
		if (curwin->w_curswant == MAXCOL)
		{
		    curwin->w_cursor.col = MAXCOL;
		    oap->end_vcol = 0;
		    for (curwin->w_cursor.lnum = oap->start.lnum;
			    curwin->w_cursor.lnum <= oap->end.lnum;
						      ++curwin->w_cursor.lnum)
		    {
			getvcol(curwin, &curwin->w_cursor, NULL, NULL, &end);
			if (end > oap->end_vcol)
			    oap->end_vcol = end;
		    }
		}
		else if (redo_VIsual_busy)
		    oap->end_vcol = oap->start_vcol + redo_VIsual_col - 1;
		/*
		 * Correct oap->end.col and oap->start.col to be the
		 * upper-left and lower-right corner of the block area.
		 */
		curwin->w_cursor.lnum = oap->end.lnum;
		coladvance(oap->end_vcol);
		oap->end = curwin->w_cursor;
		curwin->w_cursor = oap->start;
		coladvance(oap->start_vcol);
		oap->start = curwin->w_cursor;
	    }

	    if (!redo_VIsual_busy && !gui_yank)
	    {
		/*
		 * Prepare to reselect and redo Visual: this is based on the
		 * size of the Visual text
		 */
		resel_VIsual_mode = VIsual_mode;
		if (curwin->w_curswant == MAXCOL)
		    resel_VIsual_col = MAXCOL;
		else if (VIsual_mode == Ctrl('V'))
		    resel_VIsual_col = oap->end_vcol - oap->start_vcol + 1;
		else if (oap->line_count > 1)
		    resel_VIsual_col = oap->end.col;
		else
		    resel_VIsual_col = oap->end.col - oap->start.col + 1;
		resel_VIsual_line_count = oap->line_count;
	    }

	    /* can't redo yank (unless 'y' is in 'cpoptions') and ":" */
	    if ((vim_strchr(p_cpo, CPO_YANK) != NULL || oap->op_type != OP_YANK)
		    && oap->op_type != OP_COLON)
	    {
		prep_redo(oap->regname, 0L, NUL, 'v', oap->op_prechar,
						  op_chars[oap->op_type - 1]);
		redo_VIsual_mode = resel_VIsual_mode;
		redo_VIsual_col = resel_VIsual_col;
		redo_VIsual_line_count = resel_VIsual_line_count;
		redo_VIsual_count = cap->count0;
	    }

	    /*
	     * oap->inclusive defaults to TRUE.
	     * If oap->end is on a NUL (empty line) oap->inclusive becomes
	     * FALSE.  This makes "d}P" and "v}dP" work the same.
	     */
	    oap->inclusive = TRUE;
	    if (VIsual_mode == 'V')
		oap->motion_type = MLINE;
	    else
	    {
		oap->motion_type = MCHAR;
		if (VIsual_mode != Ctrl('V') && *ml_get_pos(&(oap->end)) == NUL)
		{
		    oap->inclusive = FALSE;
		    /* Try to include the newline */
		    if (*p_sel != 'o'
			    && oap->end.lnum < curbuf->b_ml.ml_line_count)
		    {
			++oap->end.lnum;
			oap->end.col = 0;
			++oap->line_count;
		    }
		}
	    }

	    redo_VIsual_busy = FALSE;
	    /*
	     * Switch Visual off now, so screen updating does
	     * not show inverted text when the screen is redrawn.
	     * With OP_YANK and sometimes with OP_COLON and OP_FILTER there is
	     * no screen redraw, so it is done here to remove the inverted
	     * part.
	     */
	    if (!gui_yank)
	    {
		VIsual_active = FALSE;
#ifdef USE_MOUSE
		setmouse();
#endif
		if (p_smd)
		    clear_cmdline = TRUE;   /* unshow visual mode later */
		if (oap->op_type == OP_YANK || oap->op_type == OP_COLON ||
						     oap->op_type == OP_FILTER)
		    update_curbuf(NOT_VALID);
	    }
	}

	curwin->w_set_curswant = TRUE;

	/*
	 * oap->empty is set when start and end are the same.  The inclusive
	 * flag affects this too, unless yanking and the end is on a NUL.
	 */
	oap->empty = (oap->motion_type == MCHAR
		    && (!oap->inclusive
			|| (oap->op_type == OP_YANK && gchar(&oap->end) == NUL))
		    && equal(oap->start, oap->end));
	/*
	 * For delete, change and yank, it's an error to operate on an
	 * empty region, when 'E' inclucded in 'cpoptions' (Vi compatible).
	 */
	empty_region_error = (oap->empty
				&& vim_strchr(p_cpo, CPO_EMPTYREGION) != NULL);

	/* Force a redraw when operating on an empty Visual region */
	if (oap->is_VIsual && oap->empty)
	    redraw_curbuf_later(NOT_VALID);

    /*
     * If the end of an operator is in column one while oap->motion_type is
     * MCHAR and oap->inclusive is FALSE, we put op_end after the last character
     * in the previous line. If op_start is on or before the first non-blank
     * in the line, the operator becomes linewise (strange, but that's the way
     * vi does it).
     */
	if (	   oap->motion_type == MCHAR
		&& oap->inclusive == FALSE
		&& !dont_adjust_op_end
		&& oap->end.col == 0
		&& (!oap->is_VIsual || *p_sel == 'o')
		&& oap->line_count > 1)
	{
	    oap->end_adjusted = TRUE;	    /* remember that we did this */
	    --oap->line_count;
	    --oap->end.lnum;
	    if (inindent(0))
		oap->motion_type = MLINE;
	    else
	    {
		oap->end.col = STRLEN(ml_get(oap->end.lnum));
		if (oap->end.col)
		{
		    --oap->end.col;
		    oap->inclusive = TRUE;
		}
	    }
	}
	else
	    oap->end_adjusted = FALSE;

	switch (oap->op_type)
	{
	case OP_LSHIFT:
	case OP_RSHIFT:
	    op_shift(oap, TRUE, oap->is_VIsual ? (int)cap->count1 : 1);
	    break;

	case DO_JOIN:
	    if (oap->line_count < 2)
		oap->line_count = 2;
	    if (curwin->w_cursor.lnum + oap->line_count - 1 >
						   curbuf->b_ml.ml_line_count)
		beep_flush();
	    else
		do_do_join(oap->line_count, !oap->op_prechar, TRUE);
	    break;

	case OP_DELETE:
	    VIsual_reselect = FALSE;	    /* don't reselect now */
	    if (empty_region_error)
		vim_beep();
	    else
		(void)op_delete(oap);
	    break;

	case OP_YANK:
	    if (empty_region_error)
	    {
		if (!gui_yank)
		    vim_beep();
	    }
	    else
		(void)op_yank(oap, FALSE, !gui_yank);
	    break;

	case OP_CHANGE:
	    VIsual_reselect = FALSE;	    /* don't reselect now */
	    if (empty_region_error)
		vim_beep();
	    else
	    {
		/* don't restart edit after typing <Esc> in edit() */
		restart_edit = 0;
		*command_busy = op_change(oap);	/* will call edit() */
	    }
	    break;

	case OP_FILTER:
	    if (vim_strchr(p_cpo, CPO_FILTER) != NULL)
		AppendToRedobuff((char_u *)"!\r");  /* use any last used !cmd */
	    else
		bangredo = TRUE;    /* do_bang() will put cmd in redo buffer */

	case OP_INDENT:
	case OP_COLON:

#if defined(LISPINDENT) || defined(CINDENT)
	    /*
	     * If 'equalprg' is empty, do the indenting internally.
	     */
	    if (oap->op_type == OP_INDENT && *p_ep == NUL)
	    {
# ifdef LISPINDENT
		if (curbuf->b_p_lisp)
		{
		    op_reindent(oap, get_lisp_indent);
		    break;
		}
# endif
# ifdef CINDENT
		op_reindent(oap, get_c_indent);
		break;
# endif
	    }
#endif /* defined(LISPINDENT) || defined(CINDENT) */

	    op_colon(oap);
	    break;

	case OP_TILDE:
	case OP_UPPER:
	case OP_LOWER:
	    if (empty_region_error)
		vim_beep();
	    else
		op_tilde(oap);
	    break;

	case OP_FORMAT:
	    if (*p_fp != NUL)
		op_colon(oap);		/* use external command */
	    else
		op_format(oap);		/* use internal function */
	    break;

	default:
	    clearopbeep(oap);
	}
	oap->op_prechar = NUL;
	if (!gui_yank)
	{
	    /*
	     * if 'sol' not set, go back to old column for some commands
	     */
	    if (!p_sol && oap->motion_type == MLINE && !oap->end_adjusted
		    && (oap->op_type == OP_LSHIFT || oap->op_type == OP_RSHIFT
						|| oap->op_type == OP_DELETE))
		coladvance(curwin->w_curswant = old_col);
	    oap->op_type = OP_NOP;
	}
	else
	    curwin->w_cursor = old_cursor;
	oap->block_mode = FALSE;
	oap->regname = 0;
    }
}

/*
 * Handle indent and format operators and visual mode ":".
 */
    static void
op_colon(oap)
    OPARG	*oap;
{
    stuffcharReadbuff(':');
    if (oap->is_VIsual)
	stuffReadbuff((char_u *)"'<,'>");
    else
    {
	/*
	 * Make the range look nice, so it can be repeated.
	 */
	if (oap->start.lnum == curwin->w_cursor.lnum)
	    stuffcharReadbuff('.');
	else
	    stuffnumReadbuff((long)oap->start.lnum);
	if (oap->end.lnum != oap->start.lnum)
	{
	    stuffcharReadbuff(',');
	    if (oap->end.lnum == curwin->w_cursor.lnum)
		stuffcharReadbuff('.');
	    else if (oap->end.lnum == curbuf->b_ml.ml_line_count)
		stuffcharReadbuff('$');
	    else if (oap->start.lnum == curwin->w_cursor.lnum)
	    {
		stuffReadbuff((char_u *)".+");
		stuffnumReadbuff((long)oap->line_count - 1);
	    }
	    else
		stuffnumReadbuff((long)oap->end.lnum);
	}
    }
    if (oap->op_type != OP_COLON)
	stuffReadbuff((char_u *)"!");
    if (oap->op_type == OP_INDENT)
    {
#ifndef CINDENT
	if (*p_ep == NUL)
	    stuffReadbuff((char_u *)"indent");
	else
#endif
	    stuffReadbuff(p_ep);
	stuffReadbuff((char_u *)"\n");
    }
    else if (oap->op_type == OP_FORMAT)
    {
	if (*p_fp == NUL)
	    stuffReadbuff((char_u *)"fmt");
	else
	    stuffReadbuff(p_fp);
	stuffReadbuff((char_u *)"\n");
    }

    /*
     * do_cmdline() does the rest
     */
}

#ifdef USE_MOUSE
/*
 * Do the appropriate action for the current mouse click in the current mode.
 *
 * Normal Mode:
 * event	 modi-	position      visual	   change   action
 *		 fier	cursor			   window
 * left press	  -	yes	    end		    yes
 * left press	  C	yes	    end		    yes	    "^]" (2)
 * left press	  S	yes	    end		    yes	    "*" (2)
 * left drag	  -	yes	start if moved	    no
 * left relse	  -	yes	start if moved	    no
 * middle press	  -	yes	 if not active	    no	    put register
 * middle press	  -	yes	 if active	    no	    yank and put
 * right press	  -	yes	start or extend	    yes
 * right press	  S	yes	no change	    yes	    "#" (2)
 * right drag	  -	yes	extend		    no
 * right relse	  -	yes	extend		    no
 *
 * Insert or Replace Mode:
 * event	 modi-	position      visual	   change   action
 *		 fier	cursor			   window
 * left press	  -	yes	(cannot be active)  yes
 * left press	  C	yes	(cannot be active)  yes	    "CTRL-O^]" (2)
 * left press	  S	yes	(cannot be active)  yes	    "CTRL-O*" (2)
 * left drag	  -	yes	start or extend (1) no	    CTRL-O (1)
 * left relse	  -	yes	start or extend (1) no	    CTRL-O (1)
 * middle press	  -	no	(cannot be active)  no	    put register
 * right press	  -	yes	start or extend	    yes	    CTRL-O
 * right press	  S	yes	(cannot be active)  yes	    "CTRL-O#" (2)
 *
 * (1) only if mouse pointer moved since press
 * (2) only if click is in same buffer
 *
 * Return TRUE if start_arrow() should be called for edit mode.
 */
    int
do_mouse(oap, c, dir, count, fix_indent)
    OPARG   *oap;	    /* operator argument, can be NULL */
    int	    c;		    /* K_LEFTMOUSE, etc */
    int	    dir;	    /* Direction to 'put' if necessary */
    long    count;
    int	    fix_indent;	    /* PUT_FIXINDENT if fixing indent necessary */
{
    static FPOS	orig_cursor;
    static int	do_always = FALSE;	/* ignore 'mouse' setting next time */
    static int	got_click = FALSE;	/* got a click some time back */

    int	    which_button;	/* MOUSE_LEFT, _MIDDLE or _RIGHT */
    int	    is_click;		/* If FALSE it's a drag or release event */
    int	    is_drag;		/* If TRUE it's a drag event */
    int	    jump_flags = 0;	/* flags for jump_to_mouse() */
    FPOS    start_visual;
    FPOS    end_visual;
    int	    diff;
    int	    moved;		/* Has cursor moved? */
    int	    in_status_line;	/* mouse in status line */
    int	    c1, c2;
    int	    VIsual_was_active = VIsual_active;
    int	    regname;

    /*
     * When GUI is active, always recognize mouse events, otherwise:
     * - Ignore mouse event in normal mode if 'mouse' doesn't include 'n'.
     * - Ignore mouse event in visual mode if 'mouse' doesn't include 'v'.
     * - For command line and insert mode 'mouse' is checked before calling
     *	 do_mouse().
     */
    if (do_always)
	do_always = FALSE;
    else
#ifdef USE_GUI
	if (!gui.in_use)
#endif
	{
	    if (VIsual_active)
	    {
		if (!mouse_has(MOUSE_VISUAL))
		    return FALSE;
	    }
	    else if (State == NORMAL && !mouse_has(MOUSE_NORMAL))
		return FALSE;
	}

    which_button = get_mouse_button(KEY2TERMCAP1(c), &is_click, &is_drag);

    /*
     * Ignore drag and release events if we didn't get a click.
     */
    if (is_click)
	got_click = TRUE;
    else
    {
	if (!got_click)			/* didn't get click, ignore */
	    return FALSE;
	if (!is_drag)			/* release, reset got_click */
	    got_click = FALSE;
    }

    /*
     * ALT is currently ignored
     */
    if ((mod_mask & MOD_MASK_ALT))
	return FALSE;

    /*
     * CTRL right mouse button does CTRL-T
     */
    if (is_click && (mod_mask & MOD_MASK_CTRL) && which_button == MOUSE_RIGHT)
    {
	if (State & INSERT)
	    stuffcharReadbuff(Ctrl('O'));
	stuffcharReadbuff(Ctrl('T'));
	got_click = FALSE;		/* ignore drag&release now */
	return FALSE;
    }

    /*
     * CTRL only works with left mouse button
     */
    if ((mod_mask & MOD_MASK_CTRL) && which_button != MOUSE_LEFT)
	return FALSE;

    /*
     * When a modifier is down, ignore drag and release events, as well as
     * multiple clicks and the middle mouse button.
     * Accept shift-leftmouse drags when 'M' option is in 'mouse'.
     */
    if ((mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL | MOD_MASK_ALT))
	    && (!is_click
		|| (mod_mask & MOD_MASK_MULTI_CLICK)
		|| which_button == MOUSE_MIDDLE)
	    && !((mod_mask & MOD_MASK_SHIFT)
		&& mouse_model_popup()
		&& which_button == MOUSE_LEFT)
	    )
	return FALSE;

    /*
     * If the button press was used as the movement command for an operator
     * (eg "d<MOUSE>"), or it is the middle button that is held down, ignore
     * drag/release events.
     */
    if (!is_click && which_button == MOUSE_MIDDLE)
	return FALSE;

    if (oap != NULL)
	regname = oap->regname;
    else
	regname = 0;

⌨️ 快捷键说明

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