aboutsummaryrefslogtreecommitdiff
path: root/miscutils/less.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2011-07-25 15:18:20 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2011-07-25 15:18:20 +0200
commit4e552a70ec00e4eb9bb0bcde95688ddb3c4fcefe (patch)
treef39123cd092c53644788dea0636cfe155d4e8cb3 /miscutils/less.c
parentbe391e759675b23ccf6e19cb6ea5b819840f3026 (diff)
downloadbusybox-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.c132
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
821static int getch_nowait(void) 907static 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. */
890static int less_getch(int pos) 977static 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
905static char* less_gets(int sz) 996static char* less_gets(int sz)
@@ -1514,8 +1605,6 @@ static void sigwinch_handler(int sig UNUSED_PARAM)
1514int less_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 1605int less_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1515int less_main(int argc, char **argv) 1606int 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}