9119 lines · 214.4 KB · C
RawDownload
/* vi:set ts=8 sts=4 sw=4: * * 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 "vim.h" #ifdef FEAT_VISUAL/* * 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_col;		/* nr of cols or end col */ static int	restart_VIsual_select = 0;#endif static int# ifdef __BORLANDC___RTLENTRYF# endif		nv_compare __ARGS((const void *s1, const void *s2));static int	find_command __ARGS((int cmdchar));static void	op_colon __ARGS((oparg_T *oap));static void	op_function __ARGS((oparg_T *oap));#if defined(FEAT_MOUSE) && defined(FEAT_VISUAL)static void	find_start_of_word __ARGS((pos_T *));static void	find_end_of_word __ARGS((pos_T *));static int	get_mouse_class __ARGS((char_u *p));#endifstatic void	prep_redo_cmd __ARGS((cmdarg_T *cap));static void	prep_redo __ARGS((int regname, long, int, int, int, int, int));static int	checkclearop __ARGS((oparg_T *oap));static int	checkclearopq __ARGS((oparg_T *oap));static void	clearop __ARGS((oparg_T *oap));static void	clearopbeep __ARGS((oparg_T *oap));#ifdef FEAT_VISUALstatic void	unshift_special __ARGS((cmdarg_T *cap));#endif#ifdef FEAT_CMDL_INFOstatic void	del_from_showcmd __ARGS((int));#endif /* * 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 __ARGS((cmdarg_T *cap));static void	nv_nop __ARGS((cmdarg_T *cap));static void	nv_error __ARGS((cmdarg_T *cap));static void	nv_help __ARGS((cmdarg_T *cap));static void	nv_addsub __ARGS((cmdarg_T *cap));static void	nv_page __ARGS((cmdarg_T *cap));static void	nv_gd __ARGS((oparg_T *oap, int nchar, int thisblock));static int	nv_screengo __ARGS((oparg_T *oap, int dir, long dist));#ifdef FEAT_MOUSEstatic void	nv_mousescroll __ARGS((cmdarg_T *cap));static void	nv_mouse __ARGS((cmdarg_T *cap));#endifstatic void	nv_scroll_line __ARGS((cmdarg_T *cap));static void	nv_zet __ARGS((cmdarg_T *cap));#ifdef FEAT_GUIstatic void	nv_ver_scrollbar __ARGS((cmdarg_T *cap));static void	nv_hor_scrollbar __ARGS((cmdarg_T *cap));#endif#ifdef FEAT_GUI_TABLINEstatic void	nv_tabline __ARGS((cmdarg_T *cap));static void	nv_tabmenu __ARGS((cmdarg_T *cap));#endifstatic void	nv_exmode __ARGS((cmdarg_T *cap));static void	nv_colon __ARGS((cmdarg_T *cap));static void	nv_ctrlg __ARGS((cmdarg_T *cap));static void	nv_ctrlh __ARGS((cmdarg_T *cap));static void	nv_clear __ARGS((cmdarg_T *cap));static void	nv_ctrlo __ARGS((cmdarg_T *cap));static void	nv_hat __ARGS((cmdarg_T *cap));static void	nv_Zet __ARGS((cmdarg_T *cap));static void	nv_ident __ARGS((cmdarg_T *cap));static void	nv_tagpop __ARGS((cmdarg_T *cap));static void	nv_scroll __ARGS((cmdarg_T *cap));static void	nv_right __ARGS((cmdarg_T *cap));static void	nv_left __ARGS((cmdarg_T *cap));static void	nv_up __ARGS((cmdarg_T *cap));static void	nv_down __ARGS((cmdarg_T *cap));#ifdef FEAT_SEARCHPATHstatic void	nv_gotofile __ARGS((cmdarg_T *cap));#endifstatic void	nv_end __ARGS((cmdarg_T *cap));static void	nv_dollar __ARGS((cmdarg_T *cap));static void	nv_search __ARGS((cmdarg_T *cap));static void	nv_next __ARGS((cmdarg_T *cap));static void	normal_search __ARGS((cmdarg_T *cap, int dir, char_u *pat, int opt));static void	nv_csearch __ARGS((cmdarg_T *cap));static void	nv_brackets __ARGS((cmdarg_T *cap));static void	nv_percent __ARGS((cmdarg_T *cap));static void	nv_brace __ARGS((cmdarg_T *cap));static void	nv_mark __ARGS((cmdarg_T *cap));static void	nv_findpar __ARGS((cmdarg_T *cap));static void	nv_undo __ARGS((cmdarg_T *cap));static void	nv_kundo __ARGS((cmdarg_T *cap));static void	nv_Replace __ARGS((cmdarg_T *cap));#ifdef FEAT_VREPLACEstatic void	nv_vreplace __ARGS((cmdarg_T *cap));#endif#ifdef FEAT_VISUALstatic void	v_swap_corners __ARGS((int cmdchar));#endifstatic void	nv_replace __ARGS((cmdarg_T *cap));static void	n_swapchar __ARGS((cmdarg_T *cap));static void	nv_cursormark __ARGS((cmdarg_T *cap, int flag, pos_T *pos));#ifdef FEAT_VISUALstatic void	v_visop __ARGS((cmdarg_T *cap));#endifstatic void	nv_subst __ARGS((cmdarg_T *cap));static void	nv_abbrev __ARGS((cmdarg_T *cap));static void	nv_optrans __ARGS((cmdarg_T *cap));static void	nv_gomark __ARGS((cmdarg_T *cap));static void	nv_pcmark __ARGS((cmdarg_T *cap));static void	nv_regname __ARGS((cmdarg_T *cap));#ifdef FEAT_VISUALstatic void	nv_visual __ARGS((cmdarg_T *cap));static void	n_start_visual_mode __ARGS((int c));#endifstatic void	nv_window __ARGS((cmdarg_T *cap));static void	nv_suspend __ARGS((cmdarg_T *cap));static void	nv_g_cmd __ARGS((cmdarg_T *cap));static void	n_opencmd __ARGS((cmdarg_T *cap));static void	nv_dot __ARGS((cmdarg_T *cap));static void	nv_redo __ARGS((cmdarg_T *cap));static void	nv_Undo __ARGS((cmdarg_T *cap));static void	nv_tilde __ARGS((cmdarg_T *cap));static void	nv_operator __ARGS((cmdarg_T *cap));static void	nv_lineop __ARGS((cmdarg_T *cap));static void	nv_home __ARGS((cmdarg_T *cap));static void	nv_pipe __ARGS((cmdarg_T *cap));static void	nv_bck_word __ARGS((cmdarg_T *cap));static void	nv_wordcmd __ARGS((cmdarg_T *cap));static void	nv_beginline __ARGS((cmdarg_T *cap));#ifdef FEAT_VISUALstatic void	adjust_for_sel __ARGS((cmdarg_T *cap));static int	unadjust_for_sel __ARGS((void));static void	nv_select __ARGS((cmdarg_T *cap));#endifstatic void	nv_goto __ARGS((cmdarg_T *cap));static void	nv_normal __ARGS((cmdarg_T *cap));static void	nv_esc __ARGS((cmdarg_T *oap));static void	nv_edit __ARGS((cmdarg_T *cap));static void	invoke_edit __ARGS((cmdarg_T *cap, int repl, int cmd, int startln));#ifdef FEAT_TEXTOBJstatic void	nv_object __ARGS((cmdarg_T *cap));#endifstatic void	nv_record __ARGS((cmdarg_T *cap));static void	nv_at __ARGS((cmdarg_T *cap));static void	nv_halfpage __ARGS((cmdarg_T *cap));static void	nv_join __ARGS((cmdarg_T *cap));static void	nv_put __ARGS((cmdarg_T *cap));static void	nv_open __ARGS((cmdarg_T *cap));#ifdef FEAT_SNIFFstatic void	nv_sniff __ARGS((cmdarg_T *cap));#endif#ifdef FEAT_NETBEANS_INTGstatic void	nv_nbcmd __ARGS((cmdarg_T *cap));#endif#ifdef FEAT_DNDstatic void	nv_drop __ARGS((cmdarg_T *cap));#endif#ifdef FEAT_AUTOCMDstatic void	nv_cursorhold __ARGS((cmdarg_T *cap));#endif /* * Function to be called for a Normal or Visual mode command. * The argument is a cmdarg_T. */typedef void (*nv_func_T) __ARGS((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 */    short_u	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},#ifdef FEAT_VISUAL    {Ctrl_Q,	nv_visual,	0,			FALSE},#else    {Ctrl_Q,	nv_ignore,	0,			0},#endif    {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},#ifdef FEAT_VISUAL    {Ctrl_V,	nv_visual,	0,			FALSE},    {'V',	nv_visual,	0,			FALSE},    {'v',	nv_visual,	0,			FALSE},#else    {Ctrl_V,	nv_error,	0,			0},    {'V',	nv_error,	0,			0},    {'v',	nv_error,	0,			0},#endif    {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},#ifdef FEAT_MOUSE    {K_MOUSEUP, nv_mousescroll,	0,			TRUE},    {K_MOUSEDOWN, nv_mousescroll, 0,			FALSE},    {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},#endif    {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},#ifdef FEAT_VISUAL    {K_SELECT,	nv_select,	0,			0},#endif#ifdef FEAT_GUI    {K_VER_SCROLLBAR, nv_ver_scrollbar, 0,		0},    {K_HOR_SCROLLBAR, nv_hor_scrollbar, 0,		0},#endif#ifdef FEAT_GUI_TABLINE    {K_TABLINE, nv_tabline,	0,			0},    {K_TABMENU, nv_tabmenu,	0,			0},#endif#ifdef FEAT_FKMAP    {K_F8,	farsi_fkey,	0,			0},    {K_F9,	farsi_fkey,	0,			0},#endif#ifdef FEAT_SNIFF    {K_SNIFF,	nv_sniff,	0,			0},#endif#ifdef FEAT_NETBEANS_INTG    {K_F21,	nv_nbcmd,	NV_NCH_ALW,		0},#endif#ifdef FEAT_DND    {K_DROP,	nv_drop,	NV_STS,			0},#endif#ifdef FEAT_AUTOCMD    {K_CURSORHOLD, nv_cursorhold, NV_KEEPREG,		0},#endif}; /* 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#ifdef __BORLANDC___RTLENTRYF#endifnv_compare(s1, s2)    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. */    voidinit_normal_cmds(){    int		i;     /* Fill the index table with a one to one relation. */    for (i = 0; i < 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 < NV_CMDS_SIZE; ++i)	if (i != nv_cmds[nv_cmd_idx[i]].cmd_char)	    break;    nv_max_linear = i - 1;

Lines 1–500 of 9119.