2 * Copyright 2008 Peter Harris <git@peter.is-a-geek.org>
6 #include "../git-compat-util.h"
9 Functions to be wrapped:
17 ANSI codes used by git: m, K
19 This file is git-specific. Therefore, this file does not attempt
20 to implement any codes that are not used by git.
23 static HANDLE console
;
24 static WORD plain_attr
;
28 static void init(void)
30 CONSOLE_SCREEN_BUFFER_INFO sbi
;
32 static int initialized
= 0;
36 console
= GetStdHandle(STD_OUTPUT_HANDLE
);
37 if (console
== INVALID_HANDLE_VALUE
)
43 GetConsoleScreenBufferInfo(console
, &sbi
);
44 attr
= plain_attr
= sbi
.wAttributes
;
51 #define FOREGROUND_ALL (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
52 #define BACKGROUND_ALL (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
54 static void set_console_attr(void)
56 WORD attributes
= attr
;
58 attributes
&= ~FOREGROUND_ALL
;
59 attributes
&= ~BACKGROUND_ALL
;
61 /* This could probably use a bitmask
62 instead of a series of ifs */
63 if (attr
& FOREGROUND_RED
)
64 attributes
|= BACKGROUND_RED
;
65 if (attr
& FOREGROUND_GREEN
)
66 attributes
|= BACKGROUND_GREEN
;
67 if (attr
& FOREGROUND_BLUE
)
68 attributes
|= BACKGROUND_BLUE
;
70 if (attr
& BACKGROUND_RED
)
71 attributes
|= FOREGROUND_RED
;
72 if (attr
& BACKGROUND_GREEN
)
73 attributes
|= FOREGROUND_GREEN
;
74 if (attr
& BACKGROUND_BLUE
)
75 attributes
|= FOREGROUND_BLUE
;
77 SetConsoleTextAttribute(console
, attributes
);
80 static const char *set_attr(const char *str
)
83 size_t len
= strspn(str
, "0123456789;");
89 long val
= strtol(str
, (char **)&str
, 10);
96 attr
|= FOREGROUND_INTENSITY
;
100 attr
&= ~FOREGROUND_INTENSITY
;
105 case 4: /* underline */
106 case 21: /* double underline */
107 /* Wikipedia says this flag does nothing */
108 /* Furthermore, mingw doesn't define this flag
109 attr |= COMMON_LVB_UNDERSCORE; */
111 case 24: /* no underline */
112 /* attr &= ~COMMON_LVB_UNDERSCORE; */
114 case 5: /* slow blink */
115 case 6: /* fast blink */
116 /* We don't have blink, but we do have
117 background intensity */
118 attr
|= BACKGROUND_INTENSITY
;
120 case 25: /* no blink */
121 attr
&= ~BACKGROUND_INTENSITY
;
123 case 7: /* negative */
126 case 27: /* positive */
129 case 8: /* conceal */
130 case 28: /* reveal */
134 attr
&= ~FOREGROUND_ALL
;
137 attr
&= ~FOREGROUND_ALL
;
138 attr
|= FOREGROUND_RED
;
141 attr
&= ~FOREGROUND_ALL
;
142 attr
|= FOREGROUND_GREEN
;
144 case 33: /* Yellow */
145 attr
&= ~FOREGROUND_ALL
;
146 attr
|= FOREGROUND_RED
| FOREGROUND_GREEN
;
149 attr
&= ~FOREGROUND_ALL
;
150 attr
|= FOREGROUND_BLUE
;
152 case 35: /* Magenta */
153 attr
&= ~FOREGROUND_ALL
;
154 attr
|= FOREGROUND_RED
| FOREGROUND_BLUE
;
157 attr
&= ~FOREGROUND_ALL
;
158 attr
|= FOREGROUND_GREEN
| FOREGROUND_BLUE
;
161 attr
|= FOREGROUND_RED
|
165 case 38: /* Unknown */
168 attr
&= ~FOREGROUND_ALL
;
169 attr
|= (plain_attr
& FOREGROUND_ALL
);
172 attr
&= ~BACKGROUND_ALL
;
175 attr
&= ~BACKGROUND_ALL
;
176 attr
|= BACKGROUND_RED
;
179 attr
&= ~BACKGROUND_ALL
;
180 attr
|= BACKGROUND_GREEN
;
182 case 43: /* Yellow */
183 attr
&= ~BACKGROUND_ALL
;
184 attr
|= BACKGROUND_RED
| BACKGROUND_GREEN
;
187 attr
&= ~BACKGROUND_ALL
;
188 attr
|= BACKGROUND_BLUE
;
190 case 45: /* Magenta */
191 attr
&= ~BACKGROUND_ALL
;
192 attr
|= BACKGROUND_RED
| BACKGROUND_BLUE
;
195 attr
&= ~BACKGROUND_ALL
;
196 attr
|= BACKGROUND_GREEN
| BACKGROUND_BLUE
;
199 attr
|= BACKGROUND_RED
|
203 case 48: /* Unknown */
206 attr
&= ~BACKGROUND_ALL
;
207 attr
|= (plain_attr
& BACKGROUND_ALL
);
210 /* Unsupported code */
214 } while (*(str
-1) == ';');
220 CONSOLE_SCREEN_BUFFER_INFO csbi
;
223 long val
= strtol(str
, (char **)&str
, 10);
225 if (!GetConsoleScreenBufferInfo(console
, &csbi
))
230 /* Clear to end of line */
231 pos
= csbi
.dwCursorPosition
;
232 len
= csbi
.dwSize
.X
- pos
.X
;
235 /* Clear to start of line */
237 pos
.Y
= csbi
.dwCursorPosition
.Y
;
238 len
= csbi
.dwCursorPosition
.X
- 1;
241 /* Clear entire line */
243 pos
.Y
= csbi
.dwCursorPosition
.Y
;
247 /* Unsupported code */
253 FillConsoleOutputCharacter(console
, ' ', len
, pos
, &len
);
254 FillConsoleOutputAttribute(console
, attr
, len
, pos
, &len
);
260 /* Unsupported code */
267 static int ansi_emulate(const char *str
, FILE *stream
)
270 const char *pos
= str
;
273 pos
= strstr(str
, "\033[");
275 size_t len
= pos
- str
;
278 size_t out_len
= fwrite(str
, 1, len
, stream
);
301 int winansi_fputs(const char *str
, FILE *stream
)
305 if (!isatty(fileno(stream
)))
306 return fputs(str
, stream
);
311 return fputs(str
, stream
);
313 rv
= ansi_emulate(str
, stream
);
321 static int winansi_vfprintf(FILE *stream
, const char *format
, va_list list
)
325 char *buf
= small_buf
;
328 if (!isatty(fileno(stream
)))
337 len
= vsnprintf(small_buf
, sizeof(small_buf
), format
, cp
);
340 if (len
> sizeof(small_buf
) - 1) {
341 buf
= malloc(len
+ 1);
345 len
= vsnprintf(buf
, len
+ 1, format
, list
);
348 rv
= ansi_emulate(buf
, stream
);
350 if (buf
!= small_buf
)
355 rv
= vfprintf(stream
, format
, list
);
359 int winansi_fprintf(FILE *stream
, const char *format
, ...)
364 va_start(list
, format
);
365 rv
= winansi_vfprintf(stream
, format
, list
);
371 int winansi_printf(const char *format
, ...)
376 va_start(list
, format
);
377 rv
= winansi_vfprintf(stdout
, format
, list
);
383 int winansi_write(int fd
, const void *buf
, size_t count
)
386 const char *pos
= buf
;
397 pos
= memchr(buf
, '\033', count
- 1);
398 while (pos
&& pos
[1] != '[')
399 pos
= memchr(pos
+ 1, '\033', count
- (pos
- (char *)buf
) - 2);
402 size_t len
= pos
- (const char *)buf
;
405 int output_len
= write(fd
, buf
, len
);
406 if (output_len
<= 0 && rv
)
408 if (output_len
< len
)
409 return rv
+ output_len
;
412 pos
= set_attr(pos
+ 2);
413 rv
+= pos
- (const char *)buf
;
414 count
-= pos
- (const char *)buf
;
418 output_len
= write(fd
, buf
, count
);
419 if (output_len
> 0 || rv
== 0)
427 return write(fd
, buf
, count
);