📄 normal.c
字号:
&& !VIsual_active
&& oap->op_type != OP_TILDE)
{
n_swapchar(&ca);
break;
}
/*FALLTHROUGH*/
case 'd':
case 'c':
case 'y':
case '>':
case '<':
case '!':
case '=':
nv_operator(&ca);
break;
/*
* 8: Abbreviations
*/
case 'S':
case 's':
if (VIsual_active) /* "vs" and "vS" are the same as "vc" */
{
if (ca.cmdchar == 'S')
VIsual_mode = 'V';
ca.cmdchar = 'c';
nv_operator(&ca);
break;
}
/* FALLTHROUGH */
case K_DEL:
case 'Y':
case 'D':
case 'C':
case 'x':
case 'X':
if (ca.cmdchar == K_DEL)
ca.cmdchar = 'x'; /* DEL key behaves like 'x' */
/* with Visual these commands are operators */
if (VIsual_active)
{
v_visop(&ca);
break;
}
/* FALLTHROUGH */
case '&':
nv_optrans(&ca);
opnum = 0;
break;
/*
* 9: Marks
*/
case 'm':
if (!checkclearop(oap))
{
if (setmark(ca.nchar) == FAIL)
clearopbeep(oap);
}
break;
case '\'':
flag = TRUE;
/* FALLTHROUGH */
case '`':
nv_gomark(&ca, flag);
break;
case Ctrl('O'):
/* switch from Select to Visual mode for one command */
if (VIsual_active && VIsual_select)
{
VIsual_select = FALSE;
showmode();
restart_VIsual_select = 2;
break;
}
ca.count1 = -ca.count1; /* goto older pcmark */
/* FALLTHROUGH */
case Ctrl('I'): /* goto newer pcmark */
nv_pcmark(&ca);
break;
/*
* 10. Register name setting
*/
case '"':
nv_regname(&ca, &opnum);
break;
/*
* 11. Visual
*/
case 'v':
case 'V':
case Ctrl('V'):
if (!checkclearop(oap))
nv_visual(&ca, FALSE);
break;
/*
* 12. Suspend
*/
case Ctrl('Z'):
clearop(oap);
if (VIsual_active)
end_visual_mode(); /* stop Visual */
stuffReadbuff((char_u *)":st\r"); /* with autowrite */
break;
/*
* 13. Window commands
*/
case Ctrl('W'):
if (!checkclearop(oap))
do_window(ca.nchar, ca.count0); /* everything is in window.c */
break;
/*
* 14. extended commands (starting with 'g')
*/
case 'g':
command_busy = nv_g_cmd(&ca, &searchbuff);
break;
/*
* 15. mouse click
*/
#ifdef USE_MOUSE
case K_MIDDLEMOUSE:
case K_MIDDLEDRAG:
case K_MIDDLERELEASE:
case K_LEFTMOUSE:
case K_LEFTDRAG:
case K_LEFTRELEASE:
case K_RIGHTMOUSE:
case K_RIGHTDRAG:
case K_RIGHTRELEASE:
(void)do_mouse(oap, ca.cmdchar, BACKWARD, ca.count1, 0);
break;
case K_IGNORE:
break;
#endif
#ifdef USE_GUI
/*
* 16. scrollbar movement
*/
case K_SCROLLBAR:
if (oap->op_type != OP_NOP)
clearopbeep(oap);
/* Even if an operator was pending, we still want to scroll */
gui_do_scroll();
break;
case K_HORIZ_SCROLLBAR:
if (oap->op_type != OP_NOP)
clearopbeep(oap);
/* Even if an operator was pending, we still want to scroll */
gui_do_horiz_scroll();
break;
#endif
case K_SELECT: /* end of Select mode mapping */
nv_select(&ca);
break;
#ifdef FKMAP
case K_F8:
case K_F9:
farsi_fkey(ca.cmdchar);
break;
#endif
#ifdef USE_SNIFF
case K_SNIFF:
ProcessSniffRequests();
break;
#endif
/*
* 17. The end
*/
case Ctrl('C'):
restart_edit = 0;
/*FALLTHROUGH*/
case ESC:
nv_esc(&ca, opnum);
break;
default: /* not a known command */
clearopbeep(oap);
break;
} /* end of switch on command character */
/*
* if we didn't start or finish an operator, reset oap->regname, unless we
* need it later.
*/
if (!finish_op && !oap->op_type &&
vim_strchr((char_u *)"\"DCYSsXx.", ca.cmdchar) == NULL)
oap->regname = 0;
/*
* If an operation is pending, handle it...
*/
do_pending_operator(&ca, searchbuff,
&command_busy, old_col, FALSE, dont_adjust_op_end);
/*
* Wait when a message is displayed that will be overwritten by the mode
* message.
* In Visual mode and with "^O" in Insert mode, a short message will be
* overwritten by the mode message. Wait a bit, until a key is hit.
* In Visual mode, it's more important to keep the Visual area updated
* than keeping a message (e.g. from a /pat search).
* Only do this if the command was typed, not from a mapping.
* Also wait a bit after an error message, e.g. for "^O:".
* Don't redraw the screen, it would remove the message.
*/
if ( ((p_smd
&& ((VIsual_active
&& old_pos.lnum == curwin->w_cursor.lnum
&& old_pos.col == curwin->w_cursor.col)
|| restart_edit)
&& (clear_cmdline
|| redraw_cmdline)
&& msg_didany
&& !msg_nowait
&& KeyTyped)
|| (restart_edit
&& !VIsual_active
&& (msg_scroll
|| emsg_on_display)))
&& oap->regname == 0
&& !command_busy
&& stuff_empty()
&& typebuf_typed()
&& oap->op_type == OP_NOP)
{
/* If need to redraw, and there is a "keep_msg", redraw before the
* delay */
if (must_redraw && keep_msg != NULL && !emsg_on_display)
{
char_u *kmsg = keep_msg;
/* showmode() will clear keep_msg, but we want to use it anyway */
update_screen(must_redraw);
msg_attr(kmsg, keep_msg_attr);
}
setcursor();
cursor_on();
out_flush();
if (msg_scroll || emsg_on_display)
ui_delay(1000L, TRUE); /* wait at least one second */
ui_delay(3000L, FALSE); /* wait up to three seconds */
msg_scroll = FALSE;
emsg_on_display = FALSE;
}
/*
* Finish up after executing a Normal mode command.
*/
normal_end:
msg_nowait = FALSE;
/* Reset finish_op, in case it was set */
#ifdef USE_GUI
c = finish_op;
#endif
finish_op = FALSE;
#ifdef CURSOR_SHAPE
/* Redraw the cursor with another shape, if we were in Operator-pending
* mode or did a replace command. */
if ((c && !finish_op) || ca.cmdchar == 'r')
ui_cursor_shape(); /* may show different cursor shape */
#endif
#ifdef SHOWCMD
if (oap->op_type == OP_NOP && oap->regname == 0)
clear_showcmd();
#endif
/*
* Update the other windows for the current buffer if modified has been
* set in set_Changed() (This should be done more efficiently)
*/
if (modified)
{
update_other_win();
modified = FALSE;
}
checkpcmark(); /* check if we moved since setting pcmark */
vim_free(searchbuff);
/*
* May restart edit(), if we got here with CTRL-O in Insert mode (but not
* if still inside a mapping that started in Visual mode).
* May switch from Visual to Select mode after CTRL-O command.
*/
if ( ((restart_edit && !VIsual_active && old_mapped_len == 0)
|| restart_VIsual_select == 1)
&& oap->op_type == OP_NOP
&& !command_busy
&& stuff_empty()
&& oap->regname == 0)
{
if (restart_VIsual_select == 1)
{
VIsual_select = TRUE;
showmode();
restart_VIsual_select = 0;
}
if (restart_edit && !VIsual_active && old_mapped_len == 0)
(void)edit(restart_edit, FALSE, 1L);
}
if (restart_VIsual_select == 2)
restart_VIsual_select = 1;
#ifdef MULTI_BYTE
if (is_dbcs)
AdjustCursorForMultiByteCharacter();
#endif
}
/*
* Handle an operator after visual mode or when the movement is finished
*/
void
do_pending_operator(cap, searchbuff,
command_busy, old_col, gui_yank, dont_adjust_op_end)
CMDARG *cap;
char_u *searchbuff;
int *command_busy;
int old_col;
int gui_yank; /* yanking visual area for GUI */
int dont_adjust_op_end;
{
OPARG *oap = cap->oap;
FPOS old_cursor;
int empty_region_error;
/* The visual area is remembered for redo */
static int redo_VIsual_mode = NUL; /* 'v', 'V', or Ctrl-V */
static linenr_t redo_VIsual_line_count; /* number of lines */
static colnr_t redo_VIsual_col; /* number of cols or end column */
static long redo_VIsual_count; /* count for Visual operator */
#if defined(USE_CLIPBOARD) && !defined(WIN32)
/*
* Yank the visual area into the GUI selection register before we operate
* on it and lose it forever. This could call do_pending_operator()
* recursively, but that's OK because gui_yank will be TRUE for the
* nested call. Note also that we call clip_copy_selection() and not
* clip_auto_select(). This is because even when 'autoselect' is not set,
* if we operate on the text, eg by deleting it, then this is considered to
* be an explicit request for it to be put in the global cut buffer, so we
* always want to do it here. -- webb
*/
/* WIN32: don't do this, there is no automatic copy to the clipboard */
/* Don't do it if a specific register was specified, so that ""x"*P works */
if (clipboard.available
&& oap->op_type != OP_NOP
&& !gui_yank
&& VIsual_active
&& oap->regname == 0
&& !redo_VIsual_busy)
clip_copy_selection();
#endif
old_cursor = curwin->w_cursor;
/*
* If an operation is pending, handle it...
*/
if ((VIsual_active || finish_op) && oap->op_type != OP_NOP)
{
oap->is_VIsual = VIsual_active;
/* only redo yank when 'y' flag is in 'cpoptions' */
if ((vim_strchr(p_cpo, CPO_YANK) != NULL || oap->op_type != OP_YANK)
&& !VIsual_active)
{
prep_redo(oap->regname, cap->count0, oap->op_prechar,
op_chars[oap->op_type - 1], cap->cmdchar, cap->nchar);
if (cap->cmdchar == '/' || cap->cmdchar == '?') /* was a search */
{
/*
* If 'cpoptions' does not contain 'r', insert the search
* pattern to really repeat the same command.
*/
if (vim_strchr(p_cpo, CPO_REDO) == NULL)
AppendToRedobuff(searchbuff);
AppendToRedobuff(NL_STR);
}
}
if (redo_VIsual_busy)
{
oap->start = curwin->w_cursor;
curwin->w_cursor.lnum += redo_VIsual_line_count - 1;
if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
VIsual_mode = redo_VIsual_mode;
if (VIsual_mode == 'v')
{
if (redo_VIsual_line_count <= 1)
curwin->w_cursor.col += redo_VIsual_col - 1;
else
curwin->w_cursor.col = redo_VIsual_col;
}
if (redo_VIsual_col == MAXCOL)
{
curwin->w_curswant = MAXCOL;
coladvance(MAXCOL);
}
cap->count0 = redo_VIsual_count;
if (redo_VIsual_count != 0)
cap->count1 = redo_VIsual_count;
else
cap->count1 = 1;
}
else if (VIsual_active)
{
/* In Select mode, a linewise selection is operated upon like a
* characterwise selection. */
if (VIsual_select && VIsual_mode == 'V')
{
if (lt(VIsual, curwin->w_cursor))
{
VIsual.col = 0;
curwin->w_cursor.col =
STRLEN(ml_get(curwin->w_cursor.lnum));
}
else
{
curwin->w_cursor.col = 0;
VIsual.col = STRLEN(ml_get(VIsual.lnum));
}
VIsual_mode = 'v';
}
/* If 'selection' is "exclusive", backup one character for
* charwise selections. */
else if (*p_sel == 'e' && VIsual_mode == 'v'
&& !equal(VIsual, curwin->w_cursor))
{
FPOS *pp;
if (lt(VIsual, curwin->w_cursor))
pp = &curwin->w_cursor;
else
pp = &VIsual;
if (pp->col > 0)
--pp->col;
else if (pp->lnum > 1)
{
--pp->lnum;
pp->col = STRLEN(ml_get(pp->lnum));
}
}
/* 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;
oap->start = VIsual;
if (VIsual_mode == 'V')
oap->start.col = 0;
}
/*
* Set oap->start to the first position of the operated text, oap->end
* to the end of the operated text. w_cursor is equal to oap->start.
*/
if (lt(oap->start, curwin->w_cursor))
{
oap->end = curwin->w_cursor;
curwin->w_cursor = oap->start;
}
else
{
oap->end = oap->start;
oap->start = curwin->w_cursor;
}
#ifdef MULTI_BYTE
if (is_dbcs && (VIsual_active || oap->inclusive))
{
char_u *p;
p = ml_get(oap->end.lnum);
if (IsTrailByte(p, p + oap->end.col + 1))
oap->end.col++;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -