To: vim_dev@googlegroups.com Subject: Patch 8.2.4221 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.4221 Problem: Some functions in normal.c are very long. Solution: Move code to separate functions. (Yegappan Lakshmanan, closes #9628) Files: src/normal.c *** ../vim-8.2.4220/src/normal.c 2022-01-24 16:30:26.564796202 +0000 --- src/normal.c 2022-01-26 12:11:01.174012265 +0000 *************** *** 627,634 **** * Return the updated command index (if changed). */ static int ! normal_cmd_get_more_chars(int idx, cmdarg_T *cap, int *need_flushbuf UNUSED) { int c; int *cp; int repl = FALSE; // get character for replace mode --- 627,638 ---- * Return the updated command index (if changed). */ static int ! normal_cmd_get_more_chars( ! int idx_arg, ! cmdarg_T *cap, ! int *need_flushbuf UNUSED) { + int idx = idx_arg; int c; int *cp; int repl = FALSE; // get character for replace mode *************** *** 779,788 **** #endif } ! /* ! * When the next character is CTRL-\ a following CTRL-N means the ! * command is aborted and we go to Normal mode. ! */ if (cp == &cap->extra_char && cap->nchar == Ctrl_BSL && (cap->extra_char == Ctrl_N || cap->extra_char == Ctrl_G)) --- 783,790 ---- #endif } ! // When the next character is CTRL-\ a following CTRL-N means the ! // command is aborted and we go to Normal mode. if (cp == &cap->extra_char && cap->nchar == Ctrl_BSL && (cap->extra_char == Ctrl_N || cap->extra_char == Ctrl_G)) *************** *** 854,869 **** static int normal_cmd_need_to_wait_for_msg(cmdarg_T *cap, pos_T *old_pos) { ! /* ! * In Visual mode and with "^O" in Insert mode, a short message will be ! * overwritten by the mode message. Wait a bit, until a key is hit. ! * In Visual mode, it's more important to keep the Visual area updated ! * than keeping a message (e.g. from a /pat search). ! * Only do this if the command was typed, not from a mapping. ! * Don't wait when emsg_silent is non-zero. ! * Also wait a bit after an error message, e.g. for "^O:". ! * Don't redraw the screen, it would remove the message. ! */ return ( ((p_smd && msg_silent == 0 && (restart_edit != 0 --- 856,869 ---- static int normal_cmd_need_to_wait_for_msg(cmdarg_T *cap, pos_T *old_pos) { ! // In Visual mode and with "^O" in Insert mode, a short message will be ! // overwritten by the mode message. Wait a bit, until a key is hit. ! // In Visual mode, it's more important to keep the Visual area updated ! // than keeping a message (e.g. from a /pat search). ! // Only do this if the command was typed, not from a mapping. ! // Don't wait when emsg_silent is non-zero. ! // Also wait a bit after an error message, e.g. for "^O:". ! // Don't redraw the screen, it would remove the message. return ( ((p_smd && msg_silent == 0 && (restart_edit != 0 *************** *** 968,978 **** // remembered in "opcount". ca.opcount = opcount; ! /* ! * If there is an operator pending, then the command we take this time ! * will terminate it. Finish_op tells us to finish the operation before ! * returning this time (unless the operation was cancelled). ! */ #ifdef CURSOR_SHAPE c = finish_op; #endif --- 968,976 ---- // remembered in "opcount". ca.opcount = opcount; ! // If there is an operator pending, then the command we take this time ! // will terminate it. Finish_op tells us to finish the operation before ! // returning this time (unless the operation was cancelled). #ifdef CURSOR_SHAPE c = finish_op; #endif *************** *** 1030,1040 **** c = safe_vgetc(); LANGMAP_ADJUST(c, get_real_state() != SELECTMODE); ! /* ! * If a mapping was started in Visual or Select mode, remember the length ! * of the mapping. This is used below to not return to Insert mode for as ! * long as the mapping is being executed. ! */ if (restart_edit == 0) old_mapped_len = 0; else if (old_mapped_len --- 1028,1036 ---- c = safe_vgetc(); LANGMAP_ADJUST(c, get_real_state() != SELECTMODE); ! // If a mapping was started in Visual or Select mode, remember the length ! // of the mapping. This is used below to not return to Insert mode for as ! // long as the mapping is being executed. if (restart_edit == 0) old_mapped_len = 0; else if (old_mapped_len *************** *** 1044,1052 **** if (c == NUL) c = K_ZERO; ! /* ! * In Select mode, typed text replaces the selection. ! */ if (VIsual_active && VIsual_select && (vim_isprintc(c) || c == NL || c == CAR || c == K_KENTER)) --- 1040,1046 ---- if (c == NUL) c = K_ZERO; ! // In Select mode, typed text replaces the selection. if (VIsual_active && VIsual_select && (vim_isprintc(c) || c == NL || c == CAR || c == K_KENTER)) *************** *** 1085,1094 **** c = normal_cmd_get_count(&ca, c, toplevel, set_prevcount, &ctrl_w, &need_flushbuf); ! /* ! * Find the command character in the table of commands. ! * For CTRL-W we already got nchar when looking for a count. ! */ if (ctrl_w) { ca.nchar = c; --- 1079,1086 ---- c = normal_cmd_get_count(&ca, c, toplevel, set_prevcount, &ctrl_w, &need_flushbuf); ! // Find the command character in the table of commands. ! // For CTRL-W we already got nchar when looking for a count. if (ctrl_w) { ca.nchar = c; *************** *** 1114,1122 **** if ((nv_cmds[idx].cmd_flags & NV_NCW) && curbuf_locked()) goto normal_end; ! /* ! * In Visual/Select mode, a few keys are handled in a special way. ! */ if (VIsual_active) { // when 'keymodel' contains "stopsel" may stop Select/Visual mode --- 1106,1112 ---- if ((nv_cmds[idx].cmd_flags & NV_NCW) && curbuf_locked()) goto normal_end; ! // In Visual/Select mode, a few keys are handled in a special way. if (VIsual_active) { // when 'keymodel' contains "stopsel" may stop Select/Visual mode *************** *** 1177,1188 **** idx = normal_cmd_get_more_chars(idx, &ca, &need_flushbuf); #ifdef FEAT_CMDL_INFO ! /* ! * Flush the showcmd characters onto the screen so we can see them while ! * the command is being executed. Only do this when the shown command was ! * actually displayed, otherwise this will slow down a lot when executing ! * mappings. ! */ if (need_flushbuf) out_flush(); #endif --- 1167,1176 ---- idx = normal_cmd_get_more_chars(idx, &ca, &need_flushbuf); #ifdef FEAT_CMDL_INFO ! // Flush the showcmd characters onto the screen so we can see them while ! // the command is being executed. Only do this when the shown command was ! // actually displayed, otherwise this will slow down a lot when executing ! // mappings. if (need_flushbuf) out_flush(); #endif *************** *** 1230,1246 **** } } ! /* ! * Execute the command! ! * Call the command function found in the commands table. ! */ ca.arg = nv_cmds[idx].cmd_arg; (nv_cmds[idx].cmd_func)(&ca); ! /* ! * If we didn't start or finish an operator, reset oap->regname, unless we ! * need it later. ! */ if (!finish_op && !oap->op_type && (idx < 0 || !(nv_cmds[idx].cmd_flags & NV_KEEPREG))) --- 1218,1230 ---- } } ! // Execute the command! ! // Call the command function found in the commands table. ca.arg = nv_cmds[idx].cmd_arg; (nv_cmds[idx].cmd_func)(&ca); ! // If we didn't start or finish an operator, reset oap->regname, unless we ! // need it later. if (!finish_op && !oap->op_type && (idx < 0 || !(nv_cmds[idx].cmd_flags & NV_KEEPREG))) *************** *** 1256,1265 **** if (old_mapped_len > 0) old_mapped_len = typebuf_maplen(); ! /* ! * If an operation is pending, handle it. But not for K_IGNORE or ! * K_MOUSEMOVE. ! */ if (ca.cmdchar != K_IGNORE && ca.cmdchar != K_MOUSEMOVE) do_pending_operator(&ca, old_col, FALSE); --- 1240,1247 ---- if (old_mapped_len > 0) old_mapped_len = typebuf_maplen(); ! // If an operation is pending, handle it. But not for K_IGNORE or ! // K_MOUSEMOVE. if (ca.cmdchar != K_IGNORE && ca.cmdchar != K_MOUSEMOVE) do_pending_operator(&ca, old_col, FALSE); *************** *** 1268,1356 **** if (normal_cmd_need_to_wait_for_msg(&ca, &old_pos)) normal_cmd_wait_for_msg(); ! /* ! * Wait for a moment when a message is displayed that will be overwritten ! * by the mode message. ! * In Visual mode and with "^O" in Insert mode, a short message will be ! * overwritten by the mode message. Wait a bit, until a key is hit. ! * In Visual mode, it's more important to keep the Visual area updated ! * than keeping a message (e.g. from a /pat search). ! * Only do this if the command was typed, not from a mapping. ! * Don't wait when emsg_silent is non-zero. ! * Also wait a bit after an error message, e.g. for "^O:". ! * Don't redraw the screen, it would remove the message. ! */ ! if ( ((p_smd ! && msg_silent == 0 ! && (restart_edit != 0 ! || (VIsual_active ! && old_pos.lnum == curwin->w_cursor.lnum ! && old_pos.col == curwin->w_cursor.col) ! ) ! && (clear_cmdline ! || redraw_cmdline) ! && (msg_didout || (msg_didany && msg_scroll)) ! && !msg_nowait ! && KeyTyped) ! || (restart_edit != 0 ! && !VIsual_active ! && (msg_scroll ! || emsg_on_display))) ! && oap->regname == 0 ! && !(ca.retval & CA_COMMAND_BUSY) ! && stuff_empty() ! && typebuf_typed() ! && emsg_silent == 0 ! && !in_assert_fails ! && !did_wait_return ! && oap->op_type == OP_NOP) ! { ! int save_State = State; ! ! // Draw the cursor with the right shape here ! if (restart_edit != 0) ! State = INSERT; ! ! // If need to redraw, and there is a "keep_msg", redraw before the ! // delay ! if (must_redraw && keep_msg != NULL && !emsg_on_display) ! { ! char_u *kmsg; ! ! kmsg = keep_msg; ! keep_msg = NULL; ! // Showmode() will clear keep_msg, but we want to use it anyway. ! // First update w_topline. ! setcursor(); ! update_screen(0); ! // now reset it, otherwise it's put in the history again ! keep_msg = kmsg; ! ! kmsg = vim_strsave(keep_msg); ! if (kmsg != NULL) ! { ! msg_attr((char *)kmsg, keep_msg_attr); ! vim_free(kmsg); ! } ! } ! setcursor(); ! #ifdef CURSOR_SHAPE ! ui_cursor_shape(); // may show different cursor shape ! #endif ! cursor_on(); ! out_flush(); ! if (msg_scroll || emsg_on_display) ! ui_delay(1003L, TRUE); // wait at least one second ! ui_delay(3003L, FALSE); // wait up to three seconds ! State = save_State; ! ! msg_scroll = FALSE; ! emsg_on_display = FALSE; ! } ! ! /* ! * Finish up after executing a Normal mode command. ! */ normal_end: msg_nowait = FALSE; --- 1250,1256 ---- if (normal_cmd_need_to_wait_for_msg(&ca, &old_pos)) normal_cmd_wait_for_msg(); ! // Finish up after executing a Normal mode command. normal_end: msg_nowait = FALSE; *************** *** 1408,1418 **** restart_edit = 0; #endif ! /* ! * May restart edit(), if we got here with CTRL-O in Insert mode (but not ! * if still inside a mapping that started in Visual mode). ! * May switch from Visual to Select mode after CTRL-O command. ! */ if ( oap->op_type == OP_NOP && ((restart_edit != 0 && !VIsual_active && old_mapped_len == 0) || restart_VIsual_select == 1) --- 1308,1316 ---- restart_edit = 0; #endif ! // May restart edit(), if we got here with CTRL-O in Insert mode (but not ! // if still inside a mapping that started in Visual mode). ! // May switch from Visual to Select mode after CTRL-O command. if ( oap->op_type == OP_NOP && ((restart_edit != 0 && !VIsual_active && old_mapped_len == 0) || restart_VIsual_select == 1) *************** *** 1510,1521 **** end_visual_mode_keep_button() { #ifdef FEAT_CLIPBOARD ! /* ! * If we are using the clipboard, then remember what was selected in case ! * we need to paste it somewhere while we still own the selection. ! * Only do this when the clipboard is already owned. Don't want to grab ! * the selection when hitting ESC. ! */ if (clip_star.available && clip_star.owned) clip_auto_select(); --- 1408,1417 ---- end_visual_mode_keep_button() { #ifdef FEAT_CLIPBOARD ! // If we are using the clipboard, then remember what was selected in case ! // we need to paste it somewhere while we still own the selection. ! // Only do this when the clipboard is already owned. Don't want to grab ! // the selection when hitting ESC. if (clip_star.available && clip_star.owned) clip_auto_select(); *************** *** 1678,1687 **** int prevcol; int bn = 0; // bracket nesting ! /* ! * if i == 0: try to find an identifier ! * if i == 1: try to find any non-white text ! */ ptr = ml_get_buf(wp->w_buffer, lnum, FALSE); for (i = (find_type & FIND_IDENT) ? 0 : 1; i < 2; ++i) { --- 1574,1581 ---- int prevcol; int bn = 0; // bracket nesting ! // if i == 0: try to find an identifier ! // if i == 1: try to find any non-white text ptr = ml_get_buf(wp->w_buffer, lnum, FALSE); for (i = (find_type & FIND_IDENT) ? 0 : 1; i < 2; ++i) { *************** *** 2200,2209 **** showcmd_is_clear = FALSE; } ! /* ! * clear the rest of an old message by outputting up to SHOWCMD_COLS ! * spaces ! */ screen_puts((char_u *)" " + len, (int)Rows - 1, sc_col + len, 0); setcursor(); // put cursor back where it belongs --- 2094,2101 ---- showcmd_is_clear = FALSE; } ! // clear the rest of an old message by outputting up to SHOWCMD_COLS ! // spaces screen_puts((char_u *)" " + len, (int)Rows - 1, sc_col + len, 0); setcursor(); // put cursor back where it belongs *************** *** 2234,2244 **** did_syncbind = FALSE; else if (curwin == old_curwin) { ! /* ! * Synchronize other windows, as necessary according to ! * 'scrollbind'. Don't do this after an ":edit" command, except ! * when 'diff' is set. ! */ if ((curwin->w_buffer == old_buf #ifdef FEAT_DIFF || curwin->w_p_diff --- 2126,2134 ---- did_syncbind = FALSE; else if (curwin == old_curwin) { ! // Synchronize other windows, as necessary according to ! // 'scrollbind'. Don't do this after an ":edit" command, except ! // when 'diff' is set. if ((curwin->w_buffer == old_buf #ifdef FEAT_DIFF || curwin->w_p_diff *************** *** 2256,2271 **** } else if (vim_strchr(p_sbo, 'j')) // jump flag set in 'scrollopt' { ! /* ! * When switching between windows, make sure that the relative ! * vertical offset is valid for the new window. The relative ! * offset is invalid whenever another 'scrollbind' window has ! * scrolled to a point that would force the current window to ! * scroll past the beginning or end of its buffer. When the ! * resync is performed, some of the other 'scrollbind' windows may ! * need to jump so that the current window's relative position is ! * visible on-screen. ! */ check_scrollbind(curwin->w_topline - curwin->w_scbind_pos, 0L); } curwin->w_scbind_pos = curwin->w_topline; --- 2146,2159 ---- } else if (vim_strchr(p_sbo, 'j')) // jump flag set in 'scrollopt' { ! // When switching between windows, make sure that the relative ! // vertical offset is valid for the new window. The relative ! // offset is invalid whenever another 'scrollbind' window has ! // scrolled to a point that would force the current window to ! // scroll past the beginning or end of its buffer. When the ! // resync is performed, some of the other 'scrollbind' windows may ! // need to jump so that the current window's relative position is ! // visible on-screen. check_scrollbind(curwin->w_topline - curwin->w_scbind_pos, 0L); } curwin->w_scbind_pos = curwin->w_topline; *************** *** 2298,2315 **** long topline; long y; ! /* ! * check 'scrollopt' string for vertical and horizontal scroll options ! */ want_ver = (vim_strchr(p_sbo, 'v') && topline_diff != 0); #ifdef FEAT_DIFF want_ver |= old_curwin->w_p_diff; #endif want_hor = (vim_strchr(p_sbo, 'h') && (leftcol_diff || topline_diff != 0)); ! /* ! * loop through the scrollbound windows and scroll accordingly ! */ VIsual_select = VIsual_active = 0; FOR_ALL_WINDOWS(curwin) { --- 2186,2199 ---- long topline; long y; ! // check 'scrollopt' string for vertical and horizontal scroll options want_ver = (vim_strchr(p_sbo, 'v') && topline_diff != 0); #ifdef FEAT_DIFF want_ver |= old_curwin->w_p_diff; #endif want_hor = (vim_strchr(p_sbo, 'h') && (leftcol_diff || topline_diff != 0)); ! // loop through the scrollbound windows and scroll accordingly VIsual_select = VIsual_active = 0; FOR_ALL_WINDOWS(curwin) { *************** *** 2317,2325 **** // skip original window and windows with 'noscrollbind' if (curwin != old_curwin && curwin->w_p_scb) { ! /* ! * do the vertical scroll ! */ if (want_ver) { #ifdef FEAT_DIFF --- 2201,2207 ---- // skip original window and windows with 'noscrollbind' if (curwin != old_curwin && curwin->w_p_scb) { ! // do the vertical scroll if (want_ver) { #ifdef FEAT_DIFF *************** *** 2349,2357 **** curwin->w_redr_status = TRUE; } ! /* ! * do the horizontal scroll ! */ if (want_hor && curwin->w_leftcol != tgt_leftcol) { curwin->w_leftcol = tgt_leftcol; --- 2231,2237 ---- curwin->w_redr_status = TRUE; } ! // do the horizontal scroll if (want_hor && curwin->w_leftcol != tgt_leftcol) { curwin->w_leftcol = tgt_leftcol; *************** *** 2360,2368 **** } } ! /* ! * reset current-window ! */ VIsual_select = old_VIsual_select; VIsual_active = old_VIsual_active; curwin = old_curwin; --- 2240,2246 ---- } } ! // reset current-window VIsual_select = old_VIsual_select; VIsual_active = old_VIsual_active; curwin = old_curwin; *************** *** 2569,2579 **** p_ws = FALSE; // don't wrap around end of file now p_scs = FALSE; // don't switch ignorecase off now ! /* ! * With "gD" go to line 1. ! * With "gd" Search back for the start of the current function, then go ! * back until a blank line. If this fails go to line 1. ! */ if (!locally || !findpar(&incll, BACKWARD, 1L, '{', FALSE)) { setpcmark(); // Set in findpar() otherwise --- 2447,2455 ---- p_ws = FALSE; // don't wrap around end of file now p_scs = FALSE; // don't switch ignorecase off now ! // With "gD" go to line 1. ! // With "gd" Search back for the start of the current function, then go ! // back until a blank line. If this fails go to line 1. if (!locally || !findpar(&incll, BACKWARD, 1L, '{', FALSE)) { setpcmark(); // Set in findpar() otherwise *************** *** 2714,2723 **** if (curwin->w_width != 0) { ! /* ! * Instead of sticking at the last character of the buffer line we ! * try to stick in the last column of the screen. ! */ if (curwin->w_curswant == MAXCOL) { atend = TRUE; --- 2590,2597 ---- if (curwin->w_width != 0) { ! // Instead of sticking at the last character of the buffer line we ! // try to stick in the last column of the screen. if (curwin->w_curswant == MAXCOL) { atend = TRUE; *************** *** 2828,2838 **** colnr_T virtcol; int c; ! /* ! * Check for landing on a character that got split at the end of the ! * last line. We want to advance a screenline, not end up in the same ! * screenline or move two screenlines. ! */ validate_virtcol(); virtcol = curwin->w_virtcol; #if defined(FEAT_LINEBREAK) --- 2702,2710 ---- colnr_T virtcol; int c; ! // Check for landing on a character that got split at the end of the ! // last line. We want to advance a screenline, not end up in the same ! // screenline or move two screenlines. validate_virtcol(); virtcol = curwin->w_virtcol; #if defined(FEAT_LINEBREAK) *************** *** 2929,2934 **** --- 2801,2930 ---- } /* + * Get the count specified after a 'z' command. Returns TRUE to process + * the 'z' command and FALSE to skip it. + */ + static int + nv_z_get_count(cmdarg_T *cap, int *nchar_arg) + { + int nchar = *nchar_arg; + long n; + + // "z123{nchar}": edit the count before obtaining {nchar} + if (checkclearop(cap->oap)) + return FALSE; + n = nchar - '0'; + + for (;;) + { + #ifdef USE_ON_FLY_SCROLL + dont_scroll = TRUE; // disallow scrolling here + #endif + ++no_mapping; + ++allow_keys; // no mapping for nchar, but allow key codes + nchar = plain_vgetc(); + LANGMAP_ADJUST(nchar, TRUE); + --no_mapping; + --allow_keys; + #ifdef FEAT_CMDL_INFO + (void)add_to_showcmd(nchar); + #endif + if (nchar == K_DEL || nchar == K_KDEL) + n /= 10; + else if (VIM_ISDIGIT(nchar)) + n = n * 10 + (nchar - '0'); + else if (nchar == CAR) + { + #ifdef FEAT_GUI + need_mouse_correct = TRUE; + #endif + win_setheight((int)n); + break; + } + else if (nchar == 'l' + || nchar == 'h' + || nchar == K_LEFT + || nchar == K_RIGHT) + { + cap->count1 = n ? n * cap->count1 : cap->count1; + *nchar_arg = nchar; + return TRUE; + } + else + { + clearopbeep(cap->oap); + break; + } + } + cap->oap->op_type = OP_NOP; + return FALSE; + } + + #ifdef FEAT_SPELL + /* + * "zug" and "zuw": undo "zg" and "zw" + * "zg": add good word to word list + * "zw": add wrong word to word list + * "zG": add good word to temp word list + * "zW": add wrong word to temp word list + */ + static int + nv_zg_zw(cmdarg_T *cap, int nchar) + { + char_u *ptr = NULL; + int len; + int undo = FALSE; + + if (nchar == 'u') + { + ++no_mapping; + ++allow_keys; // no mapping for nchar, but allow key codes + nchar = plain_vgetc(); + LANGMAP_ADJUST(nchar, TRUE); + --no_mapping; + --allow_keys; + #ifdef FEAT_CMDL_INFO + (void)add_to_showcmd(nchar); + #endif + if (vim_strchr((char_u *)"gGwW", nchar) == NULL) + { + clearopbeep(cap->oap); + return OK; + } + undo = TRUE; + } + + if (checkclearop(cap->oap)) + return OK; + if (VIsual_active && get_visual_text(cap, &ptr, &len) == FAIL) + return FAIL; + if (ptr == NULL) + { + pos_T pos = curwin->w_cursor; + + // Find bad word under the cursor. When 'spell' is + // off this fails and find_ident_under_cursor() is + // used below. + emsg_off++; + len = spell_move_to(curwin, FORWARD, TRUE, TRUE, NULL); + emsg_off--; + if (len != 0 && curwin->w_cursor.col <= pos.col) + ptr = ml_get_pos(&curwin->w_cursor); + curwin->w_cursor = pos; + } + + if (ptr == NULL + && (len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0) + return FAIL; + spell_add_word(ptr, len, nchar == 'w' || nchar == 'W' + ? SPELL_ADD_BAD : SPELL_ADD_GOOD, + (nchar == 'G' || nchar == 'W') ? 0 : (int)cap->count1, undo); + + return OK; + } + #endif + + /* * Commands that start with "z". */ static void *************** *** 2941,3004 **** long old_fdl = curwin->w_p_fdl; int old_fen = curwin->w_p_fen; #endif - #ifdef FEAT_SPELL - int undo = FALSE; - #endif long siso = get_sidescrolloff_value(); ! if (VIM_ISDIGIT(nchar)) ! { ! /* ! * "z123{nchar}": edit the count before obtaining {nchar} ! */ ! if (checkclearop(cap->oap)) return; - n = nchar - '0'; - for (;;) - { - #ifdef USE_ON_FLY_SCROLL - dont_scroll = TRUE; // disallow scrolling here - #endif - ++no_mapping; - ++allow_keys; // no mapping for nchar, but allow key codes - nchar = plain_vgetc(); - LANGMAP_ADJUST(nchar, TRUE); - --no_mapping; - --allow_keys; - #ifdef FEAT_CMDL_INFO - (void)add_to_showcmd(nchar); - #endif - if (nchar == K_DEL || nchar == K_KDEL) - n /= 10; - else if (VIM_ISDIGIT(nchar)) - n = n * 10 + (nchar - '0'); - else if (nchar == CAR) - { - #ifdef FEAT_GUI - need_mouse_correct = TRUE; - #endif - win_setheight((int)n); - break; - } - else if (nchar == 'l' - || nchar == 'h' - || nchar == K_LEFT - || nchar == K_RIGHT) - { - cap->count1 = n ? n * cap->count1 : cap->count1; - goto dozet; - } - else - { - clearopbeep(cap->oap); - break; - } - } - cap->oap->op_type = OP_NOP; - return; - } - dozet: if ( #ifdef FEAT_FOLDING // "zf" and "zF" are always an operator, "zd", "zo", "zO", "zc" --- 2937,2947 ---- long old_fdl = curwin->w_p_fdl; int old_fen = curwin->w_p_fen; #endif long siso = get_sidescrolloff_value(); ! if (VIM_ISDIGIT(nchar) && !nv_z_get_count(cap, &nchar)) return; if ( #ifdef FEAT_FOLDING // "zf" and "zF" are always an operator, "zd", "zo", "zO", "zc" *************** *** 3012,3021 **** checkclearop(cap->oap)) return; ! /* ! * For "z+", "z", "zt", "z.", "zz", "z^", "z-", "zb": ! * If line number given, set cursor. ! */ if ((vim_strchr((char_u *)"+\r\nt.z^-b", nchar) != NULL) && cap->count0 && cap->count0 != curwin->w_cursor.lnum) --- 2955,2962 ---- checkclearop(cap->oap)) return; ! // For "z+", "z", "zt", "z.", "zz", "z^", "z-", "zb": ! // If line number given, set cursor. if ((vim_strchr((char_u *)"+\r\nt.z^-b", nchar) != NULL) && cap->count0 && cap->count0 != curwin->w_cursor.lnum) *************** *** 3337,3396 **** #ifdef FEAT_SPELL case 'u': // "zug" and "zuw": undo "zg" and "zw" - ++no_mapping; - ++allow_keys; // no mapping for nchar, but allow key codes - nchar = plain_vgetc(); - LANGMAP_ADJUST(nchar, TRUE); - --no_mapping; - --allow_keys; - #ifdef FEAT_CMDL_INFO - (void)add_to_showcmd(nchar); - #endif - if (vim_strchr((char_u *)"gGwW", nchar) == NULL) - { - clearopbeep(cap->oap); - break; - } - undo = TRUE; - // FALLTHROUGH - case 'g': // "zg": add good word to word list case 'w': // "zw": add wrong word to word list case 'G': // "zG": add good word to temp word list case 'W': // "zW": add wrong word to temp word list ! { ! char_u *ptr = NULL; ! int len; ! ! if (checkclearop(cap->oap)) ! break; ! if (VIsual_active && get_visual_text(cap, &ptr, &len) ! == FAIL) ! return; ! if (ptr == NULL) ! { ! pos_T pos = curwin->w_cursor; ! ! // Find bad word under the cursor. When 'spell' is ! // off this fails and find_ident_under_cursor() is ! // used below. ! emsg_off++; ! len = spell_move_to(curwin, FORWARD, TRUE, TRUE, NULL); ! emsg_off--; ! if (len != 0 && curwin->w_cursor.col <= pos.col) ! ptr = ml_get_pos(&curwin->w_cursor); ! curwin->w_cursor = pos; ! } ! ! if (ptr == NULL && (len = find_ident_under_cursor(&ptr, ! FIND_IDENT)) == 0) ! return; ! spell_add_word(ptr, len, nchar == 'w' || nchar == 'W' ! ? SPELL_ADD_BAD : SPELL_ADD_GOOD, ! (nchar == 'G' || nchar == 'W') ! ? 0 : (int)cap->count1, ! undo); ! } break; case '=': // "z=": suggestions for a badly spelled word --- 3278,3289 ---- #ifdef FEAT_SPELL case 'u': // "zug" and "zuw": undo "zg" and "zw" case 'g': // "zg": add good word to word list case 'w': // "zw": add wrong word to word list case 'G': // "zG": add good word to temp word list case 'W': // "zW": add wrong word to temp word list ! if (nv_zg_zw(cap, nchar) == FAIL) ! return; break; case '=': // "z=": suggestions for a badly spelled word *************** *** 3537,3545 **** static void nv_exmode(cmdarg_T *cap) { ! /* ! * Ignore 'Q' in Visual mode, just give a beep. ! */ if (VIsual_active) vim_beep(BO_EX); else if (!checkclearop(cap->oap)) --- 3430,3436 ---- static void nv_exmode(cmdarg_T *cap) { ! // Ignore 'Q' in Visual mode, just give a beep. if (VIsual_active) vim_beep(BO_EX); else if (!checkclearop(cap->oap)) *************** *** 3751,3756 **** --- 3642,3723 ---- } /* + * 'K' normal-mode command. Get the command to lookup the keyword under the + * cursor. + */ + static int + nv_K_getcmd( + cmdarg_T *cap, + char_u *kp, + int kp_help, + int kp_ex, + char_u **ptr_arg, + int n, + char_u *buf, + unsigned buflen) + { + char_u *ptr = *ptr_arg; + int isman; + int isman_s; + + if (kp_help) + { + // in the help buffer + STRCPY(buf, "he! "); + return n; + } + + if (kp_ex) + { + // 'keywordprog' is an ex command + if (cap->count0 != 0) + vim_snprintf((char *)buf, buflen, "%s %ld", kp, cap->count0); + else + STRCPY(buf, kp); + STRCAT(buf, " "); + return n; + } + + // An external command will probably use an argument starting + // with "-" as an option. To avoid trouble we skip the "-". + while (*ptr == '-' && n > 0) + { + ++ptr; + --n; + } + if (n == 0) + { + // found dashes only + emsg(_(e_no_identifier_under_cursor)); + vim_free(buf); + *ptr_arg = ptr; + return 0; + } + + // When a count is given, turn it into a range. Is this + // really what we want? + isman = (STRCMP(kp, "man") == 0); + isman_s = (STRCMP(kp, "man -s") == 0); + if (cap->count0 != 0 && !(isman || isman_s)) + sprintf((char *)buf, ".,.+%ld", cap->count0 - 1); + + STRCAT(buf, "! "); + if (cap->count0 == 0 && isman_s) + STRCAT(buf, "man"); + else + STRCAT(buf, kp); + STRCAT(buf, " "); + if (cap->count0 != 0 && (isman || isman_s)) + { + sprintf((char *)buf + STRLEN(buf), "%ld", cap->count0); + STRCAT(buf, " "); + } + + *ptr_arg = ptr; + return n; + } + + /* * Handle the commands that use the word under the cursor. * [g] CTRL-] :ta to current identifier * [g] 'K' run program for current identifier *************** *** 3774,3781 **** int g_cmd; // "g" command int tag_cmd = FALSE; char_u *aux_ptr; - int isman; - int isman_s; if (cap->cmdchar == 'g') // "g*", "g#", "g]" and "gCTRL-]" { --- 3741,3746 ---- *************** *** 3791,3799 **** if (cmdchar == POUND) // the pound sign, '#' for English keyboards cmdchar = '#'; ! /* ! * The "]", "CTRL-]" and "K" commands accept an argument in Visual mode. ! */ if (cmdchar == ']' || cmdchar == Ctrl_RSB || cmdchar == 'K') { if (VIsual_active && get_visual_text(cap, &ptr, &n) == FAIL) --- 3756,3762 ---- if (cmdchar == POUND) // the pound sign, '#' for English keyboards cmdchar = '#'; ! // The "]", "CTRL-]" and "K" commands accept an argument in Visual mode. if (cmdchar == ']' || cmdchar == Ctrl_RSB || cmdchar == 'K') { if (VIsual_active && get_visual_text(cap, &ptr, &n) == FAIL) *************** *** 3832,3843 **** { case '*': case '#': ! /* ! * Put cursor at start of word, makes search skip the word ! * under the cursor. ! * Call setpcmark() first, so "*``" puts the cursor back where ! * it was. ! */ setpcmark(); curwin->w_cursor.col = (colnr_T) (ptr - ml_get_curline()); --- 3795,3804 ---- { case '*': case '#': ! // Put cursor at start of word, makes search skip the word ! // under the cursor. ! // Call setpcmark() first, so "*``" puts the cursor back where ! // it was. setpcmark(); curwin->w_cursor.col = (colnr_T) (ptr - ml_get_curline()); *************** *** 3847,3899 **** break; case 'K': ! if (kp_help) ! STRCPY(buf, "he! "); ! else if (kp_ex) ! { ! if (cap->count0 != 0) ! vim_snprintf((char *)buf, buflen, "%s %ld", ! kp, cap->count0); ! else ! STRCPY(buf, kp); ! STRCAT(buf, " "); ! } ! else ! { ! // An external command will probably use an argument starting ! // with "-" as an option. To avoid trouble we skip the "-". ! while (*ptr == '-' && n > 0) ! { ! ++ptr; ! --n; ! } ! if (n == 0) ! { ! // found dashes only ! emsg(_(e_no_identifier_under_cursor)); ! vim_free(buf); ! return; ! } ! ! // When a count is given, turn it into a range. Is this ! // really what we want? ! isman = (STRCMP(kp, "man") == 0); ! isman_s = (STRCMP(kp, "man -s") == 0); ! if (cap->count0 != 0 && !(isman || isman_s)) ! sprintf((char *)buf, ".,.+%ld", cap->count0 - 1); ! ! STRCAT(buf, "! "); ! if (cap->count0 == 0 && isman_s) ! STRCAT(buf, "man"); ! else ! STRCAT(buf, kp); ! STRCAT(buf, " "); ! if (cap->count0 != 0 && (isman || isman_s)) ! { ! sprintf((char *)buf + STRLEN(buf), "%ld", cap->count0); ! STRCAT(buf, " "); ! } ! } break; case ']': --- 3808,3816 ---- break; case 'K': ! n = nv_K_getcmd(cap, kp, kp_help, kp_ex, &ptr, n, buf, buflen); ! if (n == 0) ! return; break; case ']': *************** *** 3921,3929 **** } } ! /* ! * Now grab the chars in the identifier ! */ if (cmdchar == 'K' && !kp_help) { ptr = vim_strnsave(ptr, n); --- 3838,3844 ---- } } ! // Now grab the chars in the identifier if (cmdchar == 'K' && !kp_help) { ptr = vim_strnsave(ptr, n); *************** *** 3988,3996 **** *p = NUL; } ! /* ! * Execute the command. ! */ if (cmdchar == '*' || cmdchar == '#') { if (!g_cmd && (has_mbyte --- 3903,3909 ---- *p = NUL; } ! // Execute the command. if (cmdchar == '*' || cmdchar == '#') { if (!g_cmd && (has_mbyte *************** *** 4194,4203 **** cap->oap->inclusive = FALSE; past_line = (VIsual_active && *p_sel != 'o'); ! /* ! * In virtual edit mode, there's no such thing as "past_line", as lines ! * are (theoretically) infinitely long. ! */ if (virtual_active()) past_line = 0; --- 4107,4114 ---- cap->oap->inclusive = FALSE; past_line = (VIsual_active && *p_sel != 'o'); ! // In virtual edit mode, there's no such thing as "past_line", as lines ! // are (theoretically) infinitely long. if (virtual_active()) past_line = 0; *************** *** 4207,4217 **** || (past_line && *ml_get_cursor() == NUL) ) { ! /* ! * wraps to next line if 'whichwrap' has 's'. ! * 'l' wraps to next line if 'whichwrap' has 'l'. ! * CURS_RIGHT wraps to next line if 'whichwrap' has '>'. ! */ if ( ((cap->cmdchar == ' ' && vim_strchr(p_ww, 's') != NULL) || (cap->cmdchar == 'l' --- 4118,4126 ---- || (past_line && *ml_get_cursor() == NUL) ) { ! // wraps to next line if 'whichwrap' has 's'. ! // 'l' wraps to next line if 'whichwrap' has 'l'. ! // CURS_RIGHT wraps to next line if 'whichwrap' has '>'. if ( ((cap->cmdchar == ' ' && vim_strchr(p_ww, 's') != NULL) || (cap->cmdchar == 'l' *************** *** 4646,4665 **** } /* * "[" and "]" commands. * cap->arg is BACKWARD for "[" and FORWARD for "]". */ static void nv_brackets(cmdarg_T *cap) { - pos_T new_pos = {0, 0, 0}; pos_T prev_pos; pos_T *pos = NULL; // init for GCC pos_T old_pos; // cursor position before command int flag; long n; - int findc; - int c; cap->oap->motion_type = MCHAR; cap->oap->inclusive = FALSE; --- 4555,4703 ---- } /* + * "[{", "[(", "]}" or "])": go to Nth unclosed '{', '(', '}' or ')' + * "[#", "]#": go to start/end of Nth innermost #if..#endif construct. + * "[/", "[*", "]/", "]*": go to Nth comment start/end. + * "[m" or "]m" search for prev/next start of (Java) method. + * "[M" or "]M" search for prev/next end of (Java) method. + */ + static void + nv_bracket_block(cmdarg_T *cap, pos_T *old_pos) + { + pos_T new_pos = {0, 0, 0}; + pos_T *pos = NULL; // init for GCC + pos_T prev_pos; + long n; + int findc; + int c; + + if (cap->nchar == '*') + cap->nchar = '/'; + prev_pos.lnum = 0; + if (cap->nchar == 'm' || cap->nchar == 'M') + { + if (cap->cmdchar == '[') + findc = '{'; + else + findc = '}'; + n = 9999; + } + else + { + findc = cap->nchar; + n = cap->count1; + } + for ( ; n > 0; --n) + { + if ((pos = findmatchlimit(cap->oap, findc, + (cap->cmdchar == '[') ? FM_BACKWARD : FM_FORWARD, 0)) == NULL) + { + if (new_pos.lnum == 0) // nothing found + { + if (cap->nchar != 'm' && cap->nchar != 'M') + clearopbeep(cap->oap); + } + else + pos = &new_pos; // use last one found + break; + } + prev_pos = new_pos; + curwin->w_cursor = *pos; + new_pos = *pos; + } + curwin->w_cursor = *old_pos; + + // Handle "[m", "]m", "[M" and "[M". The findmatchlimit() only + // brought us to the match for "[m" and "]M" when inside a method. + // Try finding the '{' or '}' we want to be at. + // Also repeat for the given count. + if (cap->nchar == 'm' || cap->nchar == 'M') + { + // norm is TRUE for "]M" and "[m" + int norm = ((findc == '{') == (cap->nchar == 'm')); + + n = cap->count1; + // found a match: we were inside a method + if (prev_pos.lnum != 0) + { + pos = &prev_pos; + curwin->w_cursor = prev_pos; + if (norm) + --n; + } + else + pos = NULL; + while (n > 0) + { + for (;;) + { + if ((findc == '{' ? dec_cursor() : inc_cursor()) < 0) + { + // if not found anything, that's an error + if (pos == NULL) + clearopbeep(cap->oap); + n = 0; + break; + } + c = gchar_cursor(); + if (c == '{' || c == '}') + { + // Must have found end/start of class: use it. + // Or found the place to be at. + if ((c == findc && norm) || (n == 1 && !norm)) + { + new_pos = curwin->w_cursor; + pos = &new_pos; + n = 0; + } + // if no match found at all, we started outside of the + // class and we're inside now. Just go on. + else if (new_pos.lnum == 0) + { + new_pos = curwin->w_cursor; + pos = &new_pos; + } + // found start/end of other method: go to match + else if ((pos = findmatchlimit(cap->oap, findc, + (cap->cmdchar == '[') ? FM_BACKWARD : FM_FORWARD, + 0)) == NULL) + n = 0; + else + curwin->w_cursor = *pos; + break; + } + } + --n; + } + curwin->w_cursor = *old_pos; + if (pos == NULL && new_pos.lnum != 0) + clearopbeep(cap->oap); + } + if (pos != NULL) + { + setpcmark(); + curwin->w_cursor = *pos; + curwin->w_set_curswant = TRUE; + #ifdef FEAT_FOLDING + if ((fdo_flags & FDO_BLOCK) && KeyTyped + && cap->oap->op_type == OP_NOP) + foldOpenCursor(); + #endif + } + } + + /* * "[" and "]" commands. * cap->arg is BACKWARD for "[" and FORWARD for "]". */ static void nv_brackets(cmdarg_T *cap) { pos_T prev_pos; pos_T *pos = NULL; // init for GCC pos_T old_pos; // cursor position before command int flag; long n; cap->oap->motion_type = MCHAR; cap->oap->inclusive = FALSE; *************** *** 4667,4690 **** curwin->w_cursor.coladd = 0; // TODO: don't do this for an error. #ifdef FEAT_SEARCHPATH ! /* ! * "[f" or "]f" : Edit file under the cursor (same as "gf") ! */ if (cap->nchar == 'f') nv_gotofile(cap); else #endif #ifdef FEAT_FIND_ID ! /* ! * Find the occurrence(s) of the identifier or define under cursor ! * in current and included files or jump to the first occurrence. ! * ! * search list jump ! * fwd bwd fwd bwd fwd bwd ! * identifier "]i" "[i" "]I" "[I" "]^I" "[^I" ! * define "]d" "[d" "]D" "[D" "]^D" "[^D" ! */ if (vim_strchr((char_u *) # ifdef EBCDIC "iI\005dD\067", --- 4705,4724 ---- curwin->w_cursor.coladd = 0; // TODO: don't do this for an error. #ifdef FEAT_SEARCHPATH ! // "[f" or "]f" : Edit file under the cursor (same as "gf") if (cap->nchar == 'f') nv_gotofile(cap); else #endif #ifdef FEAT_FIND_ID ! // Find the occurrence(s) of the identifier or define under cursor ! // in current and included files or jump to the first occurrence. ! // ! // search list jump ! // fwd bwd fwd bwd fwd bwd ! // identifier "]i" "[i" "]I" "[I" "]^I" "[^I" ! // define "]d" "[d" "]D" "[D" "]^D" "[^D" if (vim_strchr((char_u *) # ifdef EBCDIC "iI\005dD\067", *************** *** 4714,4851 **** else #endif ! /* ! * "[{", "[(", "]}" or "])": go to Nth unclosed '{', '(', '}' or ')' ! * "[#", "]#": go to start/end of Nth innermost #if..#endif construct. ! * "[/", "[*", "]/", "]*": go to Nth comment start/end. ! * "[m" or "]m" search for prev/next start of (Java) method. ! * "[M" or "]M" search for prev/next end of (Java) method. ! */ if ( (cap->cmdchar == '[' && vim_strchr((char_u *)"{(*/#mM", cap->nchar) != NULL) || (cap->cmdchar == ']' && vim_strchr((char_u *)"})*/#mM", cap->nchar) != NULL)) ! { ! if (cap->nchar == '*') ! cap->nchar = '/'; ! prev_pos.lnum = 0; ! if (cap->nchar == 'm' || cap->nchar == 'M') ! { ! if (cap->cmdchar == '[') ! findc = '{'; ! else ! findc = '}'; ! n = 9999; ! } ! else ! { ! findc = cap->nchar; ! n = cap->count1; ! } ! for ( ; n > 0; --n) ! { ! if ((pos = findmatchlimit(cap->oap, findc, ! (cap->cmdchar == '[') ? FM_BACKWARD : FM_FORWARD, 0)) == NULL) ! { ! if (new_pos.lnum == 0) // nothing found ! { ! if (cap->nchar != 'm' && cap->nchar != 'M') ! clearopbeep(cap->oap); ! } ! else ! pos = &new_pos; // use last one found ! break; ! } ! prev_pos = new_pos; ! curwin->w_cursor = *pos; ! new_pos = *pos; ! } ! curwin->w_cursor = old_pos; ! ! /* ! * Handle "[m", "]m", "[M" and "[M". The findmatchlimit() only ! * brought us to the match for "[m" and "]M" when inside a method. ! * Try finding the '{' or '}' we want to be at. ! * Also repeat for the given count. ! */ ! if (cap->nchar == 'm' || cap->nchar == 'M') ! { ! // norm is TRUE for "]M" and "[m" ! int norm = ((findc == '{') == (cap->nchar == 'm')); ! n = cap->count1; ! // found a match: we were inside a method ! if (prev_pos.lnum != 0) ! { ! pos = &prev_pos; ! curwin->w_cursor = prev_pos; ! if (norm) ! --n; ! } ! else ! pos = NULL; ! while (n > 0) ! { ! for (;;) ! { ! if ((findc == '{' ? dec_cursor() : inc_cursor()) < 0) ! { ! // if not found anything, that's an error ! if (pos == NULL) ! clearopbeep(cap->oap); ! n = 0; ! break; ! } ! c = gchar_cursor(); ! if (c == '{' || c == '}') ! { ! // Must have found end/start of class: use it. ! // Or found the place to be at. ! if ((c == findc && norm) || (n == 1 && !norm)) ! { ! new_pos = curwin->w_cursor; ! pos = &new_pos; ! n = 0; ! } ! // if no match found at all, we started outside of the ! // class and we're inside now. Just go on. ! else if (new_pos.lnum == 0) ! { ! new_pos = curwin->w_cursor; ! pos = &new_pos; ! } ! // found start/end of other method: go to match ! else if ((pos = findmatchlimit(cap->oap, findc, ! (cap->cmdchar == '[') ? FM_BACKWARD : FM_FORWARD, ! 0)) == NULL) ! n = 0; ! else ! curwin->w_cursor = *pos; ! break; ! } ! } ! --n; ! } ! curwin->w_cursor = old_pos; ! if (pos == NULL && new_pos.lnum != 0) ! clearopbeep(cap->oap); ! } ! if (pos != NULL) ! { ! setpcmark(); ! curwin->w_cursor = *pos; ! curwin->w_set_curswant = TRUE; ! #ifdef FEAT_FOLDING ! if ((fdo_flags & FDO_BLOCK) && KeyTyped ! && cap->oap->op_type == OP_NOP) ! foldOpenCursor(); ! #endif ! } ! } ! ! /* ! * "[[", "[]", "]]" and "][": move to start or end of function ! */ else if (cap->nchar == '[' || cap->nchar == ']') { if (cap->nchar == cap->cmdchar) // "]]" or "[[" --- 4748,4765 ---- else #endif ! // "[{", "[(", "]}" or "])": go to Nth unclosed '{', '(', '}' or ')' ! // "[#", "]#": go to start/end of Nth innermost #if..#endif construct. ! // "[/", "[*", "]/", "]*": go to Nth comment start/end. ! // "[m" or "]m" search for prev/next start of (Java) method. ! // "[M" or "]M" search for prev/next end of (Java) method. if ( (cap->cmdchar == '[' && vim_strchr((char_u *)"{(*/#mM", cap->nchar) != NULL) || (cap->cmdchar == ']' && vim_strchr((char_u *)"})*/#mM", cap->nchar) != NULL)) ! nv_bracket_block(cap, &old_pos); ! // "[[", "[]", "]]" and "][": move to start or end of function else if (cap->nchar == '[' || cap->nchar == ']') { if (cap->nchar == cap->cmdchar) // "]]" or "[[" *************** *** 4854,4863 **** flag = '}'; // "][" or "[]" curwin->w_set_curswant = TRUE; ! /* ! * Imitate strange Vi behaviour: When using "]]" with an operator ! * we also stop at '}'. ! */ if (!findpar(&cap->oap->inclusive, cap->arg, cap->count1, flag, (cap->oap->op_type != OP_NOP && cap->arg == FORWARD && flag == '{'))) --- 4768,4775 ---- flag = '}'; // "][" or "[]" curwin->w_set_curswant = TRUE; ! // Imitate strange Vi behaviour: When using "]]" with an operator ! // we also stop at '}'. if (!findpar(&cap->oap->inclusive, cap->arg, cap->count1, flag, (cap->oap->op_type != OP_NOP && cap->arg == FORWARD && flag == '{'))) *************** *** 4873,4889 **** } } ! /* ! * "[p", "[P", "]P" and "]p": put with indent adjustment ! */ else if (cap->nchar == 'p' || cap->nchar == 'P') { nv_put_opt(cap, TRUE); } ! /* ! * "['", "[`", "]'" and "]`": jump to next mark ! */ else if (cap->nchar == '\'' || cap->nchar == '`') { pos = &curwin->w_cursor; --- 4785,4797 ---- } } ! // "[p", "[P", "]P" and "]p": put with indent adjustment else if (cap->nchar == 'p' || cap->nchar == 'P') { nv_put_opt(cap, TRUE); } ! // "['", "[`", "]'" and "]`": jump to next mark else if (cap->nchar == '\'' || cap->nchar == '`') { pos = &curwin->w_cursor; *************** *** 4900,4909 **** nv_cursormark(cap, cap->nchar == '\'', pos); } ! /* ! * [ or ] followed by a middle mouse click: put selected text with ! * indent adjustment. Any other button just does as usual. ! */ else if (cap->nchar >= K_RIGHTRELEASE && cap->nchar <= K_LEFTMOUSE) { (void)do_mouse(cap->oap, cap->nchar, --- 4808,4815 ---- nv_cursormark(cap, cap->nchar == '\'', pos); } ! // [ or ] followed by a middle mouse click: put selected text with ! // indent adjustment. Any other button just does as usual. else if (cap->nchar >= K_RIGHTRELEASE && cap->nchar <= K_LEFTMOUSE) { (void)do_mouse(cap->oap, cap->nchar, *************** *** 4912,4920 **** } #ifdef FEAT_FOLDING ! /* ! * "[z" and "]z": move to start or end of open fold. ! */ else if (cap->nchar == 'z') { if (foldMoveTo(FALSE, cap->cmdchar == ']' ? FORWARD : BACKWARD, --- 4818,4824 ---- } #ifdef FEAT_FOLDING ! // "[z" and "]z": move to start or end of open fold. else if (cap->nchar == 'z') { if (foldMoveTo(FALSE, cap->cmdchar == ']' ? FORWARD : BACKWARD, *************** *** 4924,4932 **** #endif #ifdef FEAT_DIFF ! /* ! * "[c" and "]c": move to next or previous diff-change. ! */ else if (cap->nchar == 'c') { if (diff_move_to(cap->cmdchar == ']' ? FORWARD : BACKWARD, --- 4828,4834 ---- #endif #ifdef FEAT_DIFF ! // "[c" and "]c": move to next or previous diff-change. else if (cap->nchar == 'c') { if (diff_move_to(cap->cmdchar == ']' ? FORWARD : BACKWARD, *************** *** 4936,4944 **** #endif #ifdef FEAT_SPELL ! /* ! * "[s", "[S", "]s" and "]S": move to next spell error. ! */ else if (cap->nchar == 's' || cap->nchar == 'S') { setpcmark(); --- 4838,4844 ---- #endif #ifdef FEAT_SPELL ! // "[s", "[S", "]s" and "]S": move to next spell error. else if (cap->nchar == 's' || cap->nchar == 'S') { setpcmark(); *************** *** 5205,5216 **** return; } ! /* ! * Replacing with a TAB is done by edit() when it is complicated because ! * 'expandtab' or 'smarttab' is set. CTRL-V TAB inserts a literal TAB. ! * Other characters are done below to avoid problems with things like ! * CTRL-V 048 (for edit() this would be R CTRL-V 0 ESC). ! */ if (had_ctrl_v != Ctrl_V && cap->nchar == '\t' && (curbuf->b_p_et || p_sta)) { stuffnumReadbuff(cap->count1); --- 5105,5114 ---- return; } ! // Replacing with a TAB is done by edit() when it is complicated because ! // 'expandtab' or 'smarttab' is set. CTRL-V TAB inserts a literal TAB. ! // Other characters are done below to avoid problems with things like ! // CTRL-V 048 (for edit() this would be R CTRL-V 0 ESC). if (had_ctrl_v != Ctrl_V && cap->nchar == '\t' && (curbuf->b_p_et || p_sta)) { stuffnumReadbuff(cap->count1); *************** *** 5226,5239 **** if (had_ctrl_v != Ctrl_V && (cap->nchar == '\r' || cap->nchar == '\n')) { ! /* ! * Replace character(s) by a single newline. ! * Strange vi behaviour: Only one newline is inserted. ! * Delete the characters here. ! * Insert the newline with an insert command, takes care of ! * autoindent. The insert command depends on being on the last ! * character of a line or not. ! */ (void)del_chars(cap->count1, FALSE); // delete the characters stuffcharReadbuff('\r'); stuffcharReadbuff(ESC); --- 5124,5135 ---- if (had_ctrl_v != Ctrl_V && (cap->nchar == '\r' || cap->nchar == '\n')) { ! // Replace character(s) by a single newline. ! // Strange vi behaviour: Only one newline is inserted. ! // Delete the characters here. ! // Insert the newline with an insert command, takes care of ! // autoindent. The insert command depends on being on the last ! // character of a line or not. (void)del_chars(cap->count1, FALSE); // delete the characters stuffcharReadbuff('\r'); stuffcharReadbuff(ESC); *************** *** 5283,5298 **** } else { ! /* ! * Replace the characters within one line. ! */ for (n = cap->count1; n > 0; --n) { ! /* ! * Get ptr again, because u_save and/or showmatch() will have ! * released the line. This may also happen in ins_copychar(). ! * At the same time we let know that the line will be changed. ! */ if (cap->nchar == Ctrl_E || cap->nchar == Ctrl_Y) { int c = ins_copychar(curwin->w_cursor.lnum --- 5179,5190 ---- } else { ! // Replace the characters within one line. for (n = cap->count1; n > 0; --n) { ! // Get ptr again, because u_save and/or showmatch() will have ! // released the line. This may also happen in ins_copychar(). ! // At the same time we let know that the line will be changed. if (cap->nchar == Ctrl_E || cap->nchar == Ctrl_Y) { int c = ins_copychar(curwin->w_cursor.lnum *************** *** 5849,5858 **** setmouse(); if (p_smd && msg_silent == 0) redraw_cmdline = TRUE; // show visual mode later ! /* ! * For V and ^V, we multiply the number of lines even if there ! * was only one -- webb ! */ if (resel_VIsual_mode != 'v' || resel_VIsual_line_count > 1) { curwin->w_cursor.lnum += --- 5741,5748 ---- setmouse(); if (p_smd && msg_silent == 0) redraw_cmdline = TRUE; // show visual mode later ! // For V and ^V, we multiply the number of lines even if there ! // was only one -- webb if (resel_VIsual_mode != 'v' || resel_VIsual_line_count > 1) { curwin->w_cursor.lnum += *************** *** 6677,6687 **** { if (!checkclearopq(cap->oap)) { ! /* ! * If "restart_edit" is TRUE, the last but one command is repeated ! * instead of the last command (inserting text). This is used for ! * CTRL-O <.> in insert mode. ! */ if (start_redo(cap->count0, restart_edit != 0 && !arrow_used) == FAIL) clearopbeep(cap->oap); } --- 6567,6575 ---- { if (!checkclearopq(cap->oap)) { ! // If "restart_edit" is TRUE, the last but one command is repeated ! // instead of the last command (inserting text). This is used for ! // CTRL-O <.> in insert mode. if (start_redo(cap->count0, restart_edit != 0 && !arrow_used) == FAIL) clearopbeep(cap->oap); } *************** *** 6907,6924 **** int flag = FALSE; pos_T startpos = curwin->w_cursor; ! /* ! * Set inclusive for the "E" and "e" command. ! */ if (cap->cmdchar == 'e' || cap->cmdchar == 'E') word_end = TRUE; else word_end = FALSE; cap->oap->inclusive = word_end; ! /* ! * "cw" and "cW" are a special case. ! */ if (!word_end && cap->oap->op_type == OP_CHANGE) { n = gchar_cursor(); --- 6795,6808 ---- int flag = FALSE; pos_T startpos = curwin->w_cursor; ! // Set inclusive for the "E" and "e" command. if (cap->cmdchar == 'e' || cap->cmdchar == 'E') word_end = TRUE; else word_end = FALSE; cap->oap->inclusive = word_end; ! // "cw" and "cW" are a special case. if (!word_end && cap->oap->op_type == OP_CHANGE) { n = gchar_cursor(); *************** *** 6926,6937 **** { if (VIM_ISWHITE(n)) { ! /* ! * Reproduce a funny Vi behaviour: "cw" on a blank only ! * changes one character, not all blanks until the start of ! * the next word. Only do this when the 'w' flag is included ! * in 'cpoptions'. ! */ if (cap->count1 == 1 && vim_strchr(p_cpo, CPO_CW) != NULL) { cap->oap->inclusive = TRUE; --- 6810,6819 ---- { if (VIM_ISWHITE(n)) { ! // Reproduce a funny Vi behaviour: "cw" on a blank only ! // changes one character, not all blanks until the start of ! // the next word. Only do this when the 'w' flag is included ! // in 'cpoptions'. if (cap->count1 == 1 && vim_strchr(p_cpo, CPO_CW) != NULL) { cap->oap->inclusive = TRUE; *************** *** 6941,6957 **** } else { ! /* ! * This is a little strange. To match what the real Vi does, ! * we effectively map 'cw' to 'ce', and 'cW' to 'cE', provided ! * that we are not on a space or a TAB. This seems impolite ! * at first, but it's really more what we mean when we say ! * 'cw'. ! * Another strangeness: When standing on the end of a word ! * "ce" will change until the end of the next word, but "cw" ! * will change only one character! This is done by setting ! * flag. ! */ cap->oap->inclusive = TRUE; word_end = TRUE; flag = TRUE; --- 6823,6837 ---- } else { ! // This is a little strange. To match what the real Vi does, ! // we effectively map 'cw' to 'ce', and 'cW' to 'cE', provided ! // that we are not on a space or a TAB. This seems impolite ! // at first, but it's really more what we mean when we say ! // 'cw'. ! // Another strangeness: When standing on the end of a word ! // "ce" will change until the end of the next word, but "cw" ! // will change only one character! This is done by setting ! // flag. cap->oap->inclusive = TRUE; word_end = TRUE; flag = TRUE; *** ../vim-8.2.4220/src/version.c 2022-01-26 11:16:48.663593514 +0000 --- src/version.c 2022-01-26 12:07:16.074355910 +0000 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 4221, /**/ -- If you only have a hammer, you tend to see every problem as a nail. If you only have MS-Windows, you tend to solve every problem by rebooting. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///