X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=miscutils%2Fless.c;h=596490483e419ae5e2b3023183282bf476c3500a;hb=eea561871b45a2335ab6a09f14dad627ffcdc1cd;hp=eba916a80efbfdf83e2101f3418364ea25cf943d;hpb=bf2d9905caaf878efc6ee2b42069136634b2d92a;p=oweals%2Fbusybox.git diff --git a/miscutils/less.c b/miscutils/less.c index eba916a80..596490483 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -30,6 +30,7 @@ * redirected input has been read from stdin */ +#include "busybox.h" #include #include #include @@ -37,8 +38,6 @@ #include #include -#include "busybox.h" - #ifdef CONFIG_FEATURE_LESS_REGEXP #include "xregex.h" #endif @@ -70,9 +69,6 @@ /* Maximum number of lines in a file */ #define MAXLINES 10000 -/* Get height and width of terminal */ -#define tty_width_height() get_terminal_width_height(0, &width, &height) - static int height; static int width; static char **files; @@ -104,11 +100,11 @@ static int num_marks; #ifdef CONFIG_FEATURE_LESS_REGEXP static int match_found; -static int match_lines[100]; +static int *match_lines; static int match_pos; static int num_matches; static int match_backwards; -static int num_back_match = 1; +static regex_t old_pattern; #endif /* Needed termios structures */ @@ -210,7 +206,7 @@ static void data_readlines(void) char current_line[256]; FILE *fp; - fp = (inp_stdin) ? stdin : bb_xfopen(filename, "rt"); + fp = (inp_stdin) ? stdin : bb_xfopen(filename, "r"); flines = NULL; for (i = 0; (feof(fp)==0) && (i <= MAXLINES); i++) { strcpy(current_line, ""); @@ -236,14 +232,6 @@ static void data_readlines(void) add_linenumbers(); } -/* Turn a percentage into a line number */ -static int reverse_percent(int percentage) -{ - double linenum = percentage; - linenum = ((linenum / 100) * num_flines) - 1; - return(linenum); -} - #ifdef CONFIG_FEATURE_LESS_FLAGS /* Interestingly, writing calc_percent as a function and not a prototype saves around 32 bytes @@ -464,12 +452,11 @@ static void buffer_up(int nlines) static void buffer_line(int linenum) { int i; - past_eof = 0; - if (linenum < 1 || linenum > num_flines) { + if (linenum < 0 || linenum > num_flines) { clear_line(); - printf("%s%s%i%s", HIGHLIGHT, "Cannot seek to line number ", linenum, NORMAL); + printf("%s%s%i%s", HIGHLIGHT, "Cannot seek to line number ", linenum + 1, NORMAL); } else if (linenum < (num_flines - height - 2)) { for (i = 0; i < (height - 1); i++) { @@ -477,6 +464,7 @@ static void buffer_line(int linenum) buffer[i] = bb_xstrdup(flines[linenum + i]); } line_pos = linenum; + buffer_print(); } else { for (i = 0; i < (height - 1); i++) { @@ -489,6 +477,7 @@ static void buffer_line(int linenum) line_pos = linenum; /* Set past_eof so buffer_down and buffer_up act differently */ past_eof = 1; + buffer_print(); } } @@ -611,127 +600,123 @@ static void colon_process(void) /* Get a regular expression from the user, and then go through the current file line by line, running a processing regex function on each one. */ -static char *insert_highlights(char *line, int start, int end) -{ - return bb_xasprintf("%.*s%s%.*s%s%s", start, line, HIGHLIGHT, - end - start, line + start, NORMAL, line + end); -} - -static char *process_regex_on_line(char *line, regex_t *pattern) +static char *process_regex_on_line(char *line, regex_t *pattern, int action) { /* This function takes the regex and applies it to the line. Each part of the line that matches has the HIGHLIGHT and NORMAL escape sequences placed around it by - insert_highlights, and then the line is returned. */ - + insert_highlights if action = 1, or has the escape sequences + removed if action = 0, and then the line is returned. */ int match_status; char *line2 = (char *) xmalloc((sizeof(char) * (strlen(line) + 1)) + 64); - char sub_line[256]; - int prev_eo = 0; + char *growline = ""; regmatch_t match_structs; - strcpy(line2, line); + line2 = bb_xstrdup(line); match_found = 0; match_status = regexec(pattern, line2, 1, &match_structs, 0); - + while (match_status == 0) { - - memset(sub_line, 0, sizeof(sub_line)); - if (match_found == 0) match_found = 1; - - line2 = insert_highlights(line2, match_structs.rm_so + prev_eo, match_structs.rm_eo + prev_eo); - if ((size_t)match_structs.rm_eo + 11 + prev_eo < strlen(line2)) - strcat(sub_line, line2 + match_structs.rm_eo + 11 + prev_eo); - - prev_eo += match_structs.rm_eo + 11; - match_status = regexec(pattern, sub_line, 1, &match_structs, REG_NOTBOL); + + if (action) { + growline = bb_xasprintf("%s%.*s%s%.*s%s", growline, match_structs.rm_so, line2, HIGHLIGHT, match_structs.rm_eo - match_structs.rm_so, line2 + match_structs.rm_so, NORMAL); + } + else { + growline = bb_xasprintf("%s%.*s%.*s", growline, match_structs.rm_so - 4, line2, match_structs.rm_eo - match_structs.rm_so, line2 + match_structs.rm_so); + } + + line2 += match_structs.rm_eo; + match_status = regexec(pattern, line2, 1, &match_structs, REG_NOTBOL); } + + growline = bb_xasprintf("%s%s", growline, line2); + + return (match_found ? growline : line); + + free(growline); + free(line2); +} - return line2; +static void goto_match(int match) +{ + /* This goes to a specific match - all line positions of matches are + stored within the match_lines[] array. */ + if ((match < num_matches) && (match >= 0)) { + buffer_line(match_lines[match]); + match_pos = match; + } } static void regex_process(void) { char uncomp_regex[100]; - char current_line[256]; + char *current_line; int i; int j = 0; - regex_t *pattern; - - /* Reset variables */ - match_lines[0] = -1; - match_pos = 0; - num_matches = 0; - match_found = 0; - - pattern = (regex_t *) malloc(sizeof(regex_t)); - memset(pattern, 0, sizeof(regex_t)); - + regex_t pattern; /* Get the uncompiled regular expression from the user */ clear_line(); putchar((match_backwards) ? '?' : '/'); uncomp_regex[0] = 0; - fgets(uncomp_regex, sizeof(uncomp_regex), stdin); - i = strlen(uncomp_regex); - if (i > 0) { - if (uncomp_regex[i-1] == '\n') - uncomp_regex[i-1] = '\0'; + fgets(uncomp_regex, sizeof(uncomp_regex), inp); + + if (strlen(uncomp_regex) == 1) { + if (num_matches) + goto_match(match_backwards ? match_pos - 1 : match_pos + 1); else - while((i = getchar()) != '\n' && i != EOF); + buffer_print(); + return; } - + uncomp_regex[strlen(uncomp_regex) - 1] = '\0'; + /* Compile the regex and check for errors */ - xregcomp(pattern, uncomp_regex, 0); + xregcomp(&pattern, uncomp_regex, 0); + if (num_matches) { + /* Get rid of all the highlights we added previously */ + for (i = 0; i <= num_flines; i++) { + current_line = process_regex_on_line(flines[i], &old_pattern, 0); + flines[i] = bb_xstrdup(current_line); + } + } + old_pattern = pattern; + + /* Reset variables */ + match_lines = xrealloc(match_lines, sizeof(int)); + match_lines[0] = -1; + match_pos = 0; + num_matches = 0; + match_found = 0; /* Run the regex on each line of the current file here */ for (i = 0; i <= num_flines; i++) { - strcpy(current_line, process_regex_on_line(flines[i], pattern)); + current_line = process_regex_on_line(flines[i], &pattern, 1); flines[i] = bb_xstrdup(current_line); if (match_found) { + match_lines = xrealloc(match_lines, (j + 1) * sizeof(int)); match_lines[j] = i; j++; } } - + num_matches = j; - if ((match_lines[0] != -1) && (num_flines > height - 2)) - buffer_line(match_lines[0]); - else - buffer_init(); -} - -static void goto_match(int match) -{ - /* This goes to a specific match - all line positions of matches are - stored within the match_lines[] array. */ - if ((match < num_matches) && (match >= 0)) { - buffer_line(match_lines[match]); - match_pos = match; - } -} - -static void search_backwards(void) -{ - int current_linepos = line_pos; - int i; - - match_backwards = 1; - regex_process(); - - for (i = 0; i < num_matches; i++) { - if (match_lines[i] > current_linepos) { - buffer_line(match_lines[i - num_back_match]); - break; + if ((match_lines[0] != -1) && (num_flines > height - 2)) { + if (match_backwards) { + for (i = 0; i < num_matches; i++) { + if (match_lines[i] > line_pos) { + match_pos = i - 1; + buffer_line(match_lines[match_pos]); + break; + } + } } + else + buffer_line(match_lines[0]); } - - /* Reset variables */ - match_backwards = 0; - num_back_match = 1; - + else + buffer_init(); } #endif @@ -759,8 +744,10 @@ static void number_process(int first_digit) keypress = num_input[i]; num_input[i] = '\0'; num = strtol(num_input, &endptr, 10); - if (endptr==num_input || *endptr!='\0' || num < 1 || num > MAXLINES) - goto END; + if (endptr==num_input || *endptr!='\0' || num < 1 || num > MAXLINES) { + buffer_print(); + return; + } /* We now know the number and the letter entered, so we process them */ switch (keypress) { @@ -775,26 +762,24 @@ static void number_process(int first_digit) buffer_line(num - 1); break; case 'p': case '%': - buffer_line(reverse_percent(num)); + buffer_line(((num / 100) * num_flines) - 1); break; #ifdef CONFIG_FEATURE_LESS_REGEXP case 'n': - goto_match(match_pos + num - 1); + goto_match(match_pos + num); break; case '/': + match_backwards = 0; regex_process(); - goto_match(num - 1); break; case '?': - num_back_match = num; - search_backwards(); + match_backwards = 1; + regex_process(); break; #endif default: break; } -END: - buffer_print(); } #ifdef CONFIG_FEATURE_LESS_FLAGCS @@ -865,7 +850,6 @@ static void full_repaint(void) data_readlines(); buffer_init(); buffer_line(temp_line_pos); - buffer_print(); } @@ -879,7 +863,7 @@ static void save_input_to_file(void) printf("Log file: "); fgets(current_line, 256, inp); current_line[strlen(current_line) - 1] = '\0'; - if (strlen(current_line)) { + if (strlen(current_line) > 1) { fp = bb_xfopen(current_line, "w"); for (i = 0; i < num_flines; i++) fprintf(fp, "%s", flines[i]); @@ -986,7 +970,6 @@ static void match_right_bracket(char bracket) printf("%s%s%s", HIGHLIGHT, "No matching bracket found", NORMAL); buffer_line(bracket_line - height + 2); - buffer_print(); } } @@ -1014,7 +997,6 @@ static void match_left_bracket(char bracket) printf("%s%s%s", HIGHLIGHT, "No matching bracket found", NORMAL); buffer_line(bracket_line); - buffer_print(); } } @@ -1048,12 +1030,10 @@ static void keypress_process(int keypress) buffer_print(); break; case 'g': case 'p': case '<': case '%': - buffer_up(num_flines + 1); - buffer_print(); + buffer_line(0); break; case 'G': case '>': - buffer_down(num_flines + 1); - buffer_print(); + buffer_line(num_flines - height + 2); break; case 'q': case 'Q': tless_exit(0); @@ -1089,20 +1069,18 @@ static void keypress_process(int keypress) #endif #ifdef CONFIG_FEATURE_LESS_REGEXP case '/': + match_backwards = 0; regex_process(); - buffer_print(); break; case 'n': goto_match(match_pos + 1); - buffer_print(); break; case 'N': goto_match(match_pos - 1); - buffer_print(); break; case '?': - search_backwards(); - buffer_print(); + match_backwards = 1; + regex_process(); break; #endif #ifdef CONFIG_FEATURE_LESS_FLAGCS @@ -1154,7 +1132,7 @@ int less_main(int argc, char **argv) { } strcpy(filename, (inp_stdin) ? bb_msg_standard_input : files[0]); - tty_width_height(); + get_terminal_width_height(0, &width, &height); data_readlines(); tcgetattr(fileno(inp), &term_orig); term_vi = term_orig;