mirror of
https://github.com/vim/vim.git
synced 2025-09-28 04:24:06 -04:00
patch 8.2.1622: loop to handle keys for the command line is too long
Problem: Loop to handle keys for the command line is too long. Solution: Move code to functions. (Yegappan Lakshmanan, closes #6880)
This commit is contained in:
879
src/ex_getln.c
879
src/ex_getln.c
@@ -17,6 +17,11 @@
|
|||||||
# define MAX(x,y) ((x) > (y) ? (x) : (y))
|
# define MAX(x,y) ((x) > (y) ? (x) : (y))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Return value when handling keys in command-line mode.
|
||||||
|
#define CMDLINE_NOT_CHANGED 1
|
||||||
|
#define CMDLINE_CHANGED 2
|
||||||
|
#define GOTO_NORMAL_MODE 3
|
||||||
|
|
||||||
// The current cmdline_info. It is initialized in getcmdline() and after that
|
// The current cmdline_info. It is initialized in getcmdline() and after that
|
||||||
// used by other functions. When invoking getcmdline() recursively it needs
|
// used by other functions. When invoking getcmdline() recursively it needs
|
||||||
// to be saved with save_cmdline() and restored with restore_cmdline().
|
// to be saved with save_cmdline() and restored with restore_cmdline().
|
||||||
@@ -762,6 +767,483 @@ cmdline_init(void)
|
|||||||
CLEAR_FIELD(ccline);
|
CLEAR_FIELD(ccline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle backspace, delete and CTRL-W keys in the command-line mode.
|
||||||
|
* Returns:
|
||||||
|
* CMDLINE_NOT_CHANGED - if the command line is not changed
|
||||||
|
* CMDLINE_CHANGED - if the command line is changed
|
||||||
|
* GOTO_NORMAL_MODE - go back to normal mode
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
cmdline_erase_chars(
|
||||||
|
int c,
|
||||||
|
int indent
|
||||||
|
#ifdef FEAT_SEARCH_EXTRA
|
||||||
|
, incsearch_state_T *isp
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
if (c == K_KDEL)
|
||||||
|
c = K_DEL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delete current character is the same as backspace on next
|
||||||
|
* character, except at end of line.
|
||||||
|
*/
|
||||||
|
if (c == K_DEL && ccline.cmdpos != ccline.cmdlen)
|
||||||
|
++ccline.cmdpos;
|
||||||
|
if (has_mbyte && c == K_DEL)
|
||||||
|
ccline.cmdpos += mb_off_next(ccline.cmdbuff,
|
||||||
|
ccline.cmdbuff + ccline.cmdpos);
|
||||||
|
if (ccline.cmdpos > 0)
|
||||||
|
{
|
||||||
|
char_u *p;
|
||||||
|
|
||||||
|
j = ccline.cmdpos;
|
||||||
|
p = ccline.cmdbuff + j;
|
||||||
|
if (has_mbyte)
|
||||||
|
{
|
||||||
|
p = mb_prevptr(ccline.cmdbuff, p);
|
||||||
|
if (c == Ctrl_W)
|
||||||
|
{
|
||||||
|
while (p > ccline.cmdbuff && vim_isspace(*p))
|
||||||
|
p = mb_prevptr(ccline.cmdbuff, p);
|
||||||
|
i = mb_get_class(p);
|
||||||
|
while (p > ccline.cmdbuff && mb_get_class(p) == i)
|
||||||
|
p = mb_prevptr(ccline.cmdbuff, p);
|
||||||
|
if (mb_get_class(p) != i)
|
||||||
|
p += (*mb_ptr2len)(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c == Ctrl_W)
|
||||||
|
{
|
||||||
|
while (p > ccline.cmdbuff && vim_isspace(p[-1]))
|
||||||
|
--p;
|
||||||
|
i = vim_iswordc(p[-1]);
|
||||||
|
while (p > ccline.cmdbuff && !vim_isspace(p[-1])
|
||||||
|
&& vim_iswordc(p[-1]) == i)
|
||||||
|
--p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
--p;
|
||||||
|
ccline.cmdpos = (int)(p - ccline.cmdbuff);
|
||||||
|
ccline.cmdlen -= j - ccline.cmdpos;
|
||||||
|
i = ccline.cmdpos;
|
||||||
|
while (i < ccline.cmdlen)
|
||||||
|
ccline.cmdbuff[i++] = ccline.cmdbuff[j++];
|
||||||
|
|
||||||
|
// Truncate at the end, required for multi-byte chars.
|
||||||
|
ccline.cmdbuff[ccline.cmdlen] = NUL;
|
||||||
|
#ifdef FEAT_SEARCH_EXTRA
|
||||||
|
if (ccline.cmdlen == 0)
|
||||||
|
{
|
||||||
|
isp->search_start = isp->save_cursor;
|
||||||
|
// save view settings, so that the screen
|
||||||
|
// won't be restored at the wrong position
|
||||||
|
isp->old_viewstate = isp->init_viewstate;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
redrawcmd();
|
||||||
|
}
|
||||||
|
else if (ccline.cmdlen == 0 && c != Ctrl_W
|
||||||
|
&& ccline.cmdprompt == NULL && indent == 0)
|
||||||
|
{
|
||||||
|
// In ex and debug mode it doesn't make sense to return.
|
||||||
|
if (exmode_active
|
||||||
|
#ifdef FEAT_EVAL
|
||||||
|
|| ccline.cmdfirstc == '>'
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
return CMDLINE_NOT_CHANGED;
|
||||||
|
|
||||||
|
VIM_CLEAR(ccline.cmdbuff); // no commandline to return
|
||||||
|
if (!cmd_silent)
|
||||||
|
{
|
||||||
|
#ifdef FEAT_RIGHTLEFT
|
||||||
|
if (cmdmsg_rl)
|
||||||
|
msg_col = Columns;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
msg_col = 0;
|
||||||
|
msg_putchar(' '); // delete ':'
|
||||||
|
}
|
||||||
|
#ifdef FEAT_SEARCH_EXTRA
|
||||||
|
if (ccline.cmdlen == 0)
|
||||||
|
isp->search_start = isp->save_cursor;
|
||||||
|
#endif
|
||||||
|
redraw_cmdline = TRUE;
|
||||||
|
return GOTO_NORMAL_MODE;
|
||||||
|
}
|
||||||
|
return CMDLINE_CHANGED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle the CTRL-^ key in the command-line mode and toggle the use of the
|
||||||
|
* language :lmap mappings and/or Input Method.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
cmdline_toggle_langmap(long *b_im_ptr)
|
||||||
|
{
|
||||||
|
if (map_to_exists_mode((char_u *)"", LANGMAP, FALSE))
|
||||||
|
{
|
||||||
|
// ":lmap" mappings exists, toggle use of mappings.
|
||||||
|
State ^= LANGMAP;
|
||||||
|
#ifdef HAVE_INPUT_METHOD
|
||||||
|
im_set_active(FALSE); // Disable input method
|
||||||
|
#endif
|
||||||
|
if (b_im_ptr != NULL)
|
||||||
|
{
|
||||||
|
if (State & LANGMAP)
|
||||||
|
*b_im_ptr = B_IMODE_LMAP;
|
||||||
|
else
|
||||||
|
*b_im_ptr = B_IMODE_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef HAVE_INPUT_METHOD
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// There are no ":lmap" mappings, toggle IM. When
|
||||||
|
// 'imdisable' is set don't try getting the status, it's
|
||||||
|
// always off.
|
||||||
|
if ((p_imdisable && b_im_ptr != NULL)
|
||||||
|
? *b_im_ptr == B_IMODE_IM : im_get_status())
|
||||||
|
{
|
||||||
|
im_set_active(FALSE); // Disable input method
|
||||||
|
if (b_im_ptr != NULL)
|
||||||
|
*b_im_ptr = B_IMODE_NONE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
im_set_active(TRUE); // Enable input method
|
||||||
|
if (b_im_ptr != NULL)
|
||||||
|
*b_im_ptr = B_IMODE_IM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (b_im_ptr != NULL)
|
||||||
|
{
|
||||||
|
if (b_im_ptr == &curbuf->b_p_iminsert)
|
||||||
|
set_iminsert_global();
|
||||||
|
else
|
||||||
|
set_imsearch_global();
|
||||||
|
}
|
||||||
|
#ifdef CURSOR_SHAPE
|
||||||
|
ui_cursor_shape(); // may show different cursor shape
|
||||||
|
#endif
|
||||||
|
#if defined(FEAT_KEYMAP)
|
||||||
|
// Show/unshow value of 'keymap' in status lines later.
|
||||||
|
status_redraw_curbuf();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle the CTRL-R key in the command-line mode and insert the contents of a
|
||||||
|
* numbered or named register.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
cmdline_insert_reg(int *gotesc UNUSED)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
#ifdef USE_ON_FLY_SCROLL
|
||||||
|
dont_scroll = TRUE; // disallow scrolling here
|
||||||
|
#endif
|
||||||
|
putcmdline('"', TRUE);
|
||||||
|
++no_mapping;
|
||||||
|
++allow_keys;
|
||||||
|
i = c = plain_vgetc(); // CTRL-R <char>
|
||||||
|
if (i == Ctrl_O)
|
||||||
|
i = Ctrl_R; // CTRL-R CTRL-O == CTRL-R CTRL-R
|
||||||
|
if (i == Ctrl_R)
|
||||||
|
c = plain_vgetc(); // CTRL-R CTRL-R <char>
|
||||||
|
extra_char = NUL;
|
||||||
|
--no_mapping;
|
||||||
|
--allow_keys;
|
||||||
|
#ifdef FEAT_EVAL
|
||||||
|
/*
|
||||||
|
* Insert the result of an expression.
|
||||||
|
* Need to save the current command line, to be able to enter
|
||||||
|
* a new one...
|
||||||
|
*/
|
||||||
|
new_cmdpos = -1;
|
||||||
|
if (c == '=')
|
||||||
|
{
|
||||||
|
if (ccline.cmdfirstc == '=' // can't do this recursively
|
||||||
|
|| cmdline_star > 0) // or when typing a password
|
||||||
|
{
|
||||||
|
beep_flush();
|
||||||
|
c = ESC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
c = get_expr_register();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (c != ESC) // use ESC to cancel inserting register
|
||||||
|
{
|
||||||
|
cmdline_paste(c, i == Ctrl_R, FALSE);
|
||||||
|
|
||||||
|
#ifdef FEAT_EVAL
|
||||||
|
// When there was a serious error abort getting the
|
||||||
|
// command line.
|
||||||
|
if (aborting())
|
||||||
|
{
|
||||||
|
*gotesc = TRUE; // will free ccline.cmdbuff after
|
||||||
|
// putting it in history
|
||||||
|
return GOTO_NORMAL_MODE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
KeyTyped = FALSE; // Don't do p_wc completion.
|
||||||
|
#ifdef FEAT_EVAL
|
||||||
|
if (new_cmdpos >= 0)
|
||||||
|
{
|
||||||
|
// set_cmdline_pos() was used
|
||||||
|
if (new_cmdpos > ccline.cmdlen)
|
||||||
|
ccline.cmdpos = ccline.cmdlen;
|
||||||
|
else
|
||||||
|
ccline.cmdpos = new_cmdpos;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
redrawcmd();
|
||||||
|
return CMDLINE_CHANGED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle the Left and Right mouse clicks in the command-line mode.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
cmdline_left_right_mouse(int c, int *ignore_drag_release)
|
||||||
|
{
|
||||||
|
if (c == K_LEFTRELEASE || c == K_RIGHTRELEASE)
|
||||||
|
*ignore_drag_release = TRUE;
|
||||||
|
else
|
||||||
|
*ignore_drag_release = FALSE;
|
||||||
|
# ifdef FEAT_GUI
|
||||||
|
// When GUI is active, also move when 'mouse' is empty
|
||||||
|
if (!gui.in_use)
|
||||||
|
# endif
|
||||||
|
if (!mouse_has(MOUSE_COMMAND))
|
||||||
|
return;
|
||||||
|
# ifdef FEAT_CLIPBOARD
|
||||||
|
if (mouse_row < cmdline_row && clip_star.available)
|
||||||
|
{
|
||||||
|
int button, is_click, is_drag;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle modeless selection.
|
||||||
|
*/
|
||||||
|
button = get_mouse_button(KEY2TERMCAP1(c),
|
||||||
|
&is_click, &is_drag);
|
||||||
|
if (mouse_model_popup() && button == MOUSE_LEFT
|
||||||
|
&& (mod_mask & MOD_MASK_SHIFT))
|
||||||
|
{
|
||||||
|
// Translate shift-left to right button.
|
||||||
|
button = MOUSE_RIGHT;
|
||||||
|
mod_mask &= ~MOD_MASK_SHIFT;
|
||||||
|
}
|
||||||
|
clip_modeless(button, is_click, is_drag);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
set_cmdspos();
|
||||||
|
for (ccline.cmdpos = 0; ccline.cmdpos < ccline.cmdlen;
|
||||||
|
++ccline.cmdpos)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = cmdline_charsize(ccline.cmdpos);
|
||||||
|
if (mouse_row <= cmdline_row + ccline.cmdspos / Columns
|
||||||
|
&& mouse_col < ccline.cmdspos % Columns + i)
|
||||||
|
break;
|
||||||
|
if (has_mbyte)
|
||||||
|
{
|
||||||
|
// Count ">" for double-wide char that doesn't fit.
|
||||||
|
correct_cmdspos(ccline.cmdpos, i);
|
||||||
|
ccline.cmdpos += (*mb_ptr2len)(ccline.cmdbuff
|
||||||
|
+ ccline.cmdpos) - 1;
|
||||||
|
}
|
||||||
|
ccline.cmdspos += i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle the Up, Down, Page Up, Page down, CTRL-N and CTRL-P key in the
|
||||||
|
* command-line mode. The pressed key is in 'c'.
|
||||||
|
* Returns:
|
||||||
|
* CMDLINE_NOT_CHANGED - if the command line is not changed
|
||||||
|
* CMDLINE_CHANGED - if the command line is changed
|
||||||
|
* GOTO_NORMAL_MODE - go back to normal mode
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
cmdline_browse_history(
|
||||||
|
int c,
|
||||||
|
int firstc,
|
||||||
|
char_u **curcmdstr,
|
||||||
|
int histype,
|
||||||
|
int *hiscnt_p,
|
||||||
|
expand_T *xp)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
char_u *lookfor = *curcmdstr;
|
||||||
|
int hiscnt = *hiscnt_p;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (get_hislen() == 0 || firstc == NUL) // no history
|
||||||
|
return CMDLINE_NOT_CHANGED;
|
||||||
|
|
||||||
|
i = hiscnt;
|
||||||
|
|
||||||
|
// save current command string so it can be restored later
|
||||||
|
if (lookfor == NULL)
|
||||||
|
{
|
||||||
|
if ((lookfor = vim_strsave(ccline.cmdbuff)) == NULL)
|
||||||
|
return CMDLINE_NOT_CHANGED;
|
||||||
|
lookfor[ccline.cmdpos] = NUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
j = (int)STRLEN(lookfor);
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
// one step backwards
|
||||||
|
if (c == K_UP|| c == K_S_UP || c == Ctrl_P
|
||||||
|
|| c == K_PAGEUP || c == K_KPAGEUP)
|
||||||
|
{
|
||||||
|
if (hiscnt == get_hislen()) // first time
|
||||||
|
hiscnt = *get_hisidx(histype);
|
||||||
|
else if (hiscnt == 0 && *get_hisidx(histype)
|
||||||
|
!= get_hislen() - 1)
|
||||||
|
hiscnt = get_hislen() - 1;
|
||||||
|
else if (hiscnt != *get_hisidx(histype) + 1)
|
||||||
|
--hiscnt;
|
||||||
|
else // at top of list
|
||||||
|
{
|
||||||
|
hiscnt = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // one step forwards
|
||||||
|
{
|
||||||
|
// on last entry, clear the line
|
||||||
|
if (hiscnt == *get_hisidx(histype))
|
||||||
|
{
|
||||||
|
hiscnt = get_hislen();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not on a history line, nothing to do
|
||||||
|
if (hiscnt == get_hislen())
|
||||||
|
break;
|
||||||
|
if (hiscnt == get_hislen() - 1) // wrap around
|
||||||
|
hiscnt = 0;
|
||||||
|
else
|
||||||
|
++hiscnt;
|
||||||
|
}
|
||||||
|
if (hiscnt < 0 || get_histentry(histype)[hiscnt].hisstr
|
||||||
|
== NULL)
|
||||||
|
{
|
||||||
|
hiscnt = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((c != K_UP && c != K_DOWN)
|
||||||
|
|| hiscnt == i
|
||||||
|
|| STRNCMP(get_histentry(histype)[hiscnt].hisstr,
|
||||||
|
lookfor, (size_t)j) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hiscnt != i) // jumped to other entry
|
||||||
|
{
|
||||||
|
char_u *p;
|
||||||
|
int len;
|
||||||
|
int old_firstc;
|
||||||
|
|
||||||
|
VIM_CLEAR(ccline.cmdbuff);
|
||||||
|
xp->xp_context = EXPAND_NOTHING;
|
||||||
|
if (hiscnt == get_hislen())
|
||||||
|
p = lookfor; // back to the old one
|
||||||
|
else
|
||||||
|
p = get_histentry(histype)[hiscnt].hisstr;
|
||||||
|
|
||||||
|
if (histype == HIST_SEARCH
|
||||||
|
&& p != lookfor
|
||||||
|
&& (old_firstc = p[STRLEN(p) + 1]) != firstc)
|
||||||
|
{
|
||||||
|
// Correct for the separator character used when
|
||||||
|
// adding the history entry vs the one used now.
|
||||||
|
// First loop: count length.
|
||||||
|
// Second loop: copy the characters.
|
||||||
|
for (i = 0; i <= 1; ++i)
|
||||||
|
{
|
||||||
|
len = 0;
|
||||||
|
for (j = 0; p[j] != NUL; ++j)
|
||||||
|
{
|
||||||
|
// Replace old sep with new sep, unless it is
|
||||||
|
// escaped.
|
||||||
|
if (p[j] == old_firstc
|
||||||
|
&& (j == 0 || p[j - 1] != '\\'))
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
ccline.cmdbuff[len] = firstc;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Escape new sep, unless it is already
|
||||||
|
// escaped.
|
||||||
|
if (p[j] == firstc
|
||||||
|
&& (j == 0 || p[j - 1] != '\\'))
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
ccline.cmdbuff[len] = '\\';
|
||||||
|
++len;
|
||||||
|
}
|
||||||
|
if (i > 0)
|
||||||
|
ccline.cmdbuff[len] = p[j];
|
||||||
|
}
|
||||||
|
++len;
|
||||||
|
}
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
alloc_cmdbuff(len);
|
||||||
|
if (ccline.cmdbuff == NULL)
|
||||||
|
{
|
||||||
|
res = GOTO_NORMAL_MODE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ccline.cmdbuff[len] = NUL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alloc_cmdbuff((int)STRLEN(p));
|
||||||
|
if (ccline.cmdbuff == NULL)
|
||||||
|
{
|
||||||
|
res = GOTO_NORMAL_MODE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
STRCPY(ccline.cmdbuff, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
ccline.cmdpos = ccline.cmdlen = (int)STRLEN(ccline.cmdbuff);
|
||||||
|
redrawcmd();
|
||||||
|
res = CMDLINE_CHANGED;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
beep_flush();
|
||||||
|
res = CMDLINE_NOT_CHANGED;
|
||||||
|
|
||||||
|
done:
|
||||||
|
*curcmdstr = lookfor;
|
||||||
|
*hiscnt_p = hiscnt;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* getcmdline() - accept a command line starting with firstc.
|
* getcmdline() - accept a command line starting with firstc.
|
||||||
*
|
*
|
||||||
@@ -1361,97 +1843,15 @@ getcmdline_int(
|
|||||||
case K_DEL:
|
case K_DEL:
|
||||||
case K_KDEL:
|
case K_KDEL:
|
||||||
case Ctrl_W:
|
case Ctrl_W:
|
||||||
if (c == K_KDEL)
|
res = cmdline_erase_chars(c, indent
|
||||||
c = K_DEL;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* delete current character is the same as backspace on next
|
|
||||||
* character, except at end of line
|
|
||||||
*/
|
|
||||||
if (c == K_DEL && ccline.cmdpos != ccline.cmdlen)
|
|
||||||
++ccline.cmdpos;
|
|
||||||
if (has_mbyte && c == K_DEL)
|
|
||||||
ccline.cmdpos += mb_off_next(ccline.cmdbuff,
|
|
||||||
ccline.cmdbuff + ccline.cmdpos);
|
|
||||||
if (ccline.cmdpos > 0)
|
|
||||||
{
|
|
||||||
char_u *p;
|
|
||||||
|
|
||||||
j = ccline.cmdpos;
|
|
||||||
p = ccline.cmdbuff + j;
|
|
||||||
if (has_mbyte)
|
|
||||||
{
|
|
||||||
p = mb_prevptr(ccline.cmdbuff, p);
|
|
||||||
if (c == Ctrl_W)
|
|
||||||
{
|
|
||||||
while (p > ccline.cmdbuff && vim_isspace(*p))
|
|
||||||
p = mb_prevptr(ccline.cmdbuff, p);
|
|
||||||
i = mb_get_class(p);
|
|
||||||
while (p > ccline.cmdbuff && mb_get_class(p) == i)
|
|
||||||
p = mb_prevptr(ccline.cmdbuff, p);
|
|
||||||
if (mb_get_class(p) != i)
|
|
||||||
p += (*mb_ptr2len)(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (c == Ctrl_W)
|
|
||||||
{
|
|
||||||
while (p > ccline.cmdbuff && vim_isspace(p[-1]))
|
|
||||||
--p;
|
|
||||||
i = vim_iswordc(p[-1]);
|
|
||||||
while (p > ccline.cmdbuff && !vim_isspace(p[-1])
|
|
||||||
&& vim_iswordc(p[-1]) == i)
|
|
||||||
--p;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
--p;
|
|
||||||
ccline.cmdpos = (int)(p - ccline.cmdbuff);
|
|
||||||
ccline.cmdlen -= j - ccline.cmdpos;
|
|
||||||
i = ccline.cmdpos;
|
|
||||||
while (i < ccline.cmdlen)
|
|
||||||
ccline.cmdbuff[i++] = ccline.cmdbuff[j++];
|
|
||||||
|
|
||||||
// Truncate at the end, required for multi-byte chars.
|
|
||||||
ccline.cmdbuff[ccline.cmdlen] = NUL;
|
|
||||||
#ifdef FEAT_SEARCH_EXTRA
|
#ifdef FEAT_SEARCH_EXTRA
|
||||||
if (ccline.cmdlen == 0)
|
, &is_state
|
||||||
{
|
|
||||||
is_state.search_start = is_state.save_cursor;
|
|
||||||
// save view settings, so that the screen
|
|
||||||
// won't be restored at the wrong position
|
|
||||||
is_state.old_viewstate = is_state.init_viewstate;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
redrawcmd();
|
);
|
||||||
}
|
if (res == CMDLINE_NOT_CHANGED)
|
||||||
else if (ccline.cmdlen == 0 && c != Ctrl_W
|
|
||||||
&& ccline.cmdprompt == NULL && indent == 0)
|
|
||||||
{
|
|
||||||
// In ex and debug mode it doesn't make sense to return.
|
|
||||||
if (exmode_active
|
|
||||||
#ifdef FEAT_EVAL
|
|
||||||
|| ccline.cmdfirstc == '>'
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
goto cmdline_not_changed;
|
goto cmdline_not_changed;
|
||||||
|
else if (res == GOTO_NORMAL_MODE)
|
||||||
VIM_CLEAR(ccline.cmdbuff); // no commandline to return
|
|
||||||
if (!cmd_silent)
|
|
||||||
{
|
|
||||||
#ifdef FEAT_RIGHTLEFT
|
|
||||||
if (cmdmsg_rl)
|
|
||||||
msg_col = Columns;
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
msg_col = 0;
|
|
||||||
msg_putchar(' '); // delete ':'
|
|
||||||
}
|
|
||||||
#ifdef FEAT_SEARCH_EXTRA
|
|
||||||
if (ccline.cmdlen == 0)
|
|
||||||
is_state.search_start = is_state.save_cursor;
|
|
||||||
#endif
|
|
||||||
redraw_cmdline = TRUE;
|
|
||||||
goto returncmd; // back to cmd mode
|
goto returncmd; // back to cmd mode
|
||||||
}
|
|
||||||
goto cmdline_changed;
|
goto cmdline_changed;
|
||||||
|
|
||||||
case K_INS:
|
case K_INS:
|
||||||
@@ -1463,56 +1863,7 @@ getcmdline_int(
|
|||||||
goto cmdline_not_changed;
|
goto cmdline_not_changed;
|
||||||
|
|
||||||
case Ctrl_HAT:
|
case Ctrl_HAT:
|
||||||
if (map_to_exists_mode((char_u *)"", LANGMAP, FALSE))
|
cmdline_toggle_langmap(b_im_ptr);
|
||||||
{
|
|
||||||
// ":lmap" mappings exists, toggle use of mappings.
|
|
||||||
State ^= LANGMAP;
|
|
||||||
#ifdef HAVE_INPUT_METHOD
|
|
||||||
im_set_active(FALSE); // Disable input method
|
|
||||||
#endif
|
|
||||||
if (b_im_ptr != NULL)
|
|
||||||
{
|
|
||||||
if (State & LANGMAP)
|
|
||||||
*b_im_ptr = B_IMODE_LMAP;
|
|
||||||
else
|
|
||||||
*b_im_ptr = B_IMODE_NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef HAVE_INPUT_METHOD
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// There are no ":lmap" mappings, toggle IM. When
|
|
||||||
// 'imdisable' is set don't try getting the status, it's
|
|
||||||
// always off.
|
|
||||||
if ((p_imdisable && b_im_ptr != NULL)
|
|
||||||
? *b_im_ptr == B_IMODE_IM : im_get_status())
|
|
||||||
{
|
|
||||||
im_set_active(FALSE); // Disable input method
|
|
||||||
if (b_im_ptr != NULL)
|
|
||||||
*b_im_ptr = B_IMODE_NONE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
im_set_active(TRUE); // Enable input method
|
|
||||||
if (b_im_ptr != NULL)
|
|
||||||
*b_im_ptr = B_IMODE_IM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (b_im_ptr != NULL)
|
|
||||||
{
|
|
||||||
if (b_im_ptr == &curbuf->b_p_iminsert)
|
|
||||||
set_iminsert_global();
|
|
||||||
else
|
|
||||||
set_imsearch_global();
|
|
||||||
}
|
|
||||||
#ifdef CURSOR_SHAPE
|
|
||||||
ui_cursor_shape(); // may show different cursor shape
|
|
||||||
#endif
|
|
||||||
#if defined(FEAT_KEYMAP)
|
|
||||||
// Show/unshow value of 'keymap' in status lines later.
|
|
||||||
status_redraw_curbuf();
|
|
||||||
#endif
|
|
||||||
goto cmdline_not_changed;
|
goto cmdline_not_changed;
|
||||||
|
|
||||||
// case '@': only in very old vi
|
// case '@': only in very old vi
|
||||||
@@ -1557,66 +1908,11 @@ getcmdline_int(
|
|||||||
goto returncmd; // back to cmd mode
|
goto returncmd; // back to cmd mode
|
||||||
|
|
||||||
case Ctrl_R: // insert register
|
case Ctrl_R: // insert register
|
||||||
#ifdef USE_ON_FLY_SCROLL
|
res = cmdline_insert_reg(&gotesc);
|
||||||
dont_scroll = TRUE; // disallow scrolling here
|
if (res == CMDLINE_NOT_CHANGED)
|
||||||
#endif
|
goto cmdline_not_changed;
|
||||||
putcmdline('"', TRUE);
|
else if (res == GOTO_NORMAL_MODE)
|
||||||
++no_mapping;
|
goto returncmd;
|
||||||
++allow_keys;
|
|
||||||
i = c = plain_vgetc(); // CTRL-R <char>
|
|
||||||
if (i == Ctrl_O)
|
|
||||||
i = Ctrl_R; // CTRL-R CTRL-O == CTRL-R CTRL-R
|
|
||||||
if (i == Ctrl_R)
|
|
||||||
c = plain_vgetc(); // CTRL-R CTRL-R <char>
|
|
||||||
extra_char = NUL;
|
|
||||||
--no_mapping;
|
|
||||||
--allow_keys;
|
|
||||||
#ifdef FEAT_EVAL
|
|
||||||
/*
|
|
||||||
* Insert the result of an expression.
|
|
||||||
* Need to save the current command line, to be able to enter
|
|
||||||
* a new one...
|
|
||||||
*/
|
|
||||||
new_cmdpos = -1;
|
|
||||||
if (c == '=')
|
|
||||||
{
|
|
||||||
if (ccline.cmdfirstc == '=' // can't do this recursively
|
|
||||||
|| cmdline_star > 0) // or when typing a password
|
|
||||||
{
|
|
||||||
beep_flush();
|
|
||||||
c = ESC;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
c = get_expr_register();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (c != ESC) // use ESC to cancel inserting register
|
|
||||||
{
|
|
||||||
cmdline_paste(c, i == Ctrl_R, FALSE);
|
|
||||||
|
|
||||||
#ifdef FEAT_EVAL
|
|
||||||
// When there was a serious error abort getting the
|
|
||||||
// command line.
|
|
||||||
if (aborting())
|
|
||||||
{
|
|
||||||
gotesc = TRUE; // will free ccline.cmdbuff after
|
|
||||||
// putting it in history
|
|
||||||
goto returncmd; // back to cmd mode
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
KeyTyped = FALSE; // Don't do p_wc completion.
|
|
||||||
#ifdef FEAT_EVAL
|
|
||||||
if (new_cmdpos >= 0)
|
|
||||||
{
|
|
||||||
// set_cmdline_pos() was used
|
|
||||||
if (new_cmdpos > ccline.cmdlen)
|
|
||||||
ccline.cmdpos = ccline.cmdlen;
|
|
||||||
else
|
|
||||||
ccline.cmdpos = new_cmdpos;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
redrawcmd();
|
|
||||||
goto cmdline_changed;
|
goto cmdline_changed;
|
||||||
|
|
||||||
case Ctrl_D:
|
case Ctrl_D:
|
||||||
@@ -1725,55 +2021,7 @@ getcmdline_int(
|
|||||||
// FALLTHROUGH
|
// FALLTHROUGH
|
||||||
case K_LEFTMOUSE:
|
case K_LEFTMOUSE:
|
||||||
case K_RIGHTMOUSE:
|
case K_RIGHTMOUSE:
|
||||||
if (c == K_LEFTRELEASE || c == K_RIGHTRELEASE)
|
cmdline_left_right_mouse(c, &ignore_drag_release);
|
||||||
ignore_drag_release = TRUE;
|
|
||||||
else
|
|
||||||
ignore_drag_release = FALSE;
|
|
||||||
# ifdef FEAT_GUI
|
|
||||||
// When GUI is active, also move when 'mouse' is empty
|
|
||||||
if (!gui.in_use)
|
|
||||||
# endif
|
|
||||||
if (!mouse_has(MOUSE_COMMAND))
|
|
||||||
goto cmdline_not_changed; // Ignore mouse
|
|
||||||
# ifdef FEAT_CLIPBOARD
|
|
||||||
if (mouse_row < cmdline_row && clip_star.available)
|
|
||||||
{
|
|
||||||
int button, is_click, is_drag;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Handle modeless selection.
|
|
||||||
*/
|
|
||||||
button = get_mouse_button(KEY2TERMCAP1(c),
|
|
||||||
&is_click, &is_drag);
|
|
||||||
if (mouse_model_popup() && button == MOUSE_LEFT
|
|
||||||
&& (mod_mask & MOD_MASK_SHIFT))
|
|
||||||
{
|
|
||||||
// Translate shift-left to right button.
|
|
||||||
button = MOUSE_RIGHT;
|
|
||||||
mod_mask &= ~MOD_MASK_SHIFT;
|
|
||||||
}
|
|
||||||
clip_modeless(button, is_click, is_drag);
|
|
||||||
goto cmdline_not_changed;
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
set_cmdspos();
|
|
||||||
for (ccline.cmdpos = 0; ccline.cmdpos < ccline.cmdlen;
|
|
||||||
++ccline.cmdpos)
|
|
||||||
{
|
|
||||||
i = cmdline_charsize(ccline.cmdpos);
|
|
||||||
if (mouse_row <= cmdline_row + ccline.cmdspos / Columns
|
|
||||||
&& mouse_col < ccline.cmdspos % Columns + i)
|
|
||||||
break;
|
|
||||||
if (has_mbyte)
|
|
||||||
{
|
|
||||||
// Count ">" for double-wide char that doesn't fit.
|
|
||||||
correct_cmdspos(ccline.cmdpos, i);
|
|
||||||
ccline.cmdpos += (*mb_ptr2len)(ccline.cmdbuff
|
|
||||||
+ ccline.cmdpos) - 1;
|
|
||||||
}
|
|
||||||
ccline.cmdspos += i;
|
|
||||||
}
|
|
||||||
goto cmdline_not_changed;
|
goto cmdline_not_changed;
|
||||||
|
|
||||||
// Mouse scroll wheel: ignored here
|
// Mouse scroll wheel: ignored here
|
||||||
@@ -1877,141 +2125,12 @@ getcmdline_int(
|
|||||||
case K_KPAGEUP:
|
case K_KPAGEUP:
|
||||||
case K_PAGEDOWN:
|
case K_PAGEDOWN:
|
||||||
case K_KPAGEDOWN:
|
case K_KPAGEDOWN:
|
||||||
if (get_hislen() == 0 || firstc == NUL) // no history
|
res = cmdline_browse_history(c, firstc, &lookfor, histype,
|
||||||
goto cmdline_not_changed;
|
&hiscnt, &xpc);
|
||||||
|
if (res == CMDLINE_CHANGED)
|
||||||
i = hiscnt;
|
|
||||||
|
|
||||||
// save current command string so it can be restored later
|
|
||||||
if (lookfor == NULL)
|
|
||||||
{
|
|
||||||
if ((lookfor = vim_strsave(ccline.cmdbuff)) == NULL)
|
|
||||||
goto cmdline_not_changed;
|
|
||||||
lookfor[ccline.cmdpos] = NUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
j = (int)STRLEN(lookfor);
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
// one step backwards
|
|
||||||
if (c == K_UP|| c == K_S_UP || c == Ctrl_P
|
|
||||||
|| c == K_PAGEUP || c == K_KPAGEUP)
|
|
||||||
{
|
|
||||||
if (hiscnt == get_hislen()) // first time
|
|
||||||
hiscnt = *get_hisidx(histype);
|
|
||||||
else if (hiscnt == 0 && *get_hisidx(histype)
|
|
||||||
!= get_hislen() - 1)
|
|
||||||
hiscnt = get_hislen() - 1;
|
|
||||||
else if (hiscnt != *get_hisidx(histype) + 1)
|
|
||||||
--hiscnt;
|
|
||||||
else // at top of list
|
|
||||||
{
|
|
||||||
hiscnt = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // one step forwards
|
|
||||||
{
|
|
||||||
// on last entry, clear the line
|
|
||||||
if (hiscnt == *get_hisidx(histype))
|
|
||||||
{
|
|
||||||
hiscnt = get_hislen();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// not on a history line, nothing to do
|
|
||||||
if (hiscnt == get_hislen())
|
|
||||||
break;
|
|
||||||
if (hiscnt == get_hislen() - 1) // wrap around
|
|
||||||
hiscnt = 0;
|
|
||||||
else
|
|
||||||
++hiscnt;
|
|
||||||
}
|
|
||||||
if (hiscnt < 0 || get_histentry(histype)[hiscnt].hisstr
|
|
||||||
== NULL)
|
|
||||||
{
|
|
||||||
hiscnt = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((c != K_UP && c != K_DOWN)
|
|
||||||
|| hiscnt == i
|
|
||||||
|| STRNCMP(get_histentry(histype)[hiscnt].hisstr,
|
|
||||||
lookfor, (size_t)j) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hiscnt != i) // jumped to other entry
|
|
||||||
{
|
|
||||||
char_u *p;
|
|
||||||
int len;
|
|
||||||
int old_firstc;
|
|
||||||
|
|
||||||
VIM_CLEAR(ccline.cmdbuff);
|
|
||||||
xpc.xp_context = EXPAND_NOTHING;
|
|
||||||
if (hiscnt == get_hislen())
|
|
||||||
p = lookfor; // back to the old one
|
|
||||||
else
|
|
||||||
p = get_histentry(histype)[hiscnt].hisstr;
|
|
||||||
|
|
||||||
if (histype == HIST_SEARCH
|
|
||||||
&& p != lookfor
|
|
||||||
&& (old_firstc = p[STRLEN(p) + 1]) != firstc)
|
|
||||||
{
|
|
||||||
// Correct for the separator character used when
|
|
||||||
// adding the history entry vs the one used now.
|
|
||||||
// First loop: count length.
|
|
||||||
// Second loop: copy the characters.
|
|
||||||
for (i = 0; i <= 1; ++i)
|
|
||||||
{
|
|
||||||
len = 0;
|
|
||||||
for (j = 0; p[j] != NUL; ++j)
|
|
||||||
{
|
|
||||||
// Replace old sep with new sep, unless it is
|
|
||||||
// escaped.
|
|
||||||
if (p[j] == old_firstc
|
|
||||||
&& (j == 0 || p[j - 1] != '\\'))
|
|
||||||
{
|
|
||||||
if (i > 0)
|
|
||||||
ccline.cmdbuff[len] = firstc;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Escape new sep, unless it is already
|
|
||||||
// escaped.
|
|
||||||
if (p[j] == firstc
|
|
||||||
&& (j == 0 || p[j - 1] != '\\'))
|
|
||||||
{
|
|
||||||
if (i > 0)
|
|
||||||
ccline.cmdbuff[len] = '\\';
|
|
||||||
++len;
|
|
||||||
}
|
|
||||||
if (i > 0)
|
|
||||||
ccline.cmdbuff[len] = p[j];
|
|
||||||
}
|
|
||||||
++len;
|
|
||||||
}
|
|
||||||
if (i == 0)
|
|
||||||
{
|
|
||||||
alloc_cmdbuff(len);
|
|
||||||
if (ccline.cmdbuff == NULL)
|
|
||||||
goto returncmd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ccline.cmdbuff[len] = NUL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
alloc_cmdbuff((int)STRLEN(p));
|
|
||||||
if (ccline.cmdbuff == NULL)
|
|
||||||
goto returncmd;
|
|
||||||
STRCPY(ccline.cmdbuff, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
ccline.cmdpos = ccline.cmdlen = (int)STRLEN(ccline.cmdbuff);
|
|
||||||
redrawcmd();
|
|
||||||
goto cmdline_changed;
|
goto cmdline_changed;
|
||||||
}
|
else if (res == GOTO_NORMAL_MODE)
|
||||||
beep_flush();
|
goto returncmd;
|
||||||
goto cmdline_not_changed;
|
goto cmdline_not_changed;
|
||||||
|
|
||||||
#ifdef FEAT_SEARCH_EXTRA
|
#ifdef FEAT_SEARCH_EXTRA
|
||||||
|
@@ -754,6 +754,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1622,
|
||||||
/**/
|
/**/
|
||||||
1621,
|
1621,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user