summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-09-06 15:54:00 +0200
committerBram Moolenaar <Bram@vim.org>2020-09-06 15:54:00 +0200
commit2f3cd2e4ec5617e3697ec4f4c6e1c9449061ad30 (patch)
tree4687b2544e21c5316d25e63107f17b7cdcfeea30
parent8a0dcf43305586853f452a77fa295b0c8d54b463 (diff)
downloadvim-git-2f3cd2e4ec5617e3697ec4f4c6e1c9449061ad30.tar.gz
patch 8.2.1622: loop to handle keys for the command line is too longv8.2.1622
Problem: Loop to handle keys for the command line is too long. Solution: Move code to functions. (Yegappan Lakshmanan, closes #6880)
-rw-r--r--src/ex_getln.c885
-rw-r--r--src/version.c2
2 files changed, 504 insertions, 383 deletions
diff --git a/src/ex_getln.c b/src/ex_getln.c
index eb922a1c4..ba10af3a4 100644
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -17,6 +17,11 @@
# define MAX(x,y) ((x) > (y) ? (x) : (y))
#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
// used by other functions. When invoking getcmdline() recursively it needs
// to be saved with save_cmdline() and restored with restore_cmdline().
@@ -763,6 +768,483 @@ cmdline_init(void)
}
/*
+ * 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.
*
* firstc == ':' get ":" command line.
@@ -1361,98 +1843,16 @@ getcmdline_int(
case K_DEL:
case K_KDEL:
case Ctrl_W:
- 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;
+ res = cmdline_erase_chars(c, indent
#ifdef FEAT_SEARCH_EXTRA
- if (ccline.cmdlen == 0)
- {
- 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
- 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
- )
- goto cmdline_not_changed;
-
- VIM_CLEAR(ccline.cmdbuff); // no commandline to return
- if (!cmd_silent)
- {
-#ifdef FEAT_RIGHTLEFT
- if (cmdmsg_rl)
- msg_col = Columns;
- else
+ , &is_state
#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 cmdline_changed;
+ );
+ if (res == CMDLINE_NOT_CHANGED)
+ goto cmdline_not_changed;
+ else if (res == GOTO_NORMAL_MODE)
+ goto returncmd; // back to cmd mode
+ goto cmdline_changed;
case K_INS:
case K_KINS:
@@ -1463,56 +1863,7 @@ getcmdline_int(
goto cmdline_not_changed;
case Ctrl_HAT:
- 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
+ cmdline_toggle_langmap(b_im_ptr);
goto cmdline_not_changed;
// case '@': only in very old vi
@@ -1557,66 +1908,11 @@ getcmdline_int(
goto returncmd; // back to cmd mode
case Ctrl_R: // insert register
-#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
- 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();
+ res = cmdline_insert_reg(&gotesc);
+ if (res == CMDLINE_NOT_CHANGED)
+ goto cmdline_not_changed;
+ else if (res == GOTO_NORMAL_MODE)
+ goto returncmd;
goto cmdline_changed;
case Ctrl_D:
@@ -1725,55 +2021,7 @@ getcmdline_int(
// FALLTHROUGH
case K_LEFTMOUSE:
case K_RIGHTMOUSE:
- 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))
- 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;
- }
+ cmdline_left_right_mouse(c, &ignore_drag_release);
goto cmdline_not_changed;
// Mouse scroll wheel: ignored here
@@ -1877,141 +2125,12 @@ getcmdline_int(
case K_KPAGEUP:
case K_PAGEDOWN:
case K_KPAGEDOWN:
- if (get_hislen() == 0 || firstc == NUL) // no history
- goto 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)
- 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();
+ res = cmdline_browse_history(c, firstc, &lookfor, histype,
+ &hiscnt, &xpc);
+ if (res == CMDLINE_CHANGED)
goto cmdline_changed;
- }
- beep_flush();
+ else if (res == GOTO_NORMAL_MODE)
+ goto returncmd;
goto cmdline_not_changed;
#ifdef FEAT_SEARCH_EXTRA
diff --git a/src/version.c b/src/version.c
index cf7de76a6..1180a6075 100644
--- a/src/version.c
+++ b/src/version.c
@@ -755,6 +755,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1622,
+/**/
1621,
/**/
1620,