2 * Copyright 2008 Peter Harris <git@peter.is-a-geek.org>
5 #include "../git-compat-util.h"
11 Functions to be wrapped:
20 ANSI codes used by git: m, K
22 This file is git-specific. Therefore, this file does not attempt
23 to implement any codes that are not used by git.
26 static HANDLE console
;
27 static WORD plain_attr
;
30 static FILE *last_stream
= NULL
;
32 typedef struct _CONSOLE_FONT_INFOEX
{
38 WCHAR FaceName
[LF_FACESIZE
];
39 } CONSOLE_FONT_INFOEX
, *PCONSOLE_FONT_INFOEX
;
41 typedef BOOL (WINAPI
*PGETCURRENTCONSOLEFONTEX
)(HANDLE
, BOOL
,
42 PCONSOLE_FONT_INFOEX
);
44 static void print_font_warning(void)
46 warning("Your console font probably doesn\'t support Unicode. If "
47 "you experience strange characters in the output, consider "
48 "switching to a TrueType font such as Lucida Console!");
51 static void check_truetype_font(void)
53 static int truetype_font_checked
;
55 PGETCURRENTCONSOLEFONTEX pGetCurrentConsoleFontEx
;
57 /* don't do this twice */
58 if (truetype_font_checked
)
60 truetype_font_checked
= 1;
62 /* GetCurrentConsoleFontEx is available since Vista */
63 pGetCurrentConsoleFontEx
= GetProcAddress(GetModuleHandle("kernel32.dll"),
64 "GetCurrentConsoleFontEx");
65 if (pGetCurrentConsoleFontEx
) {
66 CONSOLE_FONT_INFOEX cfi
;
67 cfi
.cbSize
= sizeof(cfi
);
68 if (pGetCurrentConsoleFontEx(console
, 0, &cfi
))
69 fontFamily
= cfi
.FontFamily
;
71 /* pre-Vista: check default console font in registry */
73 if (ERROR_SUCCESS
== RegOpenKeyExA(HKEY_CURRENT_USER
, "Console", 0,
75 DWORD size
= sizeof(fontFamily
);
76 RegQueryValueExA(hkey
, "FontFamily", NULL
, NULL
,
77 (LPVOID
) &fontFamily
, &size
);
82 if (!(fontFamily
& TMPF_TRUETYPE
))
83 atexit(print_font_warning
);
86 static int is_console(FILE *stream
)
88 CONSOLE_SCREEN_BUFFER_INFO sbi
;
91 static int initialized
= 0;
93 /* use cached value if stream hasn't changed */
94 if (stream
== last_stream
)
95 return console
!= NULL
;
100 /* get OS handle of the stream */
101 hcon
= (HANDLE
) _get_osfhandle(_fileno(stream
));
102 if (hcon
== INVALID_HANDLE_VALUE
)
105 /* check if its a handle to a console output screen buffer */
106 if (!GetConsoleScreenBufferInfo(hcon
, &sbi
))
110 attr
= plain_attr
= sbi
.wAttributes
;
119 static int write_console(const char *str
, size_t len
)
121 /* convert utf-8 to utf-16, write directly to console */
122 int wlen
= MultiByteToWideChar(CP_UTF8
, 0, str
, len
, NULL
, 0);
123 wchar_t *wbuf
= (wchar_t *) alloca(wlen
* sizeof(wchar_t));
124 MultiByteToWideChar(CP_UTF8
, 0, str
, len
, wbuf
, wlen
);
126 WriteConsoleW(console
, wbuf
, wlen
, NULL
, NULL
);
129 * if non-ascii characters are printed, check that the current console
133 check_truetype_font();
135 /* return original (utf-8 encoded) length */
139 #define FOREGROUND_ALL (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
140 #define BACKGROUND_ALL (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
142 static void set_console_attr(void)
144 WORD attributes
= attr
;
146 attributes
&= ~FOREGROUND_ALL
;
147 attributes
&= ~BACKGROUND_ALL
;
149 /* This could probably use a bitmask
150 instead of a series of ifs */
151 if (attr
& FOREGROUND_RED
)
152 attributes
|= BACKGROUND_RED
;
153 if (attr
& FOREGROUND_GREEN
)
154 attributes
|= BACKGROUND_GREEN
;
155 if (attr
& FOREGROUND_BLUE
)
156 attributes
|= BACKGROUND_BLUE
;
158 if (attr
& BACKGROUND_RED
)
159 attributes
|= FOREGROUND_RED
;
160 if (attr
& BACKGROUND_GREEN
)
161 attributes
|= FOREGROUND_GREEN
;
162 if (attr
& BACKGROUND_BLUE
)
163 attributes
|= FOREGROUND_BLUE
;
165 SetConsoleTextAttribute(console
, attributes
);
168 static void erase_in_line(void)
170 CONSOLE_SCREEN_BUFFER_INFO sbi
;
171 DWORD dummy
; /* Needed for Windows 7 (or Vista) regression */
176 GetConsoleScreenBufferInfo(console
, &sbi
);
177 FillConsoleOutputCharacterA(console
, ' ',
178 sbi
.dwSize
.X
- sbi
.dwCursorPosition
.X
, sbi
.dwCursorPosition
,
183 static const char *set_attr(const char *str
)
186 size_t len
= strspn(str
, "0123456789;");
192 long val
= strtol(str
, (char **)&str
, 10);
199 attr
|= FOREGROUND_INTENSITY
;
202 case 22: /* normal */
203 attr
&= ~FOREGROUND_INTENSITY
;
208 case 4: /* underline */
209 case 21: /* double underline */
210 /* Wikipedia says this flag does nothing */
211 /* Furthermore, mingw doesn't define this flag
212 attr |= COMMON_LVB_UNDERSCORE; */
214 case 24: /* no underline */
215 /* attr &= ~COMMON_LVB_UNDERSCORE; */
217 case 5: /* slow blink */
218 case 6: /* fast blink */
219 /* We don't have blink, but we do have
220 background intensity */
221 attr
|= BACKGROUND_INTENSITY
;
223 case 25: /* no blink */
224 attr
&= ~BACKGROUND_INTENSITY
;
226 case 7: /* negative */
229 case 27: /* positive */
232 case 8: /* conceal */
233 case 28: /* reveal */
237 attr
&= ~FOREGROUND_ALL
;
240 attr
&= ~FOREGROUND_ALL
;
241 attr
|= FOREGROUND_RED
;
244 attr
&= ~FOREGROUND_ALL
;
245 attr
|= FOREGROUND_GREEN
;
247 case 33: /* Yellow */
248 attr
&= ~FOREGROUND_ALL
;
249 attr
|= FOREGROUND_RED
| FOREGROUND_GREEN
;
252 attr
&= ~FOREGROUND_ALL
;
253 attr
|= FOREGROUND_BLUE
;
255 case 35: /* Magenta */
256 attr
&= ~FOREGROUND_ALL
;
257 attr
|= FOREGROUND_RED
| FOREGROUND_BLUE
;
260 attr
&= ~FOREGROUND_ALL
;
261 attr
|= FOREGROUND_GREEN
| FOREGROUND_BLUE
;
264 attr
|= FOREGROUND_RED
|
268 case 38: /* Unknown */
271 attr
&= ~FOREGROUND_ALL
;
272 attr
|= (plain_attr
& FOREGROUND_ALL
);
275 attr
&= ~BACKGROUND_ALL
;
278 attr
&= ~BACKGROUND_ALL
;
279 attr
|= BACKGROUND_RED
;
282 attr
&= ~BACKGROUND_ALL
;
283 attr
|= BACKGROUND_GREEN
;
285 case 43: /* Yellow */
286 attr
&= ~BACKGROUND_ALL
;
287 attr
|= BACKGROUND_RED
| BACKGROUND_GREEN
;
290 attr
&= ~BACKGROUND_ALL
;
291 attr
|= BACKGROUND_BLUE
;
293 case 45: /* Magenta */
294 attr
&= ~BACKGROUND_ALL
;
295 attr
|= BACKGROUND_RED
| BACKGROUND_BLUE
;
298 attr
&= ~BACKGROUND_ALL
;
299 attr
|= BACKGROUND_GREEN
| BACKGROUND_BLUE
;
302 attr
|= BACKGROUND_RED
|
306 case 48: /* Unknown */
309 attr
&= ~BACKGROUND_ALL
;
310 attr
|= (plain_attr
& BACKGROUND_ALL
);
313 /* Unsupported code */
317 } while (*(str
-1) == ';');
325 /* Unsupported code */
332 static int ansi_emulate(const char *str
, FILE *stream
)
335 const char *pos
= str
;
340 pos
= strstr(str
, "\033[");
342 size_t len
= pos
- str
;
345 size_t out_len
= write_console(str
, len
);
358 size_t len
= strlen(str
);
359 rv
+= write_console(str
, len
);
366 int winansi_fputs(const char *str
, FILE *stream
)
370 if (!is_console(stream
))
371 return fputs(str
, stream
);
373 rv
= ansi_emulate(str
, stream
);
381 int winansi_vfprintf(FILE *stream
, const char *format
, va_list list
)
385 char *buf
= small_buf
;
388 if (!is_console(stream
))
392 len
= vsnprintf(small_buf
, sizeof(small_buf
), format
, cp
);
395 if (len
> sizeof(small_buf
) - 1) {
396 buf
= malloc(len
+ 1);
400 len
= vsnprintf(buf
, len
+ 1, format
, list
);
403 rv
= ansi_emulate(buf
, stream
);
405 if (buf
!= small_buf
)
410 rv
= vfprintf(stream
, format
, list
);
414 int winansi_fprintf(FILE *stream
, const char *format
, ...)
419 va_start(list
, format
);
420 rv
= winansi_vfprintf(stream
, format
, list
);
426 int winansi_printf(const char *format
, ...)
431 va_start(list
, format
);
432 rv
= winansi_vfprintf(stdout
, format
, list
);