2 * Copyright 2008 Peter Harris <git@peter.is-a-geek.org>
5 #include "../git-compat-util.h"
9 Functions to be wrapped:
18 ANSI codes used by git: m, K
20 This file is git-specific. Therefore, this file does not attempt
21 to implement any codes that are not used by git.
24 static HANDLE console
;
25 static WORD plain_attr
;
29 static void init(void)
31 CONSOLE_SCREEN_BUFFER_INFO sbi
;
33 static int initialized
= 0;
37 console
= GetStdHandle(STD_OUTPUT_HANDLE
);
38 if (console
== INVALID_HANDLE_VALUE
)
44 GetConsoleScreenBufferInfo(console
, &sbi
);
45 attr
= plain_attr
= sbi
.wAttributes
;
51 static int write_console(const char *str
, size_t len
)
53 /* convert utf-8 to utf-16, write directly to console */
54 int wlen
= MultiByteToWideChar(CP_UTF8
, 0, str
, len
, NULL
, 0);
55 wchar_t *wbuf
= (wchar_t *) alloca(wlen
* sizeof(wchar_t));
56 MultiByteToWideChar(CP_UTF8
, 0, str
, len
, wbuf
, wlen
);
58 WriteConsoleW(console
, wbuf
, wlen
, NULL
, NULL
);
60 /* return original (utf-8 encoded) length */
64 #define FOREGROUND_ALL (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
65 #define BACKGROUND_ALL (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
67 static void set_console_attr(void)
69 WORD attributes
= attr
;
71 attributes
&= ~FOREGROUND_ALL
;
72 attributes
&= ~BACKGROUND_ALL
;
74 /* This could probably use a bitmask
75 instead of a series of ifs */
76 if (attr
& FOREGROUND_RED
)
77 attributes
|= BACKGROUND_RED
;
78 if (attr
& FOREGROUND_GREEN
)
79 attributes
|= BACKGROUND_GREEN
;
80 if (attr
& FOREGROUND_BLUE
)
81 attributes
|= BACKGROUND_BLUE
;
83 if (attr
& BACKGROUND_RED
)
84 attributes
|= FOREGROUND_RED
;
85 if (attr
& BACKGROUND_GREEN
)
86 attributes
|= FOREGROUND_GREEN
;
87 if (attr
& BACKGROUND_BLUE
)
88 attributes
|= FOREGROUND_BLUE
;
90 SetConsoleTextAttribute(console
, attributes
);
93 static void erase_in_line(void)
95 CONSOLE_SCREEN_BUFFER_INFO sbi
;
96 DWORD dummy
; /* Needed for Windows 7 (or Vista) regression */
101 GetConsoleScreenBufferInfo(console
, &sbi
);
102 FillConsoleOutputCharacterA(console
, ' ',
103 sbi
.dwSize
.X
- sbi
.dwCursorPosition
.X
, sbi
.dwCursorPosition
,
108 static const char *set_attr(const char *str
)
111 size_t len
= strspn(str
, "0123456789;");
117 long val
= strtol(str
, (char **)&str
, 10);
124 attr
|= FOREGROUND_INTENSITY
;
127 case 22: /* normal */
128 attr
&= ~FOREGROUND_INTENSITY
;
133 case 4: /* underline */
134 case 21: /* double underline */
135 /* Wikipedia says this flag does nothing */
136 /* Furthermore, mingw doesn't define this flag
137 attr |= COMMON_LVB_UNDERSCORE; */
139 case 24: /* no underline */
140 /* attr &= ~COMMON_LVB_UNDERSCORE; */
142 case 5: /* slow blink */
143 case 6: /* fast blink */
144 /* We don't have blink, but we do have
145 background intensity */
146 attr
|= BACKGROUND_INTENSITY
;
148 case 25: /* no blink */
149 attr
&= ~BACKGROUND_INTENSITY
;
151 case 7: /* negative */
154 case 27: /* positive */
157 case 8: /* conceal */
158 case 28: /* reveal */
162 attr
&= ~FOREGROUND_ALL
;
165 attr
&= ~FOREGROUND_ALL
;
166 attr
|= FOREGROUND_RED
;
169 attr
&= ~FOREGROUND_ALL
;
170 attr
|= FOREGROUND_GREEN
;
172 case 33: /* Yellow */
173 attr
&= ~FOREGROUND_ALL
;
174 attr
|= FOREGROUND_RED
| FOREGROUND_GREEN
;
177 attr
&= ~FOREGROUND_ALL
;
178 attr
|= FOREGROUND_BLUE
;
180 case 35: /* Magenta */
181 attr
&= ~FOREGROUND_ALL
;
182 attr
|= FOREGROUND_RED
| FOREGROUND_BLUE
;
185 attr
&= ~FOREGROUND_ALL
;
186 attr
|= FOREGROUND_GREEN
| FOREGROUND_BLUE
;
189 attr
|= FOREGROUND_RED
|
193 case 38: /* Unknown */
196 attr
&= ~FOREGROUND_ALL
;
197 attr
|= (plain_attr
& FOREGROUND_ALL
);
200 attr
&= ~BACKGROUND_ALL
;
203 attr
&= ~BACKGROUND_ALL
;
204 attr
|= BACKGROUND_RED
;
207 attr
&= ~BACKGROUND_ALL
;
208 attr
|= BACKGROUND_GREEN
;
210 case 43: /* Yellow */
211 attr
&= ~BACKGROUND_ALL
;
212 attr
|= BACKGROUND_RED
| BACKGROUND_GREEN
;
215 attr
&= ~BACKGROUND_ALL
;
216 attr
|= BACKGROUND_BLUE
;
218 case 45: /* Magenta */
219 attr
&= ~BACKGROUND_ALL
;
220 attr
|= BACKGROUND_RED
| BACKGROUND_BLUE
;
223 attr
&= ~BACKGROUND_ALL
;
224 attr
|= BACKGROUND_GREEN
| BACKGROUND_BLUE
;
227 attr
|= BACKGROUND_RED
|
231 case 48: /* Unknown */
234 attr
&= ~BACKGROUND_ALL
;
235 attr
|= (plain_attr
& BACKGROUND_ALL
);
238 /* Unsupported code */
242 } while (*(str
-1) == ';');
250 /* Unsupported code */
257 static int ansi_emulate(const char *str
, FILE *stream
)
260 const char *pos
= str
;
265 pos
= strstr(str
, "\033[");
267 size_t len
= pos
- str
;
270 size_t out_len
= write_console(str
, len
);
283 size_t len
= strlen(str
);
284 rv
+= write_console(str
, len
);
291 int winansi_fputs(const char *str
, FILE *stream
)
295 if (!isatty(fileno(stream
)))
296 return fputs(str
, stream
);
301 return fputs(str
, stream
);
303 rv
= ansi_emulate(str
, stream
);
311 int winansi_vfprintf(FILE *stream
, const char *format
, va_list list
)
315 char *buf
= small_buf
;
318 if (!isatty(fileno(stream
)))
327 len
= vsnprintf(small_buf
, sizeof(small_buf
), format
, cp
);
330 if (len
> sizeof(small_buf
) - 1) {
331 buf
= malloc(len
+ 1);
335 len
= vsnprintf(buf
, len
+ 1, format
, list
);
338 rv
= ansi_emulate(buf
, stream
);
340 if (buf
!= small_buf
)
345 rv
= vfprintf(stream
, format
, list
);
349 int winansi_fprintf(FILE *stream
, const char *format
, ...)
354 va_start(list
, format
);
355 rv
= winansi_vfprintf(stream
, format
, list
);
361 int winansi_printf(const char *format
, ...)
366 va_start(list
, format
);
367 rv
= winansi_vfprintf(stdout
, format
, list
);