[git commit] less: optionally query terminal size via "ESC [ 6 n". Closes bug 2659.

Denys Vlasenko vda.linux at googlemail.com
Mon Jul 25 13:18:20 UTC 2011


commit: http://git.busybox.net/busybox/commit/?id=4e552a70ec00e4eb9bb0bcde95688ddb3c4fcefe
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

+7 bytes is not selected, +100 if selected.

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 editors/vi.c         |    4 +-
 libbb/read_key.c     |    5 ++-
 miscutils/Config.src |   66 -------------------------
 miscutils/less.c     |  132 ++++++++++++++++++++++++++++++++++++++++++++------
 4 files changed, 123 insertions(+), 84 deletions(-)

diff --git a/editors/vi.c b/editors/vi.c
index 55092f9..96a0c8d 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -132,8 +132,8 @@
 //config:	help
 //config:	  If terminal size can't be retrieved and $LINES/$COLUMNS are not set,
 //config:	  this option makes vi perform a last-ditch effort to find it:
-//config:	  vi positions cursor to 999,999 and asks terminal to report real
-//config:	  cursor position using "ESC [ 6 n" escape sequence, then reads stdin.
+//config:	  position cursor to 999,999 and ask terminal to report real
+//config:	  cursor position using "ESC [ 6 n" escape sequence, then read stdin.
 //config:
 //config:	  This is not clean but helps a lot on serial lines and such.
 //config:
diff --git a/libbb/read_key.c b/libbb/read_key.c
index 840325c..5dcd19c 100644
--- a/libbb/read_key.c
+++ b/libbb/read_key.c
@@ -214,7 +214,10 @@ int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout)
 		}
 		n++;
 		/* Try to decipher "ESC [ NNN ; NNN R" sequence */
-		if ((ENABLE_FEATURE_EDITING_ASK_TERMINAL || ENABLE_FEATURE_VI_ASK_TERMINAL)
+		if ((ENABLE_FEATURE_EDITING_ASK_TERMINAL
+		    || ENABLE_FEATURE_VI_ASK_TERMINAL
+		    || ENABLE_FEATURE_LESS_ASK_TERMINAL
+		    )
 		 && n >= 5
 		 && buffer[0] == '['
 		 && buffer[n-1] == 'R'
diff --git a/miscutils/Config.src b/miscutils/Config.src
index 6152914..b9fc196 100644
--- a/miscutils/Config.src
+++ b/miscutils/Config.src
@@ -360,72 +360,6 @@ config FEATURE_LAST_FANCY
 	  logged into the system (mimics sysvinit last). +900 bytes.
 endchoice
 
-config LESS
-	bool "less"
-	default y
-	help
-	  'less' is a pager, meaning that it displays text files. It possesses
-	  a wide array of features, and is an improvement over 'more'.
-
-config FEATURE_LESS_MAXLINES
-	int "Max number of input lines less will try to eat"
-	default 9999999
-	depends on LESS
-
-config FEATURE_LESS_BRACKETS
-	bool "Enable bracket searching"
-	default y
-	depends on LESS
-	help
-	  This option adds the capability to search for matching left and right
-	  brackets, facilitating programming.
-
-config FEATURE_LESS_FLAGS
-	bool "Enable extra flags"
-	default y
-	depends on LESS
-	help
-	  The extra flags provided do the following:
-
-	  The -M flag enables a more sophisticated status line.
-	  The -m flag enables a simpler status line with a percentage.
-
-config FEATURE_LESS_MARKS
-	bool "Enable marks"
-	default y
-	depends on LESS
-	help
-	  Marks enable positions in a file to be stored for easy reference.
-
-config FEATURE_LESS_REGEXP
-	bool "Enable regular expressions"
-	default y
-	depends on LESS
-	help
-	  Enable regular expressions, allowing complex file searches.
-
-config FEATURE_LESS_WINCH
-	bool "Enable automatic resizing on window size changes"
-	default y
-	depends on LESS
-	help
-	  Makes less track window size changes.
-
-config FEATURE_LESS_DASHCMD
-	bool "Enable flag changes ('-' command)"
-	default y
-	depends on LESS
-	help
-	  This enables the ability to change command-line flags within
-	  less itself ('-' keyboard command).
-
-config FEATURE_LESS_LINENUMS
-	bool "Enable dynamic switching of line numbers"
-	default y
-	depends on FEATURE_LESS_DASHCMD
-	help
-	  Enables "-N" command.
-
 config HDPARM
 	bool "hdparm"
 	default y
diff --git a/miscutils/less.c b/miscutils/less.c
index 46024f9..16eb95d 100644
--- a/miscutils/less.c
+++ b/miscutils/less.c
@@ -21,6 +21,85 @@
  *   redirected input has been read from stdin
  */
 
+//config:config LESS
+//config:	bool "less"
+//config:	default y
+//config:	help
+//config:	  'less' is a pager, meaning that it displays text files. It possesses
+//config:	  a wide array of features, and is an improvement over 'more'.
+//config:
+//config:config FEATURE_LESS_MAXLINES
+//config:	int "Max number of input lines less will try to eat"
+//config:	default 9999999
+//config:	depends on LESS
+//config:
+//config:config FEATURE_LESS_BRACKETS
+//config:	bool "Enable bracket searching"
+//config:	default y
+//config:	depends on LESS
+//config:	help
+//config:	  This option adds the capability to search for matching left and right
+//config:	  brackets, facilitating programming.
+//config:
+//config:config FEATURE_LESS_FLAGS
+//config:	bool "Enable extra flags"
+//config:	default y
+//config:	depends on LESS
+//config:	help
+//config:	  The extra flags provided do the following:
+//config:
+//config:	  The -M flag enables a more sophisticated status line.
+//config:	  The -m flag enables a simpler status line with a percentage.
+//config:
+//config:config FEATURE_LESS_MARKS
+//config:	bool "Enable marks"
+//config:	default y
+//config:	depends on LESS
+//config:	help
+//config:	  Marks enable positions in a file to be stored for easy reference.
+//config:
+//config:config FEATURE_LESS_REGEXP
+//config:	bool "Enable regular expressions"
+//config:	default y
+//config:	depends on LESS
+//config:	help
+//config:	  Enable regular expressions, allowing complex file searches.
+//config:
+//config:config FEATURE_LESS_WINCH
+//config:	bool "Enable automatic resizing on window size changes"
+//config:	default y
+//config:	depends on LESS
+//config:	help
+//config:	  Makes less track window size changes.
+//config:
+//config:config FEATURE_LESS_ASK_TERMINAL
+//config:	bool "Use 'tell me cursor position' ESC sequence to measure window"
+//config:	default y
+//config:	depends on FEATURE_LESS_WINCH
+//config:	help
+//config:	  Makes less track window size changes.
+//config:	  If terminal size can't be retrieved and $LINES/$COLUMNS are not set,
+//config:	  this option makes less perform a last-ditch effort to find it:
+//config:	  position cursor to 999,999 and ask terminal to report real
+//config:	  cursor position using "ESC [ 6 n" escape sequence, then read stdin.
+//config:
+//config:	  This is not clean but helps a lot on serial lines and such.
+//config:
+//config:config FEATURE_LESS_DASHCMD
+//config:	bool "Enable flag changes ('-' command)"
+//config:	default y
+//config:	depends on LESS
+//config:	help
+//config:	  This enables the ability to change command-line flags within
+//config:	  less itself ('-' keyboard command).
+//config:
+//config:config FEATURE_LESS_LINENUMS
+//config:	bool "Enable dynamic switching of line numbers"
+//config:	default y
+//config:	depends on FEATURE_LESS_DASHCMD
+//config:	help
+//config:	  Enables "-N" command.
+
 //usage:#define less_trivial_usage
 //usage:       "[-EMNmh~I?] [FILE]..."
 //usage:#define less_full_usage "\n\n"
@@ -108,6 +187,9 @@ struct globals {
 	regex_t pattern;
 	smallint pattern_valid;
 #endif
+#if ENABLE_FEATURE_LESS_ASK_TERMINAL
+	smallint winsize_err;
+#endif
 	smallint terminated;
 	struct termios term_orig, term_less;
 	char kbd_input[KEYCODE_BUFFER_SIZE];
@@ -815,12 +897,17 @@ static void reinitialize(void)
 	cur_fline = 0;
 	max_lineno = 0;
 	open_file_and_read_lines();
+#if ENABLE_FEATURE_LESS_ASK_TERMINAL
+	if (G.winsize_err)
+		printf("\033[999;999H" "\033[6n");
+#endif
 	buffer_fill_and_print();
 }
 
-static int getch_nowait(void)
+static int64_t getch_nowait(void)
 {
 	int rd;
+	int64_t key64;
 	struct pollfd pfd[2];
 
 	pfd[0].fd = STDIN_FILENO;
@@ -868,8 +955,8 @@ static int getch_nowait(void)
 
 	/* We have kbd_fd in O_NONBLOCK mode, read inside read_key()
 	 * would not block even if there is no input available */
-	rd = read_key(kbd_fd, kbd_input, /*timeout off:*/ -2);
-	if (rd == -1) {
+	key64 = read_key(kbd_fd, kbd_input, /*timeout off:*/ -2);
+	if ((int)key64 == -1) {
 		if (errno == EAGAIN) {
 			/* No keyboard input available. Since poll() did return,
 			 * we should have input on stdin */
@@ -881,25 +968,29 @@ static int getch_nowait(void)
 		less_exit(0);
 	}
 	set_tty_cooked();
-	return rd;
+	return key64;
 }
 
 /* Grab a character from input without requiring the return key.
  * May return KEYCODE_xxx values.
  * Note that this function works best with raw input. */
-static int less_getch(int pos)
+static int64_t less_getch(int pos)
 {
-	int i;
+	int64_t key64;
+	int key;
 
  again:
 	less_gets_pos = pos;
-	i = getch_nowait();
+	key = key64 = getch_nowait();
 	less_gets_pos = -1;
 
-	/* Discard Ctrl-something chars */
-	if (i >= 0 && i < ' ' && i != 0x0d && i != 8)
+	/* Discard Ctrl-something chars.
+	 * (checking only lower 32 bits is a size optimization:
+	 * upper 32 bits are used only by KEYCODE_CURSOR_POS)
+	 */
+	if (key >= 0 && key < ' ' && key != 0x0d && key != 8)
 		goto again;
-	return i;
+	return key;
 }
 
 static char* less_gets(int sz)
@@ -1514,8 +1605,6 @@ static void sigwinch_handler(int sig UNUSED_PARAM)
 int less_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int less_main(int argc, char **argv)
 {
-	int keypress;
-
 	INIT_G();
 
 	/* TODO: -x: do not interpret backspace, -xx: tab also */
@@ -1558,7 +1647,7 @@ int less_main(int argc, char **argv)
 	term_less.c_cc[VMIN] = 1;
 	term_less.c_cc[VTIME] = 0;
 
-	get_terminal_width_height(kbd_fd, &width, &max_displayed_line);
+	IF_FEATURE_LESS_ASK_TERMINAL(G.winsize_err =) get_terminal_width_height(kbd_fd, &width, &max_displayed_line);
 	/* 20: two tabstops + 4 */
 	if (width < 20 || max_displayed_line < 3)
 		return bb_cat(argv);
@@ -1573,11 +1662,14 @@ int less_main(int argc, char **argv)
 	buffer = xmalloc((max_displayed_line+1) * sizeof(char *));
 	reinitialize();
 	while (1) {
+		int64_t keypress;
+
 #if ENABLE_FEATURE_LESS_WINCH
 		while (WINCH_COUNTER) {
  again:
 			winch_counter--;
-			get_terminal_width_height(kbd_fd, &width, &max_displayed_line);
+			IF_FEATURE_LESS_ASK_TERMINAL(G.winsize_err =) get_terminal_width_height(kbd_fd, &width, &max_displayed_line);
+ IF_FEATURE_LESS_ASK_TERMINAL(got_size:)
 			/* 20: two tabstops + 4 */
 			if (width < 20)
 				width = 20;
@@ -1597,8 +1689,18 @@ int less_main(int argc, char **argv)
 			/* This took some time. Loop back and check,
 			 * were there another SIGWINCH? */
 		}
-#endif
 		keypress = less_getch(-1); /* -1: do not position cursor */
+# if ENABLE_FEATURE_LESS_ASK_TERMINAL
+		if ((int32_t)keypress == KEYCODE_CURSOR_POS) {
+			uint32_t rc = (keypress >> 32);
+			width = (rc & 0x7fff);
+			max_displayed_line = ((rc >> 16) & 0x7fff);
+			goto got_size;
+		}
+# endif
+#else
+		keypress = less_getch(-1); /* -1: do not position cursor */
+#endif
 		keypress_process(keypress);
 	}
 }
-- 
1.7.3.4



More information about the busybox-cvs mailing list