From ac04eb3657f99f6952971d8ceb8a82d73b783de8 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Wed, 16 Jun 2021 14:46:01 +0100 Subject: vi: up/down motion beyond end of file should fail In traditional vi and vim line motion commands ('+'/'-'/'j'/'k') fail if the movement would exceed the bounds of the file. BusyBox vi allowed such commands to succeed, leaving the cursor on the first or last character of the file. Make BusyBox vi work like vi/vim. For the 'G'/'H'/'L' commands traditional vi treats an out of bounds result as an error, vim doesn't. BusyBox vi behaves like vim, both before and after this patch. function old new delta do_cmd 4785 4851 +66 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/0 up/down: 66/0) Total: 66 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- editors/vi.c | 63 ++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 25 deletions(-) (limited to 'editors') diff --git a/editors/vi.c b/editors/vi.c index 3daa075..231c628 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -3635,24 +3635,30 @@ static void do_cmd(int c) case 10: // Newline ^J case 'j': // j- goto next line, same col case KEYCODE_DOWN: // cursor key Down + case 13: // Carriage Return ^M + case '+': // +- goto next line + q = dot; do { - dot_next(); // go to next B-o-l + p = next_line(q); + if (p == end_line(q)) { + indicate_error(); + goto dc1; + } + q = p; } while (--cmdcnt > 0); - // try to stay in saved column - dot = cindex == C_END ? end_line(dot) : move_to_col(dot, cindex); - keep_index = TRUE; + dot = q; + if (c == 13 || c == '+') { + dot_skip_over_ws(); + } else { + // try to stay in saved column + dot = cindex == C_END ? end_line(dot) : move_to_col(dot, cindex); + keep_index = TRUE; + } break; case 12: // ctrl-L force redraw whole screen case 18: // ctrl-R force redraw redraw(TRUE); // this will redraw the entire display break; - case 13: // Carriage Return ^M - case '+': // +- goto next line - do { - dot_next(); - } while (--cmdcnt > 0); - dot_skip_over_ws(); - break; case 21: // ctrl-U scroll up half screen dot_scroll((rows - 2) / 2, -1); break; @@ -3818,12 +3824,6 @@ static void do_cmd(int c) case ',': // ,- repeat latest search in opposite direction dot_to_char(c != ',' ? last_search_cmd : last_search_cmd ^ 0x20); break; - case '-': // -- goto prev line - do { - dot_prev(); - } while (--cmdcnt > 0); - dot_skip_over_ws(); - break; #if ENABLE_FEATURE_VI_DOT_CMD case '.': // .- repeat the last modifying command // Stuff the last_modifying_cmd back into stdin @@ -4029,9 +4029,10 @@ static void do_cmd(int c) if (cmdcnt > (rows - 1)) { cmdcnt = (rows - 1); } - if (--cmdcnt > 0) { - do_cmd('+'); + while (--cmdcnt > 0) { + dot_next(); } + dot_begin(); dot_skip_over_ws(); break; case 'I': // I- insert before first non-blank @@ -4068,8 +4069,8 @@ static void do_cmd(int c) if (cmdcnt > (rows - 1)) { cmdcnt = (rows - 1); } - if (--cmdcnt > 0) { - do_cmd('-'); + while (--cmdcnt > 0) { + dot_prev(); } dot_begin(); dot_skip_over_ws(); @@ -4234,12 +4235,24 @@ static void do_cmd(int c) } case 'k': // k- goto prev line, same col case KEYCODE_UP: // cursor key Up + case '-': // -- goto prev line + q = dot; do { - dot_prev(); + p = prev_line(q); + if (p == begin_line(q)) { + indicate_error(); + goto dc1; + } + q = p; } while (--cmdcnt > 0); - // try to stay in saved column - dot = cindex == C_END ? end_line(dot) : move_to_col(dot, cindex); - keep_index = TRUE; + dot = q; + if (c == '-') { + dot_skip_over_ws(); + } else { + // try to stay in saved column + dot = cindex == C_END ? end_line(dot) : move_to_col(dot, cindex); + keep_index = TRUE; + } break; case 'r': // r- replace the current char with user input c1 = get_one_char(); // get the replacement char -- cgit v1.1