aboutsummaryrefslogtreecommitdiff
path: root/win32
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2023-03-05 12:31:30 +0000
committerRon Yorston <rmy@pobox.com>2023-03-05 12:31:30 +0000
commitf52c2004b818ac739ec886d5ff0a87734b55d293 (patch)
treee68d21ec6e1673e458d1e5b3827c08af146cd14a /win32
parent76d3eafb4c28bc6579baff917ffe7726acf6817a (diff)
downloadbusybox-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.c76
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
74int skip_ansi_emulation(int reset) 74int 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
121void set_title(const char *str) 157void 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) {