diff options
author | Ron Yorston <rmy@pobox.com> | 2023-03-05 12:31:30 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2023-03-05 12:31:30 +0000 |
commit | f52c2004b818ac739ec886d5ff0a87734b55d293 (patch) | |
tree | e68d21ec6e1673e458d1e5b3827c08af146cd14a /win32 | |
parent | 76d3eafb4c28bc6579baff917ffe7726acf6817a (diff) | |
download | busybox-w32-f52c2004b818ac739ec886d5ff0a87734b55d293.tar.gz busybox-w32-f52c2004b818ac739ec886d5ff0a87734b55d293.tar.bz2 busybox-w32-f52c2004b818ac739ec886d5ff0a87734b55d293.zip |
win32: changes to console mode handling
Add the environment variable BB_TERMINAL_MODE as a more general way
of controlling console/terminal mode setting. The default remains
unchanged: use virtual terminal mode for output if possible but
fall back to the console API with emulated ANSI escape sequences.
Currently valid settings are:
0 Force use of console mode
1 Force use of virtual terminal mode for output
5 Prefer virtual terminal mode for output, fall back to console
Other values won't do anything useful until code elsewhere has been
updated.
BB_SKIP_ANSI_EMULATION remains available for backwards compatibility.
If both variables are set BB_TERMINAL_MODE takes precedence.
Diffstat (limited to 'win32')
-rw-r--r-- | win32/winansi.c | 76 |
1 files changed, 56 insertions, 20 deletions
diff --git a/win32/winansi.c b/win32/winansi.c index ef566684e..11a9327e1 100644 --- a/win32/winansi.c +++ b/win32/winansi.c | |||
@@ -71,22 +71,38 @@ static int is_wine(void) | |||
71 | #define DISABLE_NEWLINE_AUTO_RETURN 0x0008 | 71 | #define DISABLE_NEWLINE_AUTO_RETURN 0x0008 |
72 | #endif | 72 | #endif |
73 | 73 | ||
74 | int skip_ansi_emulation(int reset) | 74 | int terminal_mode(int reset) |
75 | { | 75 | { |
76 | static int skip = -1; | 76 | static int mode = -1; |
77 | 77 | ||
78 | if (skip < 0 || reset) { | 78 | if (mode < 0 || reset) { |
79 | int prefer; | ||
79 | HANDLE h; | 80 | HANDLE h; |
80 | DWORD oldmode, newmode; | 81 | DWORD oldmode, newmode; |
81 | const char *var = getenv(BB_SKIP_ANSI_EMULATION); | 82 | const char *term = getenv(BB_TERMINAL_MODE); |
83 | const char *skip = getenv(BB_SKIP_ANSI_EMULATION); | ||
84 | |||
85 | if (term) { | ||
86 | mode = atoi(term); | ||
87 | } else if (skip) { | ||
88 | mode = atoi(skip); | ||
89 | if (mode == 2) | ||
90 | mode = 5; | ||
91 | else if (mode != 1) | ||
92 | mode = 0; | ||
93 | } else { | ||
94 | mode = (getenv("CONEMUPID") != NULL || is_wine()) ? 0 : | ||
95 | CONFIG_TERMINAL_MODE; | ||
96 | } | ||
82 | 97 | ||
83 | if (var) { | 98 | if (mode < 0 || mode > 7) { |
84 | skip = atoi(var); | 99 | prefer = mode = 0; |
85 | if (skip < 0 || skip > 2) | 100 | } else if (mode > 3) { |
86 | skip = 0; | 101 | // Try to get requested mode, fall back to console on failure. |
102 | prefer = mode = mode - 4; | ||
87 | } else { | 103 | } else { |
88 | skip = (getenv("CONEMUPID") != NULL || is_wine()) ? 0 : | 104 | // Force the requested mode, even if we can't get it. |
89 | CONFIG_SKIP_ANSI_EMULATION_DEFAULT; | 105 | prefer = 0; |
90 | } | 106 | } |
91 | 107 | ||
92 | if (is_console(STDOUT_FILENO)) { | 108 | if (is_console(STDOUT_FILENO)) { |
@@ -94,28 +110,48 @@ int skip_ansi_emulation(int reset) | |||
94 | if (GetConsoleMode(h, &oldmode)) { | 110 | if (GetConsoleMode(h, &oldmode)) { |
95 | // Try to recover from mode 0 induced by SSH. | 111 | // Try to recover from mode 0 induced by SSH. |
96 | newmode = oldmode == 0 ? 3 : oldmode; | 112 | newmode = oldmode == 0 ? 3 : oldmode; |
97 | if (skip) | 113 | if ((mode & VT_OUTPUT)) |
98 | newmode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; | 114 | newmode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; |
99 | else | 115 | else |
100 | newmode &= ~ENABLE_VIRTUAL_TERMINAL_PROCESSING; | 116 | newmode &= ~ENABLE_VIRTUAL_TERMINAL_PROCESSING; |
101 | newmode &= ~DISABLE_NEWLINE_AUTO_RETURN; | 117 | newmode &= ~DISABLE_NEWLINE_AUTO_RETURN; |
118 | |||
102 | if (newmode != oldmode) { | 119 | if (newmode != oldmode) { |
103 | if (!SetConsoleMode(h, newmode) && skip == 2) | 120 | if (!SetConsoleMode(h, newmode)) { |
104 | skip = 0; | 121 | if ((prefer & VT_OUTPUT)) |
122 | mode &= ~VT_OUTPUT; | ||
123 | newmode &= ~ENABLE_VIRTUAL_TERMINAL_PROCESSING; | ||
124 | SetConsoleMode(h, newmode); | ||
125 | } | ||
105 | } | 126 | } |
106 | } | 127 | } |
107 | } | 128 | } |
108 | 129 | ||
109 | // Try to recover from mode 0 induced by SSH. | 130 | if (is_console_in(STDIN_FILENO)) { |
110 | if (reset && is_console_in(STDIN_FILENO)) { | ||
111 | h = GetStdHandle(STD_INPUT_HANDLE); | 131 | h = GetStdHandle(STD_INPUT_HANDLE); |
112 | if (GetConsoleMode(h, &oldmode) && oldmode == 0) { | 132 | if (GetConsoleMode(h, &oldmode)) { |
113 | SetConsoleMode(h, 0x1f7); | 133 | // Try to recover from mode 0 induced by SSH. |
134 | newmode = oldmode == 0 ? 0x1f7 : oldmode; | ||
135 | if ((mode & VT_INPUT)) | ||
136 | newmode |= ENABLE_VIRTUAL_TERMINAL_INPUT; | ||
137 | else | ||
138 | newmode &= ~ENABLE_VIRTUAL_TERMINAL_INPUT; | ||
139 | |||
140 | if (newmode != oldmode) { | ||
141 | if (!SetConsoleMode(h, newmode)) { | ||
142 | if ((prefer & VT_INPUT)) | ||
143 | mode &= ~VT_INPUT; | ||
144 | // Failure to set the new mode seems to leave | ||
145 | // the flag set. Forcibly unset it. | ||
146 | newmode &= ~ENABLE_VIRTUAL_TERMINAL_INPUT; | ||
147 | SetConsoleMode(h, newmode); | ||
148 | } | ||
149 | } | ||
114 | } | 150 | } |
115 | } | 151 | } |
116 | } | 152 | } |
117 | 153 | ||
118 | return skip; | 154 | return mode; |
119 | } | 155 | } |
120 | 156 | ||
121 | void set_title(const char *str) | 157 | void set_title(const char *str) |
@@ -768,7 +804,7 @@ static int ansi_emulate(const char *s, FILE *stream) | |||
768 | 804 | ||
769 | while (*pos) { | 805 | while (*pos) { |
770 | pos = strchr(str, '\033'); | 806 | pos = strchr(str, '\033'); |
771 | if (pos && !skip_ansi_emulation(FALSE)) { | 807 | if (pos && !(terminal_mode(FALSE) & VT_OUTPUT)) { |
772 | size_t len = pos - str; | 808 | size_t len = pos - str; |
773 | 809 | ||
774 | if (len) { | 810 | if (len) { |
@@ -1037,7 +1073,7 @@ static int ansi_emulate_write(int fd, const void *buf, size_t count) | |||
1037 | /* we've checked the data doesn't contain any NULs */ | 1073 | /* we've checked the data doesn't contain any NULs */ |
1038 | while (*pos) { | 1074 | while (*pos) { |
1039 | pos = strchr(str, '\033'); | 1075 | pos = strchr(str, '\033'); |
1040 | if (pos && !skip_ansi_emulation(FALSE)) { | 1076 | if (pos && !(terminal_mode(FALSE) & VT_OUTPUT)) { |
1041 | len = pos - str; | 1077 | len = pos - str; |
1042 | 1078 | ||
1043 | if (len) { | 1079 | if (len) { |