diff options
Diffstat (limited to 'editors')
-rw-r--r-- | editors/Config.in | 12 | ||||
-rw-r--r-- | editors/cmp.c | 26 | ||||
-rw-r--r-- | editors/sed.c | 26 | ||||
-rw-r--r-- | editors/vi.c | 41 |
4 files changed, 67 insertions, 38 deletions
diff --git a/editors/Config.in b/editors/Config.in index e4fdd0f38..5f9566f0a 100644 --- a/editors/Config.in +++ b/editors/Config.in | |||
@@ -168,6 +168,18 @@ config FEATURE_VI_WIN_RESIZE | |||
168 | help | 168 | help |
169 | Make busybox vi behave nicely with terminals that get resized. | 169 | Make busybox vi behave nicely with terminals that get resized. |
170 | 170 | ||
171 | config FEATURE_VI_ASK_TERMINAL | ||
172 | bool "Use 'tell me cursor position' ESC sequence to measure window" | ||
173 | default n | ||
174 | depends on VI | ||
175 | help | ||
176 | If terminal size can't be retrieved and $LINES/$COLUMNS are not set, | ||
177 | this option makes vi perform a last-ditch effort to find it: | ||
178 | vi positions cursor to 999,999 and asks terminal to report real | ||
179 | cursor position using "ESC [ 6 n" escape sequence, then reads stdin. | ||
180 | |||
181 | This is not clean but helps a lot on serial lines and such. | ||
182 | |||
171 | config FEATURE_VI_OPTIMIZE_CURSOR | 183 | config FEATURE_VI_OPTIMIZE_CURSOR |
172 | bool "Optimize cursor movement" | 184 | bool "Optimize cursor movement" |
173 | default y | 185 | default y |
diff --git a/editors/cmp.c b/editors/cmp.c index 0cb80f21e..dbfa4be35 100644 --- a/editors/cmp.c +++ b/editors/cmp.c | |||
@@ -10,17 +10,6 @@ | |||
10 | /* BB_AUDIT SUSv3 (virtually) compliant -- uses nicer GNU format for -l. */ | 10 | /* BB_AUDIT SUSv3 (virtually) compliant -- uses nicer GNU format for -l. */ |
11 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/cmp.html */ | 11 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/cmp.html */ |
12 | 12 | ||
13 | /* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) | ||
14 | * | ||
15 | * Original version majorly reworked for SUSv3 compliance, bug fixes, and | ||
16 | * size optimizations. Changes include: | ||
17 | * 1) Now correctly distinguishes between errors and actual file differences. | ||
18 | * 2) Proper handling of '-' args. | ||
19 | * 3) Actual error checking of i/o. | ||
20 | * 4) Accept SUSv3 -l option. Note that we use the slightly nicer gnu format | ||
21 | * in the '-l' case. | ||
22 | */ | ||
23 | |||
24 | #include "libbb.h" | 13 | #include "libbb.h" |
25 | 14 | ||
26 | static const char fmt_eof[] ALIGN1 = "cmp: EOF on %s\n"; | 15 | static const char fmt_eof[] ALIGN1 = "cmp: EOF on %s\n"; |
@@ -37,8 +26,7 @@ int cmp_main(int argc UNUSED_PARAM, char **argv) | |||
37 | { | 26 | { |
38 | FILE *fp1, *fp2, *outfile = stdout; | 27 | FILE *fp1, *fp2, *outfile = stdout; |
39 | const char *filename1, *filename2 = "-"; | 28 | const char *filename1, *filename2 = "-"; |
40 | IF_DESKTOP(off_t skip1 = 0, skip2 = 0;) | 29 | off_t skip1 = 0, skip2 = 0, char_pos = 0; |
41 | off_t char_pos = 0; | ||
42 | int line_pos = 1; /* Hopefully won't overflow... */ | 30 | int line_pos = 1; /* Hopefully won't overflow... */ |
43 | const char *fmt; | 31 | const char *fmt; |
44 | int c1, c2; | 32 | int c1, c2; |
@@ -59,14 +47,12 @@ int cmp_main(int argc UNUSED_PARAM, char **argv) | |||
59 | 47 | ||
60 | if (*++argv) { | 48 | if (*++argv) { |
61 | filename2 = *argv; | 49 | filename2 = *argv; |
62 | #if ENABLE_DESKTOP | 50 | if (ENABLE_DESKTOP && *++argv) { |
63 | if (*++argv) { | ||
64 | skip1 = XATOOFF(*argv); | 51 | skip1 = XATOOFF(*argv); |
65 | if (*++argv) { | 52 | if (*++argv) { |
66 | skip2 = XATOOFF(*argv); | 53 | skip2 = XATOOFF(*argv); |
67 | } | 54 | } |
68 | } | 55 | } |
69 | #endif | ||
70 | } | 56 | } |
71 | 57 | ||
72 | fp2 = xfopen_stdin(filename2); | 58 | fp2 = xfopen_stdin(filename2); |
@@ -83,10 +69,10 @@ int cmp_main(int argc UNUSED_PARAM, char **argv) | |||
83 | else | 69 | else |
84 | fmt = fmt_differ; | 70 | fmt = fmt_differ; |
85 | 71 | ||
86 | #if ENABLE_DESKTOP | 72 | if (ENABLE_DESKTOP) { |
87 | while (skip1) { getc(fp1); skip1--; } | 73 | while (skip1) { getc(fp1); skip1--; } |
88 | while (skip2) { getc(fp2); skip2--; } | 74 | while (skip2) { getc(fp2); skip2--; } |
89 | #endif | 75 | } |
90 | do { | 76 | do { |
91 | c1 = getc(fp1); | 77 | c1 = getc(fp1); |
92 | c2 = getc(fp2); | 78 | c2 = getc(fp2); |
diff --git a/editors/sed.c b/editors/sed.c index e5e187725..4bd6e0168 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
@@ -487,7 +487,7 @@ static const char *parse_cmd_args(sed_cmd_t *sed_cmd, const char *cmdstr) | |||
487 | static void add_cmd(const char *cmdstr) | 487 | static void add_cmd(const char *cmdstr) |
488 | { | 488 | { |
489 | sed_cmd_t *sed_cmd; | 489 | sed_cmd_t *sed_cmd; |
490 | int temp; | 490 | unsigned len, n; |
491 | 491 | ||
492 | /* Append this line to any unfinished line from last time. */ | 492 | /* Append this line to any unfinished line from last time. */ |
493 | if (G.add_cmd_line) { | 493 | if (G.add_cmd_line) { |
@@ -496,12 +496,14 @@ static void add_cmd(const char *cmdstr) | |||
496 | cmdstr = G.add_cmd_line = tp; | 496 | cmdstr = G.add_cmd_line = tp; |
497 | } | 497 | } |
498 | 498 | ||
499 | /* If this line ends with backslash, request next line. */ | 499 | /* If this line ends with unescaped backslash, request next line. */ |
500 | temp = strlen(cmdstr); | 500 | n = len = strlen(cmdstr); |
501 | if (temp && cmdstr[--temp] == '\\') { | 501 | while (n && cmdstr[n-1] == '\\') |
502 | n--; | ||
503 | if ((len - n) & 1) { /* if odd number of trailing backslashes */ | ||
502 | if (!G.add_cmd_line) | 504 | if (!G.add_cmd_line) |
503 | G.add_cmd_line = xstrdup(cmdstr); | 505 | G.add_cmd_line = xstrdup(cmdstr); |
504 | G.add_cmd_line[temp] = '\0'; | 506 | G.add_cmd_line[len-1] = '\0'; |
505 | return; | 507 | return; |
506 | } | 508 | } |
507 | 509 | ||
@@ -560,7 +562,7 @@ static void add_cmd(const char *cmdstr) | |||
560 | /* last part (mandatory) will be a command */ | 562 | /* last part (mandatory) will be a command */ |
561 | if (!*cmdstr) | 563 | if (!*cmdstr) |
562 | bb_error_msg_and_die("missing command"); | 564 | bb_error_msg_and_die("missing command"); |
563 | sed_cmd->cmd = *(cmdstr++); | 565 | sed_cmd->cmd = *cmdstr++; |
564 | cmdstr = parse_cmd_args(sed_cmd, cmdstr); | 566 | cmdstr = parse_cmd_args(sed_cmd, cmdstr); |
565 | 567 | ||
566 | /* Add the command to the command array */ | 568 | /* Add the command to the command array */ |
@@ -936,7 +938,15 @@ static void process_files(void) | |||
936 | /* Skip blocks of commands we didn't match */ | 938 | /* Skip blocks of commands we didn't match */ |
937 | if (sed_cmd->cmd == '{') { | 939 | if (sed_cmd->cmd == '{') { |
938 | if (sed_cmd->invert ? matched : !matched) { | 940 | if (sed_cmd->invert ? matched : !matched) { |
939 | while (sed_cmd->cmd != '}') { | 941 | unsigned nest_cnt = 0; |
942 | while (1) { | ||
943 | if (sed_cmd->cmd == '{') | ||
944 | nest_cnt++; | ||
945 | if (sed_cmd->cmd == '}') { | ||
946 | nest_cnt--; | ||
947 | if (nest_cnt == 0) | ||
948 | break; | ||
949 | } | ||
940 | sed_cmd = sed_cmd->next; | 950 | sed_cmd = sed_cmd->next; |
941 | if (!sed_cmd) | 951 | if (!sed_cmd) |
942 | bb_error_msg_and_die("unterminated {"); | 952 | bb_error_msg_and_die("unterminated {"); |
@@ -1031,7 +1041,7 @@ static void process_files(void) | |||
1031 | case 'c': | 1041 | case 'c': |
1032 | /* Only triggers on last line of a matching range. */ | 1042 | /* Only triggers on last line of a matching range. */ |
1033 | if (!sed_cmd->in_match) | 1043 | if (!sed_cmd->in_match) |
1034 | sed_puts(sed_cmd->string, NO_EOL_CHAR); | 1044 | sed_puts(sed_cmd->string, '\n'); |
1035 | goto discard_line; | 1045 | goto discard_line; |
1036 | 1046 | ||
1037 | /* Read file, append contents to output */ | 1047 | /* Read file, append contents to output */ |
diff --git a/editors/vi.c b/editors/vi.c index 28612508f..d9124fd76 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -60,18 +60,18 @@ enum { | |||
60 | 60 | ||
61 | /* vt102 typical ESC sequence */ | 61 | /* vt102 typical ESC sequence */ |
62 | /* terminal standout start/normal ESC sequence */ | 62 | /* terminal standout start/normal ESC sequence */ |
63 | static const char SOs[] ALIGN1 = "\033[7m"; | 63 | #define SOs "\033[7m" |
64 | static const char SOn[] ALIGN1 = "\033[0m"; | 64 | #define SOn "\033[0m" |
65 | /* terminal bell sequence */ | 65 | /* terminal bell sequence */ |
66 | static const char bell[] ALIGN1 = "\007"; | 66 | #define bell "\007" |
67 | /* Clear-end-of-line and Clear-end-of-screen ESC sequence */ | 67 | /* Clear-end-of-line and Clear-end-of-screen ESC sequence */ |
68 | static const char Ceol[] ALIGN1 = "\033[0K"; | 68 | #define Ceol "\033[K" |
69 | static const char Ceos[] ALIGN1 = "\033[0J"; | 69 | #define Ceos "\033[J" |
70 | /* Cursor motion arbitrary destination ESC sequence */ | 70 | /* Cursor motion arbitrary destination ESC sequence */ |
71 | static const char CMrc[] ALIGN1 = "\033[%d;%dH"; | 71 | #define CMrc "\033[%u;%uH" |
72 | /* Cursor motion up and down ESC sequence */ | 72 | /* Cursor motion up and down ESC sequence */ |
73 | static const char CMup[] ALIGN1 = "\033[A"; | 73 | #define CMup "\033[A" |
74 | static const char CMdown[] ALIGN1 = "\n"; | 74 | #define CMdown "\n" |
75 | 75 | ||
76 | #if ENABLE_FEATURE_VI_DOT_CMD || ENABLE_FEATURE_VI_YANKMARK | 76 | #if ENABLE_FEATURE_VI_DOT_CMD || ENABLE_FEATURE_VI_YANKMARK |
77 | // cmds modifying text[] | 77 | // cmds modifying text[] |
@@ -138,6 +138,9 @@ struct globals { | |||
138 | int save_argc; // how many file names on cmd line | 138 | int save_argc; // how many file names on cmd line |
139 | int cmdcnt; // repetition count | 139 | int cmdcnt; // repetition count |
140 | unsigned rows, columns; // the terminal screen is this size | 140 | unsigned rows, columns; // the terminal screen is this size |
141 | #if ENABLE_FEATURE_VI_ASK_TERMINAL | ||
142 | int get_rowcol_error; | ||
143 | #endif | ||
141 | int crow, ccol; // cursor is on Crow x Ccol | 144 | int crow, ccol; // cursor is on Crow x Ccol |
142 | int offset; // chars scrolled off the screen to the left | 145 | int offset; // chars scrolled off the screen to the left |
143 | int have_status_msg; // is default edit status needed? | 146 | int have_status_msg; // is default edit status needed? |
@@ -503,7 +506,11 @@ static int init_text_buffer(char *fn) | |||
503 | #if ENABLE_FEATURE_VI_WIN_RESIZE | 506 | #if ENABLE_FEATURE_VI_WIN_RESIZE |
504 | static void query_screen_dimensions(void) | 507 | static void query_screen_dimensions(void) |
505 | { | 508 | { |
506 | get_terminal_width_height(STDIN_FILENO, &columns, &rows); | 509 | # if ENABLE_FEATURE_VI_ASK_TERMINAL |
510 | if (!G.get_rowcol_error) | ||
511 | G.get_rowcol_error = | ||
512 | # endif | ||
513 | get_terminal_width_height(STDIN_FILENO, &columns, &rows); | ||
507 | if (rows > MAX_SCR_ROWS) | 514 | if (rows > MAX_SCR_ROWS) |
508 | rows = MAX_SCR_ROWS; | 515 | rows = MAX_SCR_ROWS; |
509 | if (columns > MAX_SCR_COLS) | 516 | if (columns > MAX_SCR_COLS) |
@@ -530,6 +537,20 @@ static void edit_file(char *fn) | |||
530 | columns = 80; | 537 | columns = 80; |
531 | size = 0; | 538 | size = 0; |
532 | query_screen_dimensions(); | 539 | query_screen_dimensions(); |
540 | #if ENABLE_FEATURE_VI_ASK_TERMINAL | ||
541 | if (G.get_rowcol_error /* TODO? && no input on stdin */) { | ||
542 | uint64_t k; | ||
543 | write1("\033[999;999H" "\033[6n"); | ||
544 | fflush_all(); | ||
545 | k = read_key(STDIN_FILENO, readbuffer, /*timeout_ms:*/ 100); | ||
546 | if ((int32_t)k == KEYCODE_CURSOR_POS) { | ||
547 | uint32_t rc = (k >> 32); | ||
548 | columns = (rc & 0x7fff); | ||
549 | rows = ((rc >> 16) & 0x7fff); | ||
550 | } | ||
551 | query_screen_dimensions(); | ||
552 | } | ||
553 | #endif | ||
533 | new_screen(rows, columns); // get memory for virtual screen | 554 | new_screen(rows, columns); // get memory for virtual screen |
534 | init_text_buffer(fn); | 555 | init_text_buffer(fn); |
535 | 556 | ||
@@ -2306,7 +2327,7 @@ static int file_size(const char *fn) // what is the byte size of "fn" | |||
2306 | int cnt; | 2327 | int cnt; |
2307 | 2328 | ||
2308 | cnt = -1; | 2329 | cnt = -1; |
2309 | if (fn && fn[0] && stat(fn, &st_buf) == 0) // see if file exists | 2330 | if (fn && stat(fn, &st_buf) == 0) // see if file exists |
2310 | cnt = (int) st_buf.st_size; | 2331 | cnt = (int) st_buf.st_size; |
2311 | return cnt; | 2332 | return cnt; |
2312 | } | 2333 | } |