summaryrefslogtreecommitdiff
path: root/miscutils/less.c
diff options
context:
space:
mode:
authorDenys Vlasenko2011-07-25 15:18:20 +0200
committerDenys Vlasenko2011-07-25 15:18:20 +0200
commit4e552a70ec00e4eb9bb0bcde95688ddb3c4fcefe (patch)
treef39123cd092c53644788dea0636cfe155d4e8cb3 /miscutils/less.c
parentbe391e759675b23ccf6e19cb6ea5b819840f3026 (diff)
downloadbusybox-4e552a70ec00e4eb9bb0bcde95688ddb3c4fcefe.zip
busybox-4e552a70ec00e4eb9bb0bcde95688ddb3c4fcefe.tar.gz
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 <vda.linux@googlemail.com>
Diffstat (limited to 'miscutils/less.c')
-rw-r--r--miscutils/less.c132
1 files changed, 117 insertions, 15 deletions
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);
}
}