diff options
author | Ron Yorston <rmy@pobox.com> | 2023-03-05 12:34:31 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2023-03-05 12:43:46 +0000 |
commit | 8ade494aebe60ea14026d48025a462e6d0b58a7f (patch) | |
tree | 55181219752cf8c2efac037d8f2bd26c71baaca4 | |
parent | 9aef4d4d298987437e33bf25bcddd16175148d45 (diff) | |
download | busybox-w32-8ade494aebe60ea14026d48025a462e6d0b58a7f.tar.gz busybox-w32-8ade494aebe60ea14026d48025a462e6d0b58a7f.tar.bz2 busybox-w32-8ade494aebe60ea14026d48025a462e6d0b58a7f.zip |
win32: add support for virtual terminal input
Alter certain applets to support virtual terminal input, if enabled.
In many places this is achieved by building previously excluded
upstream terminal-handling code. The busybox-w32 implementation
of termios(3) functions does nothing if virtual terminal input is
disabled, so it can be invoked regardless.
Some applet-specific terminal-handling code is also required.
This affects less, more, vi and command line editing in the shell.
(The `more` applet isn't enabled in the default configuration.)
This series of patches adds about 1.7KB to the binaries.
-rw-r--r-- | editors/vi.c | 7 | ||||
-rw-r--r-- | libbb/lineedit.c | 21 | ||||
-rw-r--r-- | miscutils/less.c | 27 | ||||
-rw-r--r-- | util-linux/more.c | 11 |
4 files changed, 34 insertions, 32 deletions
diff --git a/editors/vi.c b/editors/vi.c index 13f0ae8ee..74028e2b4 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -456,9 +456,7 @@ struct globals { | |||
456 | #if ENABLE_FEATURE_VI_USE_SIGNALS | 456 | #if ENABLE_FEATURE_VI_USE_SIGNALS |
457 | sigjmp_buf restart; // int_handler() jumps to location remembered here | 457 | sigjmp_buf restart; // int_handler() jumps to location remembered here |
458 | #endif | 458 | #endif |
459 | #if !ENABLE_PLATFORM_MINGW32 | ||
460 | struct termios term_orig; // remember what the cooked mode was | 459 | struct termios term_orig; // remember what the cooked mode was |
461 | #endif | ||
462 | int cindex; // saved character index for up/down motion | 460 | int cindex; // saved character index for up/down motion |
463 | smallint keep_index; // retain saved character index | 461 | smallint keep_index; // retain saved character index |
464 | #if ENABLE_FEATURE_VI_COLON | 462 | #if ENABLE_FEATURE_VI_COLON |
@@ -700,7 +698,6 @@ static int mysleep(int hund) | |||
700 | } | 698 | } |
701 | 699 | ||
702 | //----- Set terminal attributes -------------------------------- | 700 | //----- Set terminal attributes -------------------------------- |
703 | #if !ENABLE_PLATFORM_MINGW32 | ||
704 | static void rawmode(void) | 701 | static void rawmode(void) |
705 | { | 702 | { |
706 | // no TERMIOS_CLEAR_ISIG: leave ISIG on - allow signals | 703 | // no TERMIOS_CLEAR_ISIG: leave ISIG on - allow signals |
@@ -712,10 +709,6 @@ static void cookmode(void) | |||
712 | fflush_all(); | 709 | fflush_all(); |
713 | tcsetattr_stdin_TCSANOW(&term_orig); | 710 | tcsetattr_stdin_TCSANOW(&term_orig); |
714 | } | 711 | } |
715 | #else | ||
716 | #define rawmode() ((void)0) | ||
717 | #define cookmode fflush_all | ||
718 | #endif | ||
719 | 712 | ||
720 | //----- Terminal Drawing --------------------------------------- | 713 | //----- Terminal Drawing --------------------------------------- |
721 | // The terminal is made up of 'rows' line of 'columns' columns. | 714 | // The terminal is made up of 'rows' line of 'columns' columns. |
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index c4f0c65f1..9bf2f89a5 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -726,7 +726,12 @@ static void input_forward(void) | |||
726 | #if !ENABLE_PLATFORM_MINGW32 | 726 | #if !ENABLE_PLATFORM_MINGW32 |
727 | put_cur_glyph_and_inc_cursor(); | 727 | put_cur_glyph_and_inc_cursor(); |
728 | #else | 728 | #else |
729 | inc_cursor(); | 729 | { |
730 | if (terminal_mode(FALSE) & VT_INPUT) | ||
731 | put_cur_glyph_and_inc_cursor(); | ||
732 | else | ||
733 | inc_cursor(); | ||
734 | } | ||
730 | #endif | 735 | #endif |
731 | } | 736 | } |
732 | 737 | ||
@@ -2579,7 +2584,7 @@ static void sigaction2(int sig, struct sigaction *act) | |||
2579 | */ | 2584 | */ |
2580 | int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize) | 2585 | int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize) |
2581 | { | 2586 | { |
2582 | int len IF_NOT_PLATFORM_MINGW32(, n); | 2587 | int len, n; |
2583 | int timeout; | 2588 | int timeout; |
2584 | #if ENABLE_FEATURE_TAB_COMPLETION | 2589 | #if ENABLE_FEATURE_TAB_COMPLETION |
2585 | smallint lastWasTab = 0; | 2590 | smallint lastWasTab = 0; |
@@ -2589,9 +2594,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
2589 | smallint vi_cmdmode = 0; | 2594 | smallint vi_cmdmode = 0; |
2590 | #endif | 2595 | #endif |
2591 | struct termios initial_settings; | 2596 | struct termios initial_settings; |
2592 | #if !ENABLE_PLATFORM_MINGW32 | ||
2593 | struct termios new_settings; | 2597 | struct termios new_settings; |
2594 | #endif | ||
2595 | char read_key_buffer[KEYCODE_BUFFER_SIZE]; | 2598 | char read_key_buffer[KEYCODE_BUFFER_SIZE]; |
2596 | 2599 | ||
2597 | INIT_S(); | 2600 | INIT_S(); |
@@ -2600,15 +2603,13 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
2600 | cmdedit_termw = 80; | 2603 | cmdedit_termw = 80; |
2601 | IF_FEATURE_EDITING_VI(delptr = delbuf;) | 2604 | IF_FEATURE_EDITING_VI(delptr = delbuf;) |
2602 | 2605 | ||
2603 | #if !ENABLE_PLATFORM_MINGW32 | ||
2604 | n = get_termios_and_make_raw(STDIN_FILENO, &new_settings, &initial_settings, 0 | 2606 | n = get_termios_and_make_raw(STDIN_FILENO, &new_settings, &initial_settings, 0 |
2605 | | TERMIOS_CLEAR_ISIG /* turn off INTR (ctrl-C), QUIT, SUSP */ | 2607 | | TERMIOS_CLEAR_ISIG /* turn off INTR (ctrl-C), QUIT, SUSP */ |
2606 | ); | 2608 | ); |
2609 | #if !ENABLE_PLATFORM_MINGW32 | ||
2607 | if (n != 0 || (initial_settings.c_lflag & (ECHO|ICANON)) == ICANON) { | 2610 | if (n != 0 || (initial_settings.c_lflag & (ECHO|ICANON)) == ICANON) { |
2608 | #else | 2611 | #else |
2609 | initial_settings.c_cc[VINTR] = CTRL('C'); | 2612 | if (n != 0 || !isatty(0) || !isatty(1)) { |
2610 | initial_settings.c_cc[VEOF] = CTRL('D'); | ||
2611 | if (!isatty(0) || !isatty(1)) { | ||
2612 | #endif | 2613 | #endif |
2613 | /* Happens when e.g. stty -echo was run before. | 2614 | /* Happens when e.g. stty -echo was run before. |
2614 | * But if ICANON is not set, we don't come here. | 2615 | * But if ICANON is not set, we don't come here. |
@@ -2661,9 +2662,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
2661 | #endif | 2662 | #endif |
2662 | #define command command_must_not_be_used | 2663 | #define command command_must_not_be_used |
2663 | 2664 | ||
2664 | #if !ENABLE_PLATFORM_MINGW32 | ||
2665 | tcsetattr_stdin_TCSANOW(&new_settings); | 2665 | tcsetattr_stdin_TCSANOW(&new_settings); |
2666 | #endif | ||
2667 | 2666 | ||
2668 | #if 0 | 2667 | #if 0 |
2669 | for (i = 0; i <= state->max_history; i++) | 2668 | for (i = 0; i <= state->max_history; i++) |
@@ -3150,10 +3149,8 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
3150 | free_tab_completion_data(); | 3149 | free_tab_completion_data(); |
3151 | #endif | 3150 | #endif |
3152 | 3151 | ||
3153 | #if !ENABLE_PLATFORM_MINGW32 | ||
3154 | /* restore initial_settings */ | 3152 | /* restore initial_settings */ |
3155 | tcsetattr_stdin_TCSANOW(&initial_settings); | 3153 | tcsetattr_stdin_TCSANOW(&initial_settings); |
3156 | #endif | ||
3157 | #if ENABLE_FEATURE_EDITING_WINCH | 3154 | #if ENABLE_FEATURE_EDITING_WINCH |
3158 | /* restore SIGWINCH handler */ | 3155 | /* restore SIGWINCH handler */ |
3159 | sigaction_set(SIGWINCH, &S.SIGWINCH_handler); | 3156 | sigaction_set(SIGWINCH, &S.SIGWINCH_handler); |
diff --git a/miscutils/less.c b/miscutils/less.c index 842031ca3..467c76e2a 100644 --- a/miscutils/less.c +++ b/miscutils/less.c | |||
@@ -240,9 +240,7 @@ struct globals { | |||
240 | smallint winsize_err; | 240 | smallint winsize_err; |
241 | #endif | 241 | #endif |
242 | smallint terminated; | 242 | smallint terminated; |
243 | #if !ENABLE_PLATFORM_MINGW32 | ||
244 | struct termios term_orig, term_less; | 243 | struct termios term_orig, term_less; |
245 | #endif | ||
246 | char kbd_input[KEYCODE_BUFFER_SIZE]; | 244 | char kbd_input[KEYCODE_BUFFER_SIZE]; |
247 | }; | 245 | }; |
248 | #define G (*ptr_to_globals) | 246 | #define G (*ptr_to_globals) |
@@ -304,9 +302,7 @@ struct globals { | |||
304 | static void set_tty_cooked(void) | 302 | static void set_tty_cooked(void) |
305 | { | 303 | { |
306 | fflush_all(); | 304 | fflush_all(); |
307 | #if !ENABLE_PLATFORM_MINGW32 | ||
308 | tcsetattr(kbd_fd, TCSANOW, &term_orig); | 305 | tcsetattr(kbd_fd, TCSANOW, &term_orig); |
309 | #endif | ||
310 | } | 306 | } |
311 | 307 | ||
312 | /* Move the cursor to a position (x,y), where (0,0) is the | 308 | /* Move the cursor to a position (x,y), where (0,0) is the |
@@ -1132,8 +1128,11 @@ static void reinitialize(void) | |||
1132 | buffer_fill_and_print(); | 1128 | buffer_fill_and_print(); |
1133 | } | 1129 | } |
1134 | 1130 | ||
1135 | #if !ENABLE_PLATFORM_MINGW32 | 1131 | #if ENABLE_PLATFORM_MINGW32 |
1132 | static int64_t unix_getch_nowait(void) | ||
1133 | #else | ||
1136 | static int64_t getch_nowait(void) | 1134 | static int64_t getch_nowait(void) |
1135 | #endif | ||
1137 | { | 1136 | { |
1138 | int rd; | 1137 | int rd; |
1139 | int64_t key64; | 1138 | int64_t key64; |
@@ -1194,11 +1193,15 @@ static int64_t getch_nowait(void) | |||
1194 | set_tty_cooked(); | 1193 | set_tty_cooked(); |
1195 | return key64; | 1194 | return key64; |
1196 | } | 1195 | } |
1197 | #else | 1196 | |
1197 | #if ENABLE_PLATFORM_MINGW32 | ||
1198 | static int64_t getch_nowait(void) | 1198 | static int64_t getch_nowait(void) |
1199 | { | 1199 | { |
1200 | int64_t c; | 1200 | int64_t c; |
1201 | 1201 | ||
1202 | if (terminal_mode(FALSE) & VT_INPUT) | ||
1203 | return unix_getch_nowait(); | ||
1204 | |||
1202 | retry: | 1205 | retry: |
1203 | c = _getch(); | 1206 | c = _getch(); |
1204 | if (c == 0 || c == 0xe0) { | 1207 | if (c == 0 || c == 0xe0) { |
@@ -1894,6 +1897,8 @@ int less_main(int argc, char **argv) | |||
1894 | { | 1897 | { |
1895 | #if !ENABLE_PLATFORM_MINGW32 | 1898 | #if !ENABLE_PLATFORM_MINGW32 |
1896 | char *tty_name; | 1899 | char *tty_name; |
1900 | #else | ||
1901 | HANDLE h; | ||
1897 | #endif | 1902 | #endif |
1898 | int tty_fd; | 1903 | int tty_fd; |
1899 | 1904 | ||
@@ -1980,12 +1985,16 @@ int less_main(int argc, char **argv) | |||
1980 | G.kbd_fd_orig_flags = ndelay_on(tty_fd); | 1985 | G.kbd_fd_orig_flags = ndelay_on(tty_fd); |
1981 | kbd_fd = tty_fd; /* save in a global */ | 1986 | kbd_fd = tty_fd; /* save in a global */ |
1982 | #else | 1987 | #else |
1983 | kbd_fd = tty_fd = 0; | 1988 | h = CreateFileA("CONIN$", GENERIC_READ | GENERIC_WRITE, |
1989 | FILE_SHARE_READ, NULL, OPEN_EXISTING, | ||
1990 | FILE_ATTRIBUTE_NORMAL, NULL); | ||
1991 | if (h == INVALID_HANDLE_VALUE) | ||
1992 | bb_simple_error_msg_and_die("unable to open console"); | ||
1993 | |||
1994 | kbd_fd = tty_fd = _open_osfhandle((intptr_t)h, O_BINARY); | ||
1984 | #endif | 1995 | #endif |
1985 | 1996 | ||
1986 | #if !ENABLE_PLATFORM_MINGW32 | ||
1987 | get_termios_and_make_raw(tty_fd, &term_less, &term_orig, TERMIOS_RAW_CRNL_INPUT); | 1997 | get_termios_and_make_raw(tty_fd, &term_less, &term_orig, TERMIOS_RAW_CRNL_INPUT); |
1988 | #endif | ||
1989 | 1998 | ||
1990 | IF_FEATURE_LESS_ASK_TERMINAL(G.winsize_err =) get_terminal_width_height(tty_fd, &width, &max_displayed_line); | 1999 | IF_FEATURE_LESS_ASK_TERMINAL(G.winsize_err =) get_terminal_width_height(tty_fd, &width, &max_displayed_line); |
1991 | /* 20: two tabstops + 4 */ | 2000 | /* 20: two tabstops + 4 */ |
diff --git a/util-linux/more.c b/util-linux/more.c index 07275131e..84ce37bc7 100644 --- a/util-linux/more.c +++ b/util-linux/more.c | |||
@@ -62,6 +62,7 @@ static void tcsetattr_tty_TCSANOW(struct termios *settings) | |||
62 | tcsetattr(G.tty_fileno, TCSANOW, settings); | 62 | tcsetattr(G.tty_fileno, TCSANOW, settings); |
63 | } | 63 | } |
64 | 64 | ||
65 | #if !ENABLE_PLATFORM_MINGW32 | ||
65 | static void gotsig(int sig UNUSED_PARAM) | 66 | static void gotsig(int sig UNUSED_PARAM) |
66 | { | 67 | { |
67 | /* bb_putchar_stderr doesn't use stdio buffering, | 68 | /* bb_putchar_stderr doesn't use stdio buffering, |
@@ -70,6 +71,7 @@ static void gotsig(int sig UNUSED_PARAM) | |||
70 | tcsetattr_tty_TCSANOW(&G.initial_settings); | 71 | tcsetattr_tty_TCSANOW(&G.initial_settings); |
71 | _exit(EXIT_FAILURE); | 72 | _exit(EXIT_FAILURE); |
72 | } | 73 | } |
74 | #endif | ||
73 | 75 | ||
74 | #define CONVERTED_TAB_SIZE 8 | 76 | #define CONVERTED_TAB_SIZE 8 |
75 | 77 | ||
@@ -159,12 +161,13 @@ int more_main(int argc UNUSED_PARAM, char **argv) | |||
159 | * to get input from the user. | 161 | * to get input from the user. |
160 | */ | 162 | */ |
161 | for (;;) { | 163 | for (;;) { |
162 | #if !ENABLE_PLATFORM_MINGW32 | ||
163 | fflush_all(); | 164 | fflush_all(); |
164 | input = getc(tty); | 165 | #if ENABLE_PLATFORM_MINGW32 |
165 | #else | 166 | if (!(terminal_mode(FALSE) & VT_INPUT)) |
166 | input = _getch(); | 167 | input = _getch(); |
168 | else | ||
167 | #endif | 169 | #endif |
170 | input = getc(tty); | ||
168 | input = tolower(input); | 171 | input = tolower(input); |
169 | /* Erase the last message */ | 172 | /* Erase the last message */ |
170 | printf("\r%*s\r", len, ""); | 173 | printf("\r%*s\r", len, ""); |