mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 03:18:16 +00:00
vim-patch:8.2.1622: loop to handle keys for the command line is too long (#21307)
Problem: Loop to handle keys for the command line is too long.
Solution: Move code to functions. (Yegappan Lakshmanan, closes vim/vim#6880)
2f3cd2e4ec
Use the command line state as only argument instead.
This commit is contained in:
@@ -1410,6 +1410,198 @@ static int may_do_command_line_next_incsearch(int firstc, long count, incsearch_
|
|||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handle backspace, delete and CTRL-W keys in the command-line mode.
|
||||||
|
static int command_line_erase_chars(CommandLineState *s)
|
||||||
|
{
|
||||||
|
if (s->c == K_KDEL) {
|
||||||
|
s->c = K_DEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete current character is the same as backspace on next
|
||||||
|
// character, except at end of line
|
||||||
|
if (s->c == K_DEL && ccline.cmdpos != ccline.cmdlen) {
|
||||||
|
ccline.cmdpos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->c == K_DEL) {
|
||||||
|
ccline.cmdpos += mb_off_next((char_u *)ccline.cmdbuff,
|
||||||
|
(char_u *)ccline.cmdbuff + ccline.cmdpos);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ccline.cmdpos > 0) {
|
||||||
|
char_u *p;
|
||||||
|
|
||||||
|
int j = ccline.cmdpos;
|
||||||
|
p = mb_prevptr((char_u *)ccline.cmdbuff, (char_u *)ccline.cmdbuff + j);
|
||||||
|
|
||||||
|
if (s->c == Ctrl_W) {
|
||||||
|
while (p > (char_u *)ccline.cmdbuff && ascii_isspace(*p)) {
|
||||||
|
p = mb_prevptr((char_u *)ccline.cmdbuff, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = mb_get_class(p);
|
||||||
|
while (p > (char_u *)ccline.cmdbuff && mb_get_class(p) == i) {
|
||||||
|
p = mb_prevptr((char_u *)ccline.cmdbuff, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mb_get_class(p) != i) {
|
||||||
|
p += utfc_ptr2len((char *)p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ccline.cmdpos = (int)(p - (char_u *)ccline.cmdbuff);
|
||||||
|
ccline.cmdlen -= j - ccline.cmdpos;
|
||||||
|
int 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;
|
||||||
|
if (ccline.cmdlen == 0) {
|
||||||
|
s->is_state.search_start = s->is_state.save_cursor;
|
||||||
|
// save view settings, so that the screen won't be restored at the
|
||||||
|
// wrong position
|
||||||
|
s->is_state.old_viewstate = s->is_state.init_viewstate;
|
||||||
|
}
|
||||||
|
redrawcmd();
|
||||||
|
} else if (ccline.cmdlen == 0 && s->c != Ctrl_W
|
||||||
|
&& ccline.cmdprompt == NULL && s->indent == 0) {
|
||||||
|
// In ex and debug mode it doesn't make sense to return.
|
||||||
|
if (exmode_active || ccline.cmdfirstc == '>') {
|
||||||
|
return command_line_not_changed(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
XFREE_CLEAR(ccline.cmdbuff); // no commandline to return
|
||||||
|
if (!cmd_silent && !ui_has(kUICmdline)) {
|
||||||
|
if (cmdmsg_rl) {
|
||||||
|
msg_col = Columns;
|
||||||
|
} else {
|
||||||
|
msg_col = 0;
|
||||||
|
}
|
||||||
|
msg_putchar(' '); // delete ':'
|
||||||
|
}
|
||||||
|
s->is_state.search_start = s->is_state.save_cursor;
|
||||||
|
redraw_cmdline = true;
|
||||||
|
return 0; // back to cmd mode
|
||||||
|
}
|
||||||
|
return command_line_changed(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Handle the CTRL-^ key in the command-line mode and toggle the use of the
|
||||||
|
/// language :lmap mappings and/or Input Method.
|
||||||
|
static void command_line_toggle_langmap(CommandLineState *s)
|
||||||
|
{
|
||||||
|
if (map_to_exists_mode("", MODE_LANGMAP, false)) {
|
||||||
|
// ":lmap" mappings exists, toggle use of mappings.
|
||||||
|
State ^= MODE_LANGMAP;
|
||||||
|
if (s->b_im_ptr != NULL) {
|
||||||
|
if (State & MODE_LANGMAP) {
|
||||||
|
*s->b_im_ptr = B_IMODE_LMAP;
|
||||||
|
} else {
|
||||||
|
*s->b_im_ptr = B_IMODE_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->b_im_ptr != NULL) {
|
||||||
|
if (s->b_im_ptr == &curbuf->b_p_iminsert) {
|
||||||
|
set_iminsert_global();
|
||||||
|
} else {
|
||||||
|
set_imsearch_global();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ui_cursor_shape(); // may show different cursor shape
|
||||||
|
// Show/unshow value of 'keymap' in status lines later.
|
||||||
|
status_redraw_curbuf();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Handle the CTRL-R key in the command-line mode and insert the contents of a
|
||||||
|
/// numbered or named register.
|
||||||
|
static int command_line_insert_reg(CommandLineState *s)
|
||||||
|
{
|
||||||
|
const int save_new_cmdpos = new_cmdpos;
|
||||||
|
|
||||||
|
putcmdline('"', true);
|
||||||
|
no_mapping++;
|
||||||
|
allow_keys++;
|
||||||
|
int i = s->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) {
|
||||||
|
s->c = plain_vgetc(); // CTRL-R CTRL-R <char>
|
||||||
|
}
|
||||||
|
no_mapping--;
|
||||||
|
allow_keys--;
|
||||||
|
// Insert the result of an expression.
|
||||||
|
new_cmdpos = -1;
|
||||||
|
if (s->c == '=') {
|
||||||
|
if (ccline.cmdfirstc == '=' // can't do this recursively
|
||||||
|
|| cmdline_star > 0) { // or when typing a password
|
||||||
|
beep_flush();
|
||||||
|
s->c = ESC;
|
||||||
|
} else {
|
||||||
|
s->c = get_expr_register();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->c != ESC) { // use ESC to cancel inserting register
|
||||||
|
cmdline_paste(s->c, i == Ctrl_R, false);
|
||||||
|
|
||||||
|
// When there was a serious error abort getting the
|
||||||
|
// command line.
|
||||||
|
if (aborting()) {
|
||||||
|
s->gotesc = true; // will free ccline.cmdbuff after
|
||||||
|
// putting it in history
|
||||||
|
return 0; // back to cmd mode
|
||||||
|
}
|
||||||
|
KeyTyped = false; // Don't do p_wc completion.
|
||||||
|
if (new_cmdpos >= 0) {
|
||||||
|
// set_cmdline_pos() was used
|
||||||
|
if (new_cmdpos > ccline.cmdlen) {
|
||||||
|
ccline.cmdpos = ccline.cmdlen;
|
||||||
|
} else {
|
||||||
|
ccline.cmdpos = new_cmdpos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new_cmdpos = save_new_cmdpos;
|
||||||
|
|
||||||
|
// remove the double quote
|
||||||
|
ccline.special_char = NUL;
|
||||||
|
redrawcmd();
|
||||||
|
|
||||||
|
return command_line_changed(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Handle the Left and Right mouse clicks in the command-line mode.
|
||||||
|
static void command_line_left_right_mouse(CommandLineState *s)
|
||||||
|
{
|
||||||
|
if (s->c == K_LEFTRELEASE || s->c == K_RIGHTRELEASE) {
|
||||||
|
s->ignore_drag_release = true;
|
||||||
|
} else {
|
||||||
|
s->ignore_drag_release = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ccline.cmdspos = cmd_startcol();
|
||||||
|
for (ccline.cmdpos = 0; ccline.cmdpos < ccline.cmdlen;
|
||||||
|
ccline.cmdpos++) {
|
||||||
|
int cells = cmdline_charsize(ccline.cmdpos);
|
||||||
|
if (mouse_row <= cmdline_row + ccline.cmdspos / Columns
|
||||||
|
&& mouse_col < ccline.cmdspos % Columns + cells) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count ">" for double-wide char that doesn't fit.
|
||||||
|
correct_screencol(ccline.cmdpos, cells, &ccline.cmdspos);
|
||||||
|
ccline.cmdpos += utfc_ptr2len(ccline.cmdbuff + ccline.cmdpos) - 1;
|
||||||
|
ccline.cmdspos += cells;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void command_line_next_histidx(CommandLineState *s, bool next_match)
|
static void command_line_next_histidx(CommandLineState *s, bool next_match)
|
||||||
{
|
{
|
||||||
int j = (int)strlen(s->lookfor);
|
int j = (int)strlen(s->lookfor);
|
||||||
@@ -1462,6 +1654,94 @@ static void command_line_next_histidx(CommandLineState *s, bool next_match)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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'.
|
||||||
|
static int command_line_browse_history(CommandLineState *s)
|
||||||
|
{
|
||||||
|
if (s->histype == HIST_INVALID || get_hislen() == 0 || s->firstc == NUL) {
|
||||||
|
// no history
|
||||||
|
return command_line_not_changed(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
s->save_hiscnt = s->hiscnt;
|
||||||
|
|
||||||
|
// save current command string so it can be restored later
|
||||||
|
if (s->lookfor == NULL) {
|
||||||
|
s->lookfor = xstrdup(ccline.cmdbuff);
|
||||||
|
s->lookfor[ccline.cmdpos] = NUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool next_match = (s->c == K_DOWN || s->c == K_S_DOWN || s->c == Ctrl_N
|
||||||
|
|| s->c == K_PAGEDOWN || s->c == K_KPAGEDOWN);
|
||||||
|
command_line_next_histidx(s, next_match);
|
||||||
|
|
||||||
|
if (s->hiscnt != s->save_hiscnt) {
|
||||||
|
// jumped to other entry
|
||||||
|
char *p;
|
||||||
|
int len = 0;
|
||||||
|
int old_firstc;
|
||||||
|
|
||||||
|
XFREE_CLEAR(ccline.cmdbuff);
|
||||||
|
s->xpc.xp_context = EXPAND_NOTHING;
|
||||||
|
if (s->hiscnt == get_hislen()) {
|
||||||
|
p = s->lookfor; // back to the old one
|
||||||
|
} else {
|
||||||
|
p = get_histentry(s->histype)[s->hiscnt].hisstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->histype == HIST_SEARCH
|
||||||
|
&& p != s->lookfor
|
||||||
|
&& (old_firstc = (uint8_t)p[strlen(p) + 1]) != s->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 (int i = 0; i <= 1; i++) {
|
||||||
|
len = 0;
|
||||||
|
for (int 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] = (char)s->firstc;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Escape new sep, unless it is already
|
||||||
|
// escaped.
|
||||||
|
if (p[j] == s->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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ccline.cmdbuff[len] = NUL;
|
||||||
|
} else {
|
||||||
|
alloc_cmdbuff((int)strlen(p));
|
||||||
|
STRCPY(ccline.cmdbuff, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
ccline.cmdpos = ccline.cmdlen = (int)strlen(ccline.cmdbuff);
|
||||||
|
redrawcmd();
|
||||||
|
return command_line_changed(s);
|
||||||
|
}
|
||||||
|
beep_flush();
|
||||||
|
return command_line_not_changed(s);
|
||||||
|
}
|
||||||
|
|
||||||
static int command_line_handle_key(CommandLineState *s)
|
static int command_line_handle_key(CommandLineState *s)
|
||||||
{
|
{
|
||||||
// Big switch for a typed command line character.
|
// Big switch for a typed command line character.
|
||||||
@@ -1471,80 +1751,7 @@ static int command_line_handle_key(CommandLineState *s)
|
|||||||
case K_DEL:
|
case K_DEL:
|
||||||
case K_KDEL:
|
case K_KDEL:
|
||||||
case Ctrl_W:
|
case Ctrl_W:
|
||||||
if (s->c == K_KDEL) {
|
return command_line_erase_chars(s);
|
||||||
s->c = K_DEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete current character is the same as backspace on next
|
|
||||||
// character, except at end of line
|
|
||||||
if (s->c == K_DEL && ccline.cmdpos != ccline.cmdlen) {
|
|
||||||
ccline.cmdpos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s->c == K_DEL) {
|
|
||||||
ccline.cmdpos += mb_off_next((char_u *)ccline.cmdbuff,
|
|
||||||
(char_u *)ccline.cmdbuff + ccline.cmdpos);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ccline.cmdpos > 0) {
|
|
||||||
char_u *p;
|
|
||||||
|
|
||||||
int j = ccline.cmdpos;
|
|
||||||
p = mb_prevptr((char_u *)ccline.cmdbuff, (char_u *)ccline.cmdbuff + j);
|
|
||||||
|
|
||||||
if (s->c == Ctrl_W) {
|
|
||||||
while (p > (char_u *)ccline.cmdbuff && ascii_isspace(*p)) {
|
|
||||||
p = mb_prevptr((char_u *)ccline.cmdbuff, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
int i = mb_get_class(p);
|
|
||||||
while (p > (char_u *)ccline.cmdbuff && mb_get_class(p) == i) {
|
|
||||||
p = mb_prevptr((char_u *)ccline.cmdbuff, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mb_get_class(p) != i) {
|
|
||||||
p += utfc_ptr2len((char *)p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ccline.cmdpos = (int)(p - (char_u *)ccline.cmdbuff);
|
|
||||||
ccline.cmdlen -= j - ccline.cmdpos;
|
|
||||||
int 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;
|
|
||||||
if (ccline.cmdlen == 0) {
|
|
||||||
s->is_state.search_start = s->is_state.save_cursor;
|
|
||||||
// save view settings, so that the screen won't be restored at the
|
|
||||||
// wrong position
|
|
||||||
s->is_state.old_viewstate = s->is_state.init_viewstate;
|
|
||||||
}
|
|
||||||
redrawcmd();
|
|
||||||
} else if (ccline.cmdlen == 0 && s->c != Ctrl_W
|
|
||||||
&& ccline.cmdprompt == NULL && s->indent == 0) {
|
|
||||||
// In ex and debug mode it doesn't make sense to return.
|
|
||||||
if (exmode_active || ccline.cmdfirstc == '>') {
|
|
||||||
return command_line_not_changed(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
XFREE_CLEAR(ccline.cmdbuff); // no commandline to return
|
|
||||||
if (!cmd_silent && !ui_has(kUICmdline)) {
|
|
||||||
if (cmdmsg_rl) {
|
|
||||||
msg_col = Columns;
|
|
||||||
} else {
|
|
||||||
msg_col = 0;
|
|
||||||
}
|
|
||||||
msg_putchar(' '); // delete ':'
|
|
||||||
}
|
|
||||||
s->is_state.search_start = s->is_state.save_cursor;
|
|
||||||
redraw_cmdline = true;
|
|
||||||
return 0; // back to cmd mode
|
|
||||||
}
|
|
||||||
return command_line_changed(s);
|
|
||||||
|
|
||||||
case K_INS:
|
case K_INS:
|
||||||
case K_KINS:
|
case K_KINS:
|
||||||
@@ -1554,28 +1761,7 @@ static int command_line_handle_key(CommandLineState *s)
|
|||||||
return command_line_not_changed(s);
|
return command_line_not_changed(s);
|
||||||
|
|
||||||
case Ctrl_HAT:
|
case Ctrl_HAT:
|
||||||
if (map_to_exists_mode("", MODE_LANGMAP, false)) {
|
command_line_toggle_langmap(s);
|
||||||
// ":lmap" mappings exists, toggle use of mappings.
|
|
||||||
State ^= MODE_LANGMAP;
|
|
||||||
if (s->b_im_ptr != NULL) {
|
|
||||||
if (State & MODE_LANGMAP) {
|
|
||||||
*s->b_im_ptr = B_IMODE_LMAP;
|
|
||||||
} else {
|
|
||||||
*s->b_im_ptr = B_IMODE_NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s->b_im_ptr != NULL) {
|
|
||||||
if (s->b_im_ptr == &curbuf->b_p_iminsert) {
|
|
||||||
set_iminsert_global();
|
|
||||||
} else {
|
|
||||||
set_imsearch_global();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ui_cursor_shape(); // may show different cursor shape
|
|
||||||
// Show/unshow value of 'keymap' in status lines later.
|
|
||||||
status_redraw_curbuf();
|
|
||||||
return command_line_not_changed(s);
|
return command_line_not_changed(s);
|
||||||
|
|
||||||
case Ctrl_U: {
|
case Ctrl_U: {
|
||||||
@@ -1611,62 +1797,8 @@ static int command_line_handle_key(CommandLineState *s)
|
|||||||
// putting it in history
|
// putting it in history
|
||||||
return 0; // back to cmd mode
|
return 0; // back to cmd mode
|
||||||
|
|
||||||
case Ctrl_R: { // insert register
|
case Ctrl_R: // insert register
|
||||||
const int save_new_cmdpos = new_cmdpos;
|
return command_line_insert_reg(s);
|
||||||
|
|
||||||
putcmdline('"', true);
|
|
||||||
no_mapping++;
|
|
||||||
allow_keys++;
|
|
||||||
int i = s->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) {
|
|
||||||
s->c = plain_vgetc(); // CTRL-R CTRL-R <char>
|
|
||||||
}
|
|
||||||
no_mapping--;
|
|
||||||
allow_keys--;
|
|
||||||
// Insert the result of an expression.
|
|
||||||
new_cmdpos = -1;
|
|
||||||
if (s->c == '=') {
|
|
||||||
if (ccline.cmdfirstc == '=' // can't do this recursively
|
|
||||||
|| cmdline_star > 0) { // or when typing a password
|
|
||||||
beep_flush();
|
|
||||||
s->c = ESC;
|
|
||||||
} else {
|
|
||||||
s->c = get_expr_register();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s->c != ESC) { // use ESC to cancel inserting register
|
|
||||||
cmdline_paste(s->c, i == Ctrl_R, false);
|
|
||||||
|
|
||||||
// When there was a serious error abort getting the
|
|
||||||
// command line.
|
|
||||||
if (aborting()) {
|
|
||||||
s->gotesc = true; // will free ccline.cmdbuff after
|
|
||||||
// putting it in history
|
|
||||||
return 0; // back to cmd mode
|
|
||||||
}
|
|
||||||
KeyTyped = false; // Don't do p_wc completion.
|
|
||||||
if (new_cmdpos >= 0) {
|
|
||||||
// set_cmdline_pos() was used
|
|
||||||
if (new_cmdpos > ccline.cmdlen) {
|
|
||||||
ccline.cmdpos = ccline.cmdlen;
|
|
||||||
} else {
|
|
||||||
ccline.cmdpos = new_cmdpos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
new_cmdpos = save_new_cmdpos;
|
|
||||||
|
|
||||||
// remove the double quote
|
|
||||||
ccline.special_char = NUL;
|
|
||||||
redrawcmd();
|
|
||||||
|
|
||||||
return command_line_changed(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
case Ctrl_D:
|
case Ctrl_D:
|
||||||
if (showmatches(&s->xpc, false) == EXPAND_NOTHING) {
|
if (showmatches(&s->xpc, false) == EXPAND_NOTHING) {
|
||||||
@@ -1747,26 +1879,7 @@ static int command_line_handle_key(CommandLineState *s)
|
|||||||
FALLTHROUGH;
|
FALLTHROUGH;
|
||||||
case K_LEFTMOUSE:
|
case K_LEFTMOUSE:
|
||||||
case K_RIGHTMOUSE:
|
case K_RIGHTMOUSE:
|
||||||
if (s->c == K_LEFTRELEASE || s->c == K_RIGHTRELEASE) {
|
command_line_left_right_mouse(s);
|
||||||
s->ignore_drag_release = true;
|
|
||||||
} else {
|
|
||||||
s->ignore_drag_release = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ccline.cmdspos = cmd_startcol();
|
|
||||||
for (ccline.cmdpos = 0; ccline.cmdpos < ccline.cmdlen;
|
|
||||||
ccline.cmdpos++) {
|
|
||||||
int cells = cmdline_charsize(ccline.cmdpos);
|
|
||||||
if (mouse_row <= cmdline_row + ccline.cmdspos / Columns
|
|
||||||
&& mouse_col < ccline.cmdspos % Columns + cells) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Count ">" for double-wide char that doesn't fit.
|
|
||||||
correct_screencol(ccline.cmdpos, cells, &ccline.cmdspos);
|
|
||||||
ccline.cmdpos += utfc_ptr2len(ccline.cmdbuff + ccline.cmdpos) - 1;
|
|
||||||
ccline.cmdspos += cells;
|
|
||||||
}
|
|
||||||
return command_line_not_changed(s);
|
return command_line_not_changed(s);
|
||||||
|
|
||||||
// Mouse scroll wheel: ignored here
|
// Mouse scroll wheel: ignored here
|
||||||
@@ -1849,88 +1962,7 @@ static int command_line_handle_key(CommandLineState *s)
|
|||||||
case K_KPAGEUP:
|
case K_KPAGEUP:
|
||||||
case K_PAGEDOWN:
|
case K_PAGEDOWN:
|
||||||
case K_KPAGEDOWN:
|
case K_KPAGEDOWN:
|
||||||
if (s->histype == HIST_INVALID || get_hislen() == 0 || s->firstc == NUL) {
|
return command_line_browse_history(s);
|
||||||
// no history
|
|
||||||
return command_line_not_changed(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
s->save_hiscnt = s->hiscnt;
|
|
||||||
|
|
||||||
// save current command string so it can be restored later
|
|
||||||
if (s->lookfor == NULL) {
|
|
||||||
s->lookfor = xstrdup(ccline.cmdbuff);
|
|
||||||
s->lookfor[ccline.cmdpos] = NUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool next_match = (s->c == K_DOWN || s->c == K_S_DOWN || s->c == Ctrl_N
|
|
||||||
|| s->c == K_PAGEDOWN || s->c == K_KPAGEDOWN);
|
|
||||||
command_line_next_histidx(s, next_match);
|
|
||||||
|
|
||||||
if (s->hiscnt != s->save_hiscnt) {
|
|
||||||
// jumped to other entry
|
|
||||||
char *p;
|
|
||||||
int len = 0;
|
|
||||||
int old_firstc;
|
|
||||||
|
|
||||||
XFREE_CLEAR(ccline.cmdbuff);
|
|
||||||
s->xpc.xp_context = EXPAND_NOTHING;
|
|
||||||
if (s->hiscnt == get_hislen()) {
|
|
||||||
p = s->lookfor; // back to the old one
|
|
||||||
} else {
|
|
||||||
p = get_histentry(s->histype)[s->hiscnt].hisstr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s->histype == HIST_SEARCH
|
|
||||||
&& p != s->lookfor
|
|
||||||
&& (old_firstc = (uint8_t)p[strlen(p) + 1]) != s->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 (int i = 0; i <= 1; i++) {
|
|
||||||
len = 0;
|
|
||||||
for (int 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] = (char)s->firstc;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Escape new sep, unless it is already
|
|
||||||
// escaped.
|
|
||||||
if (p[j] == s->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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ccline.cmdbuff[len] = NUL;
|
|
||||||
} else {
|
|
||||||
alloc_cmdbuff((int)strlen(p));
|
|
||||||
STRCPY(ccline.cmdbuff, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
ccline.cmdpos = ccline.cmdlen = (int)strlen(ccline.cmdbuff);
|
|
||||||
redrawcmd();
|
|
||||||
return command_line_changed(s);
|
|
||||||
}
|
|
||||||
beep_flush();
|
|
||||||
return command_line_not_changed(s);
|
|
||||||
|
|
||||||
case Ctrl_G: // next match
|
case Ctrl_G: // next match
|
||||||
case Ctrl_T: // previous match
|
case Ctrl_T: // previous match
|
||||||
|
Reference in New Issue
Block a user