To: vim_dev@googlegroups.com Subject: Patch 8.1.1794 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.1794 (after 8.1.1792) Problem: Tests are flaky. Solution: Undo the change to vgetorpeek(). Files: src/getchar.c *** ../vim-8.1.1793/src/getchar.c 2019-08-02 21:35:29.880442605 +0200 --- src/getchar.c 2019-08-02 22:39:50.475860854 +0200 *************** *** 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; - 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 - // 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 ": 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!) */ --- 1900,1905 ---- *************** *** 2466,2483 **** --- 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; *************** *** 2495,2500 **** --- 1986,1993 ---- if (vgetc_busy > 0 && ex_normal_busy == 0) return NUL; + local_State = get_real_state(); + ++vgetc_busy; if (advance) *************** *** 2539,2546 **** */ for (;;) { ! long wait_time; ! int keylen = 0; /* * ui_breakcheck() is slow, don't use it too often when --- 2032,2038 ---- */ for (;;) { ! long wait_time; /* * ui_breakcheck() is slow, don't use it too often when *************** *** 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. --- 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. *************** *** 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 } /* --- 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 ! * 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 ": 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; ! } } /* *** ../vim-8.1.1793/src/version.c 2019-08-02 22:08:21.201361921 +0200 --- src/version.c 2019-08-02 22:40:15.227708490 +0200 *************** *** 775,776 **** --- 775,778 ---- { /* Add new patch number below this line */ + /**/ + 1794, /**/ -- hundred-and-one symptoms of being an internet addict: 10. And even your night dreams are in HTML. /// Bram Moolenaar -- Bram@Moolenaar.net -- 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 ///