Mercurial > vim
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 } |