svn commit: trunk/busybox/util-linux

vda at busybox.net vda at busybox.net
Wed Aug 15 20:42:53 UTC 2007


Author: vda
Date: 2007-08-15 13:42:52 -0700 (Wed, 15 Aug 2007)
New Revision: 19519

Log:
more: by Tristan Schmelcher <tpkschme at 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.



Modified:
   trunk/busybox/util-linux/more.c


Changeset:
Modified: trunk/busybox/util-linux/more.c
===================================================================
--- trunk/busybox/util-linux/more.c	2007-08-15 20:07:53 UTC (rev 19518)
+++ trunk/busybox/util-linux/more.c	2007-08-15 20:42:52 UTC (rev 19519)
@@ -29,11 +29,11 @@
 };
 #define G (*(struct globals*)bb_common_bufsiz1)
 //#define G (*ptr_to_globals)
+#define INIT_G() ((void)0)
+//#define INIT_G() PTR_TO_GLOBALS = xzalloc(sizeof(G))
 #define initial_settings (G.initial_settings)
 #define new_settings     (G.new_settings    )
 #define cin_fileno       (G.cin_fileno      )
-#define INIT_G() ((void)0)
-//#define INIT_G() PTR_TO_GLOBALS = xzalloc(sizeof(G))
 
 #define setTermSettings(fd, argp) tcsetattr(fd, TCSANOW, argp)
 #define getTermSettings(fd, argp) tcgetattr(fd, argp)
@@ -50,16 +50,20 @@
 #define setTermSettings(fd, argp) ((void)0)
 #endif /* FEATURE_USE_TERMIOS */
 
+#define CONVERTED_TAB_SIZE 8
 
 int more_main(int argc, char **argv);
 int more_main(int argc, char **argv)
 {
-	int c, lines, input = 0;
-	int please_display_more_prompt = 0;
+	int c = c; /* for gcc */
+	int lines;
+	int input = 0;
+	int spaces = 0;
+	int please_display_more_prompt;
 	struct stat st;
 	FILE *file;
 	FILE *cin;
-	int len, page_height;
+	int len;
 	int terminal_width;
 	int terminal_height;
 
@@ -87,7 +91,6 @@
 	signal(SIGQUIT, gotsig);
 	signal(SIGTERM, gotsig);
 #endif
-	please_display_more_prompt = 2;
 
 	do {
 		file = stdin;
@@ -99,19 +102,21 @@
 		st.st_size = 0;
 		fstat(fileno(file), &st);
 
-		please_display_more_prompt &= ~1;
+		please_display_more_prompt = 0;
 		/* never returns w, h <= 1 */
 		get_terminal_width_height(fileno(cin), &terminal_width, &terminal_height);
-		terminal_width -= 1;
 		terminal_height -= 1;
 
 		len = 0;
 		lines = 0;
-		page_height = terminal_height;
-		while ((c = getc(file)) != EOF) {
-			if ((please_display_more_prompt & 3) == 3) {
+		while (spaces || (c = getc(file)) != EOF) {
+			int wrap;
+			if (spaces)
+				spaces--;
+ loop_top:
+			if (input != 'r' && please_display_more_prompt) {
 				len = printf("--More-- ");
-				if (/*file != stdin &&*/ st.st_size > 0) {
+				if (st.st_size > 0) {
 					len += printf("(%d%% of %"OFF_FMT"d bytes)",
 						(int) (ftello(file)*100 / st.st_size),
 						st.st_size);
@@ -122,23 +127,44 @@
 				 * We've just displayed the "--More--" prompt, so now we need
 				 * to get input from the user.
 				 */
-				input = getc(cin);
+				for (;;) {
+					input = getc(cin);
+					input = tolower(input);
 #if !ENABLE_FEATURE_USE_TERMIOS
-				printf("\033[A"); /* up cursor */
+					printf("\033[A"); /* up cursor */
 #endif
-				/* Erase the "More" message */
-				printf("\r%*s\r", len, "");
+					/* Erase the last message */
+					printf("\r%*s\r", len, "");
+
+					/* Due to various multibyte escape
+					 * sequences, it's not ok to accept
+					 * any input as a command to scroll
+					 * the screen. We only allow known
+					 * commands, else we show help msg. */
+					if (input == ' ' || input == '\n' || input == 'q' || input == 'r')
+						break;
+					len = printf("(Enter:next line Space:next page Q:quit R:show the rest)");
+				}
 				len = 0;
 				lines = 0;
-				/* Bottom line on page will become top line
-				 * after one page forward. Thus -1: */
-				page_height = terminal_height - 1;
-				please_display_more_prompt &= ~1;
+				please_display_more_prompt = 0;
 
 				if (input == 'q')
 					goto end;
+
+				/* The user may have resized the terminal.
+				 * Re-read the dimensions. */
+				get_terminal_width_height(cin_fileno, &terminal_width, &terminal_height);
+				terminal_height -= 1;
 			}
 
+			/* Crudely convert tabs into spaces, which are
+			 * a bajillion times easier to deal with. */
+			if (c == '\t') {
+				spaces = CONVERTED_TAB_SIZE - 1;
+				c = ' ';
+ 			}
+
 			/*
 			 * There are two input streams to worry about here:
 			 *
@@ -149,34 +175,24 @@
 			 * see if any characters have been hit in the _input_ stream. This
 			 * allows the user to quit while in the middle of a file.
 			 */
-			if (c == '\n') {
-				/* increment by just one line if we are at
-				 * the end of this line */
-				if (input == '\n')
-					please_display_more_prompt |= 1;
-				/* Adjust the terminal height for any overlap, so that
-				 * no lines get lost off the top. */
-				if (len >= terminal_width) {
-					int quot, rem;
-					quot = len / terminal_width;
-					rem  = len - (quot * terminal_width);
-					page_height -= (quot - 1);
-					if (rem)
-						page_height--;
-				}
-				if (++lines >= page_height) {
-					please_display_more_prompt |= 1;
-				}
+			wrap = (++len > terminal_width);
+			if (c == '\n' || wrap) {
+				/* Then outputting this character
+				 * will move us to a new line. */
+				if (++lines >= terminal_height || input == '\n')
+					please_display_more_prompt = 1;
 				len = 0;
 			}
-			/*
-			 * If we just read a newline from the file being 'mored' and any
-			 * key other than a return is hit, scroll by one page
-			 */
-			putc(c, stdout);
-			/* My small mind cannot fathom tabs, backspaces,
-			 * and UTF-8 */
-			len++;
+			if (c != '\n' && wrap) {
+				/* Then outputting this will also put a character on
+				 * the beginning of that new line. Thus we first want to
+				 * display the prompt (if any), so we skip the putchar()
+				 * and go back to the top of the loop, without reading
+				 * a new character. */
+				goto loop_top;
+			}
+			/* My small mind cannot fathom backspaces and UTF-8 */
+			putchar(c);
 		}
 		fclose(file);
 		fflush(stdout);




More information about the busybox-cvs mailing list