comparison src/normal.c @ 27386:ccfb16d876b1 v8.2.4221

patch 8.2.4221: some functions in normal.c are very long Commit: https://github.com/vim/vim/commit/a827bf3ea8fe465aa456ef7a7a37d6afe6a47628 Author: Yegappan Lakshmanan <yegappan@yahoo.com> Date: Wed Jan 26 12:14:15 2022 +0000 patch 8.2.4221: some functions in normal.c are very long Problem: Some functions in normal.c are very long. Solution: Move code to separate functions. (Yegappan Lakshmanan, closes #9628)
author Bram Moolenaar <Bram@vim.org>
date Wed, 26 Jan 2022 13:15:03 +0100
parents 469e643b7729
children 722db0819111
comparison
equal deleted inserted replaced
27385:4363272621fc 27386:ccfb16d876b1
625 /* 625 /*
626 * Get one or more additional characters for a normal command. 626 * Get one or more additional characters for a normal command.
627 * Return the updated command index (if changed). 627 * Return the updated command index (if changed).
628 */ 628 */
629 static int 629 static int
630 normal_cmd_get_more_chars(int idx, cmdarg_T *cap, int *need_flushbuf UNUSED) 630 normal_cmd_get_more_chars(
631 { 631 int idx_arg,
632 cmdarg_T *cap,
633 int *need_flushbuf UNUSED)
634 {
635 int idx = idx_arg;
632 int c; 636 int c;
633 int *cp; 637 int *cp;
634 int repl = FALSE; // get character for replace mode 638 int repl = FALSE; // get character for replace mode
635 int lit = FALSE; // get extra character literally 639 int lit = FALSE; // get extra character literally
636 int langmap_active = FALSE; // using :lmap mappings 640 int langmap_active = FALSE; // using :lmap mappings
777 if (p_hkmap && lang && KeyTyped) 781 if (p_hkmap && lang && KeyTyped)
778 *cp = hkmap(*cp); 782 *cp = hkmap(*cp);
779 #endif 783 #endif
780 } 784 }
781 785
782 /* 786 // When the next character is CTRL-\ a following CTRL-N means the
783 * When the next character is CTRL-\ a following CTRL-N means the 787 // command is aborted and we go to Normal mode.
784 * command is aborted and we go to Normal mode.
785 */
786 if (cp == &cap->extra_char 788 if (cp == &cap->extra_char
787 && cap->nchar == Ctrl_BSL 789 && cap->nchar == Ctrl_BSL
788 && (cap->extra_char == Ctrl_N || cap->extra_char == Ctrl_G)) 790 && (cap->extra_char == Ctrl_N || cap->extra_char == Ctrl_G))
789 { 791 {
790 cap->cmdchar = Ctrl_BSL; 792 cap->cmdchar = Ctrl_BSL;
852 * message. 854 * message.
853 */ 855 */
854 static int 856 static int
855 normal_cmd_need_to_wait_for_msg(cmdarg_T *cap, pos_T *old_pos) 857 normal_cmd_need_to_wait_for_msg(cmdarg_T *cap, pos_T *old_pos)
856 { 858 {
857 /* 859 // In Visual mode and with "^O" in Insert mode, a short message will be
858 * In Visual mode and with "^O" in Insert mode, a short message will be 860 // overwritten by the mode message. Wait a bit, until a key is hit.
859 * overwritten by the mode message. Wait a bit, until a key is hit. 861 // In Visual mode, it's more important to keep the Visual area updated
860 * In Visual mode, it's more important to keep the Visual area updated 862 // than keeping a message (e.g. from a /pat search).
861 * than keeping a message (e.g. from a /pat search). 863 // Only do this if the command was typed, not from a mapping.
862 * Only do this if the command was typed, not from a mapping. 864 // Don't wait when emsg_silent is non-zero.
863 * Don't wait when emsg_silent is non-zero. 865 // Also wait a bit after an error message, e.g. for "^O:".
864 * Also wait a bit after an error message, e.g. for "^O:". 866 // Don't redraw the screen, it would remove the message.
865 * Don't redraw the screen, it would remove the message.
866 */
867 return ( ((p_smd 867 return ( ((p_smd
868 && msg_silent == 0 868 && msg_silent == 0
869 && (restart_edit != 0 869 && (restart_edit != 0
870 || (VIsual_active 870 || (VIsual_active
871 && old_pos->lnum == curwin->w_cursor.lnum 871 && old_pos->lnum == curwin->w_cursor.lnum
966 // Use a count remembered from before entering an operator. After typing 966 // Use a count remembered from before entering an operator. After typing
967 // "3d" we return from normal_cmd() and come back here, the "3" is 967 // "3d" we return from normal_cmd() and come back here, the "3" is
968 // remembered in "opcount". 968 // remembered in "opcount".
969 ca.opcount = opcount; 969 ca.opcount = opcount;
970 970
971 /* 971 // If there is an operator pending, then the command we take this time
972 * If there is an operator pending, then the command we take this time 972 // will terminate it. Finish_op tells us to finish the operation before
973 * will terminate it. Finish_op tells us to finish the operation before 973 // returning this time (unless the operation was cancelled).
974 * returning this time (unless the operation was cancelled).
975 */
976 #ifdef CURSOR_SHAPE 974 #ifdef CURSOR_SHAPE
977 c = finish_op; 975 c = finish_op;
978 #endif 976 #endif
979 finish_op = (oap->op_type != OP_NOP); 977 finish_op = (oap->op_type != OP_NOP);
980 #ifdef CURSOR_SHAPE 978 #ifdef CURSOR_SHAPE
1028 * Get the command character from the user. 1026 * Get the command character from the user.
1029 */ 1027 */
1030 c = safe_vgetc(); 1028 c = safe_vgetc();
1031 LANGMAP_ADJUST(c, get_real_state() != SELECTMODE); 1029 LANGMAP_ADJUST(c, get_real_state() != SELECTMODE);
1032 1030
1033 /* 1031 // If a mapping was started in Visual or Select mode, remember the length
1034 * If a mapping was started in Visual or Select mode, remember the length 1032 // of the mapping. This is used below to not return to Insert mode for as
1035 * of the mapping. This is used below to not return to Insert mode for as 1033 // long as the mapping is being executed.
1036 * long as the mapping is being executed.
1037 */
1038 if (restart_edit == 0) 1034 if (restart_edit == 0)
1039 old_mapped_len = 0; 1035 old_mapped_len = 0;
1040 else if (old_mapped_len 1036 else if (old_mapped_len
1041 || (VIsual_active && mapped_len == 0 && typebuf_maplen() > 0)) 1037 || (VIsual_active && mapped_len == 0 && typebuf_maplen() > 0))
1042 old_mapped_len = typebuf_maplen(); 1038 old_mapped_len = typebuf_maplen();
1043 1039
1044 if (c == NUL) 1040 if (c == NUL)
1045 c = K_ZERO; 1041 c = K_ZERO;
1046 1042
1047 /* 1043 // In Select mode, typed text replaces the selection.
1048 * In Select mode, typed text replaces the selection.
1049 */
1050 if (VIsual_active 1044 if (VIsual_active
1051 && VIsual_select 1045 && VIsual_select
1052 && (vim_isprintc(c) || c == NL || c == CAR || c == K_KENTER)) 1046 && (vim_isprintc(c) || c == NL || c == CAR || c == K_KENTER))
1053 { 1047 {
1054 int len; 1048 int len;
1083 1077
1084 // Get the command count 1078 // Get the command count
1085 c = normal_cmd_get_count(&ca, c, toplevel, set_prevcount, &ctrl_w, 1079 c = normal_cmd_get_count(&ca, c, toplevel, set_prevcount, &ctrl_w,
1086 &need_flushbuf); 1080 &need_flushbuf);
1087 1081
1088 /* 1082 // Find the command character in the table of commands.
1089 * Find the command character in the table of commands. 1083 // For CTRL-W we already got nchar when looking for a count.
1090 * For CTRL-W we already got nchar when looking for a count.
1091 */
1092 if (ctrl_w) 1084 if (ctrl_w)
1093 { 1085 {
1094 ca.nchar = c; 1086 ca.nchar = c;
1095 ca.cmdchar = Ctrl_W; 1087 ca.cmdchar = Ctrl_W;
1096 } 1088 }
1112 goto normal_end; 1104 goto normal_end;
1113 } 1105 }
1114 if ((nv_cmds[idx].cmd_flags & NV_NCW) && curbuf_locked()) 1106 if ((nv_cmds[idx].cmd_flags & NV_NCW) && curbuf_locked())
1115 goto normal_end; 1107 goto normal_end;
1116 1108
1117 /* 1109 // In Visual/Select mode, a few keys are handled in a special way.
1118 * In Visual/Select mode, a few keys are handled in a special way.
1119 */
1120 if (VIsual_active) 1110 if (VIsual_active)
1121 { 1111 {
1122 // when 'keymodel' contains "stopsel" may stop Select/Visual mode 1112 // when 'keymodel' contains "stopsel" may stop Select/Visual mode
1123 if (km_stopsel 1113 if (km_stopsel
1124 && (nv_cmds[idx].cmd_flags & NV_STS) 1114 && (nv_cmds[idx].cmd_flags & NV_STS)
1175 // Get additional characters if we need them. 1165 // Get additional characters if we need them.
1176 if (normal_cmd_needs_more_chars(&ca, nv_cmds[idx].cmd_flags)) 1166 if (normal_cmd_needs_more_chars(&ca, nv_cmds[idx].cmd_flags))
1177 idx = normal_cmd_get_more_chars(idx, &ca, &need_flushbuf); 1167 idx = normal_cmd_get_more_chars(idx, &ca, &need_flushbuf);
1178 1168
1179 #ifdef FEAT_CMDL_INFO 1169 #ifdef FEAT_CMDL_INFO
1180 /* 1170 // Flush the showcmd characters onto the screen so we can see them while
1181 * Flush the showcmd characters onto the screen so we can see them while 1171 // the command is being executed. Only do this when the shown command was
1182 * the command is being executed. Only do this when the shown command was 1172 // actually displayed, otherwise this will slow down a lot when executing
1183 * actually displayed, otherwise this will slow down a lot when executing 1173 // mappings.
1184 * mappings.
1185 */
1186 if (need_flushbuf) 1174 if (need_flushbuf)
1187 out_flush(); 1175 out_flush();
1188 #endif 1176 #endif
1189 if (ca.cmdchar != K_IGNORE) 1177 if (ca.cmdchar != K_IGNORE)
1190 { 1178 {
1228 start_selection(); 1216 start_selection();
1229 mod_mask &= ~MOD_MASK_SHIFT; 1217 mod_mask &= ~MOD_MASK_SHIFT;
1230 } 1218 }
1231 } 1219 }
1232 1220
1233 /* 1221 // Execute the command!
1234 * Execute the command! 1222 // Call the command function found in the commands table.
1235 * Call the command function found in the commands table.
1236 */
1237 ca.arg = nv_cmds[idx].cmd_arg; 1223 ca.arg = nv_cmds[idx].cmd_arg;
1238 (nv_cmds[idx].cmd_func)(&ca); 1224 (nv_cmds[idx].cmd_func)(&ca);
1239 1225
1240 /* 1226 // If we didn't start or finish an operator, reset oap->regname, unless we
1241 * If we didn't start or finish an operator, reset oap->regname, unless we 1227 // need it later.
1242 * need it later.
1243 */
1244 if (!finish_op 1228 if (!finish_op
1245 && !oap->op_type 1229 && !oap->op_type
1246 && (idx < 0 || !(nv_cmds[idx].cmd_flags & NV_KEEPREG))) 1230 && (idx < 0 || !(nv_cmds[idx].cmd_flags & NV_KEEPREG)))
1247 { 1231 {
1248 clearop(oap); 1232 clearop(oap);
1254 // Get the length of mapped chars again after typing a count, second 1238 // Get the length of mapped chars again after typing a count, second
1255 // character or "z333<cr>". 1239 // character or "z333<cr>".
1256 if (old_mapped_len > 0) 1240 if (old_mapped_len > 0)
1257 old_mapped_len = typebuf_maplen(); 1241 old_mapped_len = typebuf_maplen();
1258 1242
1259 /* 1243 // If an operation is pending, handle it. But not for K_IGNORE or
1260 * If an operation is pending, handle it. But not for K_IGNORE or 1244 // K_MOUSEMOVE.
1261 * K_MOUSEMOVE.
1262 */
1263 if (ca.cmdchar != K_IGNORE && ca.cmdchar != K_MOUSEMOVE) 1245 if (ca.cmdchar != K_IGNORE && ca.cmdchar != K_MOUSEMOVE)
1264 do_pending_operator(&ca, old_col, FALSE); 1246 do_pending_operator(&ca, old_col, FALSE);
1265 1247
1266 // Wait for a moment when a message is displayed that will be overwritten 1248 // Wait for a moment when a message is displayed that will be overwritten
1267 // by the mode message. 1249 // by the mode message.
1268 if (normal_cmd_need_to_wait_for_msg(&ca, &old_pos)) 1250 if (normal_cmd_need_to_wait_for_msg(&ca, &old_pos))
1269 normal_cmd_wait_for_msg(); 1251 normal_cmd_wait_for_msg();
1270 1252
1271 /* 1253 // Finish up after executing a Normal mode command.
1272 * Wait for a moment when a message is displayed that will be overwritten
1273 * by the mode message.
1274 * In Visual mode and with "^O" in Insert mode, a short message will be
1275 * overwritten by the mode message. Wait a bit, until a key is hit.
1276 * In Visual mode, it's more important to keep the Visual area updated
1277 * than keeping a message (e.g. from a /pat search).
1278 * Only do this if the command was typed, not from a mapping.
1279 * Don't wait when emsg_silent is non-zero.
1280 * Also wait a bit after an error message, e.g. for "^O:".
1281 * Don't redraw the screen, it would remove the message.
1282 */
1283 if ( ((p_smd
1284 && msg_silent == 0
1285 && (restart_edit != 0
1286 || (VIsual_active
1287 && old_pos.lnum == curwin->w_cursor.lnum
1288 && old_pos.col == curwin->w_cursor.col)
1289 )
1290 && (clear_cmdline
1291 || redraw_cmdline)
1292 && (msg_didout || (msg_didany && msg_scroll))
1293 && !msg_nowait
1294 && KeyTyped)
1295 || (restart_edit != 0
1296 && !VIsual_active
1297 && (msg_scroll
1298 || emsg_on_display)))
1299 && oap->regname == 0
1300 && !(ca.retval & CA_COMMAND_BUSY)
1301 && stuff_empty()
1302 && typebuf_typed()
1303 && emsg_silent == 0
1304 && !in_assert_fails
1305 && !did_wait_return
1306 && oap->op_type == OP_NOP)
1307 {
1308 int save_State = State;
1309
1310 // Draw the cursor with the right shape here
1311 if (restart_edit != 0)
1312 State = INSERT;
1313
1314 // If need to redraw, and there is a "keep_msg", redraw before the
1315 // delay
1316 if (must_redraw && keep_msg != NULL && !emsg_on_display)
1317 {
1318 char_u *kmsg;
1319
1320 kmsg = keep_msg;
1321 keep_msg = NULL;
1322 // Showmode() will clear keep_msg, but we want to use it anyway.
1323 // First update w_topline.
1324 setcursor();
1325 update_screen(0);
1326 // now reset it, otherwise it's put in the history again
1327 keep_msg = kmsg;
1328
1329 kmsg = vim_strsave(keep_msg);
1330 if (kmsg != NULL)
1331 {
1332 msg_attr((char *)kmsg, keep_msg_attr);
1333 vim_free(kmsg);
1334 }
1335 }
1336 setcursor();
1337 #ifdef CURSOR_SHAPE
1338 ui_cursor_shape(); // may show different cursor shape
1339 #endif
1340 cursor_on();
1341 out_flush();
1342 if (msg_scroll || emsg_on_display)
1343 ui_delay(1003L, TRUE); // wait at least one second
1344 ui_delay(3003L, FALSE); // wait up to three seconds
1345 State = save_State;
1346
1347 msg_scroll = FALSE;
1348 emsg_on_display = FALSE;
1349 }
1350
1351 /*
1352 * Finish up after executing a Normal mode command.
1353 */
1354 normal_end: 1254 normal_end:
1355 1255
1356 msg_nowait = FALSE; 1256 msg_nowait = FALSE;
1357 1257
1358 #ifdef FEAT_EVAL 1258 #ifdef FEAT_EVAL
1406 // don't go to Insert mode if a terminal has a running job 1306 // don't go to Insert mode if a terminal has a running job
1407 if (term_job_running(curbuf->b_term)) 1307 if (term_job_running(curbuf->b_term))
1408 restart_edit = 0; 1308 restart_edit = 0;
1409 #endif 1309 #endif
1410 1310
1411 /* 1311 // May restart edit(), if we got here with CTRL-O in Insert mode (but not
1412 * May restart edit(), if we got here with CTRL-O in Insert mode (but not 1312 // if still inside a mapping that started in Visual mode).
1413 * if still inside a mapping that started in Visual mode). 1313 // May switch from Visual to Select mode after CTRL-O command.
1414 * May switch from Visual to Select mode after CTRL-O command.
1415 */
1416 if ( oap->op_type == OP_NOP 1314 if ( oap->op_type == OP_NOP
1417 && ((restart_edit != 0 && !VIsual_active && old_mapped_len == 0) 1315 && ((restart_edit != 0 && !VIsual_active && old_mapped_len == 0)
1418 || restart_VIsual_select == 1) 1316 || restart_VIsual_select == 1)
1419 && !(ca.retval & CA_COMMAND_BUSY) 1317 && !(ca.retval & CA_COMMAND_BUSY)
1420 && stuff_empty() 1318 && stuff_empty()
1508 1406
1509 void 1407 void
1510 end_visual_mode_keep_button() 1408 end_visual_mode_keep_button()
1511 { 1409 {
1512 #ifdef FEAT_CLIPBOARD 1410 #ifdef FEAT_CLIPBOARD
1513 /* 1411 // If we are using the clipboard, then remember what was selected in case
1514 * If we are using the clipboard, then remember what was selected in case 1412 // we need to paste it somewhere while we still own the selection.
1515 * we need to paste it somewhere while we still own the selection. 1413 // Only do this when the clipboard is already owned. Don't want to grab
1516 * Only do this when the clipboard is already owned. Don't want to grab 1414 // the selection when hitting ESC.
1517 * the selection when hitting ESC.
1518 */
1519 if (clip_star.available && clip_star.owned) 1415 if (clip_star.available && clip_star.owned)
1520 clip_auto_select(); 1416 clip_auto_select();
1521 1417
1522 # if defined(FEAT_EVAL) 1418 # if defined(FEAT_EVAL)
1523 // Emit a TextYankPost for the automatic copy of the selection into the 1419 // Emit a TextYankPost for the automatic copy of the selection into the
1676 int this_class = 0; 1572 int this_class = 0;
1677 int prev_class; 1573 int prev_class;
1678 int prevcol; 1574 int prevcol;
1679 int bn = 0; // bracket nesting 1575 int bn = 0; // bracket nesting
1680 1576
1681 /* 1577 // if i == 0: try to find an identifier
1682 * if i == 0: try to find an identifier 1578 // if i == 1: try to find any non-white text
1683 * if i == 1: try to find any non-white text
1684 */
1685 ptr = ml_get_buf(wp->w_buffer, lnum, FALSE); 1579 ptr = ml_get_buf(wp->w_buffer, lnum, FALSE);
1686 for (i = (find_type & FIND_IDENT) ? 0 : 1; i < 2; ++i) 1580 for (i = (find_type & FIND_IDENT) ? 0 : 1; i < 2; ++i)
1687 { 1581 {
1688 /* 1582 /*
1689 * 1. skip to start of identifier/text 1583 * 1. skip to start of identifier/text
2198 { 2092 {
2199 screen_puts(showcmd_buf, (int)Rows - 1, sc_col, 0); 2093 screen_puts(showcmd_buf, (int)Rows - 1, sc_col, 0);
2200 showcmd_is_clear = FALSE; 2094 showcmd_is_clear = FALSE;
2201 } 2095 }
2202 2096
2203 /* 2097 // clear the rest of an old message by outputting up to SHOWCMD_COLS
2204 * clear the rest of an old message by outputting up to SHOWCMD_COLS 2098 // spaces
2205 * spaces
2206 */
2207 screen_puts((char_u *)" " + len, (int)Rows - 1, sc_col + len, 0); 2099 screen_puts((char_u *)" " + len, (int)Rows - 1, sc_col + len, 0);
2208 2100
2209 setcursor(); // put cursor back where it belongs 2101 setcursor(); // put cursor back where it belongs
2210 } 2102 }
2211 #endif 2103 #endif
2232 // the values. 2124 // the values.
2233 if (did_syncbind) 2125 if (did_syncbind)
2234 did_syncbind = FALSE; 2126 did_syncbind = FALSE;
2235 else if (curwin == old_curwin) 2127 else if (curwin == old_curwin)
2236 { 2128 {
2237 /* 2129 // Synchronize other windows, as necessary according to
2238 * Synchronize other windows, as necessary according to 2130 // 'scrollbind'. Don't do this after an ":edit" command, except
2239 * 'scrollbind'. Don't do this after an ":edit" command, except 2131 // when 'diff' is set.
2240 * when 'diff' is set.
2241 */
2242 if ((curwin->w_buffer == old_buf 2132 if ((curwin->w_buffer == old_buf
2243 #ifdef FEAT_DIFF 2133 #ifdef FEAT_DIFF
2244 || curwin->w_p_diff 2134 || curwin->w_p_diff
2245 #endif 2135 #endif
2246 ) 2136 )
2254 (long)(curwin->w_leftcol - old_leftcol)); 2144 (long)(curwin->w_leftcol - old_leftcol));
2255 } 2145 }
2256 } 2146 }
2257 else if (vim_strchr(p_sbo, 'j')) // jump flag set in 'scrollopt' 2147 else if (vim_strchr(p_sbo, 'j')) // jump flag set in 'scrollopt'
2258 { 2148 {
2259 /* 2149 // When switching between windows, make sure that the relative
2260 * When switching between windows, make sure that the relative 2150 // vertical offset is valid for the new window. The relative
2261 * vertical offset is valid for the new window. The relative 2151 // offset is invalid whenever another 'scrollbind' window has
2262 * offset is invalid whenever another 'scrollbind' window has 2152 // scrolled to a point that would force the current window to
2263 * scrolled to a point that would force the current window to 2153 // scroll past the beginning or end of its buffer. When the
2264 * scroll past the beginning or end of its buffer. When the 2154 // resync is performed, some of the other 'scrollbind' windows may
2265 * resync is performed, some of the other 'scrollbind' windows may 2155 // need to jump so that the current window's relative position is
2266 * need to jump so that the current window's relative position is 2156 // visible on-screen.
2267 * visible on-screen.
2268 */
2269 check_scrollbind(curwin->w_topline - curwin->w_scbind_pos, 0L); 2157 check_scrollbind(curwin->w_topline - curwin->w_scbind_pos, 0L);
2270 } 2158 }
2271 curwin->w_scbind_pos = curwin->w_topline; 2159 curwin->w_scbind_pos = curwin->w_topline;
2272 } 2160 }
2273 2161
2296 int old_VIsual_active = VIsual_active; 2184 int old_VIsual_active = VIsual_active;
2297 colnr_T tgt_leftcol = curwin->w_leftcol; 2185 colnr_T tgt_leftcol = curwin->w_leftcol;
2298 long topline; 2186 long topline;
2299 long y; 2187 long y;
2300 2188
2301 /* 2189 // check 'scrollopt' string for vertical and horizontal scroll options
2302 * check 'scrollopt' string for vertical and horizontal scroll options
2303 */
2304 want_ver = (vim_strchr(p_sbo, 'v') && topline_diff != 0); 2190 want_ver = (vim_strchr(p_sbo, 'v') && topline_diff != 0);
2305 #ifdef FEAT_DIFF 2191 #ifdef FEAT_DIFF
2306 want_ver |= old_curwin->w_p_diff; 2192 want_ver |= old_curwin->w_p_diff;
2307 #endif 2193 #endif
2308 want_hor = (vim_strchr(p_sbo, 'h') && (leftcol_diff || topline_diff != 0)); 2194 want_hor = (vim_strchr(p_sbo, 'h') && (leftcol_diff || topline_diff != 0));
2309 2195
2310 /* 2196 // loop through the scrollbound windows and scroll accordingly
2311 * loop through the scrollbound windows and scroll accordingly
2312 */
2313 VIsual_select = VIsual_active = 0; 2197 VIsual_select = VIsual_active = 0;
2314 FOR_ALL_WINDOWS(curwin) 2198 FOR_ALL_WINDOWS(curwin)
2315 { 2199 {
2316 curbuf = curwin->w_buffer; 2200 curbuf = curwin->w_buffer;
2317 // skip original window and windows with 'noscrollbind' 2201 // skip original window and windows with 'noscrollbind'
2318 if (curwin != old_curwin && curwin->w_p_scb) 2202 if (curwin != old_curwin && curwin->w_p_scb)
2319 { 2203 {
2320 /* 2204 // do the vertical scroll
2321 * do the vertical scroll
2322 */
2323 if (want_ver) 2205 if (want_ver)
2324 { 2206 {
2325 #ifdef FEAT_DIFF 2207 #ifdef FEAT_DIFF
2326 if (old_curwin->w_p_diff && curwin->w_p_diff) 2208 if (old_curwin->w_p_diff && curwin->w_p_diff)
2327 { 2209 {
2347 redraw_later(VALID); 2229 redraw_later(VALID);
2348 cursor_correct(); 2230 cursor_correct();
2349 curwin->w_redr_status = TRUE; 2231 curwin->w_redr_status = TRUE;
2350 } 2232 }
2351 2233
2352 /* 2234 // do the horizontal scroll
2353 * do the horizontal scroll
2354 */
2355 if (want_hor && curwin->w_leftcol != tgt_leftcol) 2235 if (want_hor && curwin->w_leftcol != tgt_leftcol)
2356 { 2236 {
2357 curwin->w_leftcol = tgt_leftcol; 2237 curwin->w_leftcol = tgt_leftcol;
2358 leftcol_changed(); 2238 leftcol_changed();
2359 } 2239 }
2360 } 2240 }
2361 } 2241 }
2362 2242
2363 /* 2243 // reset current-window
2364 * reset current-window
2365 */
2366 VIsual_select = old_VIsual_select; 2244 VIsual_select = old_VIsual_select;
2367 VIsual_active = old_VIsual_active; 2245 VIsual_active = old_VIsual_active;
2368 curwin = old_curwin; 2246 curwin = old_curwin;
2369 curbuf = old_curbuf; 2247 curbuf = old_curbuf;
2370 } 2248 }
2567 save_p_ws = p_ws; 2445 save_p_ws = p_ws;
2568 save_p_scs = p_scs; 2446 save_p_scs = p_scs;
2569 p_ws = FALSE; // don't wrap around end of file now 2447 p_ws = FALSE; // don't wrap around end of file now
2570 p_scs = FALSE; // don't switch ignorecase off now 2448 p_scs = FALSE; // don't switch ignorecase off now
2571 2449
2572 /* 2450 // With "gD" go to line 1.
2573 * With "gD" go to line 1. 2451 // With "gd" Search back for the start of the current function, then go
2574 * With "gd" Search back for the start of the current function, then go 2452 // back until a blank line. If this fails go to line 1.
2575 * back until a blank line. If this fails go to line 1.
2576 */
2577 if (!locally || !findpar(&incll, BACKWARD, 1L, '{', FALSE)) 2453 if (!locally || !findpar(&incll, BACKWARD, 1L, '{', FALSE))
2578 { 2454 {
2579 setpcmark(); // Set in findpar() otherwise 2455 setpcmark(); // Set in findpar() otherwise
2580 curwin->w_cursor.lnum = 1; 2456 curwin->w_cursor.lnum = 1;
2581 par_pos = curwin->w_cursor; 2457 par_pos = curwin->w_cursor;
2712 if (width2 == 0) 2588 if (width2 == 0)
2713 width2 = 1; // avoid divide by zero 2589 width2 = 1; // avoid divide by zero
2714 2590
2715 if (curwin->w_width != 0) 2591 if (curwin->w_width != 0)
2716 { 2592 {
2717 /* 2593 // Instead of sticking at the last character of the buffer line we
2718 * Instead of sticking at the last character of the buffer line we 2594 // try to stick in the last column of the screen.
2719 * try to stick in the last column of the screen.
2720 */
2721 if (curwin->w_curswant == MAXCOL) 2595 if (curwin->w_curswant == MAXCOL)
2722 { 2596 {
2723 atend = TRUE; 2597 atend = TRUE;
2724 validate_virtcol(); 2598 validate_virtcol();
2725 if (width1 <= 0) 2599 if (width1 <= 0)
2826 if (curwin->w_cursor.col > 0 && curwin->w_p_wrap) 2700 if (curwin->w_cursor.col > 0 && curwin->w_p_wrap)
2827 { 2701 {
2828 colnr_T virtcol; 2702 colnr_T virtcol;
2829 int c; 2703 int c;
2830 2704
2831 /* 2705 // Check for landing on a character that got split at the end of the
2832 * Check for landing on a character that got split at the end of the 2706 // last line. We want to advance a screenline, not end up in the same
2833 * last line. We want to advance a screenline, not end up in the same 2707 // screenline or move two screenlines.
2834 * screenline or move two screenlines.
2835 */
2836 validate_virtcol(); 2708 validate_virtcol();
2837 virtcol = curwin->w_virtcol; 2709 virtcol = curwin->w_virtcol;
2838 #if defined(FEAT_LINEBREAK) 2710 #if defined(FEAT_LINEBREAK)
2839 if (virtcol > (colnr_T)width1 && *get_showbreak_value(curwin) != NUL) 2711 if (virtcol > (colnr_T)width1 && *get_showbreak_value(curwin) != NUL)
2840 virtcol -= vim_strsize(get_showbreak_value(curwin)); 2712 virtcol -= vim_strsize(get_showbreak_value(curwin));
2927 coladvance(curwin->w_curswant); 2799 coladvance(curwin->w_curswant);
2928 redraw_later(VALID); 2800 redraw_later(VALID);
2929 } 2801 }
2930 2802
2931 /* 2803 /*
2804 * Get the count specified after a 'z' command. Returns TRUE to process
2805 * the 'z' command and FALSE to skip it.
2806 */
2807 static int
2808 nv_z_get_count(cmdarg_T *cap, int *nchar_arg)
2809 {
2810 int nchar = *nchar_arg;
2811 long n;
2812
2813 // "z123{nchar}": edit the count before obtaining {nchar}
2814 if (checkclearop(cap->oap))
2815 return FALSE;
2816 n = nchar - '0';
2817
2818 for (;;)
2819 {
2820 #ifdef USE_ON_FLY_SCROLL
2821 dont_scroll = TRUE; // disallow scrolling here
2822 #endif
2823 ++no_mapping;
2824 ++allow_keys; // no mapping for nchar, but allow key codes
2825 nchar = plain_vgetc();
2826 LANGMAP_ADJUST(nchar, TRUE);
2827 --no_mapping;
2828 --allow_keys;
2829 #ifdef FEAT_CMDL_INFO
2830 (void)add_to_showcmd(nchar);
2831 #endif
2832 if (nchar == K_DEL || nchar == K_KDEL)
2833 n /= 10;
2834 else if (VIM_ISDIGIT(nchar))
2835 n = n * 10 + (nchar - '0');
2836 else if (nchar == CAR)
2837 {
2838 #ifdef FEAT_GUI
2839 need_mouse_correct = TRUE;
2840 #endif
2841 win_setheight((int)n);
2842 break;
2843 }
2844 else if (nchar == 'l'
2845 || nchar == 'h'
2846 || nchar == K_LEFT
2847 || nchar == K_RIGHT)
2848 {
2849 cap->count1 = n ? n * cap->count1 : cap->count1;
2850 *nchar_arg = nchar;
2851 return TRUE;
2852 }
2853 else
2854 {
2855 clearopbeep(cap->oap);
2856 break;
2857 }
2858 }
2859 cap->oap->op_type = OP_NOP;
2860 return FALSE;
2861 }
2862
2863 #ifdef FEAT_SPELL
2864 /*
2865 * "zug" and "zuw": undo "zg" and "zw"
2866 * "zg": add good word to word list
2867 * "zw": add wrong word to word list
2868 * "zG": add good word to temp word list
2869 * "zW": add wrong word to temp word list
2870 */
2871 static int
2872 nv_zg_zw(cmdarg_T *cap, int nchar)
2873 {
2874 char_u *ptr = NULL;
2875 int len;
2876 int undo = FALSE;
2877
2878 if (nchar == 'u')
2879 {
2880 ++no_mapping;
2881 ++allow_keys; // no mapping for nchar, but allow key codes
2882 nchar = plain_vgetc();
2883 LANGMAP_ADJUST(nchar, TRUE);
2884 --no_mapping;
2885 --allow_keys;
2886 #ifdef FEAT_CMDL_INFO
2887 (void)add_to_showcmd(nchar);
2888 #endif
2889 if (vim_strchr((char_u *)"gGwW", nchar) == NULL)
2890 {
2891 clearopbeep(cap->oap);
2892 return OK;
2893 }
2894 undo = TRUE;
2895 }
2896
2897 if (checkclearop(cap->oap))
2898 return OK;
2899 if (VIsual_active && get_visual_text(cap, &ptr, &len) == FAIL)
2900 return FAIL;
2901 if (ptr == NULL)
2902 {
2903 pos_T pos = curwin->w_cursor;
2904
2905 // Find bad word under the cursor. When 'spell' is
2906 // off this fails and find_ident_under_cursor() is
2907 // used below.
2908 emsg_off++;
2909 len = spell_move_to(curwin, FORWARD, TRUE, TRUE, NULL);
2910 emsg_off--;
2911 if (len != 0 && curwin->w_cursor.col <= pos.col)
2912 ptr = ml_get_pos(&curwin->w_cursor);
2913 curwin->w_cursor = pos;
2914 }
2915
2916 if (ptr == NULL
2917 && (len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0)
2918 return FAIL;
2919 spell_add_word(ptr, len, nchar == 'w' || nchar == 'W'
2920 ? SPELL_ADD_BAD : SPELL_ADD_GOOD,
2921 (nchar == 'G' || nchar == 'W') ? 0 : (int)cap->count1, undo);
2922
2923 return OK;
2924 }
2925 #endif
2926
2927 /*
2932 * Commands that start with "z". 2928 * Commands that start with "z".
2933 */ 2929 */
2934 static void 2930 static void
2935 nv_zet(cmdarg_T *cap) 2931 nv_zet(cmdarg_T *cap)
2936 { 2932 {
2939 int nchar = cap->nchar; 2935 int nchar = cap->nchar;
2940 #ifdef FEAT_FOLDING 2936 #ifdef FEAT_FOLDING
2941 long old_fdl = curwin->w_p_fdl; 2937 long old_fdl = curwin->w_p_fdl;
2942 int old_fen = curwin->w_p_fen; 2938 int old_fen = curwin->w_p_fen;
2943 #endif 2939 #endif
2944 #ifdef FEAT_SPELL
2945 int undo = FALSE;
2946 #endif
2947 long siso = get_sidescrolloff_value(); 2940 long siso = get_sidescrolloff_value();
2948 2941
2949 if (VIM_ISDIGIT(nchar)) 2942 if (VIM_ISDIGIT(nchar) && !nv_z_get_count(cap, &nchar))
2950 {
2951 /*
2952 * "z123{nchar}": edit the count before obtaining {nchar}
2953 */
2954 if (checkclearop(cap->oap))
2955 return; 2943 return;
2956 n = nchar - '0'; 2944
2957 for (;;)
2958 {
2959 #ifdef USE_ON_FLY_SCROLL
2960 dont_scroll = TRUE; // disallow scrolling here
2961 #endif
2962 ++no_mapping;
2963 ++allow_keys; // no mapping for nchar, but allow key codes
2964 nchar = plain_vgetc();
2965 LANGMAP_ADJUST(nchar, TRUE);
2966 --no_mapping;
2967 --allow_keys;
2968 #ifdef FEAT_CMDL_INFO
2969 (void)add_to_showcmd(nchar);
2970 #endif
2971 if (nchar == K_DEL || nchar == K_KDEL)
2972 n /= 10;
2973 else if (VIM_ISDIGIT(nchar))
2974 n = n * 10 + (nchar - '0');
2975 else if (nchar == CAR)
2976 {
2977 #ifdef FEAT_GUI
2978 need_mouse_correct = TRUE;
2979 #endif
2980 win_setheight((int)n);
2981 break;
2982 }
2983 else if (nchar == 'l'
2984 || nchar == 'h'
2985 || nchar == K_LEFT
2986 || nchar == K_RIGHT)
2987 {
2988 cap->count1 = n ? n * cap->count1 : cap->count1;
2989 goto dozet;
2990 }
2991 else
2992 {
2993 clearopbeep(cap->oap);
2994 break;
2995 }
2996 }
2997 cap->oap->op_type = OP_NOP;
2998 return;
2999 }
3000
3001 dozet:
3002 if ( 2945 if (
3003 #ifdef FEAT_FOLDING 2946 #ifdef FEAT_FOLDING
3004 // "zf" and "zF" are always an operator, "zd", "zo", "zO", "zc" 2947 // "zf" and "zF" are always an operator, "zd", "zo", "zO", "zc"
3005 // and "zC" only in Visual mode. "zj" and "zk" are motion 2948 // and "zC" only in Visual mode. "zj" and "zk" are motion
3006 // commands. 2949 // commands.
3010 && 2953 &&
3011 #endif 2954 #endif
3012 checkclearop(cap->oap)) 2955 checkclearop(cap->oap))
3013 return; 2956 return;
3014 2957
3015 /* 2958 // For "z+", "z<CR>", "zt", "z.", "zz", "z^", "z-", "zb":
3016 * For "z+", "z<CR>", "zt", "z.", "zz", "z^", "z-", "zb": 2959 // If line number given, set cursor.
3017 * If line number given, set cursor.
3018 */
3019 if ((vim_strchr((char_u *)"+\r\nt.z^-b", nchar) != NULL) 2960 if ((vim_strchr((char_u *)"+\r\nt.z^-b", nchar) != NULL)
3020 && cap->count0 2961 && cap->count0
3021 && cap->count0 != curwin->w_cursor.lnum) 2962 && cap->count0 != curwin->w_cursor.lnum)
3022 { 2963 {
3023 setpcmark(); 2964 setpcmark();
3335 3276
3336 #endif // FEAT_FOLDING 3277 #endif // FEAT_FOLDING
3337 3278
3338 #ifdef FEAT_SPELL 3279 #ifdef FEAT_SPELL
3339 case 'u': // "zug" and "zuw": undo "zg" and "zw" 3280 case 'u': // "zug" and "zuw": undo "zg" and "zw"
3340 ++no_mapping;
3341 ++allow_keys; // no mapping for nchar, but allow key codes
3342 nchar = plain_vgetc();
3343 LANGMAP_ADJUST(nchar, TRUE);
3344 --no_mapping;
3345 --allow_keys;
3346 #ifdef FEAT_CMDL_INFO
3347 (void)add_to_showcmd(nchar);
3348 #endif
3349 if (vim_strchr((char_u *)"gGwW", nchar) == NULL)
3350 {
3351 clearopbeep(cap->oap);
3352 break;
3353 }
3354 undo = TRUE;
3355 // FALLTHROUGH
3356
3357 case 'g': // "zg": add good word to word list 3281 case 'g': // "zg": add good word to word list
3358 case 'w': // "zw": add wrong word to word list 3282 case 'w': // "zw": add wrong word to word list
3359 case 'G': // "zG": add good word to temp word list 3283 case 'G': // "zG": add good word to temp word list
3360 case 'W': // "zW": add wrong word to temp word list 3284 case 'W': // "zW": add wrong word to temp word list
3361 { 3285 if (nv_zg_zw(cap, nchar) == FAIL)
3362 char_u *ptr = NULL; 3286 return;
3363 int len;
3364
3365 if (checkclearop(cap->oap))
3366 break;
3367 if (VIsual_active && get_visual_text(cap, &ptr, &len)
3368 == FAIL)
3369 return;
3370 if (ptr == NULL)
3371 {
3372 pos_T pos = curwin->w_cursor;
3373
3374 // Find bad word under the cursor. When 'spell' is
3375 // off this fails and find_ident_under_cursor() is
3376 // used below.
3377 emsg_off++;
3378 len = spell_move_to(curwin, FORWARD, TRUE, TRUE, NULL);
3379 emsg_off--;
3380 if (len != 0 && curwin->w_cursor.col <= pos.col)
3381 ptr = ml_get_pos(&curwin->w_cursor);
3382 curwin->w_cursor = pos;
3383 }
3384
3385 if (ptr == NULL && (len = find_ident_under_cursor(&ptr,
3386 FIND_IDENT)) == 0)
3387 return;
3388 spell_add_word(ptr, len, nchar == 'w' || nchar == 'W'
3389 ? SPELL_ADD_BAD : SPELL_ADD_GOOD,
3390 (nchar == 'G' || nchar == 'W')
3391 ? 0 : (int)cap->count1,
3392 undo);
3393 }
3394 break; 3287 break;
3395 3288
3396 case '=': // "z=": suggestions for a badly spelled word 3289 case '=': // "z=": suggestions for a badly spelled word
3397 if (!checkclearop(cap->oap)) 3290 if (!checkclearop(cap->oap))
3398 spell_suggest((int)cap->count0); 3291 spell_suggest((int)cap->count0);
3535 * "Q" command. 3428 * "Q" command.
3536 */ 3429 */
3537 static void 3430 static void
3538 nv_exmode(cmdarg_T *cap) 3431 nv_exmode(cmdarg_T *cap)
3539 { 3432 {
3540 /* 3433 // Ignore 'Q' in Visual mode, just give a beep.
3541 * Ignore 'Q' in Visual mode, just give a beep.
3542 */
3543 if (VIsual_active) 3434 if (VIsual_active)
3544 vim_beep(BO_EX); 3435 vim_beep(BO_EX);
3545 else if (!checkclearop(cap->oap)) 3436 else if (!checkclearop(cap->oap))
3546 do_exmode(FALSE); 3437 do_exmode(FALSE);
3547 } 3438 }
3746 CLEAR_FIELD(ca); 3637 CLEAR_FIELD(ca);
3747 ca.oap = &oa; 3638 ca.oap = &oa;
3748 ca.cmdchar = c1; 3639 ca.cmdchar = c1;
3749 ca.nchar = c2; 3640 ca.nchar = c2;
3750 nv_ident(&ca); 3641 nv_ident(&ca);
3642 }
3643
3644 /*
3645 * 'K' normal-mode command. Get the command to lookup the keyword under the
3646 * cursor.
3647 */
3648 static int
3649 nv_K_getcmd(
3650 cmdarg_T *cap,
3651 char_u *kp,
3652 int kp_help,
3653 int kp_ex,
3654 char_u **ptr_arg,
3655 int n,
3656 char_u *buf,
3657 unsigned buflen)
3658 {
3659 char_u *ptr = *ptr_arg;
3660 int isman;
3661 int isman_s;
3662
3663 if (kp_help)
3664 {
3665 // in the help buffer
3666 STRCPY(buf, "he! ");
3667 return n;
3668 }
3669
3670 if (kp_ex)
3671 {
3672 // 'keywordprog' is an ex command
3673 if (cap->count0 != 0)
3674 vim_snprintf((char *)buf, buflen, "%s %ld", kp, cap->count0);
3675 else
3676 STRCPY(buf, kp);
3677 STRCAT(buf, " ");
3678 return n;
3679 }
3680
3681 // An external command will probably use an argument starting
3682 // with "-" as an option. To avoid trouble we skip the "-".
3683 while (*ptr == '-' && n > 0)
3684 {
3685 ++ptr;
3686 --n;
3687 }
3688 if (n == 0)
3689 {
3690 // found dashes only
3691 emsg(_(e_no_identifier_under_cursor));
3692 vim_free(buf);
3693 *ptr_arg = ptr;
3694 return 0;
3695 }
3696
3697 // When a count is given, turn it into a range. Is this
3698 // really what we want?
3699 isman = (STRCMP(kp, "man") == 0);
3700 isman_s = (STRCMP(kp, "man -s") == 0);
3701 if (cap->count0 != 0 && !(isman || isman_s))
3702 sprintf((char *)buf, ".,.+%ld", cap->count0 - 1);
3703
3704 STRCAT(buf, "! ");
3705 if (cap->count0 == 0 && isman_s)
3706 STRCAT(buf, "man");
3707 else
3708 STRCAT(buf, kp);
3709 STRCAT(buf, " ");
3710 if (cap->count0 != 0 && (isman || isman_s))
3711 {
3712 sprintf((char *)buf + STRLEN(buf), "%ld", cap->count0);
3713 STRCAT(buf, " ");
3714 }
3715
3716 *ptr_arg = ptr;
3717 return n;
3751 } 3718 }
3752 3719
3753 /* 3720 /*
3754 * Handle the commands that use the word under the cursor. 3721 * Handle the commands that use the word under the cursor.
3755 * [g] CTRL-] :ta to current identifier 3722 * [g] CTRL-] :ta to current identifier
3772 int n = 0; // init for GCC 3739 int n = 0; // init for GCC
3773 int cmdchar; 3740 int cmdchar;
3774 int g_cmd; // "g" command 3741 int g_cmd; // "g" command
3775 int tag_cmd = FALSE; 3742 int tag_cmd = FALSE;
3776 char_u *aux_ptr; 3743 char_u *aux_ptr;
3777 int isman;
3778 int isman_s;
3779 3744
3780 if (cap->cmdchar == 'g') // "g*", "g#", "g]" and "gCTRL-]" 3745 if (cap->cmdchar == 'g') // "g*", "g#", "g]" and "gCTRL-]"
3781 { 3746 {
3782 cmdchar = cap->nchar; 3747 cmdchar = cap->nchar;
3783 g_cmd = TRUE; 3748 g_cmd = TRUE;
3789 } 3754 }
3790 3755
3791 if (cmdchar == POUND) // the pound sign, '#' for English keyboards 3756 if (cmdchar == POUND) // the pound sign, '#' for English keyboards
3792 cmdchar = '#'; 3757 cmdchar = '#';
3793 3758
3794 /* 3759 // The "]", "CTRL-]" and "K" commands accept an argument in Visual mode.
3795 * The "]", "CTRL-]" and "K" commands accept an argument in Visual mode.
3796 */
3797 if (cmdchar == ']' || cmdchar == Ctrl_RSB || cmdchar == 'K') 3760 if (cmdchar == ']' || cmdchar == Ctrl_RSB || cmdchar == 'K')
3798 { 3761 {
3799 if (VIsual_active && get_visual_text(cap, &ptr, &n) == FAIL) 3762 if (VIsual_active && get_visual_text(cap, &ptr, &n) == FAIL)
3800 return; 3763 return;
3801 if (checkclearopq(cap->oap)) 3764 if (checkclearopq(cap->oap))
3830 3793
3831 switch (cmdchar) 3794 switch (cmdchar)
3832 { 3795 {
3833 case '*': 3796 case '*':
3834 case '#': 3797 case '#':
3835 /* 3798 // Put cursor at start of word, makes search skip the word
3836 * Put cursor at start of word, makes search skip the word 3799 // under the cursor.
3837 * under the cursor. 3800 // Call setpcmark() first, so "*``" puts the cursor back where
3838 * Call setpcmark() first, so "*``" puts the cursor back where 3801 // it was.
3839 * it was.
3840 */
3841 setpcmark(); 3802 setpcmark();
3842 curwin->w_cursor.col = (colnr_T) (ptr - ml_get_curline()); 3803 curwin->w_cursor.col = (colnr_T) (ptr - ml_get_curline());
3843 3804
3844 if (!g_cmd && vim_iswordp(ptr)) 3805 if (!g_cmd && vim_iswordp(ptr))
3845 STRCPY(buf, "\\<"); 3806 STRCPY(buf, "\\<");
3846 no_smartcase = TRUE; // don't use 'smartcase' now 3807 no_smartcase = TRUE; // don't use 'smartcase' now
3847 break; 3808 break;
3848 3809
3849 case 'K': 3810 case 'K':
3850 if (kp_help) 3811 n = nv_K_getcmd(cap, kp, kp_help, kp_ex, &ptr, n, buf, buflen);
3851 STRCPY(buf, "he! "); 3812 if (n == 0)
3852 else if (kp_ex) 3813 return;
3853 {
3854 if (cap->count0 != 0)
3855 vim_snprintf((char *)buf, buflen, "%s %ld",
3856 kp, cap->count0);
3857 else
3858 STRCPY(buf, kp);
3859 STRCAT(buf, " ");
3860 }
3861 else
3862 {
3863 // An external command will probably use an argument starting
3864 // with "-" as an option. To avoid trouble we skip the "-".
3865 while (*ptr == '-' && n > 0)
3866 {
3867 ++ptr;
3868 --n;
3869 }
3870 if (n == 0)
3871 {
3872 // found dashes only
3873 emsg(_(e_no_identifier_under_cursor));
3874 vim_free(buf);
3875 return;
3876 }
3877
3878 // When a count is given, turn it into a range. Is this
3879 // really what we want?
3880 isman = (STRCMP(kp, "man") == 0);
3881 isman_s = (STRCMP(kp, "man -s") == 0);
3882 if (cap->count0 != 0 && !(isman || isman_s))
3883 sprintf((char *)buf, ".,.+%ld", cap->count0 - 1);
3884
3885 STRCAT(buf, "! ");
3886 if (cap->count0 == 0 && isman_s)
3887 STRCAT(buf, "man");
3888 else
3889 STRCAT(buf, kp);
3890 STRCAT(buf, " ");
3891 if (cap->count0 != 0 && (isman || isman_s))
3892 {
3893 sprintf((char *)buf + STRLEN(buf), "%ld", cap->count0);
3894 STRCAT(buf, " ");
3895 }
3896 }
3897 break; 3814 break;
3898 3815
3899 case ']': 3816 case ']':
3900 tag_cmd = TRUE; 3817 tag_cmd = TRUE;
3901 #ifdef FEAT_CSCOPE 3818 #ifdef FEAT_CSCOPE
3919 else 3836 else
3920 sprintf((char *)buf, ":%ldta ", cap->count0); 3837 sprintf((char *)buf, ":%ldta ", cap->count0);
3921 } 3838 }
3922 } 3839 }
3923 3840
3924 /* 3841 // Now grab the chars in the identifier
3925 * Now grab the chars in the identifier
3926 */
3927 if (cmdchar == 'K' && !kp_help) 3842 if (cmdchar == 'K' && !kp_help)
3928 { 3843 {
3929 ptr = vim_strnsave(ptr, n); 3844 ptr = vim_strnsave(ptr, n);
3930 if (kp_ex) 3845 if (kp_ex)
3931 // Escape the argument properly for an Ex command 3846 // Escape the argument properly for an Ex command
3986 *p++ = *ptr++; 3901 *p++ = *ptr++;
3987 } 3902 }
3988 *p = NUL; 3903 *p = NUL;
3989 } 3904 }
3990 3905
3991 /* 3906 // Execute the command.
3992 * Execute the command.
3993 */
3994 if (cmdchar == '*' || cmdchar == '#') 3907 if (cmdchar == '*' || cmdchar == '#')
3995 { 3908 {
3996 if (!g_cmd && (has_mbyte 3909 if (!g_cmd && (has_mbyte
3997 ? vim_iswordp(mb_prevptr(ml_get_curline(), ptr)) 3910 ? vim_iswordp(mb_prevptr(ml_get_curline(), ptr))
3998 : vim_iswordc(ptr[-1]))) 3911 : vim_iswordc(ptr[-1])))
4192 4105
4193 cap->oap->motion_type = MCHAR; 4106 cap->oap->motion_type = MCHAR;
4194 cap->oap->inclusive = FALSE; 4107 cap->oap->inclusive = FALSE;
4195 past_line = (VIsual_active && *p_sel != 'o'); 4108 past_line = (VIsual_active && *p_sel != 'o');
4196 4109
4197 /* 4110 // In virtual edit mode, there's no such thing as "past_line", as lines
4198 * In virtual edit mode, there's no such thing as "past_line", as lines 4111 // are (theoretically) infinitely long.
4199 * are (theoretically) infinitely long.
4200 */
4201 if (virtual_active()) 4112 if (virtual_active())
4202 past_line = 0; 4113 past_line = 0;
4203 4114
4204 for (n = cap->count1; n > 0; --n) 4115 for (n = cap->count1; n > 0; --n)
4205 { 4116 {
4206 if ((!past_line && oneright() == FAIL) 4117 if ((!past_line && oneright() == FAIL)
4207 || (past_line && *ml_get_cursor() == NUL) 4118 || (past_line && *ml_get_cursor() == NUL)
4208 ) 4119 )
4209 { 4120 {
4210 /* 4121 // <Space> wraps to next line if 'whichwrap' has 's'.
4211 * <Space> wraps to next line if 'whichwrap' has 's'. 4122 // 'l' wraps to next line if 'whichwrap' has 'l'.
4212 * 'l' wraps to next line if 'whichwrap' has 'l'. 4123 // CURS_RIGHT wraps to next line if 'whichwrap' has '>'.
4213 * CURS_RIGHT wraps to next line if 'whichwrap' has '>'.
4214 */
4215 if ( ((cap->cmdchar == ' ' 4124 if ( ((cap->cmdchar == ' '
4216 && vim_strchr(p_ww, 's') != NULL) 4125 && vim_strchr(p_ww, 's') != NULL)
4217 || (cap->cmdchar == 'l' 4126 || (cap->cmdchar == 'l'
4218 && vim_strchr(p_ww, 'l') != NULL) 4127 && vim_strchr(p_ww, 'l') != NULL)
4219 || (cap->cmdchar == K_RIGHT 4128 || (cap->cmdchar == K_RIGHT
4644 #endif 4553 #endif
4645 } 4554 }
4646 } 4555 }
4647 4556
4648 /* 4557 /*
4558 * "[{", "[(", "]}" or "])": go to Nth unclosed '{', '(', '}' or ')'
4559 * "[#", "]#": go to start/end of Nth innermost #if..#endif construct.
4560 * "[/", "[*", "]/", "]*": go to Nth comment start/end.
4561 * "[m" or "]m" search for prev/next start of (Java) method.
4562 * "[M" or "]M" search for prev/next end of (Java) method.
4563 */
4564 static void
4565 nv_bracket_block(cmdarg_T *cap, pos_T *old_pos)
4566 {
4567 pos_T new_pos = {0, 0, 0};
4568 pos_T *pos = NULL; // init for GCC
4569 pos_T prev_pos;
4570 long n;
4571 int findc;
4572 int c;
4573
4574 if (cap->nchar == '*')
4575 cap->nchar = '/';
4576 prev_pos.lnum = 0;
4577 if (cap->nchar == 'm' || cap->nchar == 'M')
4578 {
4579 if (cap->cmdchar == '[')
4580 findc = '{';
4581 else
4582 findc = '}';
4583 n = 9999;
4584 }
4585 else
4586 {
4587 findc = cap->nchar;
4588 n = cap->count1;
4589 }
4590 for ( ; n > 0; --n)
4591 {
4592 if ((pos = findmatchlimit(cap->oap, findc,
4593 (cap->cmdchar == '[') ? FM_BACKWARD : FM_FORWARD, 0)) == NULL)
4594 {
4595 if (new_pos.lnum == 0) // nothing found
4596 {
4597 if (cap->nchar != 'm' && cap->nchar != 'M')
4598 clearopbeep(cap->oap);
4599 }
4600 else
4601 pos = &new_pos; // use last one found
4602 break;
4603 }
4604 prev_pos = new_pos;
4605 curwin->w_cursor = *pos;
4606 new_pos = *pos;
4607 }
4608 curwin->w_cursor = *old_pos;
4609
4610 // Handle "[m", "]m", "[M" and "[M". The findmatchlimit() only
4611 // brought us to the match for "[m" and "]M" when inside a method.
4612 // Try finding the '{' or '}' we want to be at.
4613 // Also repeat for the given count.
4614 if (cap->nchar == 'm' || cap->nchar == 'M')
4615 {
4616 // norm is TRUE for "]M" and "[m"
4617 int norm = ((findc == '{') == (cap->nchar == 'm'));
4618
4619 n = cap->count1;
4620 // found a match: we were inside a method
4621 if (prev_pos.lnum != 0)
4622 {
4623 pos = &prev_pos;
4624 curwin->w_cursor = prev_pos;
4625 if (norm)
4626 --n;
4627 }
4628 else
4629 pos = NULL;
4630 while (n > 0)
4631 {
4632 for (;;)
4633 {
4634 if ((findc == '{' ? dec_cursor() : inc_cursor()) < 0)
4635 {
4636 // if not found anything, that's an error
4637 if (pos == NULL)
4638 clearopbeep(cap->oap);
4639 n = 0;
4640 break;
4641 }
4642 c = gchar_cursor();
4643 if (c == '{' || c == '}')
4644 {
4645 // Must have found end/start of class: use it.
4646 // Or found the place to be at.
4647 if ((c == findc && norm) || (n == 1 && !norm))
4648 {
4649 new_pos = curwin->w_cursor;
4650 pos = &new_pos;
4651 n = 0;
4652 }
4653 // if no match found at all, we started outside of the
4654 // class and we're inside now. Just go on.
4655 else if (new_pos.lnum == 0)
4656 {
4657 new_pos = curwin->w_cursor;
4658 pos = &new_pos;
4659 }
4660 // found start/end of other method: go to match
4661 else if ((pos = findmatchlimit(cap->oap, findc,
4662 (cap->cmdchar == '[') ? FM_BACKWARD : FM_FORWARD,
4663 0)) == NULL)
4664 n = 0;
4665 else
4666 curwin->w_cursor = *pos;
4667 break;
4668 }
4669 }
4670 --n;
4671 }
4672 curwin->w_cursor = *old_pos;
4673 if (pos == NULL && new_pos.lnum != 0)
4674 clearopbeep(cap->oap);
4675 }
4676 if (pos != NULL)
4677 {
4678 setpcmark();
4679 curwin->w_cursor = *pos;
4680 curwin->w_set_curswant = TRUE;
4681 #ifdef FEAT_FOLDING
4682 if ((fdo_flags & FDO_BLOCK) && KeyTyped
4683 && cap->oap->op_type == OP_NOP)
4684 foldOpenCursor();
4685 #endif
4686 }
4687 }
4688
4689 /*
4649 * "[" and "]" commands. 4690 * "[" and "]" commands.
4650 * cap->arg is BACKWARD for "[" and FORWARD for "]". 4691 * cap->arg is BACKWARD for "[" and FORWARD for "]".
4651 */ 4692 */
4652 static void 4693 static void
4653 nv_brackets(cmdarg_T *cap) 4694 nv_brackets(cmdarg_T *cap)
4654 { 4695 {
4655 pos_T new_pos = {0, 0, 0};
4656 pos_T prev_pos; 4696 pos_T prev_pos;
4657 pos_T *pos = NULL; // init for GCC 4697 pos_T *pos = NULL; // init for GCC
4658 pos_T old_pos; // cursor position before command 4698 pos_T old_pos; // cursor position before command
4659 int flag; 4699 int flag;
4660 long n; 4700 long n;
4661 int findc;
4662 int c;
4663 4701
4664 cap->oap->motion_type = MCHAR; 4702 cap->oap->motion_type = MCHAR;
4665 cap->oap->inclusive = FALSE; 4703 cap->oap->inclusive = FALSE;
4666 old_pos = curwin->w_cursor; 4704 old_pos = curwin->w_cursor;
4667 curwin->w_cursor.coladd = 0; // TODO: don't do this for an error. 4705 curwin->w_cursor.coladd = 0; // TODO: don't do this for an error.
4668 4706
4669 #ifdef FEAT_SEARCHPATH 4707 #ifdef FEAT_SEARCHPATH
4670 /* 4708 // "[f" or "]f" : Edit file under the cursor (same as "gf")
4671 * "[f" or "]f" : Edit file under the cursor (same as "gf")
4672 */
4673 if (cap->nchar == 'f') 4709 if (cap->nchar == 'f')
4674 nv_gotofile(cap); 4710 nv_gotofile(cap);
4675 else 4711 else
4676 #endif 4712 #endif
4677 4713
4678 #ifdef FEAT_FIND_ID 4714 #ifdef FEAT_FIND_ID
4679 /* 4715 // Find the occurrence(s) of the identifier or define under cursor
4680 * Find the occurrence(s) of the identifier or define under cursor 4716 // in current and included files or jump to the first occurrence.
4681 * in current and included files or jump to the first occurrence. 4717 //
4682 * 4718 // search list jump
4683 * search list jump 4719 // fwd bwd fwd bwd fwd bwd
4684 * fwd bwd fwd bwd fwd bwd 4720 // identifier "]i" "[i" "]I" "[I" "]^I" "[^I"
4685 * identifier "]i" "[i" "]I" "[I" "]^I" "[^I" 4721 // define "]d" "[d" "]D" "[D" "]^D" "[^D"
4686 * define "]d" "[d" "]D" "[D" "]^D" "[^D"
4687 */
4688 if (vim_strchr((char_u *) 4722 if (vim_strchr((char_u *)
4689 # ifdef EBCDIC 4723 # ifdef EBCDIC
4690 "iI\005dD\067", 4724 "iI\005dD\067",
4691 # else 4725 # else
4692 "iI\011dD\004", 4726 "iI\011dD\004",
4712 } 4746 }
4713 } 4747 }
4714 else 4748 else
4715 #endif 4749 #endif
4716 4750
4717 /* 4751 // "[{", "[(", "]}" or "])": go to Nth unclosed '{', '(', '}' or ')'
4718 * "[{", "[(", "]}" or "])": go to Nth unclosed '{', '(', '}' or ')' 4752 // "[#", "]#": go to start/end of Nth innermost #if..#endif construct.
4719 * "[#", "]#": go to start/end of Nth innermost #if..#endif construct. 4753 // "[/", "[*", "]/", "]*": go to Nth comment start/end.
4720 * "[/", "[*", "]/", "]*": go to Nth comment start/end. 4754 // "[m" or "]m" search for prev/next start of (Java) method.
4721 * "[m" or "]m" search for prev/next start of (Java) method. 4755 // "[M" or "]M" search for prev/next end of (Java) method.
4722 * "[M" or "]M" search for prev/next end of (Java) method.
4723 */
4724 if ( (cap->cmdchar == '[' 4756 if ( (cap->cmdchar == '['
4725 && vim_strchr((char_u *)"{(*/#mM", cap->nchar) != NULL) 4757 && vim_strchr((char_u *)"{(*/#mM", cap->nchar) != NULL)
4726 || (cap->cmdchar == ']' 4758 || (cap->cmdchar == ']'
4727 && vim_strchr((char_u *)"})*/#mM", cap->nchar) != NULL)) 4759 && vim_strchr((char_u *)"})*/#mM", cap->nchar) != NULL))
4728 { 4760 nv_bracket_block(cap, &old_pos);
4729 if (cap->nchar == '*') 4761
4730 cap->nchar = '/'; 4762 // "[[", "[]", "]]" and "][": move to start or end of function
4731 prev_pos.lnum = 0;
4732 if (cap->nchar == 'm' || cap->nchar == 'M')
4733 {
4734 if (cap->cmdchar == '[')
4735 findc = '{';
4736 else
4737 findc = '}';
4738 n = 9999;
4739 }
4740 else
4741 {
4742 findc = cap->nchar;
4743 n = cap->count1;
4744 }
4745 for ( ; n > 0; --n)
4746 {
4747 if ((pos = findmatchlimit(cap->oap, findc,
4748 (cap->cmdchar == '[') ? FM_BACKWARD : FM_FORWARD, 0)) == NULL)
4749 {
4750 if (new_pos.lnum == 0) // nothing found
4751 {
4752 if (cap->nchar != 'm' && cap->nchar != 'M')
4753 clearopbeep(cap->oap);
4754 }
4755 else
4756 pos = &new_pos; // use last one found
4757 break;
4758 }
4759 prev_pos = new_pos;
4760 curwin->w_cursor = *pos;
4761 new_pos = *pos;
4762 }
4763 curwin->w_cursor = old_pos;
4764
4765 /*
4766 * Handle "[m", "]m", "[M" and "[M". The findmatchlimit() only
4767 * brought us to the match for "[m" and "]M" when inside a method.
4768 * Try finding the '{' or '}' we want to be at.
4769 * Also repeat for the given count.
4770 */
4771 if (cap->nchar == 'm' || cap->nchar == 'M')
4772 {
4773 // norm is TRUE for "]M" and "[m"
4774 int norm = ((findc == '{') == (cap->nchar == 'm'));
4775
4776 n = cap->count1;
4777 // found a match: we were inside a method
4778 if (prev_pos.lnum != 0)
4779 {
4780 pos = &prev_pos;
4781 curwin->w_cursor = prev_pos;
4782 if (norm)
4783 --n;
4784 }
4785 else
4786 pos = NULL;
4787 while (n > 0)
4788 {
4789 for (;;)
4790 {
4791 if ((findc == '{' ? dec_cursor() : inc_cursor()) < 0)
4792 {
4793 // if not found anything, that's an error
4794 if (pos == NULL)
4795 clearopbeep(cap->oap);
4796 n = 0;
4797 break;
4798 }
4799 c = gchar_cursor();
4800 if (c == '{' || c == '}')
4801 {
4802 // Must have found end/start of class: use it.
4803 // Or found the place to be at.
4804 if ((c == findc && norm) || (n == 1 && !norm))
4805 {
4806 new_pos = curwin->w_cursor;
4807 pos = &new_pos;
4808 n = 0;
4809 }
4810 // if no match found at all, we started outside of the
4811 // class and we're inside now. Just go on.
4812 else if (new_pos.lnum == 0)
4813 {
4814 new_pos = curwin->w_cursor;
4815 pos = &new_pos;
4816 }
4817 // found start/end of other method: go to match
4818 else if ((pos = findmatchlimit(cap->oap, findc,
4819 (cap->cmdchar == '[') ? FM_BACKWARD : FM_FORWARD,
4820 0)) == NULL)
4821 n = 0;
4822 else
4823 curwin->w_cursor = *pos;
4824 break;
4825 }
4826 }
4827 --n;
4828 }
4829 curwin->w_cursor = old_pos;
4830 if (pos == NULL && new_pos.lnum != 0)
4831 clearopbeep(cap->oap);
4832 }
4833 if (pos != NULL)
4834 {
4835 setpcmark();
4836 curwin->w_cursor = *pos;
4837 curwin->w_set_curswant = TRUE;
4838 #ifdef FEAT_FOLDING
4839 if ((fdo_flags & FDO_BLOCK) && KeyTyped
4840 && cap->oap->op_type == OP_NOP)
4841 foldOpenCursor();
4842 #endif
4843 }
4844 }
4845
4846 /*
4847 * "[[", "[]", "]]" and "][": move to start or end of function
4848 */
4849 else if (cap->nchar == '[' || cap->nchar == ']') 4763 else if (cap->nchar == '[' || cap->nchar == ']')
4850 { 4764 {
4851 if (cap->nchar == cap->cmdchar) // "]]" or "[[" 4765 if (cap->nchar == cap->cmdchar) // "]]" or "[["
4852 flag = '{'; 4766 flag = '{';
4853 else 4767 else
4854 flag = '}'; // "][" or "[]" 4768 flag = '}'; // "][" or "[]"
4855 4769
4856 curwin->w_set_curswant = TRUE; 4770 curwin->w_set_curswant = TRUE;
4857 /* 4771 // Imitate strange Vi behaviour: When using "]]" with an operator
4858 * Imitate strange Vi behaviour: When using "]]" with an operator 4772 // we also stop at '}'.
4859 * we also stop at '}'.
4860 */
4861 if (!findpar(&cap->oap->inclusive, cap->arg, cap->count1, flag, 4773 if (!findpar(&cap->oap->inclusive, cap->arg, cap->count1, flag,
4862 (cap->oap->op_type != OP_NOP 4774 (cap->oap->op_type != OP_NOP
4863 && cap->arg == FORWARD && flag == '{'))) 4775 && cap->arg == FORWARD && flag == '{')))
4864 clearopbeep(cap->oap); 4776 clearopbeep(cap->oap);
4865 else 4777 else
4871 foldOpenCursor(); 4783 foldOpenCursor();
4872 #endif 4784 #endif
4873 } 4785 }
4874 } 4786 }
4875 4787
4876 /* 4788 // "[p", "[P", "]P" and "]p": put with indent adjustment
4877 * "[p", "[P", "]P" and "]p": put with indent adjustment
4878 */
4879 else if (cap->nchar == 'p' || cap->nchar == 'P') 4789 else if (cap->nchar == 'p' || cap->nchar == 'P')
4880 { 4790 {
4881 nv_put_opt(cap, TRUE); 4791 nv_put_opt(cap, TRUE);
4882 } 4792 }
4883 4793
4884 /* 4794 // "['", "[`", "]'" and "]`": jump to next mark
4885 * "['", "[`", "]'" and "]`": jump to next mark
4886 */
4887 else if (cap->nchar == '\'' || cap->nchar == '`') 4795 else if (cap->nchar == '\'' || cap->nchar == '`')
4888 { 4796 {
4889 pos = &curwin->w_cursor; 4797 pos = &curwin->w_cursor;
4890 for (n = cap->count1; n > 0; --n) 4798 for (n = cap->count1; n > 0; --n)
4891 { 4799 {
4898 if (pos == NULL) 4806 if (pos == NULL)
4899 pos = &prev_pos; 4807 pos = &prev_pos;
4900 nv_cursormark(cap, cap->nchar == '\'', pos); 4808 nv_cursormark(cap, cap->nchar == '\'', pos);
4901 } 4809 }
4902 4810
4903 /* 4811 // [ or ] followed by a middle mouse click: put selected text with
4904 * [ or ] followed by a middle mouse click: put selected text with 4812 // indent adjustment. Any other button just does as usual.
4905 * indent adjustment. Any other button just does as usual.
4906 */
4907 else if (cap->nchar >= K_RIGHTRELEASE && cap->nchar <= K_LEFTMOUSE) 4813 else if (cap->nchar >= K_RIGHTRELEASE && cap->nchar <= K_LEFTMOUSE)
4908 { 4814 {
4909 (void)do_mouse(cap->oap, cap->nchar, 4815 (void)do_mouse(cap->oap, cap->nchar,
4910 (cap->cmdchar == ']') ? FORWARD : BACKWARD, 4816 (cap->cmdchar == ']') ? FORWARD : BACKWARD,
4911 cap->count1, PUT_FIXINDENT); 4817 cap->count1, PUT_FIXINDENT);
4912 } 4818 }
4913 4819
4914 #ifdef FEAT_FOLDING 4820 #ifdef FEAT_FOLDING
4915 /* 4821 // "[z" and "]z": move to start or end of open fold.
4916 * "[z" and "]z": move to start or end of open fold.
4917 */
4918 else if (cap->nchar == 'z') 4822 else if (cap->nchar == 'z')
4919 { 4823 {
4920 if (foldMoveTo(FALSE, cap->cmdchar == ']' ? FORWARD : BACKWARD, 4824 if (foldMoveTo(FALSE, cap->cmdchar == ']' ? FORWARD : BACKWARD,
4921 cap->count1) == FAIL) 4825 cap->count1) == FAIL)
4922 clearopbeep(cap->oap); 4826 clearopbeep(cap->oap);
4923 } 4827 }
4924 #endif 4828 #endif
4925 4829
4926 #ifdef FEAT_DIFF 4830 #ifdef FEAT_DIFF
4927 /* 4831 // "[c" and "]c": move to next or previous diff-change.
4928 * "[c" and "]c": move to next or previous diff-change.
4929 */
4930 else if (cap->nchar == 'c') 4832 else if (cap->nchar == 'c')
4931 { 4833 {
4932 if (diff_move_to(cap->cmdchar == ']' ? FORWARD : BACKWARD, 4834 if (diff_move_to(cap->cmdchar == ']' ? FORWARD : BACKWARD,
4933 cap->count1) == FAIL) 4835 cap->count1) == FAIL)
4934 clearopbeep(cap->oap); 4836 clearopbeep(cap->oap);
4935 } 4837 }
4936 #endif 4838 #endif
4937 4839
4938 #ifdef FEAT_SPELL 4840 #ifdef FEAT_SPELL
4939 /* 4841 // "[s", "[S", "]s" and "]S": move to next spell error.
4940 * "[s", "[S", "]s" and "]S": move to next spell error.
4941 */
4942 else if (cap->nchar == 's' || cap->nchar == 'S') 4842 else if (cap->nchar == 's' || cap->nchar == 'S')
4943 { 4843 {
4944 setpcmark(); 4844 setpcmark();
4945 for (n = 0; n < cap->count1; ++n) 4845 for (n = 0; n < cap->count1; ++n)
4946 if (spell_move_to(curwin, cap->cmdchar == ']' ? FORWARD : BACKWARD, 4846 if (spell_move_to(curwin, cap->cmdchar == ']' ? FORWARD : BACKWARD,
5203 { 5103 {
5204 clearopbeep(cap->oap); 5104 clearopbeep(cap->oap);
5205 return; 5105 return;
5206 } 5106 }
5207 5107
5208 /* 5108 // Replacing with a TAB is done by edit() when it is complicated because
5209 * Replacing with a TAB is done by edit() when it is complicated because 5109 // 'expandtab' or 'smarttab' is set. CTRL-V TAB inserts a literal TAB.
5210 * 'expandtab' or 'smarttab' is set. CTRL-V TAB inserts a literal TAB. 5110 // Other characters are done below to avoid problems with things like
5211 * Other characters are done below to avoid problems with things like 5111 // CTRL-V 048 (for edit() this would be R CTRL-V 0 ESC).
5212 * CTRL-V 048 (for edit() this would be R CTRL-V 0 ESC).
5213 */
5214 if (had_ctrl_v != Ctrl_V && cap->nchar == '\t' && (curbuf->b_p_et || p_sta)) 5112 if (had_ctrl_v != Ctrl_V && cap->nchar == '\t' && (curbuf->b_p_et || p_sta))
5215 { 5113 {
5216 stuffnumReadbuff(cap->count1); 5114 stuffnumReadbuff(cap->count1);
5217 stuffcharReadbuff('R'); 5115 stuffcharReadbuff('R');
5218 stuffcharReadbuff('\t'); 5116 stuffcharReadbuff('\t');
5224 if (u_save_cursor() == FAIL) 5122 if (u_save_cursor() == FAIL)
5225 return; 5123 return;
5226 5124
5227 if (had_ctrl_v != Ctrl_V && (cap->nchar == '\r' || cap->nchar == '\n')) 5125 if (had_ctrl_v != Ctrl_V && (cap->nchar == '\r' || cap->nchar == '\n'))
5228 { 5126 {
5229 /* 5127 // Replace character(s) by a single newline.
5230 * Replace character(s) by a single newline. 5128 // Strange vi behaviour: Only one newline is inserted.
5231 * Strange vi behaviour: Only one newline is inserted. 5129 // Delete the characters here.
5232 * Delete the characters here. 5130 // Insert the newline with an insert command, takes care of
5233 * Insert the newline with an insert command, takes care of 5131 // autoindent. The insert command depends on being on the last
5234 * autoindent. The insert command depends on being on the last 5132 // character of a line or not.
5235 * character of a line or not.
5236 */
5237 (void)del_chars(cap->count1, FALSE); // delete the characters 5133 (void)del_chars(cap->count1, FALSE); // delete the characters
5238 stuffcharReadbuff('\r'); 5134 stuffcharReadbuff('\r');
5239 stuffcharReadbuff(ESC); 5135 stuffcharReadbuff(ESC);
5240 5136
5241 // Give 'r' to edit(), to get the redo command right. 5137 // Give 'r' to edit(), to get the redo command right.
5281 ins_char(cap->ncharC2); 5177 ins_char(cap->ncharC2);
5282 } 5178 }
5283 } 5179 }
5284 else 5180 else
5285 { 5181 {
5286 /* 5182 // Replace the characters within one line.
5287 * Replace the characters within one line.
5288 */
5289 for (n = cap->count1; n > 0; --n) 5183 for (n = cap->count1; n > 0; --n)
5290 { 5184 {
5291 /* 5185 // Get ptr again, because u_save and/or showmatch() will have
5292 * Get ptr again, because u_save and/or showmatch() will have 5186 // released the line. This may also happen in ins_copychar().
5293 * released the line. This may also happen in ins_copychar(). 5187 // At the same time we let know that the line will be changed.
5294 * At the same time we let know that the line will be changed.
5295 */
5296 if (cap->nchar == Ctrl_E || cap->nchar == Ctrl_Y) 5188 if (cap->nchar == Ctrl_E || cap->nchar == Ctrl_Y)
5297 { 5189 {
5298 int c = ins_copychar(curwin->w_cursor.lnum 5190 int c = ins_copychar(curwin->w_cursor.lnum
5299 + (cap->nchar == Ctrl_Y ? -1 : 1)); 5191 + (cap->nchar == Ctrl_Y ? -1 : 1));
5300 5192
5847 // start Select mode when 'selectmode' contains "cmd" 5739 // start Select mode when 'selectmode' contains "cmd"
5848 may_start_select('c'); 5740 may_start_select('c');
5849 setmouse(); 5741 setmouse();
5850 if (p_smd && msg_silent == 0) 5742 if (p_smd && msg_silent == 0)
5851 redraw_cmdline = TRUE; // show visual mode later 5743 redraw_cmdline = TRUE; // show visual mode later
5852 /* 5744 // For V and ^V, we multiply the number of lines even if there
5853 * For V and ^V, we multiply the number of lines even if there 5745 // was only one -- webb
5854 * was only one -- webb
5855 */
5856 if (resel_VIsual_mode != 'v' || resel_VIsual_line_count > 1) 5746 if (resel_VIsual_mode != 'v' || resel_VIsual_line_count > 1)
5857 { 5747 {
5858 curwin->w_cursor.lnum += 5748 curwin->w_cursor.lnum +=
5859 resel_VIsual_line_count * cap->count0 - 1; 5749 resel_VIsual_line_count * cap->count0 - 1;
5860 check_cursor(); 5750 check_cursor();
6675 static void 6565 static void
6676 nv_dot(cmdarg_T *cap) 6566 nv_dot(cmdarg_T *cap)
6677 { 6567 {
6678 if (!checkclearopq(cap->oap)) 6568 if (!checkclearopq(cap->oap))
6679 { 6569 {
6680 /* 6570 // If "restart_edit" is TRUE, the last but one command is repeated
6681 * If "restart_edit" is TRUE, the last but one command is repeated 6571 // instead of the last command (inserting text). This is used for
6682 * instead of the last command (inserting text). This is used for 6572 // CTRL-O <.> in insert mode.
6683 * CTRL-O <.> in insert mode.
6684 */
6685 if (start_redo(cap->count0, restart_edit != 0 && !arrow_used) == FAIL) 6573 if (start_redo(cap->count0, restart_edit != 0 && !arrow_used) == FAIL)
6686 clearopbeep(cap->oap); 6574 clearopbeep(cap->oap);
6687 } 6575 }
6688 } 6576 }
6689 6577
6905 int n; 6793 int n;
6906 int word_end; 6794 int word_end;
6907 int flag = FALSE; 6795 int flag = FALSE;
6908 pos_T startpos = curwin->w_cursor; 6796 pos_T startpos = curwin->w_cursor;
6909 6797
6910 /* 6798 // Set inclusive for the "E" and "e" command.
6911 * Set inclusive for the "E" and "e" command.
6912 */
6913 if (cap->cmdchar == 'e' || cap->cmdchar == 'E') 6799 if (cap->cmdchar == 'e' || cap->cmdchar == 'E')
6914 word_end = TRUE; 6800 word_end = TRUE;
6915 else 6801 else
6916 word_end = FALSE; 6802 word_end = FALSE;
6917 cap->oap->inclusive = word_end; 6803 cap->oap->inclusive = word_end;
6918 6804
6919 /* 6805 // "cw" and "cW" are a special case.
6920 * "cw" and "cW" are a special case.
6921 */
6922 if (!word_end && cap->oap->op_type == OP_CHANGE) 6806 if (!word_end && cap->oap->op_type == OP_CHANGE)
6923 { 6807 {
6924 n = gchar_cursor(); 6808 n = gchar_cursor();
6925 if (n != NUL) // not an empty line 6809 if (n != NUL) // not an empty line
6926 { 6810 {
6927 if (VIM_ISWHITE(n)) 6811 if (VIM_ISWHITE(n))
6928 { 6812 {
6929 /* 6813 // Reproduce a funny Vi behaviour: "cw" on a blank only
6930 * Reproduce a funny Vi behaviour: "cw" on a blank only 6814 // changes one character, not all blanks until the start of
6931 * changes one character, not all blanks until the start of 6815 // the next word. Only do this when the 'w' flag is included
6932 * the next word. Only do this when the 'w' flag is included 6816 // in 'cpoptions'.
6933 * in 'cpoptions'.
6934 */
6935 if (cap->count1 == 1 && vim_strchr(p_cpo, CPO_CW) != NULL) 6817 if (cap->count1 == 1 && vim_strchr(p_cpo, CPO_CW) != NULL)
6936 { 6818 {
6937 cap->oap->inclusive = TRUE; 6819 cap->oap->inclusive = TRUE;
6938 cap->oap->motion_type = MCHAR; 6820 cap->oap->motion_type = MCHAR;
6939 return; 6821 return;
6940 } 6822 }
6941 } 6823 }
6942 else 6824 else
6943 { 6825 {
6944 /* 6826 // This is a little strange. To match what the real Vi does,
6945 * This is a little strange. To match what the real Vi does, 6827 // we effectively map 'cw' to 'ce', and 'cW' to 'cE', provided
6946 * we effectively map 'cw' to 'ce', and 'cW' to 'cE', provided 6828 // that we are not on a space or a TAB. This seems impolite
6947 * that we are not on a space or a TAB. This seems impolite 6829 // at first, but it's really more what we mean when we say
6948 * at first, but it's really more what we mean when we say 6830 // 'cw'.
6949 * 'cw'. 6831 // Another strangeness: When standing on the end of a word
6950 * Another strangeness: When standing on the end of a word 6832 // "ce" will change until the end of the next word, but "cw"
6951 * "ce" will change until the end of the next word, but "cw" 6833 // will change only one character! This is done by setting
6952 * will change only one character! This is done by setting 6834 // flag.
6953 * flag.
6954 */
6955 cap->oap->inclusive = TRUE; 6835 cap->oap->inclusive = TRUE;
6956 word_end = TRUE; 6836 word_end = TRUE;
6957 flag = TRUE; 6837 flag = TRUE;
6958 } 6838 }
6959 } 6839 }