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 | |
| 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')
| -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 | ||
