Patch 8.2.1622
Problem:    Loop to handle keys for the command line is too long.
Solution:   Move code to functions. (Yegappan Lakshmanan, closes #6880)
Files:      src/ex_getln.c


*** ../vim-8.2.1621/src/ex_getln.c      2020-09-04 15:37:27.865546317 +0200
--- src/ex_getln.c      2020-09-06 15:42:49.737157703 +0200
***************
*** 17,22 ****
--- 17,27 ----
  # 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,768 ****
--- 768,1250 ----
  }
  
  /*
+  * 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,1458 ****
        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;
! #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
! #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;
  
        case K_INS:
        case K_KINS:
--- 1843,1858 ----
        case K_DEL:
        case K_KDEL:
        case Ctrl_W:
!           res = cmdline_erase_chars(c, indent
  #ifdef FEAT_SEARCH_EXTRA
!                   , &is_state
  #endif
!                   );
!           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,1518 ****
                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
                goto cmdline_not_changed;
  
  //    case '@':   only in very old vi
--- 1863,1869 ----
                goto cmdline_not_changed;
  
        case Ctrl_HAT:
!               cmdline_toggle_langmap(b_im_ptr);
                goto cmdline_not_changed;
  
  //    case '@':   only in very old vi
***************
*** 1557,1622 ****
                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();
                goto cmdline_changed;
  
        case Ctrl_D:
--- 1908,1918 ----
                goto returncmd;         // back to cmd mode
  
        case Ctrl_R:                    // insert register
!               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,1779 ****
                // 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;
!               }
                goto cmdline_not_changed;
  
        // Mouse scroll wheel: ignored here
--- 2021,2027 ----
                // FALLTHROUGH
        case K_LEFTMOUSE:
        case K_RIGHTMOUSE:
!               cmdline_left_right_mouse(c, &ignore_drag_release);
                goto cmdline_not_changed;
  
        // Mouse scroll wheel: ignored here
***************
*** 1877,2017 ****
        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();
                    goto cmdline_changed;
!               }
!               beep_flush();
                goto cmdline_not_changed;
  
  #ifdef FEAT_SEARCH_EXTRA
--- 2125,2136 ----
        case K_KPAGEUP:
        case K_PAGEDOWN:
        case K_KPAGEDOWN:
!               res = cmdline_browse_history(c, firstc, &lookfor, histype,
!                       &hiscnt, &xpc);
!               if (res == CMDLINE_CHANGED)
                    goto cmdline_changed;
!               else if (res == GOTO_NORMAL_MODE)
!                   goto returncmd;
                goto cmdline_not_changed;
  
  #ifdef FEAT_SEARCH_EXTRA
*** ../vim-8.2.1621/src/version.c       2020-09-06 15:14:42.217505521 +0200
--- src/version.c       2020-09-06 15:39:46.629413283 +0200
***************
*** 756,757 ****
--- 756,759 ----
  {   /* Add new patch number below this line */
+ /**/
+     1622,
  /**/

-- 
Mental Floss prevents moral decay!

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/202009061354.086DsR8D906381%40masaka.moolenaar.net.

Raspunde prin e-mail lui