aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-08-15 20:42:52 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-08-15 20:42:52 +0000
commit033e592cbc96c150c67ac9be7df65e314be5c8f8 (patch)
tree0ec512a6215295775b28eb49a4150fadf101465e
parentab9c44b1a41c9a17cd0f8a8f1e5517756ccb8bf0 (diff)
downloadbusybox-w32-033e592cbc96c150c67ac9be7df65e314be5c8f8.tar.gz
busybox-w32-033e592cbc96c150c67ac9be7df65e314be5c8f8.tar.bz2
busybox-w32-033e592cbc96c150c67ac9be7df65e314be5c8f8.zip
more: by Tristan Schmelcher <tpkschme@engmail.uwaterloo.ca>:
- Fixed a number of deficiencies in the line wrapping. - Fixed a bug where the page could scroll multiple times per keypress. - Re-read terminal dimensions after user input, in case they resized the terminal while we were waiting. - Added an 'R' key to print the rest of the file without prompting. - Crudely support tabs in the line-wrapping code by converting them to 8 spaces.
-rw-r--r--util-linux/more.c108
1 files changed, 62 insertions, 46 deletions
diff --git a/util-linux/more.c b/util-linux/more.c
index 4083d8eea..92ebdfea9 100644
--- a/util-linux/more.c
+++ b/util-linux/more.c
@@ -29,11 +29,11 @@ struct globals {
29}; 29};
30#define G (*(struct globals*)bb_common_bufsiz1) 30#define G (*(struct globals*)bb_common_bufsiz1)
31//#define G (*ptr_to_globals) 31//#define G (*ptr_to_globals)
32#define INIT_G() ((void)0)
33//#define INIT_G() PTR_TO_GLOBALS = xzalloc(sizeof(G))
32#define initial_settings (G.initial_settings) 34#define initial_settings (G.initial_settings)
33#define new_settings (G.new_settings ) 35#define new_settings (G.new_settings )
34#define cin_fileno (G.cin_fileno ) 36#define cin_fileno (G.cin_fileno )
35#define INIT_G() ((void)0)
36//#define INIT_G() PTR_TO_GLOBALS = xzalloc(sizeof(G))
37 37
38#define setTermSettings(fd, argp) tcsetattr(fd, TCSANOW, argp) 38#define setTermSettings(fd, argp) tcsetattr(fd, TCSANOW, argp)
39#define getTermSettings(fd, argp) tcgetattr(fd, argp) 39#define getTermSettings(fd, argp) tcgetattr(fd, argp)
@@ -50,16 +50,20 @@ static void gotsig(int sig)
50#define setTermSettings(fd, argp) ((void)0) 50#define setTermSettings(fd, argp) ((void)0)
51#endif /* FEATURE_USE_TERMIOS */ 51#endif /* FEATURE_USE_TERMIOS */
52 52
53#define CONVERTED_TAB_SIZE 8
53 54
54int more_main(int argc, char **argv); 55int more_main(int argc, char **argv);
55int more_main(int argc, char **argv) 56int more_main(int argc, char **argv)
56{ 57{
57 int c, lines, input = 0; 58 int c = c; /* for gcc */
58 int please_display_more_prompt = 0; 59 int lines;
60 int input = 0;
61 int spaces = 0;
62 int please_display_more_prompt;
59 struct stat st; 63 struct stat st;
60 FILE *file; 64 FILE *file;
61 FILE *cin; 65 FILE *cin;
62 int len, page_height; 66 int len;
63 int terminal_width; 67 int terminal_width;
64 int terminal_height; 68 int terminal_height;
65 69
@@ -87,7 +91,6 @@ int more_main(int argc, char **argv)
87 signal(SIGQUIT, gotsig); 91 signal(SIGQUIT, gotsig);
88 signal(SIGTERM, gotsig); 92 signal(SIGTERM, gotsig);
89#endif 93#endif
90 please_display_more_prompt = 2;
91 94
92 do { 95 do {
93 file = stdin; 96 file = stdin;
@@ -99,19 +102,21 @@ int more_main(int argc, char **argv)
99 st.st_size = 0; 102 st.st_size = 0;
100 fstat(fileno(file), &st); 103 fstat(fileno(file), &st);
101 104
102 please_display_more_prompt &= ~1; 105 please_display_more_prompt = 0;
103 /* never returns w, h <= 1 */ 106 /* never returns w, h <= 1 */
104 get_terminal_width_height(fileno(cin), &terminal_width, &terminal_height); 107 get_terminal_width_height(fileno(cin), &terminal_width, &terminal_height);
105 terminal_width -= 1;
106 terminal_height -= 1; 108 terminal_height -= 1;
107 109
108 len = 0; 110 len = 0;
109 lines = 0; 111 lines = 0;
110 page_height = terminal_height; 112 while (spaces || (c = getc(file)) != EOF) {
111 while ((c = getc(file)) != EOF) { 113 int wrap;
112 if ((please_display_more_prompt & 3) == 3) { 114 if (spaces)
115 spaces--;
116 loop_top:
117 if (input != 'r' && please_display_more_prompt) {
113 len = printf("--More-- "); 118 len = printf("--More-- ");
114 if (/*file != stdin &&*/ st.st_size > 0) { 119 if (st.st_size > 0) {
115 len += printf("(%d%% of %"OFF_FMT"d bytes)", 120 len += printf("(%d%% of %"OFF_FMT"d bytes)",
116 (int) (ftello(file)*100 / st.st_size), 121 (int) (ftello(file)*100 / st.st_size),
117 st.st_size); 122 st.st_size);
@@ -122,23 +127,44 @@ int more_main(int argc, char **argv)
122 * We've just displayed the "--More--" prompt, so now we need 127 * We've just displayed the "--More--" prompt, so now we need
123 * to get input from the user. 128 * to get input from the user.
124 */ 129 */
125 input = getc(cin); 130 for (;;) {
131 input = getc(cin);
132 input = tolower(input);
126#if !ENABLE_FEATURE_USE_TERMIOS 133#if !ENABLE_FEATURE_USE_TERMIOS
127 printf("\033[A"); /* up cursor */ 134 printf("\033[A"); /* up cursor */
128#endif 135#endif
129 /* Erase the "More" message */ 136 /* Erase the last message */
130 printf("\r%*s\r", len, ""); 137 printf("\r%*s\r", len, "");
138
139 /* Due to various multibyte escape
140 * sequences, it's not ok to accept
141 * any input as a command to scroll
142 * the screen. We only allow known
143 * commands, else we show help msg. */
144 if (input == ' ' || input == '\n' || input == 'q' || input == 'r')
145 break;
146 len = printf("(Enter:next line Space:next page Q:quit R:show the rest)");
147 }
131 len = 0; 148 len = 0;
132 lines = 0; 149 lines = 0;
133 /* Bottom line on page will become top line 150 please_display_more_prompt = 0;
134 * after one page forward. Thus -1: */
135 page_height = terminal_height - 1;
136 please_display_more_prompt &= ~1;
137 151
138 if (input == 'q') 152 if (input == 'q')
139 goto end; 153 goto end;
154
155 /* The user may have resized the terminal.
156 * Re-read the dimensions. */
157 get_terminal_width_height(cin_fileno, &terminal_width, &terminal_height);
158 terminal_height -= 1;
140 } 159 }
141 160
161 /* Crudely convert tabs into spaces, which are
162 * a bajillion times easier to deal with. */
163 if (c == '\t') {
164 spaces = CONVERTED_TAB_SIZE - 1;
165 c = ' ';
166 }
167
142 /* 168 /*
143 * There are two input streams to worry about here: 169 * There are two input streams to worry about here:
144 * 170 *
@@ -149,34 +175,24 @@ int more_main(int argc, char **argv)
149 * see if any characters have been hit in the _input_ stream. This 175 * see if any characters have been hit in the _input_ stream. This
150 * allows the user to quit while in the middle of a file. 176 * allows the user to quit while in the middle of a file.
151 */ 177 */
152 if (c == '\n') { 178 wrap = (++len > terminal_width);
153 /* increment by just one line if we are at 179 if (c == '\n' || wrap) {
154 * the end of this line */ 180 /* Then outputting this character
155 if (input == '\n') 181 * will move us to a new line. */
156 please_display_more_prompt |= 1; 182 if (++lines >= terminal_height || input == '\n')
157 /* Adjust the terminal height for any overlap, so that 183 please_display_more_prompt = 1;
158 * no lines get lost off the top. */
159 if (len >= terminal_width) {
160 int quot, rem;
161 quot = len / terminal_width;
162 rem = len - (quot * terminal_width);
163 page_height -= (quot - 1);
164 if (rem)
165 page_height--;
166 }
167 if (++lines >= page_height) {
168 please_display_more_prompt |= 1;
169 }
170 len = 0; 184 len = 0;
171 } 185 }
172 /* 186 if (c != '\n' && wrap) {
173 * If we just read a newline from the file being 'mored' and any 187 /* Then outputting this will also put a character on
174 * key other than a return is hit, scroll by one page 188 * the beginning of that new line. Thus we first want to
175 */ 189 * display the prompt (if any), so we skip the putchar()
176 putc(c, stdout); 190 * and go back to the top of the loop, without reading
177 /* My small mind cannot fathom tabs, backspaces, 191 * a new character. */
178 * and UTF-8 */ 192 goto loop_top;
179 len++; 193 }
194 /* My small mind cannot fathom backspaces and UTF-8 */
195 putchar(c);
180 } 196 }
181 fclose(file); 197 fclose(file);
182 fflush(stdout); 198 fflush(stdout);