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

📄 normal.c

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

    /*
     * Middle mouse button does a 'put' of the selected text
     */
    if (which_button == MOUSE_MIDDLE)
    {
	if (State == NORMAL)
	{
	    /*
	     * If an operator was pending, we don't know what the user wanted
	     * to do. Go back to normal mode: Clear the operator and beep().
	     */
	    if (oap != NULL && oap->op_type != OP_NOP)
	    {
		clearopbeep(oap);
		return FALSE;
	    }

	    /*
	     * If visual was active, yank the highlighted text and put it
	     * before the mouse pointer position.
	     */
	    if (VIsual_active)
	    {
		stuffcharReadbuff('y');
		stuffcharReadbuff(K_MIDDLEMOUSE);
		do_always = TRUE;	/* ignore 'mouse' setting next time */
		return FALSE;
	    }
	    /*
	     * The rest is below jump_to_mouse()
	     */
	}

	/*
	 * Middle click in insert mode doesn't move the mouse, just insert the
	 * contents of a register.  '.' register is special, can't insert that
	 * with do_put().
	 */
	else if (State & INSERT)
	{
	    if (regname == '.')
		insert_reg(regname, TRUE);
	    else
	    {
#ifdef USE_CLIPBOARD
		if (clipboard.available && regname == 0)
		    regname = '*';
#endif
		if (State == REPLACE && !yank_register_mline(regname))
		    insert_reg(regname, TRUE);
		else
		{
		    do_put(regname, BACKWARD, 1L, fix_indent | PUT_CURSEND);

		    /* Repeat it with CTRL-R CTRL-R x.  Not exactly the same,
		     * but mostly works fine. */
		    AppendCharToRedobuff(Ctrl('R'));
		    AppendCharToRedobuff(Ctrl('R'));
		    AppendCharToRedobuff(regname == 0 ? '"' : regname);
		}
	    }
	    return FALSE;
	}
	else
	    return FALSE;
    }

    if (!is_click)
	jump_flags |= MOUSE_FOCUS | MOUSE_DID_MOVE;

    start_visual.lnum = 0;

    /*
     * When 'mousemodel' is "popup", translate mouse events:
     * right button up   -> pop-up menu
     * shift-left button -> right button
     */
    if (mouse_model_popup())
    {
	if (which_button == MOUSE_RIGHT
			    && !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)))
	{
#if defined(USE_GUI_MOTIF)
	    /*
	     * NOTE: Ignore right button down and drag mouse events.
	     * Windows only shows the popup menu on the button up event.
	     */
	    if (is_click)
		gui_show_popupmenu();
#endif
#if defined(USE_GUI_ATHENA) || defined(USE_GUI_WIN32)
	    /*
	     * NOTE: Ignore right button down and drag mouse events.
	     * Windows only shows the popup menu on the button up event.
	     */
	    if (!is_click && !is_drag)
		gui_show_popupmenu();
#endif
	    return FALSE;
	}
	if (which_button == MOUSE_LEFT && (mod_mask & MOD_MASK_SHIFT))
	{
	    which_button = MOUSE_RIGHT;
	    mod_mask &= ~ MOD_MASK_SHIFT;
	}
    }

    if ((State & (NORMAL | INSERT))
			    && !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)))
    {
	if (which_button == MOUSE_LEFT)
	{
	    if (is_click)
	    {
		/* stop Visual mode for a left click in a window, but not when
		 * on a status line */
		if (VIsual_active)
		    jump_flags |= MOUSE_MAY_STOP_VIS;
	    }
	    else
		jump_flags |= MOUSE_MAY_VIS;
	}
	else if (which_button == MOUSE_RIGHT)
	{
	    if (is_click && VIsual_active)
	    {
		/*
		 * Remember the start and end of visual before moving the
		 * cursor.
		 */
		if (lt(curwin->w_cursor, VIsual))
		{
		    start_visual = curwin->w_cursor;
		    end_visual = VIsual;
		}
		else
		{
		    start_visual = VIsual;
		    end_visual = curwin->w_cursor;
		}
	    }
	    jump_flags |= MOUSE_MAY_VIS;
	}
    }

    /*
     * If an operator is pending, ignore all drags and releases until the
     * next mouse click.
     */
    if (!is_drag && oap != NULL && oap->op_type != OP_NOP)
    {
	got_click = FALSE;
	oap->motion_type = MCHAR;
    }

    /*
     * Jump!
     */
    jump_flags = jump_to_mouse(jump_flags,
				      oap == NULL ? NULL : &(oap->inclusive));
    moved = (jump_flags & CURSOR_MOVED);
    in_status_line = ((jump_flags & IN_STATUS_LINE) == IN_STATUS_LINE);

    if (start_visual.lnum)		/* right click in visual mode */
    {
	/*
	 * In Visual-block mode, divide the area in four, pick up the corner
	 * that is in the quarter that the cursor is in.
	 */
	if (VIsual_mode == Ctrl('V'))
	{
	    colnr_t	leftcol, rightcol;

	    getvcols(&start_visual, &end_visual, &leftcol, &rightcol);
	    if (curwin->w_curswant > (leftcol + rightcol) / 2)
		end_visual.col = leftcol;
	    else
		end_visual.col = rightcol;
	    if (curwin->w_cursor.lnum <
				    (start_visual.lnum + end_visual.lnum) / 2)
		end_visual.lnum = end_visual.lnum;
	    else
		end_visual.lnum = start_visual.lnum;

	    /* move VIsual to the right column */
	    start_visual = curwin->w_cursor;	    /* save the cursor pos */
	    curwin->w_cursor = end_visual;
	    coladvance(end_visual.col);
	    VIsual = curwin->w_cursor;
	    curwin->w_cursor = start_visual;	    /* restore the cursor */
	}
	else
	{
	    /*
	     * If the click is before the start of visual, change the start.
	     * If the click is after the end of visual, change the end.  If
	     * the click is inside the visual, change the closest side.
	     */
	    if (lt(curwin->w_cursor, start_visual))
		VIsual = end_visual;
	    else if (lt(end_visual, curwin->w_cursor))
		VIsual = start_visual;
	    else
	    {
		/* In the same line, compare column number */
		if (end_visual.lnum == start_visual.lnum)
		{
		    if (curwin->w_cursor.col - start_visual.col >
				    end_visual.col - curwin->w_cursor.col)
			VIsual = start_visual;
		    else
			VIsual = end_visual;
		}

		/* In different lines, compare line number */
		else
		{
		    diff = (curwin->w_cursor.lnum - start_visual.lnum) -
				(end_visual.lnum - curwin->w_cursor.lnum);

		    if (diff > 0)		/* closest to end */
			VIsual = start_visual;
		    else if (diff < 0)	/* closest to start */
			VIsual = end_visual;
		    else			/* in the middle line */
		    {
			if (curwin->w_cursor.col <
					(start_visual.col + end_visual.col) / 2)
			    VIsual = end_visual;
			else
			    VIsual = start_visual;
		    }
		}
	    }
	}
    }
    /*
     * If Visual mode started in insert mode, execute "CTRL-O"
     */
    else if ((State & INSERT) && VIsual_active)
	stuffcharReadbuff(Ctrl('O'));

    /*
     * When the cursor has moved in insert mode, and something was inserted,
     * and there are several windows, need to redraw.
     */
    if (moved && (State & INSERT) && modified && firstwin->w_next != NULL)
    {
	update_curbuf(NOT_VALID);
	modified = FALSE;
    }

    /*
     * Middle mouse click: Put text before cursor.
     */
    if (which_button == MOUSE_MIDDLE)
    {
#ifdef USE_CLIPBOARD
	if (clipboard.available && regname == 0)
	    regname = '*';
#endif
	if (yank_register_mline(regname))
	{
	    if (mouse_past_bottom)
		dir = FORWARD;
	}
	else if (mouse_past_eol)
	    dir = FORWARD;

	if (fix_indent)
	{
	    c1 = (dir == BACKWARD) ? '[' : ']';
	    c2 = 'p';
	}
	else
	{
	    c1 = (dir == FORWARD) ? 'p' : 'P';
	    c2 = NUL;
	}
	prep_redo(regname, count, NUL, c1, c2, NUL);

	/*
	 * Remember where the paste started, so in edit() Insstart can be set
	 * to this position
	 */
	if (restart_edit)
	    where_paste_started = curwin->w_cursor;
	do_put(regname, dir, count, fix_indent | PUT_CURSEND);
    }

    /*
     * Ctrl-Mouse click (or double click in a help window) jumps to the tag
     * under the mouse pointer.
     */
    else if ((mod_mask & MOD_MASK_CTRL)
			  || (curbuf->b_help && (mod_mask & MOD_MASK_2CLICK)))
    {
	if (State & INSERT)
	    stuffcharReadbuff(Ctrl('O'));
	stuffcharReadbuff(Ctrl(']'));
	got_click = FALSE;		/* ignore drag&release now */
    }

    /*
     * Shift-Mouse click searches for the next occurrence of the word under
     * the mouse pointer
     */
    else if ((mod_mask & MOD_MASK_SHIFT))
    {
	if (State & INSERT || (VIsual_active && VIsual_select))
	    stuffcharReadbuff(Ctrl('O'));
	if (which_button == MOUSE_LEFT)
	    stuffcharReadbuff('*');
	else	/* MOUSE_RIGHT */
	    stuffcharReadbuff('#');
    }

    /* Handle double clicks, unless on status line */
    else if (in_status_line)
	;
    else if ((mod_mask & MOD_MASK_MULTI_CLICK) && (State & (NORMAL | INSERT)))
    {
	if (is_click || !VIsual_active)
	{
	    if (VIsual_active)
		orig_cursor = VIsual;
	    else
	    {
		check_visual_highlight();
		VIsual = curwin->w_cursor;
		orig_cursor = VIsual;
		VIsual_active = TRUE;
		VIsual_reselect = TRUE;
		/* start Select mode if 'selectmode' contains "mouse" */
		may_start_select('o');
		setmouse();
		if (p_smd)
		    redraw_cmdline = TRUE;  /* show visual mode later */
	    }
	    if (mod_mask & MOD_MASK_2CLICK)
		VIsual_mode = 'v';
	    else if (mod_mask & MOD_MASK_3CLICK)
		VIsual_mode = 'V';
	    else if (mod_mask & MOD_MASK_4CLICK)
		VIsual_mode = Ctrl('V');
	}
	if (mod_mask & MOD_MASK_2CLICK)
	{
	    if (lt(curwin->w_cursor, orig_cursor))
	    {
		find_start_of_word(&curwin->w_cursor);
		find_end_of_word(&VIsual);
	    }
	    else
	    {
		find_start_of_word(&VIsual);
		find_end_of_word(&curwin->w_cursor);
	    }
	    curwin->w_set_curswant = TRUE;
	}
	if (is_click)
	    update_curbuf(NOT_VALID);	    /* update the inversion */
    }
    else if (VIsual_active && VIsual_was_active != VIsual_active)
	VIsual_mode = 'v';

    return moved;
}

    static void
find_start_of_word(pos)
    FPOS    *pos;
{
    char_u  *ptr;
    int	    cclass;

    ptr = ml_get(pos->lnum);
    cclass = get_mouse_class(ptr[pos->col]);

    /* Can't test pos->col >= 0 because pos->col is unsigned */
    while (pos->col > 0 && get_mouse_class(ptr[pos->col]) == cclass)
	pos->col--;
    if (pos->col != 0 || get_mouse_class(ptr[0]) != cclass)
	pos->col++;
}

    static void
find_end_of_word(pos)
    FPOS    *pos;
{
    char_u  *ptr;
    int	    cclass;

    ptr = ml_get(pos->lnum);
    if (*p_sel == 'e' && pos->col)
	pos->col--;
    cclass = get_mouse_class(ptr[pos->col]);
    while (ptr[pos->col] && get_mouse_class(ptr[pos->col]) == cclass)
	pos->col++;
    if (*p_sel != 'e' && pos->col)
	pos->col--;
}

    static int
get_mouse_class(c)
    int	    c;
{
    if (c == ' ' || c == '\t')
	return ' ';

    if (vim_isIDc(c))
	return 'a';

    /*
     * There are a few special cases where we want certain combinations of
     * characters to be considered as a single word.  These are things like
     * "->", "/ *", "*=", "+=", "&=", "<=", ">=", "!=" etc.  Otherwise, each
     * character is in it's own class.
     */
    if (c != NUL && vim_strchr((char_u *)"-+*/%<>&|^!=", c) != NULL)
	return '=';
    return c;
}
#endif /* USE_MOUSE */

/*
 * Check if  highlighting for visual mode is possible, give a warning message
 * if not.
 */
    void
check_visual_highlight()
{
    static int	    did_check = FALSE;

    if (!did_check && hl_attr(HLF_V) == 0)
	MSG("Warning: terminal cannot highlight");
    did_check = TRUE;
}

/*
 * End visual mode.  If we are using the GUI, and autoselect is set, then
 * remember what was selected in case we need to paste it somewhere while we
 * still own the selection.  This function should ALWAYS be called to end
 * visual mode.
 */
    void
end_visual_mode()
{
#ifdef USE_CLIPBOARD
    if (clipboard.available)
	clip_auto_select();
#endif
    VIsual_active = FALSE;
#ifdef USE_MOUSE
    setmouse();
#endif

    /* Save the current VIsual area for '< and '> marks, and "gv" */
    curbuf->b_visual_start = VIsual;
    curbuf->b_visual_end = curwin->w_cursor;
    curbuf->b_visual_mode = VIsual_mode;

    if (p_smd)
	clear_cmdline = TRUE;		/* unshow visual mode later */

    /* Don't leave the cursor past the end of the line */
    if (curwin->w_cursor.col > 0 && *ml_get_cursor() == NUL)
	--curwin->w_cursor.col;
}

/*
 * Find the identifier under or to the right of the cursor.  If none is
 * found and find_type has FIND_STRING, then find any non-white string.  The
 * length of the string is returned, or zero if no string is found.  If a
 * string is found, a pointer to the string is put in *string, but note that
 * the caller must use the length returned as this string may not be NUL
 * terminated.
 */
    int
find_ident_under_cursor(string, find_type)
    char_u  **string;
    int	    find_type;
{
    char_u  *ptr;
    int	    col = 0;	    /* init to shut up GCC */
    int	    i;

    /*
     * if i == 0: try to find an identifier
     * if i == 1: try to find any string
     */
    ptr = ml_get_curline();
    for (i = (find_type & FIND_IDENT) ? 0 : 1;	i < 2; ++i)
    {
	/*
	 * skip to start of identifier/string
	 */
	col = curwin->w_cursor.col;
	while (ptr[col] != NUL &&
		    (i == 0 ? !vim_iswordc(ptr[col]) : vim_iswhite(ptr[col])))
	    ++col;

	/*
	 * Back up to start of identifier/string. This doesn't match the
	 * real vi but I like it a little better and it shouldn't bother
	 * anyone.
	 * When FIND_IDENT isn't defined, we backup until a blank.
	 */
	while (col > 0 && (i == 0 ? vim_iswordc(ptr[col - 1]) :
		    (!vim_iswhite(ptr[co

⌨️ 快捷键说明

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