📄 normal.c
字号:
/*
* 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 + -