aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>2010-04-14 02:12:01 +0200
committerNguyễn Thái Ngọc Duy <pclouds@gmail.com>2010-09-10 18:50:04 +1000
commitfa37e9da4b02810eedbb0ac82e8cd0b99336aa82 (patch)
tree47434020dbb9699ea6d51a708d376518dfba6abc
parent909696f1394a67f38f678eb9cfb0d794173095fd (diff)
downloadbusybox-w32-fa37e9da4b02810eedbb0ac82e8cd0b99336aa82.tar.gz
busybox-w32-fa37e9da4b02810eedbb0ac82e8cd0b99336aa82.tar.bz2
busybox-w32-fa37e9da4b02810eedbb0ac82e8cd0b99336aa82.zip
win32: Support certain ANSI sequences on cmd.exe
Support sequences are mostly color ones. This was extracted from commit e56b799d6ad8afba4168fffa7218d44c041a72d2 in Git repository. Changes from original version: > diff --git a/home/pclouds/w/git/compat/winansi.c b/tmp/winansi2.c > index 44dc293..e2e7010 100644 > --- a/home/pclouds/w/git/compat/winansi.c > +++ b/tmp/winansi2.c > @@ -2,8 +2,9 @@ > * Copyright 2008 Peter Harris <git@peter.is-a-geek.org> > */ > > +#include "libbb.h" > #include <windows.h> > -#include "../git-compat-util.h" > +#undef PACKED > > /* > Functions to be wrapped:
-rw-r--r--include/mingw.h11
-rw-r--r--win32/Kbuild1
-rw-r--r--win32/winansi.c358
3 files changed, 370 insertions, 0 deletions
diff --git a/include/mingw.h b/include/mingw.h
index d5a675507..fd9630a58 100644
--- a/include/mingw.h
+++ b/include/mingw.h
@@ -122,6 +122,17 @@ NOIMPL(sigfillset,int *mask UNUSED_PARAM);
122int fdprintf(int fd, const char *format, ...); 122int fdprintf(int fd, const char *format, ...);
123 123
124/* 124/*
125 * ANSI emulation wrappers
126 */
127
128int winansi_fputs(const char *str, FILE *stream);
129int winansi_printf(const char *format, ...) __attribute__((format (printf, 1, 2)));
130int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format (printf, 2, 3)));
131#define fputs winansi_fputs
132#define printf(...) winansi_printf(__VA_ARGS__)
133#define fprintf(...) winansi_fprintf(__VA_ARGS__)
134
135/*
125 * stdlib.h 136 * stdlib.h
126 */ 137 */
127#define WIFEXITED(x) ((unsigned)(x) < 259) /* STILL_ACTIVE */ 138#define WIFEXITED(x) ((unsigned)(x) < 259) /* STILL_ACTIVE */
diff --git a/win32/Kbuild b/win32/Kbuild
index 68a58ca77..dc3b24376 100644
--- a/win32/Kbuild
+++ b/win32/Kbuild
@@ -9,3 +9,4 @@ lib-$(CONFIG_PLATFORM_MINGW32) += fnmatch.o
9lib-$(CONFIG_PLATFORM_MINGW32) += mingw.o 9lib-$(CONFIG_PLATFORM_MINGW32) += mingw.o
10lib-$(CONFIG_PLATFORM_MINGW32) += process.o 10lib-$(CONFIG_PLATFORM_MINGW32) += process.o
11lib-$(CONFIG_PLATFORM_MINGW32) += regex.o 11lib-$(CONFIG_PLATFORM_MINGW32) += regex.o
12lib-$(CONFIG_PLATFORM_MINGW32) += winansi.o
diff --git a/win32/winansi.c b/win32/winansi.c
new file mode 100644
index 000000000..e2e7010fb
--- /dev/null
+++ b/win32/winansi.c
@@ -0,0 +1,358 @@
1/*
2 * Copyright 2008 Peter Harris <git@peter.is-a-geek.org>
3 */
4
5#include "libbb.h"
6#include <windows.h>
7#undef PACKED
8
9/*
10 Functions to be wrapped:
11*/
12#undef printf
13#undef fprintf
14#undef fputs
15/* TODO: write */
16
17/*
18 ANSI codes used by git: m, K
19
20 This file is git-specific. Therefore, this file does not attempt
21 to implement any codes that are not used by git.
22*/
23
24static HANDLE console;
25static WORD plain_attr;
26static WORD attr;
27static int negative;
28
29static void init(void)
30{
31 CONSOLE_SCREEN_BUFFER_INFO sbi;
32
33 static int initialized = 0;
34 if (initialized)
35 return;
36
37 console = GetStdHandle(STD_OUTPUT_HANDLE);
38 if (console == INVALID_HANDLE_VALUE)
39 console = NULL;
40
41 if (!console)
42 return;
43
44 GetConsoleScreenBufferInfo(console, &sbi);
45 attr = plain_attr = sbi.wAttributes;
46 negative = 0;
47
48 initialized = 1;
49}
50
51
52#define FOREGROUND_ALL (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
53#define BACKGROUND_ALL (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
54
55static void set_console_attr(void)
56{
57 WORD attributes = attr;
58 if (negative) {
59 attributes &= ~FOREGROUND_ALL;
60 attributes &= ~BACKGROUND_ALL;
61
62 /* This could probably use a bitmask
63 instead of a series of ifs */
64 if (attr & FOREGROUND_RED)
65 attributes |= BACKGROUND_RED;
66 if (attr & FOREGROUND_GREEN)
67 attributes |= BACKGROUND_GREEN;
68 if (attr & FOREGROUND_BLUE)
69 attributes |= BACKGROUND_BLUE;
70
71 if (attr & BACKGROUND_RED)
72 attributes |= FOREGROUND_RED;
73 if (attr & BACKGROUND_GREEN)
74 attributes |= FOREGROUND_GREEN;
75 if (attr & BACKGROUND_BLUE)
76 attributes |= FOREGROUND_BLUE;
77 }
78 SetConsoleTextAttribute(console, attributes);
79}
80
81static void erase_in_line(void)
82{
83 CONSOLE_SCREEN_BUFFER_INFO sbi;
84
85 if (!console)
86 return;
87
88 GetConsoleScreenBufferInfo(console, &sbi);
89 FillConsoleOutputCharacterA(console, ' ',
90 sbi.dwSize.X - sbi.dwCursorPosition.X, sbi.dwCursorPosition,
91 NULL);
92}
93
94
95static const char *set_attr(const char *str)
96{
97 const char *func;
98 size_t len = strspn(str, "0123456789;");
99 func = str + len;
100
101 switch (*func) {
102 case 'm':
103 do {
104 long val = strtol(str, (char **)&str, 10);
105 switch (val) {
106 case 0: /* reset */
107 attr = plain_attr;
108 negative = 0;
109 break;
110 case 1: /* bold */
111 attr |= FOREGROUND_INTENSITY;
112 break;
113 case 2: /* faint */
114 case 22: /* normal */
115 attr &= ~FOREGROUND_INTENSITY;
116 break;
117 case 3: /* italic */
118 /* Unsupported */
119 break;
120 case 4: /* underline */
121 case 21: /* double underline */
122 /* Wikipedia says this flag does nothing */
123 /* Furthermore, mingw doesn't define this flag
124 attr |= COMMON_LVB_UNDERSCORE; */
125 break;
126 case 24: /* no underline */
127 /* attr &= ~COMMON_LVB_UNDERSCORE; */
128 break;
129 case 5: /* slow blink */
130 case 6: /* fast blink */
131 /* We don't have blink, but we do have
132 background intensity */
133 attr |= BACKGROUND_INTENSITY;
134 break;
135 case 25: /* no blink */
136 attr &= ~BACKGROUND_INTENSITY;
137 break;
138 case 7: /* negative */
139 negative = 1;
140 break;
141 case 27: /* positive */
142 negative = 0;
143 break;
144 case 8: /* conceal */
145 case 28: /* reveal */
146 /* Unsupported */
147 break;
148 case 30: /* Black */
149 attr &= ~FOREGROUND_ALL;
150 break;
151 case 31: /* Red */
152 attr &= ~FOREGROUND_ALL;
153 attr |= FOREGROUND_RED;
154 break;
155 case 32: /* Green */
156 attr &= ~FOREGROUND_ALL;
157 attr |= FOREGROUND_GREEN;
158 break;
159 case 33: /* Yellow */
160 attr &= ~FOREGROUND_ALL;
161 attr |= FOREGROUND_RED | FOREGROUND_GREEN;
162 break;
163 case 34: /* Blue */
164 attr &= ~FOREGROUND_ALL;
165 attr |= FOREGROUND_BLUE;
166 break;
167 case 35: /* Magenta */
168 attr &= ~FOREGROUND_ALL;
169 attr |= FOREGROUND_RED | FOREGROUND_BLUE;
170 break;
171 case 36: /* Cyan */
172 attr &= ~FOREGROUND_ALL;
173 attr |= FOREGROUND_GREEN | FOREGROUND_BLUE;
174 break;
175 case 37: /* White */
176 attr |= FOREGROUND_RED |
177 FOREGROUND_GREEN |
178 FOREGROUND_BLUE;
179 break;
180 case 38: /* Unknown */
181 break;
182 case 39: /* reset */
183 attr &= ~FOREGROUND_ALL;
184 attr |= (plain_attr & FOREGROUND_ALL);
185 break;
186 case 40: /* Black */
187 attr &= ~BACKGROUND_ALL;
188 break;
189 case 41: /* Red */
190 attr &= ~BACKGROUND_ALL;
191 attr |= BACKGROUND_RED;
192 break;
193 case 42: /* Green */
194 attr &= ~BACKGROUND_ALL;
195 attr |= BACKGROUND_GREEN;
196 break;
197 case 43: /* Yellow */
198 attr &= ~BACKGROUND_ALL;
199 attr |= BACKGROUND_RED | BACKGROUND_GREEN;
200 break;
201 case 44: /* Blue */
202 attr &= ~BACKGROUND_ALL;
203 attr |= BACKGROUND_BLUE;
204 break;
205 case 45: /* Magenta */
206 attr &= ~BACKGROUND_ALL;
207 attr |= BACKGROUND_RED | BACKGROUND_BLUE;
208 break;
209 case 46: /* Cyan */
210 attr &= ~BACKGROUND_ALL;
211 attr |= BACKGROUND_GREEN | BACKGROUND_BLUE;
212 break;
213 case 47: /* White */
214 attr |= BACKGROUND_RED |
215 BACKGROUND_GREEN |
216 BACKGROUND_BLUE;
217 break;
218 case 48: /* Unknown */
219 break;
220 case 49: /* reset */
221 attr &= ~BACKGROUND_ALL;
222 attr |= (plain_attr & BACKGROUND_ALL);
223 break;
224 default:
225 /* Unsupported code */
226 break;
227 }
228 str++;
229 } while (*(str-1) == ';');
230
231 set_console_attr();
232 break;
233 case 'K':
234 erase_in_line();
235 break;
236 default:
237 /* Unsupported code */
238 break;
239 }
240
241 return func + 1;
242}
243
244static int ansi_emulate(const char *str, FILE *stream)
245{
246 int rv = 0;
247 const char *pos = str;
248
249 while (*pos) {
250 pos = strstr(str, "\033[");
251 if (pos) {
252 size_t len = pos - str;
253
254 if (len) {
255 size_t out_len = fwrite(str, 1, len, stream);
256 rv += out_len;
257 if (out_len < len)
258 return rv;
259 }
260
261 str = pos + 2;
262 rv += 2;
263
264 fflush(stream);
265
266 pos = set_attr(str);
267 rv += pos - str;
268 str = pos;
269 } else {
270 rv += strlen(str);
271 fputs(str, stream);
272 return rv;
273 }
274 }
275 return rv;
276}
277
278int winansi_fputs(const char *str, FILE *stream)
279{
280 int rv;
281
282 if (!isatty(fileno(stream)))
283 return fputs(str, stream);
284
285 init();
286
287 if (!console)
288 return fputs(str, stream);
289
290 rv = ansi_emulate(str, stream);
291
292 if (rv >= 0)
293 return 0;
294 else
295 return EOF;
296}
297
298static int winansi_vfprintf(FILE *stream, const char *format, va_list list)
299{
300 int len, rv;
301 char small_buf[256];
302 char *buf = small_buf;
303 va_list cp;
304
305 if (!isatty(fileno(stream)))
306 goto abort;
307
308 init();
309
310 if (!console)
311 goto abort;
312
313 va_copy(cp, list);
314 len = vsnprintf(small_buf, sizeof(small_buf), format, cp);
315 va_end(cp);
316
317 if (len > sizeof(small_buf) - 1) {
318 buf = malloc(len + 1);
319 if (!buf)
320 goto abort;
321
322 len = vsnprintf(buf, len + 1, format, list);
323 }
324
325 rv = ansi_emulate(buf, stream);
326
327 if (buf != small_buf)
328 free(buf);
329 return rv;
330
331abort:
332 rv = vfprintf(stream, format, list);
333 return rv;
334}
335
336int winansi_fprintf(FILE *stream, const char *format, ...)
337{
338 va_list list;
339 int rv;
340
341 va_start(list, format);
342 rv = winansi_vfprintf(stream, format, list);
343 va_end(list);
344
345 return rv;
346}
347
348int winansi_printf(const char *format, ...)
349{
350 va_list list;
351 int rv;
352
353 va_start(list, format);
354 rv = winansi_vfprintf(stdout, format, list);
355 va_end(list);
356
357 return rv;
358}