aboutsummaryrefslogtreecommitdiff
path: root/src/normal.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/normal.c')
-rw-r--r--src/normal.c7474
1 files changed, 0 insertions, 7474 deletions
diff --git a/src/normal.c b/src/normal.c
deleted file mode 100644
index dc0035fe85..0000000000
--- a/src/normal.c
+++ /dev/null
@@ -1,7474 +0,0 @@
-/*
- * VIM - Vi IMproved by Bram Moolenaar
- *
- * Do ":help uganda" in Vim to read copying and usage conditions.
- * Do ":help credits" in Vim to see a list of people who contributed.
- * See README.txt for an overview of the Vim source code.
- */
-/*
- * normal.c: Contains the main routine for processing characters in command
- * mode. Communicates closely with the code in ops.c to handle
- * the operators.
- */
-
-#include <string.h>
-#include <stdlib.h>
-
-#include "vim.h"
-#include "normal.h"
-#include "buffer.h"
-#include "charset.h"
-#include "diff.h"
-#include "digraph.h"
-#include "edit.h"
-#include "eval.h"
-#include "ex_cmds.h"
-#include "ex_cmds2.h"
-#include "ex_docmd.h"
-#include "ex_getln.h"
-#include "farsi.h"
-#include "fileio.h"
-#include "fold.h"
-#include "getchar.h"
-#include "indent.h"
-#include "indent_c.h"
-#include "main.h"
-#include "mark.h"
-#include "memline.h"
-#include "memory.h"
-#include "message.h"
-#include "misc1.h"
-#include "misc2.h"
-#include "keymap.h"
-#include "move.h"
-#include "ops.h"
-#include "option.h"
-#include "quickfix.h"
-#include "screen.h"
-#include "search.h"
-#include "spell.h"
-#include "syntax.h"
-#include "tag.h"
-#include "term.h"
-#include "ui.h"
-#include "undo.h"
-#include "window.h"
-#include "os/event.h"
-
-/*
- * The Visual area is remembered for reselection.
- */
-static int resel_VIsual_mode = NUL; /* 'v', 'V', or Ctrl-V */
-static linenr_T resel_VIsual_line_count; /* number of lines */
-static colnr_T resel_VIsual_vcol; /* nr of cols or end col */
-static int VIsual_mode_orig = NUL; /* saved Visual mode */
-
-static int restart_VIsual_select = 0;
-
-static void set_vcount_ca(cmdarg_T *cap, int *set_prevcount);
-static int
-nv_compare(const void *s1, const void *s2);
-static int find_command(int cmdchar);
-static void op_colon(oparg_T *oap);
-static void op_function(oparg_T *oap);
-static void find_start_of_word(pos_T *);
-static void find_end_of_word(pos_T *);
-static int get_mouse_class(char_u *p);
-static void prep_redo_cmd(cmdarg_T *cap);
-static void prep_redo(int regname, long, int, int, int, int, int);
-static int checkclearop(oparg_T *oap);
-static int checkclearopq(oparg_T *oap);
-static void clearop(oparg_T *oap);
-static void clearopbeep(oparg_T *oap);
-static void unshift_special(cmdarg_T *cap);
-static void del_from_showcmd(int);
-
-/*
- * nv_*(): functions called to handle Normal and Visual mode commands.
- * n_*(): functions called to handle Normal mode commands.
- * v_*(): functions called to handle Visual mode commands.
- */
-static void nv_ignore(cmdarg_T *cap);
-static void nv_nop(cmdarg_T *cap);
-static void nv_error(cmdarg_T *cap);
-static void nv_help(cmdarg_T *cap);
-static void nv_addsub(cmdarg_T *cap);
-static void nv_page(cmdarg_T *cap);
-static void nv_gd(oparg_T *oap, int nchar, int thisblock);
-static int nv_screengo(oparg_T *oap, int dir, long dist);
-static void nv_mousescroll(cmdarg_T *cap);
-static void nv_mouse(cmdarg_T *cap);
-static void nv_scroll_line(cmdarg_T *cap);
-static void nv_zet(cmdarg_T *cap);
-static void nv_exmode(cmdarg_T *cap);
-static void nv_colon(cmdarg_T *cap);
-static void nv_ctrlg(cmdarg_T *cap);
-static void nv_ctrlh(cmdarg_T *cap);
-static void nv_clear(cmdarg_T *cap);
-static void nv_ctrlo(cmdarg_T *cap);
-static void nv_hat(cmdarg_T *cap);
-static void nv_Zet(cmdarg_T *cap);
-static void nv_ident(cmdarg_T *cap);
-static void nv_tagpop(cmdarg_T *cap);
-static void nv_scroll(cmdarg_T *cap);
-static void nv_right(cmdarg_T *cap);
-static void nv_left(cmdarg_T *cap);
-static void nv_up(cmdarg_T *cap);
-static void nv_down(cmdarg_T *cap);
-static void nv_gotofile(cmdarg_T *cap);
-static void nv_end(cmdarg_T *cap);
-static void nv_dollar(cmdarg_T *cap);
-static void nv_search(cmdarg_T *cap);
-static void nv_next(cmdarg_T *cap);
-static void normal_search(cmdarg_T *cap, int dir, char_u *pat, int opt);
-static void nv_csearch(cmdarg_T *cap);
-static void nv_brackets(cmdarg_T *cap);
-static void nv_percent(cmdarg_T *cap);
-static void nv_brace(cmdarg_T *cap);
-static void nv_mark(cmdarg_T *cap);
-static void nv_findpar(cmdarg_T *cap);
-static void nv_undo(cmdarg_T *cap);
-static void nv_kundo(cmdarg_T *cap);
-static void nv_Replace(cmdarg_T *cap);
-static void nv_vreplace(cmdarg_T *cap);
-static void v_swap_corners(int cmdchar);
-static void nv_replace(cmdarg_T *cap);
-static void n_swapchar(cmdarg_T *cap);
-static void nv_cursormark(cmdarg_T *cap, int flag, pos_T *pos);
-static void v_visop(cmdarg_T *cap);
-static void nv_subst(cmdarg_T *cap);
-static void nv_abbrev(cmdarg_T *cap);
-static void nv_optrans(cmdarg_T *cap);
-static void nv_gomark(cmdarg_T *cap);
-static void nv_pcmark(cmdarg_T *cap);
-static void nv_regname(cmdarg_T *cap);
-static void nv_visual(cmdarg_T *cap);
-static void n_start_visual_mode(int c);
-static void nv_window(cmdarg_T *cap);
-static void nv_suspend(cmdarg_T *cap);
-static void nv_g_cmd(cmdarg_T *cap);
-static void n_opencmd(cmdarg_T *cap);
-static void nv_dot(cmdarg_T *cap);
-static void nv_redo(cmdarg_T *cap);
-static void nv_Undo(cmdarg_T *cap);
-static void nv_tilde(cmdarg_T *cap);
-static void nv_operator(cmdarg_T *cap);
-static void set_op_var(int optype);
-static void nv_lineop(cmdarg_T *cap);
-static void nv_home(cmdarg_T *cap);
-static void nv_pipe(cmdarg_T *cap);
-static void nv_bck_word(cmdarg_T *cap);
-static void nv_wordcmd(cmdarg_T *cap);
-static void nv_beginline(cmdarg_T *cap);
-static void adjust_cursor(oparg_T *oap);
-static void adjust_for_sel(cmdarg_T *cap);
-static int unadjust_for_sel(void);
-static void nv_select(cmdarg_T *cap);
-static void nv_goto(cmdarg_T *cap);
-static void nv_normal(cmdarg_T *cap);
-static void nv_esc(cmdarg_T *oap);
-static void nv_edit(cmdarg_T *cap);
-static void invoke_edit(cmdarg_T *cap, int repl, int cmd, int startln);
-static void nv_object(cmdarg_T *cap);
-static void nv_record(cmdarg_T *cap);
-static void nv_at(cmdarg_T *cap);
-static void nv_halfpage(cmdarg_T *cap);
-static void nv_join(cmdarg_T *cap);
-static void nv_put(cmdarg_T *cap);
-static void nv_open(cmdarg_T *cap);
-static void nv_cursorhold(cmdarg_T *cap);
-static void nv_event(cmdarg_T *cap);
-
-static char *e_noident = N_("E349: No identifier under cursor");
-
-/*
- * Function to be called for a Normal or Visual mode command.
- * The argument is a cmdarg_T.
- */
-typedef void (*nv_func_T)(cmdarg_T *cap);
-
-/* Values for cmd_flags. */
-#define NV_NCH 0x01 /* may need to get a second char */
-#define NV_NCH_NOP (0x02|NV_NCH) /* get second char when no operator pending */
-#define NV_NCH_ALW (0x04|NV_NCH) /* always get a second char */
-#define NV_LANG 0x08 /* second char needs language adjustment */
-
-#define NV_SS 0x10 /* may start selection */
-#define NV_SSS 0x20 /* may start selection with shift modifier */
-#define NV_STS 0x40 /* may stop selection without shift modif. */
-#define NV_RL 0x80 /* 'rightleft' modifies command */
-#define NV_KEEPREG 0x100 /* don't clear regname */
-#define NV_NCW 0x200 /* not allowed in command-line window */
-
-/*
- * Generally speaking, every Normal mode command should either clear any
- * pending operator (with *clearop*()), or set the motion type variable
- * oap->motion_type.
- *
- * When a cursor motion command is made, it is marked as being a character or
- * line oriented motion. Then, if an operator is in effect, the operation
- * becomes character or line oriented accordingly.
- */
-
-/*
- * This table contains one entry for every Normal or Visual mode command.
- * The order doesn't matter, init_normal_cmds() will create a sorted index.
- * It is faster when all keys from zero to '~' are present.
- */
-static const struct nv_cmd {
- int cmd_char; /* (first) command character */
- nv_func_T cmd_func; /* function for this command */
- uint16_t cmd_flags; /* NV_ flags */
- short cmd_arg; /* value for ca.arg */
-} nv_cmds[] =
-{
- {NUL, nv_error, 0, 0},
- {Ctrl_A, nv_addsub, 0, 0},
- {Ctrl_B, nv_page, NV_STS, BACKWARD},
- {Ctrl_C, nv_esc, 0, TRUE},
- {Ctrl_D, nv_halfpage, 0, 0},
- {Ctrl_E, nv_scroll_line, 0, TRUE},
- {Ctrl_F, nv_page, NV_STS, FORWARD},
- {Ctrl_G, nv_ctrlg, 0, 0},
- {Ctrl_H, nv_ctrlh, 0, 0},
- {Ctrl_I, nv_pcmark, 0, 0},
- {NL, nv_down, 0, FALSE},
- {Ctrl_K, nv_error, 0, 0},
- {Ctrl_L, nv_clear, 0, 0},
- {Ctrl_M, nv_down, 0, TRUE},
- {Ctrl_N, nv_down, NV_STS, FALSE},
- {Ctrl_O, nv_ctrlo, 0, 0},
- {Ctrl_P, nv_up, NV_STS, FALSE},
- {Ctrl_Q, nv_visual, 0, FALSE},
- {Ctrl_R, nv_redo, 0, 0},
- {Ctrl_S, nv_ignore, 0, 0},
- {Ctrl_T, nv_tagpop, NV_NCW, 0},
- {Ctrl_U, nv_halfpage, 0, 0},
- {Ctrl_V, nv_visual, 0, FALSE},
- {'V', nv_visual, 0, FALSE},
- {'v', nv_visual, 0, FALSE},
- {Ctrl_W, nv_window, 0, 0},
- {Ctrl_X, nv_addsub, 0, 0},
- {Ctrl_Y, nv_scroll_line, 0, FALSE},
- {Ctrl_Z, nv_suspend, 0, 0},
- {ESC, nv_esc, 0, FALSE},
- {Ctrl_BSL, nv_normal, NV_NCH_ALW, 0},
- {Ctrl_RSB, nv_ident, NV_NCW, 0},
- {Ctrl_HAT, nv_hat, NV_NCW, 0},
- {Ctrl__, nv_error, 0, 0},
- {' ', nv_right, 0, 0},
- {'!', nv_operator, 0, 0},
- {'"', nv_regname, NV_NCH_NOP|NV_KEEPREG, 0},
- {'#', nv_ident, 0, 0},
- {'$', nv_dollar, 0, 0},
- {'%', nv_percent, 0, 0},
- {'&', nv_optrans, 0, 0},
- {'\'', nv_gomark, NV_NCH_ALW, TRUE},
- {'(', nv_brace, 0, BACKWARD},
- {')', nv_brace, 0, FORWARD},
- {'*', nv_ident, 0, 0},
- {'+', nv_down, 0, TRUE},
- {',', nv_csearch, 0, TRUE},
- {'-', nv_up, 0, TRUE},
- {'.', nv_dot, NV_KEEPREG, 0},
- {'/', nv_search, 0, FALSE},
- {'0', nv_beginline, 0, 0},
- {'1', nv_ignore, 0, 0},
- {'2', nv_ignore, 0, 0},
- {'3', nv_ignore, 0, 0},
- {'4', nv_ignore, 0, 0},
- {'5', nv_ignore, 0, 0},
- {'6', nv_ignore, 0, 0},
- {'7', nv_ignore, 0, 0},
- {'8', nv_ignore, 0, 0},
- {'9', nv_ignore, 0, 0},
- {':', nv_colon, 0, 0},
- {';', nv_csearch, 0, FALSE},
- {'<', nv_operator, NV_RL, 0},
- {'=', nv_operator, 0, 0},
- {'>', nv_operator, NV_RL, 0},
- {'?', nv_search, 0, FALSE},
- {'@', nv_at, NV_NCH_NOP, FALSE},
- {'A', nv_edit, 0, 0},
- {'B', nv_bck_word, 0, 1},
- {'C', nv_abbrev, NV_KEEPREG, 0},
- {'D', nv_abbrev, NV_KEEPREG, 0},
- {'E', nv_wordcmd, 0, TRUE},
- {'F', nv_csearch, NV_NCH_ALW|NV_LANG, BACKWARD},
- {'G', nv_goto, 0, TRUE},
- {'H', nv_scroll, 0, 0},
- {'I', nv_edit, 0, 0},
- {'J', nv_join, 0, 0},
- {'K', nv_ident, 0, 0},
- {'L', nv_scroll, 0, 0},
- {'M', nv_scroll, 0, 0},
- {'N', nv_next, 0, SEARCH_REV},
- {'O', nv_open, 0, 0},
- {'P', nv_put, 0, 0},
- {'Q', nv_exmode, NV_NCW, 0},
- {'R', nv_Replace, 0, FALSE},
- {'S', nv_subst, NV_KEEPREG, 0},
- {'T', nv_csearch, NV_NCH_ALW|NV_LANG, BACKWARD},
- {'U', nv_Undo, 0, 0},
- {'W', nv_wordcmd, 0, TRUE},
- {'X', nv_abbrev, NV_KEEPREG, 0},
- {'Y', nv_abbrev, NV_KEEPREG, 0},
- {'Z', nv_Zet, NV_NCH_NOP|NV_NCW, 0},
- {'[', nv_brackets, NV_NCH_ALW, BACKWARD},
- {'\\', nv_error, 0, 0},
- {']', nv_brackets, NV_NCH_ALW, FORWARD},
- {'^', nv_beginline, 0, BL_WHITE | BL_FIX},
- {'_', nv_lineop, 0, 0},
- {'`', nv_gomark, NV_NCH_ALW, FALSE},
- {'a', nv_edit, NV_NCH, 0},
- {'b', nv_bck_word, 0, 0},
- {'c', nv_operator, 0, 0},
- {'d', nv_operator, 0, 0},
- {'e', nv_wordcmd, 0, FALSE},
- {'f', nv_csearch, NV_NCH_ALW|NV_LANG, FORWARD},
- {'g', nv_g_cmd, NV_NCH_ALW, FALSE},
- {'h', nv_left, NV_RL, 0},
- {'i', nv_edit, NV_NCH, 0},
- {'j', nv_down, 0, FALSE},
- {'k', nv_up, 0, FALSE},
- {'l', nv_right, NV_RL, 0},
- {'m', nv_mark, NV_NCH_NOP, 0},
- {'n', nv_next, 0, 0},
- {'o', nv_open, 0, 0},
- {'p', nv_put, 0, 0},
- {'q', nv_record, NV_NCH, 0},
- {'r', nv_replace, NV_NCH_NOP|NV_LANG, 0},
- {'s', nv_subst, NV_KEEPREG, 0},
- {'t', nv_csearch, NV_NCH_ALW|NV_LANG, FORWARD},
- {'u', nv_undo, 0, 0},
- {'w', nv_wordcmd, 0, FALSE},
- {'x', nv_abbrev, NV_KEEPREG, 0},
- {'y', nv_operator, 0, 0},
- {'z', nv_zet, NV_NCH_ALW, 0},
- {'{', nv_findpar, 0, BACKWARD},
- {'|', nv_pipe, 0, 0},
- {'}', nv_findpar, 0, FORWARD},
- {'~', nv_tilde, 0, 0},
-
- /* pound sign */
- {POUND, nv_ident, 0, 0},
- {K_MOUSEUP, nv_mousescroll, 0, MSCR_UP},
- {K_MOUSEDOWN, nv_mousescroll, 0, MSCR_DOWN},
- {K_MOUSELEFT, nv_mousescroll, 0, MSCR_LEFT},
- {K_MOUSERIGHT, nv_mousescroll, 0, MSCR_RIGHT},
- {K_LEFTMOUSE, nv_mouse, 0, 0},
- {K_LEFTMOUSE_NM, nv_mouse, 0, 0},
- {K_LEFTDRAG, nv_mouse, 0, 0},
- {K_LEFTRELEASE, nv_mouse, 0, 0},
- {K_LEFTRELEASE_NM, nv_mouse, 0, 0},
- {K_MIDDLEMOUSE, nv_mouse, 0, 0},
- {K_MIDDLEDRAG, nv_mouse, 0, 0},
- {K_MIDDLERELEASE, nv_mouse, 0, 0},
- {K_RIGHTMOUSE, nv_mouse, 0, 0},
- {K_RIGHTDRAG, nv_mouse, 0, 0},
- {K_RIGHTRELEASE, nv_mouse, 0, 0},
- {K_X1MOUSE, nv_mouse, 0, 0},
- {K_X1DRAG, nv_mouse, 0, 0},
- {K_X1RELEASE, nv_mouse, 0, 0},
- {K_X2MOUSE, nv_mouse, 0, 0},
- {K_X2DRAG, nv_mouse, 0, 0},
- {K_X2RELEASE, nv_mouse, 0, 0},
- {K_IGNORE, nv_ignore, NV_KEEPREG, 0},
- {K_NOP, nv_nop, 0, 0},
- {K_INS, nv_edit, 0, 0},
- {K_KINS, nv_edit, 0, 0},
- {K_BS, nv_ctrlh, 0, 0},
- {K_UP, nv_up, NV_SSS|NV_STS, FALSE},
- {K_S_UP, nv_page, NV_SS, BACKWARD},
- {K_DOWN, nv_down, NV_SSS|NV_STS, FALSE},
- {K_S_DOWN, nv_page, NV_SS, FORWARD},
- {K_LEFT, nv_left, NV_SSS|NV_STS|NV_RL, 0},
- {K_S_LEFT, nv_bck_word, NV_SS|NV_RL, 0},
- {K_C_LEFT, nv_bck_word, NV_SSS|NV_RL|NV_STS, 1},
- {K_RIGHT, nv_right, NV_SSS|NV_STS|NV_RL, 0},
- {K_S_RIGHT, nv_wordcmd, NV_SS|NV_RL, FALSE},
- {K_C_RIGHT, nv_wordcmd, NV_SSS|NV_RL|NV_STS, TRUE},
- {K_PAGEUP, nv_page, NV_SSS|NV_STS, BACKWARD},
- {K_KPAGEUP, nv_page, NV_SSS|NV_STS, BACKWARD},
- {K_PAGEDOWN, nv_page, NV_SSS|NV_STS, FORWARD},
- {K_KPAGEDOWN, nv_page, NV_SSS|NV_STS, FORWARD},
- {K_END, nv_end, NV_SSS|NV_STS, FALSE},
- {K_KEND, nv_end, NV_SSS|NV_STS, FALSE},
- {K_S_END, nv_end, NV_SS, FALSE},
- {K_C_END, nv_end, NV_SSS|NV_STS, TRUE},
- {K_HOME, nv_home, NV_SSS|NV_STS, 0},
- {K_KHOME, nv_home, NV_SSS|NV_STS, 0},
- {K_S_HOME, nv_home, NV_SS, 0},
- {K_C_HOME, nv_goto, NV_SSS|NV_STS, FALSE},
- {K_DEL, nv_abbrev, 0, 0},
- {K_KDEL, nv_abbrev, 0, 0},
- {K_UNDO, nv_kundo, 0, 0},
- {K_HELP, nv_help, NV_NCW, 0},
- {K_F1, nv_help, NV_NCW, 0},
- {K_XF1, nv_help, NV_NCW, 0},
- {K_SELECT, nv_select, 0, 0},
- {K_F8, farsi_fkey, 0, 0},
- {K_F9, farsi_fkey, 0, 0},
- {K_CURSORHOLD, nv_cursorhold, NV_KEEPREG, 0},
- {K_EVENT, nv_event, NV_KEEPREG, 0},
-};
-
-/* Number of commands in nv_cmds[]. */
-#define NV_CMDS_SIZE (sizeof(nv_cmds) / sizeof(struct nv_cmd))
-
-/* Sorted index of commands in nv_cmds[]. */
-static short nv_cmd_idx[NV_CMDS_SIZE];
-
-/* The highest index for which
- * nv_cmds[idx].cmd_char == nv_cmd_idx[nv_cmds[idx].cmd_char] */
-static int nv_max_linear;
-
-/*
- * Compare functions for qsort() below, that checks the command character
- * through the index in nv_cmd_idx[].
- */
-static int nv_compare(const void *s1, const void *s2)
-{
- int c1, c2;
-
- /* The commands are sorted on absolute value. */
- c1 = nv_cmds[*(const short *)s1].cmd_char;
- c2 = nv_cmds[*(const short *)s2].cmd_char;
- if (c1 < 0)
- c1 = -c1;
- if (c2 < 0)
- c2 = -c2;
- return c1 - c2;
-}
-
-/*
- * Initialize the nv_cmd_idx[] table.
- */
-void init_normal_cmds(void)
-{
- int i;
-
- /* Fill the index table with a one to one relation. */
- for (i = 0; i < (int)NV_CMDS_SIZE; ++i)
- nv_cmd_idx[i] = i;
-
- /* Sort the commands by the command character. */
- qsort((void *)&nv_cmd_idx, (size_t)NV_CMDS_SIZE, sizeof(short), nv_compare);
-
- /* Find the first entry that can't be indexed by the command character. */
- for (i = 0; i < (int)NV_CMDS_SIZE; ++i)
- if (i != nv_cmds[nv_cmd_idx[i]].cmd_char)
- break;
- nv_max_linear = i - 1;
-}
-
-/*
- * Search for a command in the commands table.
- * Returns -1 for invalid command.
- */
-static int find_command(int cmdchar)
-{
- int i;
- int idx;
- int top, bot;
- int c;
-
- /* A multi-byte character is never a command. */
- if (cmdchar >= 0x100)
- return -1;
-
- /* We use the absolute value of the character. Special keys have a
- * negative value, but are sorted on their absolute value. */
- if (cmdchar < 0)
- cmdchar = -cmdchar;
-
- /* If the character is in the first part: The character is the index into
- * nv_cmd_idx[]. */
- if (cmdchar <= nv_max_linear)
- return nv_cmd_idx[cmdchar];
-
- /* Perform a binary search. */
- bot = nv_max_linear + 1;
- top = NV_CMDS_SIZE - 1;
- idx = -1;
- while (bot <= top) {
- i = (top + bot) / 2;
- c = nv_cmds[nv_cmd_idx[i]].cmd_char;
- if (c < 0)
- c = -c;
- if (cmdchar == c) {
- idx = nv_cmd_idx[i];
- break;
- }
- if (cmdchar > c)
- bot = i + 1;
- else
- top = i - 1;
- }
- return idx;
-}
-
-/*
- * Execute a command in Normal mode.
- */
-void
-normal_cmd (
- oparg_T *oap,
- int toplevel /* TRUE when called from main() */
-)
-{
- cmdarg_T ca; /* command arguments */
- int c;
- int ctrl_w = FALSE; /* got CTRL-W command */
- int old_col = curwin->w_curswant;
- int need_flushbuf; /* need to call out_flush() */
- pos_T old_pos; /* cursor position before command */
- int mapped_len;
- static int old_mapped_len = 0;
- int idx;
- int set_prevcount = FALSE;
-
- memset(&ca, 0, sizeof(ca)); /* also resets ca.retval */
- ca.oap = oap;
-
- /* Use a count remembered from before entering an operator. After typing
- * "3d" we return from normal_cmd() and come back here, the "3" is
- * remembered in "opcount". */
- ca.opcount = opcount;
-
-
- /*
- * If there is an operator pending, then the command we take this time
- * will terminate it. Finish_op tells us to finish the operation before
- * returning this time (unless the operation was cancelled).
- */
- c = finish_op;
- finish_op = (oap->op_type != OP_NOP);
- if (finish_op != c) {
- ui_cursor_shape(); /* may show different cursor shape */
- }
-
- /* When not finishing an operator and no register name typed, reset the
- * count. */
- if (!finish_op && !oap->regname) {
- ca.opcount = 0;
- set_prevcount = TRUE;
- }
-
- /* Restore counts from before receiving K_CURSORHOLD. This means after
- * typing "3", handling K_CURSORHOLD and then typing "2" we get "32", not
- * "3 * 2". */
- if (oap->prev_opcount > 0 || oap->prev_count0 > 0) {
- ca.opcount = oap->prev_opcount;
- ca.count0 = oap->prev_count0;
- oap->prev_opcount = 0;
- oap->prev_count0 = 0;
- }
-
- mapped_len = typebuf_maplen();
-
- State = NORMAL_BUSY;
-#ifdef USE_ON_FLY_SCROLL
- dont_scroll = FALSE; /* allow scrolling here */
-#endif
-
- /* Set v:count here, when called from main() and not a stuffed
- * command, so that v:count can be used in an expression mapping
- * when there is no count. Do set it for redo. */
- if (toplevel && readbuf1_empty())
- set_vcount_ca(&ca, &set_prevcount);
-
- /*
- * Get the command character from the user.
- */
- c = safe_vgetc();
- LANGMAP_ADJUST(c, TRUE);
-
- /*
- * If a mapping was started in Visual or Select mode, remember the length
- * of the mapping. This is used below to not return to Insert mode for as
- * long as the mapping is being executed.
- */
- if (restart_edit == 0)
- old_mapped_len = 0;
- else if (old_mapped_len
- || (VIsual_active && mapped_len == 0 && typebuf_maplen() > 0))
- old_mapped_len = typebuf_maplen();
-
- if (c == NUL)
- c = K_ZERO;
-
- /*
- * In Select mode, typed text replaces the selection.
- */
- if (VIsual_active
- && VIsual_select
- && (vim_isprintc(c) || c == NL || c == CAR || c == K_KENTER)) {
- /* Fake a "c"hange command. When "restart_edit" is set (e.g., because
- * 'insertmode' is set) fake a "d"elete command, Insert mode will
- * restart automatically.
- * Insert the typed character in the typeahead buffer, so that it can
- * be mapped in Insert mode. Required for ":lmap" to work. */
- ins_char_typebuf(c);
- if (restart_edit != 0)
- c = 'd';
- else
- c = 'c';
- msg_nowait = TRUE; /* don't delay going to insert mode */
- old_mapped_len = 0; /* do go to Insert mode */
- }
-
- need_flushbuf = add_to_showcmd(c);
-
-getcount:
- if (!(VIsual_active && VIsual_select)) {
- /*
- * Handle a count before a command and compute ca.count0.
- * Note that '0' is a command and not the start of a count, but it's
- * part of a count after other digits.
- */
- while ( (c >= '1' && c <= '9')
- || (ca.count0 != 0 &&
- (c == K_DEL || c == K_KDEL || c == '0'))) {
- if (c == K_DEL || c == K_KDEL) {
- ca.count0 /= 10;
- del_from_showcmd(4); /* delete the digit and ~@% */
- } else
- ca.count0 = ca.count0 * 10 + (c - '0');
- if (ca.count0 < 0) /* got too large! */
- ca.count0 = 999999999L;
- /* Set v:count here, when called from main() and not a stuffed
- * command, so that v:count can be used in an expression mapping
- * right after the count. Do set it for redo. */
- if (toplevel && readbuf1_empty())
- set_vcount_ca(&ca, &set_prevcount);
- if (ctrl_w) {
- ++no_mapping;
- ++allow_keys; /* no mapping for nchar, but keys */
- }
- ++no_zero_mapping; /* don't map zero here */
- c = plain_vgetc();
- LANGMAP_ADJUST(c, TRUE);
- --no_zero_mapping;
- if (ctrl_w) {
- --no_mapping;
- --allow_keys;
- }
- need_flushbuf |= add_to_showcmd(c);
- }
-
- /*
- * If we got CTRL-W there may be a/another count
- */
- if (c == Ctrl_W && !ctrl_w && oap->op_type == OP_NOP) {
- ctrl_w = TRUE;
- ca.opcount = ca.count0; /* remember first count */
- ca.count0 = 0;
- ++no_mapping;
- ++allow_keys; /* no mapping for nchar, but keys */
- c = plain_vgetc(); /* get next character */
- LANGMAP_ADJUST(c, TRUE);
- --no_mapping;
- --allow_keys;
- need_flushbuf |= add_to_showcmd(c);
- goto getcount; /* jump back */
- }
- }
-
- if (c == K_CURSORHOLD) {
- /* Save the count values so that ca.opcount and ca.count0 are exactly
- * the same when coming back here after handling K_CURSORHOLD. */
- oap->prev_opcount = ca.opcount;
- oap->prev_count0 = ca.count0;
- } else if (ca.opcount != 0) {
- /*
- * If we're in the middle of an operator (including after entering a
- * yank buffer with '"') AND we had a count before the operator, then
- * that count overrides the current value of ca.count0.
- * What this means effectively, is that commands like "3dw" get turned
- * into "d3w" which makes things fall into place pretty neatly.
- * If you give a count before AND after the operator, they are
- * multiplied.
- */
- if (ca.count0)
- ca.count0 *= ca.opcount;
- else
- ca.count0 = ca.opcount;
- }
-
- /*
- * Always remember the count. It will be set to zero (on the next call,
- * above) when there is no pending operator.
- * When called from main(), save the count for use by the "count" built-in
- * variable.
- */
- ca.opcount = ca.count0;
- ca.count1 = (ca.count0 == 0 ? 1 : ca.count0);
-
- /*
- * Only set v:count when called from main() and not a stuffed command.
- * Do set it for redo.
- */
- if (toplevel && readbuf1_empty())
- set_vcount(ca.count0, ca.count1, set_prevcount);
-
- /*
- * Find the command character in the table of commands.
- * For CTRL-W we already got nchar when looking for a count.
- */
- if (ctrl_w) {
- ca.nchar = c;
- ca.cmdchar = Ctrl_W;
- } else
- ca.cmdchar = c;
- idx = find_command(ca.cmdchar);
- if (idx < 0) {
- /* Not a known command: beep. */
- clearopbeep(oap);
- goto normal_end;
- }
-
- if (text_locked() && (nv_cmds[idx].cmd_flags & NV_NCW)) {
- /* This command is not allowed while editing a ccmdline: beep. */
- clearopbeep(oap);
- text_locked_msg();
- goto normal_end;
- }
- if ((nv_cmds[idx].cmd_flags & NV_NCW) && curbuf_locked())
- goto normal_end;
-
- /*
- * In Visual/Select mode, a few keys are handled in a special way.
- */
- if (VIsual_active) {
- /* when 'keymodel' contains "stopsel" may stop Select/Visual mode */
- if (km_stopsel
- && (nv_cmds[idx].cmd_flags & NV_STS)
- && !(mod_mask & MOD_MASK_SHIFT)) {
- end_visual_mode();
- redraw_curbuf_later(INVERTED);
- }
-
- /* Keys that work different when 'keymodel' contains "startsel" */
- if (km_startsel) {
- if (nv_cmds[idx].cmd_flags & NV_SS) {
- unshift_special(&ca);
- idx = find_command(ca.cmdchar);
- if (idx < 0) {
- /* Just in case */
- clearopbeep(oap);
- goto normal_end;
- }
- } else if ((nv_cmds[idx].cmd_flags & NV_SSS)
- && (mod_mask & MOD_MASK_SHIFT)) {
- mod_mask &= ~MOD_MASK_SHIFT;
- }
- }
- }
-
- if (curwin->w_p_rl && KeyTyped && !KeyStuffed
- && (nv_cmds[idx].cmd_flags & NV_RL)) {
- /* Invert horizontal movements and operations. Only when typed by the
- * user directly, not when the result of a mapping or "x" translated
- * to "dl". */
- switch (ca.cmdchar) {
- case 'l': ca.cmdchar = 'h'; break;
- case K_RIGHT: ca.cmdchar = K_LEFT; break;
- case K_S_RIGHT: ca.cmdchar = K_S_LEFT; break;
- case K_C_RIGHT: ca.cmdchar = K_C_LEFT; break;
- case 'h': ca.cmdchar = 'l'; break;
- case K_LEFT: ca.cmdchar = K_RIGHT; break;
- case K_S_LEFT: ca.cmdchar = K_S_RIGHT; break;
- case K_C_LEFT: ca.cmdchar = K_C_RIGHT; break;
- case '>': ca.cmdchar = '<'; break;
- case '<': ca.cmdchar = '>'; break;
- }
- idx = find_command(ca.cmdchar);
- }
-
- /*
- * Get an additional character if we need one.
- */
- if ((nv_cmds[idx].cmd_flags & NV_NCH)
- && (((nv_cmds[idx].cmd_flags & NV_NCH_NOP) == NV_NCH_NOP
- && oap->op_type == OP_NOP)
- || (nv_cmds[idx].cmd_flags & NV_NCH_ALW) == NV_NCH_ALW
- || (ca.cmdchar == 'q'
- && oap->op_type == OP_NOP
- && !Recording
- && !Exec_reg)
- || ((ca.cmdchar == 'a' || ca.cmdchar == 'i')
- && (oap->op_type != OP_NOP
- || VIsual_active
- )))) {
- int *cp;
- int repl = FALSE; /* get character for replace mode */
- int lit = FALSE; /* get extra character literally */
- int langmap_active = FALSE; /* using :lmap mappings */
- int lang; /* getting a text character */
-#ifdef USE_IM_CONTROL
- int save_smd; /* saved value of p_smd */
-#endif
-
- ++no_mapping;
- ++allow_keys; /* no mapping for nchar, but allow key codes */
- /* Don't generate a CursorHold event here, most commands can't handle
- * it, e.g., nv_replace(), nv_csearch(). */
- did_cursorhold = TRUE;
- if (ca.cmdchar == 'g') {
- /*
- * For 'g' get the next character now, so that we can check for
- * "gr", "g'" and "g`".
- */
- ca.nchar = plain_vgetc();
- LANGMAP_ADJUST(ca.nchar, TRUE);
- need_flushbuf |= add_to_showcmd(ca.nchar);
- if (ca.nchar == 'r' || ca.nchar == '\'' || ca.nchar == '`'
- || ca.nchar == Ctrl_BSL) {
- cp = &ca.extra_char; /* need to get a third character */
- if (ca.nchar != 'r')
- lit = TRUE; /* get it literally */
- else
- repl = TRUE; /* get it in replace mode */
- } else
- cp = NULL; /* no third character needed */
- } else {
- if (ca.cmdchar == 'r') /* get it in replace mode */
- repl = TRUE;
- cp = &ca.nchar;
- }
- lang = (repl || (nv_cmds[idx].cmd_flags & NV_LANG));
-
- /*
- * Get a second or third character.
- */
- if (cp != NULL) {
- if (repl) {
- State = REPLACE; /* pretend Replace mode */
- ui_cursor_shape(); /* show different cursor shape */
- }
- if (lang && curbuf->b_p_iminsert == B_IMODE_LMAP) {
- /* Allow mappings defined with ":lmap". */
- --no_mapping;
- --allow_keys;
- if (repl)
- State = LREPLACE;
- else
- State = LANGMAP;
- langmap_active = TRUE;
- }
-#ifdef USE_IM_CONTROL
- save_smd = p_smd;
- p_smd = FALSE; /* Don't let the IM code show the mode here */
- if (lang && curbuf->b_p_iminsert == B_IMODE_IM)
- im_set_active(TRUE);
-#endif
-
- *cp = plain_vgetc();
-
- if (langmap_active) {
- /* Undo the decrement done above */
- ++no_mapping;
- ++allow_keys;
- State = NORMAL_BUSY;
- }
-#ifdef USE_IM_CONTROL
- if (lang) {
- if (curbuf->b_p_iminsert != B_IMODE_LMAP)
- im_save_status(&curbuf->b_p_iminsert);
- im_set_active(FALSE);
- }
- p_smd = save_smd;
-#endif
- State = NORMAL_BUSY;
- need_flushbuf |= add_to_showcmd(*cp);
-
- if (!lit) {
- /* Typing CTRL-K gets a digraph. */
- if (*cp == Ctrl_K
- && ((nv_cmds[idx].cmd_flags & NV_LANG)
- || cp == &ca.extra_char)
- && vim_strchr(p_cpo, CPO_DIGRAPH) == NULL) {
- c = get_digraph(FALSE);
- if (c > 0) {
- *cp = c;
- /* Guessing how to update showcmd here... */
- del_from_showcmd(3);
- need_flushbuf |= add_to_showcmd(*cp);
- }
- }
-
- /* adjust chars > 127, except after "tTfFr" commands */
- LANGMAP_ADJUST(*cp, !lang);
- /* adjust Hebrew mapped char */
- if (p_hkmap && lang && KeyTyped)
- *cp = hkmap(*cp);
- /* adjust Farsi mapped char */
- if (p_fkmap && lang && KeyTyped)
- *cp = fkmap(*cp);
- }
-
- /*
- * When the next character is CTRL-\ a following CTRL-N means the
- * command is aborted and we go to Normal mode.
- */
- if (cp == &ca.extra_char
- && ca.nchar == Ctrl_BSL
- && (ca.extra_char == Ctrl_N || ca.extra_char == Ctrl_G)) {
- ca.cmdchar = Ctrl_BSL;
- ca.nchar = ca.extra_char;
- idx = find_command(ca.cmdchar);
- } else if ((ca.nchar == 'n' || ca.nchar == 'N') && ca.cmdchar == 'g')
- ca.oap->op_type = get_op_type(*cp, NUL);
- else if (*cp == Ctrl_BSL) {
- long towait = (p_ttm >= 0 ? p_ttm : p_tm);
-
- /* There is a busy wait here when typing "f<C-\>" and then
- * something different from CTRL-N. Can't be avoided. */
- while ((c = vpeekc()) <= 0 && towait > 0L) {
- do_sleep(towait > 50L ? 50L : towait);
- towait -= 50L;
- }
- if (c > 0) {
- c = plain_vgetc();
- if (c != Ctrl_N && c != Ctrl_G)
- vungetc(c);
- else {
- ca.cmdchar = Ctrl_BSL;
- ca.nchar = c;
- idx = find_command(ca.cmdchar);
- }
- }
- }
-
- /* When getting a text character and the next character is a
- * multi-byte character, it could be a composing character.
- * However, don't wait for it to arrive. */
- while (enc_utf8 && lang && (c = vpeekc()) > 0
- && (c >= 0x100 || MB_BYTE2LEN(vpeekc()) > 1)) {
- c = plain_vgetc();
- if (!utf_iscomposing(c)) {
- vungetc(c); /* it wasn't, put it back */
- break;
- } else if (ca.ncharC1 == 0)
- ca.ncharC1 = c;
- else
- ca.ncharC2 = c;
- }
- }
- --no_mapping;
- --allow_keys;
- }
-
- /*
- * Flush the showcmd characters onto the screen so we can see them while
- * the command is being executed. Only do this when the shown command was
- * actually displayed, otherwise this will slow down a lot when executing
- * mappings.
- */
- if (need_flushbuf)
- out_flush();
- if (ca.cmdchar != K_IGNORE)</