less: optionally query terminal size via "ESC [ 6 n". Closes bug 2659.
authorDenys Vlasenko <vda.linux@googlemail.com>
Mon, 25 Jul 2011 13:18:20 +0000 (15:18 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Mon, 25 Jul 2011 13:18:20 +0000 (15:18 +0200)
+7 bytes is not selected, +100 if selected.

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
editors/vi.c
libbb/read_key.c
miscutils/Config.src
miscutils/less.c

index 55092f921b64410583d6704a434c17159ee479be..96a0c8df717fd667224697b2ee2e0ad3d676cb03 100644 (file)
 //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:
index 840325c99e99edaa6fc8bf9268269b48f04241f3..5dcd19c3fca41cc6ff18b14b811d8477cff3376a 100644 (file)
@@ -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'
index 61529141dd44eb68cab1c35dfe7b246aa318281e..b9fc196d8d6dee7024aabbbe41b0999455119795 100644 (file)
@@ -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
index 46024f9f77d460095b51cc57f8aeff1e455edb88..16eb95d56d89758cd9ace192be20ab6ece93ba06 100644 (file)
  *   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"
@@ -107,6 +186,9 @@ struct globals {
        int num_matches;
        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;
@@ -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);
        }
 }