diff options
author | Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> | 2006-05-19 10:54:46 +0000 |
---|---|---|
committer | Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> | 2006-05-19 10:54:46 +0000 |
commit | 0c4b9fdda1cdc6b68f6cf531cb88f438228fcd3c (patch) | |
tree | 43229ed1da8de60d92c482ee565414d92ad8c6a3 | |
parent | 4ab339129edcea77e0a08228636114dd8ebd6093 (diff) | |
download | busybox-w32-0c4b9fdda1cdc6b68f6cf531cb88f438228fcd3c.tar.gz busybox-w32-0c4b9fdda1cdc6b68f6cf531cb88f438228fcd3c.tar.bz2 busybox-w32-0c4b9fdda1cdc6b68f6cf531cb88f438228fcd3c.zip |
Resync less.c with current svn to fix a segfault in searching.
(revisions 14889, 14890, 14891, 14896, 14897, 14905, 14961 from trunk)
-rw-r--r-- | miscutils/less.c | 368 |
1 files changed, 173 insertions, 195 deletions
diff --git a/miscutils/less.c b/miscutils/less.c index df55b50ac..84e4b612d 100644 --- a/miscutils/less.c +++ b/miscutils/less.c | |||
@@ -2,24 +2,12 @@ | |||
2 | /* | 2 | /* |
3 | * Mini less implementation for busybox | 3 | * Mini less implementation for busybox |
4 | * | 4 | * |
5 | * | ||
6 | * Copyright (C) 2005 by Rob Sullivan <cogito.ergo.cogito@gmail.com> | 5 | * Copyright (C) 2005 by Rob Sullivan <cogito.ergo.cogito@gmail.com> |
7 | * | 6 | * |
8 | * This program is free software; you can redistribute it and/or modify | 7 | * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. |
9 | * it under the terms of the GNU General Public License as published by | 8 | */ |
10 | * the Free Software Foundation; either version 2 of the License, or | 9 | |
11 | * (at your option) any later version. | 10 | /* |
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
21 | * 02111-1307 USA | ||
22 | * | ||
23 | * This program needs a lot of development, so consider it in a beta stage | 11 | * This program needs a lot of development, so consider it in a beta stage |
24 | * at best. | 12 | * at best. |
25 | * | 13 | * |
@@ -116,11 +104,11 @@ static int num_marks; | |||
116 | 104 | ||
117 | #ifdef CONFIG_FEATURE_LESS_REGEXP | 105 | #ifdef CONFIG_FEATURE_LESS_REGEXP |
118 | static int match_found; | 106 | static int match_found; |
119 | static int match_lines[100]; | 107 | static int *match_lines; |
120 | static int match_pos; | 108 | static int match_pos; |
121 | static int num_matches; | 109 | static int num_matches; |
122 | static int match_backwards; | 110 | static int match_backwards; |
123 | static int num_back_match = 1; | 111 | static regex_t old_pattern; |
124 | #endif | 112 | #endif |
125 | 113 | ||
126 | /* Needed termios structures */ | 114 | /* Needed termios structures */ |
@@ -130,19 +118,21 @@ static struct termios term_orig, term_vi; | |||
130 | static FILE *inp; | 118 | static FILE *inp; |
131 | 119 | ||
132 | /* Reset terminal input to normal */ | 120 | /* Reset terminal input to normal */ |
133 | static void set_tty_cooked(void) { | 121 | static void set_tty_cooked(void) |
122 | { | ||
134 | fflush(stdout); | 123 | fflush(stdout); |
135 | tcsetattr(fileno(inp), TCSANOW, &term_orig); | 124 | tcsetattr(fileno(inp), TCSANOW, &term_orig); |
136 | } | 125 | } |
137 | 126 | ||
138 | /* Set terminal input to raw mode (taken from vi.c) */ | 127 | /* Set terminal input to raw mode (taken from vi.c) */ |
139 | static void set_tty_raw(void) { | 128 | static void set_tty_raw(void) |
129 | { | ||
140 | tcsetattr(fileno(inp), TCSANOW, &term_vi); | 130 | tcsetattr(fileno(inp), TCSANOW, &term_vi); |
141 | } | 131 | } |
142 | 132 | ||
143 | /* Exit the program gracefully */ | 133 | /* Exit the program gracefully */ |
144 | static void tless_exit(int code) { | 134 | static void tless_exit(int code) |
145 | 135 | { | |
146 | /* TODO: We really should save the terminal state when we start, | 136 | /* TODO: We really should save the terminal state when we start, |
147 | and restore it when we exit. Less does this with the | 137 | and restore it when we exit. Less does this with the |
148 | "ti" and "te" termcap commands; can this be done with | 138 | "ti" and "te" termcap commands; can this be done with |
@@ -155,8 +145,8 @@ static void tless_exit(int code) { | |||
155 | /* Grab a character from input without requiring the return key. If the | 145 | /* Grab a character from input without requiring the return key. If the |
156 | character is ASCII \033, get more characters and assign certain sequences | 146 | character is ASCII \033, get more characters and assign certain sequences |
157 | special return codes. Note that this function works best with raw input. */ | 147 | special return codes. Note that this function works best with raw input. */ |
158 | static int tless_getch(void) { | 148 | static int tless_getch(void) |
159 | 149 | { | |
160 | int input; | 150 | int input; |
161 | 151 | ||
162 | set_tty_raw(); | 152 | set_tty_raw(); |
@@ -191,18 +181,20 @@ static int tless_getch(void) { | |||
191 | 181 | ||
192 | /* Move the cursor to a position (x,y), where (0,0) is the | 182 | /* Move the cursor to a position (x,y), where (0,0) is the |
193 | top-left corner of the console */ | 183 | top-left corner of the console */ |
194 | static void move_cursor(int x, int y) { | 184 | static void move_cursor(int x, int y) |
185 | { | ||
195 | printf("\033[%i;%iH", x, y); | 186 | printf("\033[%i;%iH", x, y); |
196 | } | 187 | } |
197 | 188 | ||
198 | static void clear_line(void) { | 189 | static void clear_line(void) |
190 | { | ||
199 | move_cursor(height, 0); | 191 | move_cursor(height, 0); |
200 | printf("\033[K"); | 192 | printf("\033[K"); |
201 | } | 193 | } |
202 | 194 | ||
203 | /* This adds line numbers to every line, as the -N flag necessitates */ | 195 | /* This adds line numbers to every line, as the -N flag necessitates */ |
204 | static void add_linenumbers(void) { | 196 | static void add_linenumbers(void) |
205 | 197 | { | |
206 | char current_line[256]; | 198 | char current_line[256]; |
207 | int i; | 199 | int i; |
208 | 200 | ||
@@ -212,8 +204,8 @@ static void add_linenumbers(void) { | |||
212 | } | 204 | } |
213 | } | 205 | } |
214 | 206 | ||
215 | static void data_readlines(void) { | 207 | static void data_readlines(void) |
216 | 208 | { | |
217 | int i; | 209 | int i; |
218 | char current_line[256]; | 210 | char current_line[256]; |
219 | FILE *fp; | 211 | FILE *fp; |
@@ -223,7 +215,7 @@ static void data_readlines(void) { | |||
223 | for (i = 0; (feof(fp)==0) && (i <= MAXLINES); i++) { | 215 | for (i = 0; (feof(fp)==0) && (i <= MAXLINES); i++) { |
224 | strcpy(current_line, ""); | 216 | strcpy(current_line, ""); |
225 | fgets(current_line, 256, fp); | 217 | fgets(current_line, 256, fp); |
226 | if(fp != stdin) | 218 | if (fp != stdin) |
227 | bb_xferror(fp, filename); | 219 | bb_xferror(fp, filename); |
228 | flines = xrealloc(flines, (i+1) * sizeof(char *)); | 220 | flines = xrealloc(flines, (i+1) * sizeof(char *)); |
229 | flines[i] = bb_xstrdup(current_line); | 221 | flines[i] = bb_xstrdup(current_line); |
@@ -237,31 +229,25 @@ static void data_readlines(void) { | |||
237 | 229 | ||
238 | fclose(fp); | 230 | fclose(fp); |
239 | 231 | ||
240 | if(inp == NULL) | 232 | if (inp == NULL) |
241 | inp = (inp_stdin) ? bb_xfopen(CURRENT_TTY, "r") : stdin; | 233 | inp = (inp_stdin) ? bb_xfopen(CURRENT_TTY, "r") : stdin; |
242 | 234 | ||
243 | if (flags & FLAG_N) | 235 | if (flags & FLAG_N) |
244 | add_linenumbers(); | 236 | add_linenumbers(); |
245 | } | 237 | } |
246 | 238 | ||
247 | /* Turn a percentage into a line number */ | ||
248 | static int reverse_percent(int percentage) { | ||
249 | double linenum = percentage; | ||
250 | linenum = ((linenum / 100) * num_flines) - 1; | ||
251 | return(linenum); | ||
252 | } | ||
253 | |||
254 | #ifdef CONFIG_FEATURE_LESS_FLAGS | 239 | #ifdef CONFIG_FEATURE_LESS_FLAGS |
255 | 240 | ||
256 | /* Interestingly, writing calc_percent as a function and not a prototype saves around 32 bytes | 241 | /* Interestingly, writing calc_percent as a function and not a prototype saves around 32 bytes |
257 | * on my build. */ | 242 | * on my build. */ |
258 | static int calc_percent(void) { | 243 | static int calc_percent(void) |
244 | { | ||
259 | return ((100 * (line_pos + height - 2) / num_flines) + 1); | 245 | return ((100 * (line_pos + height - 2) / num_flines) + 1); |
260 | } | 246 | } |
261 | 247 | ||
262 | /* Print a status line if -M was specified */ | 248 | /* Print a status line if -M was specified */ |
263 | static void m_status_print(void) { | 249 | static void m_status_print(void) |
264 | 250 | { | |
265 | int percentage; | 251 | int percentage; |
266 | 252 | ||
267 | if (!past_eof) { | 253 | if (!past_eof) { |
@@ -295,8 +281,8 @@ static void m_status_print(void) { | |||
295 | } | 281 | } |
296 | 282 | ||
297 | /* Print a status line if -m was specified */ | 283 | /* Print a status line if -m was specified */ |
298 | static void medium_status_print(void) { | 284 | static void medium_status_print(void) |
299 | 285 | { | |
300 | int percentage; | 286 | int percentage; |
301 | percentage = calc_percent(); | 287 | percentage = calc_percent(); |
302 | 288 | ||
@@ -310,8 +296,8 @@ static void medium_status_print(void) { | |||
310 | #endif | 296 | #endif |
311 | 297 | ||
312 | /* Print the status line */ | 298 | /* Print the status line */ |
313 | static void status_print(void) { | 299 | static void status_print(void) |
314 | 300 | { | |
315 | /* Change the status if flags have been set */ | 301 | /* Change the status if flags have been set */ |
316 | #ifdef CONFIG_FEATURE_LESS_FLAGS | 302 | #ifdef CONFIG_FEATURE_LESS_FLAGS |
317 | if (flags & FLAG_M) | 303 | if (flags & FLAG_M) |
@@ -340,8 +326,8 @@ static void status_print(void) { | |||
340 | } | 326 | } |
341 | 327 | ||
342 | /* Print the buffer */ | 328 | /* Print the buffer */ |
343 | static void buffer_print(void) { | 329 | static void buffer_print(void) |
344 | 330 | { | |
345 | int i; | 331 | int i; |
346 | 332 | ||
347 | printf("%s", CLEAR); | 333 | printf("%s", CLEAR); |
@@ -360,11 +346,11 @@ static void buffer_print(void) { | |||
360 | } | 346 | } |
361 | 347 | ||
362 | /* Initialise the buffer */ | 348 | /* Initialise the buffer */ |
363 | static void buffer_init(void) { | 349 | static void buffer_init(void) |
364 | 350 | { | |
365 | int i; | 351 | int i; |
366 | 352 | ||
367 | if(buffer == NULL) { | 353 | if (buffer == NULL) { |
368 | /* malloc the number of lines needed for the buffer */ | 354 | /* malloc the number of lines needed for the buffer */ |
369 | buffer = xrealloc(buffer, height * sizeof(char *)); | 355 | buffer = xrealloc(buffer, height * sizeof(char *)); |
370 | } else { | 356 | } else { |
@@ -385,8 +371,8 @@ static void buffer_init(void) { | |||
385 | } | 371 | } |
386 | 372 | ||
387 | /* Move the buffer up and down in the file in order to scroll */ | 373 | /* Move the buffer up and down in the file in order to scroll */ |
388 | static void buffer_down(int nlines) { | 374 | static void buffer_down(int nlines) |
389 | 375 | { | |
390 | int i; | 376 | int i; |
391 | 377 | ||
392 | if (!past_eof) { | 378 | if (!past_eof) { |
@@ -415,8 +401,8 @@ static void buffer_down(int nlines) { | |||
415 | } | 401 | } |
416 | } | 402 | } |
417 | 403 | ||
418 | static void buffer_up(int nlines) { | 404 | static void buffer_up(int nlines) |
419 | 405 | { | |
420 | int i; | 406 | int i; |
421 | int tilde_line; | 407 | int tilde_line; |
422 | 408 | ||
@@ -467,15 +453,14 @@ static void buffer_up(int nlines) { | |||
467 | } | 453 | } |
468 | } | 454 | } |
469 | 455 | ||
470 | static void buffer_line(int linenum) { | 456 | static void buffer_line(int linenum) |
471 | 457 | { | |
472 | int i; | 458 | int i; |
473 | |||
474 | past_eof = 0; | 459 | past_eof = 0; |
475 | 460 | ||
476 | if (linenum < 1 || linenum > num_flines) { | 461 | if (linenum < 0 || linenum > num_flines) { |
477 | clear_line(); | 462 | clear_line(); |
478 | printf("%s%s%i%s", HIGHLIGHT, "Cannot seek to line number ", linenum, NORMAL); | 463 | printf("%s%s%i%s", HIGHLIGHT, "Cannot seek to line number ", linenum + 1, NORMAL); |
479 | } | 464 | } |
480 | else if (linenum < (num_flines - height - 2)) { | 465 | else if (linenum < (num_flines - height - 2)) { |
481 | for (i = 0; i < (height - 1); i++) { | 466 | for (i = 0; i < (height - 1); i++) { |
@@ -483,6 +468,7 @@ static void buffer_line(int linenum) { | |||
483 | buffer[i] = bb_xstrdup(flines[linenum + i]); | 468 | buffer[i] = bb_xstrdup(flines[linenum + i]); |
484 | } | 469 | } |
485 | line_pos = linenum; | 470 | line_pos = linenum; |
471 | buffer_print(); | ||
486 | } | 472 | } |
487 | else { | 473 | else { |
488 | for (i = 0; i < (height - 1); i++) { | 474 | for (i = 0; i < (height - 1); i++) { |
@@ -495,12 +481,13 @@ static void buffer_line(int linenum) { | |||
495 | line_pos = linenum; | 481 | line_pos = linenum; |
496 | /* Set past_eof so buffer_down and buffer_up act differently */ | 482 | /* Set past_eof so buffer_down and buffer_up act differently */ |
497 | past_eof = 1; | 483 | past_eof = 1; |
484 | buffer_print(); | ||
498 | } | 485 | } |
499 | } | 486 | } |
500 | 487 | ||
501 | /* Reinitialise everything for a new file - free the memory and start over */ | 488 | /* Reinitialise everything for a new file - free the memory and start over */ |
502 | static void reinitialise(void) { | 489 | static void reinitialise(void) |
503 | 490 | { | |
504 | int i; | 491 | int i; |
505 | 492 | ||
506 | for (i = 0; i <= num_flines; i++) | 493 | for (i = 0; i <= num_flines; i++) |
@@ -512,8 +499,8 @@ static void reinitialise(void) { | |||
512 | buffer_print(); | 499 | buffer_print(); |
513 | } | 500 | } |
514 | 501 | ||
515 | static void examine_file(void) { | 502 | static void examine_file(void) |
516 | 503 | { | |
517 | int newline_offset; | 504 | int newline_offset; |
518 | 505 | ||
519 | clear_line(); | 506 | clear_line(); |
@@ -538,7 +525,8 @@ static void examine_file(void) { | |||
538 | * 0: go to the first file | 525 | * 0: go to the first file |
539 | * 1: go forward one file | 526 | * 1: go forward one file |
540 | */ | 527 | */ |
541 | static void change_file (int direction) { | 528 | static void change_file(int direction) |
529 | { | ||
542 | if (current_file != ((direction > 0) ? num_files : 1)) { | 530 | if (current_file != ((direction > 0) ? num_files : 1)) { |
543 | current_file = direction ? current_file + direction : 1; | 531 | current_file = direction ? current_file + direction : 1; |
544 | strcpy(filename, files[current_file - 1]); | 532 | strcpy(filename, files[current_file - 1]); |
@@ -550,8 +538,8 @@ static void change_file (int direction) { | |||
550 | } | 538 | } |
551 | } | 539 | } |
552 | 540 | ||
553 | static void remove_current_file(void) { | 541 | static void remove_current_file(void) |
554 | 542 | { | |
555 | int i; | 543 | int i; |
556 | 544 | ||
557 | if (current_file != 1) { | 545 | if (current_file != 1) { |
@@ -571,8 +559,8 @@ static void remove_current_file(void) { | |||
571 | } | 559 | } |
572 | } | 560 | } |
573 | 561 | ||
574 | static void colon_process(void) { | 562 | static void colon_process(void) |
575 | 563 | { | |
576 | int keypress; | 564 | int keypress; |
577 | 565 | ||
578 | /* Clear the current line and print a prompt */ | 566 | /* Clear the current line and print a prompt */ |
@@ -616,132 +604,128 @@ static void colon_process(void) { | |||
616 | /* Get a regular expression from the user, and then go through the current | 604 | /* Get a regular expression from the user, and then go through the current |
617 | file line by line, running a processing regex function on each one. */ | 605 | file line by line, running a processing regex function on each one. */ |
618 | 606 | ||
619 | static char *insert_highlights (char *line, int start, int end) { | 607 | static char *process_regex_on_line(char *line, regex_t *pattern, int action) |
620 | 608 | { | |
621 | return bb_xasprintf("%.*s%s%.*s%s%s", start, line, HIGHLIGHT, | ||
622 | end - start, line + start, NORMAL, line + end); | ||
623 | } | ||
624 | |||
625 | static char *process_regex_on_line(char *line, regex_t *pattern) { | ||
626 | /* This function takes the regex and applies it to the line. | 609 | /* This function takes the regex and applies it to the line. |
627 | Each part of the line that matches has the HIGHLIGHT | 610 | Each part of the line that matches has the HIGHLIGHT |
628 | and NORMAL escape sequences placed around it by | 611 | and NORMAL escape sequences placed around it by |
629 | insert_highlights, and then the line is returned. */ | 612 | insert_highlights if action = 1, or has the escape sequences |
630 | 613 | removed if action = 0, and then the line is returned. */ | |
631 | int match_status; | 614 | int match_status; |
632 | char *line2 = (char *) malloc((sizeof(char) * (strlen(line) + 1)) + 64); | 615 | char *line2 = (char *) xmalloc((sizeof(char) * (strlen(line) + 1)) + 64); |
633 | char sub_line[256]; | 616 | char *growline = ""; |
634 | int prev_eo = 0; | ||
635 | regmatch_t match_structs; | 617 | regmatch_t match_structs; |
636 | 618 | ||
637 | memset(sub_line, 0, 256); | 619 | line2 = bb_xstrdup(line); |
638 | strcpy(line2, line); | ||
639 | 620 | ||
640 | match_found = 0; | 621 | match_found = 0; |
641 | match_status = regexec(pattern, line2, 1, &match_structs, 0); | 622 | match_status = regexec(pattern, line2, 1, &match_structs, 0); |
642 | 623 | ||
643 | while (match_status == 0) { | 624 | while (match_status == 0) { |
644 | |||
645 | memset(sub_line, 0, 256); | ||
646 | |||
647 | if (match_found == 0) | 625 | if (match_found == 0) |
648 | match_found = 1; | 626 | match_found = 1; |
649 | 627 | ||
650 | line2 = insert_highlights(line2, match_structs.rm_so + prev_eo, match_structs.rm_eo + prev_eo); | 628 | if (action) { |
651 | if ((size_t)match_structs.rm_eo + 11 + prev_eo < strlen(line2)) | 629 | 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); |
652 | strcat(sub_line, line2 + match_structs.rm_eo + 11 + prev_eo); | 630 | } |
653 | 631 | else { | |
654 | prev_eo += match_structs.rm_eo + 11; | 632 | 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); |
655 | match_status = regexec(pattern, sub_line, 1, &match_structs, REG_NOTBOL); | 633 | } |
634 | |||
635 | line2 += match_structs.rm_eo; | ||
636 | match_status = regexec(pattern, line2, 1, &match_structs, REG_NOTBOL); | ||
656 | } | 637 | } |
657 | 638 | ||
658 | return line2; | 639 | growline = bb_xasprintf("%s%s", growline, line2); |
640 | |||
641 | return (match_found ? growline : line); | ||
642 | |||
643 | free(growline); | ||
644 | free(line2); | ||
659 | } | 645 | } |
660 | 646 | ||
661 | static void regex_process(void) { | 647 | static void goto_match(int match) |
648 | { | ||
649 | /* This goes to a specific match - all line positions of matches are | ||
650 | stored within the match_lines[] array. */ | ||
651 | if ((match < num_matches) && (match >= 0)) { | ||
652 | buffer_line(match_lines[match]); | ||
653 | match_pos = match; | ||
654 | } | ||
655 | } | ||
662 | 656 | ||
657 | static void regex_process(void) | ||
658 | { | ||
663 | char uncomp_regex[100]; | 659 | char uncomp_regex[100]; |
664 | char current_line[256]; | 660 | char *current_line; |
665 | int i; | 661 | int i; |
666 | int j = 0; | 662 | int j = 0; |
667 | regex_t *pattern; | 663 | regex_t pattern; |
668 | |||
669 | /* Reset variables */ | ||
670 | match_lines[0] = -1; | ||
671 | match_pos = 0; | ||
672 | num_matches = 0; | ||
673 | match_found = 0; | ||
674 | |||
675 | pattern = (regex_t *) malloc(sizeof(regex_t)); | ||
676 | memset(pattern, 0, sizeof(regex_t)); | ||
677 | |||
678 | /* Get the uncompiled regular expression from the user */ | 664 | /* Get the uncompiled regular expression from the user */ |
679 | clear_line(); | 665 | clear_line(); |
680 | putchar((match_backwards) ? '?' : '/'); | 666 | putchar((match_backwards) ? '?' : '/'); |
681 | uncomp_regex[0] = 0; | 667 | uncomp_regex[0] = 0; |
682 | fgets(uncomp_regex, sizeof(uncomp_regex), stdin); | 668 | fgets(uncomp_regex, sizeof(uncomp_regex), inp); |
683 | i = strlen(uncomp_regex); | 669 | |
684 | if(i > 0) { | 670 | if (strlen(uncomp_regex) == 1) { |
685 | if(uncomp_regex[i-1] == '\n') | 671 | if (num_matches) |
686 | uncomp_regex[i-1] = '\0'; | 672 | goto_match(match_backwards ? match_pos - 1 : match_pos + 1); |
687 | else | 673 | else |
688 | while((i = getchar()) != '\n' && i != EOF); | 674 | buffer_print(); |
675 | return; | ||
689 | } | 676 | } |
690 | 677 | uncomp_regex[strlen(uncomp_regex) - 1] = '\0'; | |
678 | |||
691 | /* Compile the regex and check for errors */ | 679 | /* Compile the regex and check for errors */ |
692 | xregcomp(pattern, uncomp_regex, 0); | 680 | xregcomp(&pattern, uncomp_regex, 0); |
693 | 681 | ||
682 | if (num_matches) { | ||
683 | /* Get rid of all the highlights we added previously */ | ||
684 | for (i = 0; i <= num_flines; i++) { | ||
685 | current_line = process_regex_on_line(flines[i], &old_pattern, 0); | ||
686 | flines[i] = bb_xstrdup(current_line); | ||
687 | } | ||
688 | } | ||
689 | old_pattern = pattern; | ||
690 | |||
691 | /* Reset variables */ | ||
692 | match_lines = xrealloc(match_lines, sizeof(int)); | ||
693 | match_lines[0] = -1; | ||
694 | match_pos = 0; | ||
695 | num_matches = 0; | ||
696 | match_found = 0; | ||
694 | /* Run the regex on each line of the current file here */ | 697 | /* Run the regex on each line of the current file here */ |
695 | for (i = 0; i <= num_flines; i++) { | 698 | for (i = 0; i <= num_flines; i++) { |
696 | strcpy(current_line, process_regex_on_line(flines[i], pattern)); | 699 | current_line = process_regex_on_line(flines[i], &pattern, 1); |
697 | flines[i] = bb_xstrdup(current_line); | 700 | flines[i] = bb_xstrdup(current_line); |
698 | if (match_found) { | 701 | if (match_found) { |
702 | match_lines = xrealloc(match_lines, (j + 1) * sizeof(int)); | ||
699 | match_lines[j] = i; | 703 | match_lines[j] = i; |
700 | j++; | 704 | j++; |
701 | } | 705 | } |
702 | } | 706 | } |
703 | 707 | ||
704 | num_matches = j; | 708 | num_matches = j; |
705 | if ((match_lines[0] != -1) && (num_flines > height - 2)) | 709 | if ((match_lines[0] != -1) && (num_flines > height - 2)) { |
706 | buffer_line(match_lines[0]); | 710 | if (match_backwards) { |
707 | else | 711 | for (i = 0; i < num_matches; i++) { |
708 | buffer_init(); | 712 | if (match_lines[i] > line_pos) { |
709 | } | 713 | match_pos = i - 1; |
710 | 714 | buffer_line(match_lines[match_pos]); | |
711 | static void goto_match(int match) { | 715 | break; |
712 | 716 | } | |
713 | /* This goes to a specific match - all line positions of matches are | 717 | } |
714 | stored within the match_lines[] array. */ | ||
715 | if ((match < num_matches) && (match >= 0)) { | ||
716 | buffer_line(match_lines[match]); | ||
717 | match_pos = match; | ||
718 | } | ||
719 | } | ||
720 | |||
721 | static void search_backwards(void) { | ||
722 | |||
723 | int current_linepos = line_pos; | ||
724 | int i; | ||
725 | |||
726 | match_backwards = 1; | ||
727 | regex_process(); | ||
728 | |||
729 | for (i = 0; i < num_matches; i++) { | ||
730 | if (match_lines[i] > current_linepos) { | ||
731 | buffer_line(match_lines[i - num_back_match]); | ||
732 | break; | ||
733 | } | 718 | } |
719 | else | ||
720 | buffer_line(match_lines[0]); | ||
734 | } | 721 | } |
735 | 722 | else | |
736 | /* Reset variables */ | 723 | buffer_init(); |
737 | match_backwards = 0; | ||
738 | num_back_match = 1; | ||
739 | |||
740 | } | 724 | } |
741 | #endif | 725 | #endif |
742 | 726 | ||
743 | static void number_process(int first_digit) { | 727 | static void number_process(int first_digit) |
744 | 728 | { | |
745 | int i = 1; | 729 | int i = 1; |
746 | int num; | 730 | int num; |
747 | char num_input[80]; | 731 | char num_input[80]; |
@@ -764,8 +748,10 @@ static void number_process(int first_digit) { | |||
764 | keypress = num_input[i]; | 748 | keypress = num_input[i]; |
765 | num_input[i] = '\0'; | 749 | num_input[i] = '\0'; |
766 | num = strtol(num_input, &endptr, 10); | 750 | num = strtol(num_input, &endptr, 10); |
767 | if (endptr==num_input || *endptr!='\0' || num < 1 || num > MAXLINES) | 751 | if (endptr==num_input || *endptr!='\0' || num < 1 || num > MAXLINES) { |
768 | goto END; | 752 | buffer_print(); |
753 | return; | ||
754 | } | ||
769 | 755 | ||
770 | /* We now know the number and the letter entered, so we process them */ | 756 | /* We now know the number and the letter entered, so we process them */ |
771 | switch (keypress) { | 757 | switch (keypress) { |
@@ -780,31 +766,29 @@ static void number_process(int first_digit) { | |||
780 | buffer_line(num - 1); | 766 | buffer_line(num - 1); |
781 | break; | 767 | break; |
782 | case 'p': case '%': | 768 | case 'p': case '%': |
783 | buffer_line(reverse_percent(num)); | 769 | buffer_line(((num / 100) * num_flines) - 1); |
784 | break; | 770 | break; |
785 | #ifdef CONFIG_FEATURE_LESS_REGEXP | 771 | #ifdef CONFIG_FEATURE_LESS_REGEXP |
786 | case 'n': | 772 | case 'n': |
787 | goto_match(match_pos + num - 1); | 773 | goto_match(match_pos + num); |
788 | break; | 774 | break; |
789 | case '/': | 775 | case '/': |
776 | match_backwards = 0; | ||
790 | regex_process(); | 777 | regex_process(); |
791 | goto_match(num - 1); | ||
792 | break; | 778 | break; |
793 | case '?': | 779 | case '?': |
794 | num_back_match = num; | 780 | match_backwards = 1; |
795 | search_backwards(); | 781 | regex_process(); |
796 | break; | 782 | break; |
797 | #endif | 783 | #endif |
798 | default: | 784 | default: |
799 | break; | 785 | break; |
800 | } | 786 | } |
801 | END: | ||
802 | buffer_print(); | ||
803 | } | 787 | } |
804 | 788 | ||
805 | #ifdef CONFIG_FEATURE_LESS_FLAGCS | 789 | #ifdef CONFIG_FEATURE_LESS_FLAGCS |
806 | static void flag_change(void) { | 790 | static void flag_change(void) |
807 | 791 | { | |
808 | int keypress; | 792 | int keypress; |
809 | 793 | ||
810 | clear_line(); | 794 | clear_line(); |
@@ -829,8 +813,8 @@ static void flag_change(void) { | |||
829 | } | 813 | } |
830 | } | 814 | } |
831 | 815 | ||
832 | static void show_flag_status(void) { | 816 | static void show_flag_status(void) |
833 | 817 | { | |
834 | int keypress; | 818 | int keypress; |
835 | int flag_val; | 819 | int flag_val; |
836 | 820 | ||
@@ -864,18 +848,17 @@ static void show_flag_status(void) { | |||
864 | } | 848 | } |
865 | #endif | 849 | #endif |
866 | 850 | ||
867 | static void full_repaint(void) { | 851 | static void full_repaint(void) |
868 | 852 | { | |
869 | int temp_line_pos = line_pos; | 853 | int temp_line_pos = line_pos; |
870 | data_readlines(); | 854 | data_readlines(); |
871 | buffer_init(); | 855 | buffer_init(); |
872 | buffer_line(temp_line_pos); | 856 | buffer_line(temp_line_pos); |
873 | buffer_print(); | ||
874 | } | 857 | } |
875 | 858 | ||
876 | 859 | ||
877 | static void save_input_to_file(void) { | 860 | static void save_input_to_file(void) |
878 | 861 | { | |
879 | char current_line[256]; | 862 | char current_line[256]; |
880 | int i; | 863 | int i; |
881 | FILE *fp; | 864 | FILE *fp; |
@@ -884,7 +867,7 @@ static void save_input_to_file(void) { | |||
884 | printf("Log file: "); | 867 | printf("Log file: "); |
885 | fgets(current_line, 256, inp); | 868 | fgets(current_line, 256, inp); |
886 | current_line[strlen(current_line) - 1] = '\0'; | 869 | current_line[strlen(current_line) - 1] = '\0'; |
887 | if (strlen(current_line)) { | 870 | if (strlen(current_line) > 1) { |
888 | fp = bb_xfopen(current_line, "w"); | 871 | fp = bb_xfopen(current_line, "w"); |
889 | for (i = 0; i < num_flines; i++) | 872 | for (i = 0; i < num_flines; i++) |
890 | fprintf(fp, "%s", flines[i]); | 873 | fprintf(fp, "%s", flines[i]); |
@@ -896,8 +879,8 @@ static void save_input_to_file(void) { | |||
896 | } | 879 | } |
897 | 880 | ||
898 | #ifdef CONFIG_FEATURE_LESS_MARKS | 881 | #ifdef CONFIG_FEATURE_LESS_MARKS |
899 | static void add_mark(void) { | 882 | static void add_mark(void) |
900 | 883 | { | |
901 | int letter; | 884 | int letter; |
902 | int mark_line; | 885 | int mark_line; |
903 | 886 | ||
@@ -922,8 +905,8 @@ static void add_mark(void) { | |||
922 | } | 905 | } |
923 | } | 906 | } |
924 | 907 | ||
925 | static void goto_mark(void) { | 908 | static void goto_mark(void) |
926 | 909 | { | |
927 | int letter; | 910 | int letter; |
928 | int i; | 911 | int i; |
929 | 912 | ||
@@ -949,8 +932,8 @@ static void goto_mark(void) { | |||
949 | 932 | ||
950 | #ifdef CONFIG_FEATURE_LESS_BRACKETS | 933 | #ifdef CONFIG_FEATURE_LESS_BRACKETS |
951 | 934 | ||
952 | static char opp_bracket (char bracket) { | 935 | static char opp_bracket(char bracket) |
953 | 936 | { | |
954 | switch (bracket) { | 937 | switch (bracket) { |
955 | case '{': case '[': | 938 | case '{': case '[': |
956 | return bracket + 2; | 939 | return bracket + 2; |
@@ -970,8 +953,8 @@ static char opp_bracket (char bracket) { | |||
970 | } | 953 | } |
971 | } | 954 | } |
972 | 955 | ||
973 | static void match_right_bracket(char bracket) { | 956 | static void match_right_bracket(char bracket) |
974 | 957 | { | |
975 | int bracket_line = -1; | 958 | int bracket_line = -1; |
976 | int i; | 959 | int i; |
977 | 960 | ||
@@ -991,12 +974,11 @@ static void match_right_bracket(char bracket) { | |||
991 | printf("%s%s%s", HIGHLIGHT, "No matching bracket found", NORMAL); | 974 | printf("%s%s%s", HIGHLIGHT, "No matching bracket found", NORMAL); |
992 | 975 | ||
993 | buffer_line(bracket_line - height + 2); | 976 | buffer_line(bracket_line - height + 2); |
994 | buffer_print(); | ||
995 | } | 977 | } |
996 | } | 978 | } |
997 | 979 | ||
998 | static void match_left_bracket (char bracket) { | 980 | static void match_left_bracket(char bracket) |
999 | 981 | { | |
1000 | int bracket_line = -1; | 982 | int bracket_line = -1; |
1001 | int i; | 983 | int i; |
1002 | 984 | ||
@@ -1019,13 +1001,13 @@ static void match_left_bracket (char bracket) { | |||
1019 | printf("%s%s%s", HIGHLIGHT, "No matching bracket found", NORMAL); | 1001 | printf("%s%s%s", HIGHLIGHT, "No matching bracket found", NORMAL); |
1020 | 1002 | ||
1021 | buffer_line(bracket_line); | 1003 | buffer_line(bracket_line); |
1022 | buffer_print(); | ||
1023 | } | 1004 | } |
1024 | } | 1005 | } |
1025 | 1006 | ||
1026 | #endif /* CONFIG_FEATURE_LESS_BRACKETS */ | 1007 | #endif /* CONFIG_FEATURE_LESS_BRACKETS */ |
1027 | 1008 | ||
1028 | static void keypress_process(int keypress) { | 1009 | static void keypress_process(int keypress) |
1010 | { | ||
1029 | switch (keypress) { | 1011 | switch (keypress) { |
1030 | case KEY_DOWN: case 'e': case 'j': case '\015': | 1012 | case KEY_DOWN: case 'e': case 'j': case '\015': |
1031 | buffer_down(1); | 1013 | buffer_down(1); |
@@ -1052,12 +1034,10 @@ static void keypress_process(int keypress) { | |||
1052 | buffer_print(); | 1034 | buffer_print(); |
1053 | break; | 1035 | break; |
1054 | case 'g': case 'p': case '<': case '%': | 1036 | case 'g': case 'p': case '<': case '%': |
1055 | buffer_up(num_flines + 1); | 1037 | buffer_line(0); |
1056 | buffer_print(); | ||
1057 | break; | 1038 | break; |
1058 | case 'G': case '>': | 1039 | case 'G': case '>': |
1059 | buffer_down(num_flines + 1); | 1040 | buffer_line(num_flines - height + 2); |
1060 | buffer_print(); | ||
1061 | break; | 1041 | break; |
1062 | case 'q': case 'Q': | 1042 | case 'q': case 'Q': |
1063 | tless_exit(0); | 1043 | tless_exit(0); |
@@ -1093,20 +1073,18 @@ static void keypress_process(int keypress) { | |||
1093 | #endif | 1073 | #endif |
1094 | #ifdef CONFIG_FEATURE_LESS_REGEXP | 1074 | #ifdef CONFIG_FEATURE_LESS_REGEXP |
1095 | case '/': | 1075 | case '/': |
1076 | match_backwards = 0; | ||
1096 | regex_process(); | 1077 | regex_process(); |
1097 | buffer_print(); | ||
1098 | break; | 1078 | break; |
1099 | case 'n': | 1079 | case 'n': |
1100 | goto_match(match_pos + 1); | 1080 | goto_match(match_pos + 1); |
1101 | buffer_print(); | ||
1102 | break; | 1081 | break; |
1103 | case 'N': | 1082 | case 'N': |
1104 | goto_match(match_pos - 1); | 1083 | goto_match(match_pos - 1); |
1105 | buffer_print(); | ||
1106 | break; | 1084 | break; |
1107 | case '?': | 1085 | case '?': |
1108 | search_backwards(); | 1086 | match_backwards = 1; |
1109 | buffer_print(); | 1087 | regex_process(); |
1110 | break; | 1088 | break; |
1111 | #endif | 1089 | #endif |
1112 | #ifdef CONFIG_FEATURE_LESS_FLAGCS | 1090 | #ifdef CONFIG_FEATURE_LESS_FLAGCS |