diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2011-07-25 15:18:20 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2011-07-25 15:18:20 +0200 |
commit | 4e552a70ec00e4eb9bb0bcde95688ddb3c4fcefe (patch) | |
tree | f39123cd092c53644788dea0636cfe155d4e8cb3 /miscutils/less.c | |
parent | be391e759675b23ccf6e19cb6ea5b819840f3026 (diff) | |
download | busybox-w32-4e552a70ec00e4eb9bb0bcde95688ddb3c4fcefe.tar.gz busybox-w32-4e552a70ec00e4eb9bb0bcde95688ddb3c4fcefe.tar.bz2 busybox-w32-4e552a70ec00e4eb9bb0bcde95688ddb3c4fcefe.zip |
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.c | 132 |
1 files changed, 117 insertions, 15 deletions
diff --git a/miscutils/less.c b/miscutils/less.c index 46024f9f7..16eb95d56 100644 --- a/miscutils/less.c +++ b/miscutils/less.c | |||
@@ -21,6 +21,85 @@ | |||
21 | * redirected input has been read from stdin | 21 | * redirected input has been read from stdin |
22 | */ | 22 | */ |
23 | 23 | ||
24 | //config:config LESS | ||
25 | //config: bool "less" | ||
26 | //config: default y | ||
27 | //config: help | ||
28 | //config: 'less' is a pager, meaning that it displays text files. It possesses | ||
29 | //config: a wide array of features, and is an improvement over 'more'. | ||
30 | //config: | ||
31 | //config:config FEATURE_LESS_MAXLINES | ||
32 | //config: int "Max number of input lines less will try to eat" | ||
33 | //config: default 9999999 | ||
34 | //config: depends on LESS | ||
35 | //config: | ||
36 | //config:config FEATURE_LESS_BRACKETS | ||
37 | //config: bool "Enable bracket searching" | ||
38 | //config: default y | ||
39 | //config: depends on LESS | ||
40 | //config: help | ||
41 | //config: This option adds the capability to search for matching left and right | ||
42 | //config: brackets, facilitating programming. | ||
43 | //config: | ||
44 | //config:config FEATURE_LESS_FLAGS | ||
45 | //config: bool "Enable extra flags" | ||
46 | //config: default y | ||
47 | //config: depends on LESS | ||
48 | //config: help | ||
49 | //config: The extra flags provided do the following: | ||
50 | //config: | ||
51 | //config: The -M flag enables a more sophisticated status line. | ||
52 | //config: The -m flag enables a simpler status line with a percentage. | ||
53 | //config: | ||
54 | //config:config FEATURE_LESS_MARKS | ||
55 | //config: bool "Enable marks" | ||
56 | //config: default y | ||
57 | //config: depends on LESS | ||
58 | //config: help | ||
59 | //config: Marks enable positions in a file to be stored for easy reference. | ||
60 | //config: | ||
61 | //config:config FEATURE_LESS_REGEXP | ||
62 | //config: bool "Enable regular expressions" | ||
63 | //config: default y | ||
64 | //config: depends on LESS | ||
65 | //config: help | ||
66 | //config: Enable regular expressions, allowing complex file searches. | ||
67 | //config: | ||
68 | //config:config FEATURE_LESS_WINCH | ||
69 | //config: bool "Enable automatic resizing on window size changes" | ||
70 | //config: default y | ||
71 | //config: depends on LESS | ||
72 | //config: help | ||
73 | //config: Makes less track window size changes. | ||
74 | //config: | ||
75 | //config:config FEATURE_LESS_ASK_TERMINAL | ||
76 | //config: bool "Use 'tell me cursor position' ESC sequence to measure window" | ||
77 | //config: default y | ||
78 | //config: depends on FEATURE_LESS_WINCH | ||
79 | //config: help | ||
80 | //config: Makes less track window size changes. | ||
81 | //config: If terminal size can't be retrieved and $LINES/$COLUMNS are not set, | ||
82 | //config: this option makes less perform a last-ditch effort to find it: | ||
83 | //config: position cursor to 999,999 and ask terminal to report real | ||
84 | //config: cursor position using "ESC [ 6 n" escape sequence, then read stdin. | ||
85 | //config: | ||
86 | //config: This is not clean but helps a lot on serial lines and such. | ||
87 | //config: | ||
88 | //config:config FEATURE_LESS_DASHCMD | ||
89 | //config: bool "Enable flag changes ('-' command)" | ||
90 | //config: default y | ||
91 | //config: depends on LESS | ||
92 | //config: help | ||
93 | //config: This enables the ability to change command-line flags within | ||
94 | //config: less itself ('-' keyboard command). | ||
95 | //config: | ||
96 | //config:config FEATURE_LESS_LINENUMS | ||
97 | //config: bool "Enable dynamic switching of line numbers" | ||
98 | //config: default y | ||
99 | //config: depends on FEATURE_LESS_DASHCMD | ||
100 | //config: help | ||
101 | //config: Enables "-N" command. | ||
102 | |||
24 | //usage:#define less_trivial_usage | 103 | //usage:#define less_trivial_usage |
25 | //usage: "[-EMNmh~I?] [FILE]..." | 104 | //usage: "[-EMNmh~I?] [FILE]..." |
26 | //usage:#define less_full_usage "\n\n" | 105 | //usage:#define less_full_usage "\n\n" |
@@ -108,6 +187,9 @@ struct globals { | |||
108 | regex_t pattern; | 187 | regex_t pattern; |
109 | smallint pattern_valid; | 188 | smallint pattern_valid; |
110 | #endif | 189 | #endif |
190 | #if ENABLE_FEATURE_LESS_ASK_TERMINAL | ||
191 | smallint winsize_err; | ||
192 | #endif | ||
111 | smallint terminated; | 193 | smallint terminated; |
112 | struct termios term_orig, term_less; | 194 | struct termios term_orig, term_less; |
113 | char kbd_input[KEYCODE_BUFFER_SIZE]; | 195 | char kbd_input[KEYCODE_BUFFER_SIZE]; |
@@ -815,12 +897,17 @@ static void reinitialize(void) | |||
815 | cur_fline = 0; | 897 | cur_fline = 0; |
816 | max_lineno = 0; | 898 | max_lineno = 0; |
817 | open_file_and_read_lines(); | 899 | open_file_and_read_lines(); |
900 | #if ENABLE_FEATURE_LESS_ASK_TERMINAL | ||
901 | if (G.winsize_err) | ||
902 | printf("\033[999;999H" "\033[6n"); | ||
903 | #endif | ||
818 | buffer_fill_and_print(); | 904 | buffer_fill_and_print(); |
819 | } | 905 | } |
820 | 906 | ||
821 | static int getch_nowait(void) | 907 | static int64_t getch_nowait(void) |
822 | { | 908 | { |
823 | int rd; | 909 | int rd; |
910 | int64_t key64; | ||
824 | struct pollfd pfd[2]; | 911 | struct pollfd pfd[2]; |
825 | 912 | ||
826 | pfd[0].fd = STDIN_FILENO; | 913 | pfd[0].fd = STDIN_FILENO; |
@@ -868,8 +955,8 @@ static int getch_nowait(void) | |||
868 | 955 | ||
869 | /* We have kbd_fd in O_NONBLOCK mode, read inside read_key() | 956 | /* We have kbd_fd in O_NONBLOCK mode, read inside read_key() |
870 | * would not block even if there is no input available */ | 957 | * would not block even if there is no input available */ |
871 | rd = read_key(kbd_fd, kbd_input, /*timeout off:*/ -2); | 958 | key64 = read_key(kbd_fd, kbd_input, /*timeout off:*/ -2); |
872 | if (rd == -1) { | 959 | if ((int)key64 == -1) { |
873 | if (errno == EAGAIN) { | 960 | if (errno == EAGAIN) { |
874 | /* No keyboard input available. Since poll() did return, | 961 | /* No keyboard input available. Since poll() did return, |
875 | * we should have input on stdin */ | 962 | * we should have input on stdin */ |
@@ -881,25 +968,29 @@ static int getch_nowait(void) | |||
881 | less_exit(0); | 968 | less_exit(0); |
882 | } | 969 | } |
883 | set_tty_cooked(); | 970 | set_tty_cooked(); |
884 | return rd; | 971 | return key64; |
885 | } | 972 | } |
886 | 973 | ||
887 | /* Grab a character from input without requiring the return key. | 974 | /* Grab a character from input without requiring the return key. |
888 | * May return KEYCODE_xxx values. | 975 | * May return KEYCODE_xxx values. |
889 | * Note that this function works best with raw input. */ | 976 | * Note that this function works best with raw input. */ |
890 | static int less_getch(int pos) | 977 | static int64_t less_getch(int pos) |
891 | { | 978 | { |
892 | int i; | 979 | int64_t key64; |
980 | int key; | ||
893 | 981 | ||
894 | again: | 982 | again: |
895 | less_gets_pos = pos; | 983 | less_gets_pos = pos; |
896 | i = getch_nowait(); | 984 | key = key64 = getch_nowait(); |
897 | less_gets_pos = -1; | 985 | less_gets_pos = -1; |
898 | 986 | ||
899 | /* Discard Ctrl-something chars */ | 987 | /* Discard Ctrl-something chars. |
900 | if (i >= 0 && i < ' ' && i != 0x0d && i != 8) | 988 | * (checking only lower 32 bits is a size optimization: |
989 | * upper 32 bits are used only by KEYCODE_CURSOR_POS) | ||
990 | */ | ||
991 | if (key >= 0 && key < ' ' && key != 0x0d && key != 8) | ||
901 | goto again; | 992 | goto again; |
902 | return i; | 993 | return key; |
903 | } | 994 | } |
904 | 995 | ||
905 | static char* less_gets(int sz) | 996 | static char* less_gets(int sz) |
@@ -1514,8 +1605,6 @@ static void sigwinch_handler(int sig UNUSED_PARAM) | |||
1514 | int less_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 1605 | int less_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
1515 | int less_main(int argc, char **argv) | 1606 | int less_main(int argc, char **argv) |
1516 | { | 1607 | { |
1517 | int keypress; | ||
1518 | |||
1519 | INIT_G(); | 1608 | INIT_G(); |
1520 | 1609 | ||
1521 | /* TODO: -x: do not interpret backspace, -xx: tab also */ | 1610 | /* TODO: -x: do not interpret backspace, -xx: tab also */ |
@@ -1558,7 +1647,7 @@ int less_main(int argc, char **argv) | |||
1558 | term_less.c_cc[VMIN] = 1; | 1647 | term_less.c_cc[VMIN] = 1; |
1559 | term_less.c_cc[VTIME] = 0; | 1648 | term_less.c_cc[VTIME] = 0; |
1560 | 1649 | ||
1561 | get_terminal_width_height(kbd_fd, &width, &max_displayed_line); | 1650 | IF_FEATURE_LESS_ASK_TERMINAL(G.winsize_err =) get_terminal_width_height(kbd_fd, &width, &max_displayed_line); |
1562 | /* 20: two tabstops + 4 */ | 1651 | /* 20: two tabstops + 4 */ |
1563 | if (width < 20 || max_displayed_line < 3) | 1652 | if (width < 20 || max_displayed_line < 3) |
1564 | return bb_cat(argv); | 1653 | return bb_cat(argv); |
@@ -1573,11 +1662,14 @@ int less_main(int argc, char **argv) | |||
1573 | buffer = xmalloc((max_displayed_line+1) * sizeof(char *)); | 1662 | buffer = xmalloc((max_displayed_line+1) * sizeof(char *)); |
1574 | reinitialize(); | 1663 | reinitialize(); |
1575 | while (1) { | 1664 | while (1) { |
1665 | int64_t keypress; | ||
1666 | |||
1576 | #if ENABLE_FEATURE_LESS_WINCH | 1667 | #if ENABLE_FEATURE_LESS_WINCH |
1577 | while (WINCH_COUNTER) { | 1668 | while (WINCH_COUNTER) { |
1578 | again: | 1669 | again: |
1579 | winch_counter--; | 1670 | winch_counter--; |
1580 | get_terminal_width_height(kbd_fd, &width, &max_displayed_line); | 1671 | IF_FEATURE_LESS_ASK_TERMINAL(G.winsize_err =) get_terminal_width_height(kbd_fd, &width, &max_displayed_line); |
1672 | IF_FEATURE_LESS_ASK_TERMINAL(got_size:) | ||
1581 | /* 20: two tabstops + 4 */ | 1673 | /* 20: two tabstops + 4 */ |
1582 | if (width < 20) | 1674 | if (width < 20) |
1583 | width = 20; | 1675 | width = 20; |
@@ -1597,8 +1689,18 @@ int less_main(int argc, char **argv) | |||
1597 | /* This took some time. Loop back and check, | 1689 | /* This took some time. Loop back and check, |
1598 | * were there another SIGWINCH? */ | 1690 | * were there another SIGWINCH? */ |
1599 | } | 1691 | } |
1600 | #endif | ||
1601 | keypress = less_getch(-1); /* -1: do not position cursor */ | 1692 | keypress = less_getch(-1); /* -1: do not position cursor */ |
1693 | # if ENABLE_FEATURE_LESS_ASK_TERMINAL | ||
1694 | if ((int32_t)keypress == KEYCODE_CURSOR_POS) { | ||
1695 | uint32_t rc = (keypress >> 32); | ||
1696 | width = (rc & 0x7fff); | ||
1697 | max_displayed_line = ((rc >> 16) & 0x7fff); | ||
1698 | goto got_size; | ||
1699 | } | ||
1700 | # endif | ||
1701 | #else | ||
1702 | keypress = less_getch(-1); /* -1: do not position cursor */ | ||
1703 | #endif | ||
1602 | keypress_process(keypress); | 1704 | keypress_process(keypress); |
1603 | } | 1705 | } |
1604 | } | 1706 | } |