6171 lines · 144.2 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. */ /* * ex_getln.c: Functions for entering and editing an Ex command line. */ #include "vim.h" /* * Variables shared between getcmdline(), redrawcmdline() and others. * These need to be saved when using CTRL-R |, that's why they are in a * structure. */struct cmdline_info{    char_u	*cmdbuff;	/* pointer to command line buffer */    int		cmdbufflen;	/* length of cmdbuff */    int		cmdlen;		/* number of chars in command line */    int		cmdpos;		/* current cursor position */    int		cmdspos;	/* cursor column on screen */    int		cmdfirstc;	/* ':', '/', '?', '=' or NUL */    int		cmdindent;	/* number of spaces before cmdline */    char_u	*cmdprompt;	/* message in front of cmdline */    int		cmdattr;	/* attributes for prompt */    int		overstrike;	/* Typing mode on the command line.  Shared by				   getcmdline() and put_on_cmdline(). */    int		xp_context;	/* type of expansion */# ifdef FEAT_EVAL    char_u	*xp_arg;	/* user-defined expansion arg */    int		input_fn;	/* when TRUE Invoked for input() function */# endif}; static struct cmdline_info ccline;	/* current cmdline_info */ static int	cmd_showtail;		/* Only show path tail in lists ? */ #ifdef FEAT_EVALstatic int	new_cmdpos;	/* position set by set_cmdline_pos() */#endif #ifdef FEAT_CMDHISTtypedef struct hist_entry{    int		hisnum;		/* identifying number */    char_u	*hisstr;	/* actual entry, separator char after the NUL */} histentry_T; static histentry_T *(history[HIST_COUNT]) = {NULL, NULL, NULL, NULL, NULL};static int	hisidx[HIST_COUNT] = {-1, -1, -1, -1, -1};  /* lastused entry */static int	hisnum[HIST_COUNT] = {0, 0, 0, 0, 0};		    /* identifying (unique) number of newest history entry */static int	hislen = 0;		/* actual length of history tables */ static int	hist_char2type __ARGS((int c)); static int	in_history __ARGS((int, char_u *, int));# ifdef FEAT_EVALstatic int	calc_hist_idx __ARGS((int histype, int num));# endif#endif #ifdef FEAT_RIGHTLEFTstatic int	cmd_hkmap = 0;	/* Hebrew mapping during command line */#endif #ifdef FEAT_FKMAPstatic int	cmd_fkmap = 0;	/* Farsi mapping during command line */#endif static int	cmdline_charsize __ARGS((int idx));static void	set_cmdspos __ARGS((void));static void	set_cmdspos_cursor __ARGS((void));#ifdef FEAT_MBYTEstatic void	correct_cmdspos __ARGS((int idx, int cells));#endifstatic void	alloc_cmdbuff __ARGS((int len));static int	realloc_cmdbuff __ARGS((int len));static void	draw_cmdline __ARGS((int start, int len));static void	save_cmdline __ARGS((struct cmdline_info *ccp));static void	restore_cmdline __ARGS((struct cmdline_info *ccp));static int	cmdline_paste __ARGS((int regname, int literally, int remcr));#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)static void	redrawcmd_preedit __ARGS((void));#endif#ifdef FEAT_WILDMENUstatic void	cmdline_del __ARGS((int from));#endifstatic void	redrawcmdprompt __ARGS((void));static void	cursorcmd __ARGS((void));static int	ccheck_abbr __ARGS((int));static int	nextwild __ARGS((expand_T *xp, int type, int options));static void	escape_fname __ARGS((char_u **pp));static int	showmatches __ARGS((expand_T *xp, int wildmenu));static void	set_expand_context __ARGS((expand_T *xp));static int	ExpandFromContext __ARGS((expand_T *xp, char_u *, int *, char_u ***, int));static int	expand_showtail __ARGS((expand_T *xp));#ifdef FEAT_CMDL_COMPLstatic int	expand_shellcmd __ARGS((char_u *filepat, int *num_file, char_u ***file, int flagsarg));static int	ExpandRTDir __ARGS((char_u *pat, int *num_file, char_u ***file, char *dirname));# if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL)static int	ExpandUserDefined __ARGS((expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file));static int	ExpandUserList __ARGS((expand_T *xp, int *num_file, char_u ***file));# endif#endif #ifdef FEAT_CMDWINstatic int	ex_window __ARGS((void));#endif /* * getcmdline() - accept a command line starting with firstc. * * firstc == ':'	    get ":" command line. * firstc == '/' or '?'	    get search pattern * firstc == '='	    get expression * firstc == '@'	    get text for input() function * firstc == '>'	    get text for debug mode * firstc == NUL	    get text for :insert command * firstc == -1		    like NUL, and break on CTRL-C * * The line is collected in ccline.cmdbuff, which is reallocated to fit the * command line. * * Careful: getcmdline() can be called recursively! * * Return pointer to allocated string if there is a commandline, NULL * otherwise. *//*ARGSUSED*/    char_u *getcmdline(firstc, count, indent)    int		firstc;    long	count;		/* only used for incremental search */    int		indent;		/* indent for inside conditionals */{    int		c;    int		i;    int		j;    int		gotesc = FALSE;		/* TRUE when <ESC> just typed */    int		do_abbr;		/* when TRUE check for abbr. */#ifdef FEAT_CMDHIST    char_u	*lookfor = NULL;	/* string to match */    int		hiscnt;			/* current history line in use */    int		histype;		/* history type to be used */#endif#ifdef FEAT_SEARCH_EXTRA    pos_T	old_cursor;    colnr_T	old_curswant;    colnr_T	old_leftcol;    linenr_T	old_topline;# ifdef FEAT_DIFF    int		old_topfill;# endif    linenr_T	old_botline;    int		did_incsearch = FALSE;    int		incsearch_postponed = FALSE;#endif    int		did_wild_list = FALSE;	/* did wild_list() recently */    int		wim_index = 0;		/* index in wim_flags[] */    int		res;    int		save_msg_scroll = msg_scroll;    int		save_State = State;	/* remember State when called */    int		some_key_typed = FALSE;	/* one of the keys was typed */#ifdef FEAT_MOUSE    /* mouse drag and release events are ignored, unless they are     * preceded with a mouse down event */    int		ignore_drag_release = TRUE;#endif#ifdef FEAT_EVAL    int		break_ctrl_c = FALSE;#endif    expand_T	xpc;    long	*b_im_ptr = NULL;#if defined(FEAT_WILDMENU) || defined(FEAT_EVAL) || defined(FEAT_SEARCH_EXTRA)    /* Everything that may work recursively should save and restore the     * current command line in save_ccline.  That includes update_screen(), a     * custom status line may invoke ":normal". */    struct cmdline_info save_ccline;#endif #ifdef FEAT_SNIFF    want_sniff_request = 0;#endif#ifdef FEAT_EVAL    if (firstc == -1)    {	firstc = NUL;	break_ctrl_c = TRUE;    }#endif#ifdef FEAT_RIGHTLEFT    /* start without Hebrew mapping for a command line */    if (firstc == ':' || firstc == '=' || firstc == '>')	cmd_hkmap = 0;#endif     ccline.overstrike = FALSE;		    /* always start in insert mode */#ifdef FEAT_SEARCH_EXTRA    old_cursor = curwin->w_cursor;	    /* needs to be restored later */    old_curswant = curwin->w_curswant;    old_leftcol = curwin->w_leftcol;    old_topline = curwin->w_topline;# ifdef FEAT_DIFF    old_topfill = curwin->w_topfill;# endif    old_botline = curwin->w_botline;#endif     /*     * set some variables for redrawcmd()     */    ccline.cmdfirstc = (firstc == '@' ? 0 : firstc);    ccline.cmdindent = (firstc > 0 ? indent : 0);     /* alloc initial ccline.cmdbuff */    alloc_cmdbuff(exmode_active ? 250 : indent + 1);    if (ccline.cmdbuff == NULL)	return NULL;			    /* out of memory */    ccline.cmdlen = ccline.cmdpos = 0;    ccline.cmdbuff[0] = NUL;     /* autoindent for :insert and :append */    if (firstc <= 0)    {	copy_spaces(ccline.cmdbuff, indent);	ccline.cmdbuff[indent] = NUL;	ccline.cmdpos = indent;	ccline.cmdspos = indent;	ccline.cmdlen = indent;    }     ExpandInit(&xpc); #ifdef FEAT_RIGHTLEFT    if (curwin->w_p_rl && *curwin->w_p_rlc == 's'					  && (firstc == '/' || firstc == '?'))	cmdmsg_rl = TRUE;    else	cmdmsg_rl = FALSE;#endif     redir_off = TRUE;		/* don't redirect the typed command */    if (!cmd_silent)    {	i = msg_scrolled;	msg_scrolled = 0;		/* avoid wait_return message */	gotocmdline(TRUE);	msg_scrolled += i;	redrawcmdprompt();		/* draw prompt or indent */	set_cmdspos();    }    xpc.xp_context = EXPAND_NOTHING;    xpc.xp_backslash = XP_BS_NONE;#ifndef BACKSLASH_IN_FILENAME    xpc.xp_shell = FALSE;#endif #if defined(FEAT_EVAL)    if (ccline.input_fn)    {	xpc.xp_context = ccline.xp_context;	xpc.xp_pattern = ccline.cmdbuff;	xpc.xp_arg = ccline.xp_arg;    }#endif     /*     * Avoid scrolling when called by a recursive do_cmdline(), e.g. when     * doing ":@0" when register 0 doesn't contain a CR.     */    msg_scroll = FALSE;     State = CMDLINE;     if (firstc == '/' || firstc == '?' || firstc == '@')    {	/* Use ":lmap" mappings for search pattern and input(). */	if (curbuf->b_p_imsearch == B_IMODE_USE_INSERT)	    b_im_ptr = &curbuf->b_p_iminsert;	else	    b_im_ptr = &curbuf->b_p_imsearch;	if (*b_im_ptr == B_IMODE_LMAP)	    State |= LANGMAP;#ifdef USE_IM_CONTROL	im_set_active(*b_im_ptr == B_IMODE_IM);#endif    }#ifdef USE_IM_CONTROL    else if (p_imcmdline)	im_set_active(TRUE);#endif #ifdef FEAT_MOUSE    setmouse();#endif#ifdef CURSOR_SHAPE    ui_cursor_shape();		/* may show different cursor shape */#endif     /* When inside an autocommand for writing "exiting" may be set and     * terminal mode set to cooked.  Need to set raw mode here then. */    settmode(TMODE_RAW); #ifdef FEAT_CMDHIST    init_history();    hiscnt = hislen;		/* set hiscnt to impossible history value */    histype = hist_char2type(firstc);#endif #ifdef FEAT_DIGRAPHS    do_digraph(-1);		/* init digraph typahead */#endif     /*     * Collect the command string, handling editing keys.     */    for (;;)    {	redir_off = TRUE;	/* Don't redirect the typed command.				   Repeated, because a ":redir" inside				   completion may switch it on. */#ifdef USE_ON_FLY_SCROLL	dont_scroll = FALSE;	/* allow scrolling here */#endif	quit_more = FALSE;	/* reset after CTRL-D which had a more-prompt */ 	cursorcmd();		/* set the cursor on the right spot */	c = safe_vgetc();	if (KeyTyped)	{	    some_key_typed = TRUE;#ifdef FEAT_RIGHTLEFT	    if (cmd_hkmap)		c = hkmap(c);# ifdef FEAT_FKMAP	    if (cmd_fkmap)		c = cmdl_fkmap(c);# endif	    if (cmdmsg_rl && !KeyStuffed)	    {		/* Invert horizontal movements and operations.  Only when		 * typed by the user directly, not when the result of a		 * mapping. */		switch (c)		{		    case K_RIGHT:   c = K_LEFT; break;		    case K_S_RIGHT: c = K_S_LEFT; break;		    case K_C_RIGHT: c = K_C_LEFT; break;		    case K_LEFT:    c = K_RIGHT; break;		    case K_S_LEFT:  c = K_S_RIGHT; break;		    case K_C_LEFT:  c = K_C_RIGHT; break;		}	    }#endif	} 	/*	 * Ignore got_int when CTRL-C was typed here.	 * Don't ignore it in :global, we really need to break then, e.g., for	 * ":g/pat/normal /pat" (without the <CR>).	 * Don't ignore it for the input() function.	 */	if ((c == Ctrl_C#ifdef UNIX		|| c == intr_char#endif				)#if defined(FEAT_EVAL) || defined(FEAT_CRYPT)		&& firstc != '@'#endif#ifdef FEAT_EVAL		&& !break_ctrl_c#endif		&& !global_busy)	    got_int = FALSE; #ifdef FEAT_CMDHIST	/* free old command line when finished moving around in the history	 * list */	if (lookfor != NULL		&& c != K_S_DOWN && c != K_S_UP		&& c != K_DOWN && c != K_UP		&& c != K_PAGEDOWN && c != K_PAGEUP		&& c != K_KPAGEDOWN && c != K_KPAGEUP		&& c != K_LEFT && c != K_RIGHT		&& (xpc.xp_numfiles > 0 || (c != Ctrl_P && c != Ctrl_N)))	{	    vim_free(lookfor);	    lookfor = NULL;	}#endif 	/*	 * <S-Tab> works like CTRL-P (unless 'wc' is <S-Tab>).	 */	if (c != p_wc && c == K_S_TAB && xpc.xp_numfiles != -1)	    c = Ctrl_P; #ifdef FEAT_WILDMENU	/* Special translations for 'wildmenu' */	if (did_wild_list && p_wmnu)	{	    if (c == K_LEFT)		c = Ctrl_P;	    else if (c == K_RIGHT)		c = Ctrl_N;	}	/* Hitting CR after "emenu Name.": complete submenu */	if (xpc.xp_context == EXPAND_MENUNAMES && p_wmnu		&& ccline.cmdpos > 1		&& ccline.cmdbuff[ccline.cmdpos - 1] == '.'		&& ccline.cmdbuff[ccline.cmdpos - 2] != '\\'		&& (c == '\n' || c == '\r' || c == K_KENTER))	    c = K_DOWN;#endif 	/* free expanded names when finished walking through matches */	if (xpc.xp_numfiles != -1		&& !(c == p_wc && KeyTyped) && c != p_wcm		&& c != Ctrl_N && c != Ctrl_P && c != Ctrl_A		&& c != Ctrl_L)	{	    (void)ExpandOne(&xpc, NULL, NULL, 0, WILD_FREE);	    did_wild_list = FALSE;#ifdef FEAT_WILDMENU	    if (!p_wmnu || (c != K_UP && c != K_DOWN))#endif		xpc.xp_context = EXPAND_NOTHING;	    wim_index = 0;#ifdef FEAT_WILDMENU	    if (p_wmnu && wild_menu_showing != 0)	    {		int skt = KeyTyped;		int old_RedrawingDisabled = RedrawingDisabled; 		if (ccline.input_fn)		    RedrawingDisabled = 0; 		if (wild_menu_showing == WM_SCROLLED)		{		    /* Entered command line, move it up */		    cmdline_row--;		    redrawcmd();		}		else if (save_p_ls != -1)		{		    /* restore 'laststatus' and 'winminheight' */		    p_ls = save_p_ls;		    p_wmh = save_p_wmh;		    last_status(FALSE);		    save_cmdline(&save_ccline);		    update_screen(VALID);	/* redraw the screen NOW */		    restore_cmdline(&save_ccline);		    redrawcmd();		    save_p_ls = -1;		}		else		{# ifdef FEAT_VERTSPLIT		    win_redraw_last_status(topframe);# else		    lastwin->w_redr_status = TRUE;# endif		    redraw_statuslines();		}		KeyTyped = skt;		wild_menu_showing = 0;		if (ccline.input_fn)		    RedrawingDisabled = old_RedrawingDisabled;	    }#endif	} #ifdef FEAT_WILDMENU	/* Special translations for 'wildmenu' */	if (xpc.xp_context == EXPAND_MENUNAMES && p_wmnu)	{	    /* Hitting <Down> after "emenu Name.": complete submenu */	    if (ccline.cmdbuff[ccline.cmdpos - 1] == '.' && c == K_DOWN)		c = p_wc;	    else if (c == K_UP)	    {		/* Hitting <Up>: Remove one submenu name in front of the		 * cursor */		int found = FALSE; 		j = (int)(xpc.xp_pattern - ccline.cmdbuff);		i = 0;		while (--j > 0)		{		    /* check for start of menu name */		    if (ccline.cmdbuff[j] == ' '

Lines 1–500 of 6171.