diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2006-12-21 13:24:58 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2006-12-21 13:24:58 +0000 |
commit | e865e81d34efb96417c549e9c326fb1c46dafbc7 (patch) | |
tree | 33ba50881b34dcb0732763d0359ca9a50bdef99a /miscutils/less.c | |
parent | bf66fbc8e2380717c1fab860cfc60c78582839dd (diff) | |
download | busybox-w32-e865e81d34efb96417c549e9c326fb1c46dafbc7.tar.gz busybox-w32-e865e81d34efb96417c549e9c326fb1c46dafbc7.tar.bz2 busybox-w32-e865e81d34efb96417c549e9c326fb1c46dafbc7.zip |
less: stop dying on bad regexps, quietly pipe data w/o
user interaction if stdout is not a tty.
size optimizations
Diffstat (limited to 'miscutils/less.c')
-rw-r--r-- | miscutils/less.c | 256 |
1 files changed, 146 insertions, 110 deletions
diff --git a/miscutils/less.c b/miscutils/less.c index 6843dddcb..068c3f393 100644 --- a/miscutils/less.c +++ b/miscutils/less.c | |||
@@ -50,9 +50,10 @@ | |||
50 | /* The escape codes for highlighted and normal text */ | 50 | /* The escape codes for highlighted and normal text */ |
51 | #define HIGHLIGHT "\033[7m" | 51 | #define HIGHLIGHT "\033[7m" |
52 | #define NORMAL "\033[0m" | 52 | #define NORMAL "\033[0m" |
53 | |||
54 | /* The escape code to clear the screen */ | 53 | /* The escape code to clear the screen */ |
55 | #define CLEAR "\033[H\033[J" | 54 | #define CLEAR "\033[H\033[J" |
55 | /* The escape code to clear to end of line */ | ||
56 | #define CLEAR_2_EOL "\033[K" | ||
56 | 57 | ||
57 | #define MAXLINES CONFIG_FEATURE_LESS_MAXLINES | 58 | #define MAXLINES CONFIG_FEATURE_LESS_MAXLINES |
58 | 59 | ||
@@ -121,9 +122,9 @@ static void tless_exit(int code) | |||
121 | static int tless_getch(void) | 122 | static int tless_getch(void) |
122 | { | 123 | { |
123 | int input; | 124 | int input; |
124 | /* Set terminal input to raw mode (taken from vi.c) */ | 125 | /* Set terminal input to raw mode (taken from vi.c) */ |
125 | tcsetattr(fileno(inp), TCSANOW, &term_vi); | 126 | tcsetattr(fileno(inp), TCSANOW, &term_vi); |
126 | 127 | again: | |
127 | input = getc(inp); | 128 | input = getc(inp); |
128 | /* Detect escape sequences (i.e. arrow keys) and handle | 129 | /* Detect escape sequences (i.e. arrow keys) and handle |
129 | them accordingly */ | 130 | them accordingly */ |
@@ -136,27 +137,56 @@ static int tless_getch(void) | |||
136 | i = input - REAL_KEY_UP; | 137 | i = input - REAL_KEY_UP; |
137 | if (i < 4) | 138 | if (i < 4) |
138 | return 20 + i; | 139 | return 20 + i; |
139 | else if ((i = input - REAL_PAGE_UP) < 4) | 140 | i = input - REAL_PAGE_UP; |
141 | if (i < 4) | ||
140 | return 24 + i; | 142 | return 24 + i; |
141 | else | 143 | return 0; /* ?? */ |
142 | return 0; /* ?? */ | ||
143 | } | 144 | } |
144 | /* The input is a normal ASCII value */ | 145 | /* Reject almost all control chars */ |
146 | if (input < ' ' && input != 0x0d && input != 8) goto again; | ||
145 | set_tty_cooked(); | 147 | set_tty_cooked(); |
146 | return input; | 148 | return input; |
147 | } | 149 | } |
148 | 150 | ||
151 | static char* tless_gets(void) | ||
152 | { | ||
153 | int c; | ||
154 | int i = 0; | ||
155 | char *result = xzalloc(1); | ||
156 | while (1) { | ||
157 | c = tless_getch(); | ||
158 | if (c == 0x0d) | ||
159 | return result; | ||
160 | if (c == 0x7f) c = 8; | ||
161 | if (c == 8 && i) { | ||
162 | printf("\x8 \x8"); | ||
163 | i--; | ||
164 | } | ||
165 | if (c < ' ') | ||
166 | continue; | ||
167 | putchar(c); | ||
168 | result[i++] = c; | ||
169 | result = xrealloc(result, i+1); | ||
170 | result[i] = '\0'; | ||
171 | if (i >= width-1) return result; | ||
172 | } | ||
173 | } | ||
174 | |||
149 | /* Move the cursor to a position (x,y), where (0,0) is the | 175 | /* Move the cursor to a position (x,y), where (0,0) is the |
150 | top-left corner of the console */ | 176 | top-left corner of the console */ |
151 | static void move_cursor(int x, int y) | 177 | static void move_cursor(int line, int row) |
152 | { | 178 | { |
153 | printf("\033[%i;%iH", x, y); | 179 | printf("\033[%u;%uH", line, row); |
154 | } | 180 | } |
155 | 181 | ||
156 | static void clear_line(void) | 182 | static void clear_line(void) |
157 | { | 183 | { |
158 | move_cursor(height, 0); | 184 | printf("\033[%u;0H" CLEAR_2_EOL, height); |
159 | printf("\033[K"); | 185 | } |
186 | |||
187 | static void print_hilite(const char *str) | ||
188 | { | ||
189 | printf(HIGHLIGHT"%s"NORMAL, str); | ||
160 | } | 190 | } |
161 | 191 | ||
162 | static void data_readlines(void) | 192 | static void data_readlines(void) |
@@ -235,26 +265,26 @@ static void m_status_print(void) | |||
235 | 265 | ||
236 | if (!line_pos) { | 266 | if (!line_pos) { |
237 | if (num_files > 1) { | 267 | if (num_files > 1) { |
238 | printf("%s%s %s%i%s%i%s%i-%i/%i ", HIGHLIGHT, | 268 | printf(HIGHLIGHT"%s (file %i of %i) lines %i-%i/%i ", |
239 | filename, "(file ", current_file, " of ", num_files, ") lines ", | 269 | filename, current_file, num_files, |
240 | line_pos + 1, line_pos + height - 1, num_flines + 1); | 270 | line_pos + 1, line_pos + height - 1, num_flines + 1); |
241 | } else { | 271 | } else { |
242 | printf("%s%s lines %i-%i/%i ", HIGHLIGHT, | 272 | printf(HIGHLIGHT"%s lines %i-%i/%i ", |
243 | filename, line_pos + 1, line_pos + height - 1, | 273 | filename, line_pos + 1, line_pos + height - 1, |
244 | num_flines + 1); | 274 | num_flines + 1); |
245 | } | 275 | } |
246 | } else { | 276 | } else { |
247 | printf("%s %s lines %i-%i/%i ", HIGHLIGHT, filename, | 277 | printf(HIGHLIGHT" %s lines %i-%i/%i ", filename, |
248 | line_pos + 1, line_pos + height - 1, num_flines + 1); | 278 | line_pos + 1, line_pos + height - 1, num_flines + 1); |
249 | } | 279 | } |
250 | 280 | ||
251 | if (line_pos >= num_flines - height + 2) { | 281 | if (line_pos >= num_flines - height + 2) { |
252 | printf("(END) %s", NORMAL); | 282 | printf("(END) "NORMAL); |
253 | if ((num_files > 1) && (current_file != num_files)) | 283 | if (num_files > 1 && current_file != num_files) |
254 | printf("%s- Next: %s%s", HIGHLIGHT, files[current_file], NORMAL); | 284 | printf(HIGHLIGHT"- Next: %s"NORMAL, files[current_file]); |
255 | } else { | 285 | } else { |
256 | percentage = calc_percent(); | 286 | percentage = calc_percent(); |
257 | printf("%i%% %s", percentage, NORMAL); | 287 | printf("%i%% "NORMAL, percentage); |
258 | } | 288 | } |
259 | } | 289 | } |
260 | 290 | ||
@@ -265,11 +295,11 @@ static void medium_status_print(void) | |||
265 | percentage = calc_percent(); | 295 | percentage = calc_percent(); |
266 | 296 | ||
267 | if (!line_pos) | 297 | if (!line_pos) |
268 | printf("%s%s %i%%%s", HIGHLIGHT, filename, percentage, NORMAL); | 298 | printf(HIGHLIGHT"%s %i%%"NORMAL, filename, percentage); |
269 | else if (line_pos == num_flines - height + 2) | 299 | else if (line_pos == num_flines - height + 2) |
270 | printf("%s(END)%s", HIGHLIGHT, NORMAL); | 300 | print_hilite("(END)"); |
271 | else | 301 | else |
272 | printf("%s%i%%%s", HIGHLIGHT, percentage, NORMAL); | 302 | printf(HIGHLIGHT"%i%%"NORMAL, percentage); |
273 | } | 303 | } |
274 | #endif | 304 | #endif |
275 | 305 | ||
@@ -286,14 +316,14 @@ static void status_print(void) | |||
286 | else { | 316 | else { |
287 | #endif | 317 | #endif |
288 | if (!line_pos) { | 318 | if (!line_pos) { |
289 | printf("%s%s %s", HIGHLIGHT, filename, NORMAL); | 319 | print_hilite(filename); |
290 | if (num_files > 1) | 320 | if (num_files > 1) |
291 | printf("%s%s%i%s%i%s%s", HIGHLIGHT, "(file ", | 321 | printf(HIGHLIGHT"(file %i of %i)"NORMAL, |
292 | current_file, " of ", num_files, ")", NORMAL); | 322 | current_file, num_files); |
293 | } else if (line_pos == num_flines - height + 2) { | 323 | } else if (line_pos == num_flines - height + 2) { |
294 | printf("%s%s %s", HIGHLIGHT, "(END)", NORMAL); | 324 | print_hilite("(END) "); |
295 | if ((num_files > 1) && (current_file != num_files)) | 325 | if (num_files > 1 && current_file != num_files) |
296 | printf("%s%s%s%s", HIGHLIGHT, "- Next: ", files[current_file], NORMAL); | 326 | printf(HIGHLIGHT"- Next: %s"NORMAL, files[current_file]); |
297 | } else { | 327 | } else { |
298 | putchar(':'); | 328 | putchar(':'); |
299 | } | 329 | } |
@@ -336,13 +366,6 @@ static void print_found(const char *line) | |||
336 | memset(p, '.', n); | 366 | memset(p, '.', n); |
337 | p += n; | 367 | p += n; |
338 | str += n; | 368 | str += n; |
339 | /* | ||
340 | do { | ||
341 | if (*str == '\x7f') { *p++ = '?'; str++; } | ||
342 | else if (*str == '\x9b') { *p++ = '{'; str++; } | ||
343 | else *p++ = ctrlconv[(unsigned char)*str++]; | ||
344 | } while (--n); | ||
345 | */ | ||
346 | } | 369 | } |
347 | strcpy(p, str); | 370 | strcpy(p, str); |
348 | 371 | ||
@@ -358,13 +381,11 @@ static void print_found(const char *line) | |||
358 | goto start; | 381 | goto start; |
359 | 382 | ||
360 | while (match_status == 0) { | 383 | while (match_status == 0) { |
361 | char *new = xasprintf("%s" "%.*s" "%s" "%.*s" "%s", | 384 | char *new = xasprintf("%s%.*s"HIGHLIGHT"%.*s"NORMAL, |
362 | growline ? : "", | 385 | growline ? : "", |
363 | match_structs.rm_so, str, | 386 | match_structs.rm_so, str, |
364 | HIGHLIGHT, | ||
365 | match_structs.rm_eo - match_structs.rm_so, | 387 | match_structs.rm_eo - match_structs.rm_so, |
366 | str + match_structs.rm_so, | 388 | str + match_structs.rm_so); |
367 | NORMAL); | ||
368 | free(growline); growline = new; | 389 | free(growline); growline = new; |
369 | str += match_structs.rm_eo; | 390 | str += match_structs.rm_eo; |
370 | line += match_structs.rm_eo; | 391 | line += match_structs.rm_eo; |
@@ -375,10 +396,10 @@ static void print_found(const char *line) | |||
375 | } | 396 | } |
376 | 397 | ||
377 | if (!growline) { | 398 | if (!growline) { |
378 | puts(str); | 399 | printf("%s"CLEAR_2_EOL"\n", str); |
379 | return; | 400 | return; |
380 | } | 401 | } |
381 | printf("%s%s\n", growline, str); | 402 | printf("%s%s"CLEAR_2_EOL"\n", growline, str); |
382 | free(growline); | 403 | free(growline); |
383 | } | 404 | } |
384 | 405 | ||
@@ -398,14 +419,20 @@ static void print_ascii(const char *str) | |||
398 | n = strspn(str, controls); | 419 | n = strspn(str, controls); |
399 | p = buf; | 420 | p = buf; |
400 | do { | 421 | do { |
401 | if (*str == '\x7f') { *p++ = '?'; str++; } | 422 | if (*str == 0x7f) |
402 | else if (*str == '\x9b') { *p++ = '{'; str++; } | 423 | *p++ = '?'; |
403 | else *p++ = ctrlconv[(unsigned char)*str++]; | 424 | else if (*str == 0x9b) |
425 | /* VT100's CSI, aka Meta-ESC. Who's inventor? */ | ||
426 | /* I want to know who committed this sin */ | ||
427 | *p++ = '{'; | ||
428 | else | ||
429 | *p++ = ctrlconv[(unsigned char)*str]; | ||
430 | str++; | ||
404 | } while (--n); | 431 | } while (--n); |
405 | *p = '\0'; | 432 | *p = '\0'; |
406 | printf("%s%s%s", HIGHLIGHT, buf, NORMAL); | 433 | print_hilite(buf); |
407 | } | 434 | } |
408 | puts(str); | 435 | printf("%s"CLEAR_2_EOL"\n", str); |
409 | } | 436 | } |
410 | 437 | ||
411 | /* Print the buffer */ | 438 | /* Print the buffer */ |
@@ -413,12 +440,13 @@ static void buffer_print(void) | |||
413 | { | 440 | { |
414 | int i; | 441 | int i; |
415 | 442 | ||
416 | printf("%s", CLEAR); | 443 | move_cursor(0, 0); |
417 | for (i = 0; i < height - 1; i++) | 444 | for (i = 0; i < height - 1; i++) |
418 | if (pattern_valid) | 445 | if (pattern_valid) |
419 | print_found(buffer[i]); | 446 | print_found(buffer[i]); |
420 | else | 447 | else |
421 | print_ascii(buffer[i]); | 448 | print_ascii(buffer[i]); |
449 | fputs(CLEAR_2_EOL, stdout); /* clears status line */ | ||
422 | status_print(); | 450 | status_print(); |
423 | } | 451 | } |
424 | 452 | ||
@@ -427,11 +455,6 @@ static void buffer_init(void) | |||
427 | { | 455 | { |
428 | int i; | 456 | int i; |
429 | 457 | ||
430 | if (!buffer) { | ||
431 | /* malloc the number of lines needed for the buffer */ | ||
432 | buffer = xmalloc(height * sizeof(char *)); | ||
433 | } | ||
434 | |||
435 | /* Fill the buffer until the end of the file or the | 458 | /* Fill the buffer until the end of the file or the |
436 | end of the buffer is reached */ | 459 | end of the buffer is reached */ |
437 | for (i = 0; i < height - 1 && i <= num_flines; i++) { | 460 | for (i = 0; i < height - 1 && i <= num_flines; i++) { |
@@ -491,18 +514,19 @@ static void buffer_line(int linenum) | |||
491 | 514 | ||
492 | if (linenum < 0 || linenum > num_flines) { | 515 | if (linenum < 0 || linenum > num_flines) { |
493 | clear_line(); | 516 | clear_line(); |
494 | printf("%s%s%i%s", HIGHLIGHT, "Cannot seek to line number ", linenum + 1, NORMAL); | 517 | printf(HIGHLIGHT"%s%u"NORMAL, "Cannot seek to line ", linenum + 1); |
495 | } else { | 518 | return; |
496 | for (i = 0; i < height - 1; i++) { | 519 | } |
497 | if (linenum + i <= num_flines) | 520 | |
498 | buffer[i] = flines[linenum + i]; | 521 | for (i = 0; i < height - 1; i++) { |
499 | else { | 522 | if (linenum + i <= num_flines) |
500 | buffer[i] = empty_line_marker; | 523 | buffer[i] = flines[linenum + i]; |
501 | } | 524 | else { |
525 | buffer[i] = empty_line_marker; | ||
502 | } | 526 | } |
503 | line_pos = linenum; | ||
504 | buffer_print(); | ||
505 | } | 527 | } |
528 | line_pos = linenum; | ||
529 | buffer_print(); | ||
506 | } | 530 | } |
507 | 531 | ||
508 | /* Reinitialise everything for a new file - free the memory and start over */ | 532 | /* Reinitialise everything for a new file - free the memory and start over */ |
@@ -524,10 +548,13 @@ static void examine_file(void) | |||
524 | clear_line(); | 548 | clear_line(); |
525 | printf("Examine: "); | 549 | printf("Examine: "); |
526 | free(filename); | 550 | free(filename); |
527 | filename = xmalloc_getline(inp); | 551 | filename = tless_gets(); |
552 | /* files start by = argv. why we assume that argv is infinitely long?? | ||
528 | files[num_files] = filename; | 553 | files[num_files] = filename; |
529 | current_file = num_files + 1; | 554 | current_file = num_files + 1; |
530 | num_files++; | 555 | num_files++; */ |
556 | files[0] = filename; | ||
557 | current_file = 1; | ||
531 | reinitialise(); | 558 | reinitialise(); |
532 | } | 559 | } |
533 | 560 | ||
@@ -545,7 +572,7 @@ static void change_file(int direction) | |||
545 | reinitialise(); | 572 | reinitialise(); |
546 | } else { | 573 | } else { |
547 | clear_line(); | 574 | clear_line(); |
548 | printf("%s%s%s", HIGHLIGHT, (direction > 0) ? "No next file" : "No previous file", NORMAL); | 575 | print_hilite((direction > 0) ? "No next file" : "No previous file"); |
549 | } | 576 | } |
550 | } | 577 | } |
551 | 578 | ||
@@ -628,7 +655,7 @@ static void goto_match(int match) | |||
628 | 655 | ||
629 | static void regex_process(void) | 656 | static void regex_process(void) |
630 | { | 657 | { |
631 | char *uncomp_regex; | 658 | char *uncomp_regex, *err; |
632 | 659 | ||
633 | /* Reset variables */ | 660 | /* Reset variables */ |
634 | match_lines = xrealloc(match_lines, sizeof(int)); | 661 | match_lines = xrealloc(match_lines, sizeof(int)); |
@@ -643,16 +670,22 @@ static void regex_process(void) | |||
643 | /* Get the uncompiled regular expression from the user */ | 670 | /* Get the uncompiled regular expression from the user */ |
644 | clear_line(); | 671 | clear_line(); |
645 | putchar((option_mask32 & LESS_STATE_MATCH_BACKWARDS) ? '?' : '/'); | 672 | putchar((option_mask32 & LESS_STATE_MATCH_BACKWARDS) ? '?' : '/'); |
646 | uncomp_regex = xmalloc_getline(inp); | 673 | uncomp_regex = tless_gets(); |
647 | if (!uncomp_regex || !uncomp_regex[0]) { | 674 | if (/*!uncomp_regex ||*/ !uncomp_regex[0]) { |
648 | free(uncomp_regex); | 675 | free(uncomp_regex); |
649 | buffer_print(); | 676 | buffer_print(); |
650 | return; | 677 | return; |
651 | } | 678 | } |
652 | 679 | ||
653 | /* Compile the regex and check for errors */ | 680 | /* Compile the regex and check for errors */ |
654 | xregcomp(&pattern, uncomp_regex, 0); | 681 | err = regcomp_or_errmsg(&pattern, uncomp_regex, 0); |
655 | free(uncomp_regex); | 682 | free(uncomp_regex); |
683 | if (err) { | ||
684 | clear_line(); | ||
685 | fputs(err, stdout); | ||
686 | free(err); | ||
687 | return; | ||
688 | } | ||
656 | pattern_valid = 1; | 689 | pattern_valid = 1; |
657 | 690 | ||
658 | /* Run the regex on each line of the current file */ | 691 | /* Run the regex on each line of the current file */ |
@@ -799,7 +832,7 @@ static void show_flag_status(void) | |||
799 | } | 832 | } |
800 | 833 | ||
801 | clear_line(); | 834 | clear_line(); |
802 | printf("%s%s%i%s", HIGHLIGHT, "The status of the flag is: ", flag_val != 0, NORMAL); | 835 | printf(HIGHLIGHT"%s%u"NORMAL, "The status of the flag is: ", flag_val != 0); |
803 | } | 836 | } |
804 | #endif | 837 | #endif |
805 | 838 | ||
@@ -820,12 +853,12 @@ static void save_input_to_file(void) | |||
820 | 853 | ||
821 | clear_line(); | 854 | clear_line(); |
822 | printf("Log file: "); | 855 | printf("Log file: "); |
823 | current_line = xmalloc_getline(inp); | 856 | current_line = tless_gets(); |
824 | if (strlen(current_line) > 0) { | 857 | if (strlen(current_line) > 0) { |
825 | fp = fopen(current_line, "w"); | 858 | fp = fopen(current_line, "w"); |
826 | free(current_line); | 859 | free(current_line); |
827 | if (!fp) { | 860 | if (!fp) { |
828 | printf("%s%s%s", HIGHLIGHT, "Error opening log file", NORMAL); | 861 | print_hilite("Error opening log file"); |
829 | return; | 862 | return; |
830 | } | 863 | } |
831 | for (i = 0; i < num_flines; i++) | 864 | for (i = 0; i < num_flines; i++) |
@@ -835,7 +868,7 @@ static void save_input_to_file(void) | |||
835 | return; | 868 | return; |
836 | } | 869 | } |
837 | free(current_line); | 870 | free(current_line); |
838 | printf("%s%s%s", HIGHLIGHT, "No log file", NORMAL); | 871 | print_hilite("No log file"); |
839 | } | 872 | } |
840 | 873 | ||
841 | #if ENABLE_FEATURE_LESS_MARKS | 874 | #if ENABLE_FEATURE_LESS_MARKS |
@@ -858,7 +891,7 @@ static void add_mark(void) | |||
858 | num_marks++; | 891 | num_marks++; |
859 | } else { | 892 | } else { |
860 | clear_line(); | 893 | clear_line(); |
861 | printf("%s%s%s", HIGHLIGHT, "Invalid mark letter", NORMAL); | 894 | print_hilite("Invalid mark letter"); |
862 | } | 895 | } |
863 | } | 896 | } |
864 | 897 | ||
@@ -878,10 +911,10 @@ static void goto_mark(void) | |||
878 | buffer_line(mark_lines[i][1]); | 911 | buffer_line(mark_lines[i][1]); |
879 | break; | 912 | break; |
880 | } | 913 | } |
881 | if ((num_marks == 14) && (letter != mark_lines[14][0])) | 914 | if (num_marks == 14 && letter != mark_lines[14][0]) |
882 | printf("%s%s%s", HIGHLIGHT, "Mark not set", NORMAL); | 915 | print_hilite("Mark not set"); |
883 | } else | 916 | } else |
884 | printf("%s%s%s", HIGHLIGHT, "Invalid mark letter", NORMAL); | 917 | print_hilite("Invalid mark letter"); |
885 | } | 918 | } |
886 | #endif | 919 | #endif |
887 | 920 | ||
@@ -911,21 +944,19 @@ static void match_right_bracket(char bracket) | |||
911 | 944 | ||
912 | clear_line(); | 945 | clear_line(); |
913 | 946 | ||
914 | if (strchr(flines[line_pos], bracket) == NULL) | 947 | if (strchr(flines[line_pos], bracket) == NULL) { |
915 | printf("%s%s%s", HIGHLIGHT, "No bracket in top line", NORMAL); | 948 | print_hilite("No bracket in top line"); |
916 | else { | 949 | return; |
917 | for (i = line_pos + 1; i < num_flines; i++) { | 950 | } |
918 | if (strchr(flines[i], opp_bracket(bracket)) != NULL) { | 951 | for (i = line_pos + 1; i < num_flines; i++) { |
919 | bracket_line = i; | 952 | if (strchr(flines[i], opp_bracket(bracket)) != NULL) { |
920 | break; | 953 | bracket_line = i; |
921 | } | 954 | break; |
922 | } | 955 | } |
923 | |||
924 | if (bracket_line == -1) | ||
925 | printf("%s%s%s", HIGHLIGHT, "No matching bracket found", NORMAL); | ||
926 | |||
927 | buffer_line(bracket_line - height + 2); | ||
928 | } | 956 | } |
957 | if (bracket_line == -1) | ||
958 | print_hilite("No matching bracket found"); | ||
959 | buffer_line(bracket_line - height + 2); | ||
929 | } | 960 | } |
930 | 961 | ||
931 | static void match_left_bracket(char bracket) | 962 | static void match_left_bracket(char bracket) |
@@ -936,22 +967,22 @@ static void match_left_bracket(char bracket) | |||
936 | clear_line(); | 967 | clear_line(); |
937 | 968 | ||
938 | if (strchr(flines[line_pos + height - 2], bracket) == NULL) { | 969 | if (strchr(flines[line_pos + height - 2], bracket) == NULL) { |
939 | printf("%s%s%s", HIGHLIGHT, "No bracket in bottom line", NORMAL); | 970 | print_hilite("No bracket in bottom line"); |
940 | printf("%s", flines[line_pos + height]); | 971 | /* ?? */ |
941 | sleep(4); | 972 | /*printf("%s", flines[line_pos + height]);*/ |
942 | } else { | 973 | /*sleep(4);*/ |
943 | for (i = line_pos + height - 2; i >= 0; i--) { | 974 | return; |
944 | if (strchr(flines[i], opp_bracket(bracket)) != NULL) { | 975 | } |
945 | bracket_line = i; | ||
946 | break; | ||
947 | } | ||
948 | } | ||
949 | |||
950 | if (bracket_line == -1) | ||
951 | printf("%s%s%s", HIGHLIGHT, "No matching bracket found", NORMAL); | ||
952 | 976 | ||
953 | buffer_line(bracket_line); | 977 | for (i = line_pos + height - 2; i >= 0; i--) { |
978 | if (strchr(flines[i], opp_bracket(bracket)) != NULL) { | ||
979 | bracket_line = i; | ||
980 | break; | ||
981 | } | ||
954 | } | 982 | } |
983 | if (bracket_line == -1) | ||
984 | print_hilite("No matching bracket found"); | ||
985 | buffer_line(bracket_line); | ||
955 | } | 986 | } |
956 | 987 | ||
957 | #endif /* FEATURE_LESS_BRACKETS */ | 988 | #endif /* FEATURE_LESS_BRACKETS */ |
@@ -959,7 +990,7 @@ static void match_left_bracket(char bracket) | |||
959 | static void keypress_process(int keypress) | 990 | static void keypress_process(int keypress) |
960 | { | 991 | { |
961 | switch (keypress) { | 992 | switch (keypress) { |
962 | case KEY_DOWN: case 'e': case 'j': case '\015': | 993 | case KEY_DOWN: case 'e': case 'j': case 0x0d: |
963 | buffer_down(1); | 994 | buffer_down(1); |
964 | buffer_print(); | 995 | buffer_print(); |
965 | break; | 996 | break; |
@@ -1080,37 +1111,42 @@ int less_main(int argc, char **argv) | |||
1080 | files = argv; | 1111 | files = argv; |
1081 | num_files = argc; | 1112 | num_files = argc; |
1082 | 1113 | ||
1114 | /* Another popular pager, most, detects when stdout | ||
1115 | * is not a tty and turns into cat. This makes sense. */ | ||
1116 | if (!isatty(STDOUT_FILENO)) | ||
1117 | return bb_cat(argv); | ||
1118 | |||
1083 | if (!num_files) { | 1119 | if (!num_files) { |
1084 | if (isatty(STDIN_FILENO)) { | 1120 | if (isatty(STDIN_FILENO)) { |
1085 | /* Just "less"? No file and no redirection? */ | 1121 | /* Just "less"? No args and no redirection? */ |
1086 | bb_error_msg("missing filename"); | 1122 | bb_error_msg("missing filename"); |
1087 | bb_show_usage(); | 1123 | bb_show_usage(); |
1088 | } | 1124 | } |
1089 | } else | 1125 | } else |
1090 | filename = xstrdup(files[0]); | 1126 | filename = xstrdup(files[0]); |
1091 | 1127 | ||
1092 | /* FIXME: another popular pager, most, detects when stdout | ||
1093 | * is not a tty and turns into cat */ | ||
1094 | inp = xfopen(CURRENT_TTY, "r"); | 1128 | inp = xfopen(CURRENT_TTY, "r"); |
1095 | 1129 | ||
1096 | get_terminal_width_height(fileno(inp), &width, &height); | 1130 | get_terminal_width_height(fileno(inp), &width, &height); |
1097 | if (width < 10 || height < 3) | 1131 | if (width < 10 || height < 3) |
1098 | bb_error_msg_and_die("too narrow here"); | 1132 | bb_error_msg_and_die("too narrow here"); |
1099 | 1133 | ||
1100 | if (option_mask32 & FLAG_TILDE) empty_line_marker = ""; | 1134 | buffer = xmalloc(height * sizeof(char *)); |
1135 | if (option_mask32 & FLAG_TILDE) | ||
1136 | empty_line_marker = ""; | ||
1101 | 1137 | ||
1102 | data_readlines(); | 1138 | data_readlines(); |
1103 | 1139 | ||
1104 | tcgetattr(fileno(inp), &term_orig); | 1140 | tcgetattr(fileno(inp), &term_orig); |
1105 | signal(SIGTERM, sig_catcher); | 1141 | signal(SIGTERM, sig_catcher); |
1106 | signal(SIGINT, sig_catcher); | 1142 | signal(SIGINT, sig_catcher); |
1107 | |||
1108 | term_vi = term_orig; | 1143 | term_vi = term_orig; |
1109 | term_vi.c_lflag &= (~ICANON & ~ECHO); | 1144 | term_vi.c_lflag &= (~ICANON & ~ECHO); |
1110 | term_vi.c_iflag &= (~IXON & ~ICRNL); | 1145 | term_vi.c_iflag &= (~IXON & ~ICRNL); |
1111 | term_vi.c_oflag &= (~ONLCR); | 1146 | term_vi.c_oflag &= (~ONLCR); |
1112 | term_vi.c_cc[VMIN] = 1; | 1147 | term_vi.c_cc[VMIN] = 1; |
1113 | term_vi.c_cc[VTIME] = 0; | 1148 | term_vi.c_cc[VTIME] = 0; |
1149 | |||
1114 | buffer_init(); | 1150 | buffer_init(); |
1115 | buffer_print(); | 1151 | buffer_print(); |
1116 | 1152 | ||