Patch 8.1.1797 (after 8.1.1794)
Problem:    The vgetorpeek() function is too long.
Solution:   Split off the part that handles mappings, with fix.
Files:      src/getchar.c


*** ../vim-8.1.1796/src/getchar.c       2019-08-02 22:46:08.317622692 +0200
--- src/getchar.c       2019-08-03 14:08:35.974397757 +0200
***************
*** 1900,1905 ****
--- 1900,2429 ----
      return (retval != NUL);
  }
  
+ typedef enum {
+     map_result_fail,    // failed, break loop
+     map_result_get,     // get a character from typeahead
+     map_result_retry,   // try to map again
+     map_result_nomatch  // no matching mapping, get char
+ } map_result_T;
+ 
+ /*
+  * Handle mappings in the typeahead buffer.
+  * - When something was mapped, return map_result_retry for recursive 
mappings.
+  * - When nothing mapped and typeahead has a character return map_result_get.
+  * - When there is no match yet, return map_result_nomatch, need to get more
+  *   typeahead.
+  */
+     static int
+ handle_mapping(
+           int *keylenp,
+           int *timedout,
+           int *mapdepth)
+ {
+     mapblock_T        *mp = NULL;
+     mapblock_T        *mp2;
+     mapblock_T        *mp_match;
+     int               mp_match_len = 0;
+     int               max_mlen = 0;
+     int               tb_c1;
+     int               mlen;
+ #ifdef FEAT_LANGMAP
+     int               nolmaplen;
+ #endif
+     int               keylen = *keylenp;
+     int               i;
+     int               local_State = get_real_state();
+ 
+     /*
+      * Check for a mappable key sequence.
+      * Walk through one maphash[] list until we find an
+      * entry that matches.
+      *
+      * Don't look for mappings if:
+      * - no_mapping set: mapping disabled (e.g. for CTRL-V)
+      * - maphash_valid not set: no mappings present.
+      * - typebuf.tb_buf[typebuf.tb_off] should not be remapped
+      * - in insert or cmdline mode and 'paste' option set
+      * - waiting for "hit return to continue" and CR or SPACE
+      *         typed
+      * - waiting for a char with --more--
+      * - in Ctrl-X mode, and we get a valid char for that mode
+      */
+     tb_c1 = typebuf.tb_buf[typebuf.tb_off];
+     if (no_mapping == 0 && is_maphash_valid()
+           && (no_zero_mapping == 0 || tb_c1 != '0')
+           && (typebuf.tb_maplen == 0
+               || (p_remap
+                   && (typebuf.tb_noremap[typebuf.tb_off]
+                                   & (RM_NONE|RM_ABBR)) == 0))
+           && !(p_paste && (State & (INSERT + CMDLINE)))
+           && !(State == HITRETURN && (tb_c1 == CAR || tb_c1 == ' '))
+           && State != ASKMORE
+           && State != CONFIRM
+ #ifdef FEAT_INS_EXPAND
+           && !((ctrl_x_mode_not_default()
+                                  && vim_is_ctrl_x_key(tb_c1))
+                   || ((compl_cont_status & CONT_LOCAL)
+                       && (tb_c1 == Ctrl_N || tb_c1 == Ctrl_P)))
+ #endif
+           )
+     {
+ #ifdef FEAT_LANGMAP
+       if (tb_c1 == K_SPECIAL)
+           nolmaplen = 2;
+       else
+       {
+           LANGMAP_ADJUST(tb_c1,
+                          (State & (CMDLINE | INSERT)) == 0
+                          && get_real_state() != SELECTMODE);
+           nolmaplen = 0;
+       }
+ #endif
+       // First try buffer-local mappings.
+       mp = get_buf_maphash_list(local_State, tb_c1);
+       mp2 = get_maphash_list(local_State, tb_c1);
+       if (mp == NULL)
+       {
+           // There are no buffer-local mappings.
+           mp = mp2;
+           mp2 = NULL;
+       }
+       /*
+        * Loop until a partly matching mapping is found or
+        * all (local) mappings have been checked.
+        * The longest full match is remembered in "mp_match".
+        * A full match is only accepted if there is no partly
+        * match, so "aa" and "aaa" can both be mapped.
+        */
+       mp_match = NULL;
+       mp_match_len = 0;
+       for ( ; mp != NULL;
+               mp->m_next == NULL ? (mp = mp2, mp2 = NULL)
+                                  : (mp = mp->m_next))
+       {
+           // Only consider an entry if the first character
+           // matches and it is for the current state.
+           // Skip ":lmap" mappings if keys were mapped.
+           if (mp->m_keys[0] == tb_c1
+                   && (mp->m_mode & local_State)
+                   && ((mp->m_mode & LANGMAP) == 0
+                       || typebuf.tb_maplen == 0))
+           {
+ #ifdef FEAT_LANGMAP
+               int     nomap = nolmaplen;
+               int     c2;
+ #endif
+               // find the match length of this mapping
+               for (mlen = 1; mlen < typebuf.tb_len; ++mlen)
+               {
+ #ifdef FEAT_LANGMAP
+                   c2 = typebuf.tb_buf[typebuf.tb_off + mlen];
+                   if (nomap > 0)
+                       --nomap;
+                   else if (c2 == K_SPECIAL)
+                       nomap = 2;
+                   else
+                       LANGMAP_ADJUST(c2, TRUE);
+                   if (mp->m_keys[mlen] != c2)
+ #else
+                   if (mp->m_keys[mlen] !=
+                       typebuf.tb_buf[typebuf.tb_off + mlen])
+ #endif
+                       break;
+               }
+ 
+               // Don't allow mapping the first byte(s) of a
+               // multi-byte char.  Happens when mapping
+               // <M-a> and then changing 'encoding'. Beware
+               // that 0x80 is escaped.
+               {
+                   char_u *p1 = mp->m_keys;
+                   char_u *p2 = mb_unescape(&p1);
+ 
+                   if (has_mbyte && p2 != NULL
+                         && MB_BYTE2LEN(tb_c1) > MB_PTR2LEN(p2))
+                       mlen = 0;
+               }
+ 
+               // Check an entry whether it matches.
+               // - Full match: mlen == keylen
+               // - Partly match: mlen == typebuf.tb_len
+               keylen = mp->m_keylen;
+               if (mlen == keylen
+                    || (mlen == typebuf.tb_len
+                                 && typebuf.tb_len < keylen))
+               {
+                   char_u  *s;
+                   int     n;
+ 
+                   // If only script-local mappings are
+                   // allowed, check if the mapping starts
+                   // with K_SNR.
+                   s = typebuf.tb_noremap + typebuf.tb_off;
+                   if (*s == RM_SCRIPT
+                           && (mp->m_keys[0] != K_SPECIAL
+                               || mp->m_keys[1] != KS_EXTRA
+                               || mp->m_keys[2]
+                                             != (int)KE_SNR))
+                       continue;
+ 
+                   // If one of the typed keys cannot be
+                   // remapped, skip the entry.
+                   for (n = mlen; --n >= 0; )
+                       if (*s++ & (RM_NONE|RM_ABBR))
+                           break;
+                   if (n >= 0)
+                       continue;
+ 
+                   if (keylen > typebuf.tb_len)
+                   {
+                       if (!*timedout && !(mp_match != NULL
+                                      && mp_match->m_nowait))
+                       {
+                           // break at a partly match
+                           keylen = KEYLEN_PART_MAP;
+                           break;
+                       }
+                   }
+                   else if (keylen > mp_match_len)
+                   {
+                       // found a longer match
+                       mp_match = mp;
+                       mp_match_len = keylen;
+                   }
+               }
+               else
+                   // No match; may have to check for
+                   // termcode at next character.
+                   if (max_mlen < mlen)
+                       max_mlen = mlen;
+           }
+       }
+ 
+       // If no partly match found, use the longest full
+       // match.
+       if (keylen != KEYLEN_PART_MAP)
+       {
+           mp = mp_match;
+           keylen = mp_match_len;
+       }
+     }
+ 
+     /*
+      * Check for match with 'pastetoggle'
+      */
+     if (*p_pt != NUL && mp == NULL && (State & (INSERT|NORMAL)))
+     {
+       for (mlen = 0; mlen < typebuf.tb_len && p_pt[mlen];
+                                                      ++mlen)
+           if (p_pt[mlen] != typebuf.tb_buf[typebuf.tb_off
+                                                     + mlen])
+                   break;
+       if (p_pt[mlen] == NUL)  // match
+       {
+           // write chars to script file(s)
+           if (mlen > typebuf.tb_maplen)
+               gotchars(typebuf.tb_buf + typebuf.tb_off
+                                         + typebuf.tb_maplen,
+                                   mlen - typebuf.tb_maplen);
+ 
+           del_typebuf(mlen, 0); // remove the chars
+           set_option_value((char_u *)"paste",
+                                    (long)!p_paste, NULL, 0);
+           if (!(State & INSERT))
+           {
+               msg_col = 0;
+               msg_row = Rows - 1;
+               msg_clr_eos();          // clear ruler
+           }
+           status_redraw_all();
+           redraw_statuslines();
+           showmode();
+           setcursor();
+           *keylenp = keylen;
+           return map_result_retry;
+       }
+       // Need more chars for partly match.
+       if (mlen == typebuf.tb_len)
+           keylen = KEYLEN_PART_KEY;
+       else if (max_mlen < mlen)
+           // no match, may have to check for termcode at
+           // next character
+           max_mlen = mlen + 1;
+     }
+ 
+     if ((mp == NULL || max_mlen >= mp_match_len)
+                                && keylen != KEYLEN_PART_MAP)
+     {
+       int     save_keylen = keylen;
+ 
+       /*
+        * When no matching mapping found or found a
+        * non-matching mapping that matches at least what the
+        * matching mapping matched:
+        * Check if we have a terminal code, when:
+        *  mapping is allowed,
+        *  keys have not been mapped,
+        *  and not an ESC sequence, not in insert mode or
+        *      p_ek is on,
+        *  and when not timed out,
+        */
+       if ((no_mapping == 0 || allow_keys != 0)
+               && (typebuf.tb_maplen == 0
+                   || (p_remap && typebuf.tb_noremap[
+                                  typebuf.tb_off] == RM_YES))
+               && !*timedout)
+       {
+           keylen = check_termcode(max_mlen + 1,
+                                              NULL, 0, NULL);
+ 
+           // If no termcode matched but 'pastetoggle'
+           // matched partially it's like an incomplete key
+           // sequence.
+           if (keylen == 0 && save_keylen == KEYLEN_PART_KEY)
+               keylen = KEYLEN_PART_KEY;
+ 
+           // When getting a partial match, but the last
+           // characters were not typed, don't wait for a
+           // typed character to complete the termcode.
+           // This helps a lot when a ":normal" command ends
+           // in an ESC.
+           if (keylen < 0
+                      && typebuf.tb_len == typebuf.tb_maplen)
+               keylen = 0;
+       }
+       else
+           keylen = 0;
+       if (keylen == 0)        // no matching terminal code
+       {
+ #ifdef AMIGA                  // check for window bounds report
+           if (typebuf.tb_maplen == 0 && (typebuf.tb_buf[
+                              typebuf.tb_off] & 0xff) == CSI)
+           {
+               char_u *s;
+ 
+               for (s = typebuf.tb_buf + typebuf.tb_off + 1;
+                       s < typebuf.tb_buf + typebuf.tb_off
+                                             + typebuf.tb_len
+                  && (VIM_ISDIGIT(*s) || *s == ';'
+                                               || *s == ' ');
+                       ++s)
+                   ;
+               if (*s == 'r' || *s == '|') // found one
+               {
+                   del_typebuf((int)(s + 1 -
+                      (typebuf.tb_buf + typebuf.tb_off)), 0);
+                   // get size and redraw screen
+                   shell_resized();
+                   *keylenp = keylen;
+                   return map_result_retry;
+               }
+               if (*s == NUL)      // need more characters
+                   keylen = KEYLEN_PART_KEY;
+           }
+           if (keylen >= 0)
+ #endif
+             // When there was a matching mapping and no
+             // termcode could be replaced after another one,
+             // use that mapping (loop around). If there was
+             // no mapping at all use the character from the
+             // typeahead buffer right here.
+             if (mp == NULL)
+             {
+               *keylenp = keylen;
+               return map_result_get;      // got character, break for loop
+             }
+       }
+ 
+       if (keylen > 0)     // full matching terminal code
+       {
+ #if defined(FEAT_GUI) && defined(FEAT_MENU)
+           if (typebuf.tb_len >= 2
+               && typebuf.tb_buf[typebuf.tb_off] == K_SPECIAL
+                        && typebuf.tb_buf[typebuf.tb_off + 1]
+                                                  == KS_MENU)
+           {
+               int     idx;
+ 
+               // Using a menu may cause a break in undo!
+               // It's like using gotchars(), but without
+               // recording or writing to a script file.
+               may_sync_undo();
+               del_typebuf(3, 0);
+               idx = get_menu_index(current_menu, local_State);
+               if (idx != MENU_INDEX_INVALID)
+               {
+                   // In Select mode and a Visual mode menu
+                   // is used:  Switch to Visual mode
+                   // temporarily.  Append K_SELECT to switch
+                   // back to Select mode.
+                   if (VIsual_active && VIsual_select
+                           && (current_menu->modes & VISUAL))
+                   {
+                       VIsual_select = FALSE;
+                       (void)ins_typebuf(K_SELECT_STRING,
+                                 REMAP_NONE, 0, TRUE, FALSE);
+                   }
+                   ins_typebuf(current_menu->strings[idx],
+                               current_menu->noremap[idx],
+                               0, TRUE,
+                                  current_menu->silent[idx]);
+               }
+           }
+ #endif // FEAT_GUI && FEAT_MENU
+           *keylenp = keylen;
+           return map_result_retry;    // try mapping again
+       }
+ 
+       // Partial match: get some more characters.  When a
+       // matching mapping was found use that one.
+       if (mp == NULL || keylen < 0)
+           keylen = KEYLEN_PART_KEY;
+       else
+           keylen = mp_match_len;
+     }
+ 
+     /*
+      * complete match
+      */
+     if (keylen >= 0 && keylen <= typebuf.tb_len)
+     {
+       char_u *map_str;
+ 
+ #ifdef FEAT_EVAL
+       int save_m_expr;
+       int save_m_noremap;
+       int save_m_silent;
+       char_u *save_m_keys;
+       char_u *save_m_str;
+ #else
+ # define save_m_noremap mp->m_noremap
+ # define save_m_silent mp->m_silent
+ #endif
+ 
+       // write chars to script file(s)
+       if (keylen > typebuf.tb_maplen)
+           gotchars(typebuf.tb_buf + typebuf.tb_off
+                                         + typebuf.tb_maplen,
+                                 keylen - typebuf.tb_maplen);
+ 
+       cmd_silent = (typebuf.tb_silent > 0);
+       del_typebuf(keylen, 0); // remove the mapped keys
+ 
+       /*
+        * Put the replacement string in front of mapstr.
+        * The depth check catches ":map x y" and ":map y x".
+        */
+       if (++*mapdepth >= p_mmd)
+       {
+           emsg(_("E223: recursive mapping"));
+           if (State & CMDLINE)
+               redrawcmdline();
+           else
+               setcursor();
+           flush_buffers(FLUSH_MINIMAL);
+           *mapdepth = 0;      /* for next one */
+           *keylenp = keylen;
+           return map_result_fail;
+       }
+ 
+       /*
+        * In Select mode and a Visual mode mapping is used:
+        * Switch to Visual mode temporarily.  Append K_SELECT
+        * to switch back to Select mode.
+        */
+       if (VIsual_active && VIsual_select
+                                    && (mp->m_mode & VISUAL))
+       {
+           VIsual_select = FALSE;
+           (void)ins_typebuf(K_SELECT_STRING, REMAP_NONE,
+                                             0, TRUE, FALSE);
+       }
+ 
+ #ifdef FEAT_EVAL
+       // Copy the values from *mp that are used, because
+       // evaluating the expression may invoke a function
+       // that redefines the mapping, thereby making *mp
+       // invalid.
+       save_m_expr = mp->m_expr;
+       save_m_noremap = mp->m_noremap;
+       save_m_silent = mp->m_silent;
+       save_m_keys = NULL;  // only saved when needed
+       save_m_str = NULL;  // only saved when needed
+ 
+       /*
+        * Handle ":map <expr>": evaluate the {rhs} as an
+        * expression.  Also save and restore the command line
+        * for "normal :".
+        */
+       if (mp->m_expr)
+       {
+           int save_vgetc_busy = vgetc_busy;
+           int save_may_garbage_collect = may_garbage_collect;
+ 
+           vgetc_busy = 0;
+           may_garbage_collect = FALSE;
+ 
+           save_m_keys = vim_strsave(mp->m_keys);
+           save_m_str = vim_strsave(mp->m_str);
+           map_str = eval_map_expr(save_m_str, NUL);
+ 
+           vgetc_busy = save_vgetc_busy;
+           may_garbage_collect = save_may_garbage_collect;
+       }
+       else
+ #endif
+           map_str = mp->m_str;
+ 
+       /*
+        * Insert the 'to' part in the typebuf.tb_buf.
+        * If 'from' field is the same as the start of the
+        * 'to' field, don't remap the first character (but do
+        * allow abbreviations).
+        * If m_noremap is set, don't remap the whole 'to'
+        * part.
+        */
+       if (map_str == NULL)
+           i = FAIL;
+       else
+       {
+           int noremap;
+ 
+           if (save_m_noremap != REMAP_YES)
+               noremap = save_m_noremap;
+           else if (
+ #ifdef FEAT_EVAL
+               STRNCMP(map_str, save_m_keys != NULL
+                                  ? save_m_keys : mp->m_keys,
+                                        (size_t)keylen)
+ #else
+               STRNCMP(map_str, mp->m_keys, (size_t)keylen)
+ #endif
+                  != 0)
+               noremap = REMAP_YES;
+           else
+               noremap = REMAP_SKIP;
+           i = ins_typebuf(map_str, noremap,
+                                        0, TRUE, cmd_silent || save_m_silent);
+ #ifdef FEAT_EVAL
+           if (save_m_expr)
+               vim_free(map_str);
+ #endif
+       }
+ #ifdef FEAT_EVAL
+       vim_free(save_m_keys);
+       vim_free(save_m_str);
+ #endif
+       *keylenp = keylen;
+       if (i == FAIL)
+           return map_result_fail;
+       return map_result_retry;
+     }
+ 
+     *keylenp = keylen;
+     return map_result_nomatch;
+ }
+ 
  /*
   * unget one character (can only be done once!)
   */
***************
*** 1942,1974 ****
  vgetorpeek(int advance)
  {
      int               c, c1;
-     int               keylen;
-     char_u    *s;
-     mapblock_T        *mp;
-     mapblock_T        *mp2;
-     mapblock_T        *mp_match;
-     int               mp_match_len = 0;
      int               timedout = FALSE;           /* waited for more than 1 
second
                                                for mapping to complete */
      int               mapdepth = 0;       /* check for recursive mapping */
      int               mode_deleted = FALSE;   /* set when mode has been 
deleted */
-     int               local_State;
-     int               mlen;
-     int               max_mlen;
      int               i;
  #ifdef FEAT_CMDL_INFO
      int               new_wcol, new_wrow;
  #endif
  #ifdef FEAT_GUI
- # ifdef FEAT_MENU
-     int               idx;
- # endif
      int               shape_changed = FALSE;  /* adjusted cursor shape */
  #endif
      int               n;
- #ifdef FEAT_LANGMAP
-     int               nolmaplen;
- #endif
      int               old_wcol, old_wrow;
      int               wait_tb_len;
  
--- 2466,2483 ----
***************
*** 1986,1993 ****
      if (vgetc_busy > 0 && ex_normal_busy == 0)
        return NUL;
  
-     local_State = get_real_state();
- 
      ++vgetc_busy;
  
      if (advance)
--- 2495,2500 ----
***************
*** 2032,2038 ****
             */
            for (;;)
            {
!               long        wait_time;
  
                /*
                 * ui_breakcheck() is slow, don't use it too often when
--- 2539,2546 ----
             */
            for (;;)
            {
!               long    wait_time;
!               int     keylen = 0;
  
                /*
                 * ui_breakcheck() is slow, don't use it too often when
***************
*** 2043,2053 ****
                    line_breakcheck();
                else
                    ui_breakcheck();            /* check for CTRL-C */
-               keylen = 0;
                if (got_int)
                {
                    /* flush all input */
                    c = inchar(typebuf.tb_buf, typebuf.tb_buflen - 1, 0L);
                    /*
                     * If inchar() returns TRUE (script file was active) or we
                     * are inside a mapping, get out of Insert mode.
--- 2551,2561 ----
                    line_breakcheck();
                else
                    ui_breakcheck();            /* check for CTRL-C */
                if (got_int)
                {
                    /* flush all input */
                    c = inchar(typebuf.tb_buf, typebuf.tb_buflen - 1, 0L);
+ 
                    /*
                     * If inchar() returns TRUE (script file was active) or we
                     * are inside a mapping, get out of Insert mode.
***************
*** 2076,2583 ****
                else if (typebuf.tb_len > 0)
                {
                    /*
!                    * Check for a mappable key sequence.
!                    * Walk through one maphash[] list until we find an
!                    * entry that matches.
!                    *
!                    * Don't look for mappings if:
!                    * - no_mapping set: mapping disabled (e.g. for CTRL-V)
!                    * - maphash_valid not set: no mappings present.
!                    * - typebuf.tb_buf[typebuf.tb_off] should not be remapped
!                    * - in insert or cmdline mode and 'paste' option set
!                    * - waiting for "hit return to continue" and CR or SPACE
!                    *   typed
!                    * - waiting for a char with --more--
!                    * - in Ctrl-X mode, and we get a valid char for that mode
                     */
!                   mp = NULL;
!                   max_mlen = 0;
!                   c1 = typebuf.tb_buf[typebuf.tb_off];
!                   if (no_mapping == 0 && is_maphash_valid()
!                           && (no_zero_mapping == 0 || c1 != '0')
!                           && (typebuf.tb_maplen == 0
!                               || (p_remap
!                                   && (typebuf.tb_noremap[typebuf.tb_off]
!                                                   & (RM_NONE|RM_ABBR)) == 0))
!                           && !(p_paste && (State & (INSERT + CMDLINE)))
!                           && !(State == HITRETURN && (c1 == CAR || c1 == ' '))
!                           && State != ASKMORE
!                           && State != CONFIRM
! #ifdef FEAT_INS_EXPAND
!                           && !((ctrl_x_mode_not_default()
!                                                     && vim_is_ctrl_x_key(c1))
!                                   || ((compl_cont_status & CONT_LOCAL)
!                                       && (c1 == Ctrl_N || c1 == Ctrl_P)))
! #endif
!                           )
!                   {
! #ifdef FEAT_LANGMAP
!                       if (c1 == K_SPECIAL)
!                           nolmaplen = 2;
!                       else
!                       {
!                           LANGMAP_ADJUST(c1,
!                                          (State & (CMDLINE | INSERT)) == 0
!                                          && get_real_state() != SELECTMODE);
!                           nolmaplen = 0;
!                       }
! #endif
!                       // First try buffer-local mappings.
!                       mp = get_buf_maphash_list(local_State, c1);
!                       mp2 = get_maphash_list(local_State, c1);
!                       if (mp == NULL)
!                       {
!                           // There are no buffer-local mappings.
!                           mp = mp2;
!                           mp2 = NULL;
!                       }
!                       /*
!                        * Loop until a partly matching mapping is found or
!                        * all (local) mappings have been checked.
!                        * The longest full match is remembered in "mp_match".
!                        * A full match is only accepted if there is no partly
!                        * match, so "aa" and "aaa" can both be mapped.
!                        */
!                       mp_match = NULL;
!                       mp_match_len = 0;
!                       for ( ; mp != NULL;
!                               mp->m_next == NULL ? (mp = mp2, mp2 = NULL)
!                                                  : (mp = mp->m_next))
!                       {
!                           /*
!                            * Only consider an entry if the first character
!                            * matches and it is for the current state.
!                            * Skip ":lmap" mappings if keys were mapped.
!                            */
!                           if (mp->m_keys[0] == c1
!                                   && (mp->m_mode & local_State)
!                                   && ((mp->m_mode & LANGMAP) == 0
!                                       || typebuf.tb_maplen == 0))
!                           {
! #ifdef FEAT_LANGMAP
!                               int     nomap = nolmaplen;
!                               int     c2;
! #endif
!                               /* find the match length of this mapping */
!                               for (mlen = 1; mlen < typebuf.tb_len; ++mlen)
!                               {
! #ifdef FEAT_LANGMAP
!                                   c2 = typebuf.tb_buf[typebuf.tb_off + mlen];
!                                   if (nomap > 0)
!                                       --nomap;
!                                   else if (c2 == K_SPECIAL)
!                                       nomap = 2;
!                                   else
!                                       LANGMAP_ADJUST(c2, TRUE);
!                                   if (mp->m_keys[mlen] != c2)
! #else
!                                   if (mp->m_keys[mlen] !=
!                                       typebuf.tb_buf[typebuf.tb_off + mlen])
! #endif
!                                       break;
!                               }
! 
!                               /* Don't allow mapping the first byte(s) of a
!                                * multi-byte char.  Happens when mapping
!                                * <M-a> and then changing 'encoding'. Beware
!                                * that 0x80 is escaped. */
!                               {
!                                   char_u *p1 = mp->m_keys;
!                                   char_u *p2 = mb_unescape(&p1);
! 
!                                   if (has_mbyte && p2 != NULL
!                                         && MB_BYTE2LEN(c1) > MB_PTR2LEN(p2))
!                                       mlen = 0;
!                               }
!                               /*
!                                * Check an entry whether it matches.
!                                * - Full match: mlen == keylen
!                                * - Partly match: mlen == typebuf.tb_len
!                                */
!                               keylen = mp->m_keylen;
!                               if (mlen == keylen
!                                    || (mlen == typebuf.tb_len
!                                                 && typebuf.tb_len < keylen))
!                               {
!                                   /*
!                                    * If only script-local mappings are
!                                    * allowed, check if the mapping starts
!                                    * with K_SNR.
!                                    */
!                                   s = typebuf.tb_noremap + typebuf.tb_off;
!                                   if (*s == RM_SCRIPT
!                                           && (mp->m_keys[0] != K_SPECIAL
!                                               || mp->m_keys[1] != KS_EXTRA
!                                               || mp->m_keys[2]
!                                                             != (int)KE_SNR))
!                                       continue;
!                                   /*
!                                    * If one of the typed keys cannot be
!                                    * remapped, skip the entry.
!                                    */
!                                   for (n = mlen; --n >= 0; )
!                                       if (*s++ & (RM_NONE|RM_ABBR))
!                                           break;
!                                   if (n >= 0)
!                                       continue;
! 
!                                   if (keylen > typebuf.tb_len)
!                                   {
!                                       if (!timedout && !(mp_match != NULL
!                                                      && mp_match->m_nowait))
!                                       {
!                                           /* break at a partly match */
!                                           keylen = KEYLEN_PART_MAP;
!                                           break;
!                                       }
!                                   }
!                                   else if (keylen > mp_match_len)
!                                   {
!                                       /* found a longer match */
!                                       mp_match = mp;
!                                       mp_match_len = keylen;
!                                   }
!                               }
!                               else
!                                   /* No match; may have to check for
!                                    * termcode at next character. */
!                                   if (max_mlen < mlen)
!                                       max_mlen = mlen;
!                           }
!                       }
! 
!                       /* If no partly match found, use the longest full
!                        * match. */
!                       if (keylen != KEYLEN_PART_MAP)
!                       {
!                           mp = mp_match;
!                           keylen = mp_match_len;
!                       }
!                   }
  
!                   /* Check for match with 'pastetoggle' */
!                   if (*p_pt != NUL && mp == NULL && (State & (INSERT|NORMAL)))
                    {
!                       for (mlen = 0; mlen < typebuf.tb_len && p_pt[mlen];
!                                                                      ++mlen)
!                           if (p_pt[mlen] != typebuf.tb_buf[typebuf.tb_off
!                                                                     + mlen])
!                                   break;
!                       if (p_pt[mlen] == NUL)  /* match */
!                       {
!                           /* write chars to script file(s) */
!                           if (mlen > typebuf.tb_maplen)
!                               gotchars(typebuf.tb_buf + typebuf.tb_off
!                                                         + typebuf.tb_maplen,
!                                                   mlen - typebuf.tb_maplen);
! 
!                           del_typebuf(mlen, 0); /* remove the chars */
!                           set_option_value((char_u *)"paste",
!                                                    (long)!p_paste, NULL, 0);
!                           if (!(State & INSERT))
!                           {
!                               msg_col = 0;
!                               msg_row = Rows - 1;
!                               msg_clr_eos();          /* clear ruler */
!                           }
!                           status_redraw_all();
!                           redraw_statuslines();
!                           showmode();
!                           setcursor();
!                           continue;
!                       }
!                       /* Need more chars for partly match. */
!                       if (mlen == typebuf.tb_len)
!                           keylen = KEYLEN_PART_KEY;
!                       else if (max_mlen < mlen)
!                           /* no match, may have to check for termcode at
!                            * next character */
!                           max_mlen = mlen + 1;
                    }
! 
!                   if ((mp == NULL || max_mlen >= mp_match_len)
!                                                && keylen != KEYLEN_PART_MAP)
                    {
-                       int     save_keylen = keylen;
- 
-                       /*
-                        * When no matching mapping found or found a
-                        * non-matching mapping that matches at least what the
-                        * matching mapping matched:
-                        * Check if we have a terminal code, when:
-                        *  mapping is allowed,
-                        *  keys have not been mapped,
-                        *  and not an ESC sequence, not in insert mode or
-                        *      p_ek is on,
-                        *  and when not timed out,
-                        */
-                       if ((no_mapping == 0 || allow_keys != 0)
-                               && (typebuf.tb_maplen == 0
-                                   || (p_remap && typebuf.tb_noremap[
-                                                  typebuf.tb_off] == RM_YES))
-                               && !timedout)
-                       {
-                           keylen = check_termcode(max_mlen + 1,
-                                                              NULL, 0, NULL);
- 
-                           /* If no termcode matched but 'pastetoggle'
-                            * matched partially it's like an incomplete key
-                            * sequence. */
-                           if (keylen == 0 && save_keylen == KEYLEN_PART_KEY)
-                               keylen = KEYLEN_PART_KEY;
- 
-                           /*
-                            * When getting a partial match, but the last
-                            * characters were not typed, don't wait for a
-                            * typed character to complete the termcode.
-                            * This helps a lot when a ":normal" command ends
-                            * in an ESC.
-                            */
-                           if (keylen < 0
-                                      && typebuf.tb_len == typebuf.tb_maplen)
-                               keylen = 0;
-                       }
-                       else
-                           keylen = 0;
-                       if (keylen == 0)        /* no matching terminal code */
-                       {
- #ifdef AMIGA                  /* check for window bounds report */
-                           if (typebuf.tb_maplen == 0 && (typebuf.tb_buf[
-                                              typebuf.tb_off] & 0xff) == CSI)
-                           {
-                               for (s = typebuf.tb_buf + typebuf.tb_off + 1;
-                                       s < typebuf.tb_buf + typebuf.tb_off
-                                                             + typebuf.tb_len
-                                  && (VIM_ISDIGIT(*s) || *s == ';'
-                                                               || *s == ' ');
-                                       ++s)
-                                   ;
-                               if (*s == 'r' || *s == '|') /* found one */
-                               {
-                                   del_typebuf((int)(s + 1 -
-                                      (typebuf.tb_buf + typebuf.tb_off)), 0);
-                                   /* get size and redraw screen */
-                                   shell_resized();
-                                   continue;
-                               }
-                               if (*s == NUL)      /* need more characters */
-                                   keylen = KEYLEN_PART_KEY;
-                           }
-                           if (keylen >= 0)
- #endif
-                             /* When there was a matching mapping and no
-                              * termcode could be replaced after another one,
-                              * use that mapping (loop around). If there was
-                              * no mapping use the character from the
-                              * typeahead buffer right here. */
-                             if (mp == NULL)
-                             {
  /*
   * get a character: 2. from the typeahead buffer
   */
!                               c = typebuf.tb_buf[typebuf.tb_off] & 255;
!                               if (advance)    /* remove chars from tb_buf */
!                               {
!                                   cmd_silent = (typebuf.tb_silent > 0);
!                                   if (typebuf.tb_maplen > 0)
!                                       KeyTyped = FALSE;
!                                   else
!                                   {
!                                       KeyTyped = TRUE;
!                                       /* write char to script file(s) */
!                                       gotchars(typebuf.tb_buf
!                                                        + typebuf.tb_off, 1);
!                                   }
!                                   KeyNoremap = typebuf.tb_noremap[
!                                                             typebuf.tb_off];
!                                   del_typebuf(1, 0);
!                               }
!                               break;      /* got character, break for loop */
!                             }
!                       }
!                       if (keylen > 0)     /* full matching terminal code */
                        {
! #if defined(FEAT_GUI) && defined(FEAT_MENU)
!                           if (typebuf.tb_len >= 2
!                               && typebuf.tb_buf[typebuf.tb_off] == K_SPECIAL
!                                        && typebuf.tb_buf[typebuf.tb_off + 1]
!                                                                  == KS_MENU)
                            {
!                               /*
!                                * Using a menu may cause a break in undo!
!                                * It's like using gotchars(), but without
!                                * recording or writing to a script file.
!                                */
!                               may_sync_undo();
!                               del_typebuf(3, 0);
!                               idx = get_menu_index(current_menu, local_State);
!                               if (idx != MENU_INDEX_INVALID)
!                               {
!                                   /*
!                                    * In Select mode and a Visual mode menu
!                                    * is used:  Switch to Visual mode
!                                    * temporarily.  Append K_SELECT to switch
!                                    * back to Select mode.
!                                    */
!                                   if (VIsual_active && VIsual_select
!                                           && (current_menu->modes & VISUAL))
!                                   {
!                                       VIsual_select = FALSE;
!                                       (void)ins_typebuf(K_SELECT_STRING,
!                                                 REMAP_NONE, 0, TRUE, FALSE);
!                                   }
!                                   ins_typebuf(current_menu->strings[idx],
!                                               current_menu->noremap[idx],
!                                               0, TRUE,
!                                                  current_menu->silent[idx]);
!                               }
                            }
! #endif /* FEAT_GUI && FEAT_MENU */
!                           continue;   /* try mapping again */
                        }
! 
!                       /* Partial match: get some more characters.  When a
!                        * matching mapping was found use that one. */
!                       if (mp == NULL || keylen < 0)
!                           keylen = KEYLEN_PART_KEY;
!                       else
!                           keylen = mp_match_len;
                    }
  
!                   /* complete match */
!                   if (keylen >= 0 && keylen <= typebuf.tb_len)
!                   {
! #ifdef FEAT_EVAL
!                       int save_m_expr;
!                       int save_m_noremap;
!                       int save_m_silent;
!                       char_u *save_m_keys;
!                       char_u *save_m_str;
! #else
! # define save_m_noremap mp->m_noremap
! # define save_m_silent mp->m_silent
! #endif
! 
!                       /* write chars to script file(s) */
!                       if (keylen > typebuf.tb_maplen)
!                           gotchars(typebuf.tb_buf + typebuf.tb_off
!                                                         + typebuf.tb_maplen,
!                                                 keylen - typebuf.tb_maplen);
! 
!                       cmd_silent = (typebuf.tb_silent > 0);
!                       del_typebuf(keylen, 0); /* remove the mapped keys */
! 
!                       /*
!                        * Put the replacement string in front of mapstr.
!                        * The depth check catches ":map x y" and ":map y x".
!                        */
!                       if (++mapdepth >= p_mmd)
!                       {
!                           emsg(_("E223: recursive mapping"));
!                           if (State & CMDLINE)
!                               redrawcmdline();
!                           else
!                               setcursor();
!                           flush_buffers(FLUSH_MINIMAL);
!                           mapdepth = 0;       /* for next one */
!                           c = -1;
!                           break;
!                       }
! 
!                       /*
!                        * In Select mode and a Visual mode mapping is used:
!                        * Switch to Visual mode temporarily.  Append K_SELECT
!                        * to switch back to Select mode.
!                        */
!                       if (VIsual_active && VIsual_select
!                                                    && (mp->m_mode & VISUAL))
!                       {
!                           VIsual_select = FALSE;
!                           (void)ins_typebuf(K_SELECT_STRING, REMAP_NONE,
!                                                             0, TRUE, FALSE);
!                       }
! 
! #ifdef FEAT_EVAL
!                       /* Copy the values from *mp that are used, because
!                        * evaluating the expression may invoke a function
!                        * that redefines the mapping, thereby making *mp
!                        * invalid. */
!                       save_m_expr = mp->m_expr;
!                       save_m_noremap = mp->m_noremap;
!                       save_m_silent = mp->m_silent;
!                       save_m_keys = NULL;  /* only saved when needed */
!                       save_m_str = NULL;  /* only saved when needed */
! 
!                       /*
!                        * Handle ":map <expr>": evaluate the {rhs} as an
!                        * expression.  Also save and restore the command line
!                        * for "normal :".
!                        */
!                       if (mp->m_expr)
!                       {
!                           int save_vgetc_busy = vgetc_busy;
!                           int save_may_garbage_collect = may_garbage_collect;
! 
!                           vgetc_busy = 0;
!                           may_garbage_collect = FALSE;
! 
!                           save_m_keys = vim_strsave(mp->m_keys);
!                           save_m_str = vim_strsave(mp->m_str);
!                           s = eval_map_expr(save_m_str, NUL);
! 
!                           vgetc_busy = save_vgetc_busy;
!                           may_garbage_collect = save_may_garbage_collect;
!                       }
!                       else
! #endif
!                           s = mp->m_str;
! 
!                       /*
!                        * Insert the 'to' part in the typebuf.tb_buf.
!                        * If 'from' field is the same as the start of the
!                        * 'to' field, don't remap the first character (but do
!                        * allow abbreviations).
!                        * If m_noremap is set, don't remap the whole 'to'
!                        * part.
!                        */
!                       if (s == NULL)
!                           i = FAIL;
!                       else
!                       {
!                           int noremap;
! 
!                           if (save_m_noremap != REMAP_YES)
!                               noremap = save_m_noremap;
!                           else if (
! #ifdef FEAT_EVAL
!                               STRNCMP(s, save_m_keys != NULL
!                                                  ? save_m_keys : mp->m_keys,
!                                                        (size_t)keylen)
! #else
!                               STRNCMP(s, mp->m_keys, (size_t)keylen)
! #endif
!                                  != 0)
!                               noremap = REMAP_YES;
!                           else
!                               noremap = REMAP_SKIP;
!                           i = ins_typebuf(s, noremap,
!                                       0, TRUE, cmd_silent || save_m_silent);
! #ifdef FEAT_EVAL
!                           if (save_m_expr)
!                               vim_free(s);
! #endif
!                       }
! #ifdef FEAT_EVAL
!                       vim_free(save_m_keys);
!                       vim_free(save_m_str);
! #endif
!                       if (i == FAIL)
!                       {
!                           c = -1;
!                           break;
!                       }
!                       continue;
!                   }
                }
  
  /*
--- 2584,2629 ----
                else if (typebuf.tb_len > 0)
                {
                    /*
!                    * Check for a mapping in "typebuf".
                     */
!                   map_result_T result = handle_mapping(
!                                               &keylen, &timedout, &mapdepth);
  
!                   if (result == map_result_retry)
!                       // try mapping again
!                       continue;
!                   if (result == map_result_fail)
                    {
!                       // failed, use the outer loop
!                       c = -1;
!                       break;
                    }
!                   if (result == map_result_get)
                    {
  /*
   * get a character: 2. from the typeahead buffer
   */
!                       c = typebuf.tb_buf[typebuf.tb_off] & 255;
!                       if (advance)    /* remove chars from tb_buf */
                        {
!                           cmd_silent = (typebuf.tb_silent > 0);
!                           if (typebuf.tb_maplen > 0)
!                               KeyTyped = FALSE;
!                           else
                            {
!                               KeyTyped = TRUE;
!                               /* write char to script file(s) */
!                               gotchars(typebuf.tb_buf
!                                                + typebuf.tb_off, 1);
                            }
!                           KeyNoremap = typebuf.tb_noremap[
!                                                     typebuf.tb_off];
!                           del_typebuf(1, 0);
                        }
!                       break;
                    }
  
!                   // not enough characters, get more
                }
  
  /*
*** ../vim-8.1.1796/src/version.c       2019-08-03 13:50:04.562299913 +0200
--- src/version.c       2019-08-03 14:23:10.987633555 +0200
***************
*** 775,776 ****
--- 775,778 ----
  {   /* Add new patch number below this line */
+ /**/
+     1797,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
15. Your heart races faster and beats irregularly each time you see a new WWW
    site address in print or on TV, even though you've never had heart
    problems before.

 /// 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/201908031224.x73CO5GW027137%40masaka.moolenaar.net.

Raspunde prin e-mail lui