aboutsummaryrefslogtreecommitdiff
path: root/editors
diff options
context:
space:
mode:
Diffstat (limited to 'editors')
-rw-r--r--editors/Config.in12
-rw-r--r--editors/cmp.c26
-rw-r--r--editors/sed.c26
-rw-r--r--editors/vi.c41
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
171config 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
171config FEATURE_VI_OPTIMIZE_CURSOR 183config 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
26static const char fmt_eof[] ALIGN1 = "cmp: EOF on %s\n"; 15static 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)
487static void add_cmd(const char *cmdstr) 487static 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 */
63static const char SOs[] ALIGN1 = "\033[7m"; 63#define SOs "\033[7m"
64static const char SOn[] ALIGN1 = "\033[0m"; 64#define SOn "\033[0m"
65/* terminal bell sequence */ 65/* terminal bell sequence */
66static 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 */
68static const char Ceol[] ALIGN1 = "\033[0K"; 68#define Ceol "\033[K"
69static 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 */
71static 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 */
73static const char CMup[] ALIGN1 = "\033[A"; 73#define CMup "\033[A"
74static 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
504static void query_screen_dimensions(void) 507static 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}