diff options
Diffstat (limited to 'miscutils/less.c')
-rw-r--r-- | miscutils/less.c | 83 |
1 files changed, 69 insertions, 14 deletions
diff --git a/miscutils/less.c b/miscutils/less.c index 90c103888..dd932c5ed 100644 --- a/miscutils/less.c +++ b/miscutils/less.c | |||
@@ -165,6 +165,11 @@ enum { | |||
165 | enum { pattern_valid = 0 }; | 165 | enum { pattern_valid = 0 }; |
166 | #endif | 166 | #endif |
167 | 167 | ||
168 | enum { | ||
169 | READING_FILE = -1, | ||
170 | READING_STDIN = -2 | ||
171 | }; | ||
172 | |||
168 | struct globals { | 173 | struct globals { |
169 | int cur_fline; /* signed */ | 174 | int cur_fline; /* signed */ |
170 | int kbd_fd; /* fd to get input from */ | 175 | int kbd_fd; /* fd to get input from */ |
@@ -188,6 +193,9 @@ struct globals { | |||
188 | unsigned current_file; | 193 | unsigned current_file; |
189 | char *filename; | 194 | char *filename; |
190 | char **files; | 195 | char **files; |
196 | #if ENABLE_FEATURE_LESS_FLAGS | ||
197 | int num_lines; /* input source if < 0, line count if >= 0 */ | ||
198 | #endif | ||
191 | #if ENABLE_FEATURE_LESS_MARKS | 199 | #if ENABLE_FEATURE_LESS_MARKS |
192 | unsigned num_marks; | 200 | unsigned num_marks; |
193 | unsigned mark_lines[15][2]; | 201 | unsigned mark_lines[15][2]; |
@@ -229,6 +237,7 @@ struct globals { | |||
229 | #define current_file (G.current_file ) | 237 | #define current_file (G.current_file ) |
230 | #define filename (G.filename ) | 238 | #define filename (G.filename ) |
231 | #define files (G.files ) | 239 | #define files (G.files ) |
240 | #define num_lines (G.num_lines ) | ||
232 | #define num_marks (G.num_marks ) | 241 | #define num_marks (G.num_marks ) |
233 | #define mark_lines (G.mark_lines ) | 242 | #define mark_lines (G.mark_lines ) |
234 | #if ENABLE_FEATURE_LESS_REGEXP | 243 | #if ENABLE_FEATURE_LESS_REGEXP |
@@ -574,6 +583,10 @@ static void read_lines(void) | |||
574 | print_statusline(bb_msg_read_error); | 583 | print_statusline(bb_msg_read_error); |
575 | } | 584 | } |
576 | } | 585 | } |
586 | #if ENABLE_FEATURE_LESS_FLAGS | ||
587 | else if (eof_error == 0) | ||
588 | num_lines = max_lineno; | ||
589 | #endif | ||
577 | 590 | ||
578 | fill_match_lines(old_max_fline); | 591 | fill_match_lines(old_max_fline); |
579 | #if ENABLE_FEATURE_LESS_REGEXP | 592 | #if ENABLE_FEATURE_LESS_REGEXP |
@@ -584,18 +597,23 @@ static void read_lines(void) | |||
584 | } | 597 | } |
585 | 598 | ||
586 | #if ENABLE_FEATURE_LESS_FLAGS | 599 | #if ENABLE_FEATURE_LESS_FLAGS |
587 | /* Interestingly, writing calc_percent as a function saves around 32 bytes | 600 | static int safe_lineno(int fline) |
588 | * on my build. */ | ||
589 | static int calc_percent(void) | ||
590 | { | 601 | { |
591 | unsigned p = (100 * (cur_fline+max_displayed_line+1) + max_fline/2) / (max_fline+1); | 602 | if (fline >= max_fline) |
592 | return p <= 100 ? p : 100; | 603 | fline = max_fline - 1; |
604 | |||
605 | /* also catches empty file (max_fline == 0) */ | ||
606 | if (fline < 0) | ||
607 | return 0; | ||
608 | |||
609 | return LINENO(flines[fline]) + 1; | ||
593 | } | 610 | } |
594 | 611 | ||
595 | /* Print a status line if -M was specified */ | 612 | /* Print a status line if -M was specified */ |
596 | static void m_status_print(void) | 613 | static void m_status_print(void) |
597 | { | 614 | { |
598 | int percentage; | 615 | int first, last; |
616 | unsigned percent; | ||
599 | 617 | ||
600 | if (less_gets_pos >= 0) /* don't touch statusline while input is done! */ | 618 | if (less_gets_pos >= 0) /* don't touch statusline while input is done! */ |
601 | return; | 619 | return; |
@@ -604,17 +622,51 @@ static void m_status_print(void) | |||
604 | printf(HIGHLIGHT"%s", filename); | 622 | printf(HIGHLIGHT"%s", filename); |
605 | if (num_files > 1) | 623 | if (num_files > 1) |
606 | printf(" (file %i of %i)", current_file, num_files); | 624 | printf(" (file %i of %i)", current_file, num_files); |
607 | printf(" lines %i-%i/%i ", | 625 | |
608 | cur_fline + 1, cur_fline + max_displayed_line + 1, | 626 | first = safe_lineno(cur_fline); |
609 | max_fline + 1); | 627 | last = (option_mask32 & FLAG_S) |
628 | ? MIN(first + max_displayed_line, max_lineno) | ||
629 | : safe_lineno(cur_fline + max_displayed_line); | ||
630 | printf(" lines %i-%i", first, last); | ||
631 | |||
632 | if (num_lines == READING_FILE) { | ||
633 | int count, fd; | ||
634 | ssize_t len, i; | ||
635 | char buf[4096]; | ||
636 | struct stat stbuf; | ||
637 | |||
638 | /* count number of lines in file */ | ||
639 | count = 0; | ||
640 | fd = open(filename, O_RDONLY); | ||
641 | if (fd < 0) | ||
642 | goto skip; | ||
643 | if (fstat(fd, &stbuf) != 0 || !S_ISREG(stbuf.st_mode)) | ||
644 | goto do_close; | ||
645 | while ((len = safe_read(fd, buf, sizeof(buf))) > 0) { | ||
646 | for (i = 0; i < len; ++i) { | ||
647 | if (buf[i] == '\n' && ++count == MAXLINES) | ||
648 | goto done; | ||
649 | } | ||
650 | } | ||
651 | done: | ||
652 | num_lines = count; | ||
653 | do_close: | ||
654 | close(fd); | ||
655 | skip: ; | ||
656 | } | ||
657 | |||
658 | if (num_lines >= 0) | ||
659 | printf("/%i", num_lines); | ||
660 | |||
610 | if (cur_fline >= (int)(max_fline - max_displayed_line)) { | 661 | if (cur_fline >= (int)(max_fline - max_displayed_line)) { |
611 | printf("(END)"NORMAL); | 662 | printf(" (END)"); |
612 | if (num_files > 1 && current_file != num_files) | 663 | if (num_files > 1 && current_file != num_files) |
613 | printf(HIGHLIGHT" - next: %s"NORMAL, files[current_file]); | 664 | printf(" - next: %s", files[current_file]); |
614 | return; | 665 | } else if (num_lines > 0) { |
666 | percent = (100 * last + num_lines/2) / num_lines; | ||
667 | printf(" %i%%", percent <= 100 ? percent : 100); | ||
615 | } | 668 | } |
616 | percentage = calc_percent(); | 669 | printf(NORMAL); |
617 | printf("%i%%"NORMAL, percentage); | ||
618 | } | 670 | } |
619 | #endif | 671 | #endif |
620 | 672 | ||
@@ -915,6 +967,9 @@ static void reinitialize(void) | |||
915 | max_fline = -1; | 967 | max_fline = -1; |
916 | cur_fline = 0; | 968 | cur_fline = 0; |
917 | max_lineno = 0; | 969 | max_lineno = 0; |
970 | #if ENABLE_FEATURE_LESS_FLAGS | ||
971 | num_lines = filename ? READING_FILE : READING_STDIN; | ||
972 | #endif | ||
918 | open_file_and_read_lines(); | 973 | open_file_and_read_lines(); |
919 | #if ENABLE_FEATURE_LESS_ASK_TERMINAL | 974 | #if ENABLE_FEATURE_LESS_ASK_TERMINAL |
920 | if (G.winsize_err) | 975 | if (G.winsize_err) |