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
;
28 static FILE *last_stream
= NULL
;
30 static int is_console(FILE *stream
)
32 CONSOLE_SCREEN_BUFFER_INFO sbi
;
35 static int initialized
= 0;
37 /* use cached value if stream hasn't changed */
38 if (stream
== last_stream
)
39 return console
!= NULL
;
44 /* get OS handle of the stream */
45 hcon
= (HANDLE
) _get_osfhandle(_fileno(stream
));
46 if (hcon
== INVALID_HANDLE_VALUE
)
49 /* check if its a handle to a console output screen buffer */
50 if (!GetConsoleScreenBufferInfo(hcon
, &sbi
))
54 attr
= plain_attr
= sbi
.wAttributes
;
63 static int write_console(const char *str
, size_t len
)
65 /* convert utf-8 to utf-16, write directly to console */
66 int wlen
= MultiByteToWideChar(CP_UTF8
, 0, str
, len
, NULL
, 0);
67 wchar_t *wbuf
= (wchar_t *) alloca(wlen
* sizeof(wchar_t));
68 MultiByteToWideChar(CP_UTF8
, 0, str
, len
, wbuf
, wlen
);
70 WriteConsoleW(console
, wbuf
, wlen
, NULL
, NULL
);
72 /* return original (utf-8 encoded) length */
76 #define FOREGROUND_ALL (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
77 #define BACKGROUND_ALL (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
79 static void set_console_attr(void)
81 WORD attributes
= attr
;
83 attributes
&= ~FOREGROUND_ALL
;
84 attributes
&= ~BACKGROUND_ALL
;
86 /* This could probably use a bitmask
87 instead of a series of ifs */
88 if (attr
& FOREGROUND_RED
)
89 attributes
|= BACKGROUND_RED
;
90 if (attr
& FOREGROUND_GREEN
)
91 attributes
|= BACKGROUND_GREEN
;
92 if (attr
& FOREGROUND_BLUE
)
93 attributes
|= BACKGROUND_BLUE
;
95 if (attr
& BACKGROUND_RED
)
96 attributes
|= FOREGROUND_RED
;
97 if (attr
& BACKGROUND_GREEN
)
98 attributes
|= FOREGROUND_GREEN
;
99 if (attr
& BACKGROUND_BLUE
)
100 attributes
|= FOREGROUND_BLUE
;
102 SetConsoleTextAttribute(console
, attributes
);
105 static void erase_in_line(void)
107 CONSOLE_SCREEN_BUFFER_INFO sbi
;
108 DWORD dummy
; /* Needed for Windows 7 (or Vista) regression */
113 GetConsoleScreenBufferInfo(console
, &sbi
);
114 FillConsoleOutputCharacterA(console
, ' ',
115 sbi
.dwSize
.X
- sbi
.dwCursorPosition
.X
, sbi
.dwCursorPosition
,
120 static const char *set_attr(const char *str
)
123 size_t len
= strspn(str
, "0123456789;");
129 long val
= strtol(str
, (char **)&str
, 10);
136 attr
|= FOREGROUND_INTENSITY
;
139 case 22: /* normal */
140 attr
&= ~FOREGROUND_INTENSITY
;
145 case 4: /* underline */
146 case 21: /* double underline */
147 /* Wikipedia says this flag does nothing */
148 /* Furthermore, mingw doesn't define this flag
149 attr |= COMMON_LVB_UNDERSCORE; */
151 case 24: /* no underline */
152 /* attr &= ~COMMON_LVB_UNDERSCORE; */
154 case 5: /* slow blink */
155 case 6: /* fast blink */
156 /* We don't have blink, but we do have
157 background intensity */
158 attr
|= BACKGROUND_INTENSITY
;
160 case 25: /* no blink */
161 attr
&= ~BACKGROUND_INTENSITY
;
163 case 7: /* negative */
166 case 27: /* positive */
169 case 8: /* conceal */
170 case 28: /* reveal */
174 attr
&= ~FOREGROUND_ALL
;
177 attr
&= ~FOREGROUND_ALL
;
178 attr
|= FOREGROUND_RED
;
181 attr
&= ~FOREGROUND_ALL
;
182 attr
|= FOREGROUND_GREEN
;
184 case 33: /* Yellow */
185 attr
&= ~FOREGROUND_ALL
;
186 attr
|= FOREGROUND_RED
| FOREGROUND_GREEN
;
189 attr
&= ~FOREGROUND_ALL
;
190 attr
|= FOREGROUND_BLUE
;
192 case 35: /* Magenta */
193 attr
&= ~FOREGROUND_ALL
;
194 attr
|= FOREGROUND_RED
| FOREGROUND_BLUE
;
197 attr
&= ~FOREGROUND_ALL
;
198 attr
|= FOREGROUND_GREEN
| FOREGROUND_BLUE
;
201 attr
|= FOREGROUND_RED
|
205 case 38: /* Unknown */
208 attr
&= ~FOREGROUND_ALL
;
209 attr
|= (plain_attr
& FOREGROUND_ALL
);
212 attr
&= ~BACKGROUND_ALL
;
215 attr
&= ~BACKGROUND_ALL
;
216 attr
|= BACKGROUND_RED
;
219 attr
&= ~BACKGROUND_ALL
;
220 attr
|= BACKGROUND_GREEN
;
222 case 43: /* Yellow */
223 attr
&= ~BACKGROUND_ALL
;
224 attr
|= BACKGROUND_RED
| BACKGROUND_GREEN
;
227 attr
&= ~BACKGROUND_ALL
;
228 attr
|= BACKGROUND_BLUE
;
230 case 45: /* Magenta */
231 attr
&= ~BACKGROUND_ALL
;
232 attr
|= BACKGROUND_RED
| BACKGROUND_BLUE
;
235 attr
&= ~BACKGROUND_ALL
;
236 attr
|= BACKGROUND_GREEN
| BACKGROUND_BLUE
;
239 attr
|= BACKGROUND_RED
|
243 case 48: /* Unknown */
246 attr
&= ~BACKGROUND_ALL
;
247 attr
|= (plain_attr
& BACKGROUND_ALL
);
250 /* Unsupported code */
254 } while (*(str
-1) == ';');
262 /* Unsupported code */
269 static int ansi_emulate(const char *str
, FILE *stream
)
272 const char *pos
= str
;
277 pos
= strstr(str
, "\033[");
279 size_t len
= pos
- str
;
282 size_t out_len
= write_console(str
, len
);
295 size_t len
= strlen(str
);
296 rv
+= write_console(str
, len
);
303 int winansi_fputs(const char *str
, FILE *stream
)
307 if (!is_console(stream
))
308 return fputs(str
, stream
);
310 rv
= ansi_emulate(str
, stream
);
318 int winansi_vfprintf(FILE *stream
, const char *format
, va_list list
)
322 char *buf
= small_buf
;
325 if (!is_console(stream
))
329 len
= vsnprintf(small_buf
, sizeof(small_buf
), format
, cp
);
332 if (len
> sizeof(small_buf
) - 1) {
333 buf
= malloc(len
+ 1);
337 len
= vsnprintf(buf
, len
+ 1, format
, list
);
340 rv
= ansi_emulate(buf
, stream
);
342 if (buf
!= small_buf
)
347 rv
= vfprintf(stream
, format
, list
);
351 int winansi_fprintf(FILE *stream
, const char *format
, ...)
356 va_start(list
, format
);
357 rv
= winansi_vfprintf(stream
, format
, list
);
363 int winansi_printf(const char *format
, ...)
368 va_start(list
, format
);
369 rv
= winansi_vfprintf(stdout
, format
, list
);