From da51dc9cf202772f60bd2da975dbef257bd9237c Mon Sep 17 00:00:00 2001 From: Eliseo Martínez Date: Mon, 12 May 2014 02:25:17 +0200 Subject: Introduce nvim namespace: Move files. Move files from src/ to src/nvim/. - src/nvim/ becomes the new root dir for nvim executable sources. - src/libnvim/ is planned to become root dir of the neovim library. --- src/normal.c | 7474 ---------------------------------------------------------- 1 file changed, 7474 deletions(-) delete mode 100644 src/normal.c (limited to 'src/normal.c') 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 -#include - -#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" 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) - did_cursorhold = FALSE; - - State = NORMAL; - - if (ca.nchar == ESC) { - clearop(oap); - if (restart_edit == 0 && goto_im()) - restart_edit = 'a'; - goto normal_end; - } - - if (ca.cmdchar != K_IGNORE) { - msg_didout = FALSE; /* don't scroll screen up for normal command */ - msg_col = 0; - } - - old_pos = curwin->w_cursor; /* remember where cursor was */ - - /* When 'keymodel' contains "startsel" some keys start Select/Visual - * mode. */ - if (!VIsual_active && km_startsel) { - if (nv_cmds[idx].cmd_flags & NV_SS) { - start_selection(); - unshift_special(&ca); - idx = find_command(ca.cmdchar); - } else if ((nv_cmds[idx].cmd_flags & NV_SSS) - && (mod_mask & MOD_MASK_SHIFT)) { - start_selection(); - mod_mask &= ~MOD_MASK_SHIFT; - } - } - - /* - * Execute the command! - * Call the command function found in the commands table. - */ - ca.arg = nv_cmds[idx].cmd_arg; - (nv_cmds[idx].cmd_func)(&ca); - - /* - * If we didn't start or finish an operator, reset oap->regname, unless we - * need it later. - */ - if (!finish_op - && !oap->op_type - && (idx < 0 || !(nv_cmds[idx].cmd_flags & NV_KEEPREG))) { - clearop(oap); - { - int regname = 0; - - /* Adjust the register according to 'clipboard', so that when - * "unnamed" is present it becomes '*' or '+' instead of '"'. */ - set_reg_var(regname); - } - } - - /* Get the length of mapped chars again after typing a count, second - * character or "z333". */ - if (old_mapped_len > 0) - old_mapped_len = typebuf_maplen(); - - /* - * If an operation is pending, handle it... - */ - do_pending_operator(&ca, old_col, FALSE); - - /* - * Wait for a moment 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. - * Don't wait when emsg_silent is non-zero. - * 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 - && msg_silent == 0 - && (restart_edit != 0 - || (VIsual_active - && old_pos.lnum == curwin->w_cursor.lnum - && old_pos.col == curwin->w_cursor.col) - ) - && (clear_cmdline - || redraw_cmdline) - && (msg_didout || (msg_didany && msg_scroll)) - && !msg_nowait - && KeyTyped) - || (restart_edit != 0 - && !VIsual_active - && (msg_scroll - || emsg_on_display))) - && oap->regname == 0 - && !(ca.retval & CA_COMMAND_BUSY) - && stuff_empty() - && typebuf_typed() - && emsg_silent == 0 - && !did_wait_return - && oap->op_type == OP_NOP) { - int save_State = State; - - /* Draw the cursor with the right shape here */ - if (restart_edit != 0) - State = INSERT; - - /* 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; - - kmsg = keep_msg; - keep_msg = NULL; - /* showmode() will clear keep_msg, but we want to use it anyway */ - update_screen(0); - /* now reset it, otherwise it's put in the history again */ - keep_msg = kmsg; - msg_attr(kmsg, keep_msg_attr); - free(kmsg); - } - 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 */ - State = save_State; - - 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 */ - c = finish_op; - finish_op = FALSE; - /* Redraw the cursor with another shape, if we were in Operator-pending - * mode or did a replace command. */ - if (c || ca.cmdchar == 'r') { - ui_cursor_shape(); /* may show different cursor shape */ - } - - if (oap->op_type == OP_NOP && oap->regname == 0 - && ca.cmdchar != K_CURSORHOLD - ) - clear_showcmd(); - - checkpcmark(); /* check if we moved since setting pcmark */ - free(ca.searchbuf); - - if (has_mbyte) - mb_adjust_cursor(); - - if (curwin->w_p_scb && toplevel) { - validate_cursor(); /* may need to update w_leftcol */ - do_check_scrollbind(TRUE); - } - - if (curwin->w_p_crb && toplevel) { - validate_cursor(); /* may need to update w_leftcol */ - do_check_cursorbind(); - } - - /* - * 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 ( oap->op_type == OP_NOP - && ((restart_edit != 0 && !VIsual_active && old_mapped_len == 0) - || restart_VIsual_select == 1) - && !(ca.retval & CA_COMMAND_BUSY) - && stuff_empty() - && oap->regname == 0) { - if (restart_VIsual_select == 1) { - VIsual_select = TRUE; - showmode(); - restart_VIsual_select = 0; - } - if (restart_edit != 0 - && !VIsual_active && old_mapped_len == 0 - ) - (void)edit(restart_edit, FALSE, 1L); - } - - if (restart_VIsual_select == 2) - restart_VIsual_select = 1; - - /* Save count before an operator for next time. */ - opcount = ca.opcount; -} - -/* - * Set v:count and v:count1 according to "cap". - * Set v:prevcount only when "set_prevcount" is TRUE. - */ -static void set_vcount_ca(cmdarg_T *cap, int *set_prevcount) -{ - long count = cap->count0; - - /* multiply with cap->opcount the same way as above */ - if (cap->opcount != 0) - count = cap->opcount * (count == 0 ? 1 : count); - set_vcount(count, count == 0 ? 1 : count, *set_prevcount); - *set_prevcount = FALSE; /* only set v:prevcount once */ -} - -/* - * Handle an operator after visual mode or when the movement is finished - */ -void do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank) -{ - oparg_T *oap = cap->oap; - pos_T old_cursor; - int empty_region_error; - int restart_edit_save; - - /* 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_vcol; /* number of cols or end column */ - static long redo_VIsual_count; /* count for Visual operator */ - int include_line_break = FALSE; - - old_cursor = curwin->w_cursor; - - /* - * If an operation is pending, handle it... - */ - if ((finish_op - || VIsual_active - ) && oap->op_type != OP_NOP) { - oap->is_VIsual = VIsual_active; - if (oap->motion_force == 'V') - oap->motion_type = MLINE; - else if (oap->motion_force == 'v') { - /* If the motion was linewise, "inclusive" will not have been set. - * Use "exclusive" to be consistent. Makes "dvj" work nice. */ - if (oap->motion_type == MLINE) - oap->inclusive = FALSE; - /* If the motion already was characterwise, toggle "inclusive" */ - else if (oap->motion_type == MCHAR) - oap->inclusive = !oap->inclusive; - oap->motion_type = MCHAR; - } else if (oap->motion_force == Ctrl_V) { - /* Change line- or characterwise motion into Visual block mode. */ - VIsual_active = TRUE; - VIsual = oap->start; - VIsual_mode = Ctrl_V; - VIsual_select = FALSE; - VIsual_reselect = FALSE; - } - - /* Only redo yank when 'y' flag is in 'cpoptions'. */ - /* Never redo "zf" (define fold). */ - if ((vim_strchr(p_cpo, CPO_YANK) != NULL || oap->op_type != OP_YANK) - && ((!VIsual_active || oap->motion_force) - /* Also redo Operator-pending Visual mode mappings */ - || (VIsual_active && cap->cmdchar == ':' - && oap->op_type != OP_COLON)) - && cap->cmdchar != 'D' - && oap->op_type != OP_FOLD - && oap->op_type != OP_FOLDOPEN - && oap->op_type != OP_FOLDOPENREC - && oap->op_type != OP_FOLDCLOSE - && oap->op_type != OP_FOLDCLOSEREC - && oap->op_type != OP_FOLDDEL - && oap->op_type != OP_FOLDDELREC - ) { - prep_redo(oap->regname, cap->count0, - get_op_char(oap->op_type), get_extra_op_char(oap->op_type), - oap->motion_force, 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) - AppendToRedobuffLit(cap->searchbuf, -1); - AppendToRedobuff(NL_STR); - } else if (cap->cmdchar == ':') { - /* do_cmdline() has stored the first typed line in - * "repeat_cmdline". When several lines are typed repeating - * won't be possible. */ - if (repeat_cmdline == NULL) - ResetRedobuff(); - else { - AppendToRedobuffLit(repeat_cmdline, -1); - AppendToRedobuff(NL_STR); - free(repeat_cmdline); - repeat_cmdline = NULL; - } - } - } - - if (redo_VIsual_busy) { - /* Redo of an operation on a Visual area. Use the same size from - * redo_VIsual_line_count and redo_VIsual_vcol. */ - 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 (redo_VIsual_vcol == MAXCOL || VIsual_mode == 'v') { - if (VIsual_mode == 'v') { - if (redo_VIsual_line_count <= 1) { - validate_virtcol(); - curwin->w_curswant = - curwin->w_virtcol + redo_VIsual_vcol - 1; - } else - curwin->w_curswant = redo_VIsual_vcol; - } else { - curwin->w_curswant = MAXCOL; - } - coladvance(curwin->w_curswant); - } - cap->count0 = redo_VIsual_count; - if (redo_VIsual_count != 0) - cap->count1 = redo_VIsual_count; - else - cap->count1 = 1; - } else if (VIsual_active) { - if (!gui_yank) { - /* Save the current VIsual area for '< and '> marks, and "gv" */ - curbuf->b_visual.vi_start = VIsual; - curbuf->b_visual.vi_end = curwin->w_cursor; - curbuf->b_visual.vi_mode = VIsual_mode; - if (VIsual_mode_orig != NUL) { - curbuf->b_visual.vi_mode = VIsual_mode_orig; - VIsual_mode_orig = NUL; - } - curbuf->b_visual.vi_curswant = curwin->w_curswant; - curbuf->b_visual_mode_eval = VIsual_mode; - } - - /* 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 = - (colnr_T)STRLEN(ml_get(curwin->w_cursor.lnum)); - } else { - curwin->w_cursor.col = 0; - VIsual.col = (colnr_T)STRLEN(ml_get(VIsual.lnum)); - } - VIsual_mode = 'v'; - } - /* If 'selection' is "exclusive", backup one character for - * charwise selections. */ - else if (VIsual_mode == 'v') { - include_line_break = - unadjust_for_sel(); - } - - 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)) { - /* Include folded lines completely. */ - if (!VIsual_active) { - if (hasFolding(oap->start.lnum, &oap->start.lnum, NULL)) - oap->start.col = 0; - if (hasFolding(curwin->w_cursor.lnum, NULL, - &curwin->w_cursor.lnum)) - curwin->w_cursor.col = (colnr_T)STRLEN(ml_get_curline()); - } - oap->end = curwin->w_cursor; - curwin->w_cursor = oap->start; - - /* w_virtcol may have been updated; if the cursor goes back to its - * previous position w_virtcol becomes invalid and isn't updated - * automatically. */ - curwin->w_valid &= ~VALID_VIRTCOL; - } else { - /* Include folded lines completely. */ - if (!VIsual_active && oap->motion_type == MLINE) { - if (hasFolding(curwin->w_cursor.lnum, &curwin->w_cursor.lnum, - NULL)) - curwin->w_cursor.col = 0; - if (hasFolding(oap->start.lnum, NULL, &oap->start.lnum)) - oap->start.col = (colnr_T)STRLEN(ml_get(oap->start.lnum)); - } - oap->end = oap->start; - oap->start = curwin->w_cursor; - } - - oap->line_count = oap->end.lnum - oap->start.lnum + 1; - - /* Set "virtual_op" before resetting VIsual_active. */ - virtual_op = virtual_active(); - - if (VIsual_active || redo_VIsual_busy) { - if (VIsual_mode == Ctrl_V) { /* block mode */ - colnr_T start, end; - - oap->block_mode = TRUE; - - getvvcol(curwin, &(oap->start), - &oap->start_vcol, NULL, &oap->end_vcol); - if (!redo_VIsual_busy) { - getvvcol(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 - && 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) { - getvvcol(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_vcol - 1; - /* - * Correct oap->end.col and oap->start.col to be the - * upper-left and lower-right corner of the block area. - * - * (Actually, this does convert column positions into character - * positions) - */ - 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_vcol = MAXCOL; - else { - if (VIsual_mode != Ctrl_V) - getvvcol(curwin, &(oap->end), - NULL, NULL, &oap->end_vcol); - if (VIsual_mode == Ctrl_V || oap->line_count <= 1) { - if (VIsual_mode != Ctrl_V) - getvvcol(curwin, &(oap->start), - &oap->start_vcol, NULL, NULL); - resel_VIsual_vcol = oap->end_vcol - oap->start_vcol + 1; - } else - resel_VIsual_vcol = oap->end_vcol; - } - 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 - && oap->op_type != OP_FOLD - && oap->op_type != OP_FOLDOPEN - && oap->op_type != OP_FOLDOPENREC - && oap->op_type != OP_FOLDCLOSE - && oap->op_type != OP_FOLDCLOSEREC - && oap->op_type != OP_FOLDDEL - && oap->op_type != OP_FOLDDELREC - && oap->motion_force == NUL - ) { - /* Prepare for redoing. Only use the nchar field for "r", - * otherwise it might be the second char of the operator. */ - if (cap->cmdchar == 'g' && (cap->nchar == 'n' - || cap->nchar == 'N')) - prep_redo(oap->regname, cap->count0, - get_op_char(oap->op_type), get_extra_op_char(oap->op_type), - oap->motion_force, cap->cmdchar, cap->nchar); - else if (cap->cmdchar != ':') - prep_redo(oap->regname, 0L, NUL, 'v', - get_op_char(oap->op_type), - get_extra_op_char(oap->op_type), - oap->op_type == OP_REPLACE - ? cap->nchar : NUL); - if (!redo_VIsual_busy) { - redo_VIsual_mode = resel_VIsual_mode; - redo_VIsual_vcol = resel_VIsual_vcol; - 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. - */ - if (oap->motion_force == NUL || oap->motion_type == MLINE) - 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 - && (include_line_break || !virtual_op) - ) { - oap->inclusive = FALSE; - /* Try to include the newline, unless it's an operator - * that works on lines only. */ - if (*p_sel != 'o' && !op_on_lines(oap->op_type)) { - if (oap->end.lnum < curbuf->b_ml.ml_line_count) { - ++oap->end.lnum; - oap->end.col = 0; - oap->end.coladd = 0; - ++oap->line_count; - } else { - /* Cannot move below the last line, make the op - * inclusive to tell the operation to include the - * line break. */ - oap->inclusive = TRUE; - } - } - } - } - - 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; - setmouse(); - mouse_dragging = 0; - if (mode_displayed) - clear_cmdline = TRUE; /* unshow visual mode later */ - else - clear_showcmd(); - if ((oap->op_type == OP_YANK - || oap->op_type == OP_COLON - || oap->op_type == OP_FUNCTION - || oap->op_type == OP_FILTER) - && oap->motion_force == NUL) - redraw_curbuf_later(INVERTED); - } - } - - /* Include the trailing byte of a multi-byte char. */ - if (has_mbyte && oap->inclusive) { - int l; - - l = (*mb_ptr2len)(ml_get_pos(&oap->end)); - if (l > 1) - oap->end.col += l - 1; - } - 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_pos(&oap->end) == NUL)) - && equalpos(oap->start, oap->end) - && !(virtual_op && oap->start.coladd != oap->end.coladd) - ); - /* - * For delete, change and yank, it's an error to operate on an - * empty region, when 'E' included 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, when - * 'modifiable is off or creating a fold. */ - if (oap->is_VIsual && (oap->empty || !curbuf->b_p_ma - || oap->op_type == OP_FOLD - )) - redraw_curbuf_later(INVERTED); - - /* - * 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 - && !(cap->retval & CA_NO_ADJ_OP_END) - && oap->end.col == 0 - && (!oap->is_VIsual || *p_sel == 'o') - && !oap->block_mode - && 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 = (colnr_T)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); - auto_format(FALSE, TRUE); - break; - - case OP_JOIN_NS: - case OP_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 { - (void)do_join(oap->line_count, oap->op_type == OP_JOIN, TRUE, TRUE); - auto_format(FALSE, TRUE); - } - break; - - case OP_DELETE: - VIsual_reselect = FALSE; /* don't reselect now */ - if (empty_region_error) { - vim_beep(); - CancelRedo(); - } else { - (void)op_delete(oap); - if (oap->motion_type == MLINE && has_format_option(FO_AUTO)) - u_save_cursor(); /* cursor line wasn't saved yet */ - auto_format(FALSE, TRUE); - } - break; - - case OP_YANK: - if (empty_region_error) { - if (!gui_yank) { - vim_beep(); - CancelRedo(); - } - } else - (void)op_yank(oap, FALSE, !gui_yank); - check_cursor_col(); - break; - - case OP_CHANGE: - VIsual_reselect = FALSE; /* don't reselect now */ - if (empty_region_error) { - vim_beep(); - CancelRedo(); - } else { - /* This is a new edit command, not a restart. Need to - * remember it to make 'insertmode' work with mappings for - * Visual mode. But do this only once and not when typed and - * 'insertmode' isn't set. */ - if (p_im || !KeyTyped) - restart_edit_save = restart_edit; - else - restart_edit_save = 0; - restart_edit = 0; - /* Reset finish_op now, don't want it set inside edit(). */ - finish_op = FALSE; - if (op_change(oap)) /* will call edit() */ - cap->retval |= CA_COMMAND_BUSY; - if (restart_edit == 0) - restart_edit = restart_edit_save; - } - 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 'equalprg' is empty, do the indenting internally. - */ - if (oap->op_type == OP_INDENT && *get_equalprg() == NUL) { - if (curbuf->b_p_lisp) { - op_reindent(oap, get_lisp_indent); - break; - } - op_reindent(oap, - *curbuf->b_p_inde != NUL ? get_expr_indent : - get_c_indent); - break; - } - - op_colon(oap); - break; - - case OP_TILDE: - case OP_UPPER: - case OP_LOWER: - case OP_ROT13: - if (empty_region_error) { - vim_beep(); - CancelRedo(); - } else - op_tilde(oap); - check_cursor_col(); - break; - - case OP_FORMAT: - if (*curbuf->b_p_fex != NUL) - op_formatexpr(oap); /* use expression */ - else if (*p_fp != NUL) - op_colon(oap); /* use external command */ - else - op_format(oap, FALSE); /* use internal function */ - break; - - case OP_FORMAT2: - op_format(oap, TRUE); /* use internal function */ - break; - - case OP_FUNCTION: - op_function(oap); /* call 'operatorfunc' */ - break; - - case OP_INSERT: - case OP_APPEND: - VIsual_reselect = FALSE; /* don't reselect now */ - if (empty_region_error) { - vim_beep(); - CancelRedo(); - } else { - /* This is a new edit command, not a restart. Need to - * remember it to make 'insertmode' work with mappings for - * Visual mode. But do this only once. */ - restart_edit_save = restart_edit; - restart_edit = 0; - - op_insert(oap, cap->count1); - - /* TODO: when inserting in several lines, should format all - * the lines. */ - auto_format(FALSE, TRUE); - - if (restart_edit == 0) - restart_edit = restart_edit_save; - } - break; - - case OP_REPLACE: - VIsual_reselect = FALSE; /* don't reselect now */ - if (empty_region_error) { - vim_beep(); - CancelRedo(); - } else - op_replace(oap, cap->nchar); - break; - - case OP_FOLD