aboutsummaryrefslogtreecommitdiff
path: root/miscutils/less.c
diff options
context:
space:
mode:
authorBernhard Reutner-Fischer <rep.dot.nop@gmail.com>2006-12-04 16:04:50 +0000
committerBernhard Reutner-Fischer <rep.dot.nop@gmail.com>2006-12-04 16:04:50 +0000
commit882e60c44249d1a2a7d78d873dce02f16eb19eac (patch)
tree14f1b2a8a4da6825af0c26fb33db37c1c76ce1e3 /miscutils/less.c
parentbbda98f14c66fb573bc75ff3b9222697d2ffa8fb (diff)
downloadbusybox-w32-882e60c44249d1a2a7d78d873dce02f16eb19eac.tar.gz
busybox-w32-882e60c44249d1a2a7d78d873dce02f16eb19eac.tar.bz2
busybox-w32-882e60c44249d1a2a7d78d873dce02f16eb19eac.zip
- shrink less.
01a: svn version 01b: merge past_eof and inp_stdin into flags. 01c: merge match_backwards into flags. 01d: add handling of <HOME> and <END> keys, remove set_tty_raw, use fflush_stdout_and_exit 01e: rewrite special-key handling to be smaller. 01f: changing the format saves 4 bytes (alot of places would benefit from this) text data bss dec hex filename 9034 8 648 9690 25da less.o.01a 9023 8 640 9671 25c7 less.o.01b 9027 8 636 9671 25c7 less.o.01c 9068 8 636 9712 25f0 less.o.01d 8990 8 636 9634 25a2 less.o.01e 8986 8 636 9630 259e less.o.01f
Diffstat (limited to 'miscutils/less.c')
-rw-r--r--miscutils/less.c105
1 files changed, 49 insertions, 56 deletions
diff --git a/miscutils/less.c b/miscutils/less.c
index de97ba6b9..03ffd78ed 100644
--- a/miscutils/less.c
+++ b/miscutils/less.c
@@ -44,14 +44,18 @@
44#define REAL_KEY_LEFT 'D' 44#define REAL_KEY_LEFT 'D'
45#define REAL_PAGE_UP '5' 45#define REAL_PAGE_UP '5'
46#define REAL_PAGE_DOWN '6' 46#define REAL_PAGE_DOWN '6'
47#define REAL_KEY_HOME '7'
48#define REAL_KEY_END '8'
47 49
48/* These are the special codes assigned by this program to the special keys */ 50/* These are the special codes assigned by this program to the special keys */
49#define PAGE_UP 20 51#define KEY_UP 20
50#define PAGE_DOWN 21 52#define KEY_DOWN 21
51#define KEY_UP 22 53#define KEY_RIGHT 22
52#define KEY_DOWN 23 54#define KEY_LEFT 23
53#define KEY_RIGHT 24 55#define PAGE_UP 24
54#define KEY_LEFT 25 56#define PAGE_DOWN 25
57#define KEY_HOME 26
58#define KEY_END 27
55 59
56/* The escape codes for highlighted and normal text */ 60/* The escape codes for highlighted and normal text */
57#define HIGHLIGHT "\033[7m" 61#define HIGHLIGHT "\033[7m"
@@ -73,7 +77,6 @@ static int current_file = 1;
73static int line_pos; 77static int line_pos;
74static int num_flines; 78static int num_flines;
75static int num_files = 1; 79static int num_files = 1;
76static int past_eof;
77 80
78/* Command line options */ 81/* Command line options */
79static unsigned flags; 82static unsigned flags;
@@ -82,10 +85,11 @@ static unsigned flags;
82#define FLAG_m (1<<2) 85#define FLAG_m (1<<2)
83#define FLAG_N (1<<3) 86#define FLAG_N (1<<3)
84#define FLAG_TILDE (1<<4) 87#define FLAG_TILDE (1<<4)
85 88/* hijack command line options variable for internal state vars */
86/* This is needed so that program behaviour changes when input comes from 89#define LESS_STATE_INP_STDIN (1<<5)
87 stdin */ 90#define LESS_STATE_PAST_EOF (1<<6)
88static int inp_stdin; 91#define LESS_STATE_MATCH_BACKWARDS (1<<7)
92/* INP_STDIN is used to change behaviour when input comes from stdin */
89 93
90#ifdef CONFIG_FEATURE_LESS_MARKS 94#ifdef CONFIG_FEATURE_LESS_MARKS
91static int mark_lines[15][2]; 95static int mark_lines[15][2];
@@ -97,7 +101,6 @@ static int match_found;
97static int *match_lines; 101static int *match_lines;
98static int match_pos; 102static int match_pos;
99static int num_matches; 103static int num_matches;
100static int match_backwards;
101static regex_t old_pattern; 104static regex_t old_pattern;
102#endif 105#endif
103 106
@@ -114,12 +117,6 @@ static void set_tty_cooked(void)
114 tcsetattr(fileno(inp), TCSANOW, &term_orig); 117 tcsetattr(fileno(inp), TCSANOW, &term_orig);
115} 118}
116 119
117/* Set terminal input to raw mode (taken from vi.c) */
118static void set_tty_raw(void)
119{
120 tcsetattr(fileno(inp), TCSANOW, &term_vi);
121}
122
123/* Exit the program gracefully */ 120/* Exit the program gracefully */
124static void tless_exit(int code) 121static void tless_exit(int code)
125{ 122{
@@ -129,7 +126,7 @@ static void tless_exit(int code)
129 only termios.h? */ 126 only termios.h? */
130 127
131 putchar('\n'); 128 putchar('\n');
132 exit(code); 129 fflush_stdout_and_exit(code);
133} 130}
134 131
135/* Grab a character from input without requiring the return key. If the 132/* Grab a character from input without requiring the return key. If the
@@ -138,28 +135,23 @@ static void tless_exit(int code)
138static int tless_getch(void) 135static int tless_getch(void)
139{ 136{
140 int input; 137 int input;
141 138 /* Set terminal input to raw mode (taken from vi.c) */
142 set_tty_raw(); 139 tcsetattr(fileno(inp), TCSANOW, &term_vi);
143 140
144 input = getc(inp); 141 input = getc(inp);
145 /* Detect escape sequences (i.e. arrow keys) and handle 142 /* Detect escape sequences (i.e. arrow keys) and handle
146 them accordingly */ 143 them accordingly */
147 144
148 if (input == '\033' && getc(inp) == '[') { 145 if (input == '\033' && getc(inp) == '[') {
146 unsigned int i;
149 input = getc(inp); 147 input = getc(inp);
150 set_tty_cooked(); 148 set_tty_cooked();
151 if (input == REAL_KEY_UP) 149
152 return KEY_UP; 150 i = input - REAL_KEY_UP;
153 else if (input == REAL_KEY_DOWN) 151 if (i < 4)
154 return KEY_DOWN; 152 return 20 + i;
155 else if (input == REAL_KEY_RIGHT) 153 else if ((i = input - REAL_PAGE_UP) < 4)
156 return KEY_RIGHT; 154 return 24 + i;
157 else if (input == REAL_KEY_LEFT)
158 return KEY_LEFT;
159 else if (input == REAL_PAGE_UP)
160 return PAGE_UP;
161 else if (input == REAL_PAGE_DOWN)
162 return PAGE_DOWN;
163 } 155 }
164 /* The input is a normal ASCII value */ 156 /* The input is a normal ASCII value */
165 else { 157 else {
@@ -200,7 +192,7 @@ static void data_readlines(void)
200 char current_line[256]; 192 char current_line[256];
201 FILE *fp; 193 FILE *fp;
202 194
203 fp = (inp_stdin) ? stdin : xfopen(filename, "r"); 195 fp = (flags & LESS_STATE_INP_STDIN) ? stdin : xfopen(filename, "r");
204 flines = NULL; 196 flines = NULL;
205 for (i = 0; (feof(fp)==0) && (i <= MAXLINES); i++) { 197 for (i = 0; (feof(fp)==0) && (i <= MAXLINES); i++) {
206 strcpy(current_line, ""); 198 strcpy(current_line, "");
@@ -215,12 +207,12 @@ static void data_readlines(void)
215 /* Reset variables for a new file */ 207 /* Reset variables for a new file */
216 208
217 line_pos = 0; 209 line_pos = 0;
218 past_eof = 0; 210 flags &= ~LESS_STATE_PAST_EOF;
219 211
220 fclose(fp); 212 fclose(fp);
221 213
222 if (inp == NULL) 214 if (inp == NULL)
223 inp = (inp_stdin) ? xfopen(CURRENT_TTY, "r") : stdin; 215 inp = (flags & LESS_STATE_INP_STDIN) ? xfopen(CURRENT_TTY, "r") : stdin;
224 216
225 if (flags & FLAG_N) 217 if (flags & FLAG_N)
226 add_linenumbers(); 218 add_linenumbers();
@@ -240,7 +232,7 @@ static void m_status_print(void)
240{ 232{
241 int percentage; 233 int percentage;
242 234
243 if (!past_eof) { 235 if (!(flags & LESS_STATE_PAST_EOF)) {
244 if (!line_pos) { 236 if (!line_pos) {
245 if (num_files > 1) 237 if (num_files > 1)
246 printf("%s%s %s%i%s%i%s%i-%i/%i ", HIGHLIGHT, 238 printf("%s%s %s%i%s%i%s%i-%i/%i ", HIGHLIGHT,
@@ -372,7 +364,7 @@ static void buffer_down(int nlines)
372{ 364{
373 int i; 365 int i;
374 366
375 if (!past_eof) { 367 if (!(flags & LESS_STATE_PAST_EOF)) {
376 if (line_pos + (height - 3) + nlines < num_flines) { 368 if (line_pos + (height - 3) + nlines < num_flines) {
377 line_pos += nlines; 369 line_pos += nlines;
378 for (i = 0; i < (height - 1); i++) { 370 for (i = 0; i < (height - 1); i++) {
@@ -403,7 +395,7 @@ static void buffer_up(int nlines)
403 int i; 395 int i;
404 int tilde_line; 396 int tilde_line;
405 397
406 if (!past_eof) { 398 if (!(flags & LESS_STATE_PAST_EOF)) {
407 if (line_pos - nlines >= 0) { 399 if (line_pos - nlines >= 0) {
408 line_pos -= nlines; 400 line_pos -= nlines;
409 for (i = 0; i < (height - 1); i++) { 401 for (i = 0; i < (height - 1); i++) {
@@ -431,7 +423,7 @@ static void buffer_up(int nlines)
431 /* Going backwards nlines lines has taken us to a point where 423 /* Going backwards nlines lines has taken us to a point where
432 nothing is past the EOF, so we revert to normal. */ 424 nothing is past the EOF, so we revert to normal. */
433 if (line_pos < num_flines - height + 3) { 425 if (line_pos < num_flines - height + 3) {
434 past_eof = 0; 426 flags &= ~LESS_STATE_PAST_EOF;
435 buffer_up(nlines); 427 buffer_up(nlines);
436 } 428 }
437 else { 429 else {
@@ -453,7 +445,7 @@ static void buffer_up(int nlines)
453static void buffer_line(int linenum) 445static void buffer_line(int linenum)
454{ 446{
455 int i; 447 int i;
456 past_eof = 0; 448 flags &= ~LESS_STATE_PAST_EOF;
457 449
458 if (linenum < 0 || linenum > num_flines) { 450 if (linenum < 0 || linenum > num_flines) {
459 clear_line(); 451 clear_line();
@@ -477,7 +469,7 @@ static void buffer_line(int linenum)
477 } 469 }
478 line_pos = linenum; 470 line_pos = linenum;
479 /* Set past_eof so buffer_down and buffer_up act differently */ 471 /* Set past_eof so buffer_down and buffer_up act differently */
480 past_eof = 1; 472 flags |= LESS_STATE_PAST_EOF;
481 buffer_print(); 473 buffer_print();
482 } 474 }
483} 475}
@@ -513,7 +505,7 @@ static void examine_file(void)
513 current_file = num_files + 1; 505 current_file = num_files + 1;
514 num_files++; 506 num_files++;
515 507
516 inp_stdin = 0; 508 flags &= ~LESS_STATE_INP_STDIN;
517 reinitialise(); 509 reinitialise();
518} 510}
519 511
@@ -666,13 +658,14 @@ static void regex_process(void)
666 regex_t pattern; 658 regex_t pattern;
667 /* Get the uncompiled regular expression from the user */ 659 /* Get the uncompiled regular expression from the user */
668 clear_line(); 660 clear_line();
669 putchar((match_backwards) ? '?' : '/'); 661 putchar((flags & LESS_STATE_MATCH_BACKWARDS) ? '?' : '/');
670 uncomp_regex[0] = 0; 662 uncomp_regex[0] = 0;
671 fgets(uncomp_regex, sizeof(uncomp_regex), inp); 663 fgets(uncomp_regex, sizeof(uncomp_regex), inp);
672 664
673 if (strlen(uncomp_regex) == 1) { 665 if (strlen(uncomp_regex) == 1) {
674 if (num_matches) 666 if (num_matches)
675 goto_match(match_backwards ? match_pos - 1 : match_pos + 1); 667 goto_match((flags & LESS_STATE_MATCH_BACKWARDS)
668 ? match_pos - 1 : match_pos + 1);
676 else 669 else
677 buffer_print(); 670 buffer_print();
678 return; 671 return;
@@ -710,7 +703,7 @@ static void regex_process(void)
710 703
711 num_matches = j; 704 num_matches = j;
712 if ((match_lines[0] != -1) && (num_flines > height - 2)) { 705 if ((match_lines[0] != -1) && (num_flines > height - 2)) {
713 if (match_backwards) { 706 if (flags & LESS_STATE_MATCH_BACKWARDS) {
714 for (i = 0; i < num_matches; i++) { 707 for (i = 0; i < num_matches; i++) {
715 if (match_lines[i] > line_pos) { 708 if (match_lines[i] > line_pos) {
716 match_pos = i - 1; 709 match_pos = i - 1;
@@ -776,11 +769,11 @@ static void number_process(int first_digit)
776 goto_match(match_pos + num); 769 goto_match(match_pos + num);
777 break; 770 break;
778 case '/': 771 case '/':
779 match_backwards = 0; 772 flags &= ~LESS_STATE_MATCH_BACKWARDS;
780 regex_process(); 773 regex_process();
781 break; 774 break;
782 case '?': 775 case '?':
783 match_backwards = 1; 776 flags |= LESS_STATE_MATCH_BACKWARDS;
784 regex_process(); 777 regex_process();
785 break; 778 break;
786#endif 779#endif
@@ -878,7 +871,7 @@ static void save_input_to_file(void)
878 buffer_print(); 871 buffer_print();
879 } 872 }
880 else 873 else
881 printf("%sNo log file%s", HIGHLIGHT, NORMAL); 874 printf("%s%s%s", HIGHLIGHT, "No log file", NORMAL);
882} 875}
883 876
884#ifdef CONFIG_FEATURE_LESS_MARKS 877#ifdef CONFIG_FEATURE_LESS_MARKS
@@ -1029,10 +1022,10 @@ static void keypress_process(int keypress)
1029 buffer_up((height - 1) / 2); 1022 buffer_up((height - 1) / 2);
1030 buffer_print(); 1023 buffer_print();
1031 break; 1024 break;
1032 case 'g': case 'p': case '<': case '%': 1025 case KEY_HOME: case 'g': case 'p': case '<': case '%':
1033 buffer_line(0); 1026 buffer_line(0);
1034 break; 1027 break;
1035 case 'G': case '>': 1028 case KEY_END: case 'G': case '>':
1036 buffer_line(num_flines - height + 2); 1029 buffer_line(num_flines - height + 2);
1037 break; 1030 break;
1038 case 'q': case 'Q': 1031 case 'q': case 'Q':
@@ -1055,7 +1048,7 @@ static void keypress_process(int keypress)
1055 full_repaint(); 1048 full_repaint();
1056 break; 1049 break;
1057 case 's': 1050 case 's':
1058 if (inp_stdin) 1051 if (flags & LESS_STATE_INP_STDIN)
1059 save_input_to_file(); 1052 save_input_to_file();
1060 break; 1053 break;
1061 case 'E': 1054 case 'E':
@@ -1069,7 +1062,7 @@ static void keypress_process(int keypress)
1069#endif 1062#endif
1070#ifdef CONFIG_FEATURE_LESS_REGEXP 1063#ifdef CONFIG_FEATURE_LESS_REGEXP
1071 case '/': 1064 case '/':
1072 match_backwards = 0; 1065 flags &= ~LESS_STATE_MATCH_BACKWARDS;
1073 regex_process(); 1066 regex_process();
1074 break; 1067 break;
1075 case 'n': 1068 case 'n':
@@ -1079,7 +1072,7 @@ static void keypress_process(int keypress)
1079 goto_match(match_pos - 1); 1072 goto_match(match_pos - 1);
1080 break; 1073 break;
1081 case '?': 1074 case '?':
1082 match_backwards = 1; 1075 flags |= LESS_STATE_MATCH_BACKWARDS;
1083 regex_process(); 1076 regex_process();
1084 break; 1077 break;
1085#endif 1078#endif
@@ -1124,14 +1117,14 @@ int less_main(int argc, char **argv) {
1124 1117
1125 if (!num_files) { 1118 if (!num_files) {
1126 if (ttyname(STDIN_FILENO) == NULL) 1119 if (ttyname(STDIN_FILENO) == NULL)
1127 inp_stdin = 1; 1120 flags |= LESS_STATE_INP_STDIN;
1128 else { 1121 else {
1129 bb_error_msg("missing filename"); 1122 bb_error_msg("missing filename");
1130 bb_show_usage(); 1123 bb_show_usage();
1131 } 1124 }
1132 } 1125 }
1133 1126
1134 strcpy(filename, (inp_stdin) ? bb_msg_standard_input : files[0]); 1127 strcpy(filename, (flags & LESS_STATE_INP_STDIN) ? bb_msg_standard_input : files[0]);
1135 get_terminal_width_height(0, &width, &height); 1128 get_terminal_width_height(0, &width, &height);
1136 data_readlines(); 1129 data_readlines();
1137 tcgetattr(fileno(inp), &term_orig); 1130 tcgetattr(fileno(inp), &term_orig);