From 4e552a70ec00e4eb9bb0bcde95688ddb3c4fcefe Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 25 Jul 2011 15:18:20 +0200 Subject: less: optionally query terminal size via "ESC [ 6 n". Closes bug 2659. +7 bytes is not selected, +100 if selected. Signed-off-by: Denys Vlasenko --- 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); } } -- cgit v1.1