Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / kwsys / Terminal.c
blob77ea47f58ce98fb1fce9c92eebf00444ad46b9b8
1 /*=========================================================================
3 Program: KWSys - Kitware System Library
4 Module: $RCSfile: Terminal.c,v $
6 Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved.
7 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 This software is distributed WITHOUT ANY WARRANTY; without even
10 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 PURPOSE. See the above copyright notices for more information.
13 =========================================================================*/
14 #include "kwsysPrivate.h"
15 #include KWSYS_HEADER(Terminal.h)
17 /* Work-around CMake dependency scanning limitation. This must
18 duplicate the above list of headers. */
19 #if 0
20 # include "Terminal.h.in"
21 #endif
23 /*--------------------------------------------------------------------------*/
24 /* Configure support for this platform. */
25 #if defined(_WIN32) || defined(__CYGWIN__)
26 # define KWSYS_TERMINAL_SUPPORT_CONSOLE
27 #endif
28 #if !defined(_WIN32)
29 # define KWSYS_TERMINAL_ISATTY_WORKS
30 #endif
32 /*--------------------------------------------------------------------------*/
33 /* Include needed system APIs. */
35 #include <stdlib.h> /* getenv */
36 #include <string.h> /* strcmp */
37 #include <stdarg.h> /* va_list */
39 #if defined(KWSYS_TERMINAL_SUPPORT_CONSOLE)
40 # include <windows.h> /* SetConsoleTextAttribute */
41 # include <io.h> /* _get_osfhandle */
42 #endif
44 #if defined(KWSYS_TERMINAL_ISATTY_WORKS)
45 # include <unistd.h> /* isatty */
46 #else
47 # include <sys/stat.h> /* fstat */
48 #endif
50 /*--------------------------------------------------------------------------*/
51 static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100,
52 int default_tty);
53 static void kwsysTerminalSetVT100Color(FILE* stream, int color);
54 #if defined(KWSYS_TERMINAL_SUPPORT_CONSOLE)
55 static HANDLE kwsysTerminalGetStreamHandle(FILE* stream);
56 static void kwsysTerminalSetConsoleColor(HANDLE hOut,
57 CONSOLE_SCREEN_BUFFER_INFO* hOutInfo,
58 FILE* stream,
59 int color);
60 #endif
62 /*--------------------------------------------------------------------------*/
63 void kwsysTerminal_cfprintf(int color, FILE* stream, const char* format, ...)
65 /* Setup the stream with the given color if possible. */
66 int pipeIsConsole = 0;
67 int pipeIsVT100 = 0;
68 int default_vt100 = color & kwsysTerminal_Color_AssumeVT100;
69 int default_tty = color & kwsysTerminal_Color_AssumeTTY;
70 #if defined(KWSYS_TERMINAL_SUPPORT_CONSOLE)
71 CONSOLE_SCREEN_BUFFER_INFO hOutInfo;
72 HANDLE hOut = kwsysTerminalGetStreamHandle(stream);
73 if(GetConsoleScreenBufferInfo(hOut, &hOutInfo))
75 pipeIsConsole = 1;
76 kwsysTerminalSetConsoleColor(hOut, &hOutInfo, stream, color);
78 #endif
79 if(!pipeIsConsole && kwsysTerminalStreamIsVT100(stream,
80 default_vt100, default_tty))
82 pipeIsVT100 = 1;
83 kwsysTerminalSetVT100Color(stream, color);
86 /* Format the text into the stream. */
88 va_list var_args;
89 va_start(var_args, format);
90 vfprintf(stream, format, var_args);
91 va_end(var_args);
94 /* Restore the normal color state for the stream. */
95 #if defined(KWSYS_TERMINAL_SUPPORT_CONSOLE)
96 if(pipeIsConsole)
98 kwsysTerminalSetConsoleColor(hOut, &hOutInfo, stream,
99 kwsysTerminal_Color_Normal);
101 #endif
102 if(pipeIsVT100)
104 kwsysTerminalSetVT100Color(stream, kwsysTerminal_Color_Normal);
108 /*--------------------------------------------------------------------------*/
109 /* Detect cases when a stream is definately not interactive. */
110 #if !defined(KWSYS_TERMINAL_ISATTY_WORKS)
111 static int kwsysTerminalStreamIsNotInteractive(FILE* stream)
113 /* The given stream is definately not interactive if it is a regular
114 file. */
115 struct stat stream_stat;
116 if(fstat(fileno(stream), &stream_stat) == 0)
118 if(stream_stat.st_mode & S_IFREG)
120 return 1;
123 return 0;
125 #endif
127 /*--------------------------------------------------------------------------*/
128 /* List of terminal names known to support VT100 color escape sequences. */
129 static const char* kwsysTerminalVT100Names[] =
131 "Eterm",
132 "ansi",
133 "color-xterm",
134 "con132x25",
135 "con132x30",
136 "con132x43",
137 "con132x60",
138 "con80x25",
139 "con80x28",
140 "con80x30",
141 "con80x43",
142 "con80x50",
143 "con80x60",
144 "cons25",
145 "console",
146 "cygwin",
147 "dtterm",
148 "eterm-color",
149 "gnome",
150 "gnome-256color",
151 "konsole",
152 "konsole-256color",
153 "kterm",
154 "linux",
155 "msys",
156 "linux-c",
157 "mach-color",
158 "mlterm",
159 "putty",
160 "rxvt",
161 "rxvt-cygwin",
162 "rxvt-cygwin-native",
163 "rxvt-unicode",
164 "screen",
165 "screen-256color",
166 "screen-bce",
167 "screen-w",
168 "screen.linux",
169 "vt100",
170 "xterm",
171 "xterm-16color",
172 "xterm-256color",
173 "xterm-88color",
174 "xterm-color",
175 "xterm-debian",
179 /*--------------------------------------------------------------------------*/
180 /* Detect whether a stream is displayed in a VT100-compatible terminal. */
181 static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100,
182 int default_tty)
184 /* If running inside emacs the terminal is not VT100. Some emacs
185 seem to claim the TERM is xterm even though they do not support
186 VT100 escapes. */
187 const char* emacs = getenv("EMACS");
188 if(emacs && *emacs == 't')
190 return 0;
193 /* Check for a valid terminal. */
194 if(!default_vt100)
196 const char** t = 0;
197 const char* term = getenv("TERM");
198 if(term)
200 for(t = kwsysTerminalVT100Names; *t && strcmp(term, *t) != 0; ++t) {}
202 if(!(t && *t))
204 return 0;
208 #if defined(KWSYS_TERMINAL_ISATTY_WORKS)
209 /* Make sure the stream is a tty. */
210 (void)default_tty;
211 return isatty(fileno(stream))? 1:0;
212 #else
213 /* Check for cases in which the stream is definately not a tty. */
214 if(kwsysTerminalStreamIsNotInteractive(stream))
216 return 0;
219 /* Use the provided default for whether this is a tty. */
220 return default_tty;
221 #endif
224 /*--------------------------------------------------------------------------*/
225 /* VT100 escape sequence strings. */
226 #define KWSYS_TERMINAL_VT100_NORMAL "\33[0m"
227 #define KWSYS_TERMINAL_VT100_BOLD "\33[1m"
228 #define KWSYS_TERMINAL_VT100_UNDERLINE "\33[4m"
229 #define KWSYS_TERMINAL_VT100_BLINK "\33[5m"
230 #define KWSYS_TERMINAL_VT100_INVERSE "\33[7m"
231 #define KWSYS_TERMINAL_VT100_FOREGROUND_BLACK "\33[30m"
232 #define KWSYS_TERMINAL_VT100_FOREGROUND_RED "\33[31m"
233 #define KWSYS_TERMINAL_VT100_FOREGROUND_GREEN "\33[32m"
234 #define KWSYS_TERMINAL_VT100_FOREGROUND_YELLOW "\33[33m"
235 #define KWSYS_TERMINAL_VT100_FOREGROUND_BLUE "\33[34m"
236 #define KWSYS_TERMINAL_VT100_FOREGROUND_MAGENTA "\33[35m"
237 #define KWSYS_TERMINAL_VT100_FOREGROUND_CYAN "\33[36m"
238 #define KWSYS_TERMINAL_VT100_FOREGROUND_WHITE "\33[37m"
239 #define KWSYS_TERMINAL_VT100_BACKGROUND_BLACK "\33[40m"
240 #define KWSYS_TERMINAL_VT100_BACKGROUND_RED "\33[41m"
241 #define KWSYS_TERMINAL_VT100_BACKGROUND_GREEN "\33[42m"
242 #define KWSYS_TERMINAL_VT100_BACKGROUND_YELLOW "\33[43m"
243 #define KWSYS_TERMINAL_VT100_BACKGROUND_BLUE "\33[44m"
244 #define KWSYS_TERMINAL_VT100_BACKGROUND_MAGENTA "\33[45m"
245 #define KWSYS_TERMINAL_VT100_BACKGROUND_CYAN "\33[46m"
246 #define KWSYS_TERMINAL_VT100_BACKGROUND_WHITE "\33[47m"
248 /*--------------------------------------------------------------------------*/
249 /* Write VT100 escape sequences to the stream for the given color. */
250 static void kwsysTerminalSetVT100Color(FILE* stream, int color)
252 if(color == kwsysTerminal_Color_Normal)
254 fprintf(stream, KWSYS_TERMINAL_VT100_NORMAL);
255 return;
258 switch(color & kwsysTerminal_Color_ForegroundMask)
260 case kwsysTerminal_Color_Normal:
261 fprintf(stream, KWSYS_TERMINAL_VT100_NORMAL);
262 break;
263 case kwsysTerminal_Color_ForegroundBlack:
264 fprintf(stream, KWSYS_TERMINAL_VT100_FOREGROUND_BLACK);
265 break;
266 case kwsysTerminal_Color_ForegroundRed:
267 fprintf(stream, KWSYS_TERMINAL_VT100_FOREGROUND_RED);
268 break;
269 case kwsysTerminal_Color_ForegroundGreen:
270 fprintf(stream, KWSYS_TERMINAL_VT100_FOREGROUND_GREEN);
271 break;
272 case kwsysTerminal_Color_ForegroundYellow:
273 fprintf(stream, KWSYS_TERMINAL_VT100_FOREGROUND_YELLOW);
274 break;
275 case kwsysTerminal_Color_ForegroundBlue:
276 fprintf(stream, KWSYS_TERMINAL_VT100_FOREGROUND_BLUE);
277 break;
278 case kwsysTerminal_Color_ForegroundMagenta:
279 fprintf(stream, KWSYS_TERMINAL_VT100_FOREGROUND_MAGENTA);
280 break;
281 case kwsysTerminal_Color_ForegroundCyan:
282 fprintf(stream, KWSYS_TERMINAL_VT100_FOREGROUND_CYAN);
283 break;
284 case kwsysTerminal_Color_ForegroundWhite:
285 fprintf(stream, KWSYS_TERMINAL_VT100_FOREGROUND_WHITE);
286 break;
288 switch(color & kwsysTerminal_Color_BackgroundMask)
290 case kwsysTerminal_Color_BackgroundBlack:
291 fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_BLACK);
292 break;
293 case kwsysTerminal_Color_BackgroundRed:
294 fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_RED);
295 break;
296 case kwsysTerminal_Color_BackgroundGreen:
297 fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_GREEN);
298 break;
299 case kwsysTerminal_Color_BackgroundYellow:
300 fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_YELLOW);
301 break;
302 case kwsysTerminal_Color_BackgroundBlue:
303 fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_BLUE);
304 break;
305 case kwsysTerminal_Color_BackgroundMagenta:
306 fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_MAGENTA);
307 break;
308 case kwsysTerminal_Color_BackgroundCyan:
309 fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_CYAN);
310 break;
311 case kwsysTerminal_Color_BackgroundWhite:
312 fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_WHITE);
313 break;
315 if(color & kwsysTerminal_Color_ForegroundBold)
317 fprintf(stream, KWSYS_TERMINAL_VT100_BOLD);
321 /*--------------------------------------------------------------------------*/
322 #if defined(KWSYS_TERMINAL_SUPPORT_CONSOLE)
324 # define KWSYS_TERMINAL_MASK_FOREGROUND \
325 (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY)
326 # define KWSYS_TERMINAL_MASK_BACKGROUND \
327 (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)
329 /* Get the Windows handle for a FILE stream. */
330 static HANDLE kwsysTerminalGetStreamHandle(FILE* stream)
332 /* Get the C-library file descriptor from the stream. */
333 int fd = fileno(stream);
335 # if defined(__CYGWIN__)
336 /* Cygwin seems to have an extra pipe level. If the file descriptor
337 corresponds to stdout or stderr then obtain the matching windows
338 handle directly. */
339 if(fd == fileno(stdout))
341 return GetStdHandle(STD_OUTPUT_HANDLE);
343 else if(fd == fileno(stderr))
345 return GetStdHandle(STD_ERROR_HANDLE);
347 # endif
349 /* Get the underlying Windows handle for the descriptor. */
350 return (HANDLE)_get_osfhandle(fd);
353 /* Set color attributes in a Windows console. */
354 static void kwsysTerminalSetConsoleColor(HANDLE hOut,
355 CONSOLE_SCREEN_BUFFER_INFO* hOutInfo,
356 FILE* stream,
357 int color)
359 WORD attributes = 0;
360 switch(color & kwsysTerminal_Color_ForegroundMask)
362 case kwsysTerminal_Color_Normal:
363 attributes |= hOutInfo->wAttributes & KWSYS_TERMINAL_MASK_FOREGROUND;
364 break;
365 case kwsysTerminal_Color_ForegroundBlack:
366 attributes |= 0;
367 break;
368 case kwsysTerminal_Color_ForegroundRed:
369 attributes |= FOREGROUND_RED;
370 break;
371 case kwsysTerminal_Color_ForegroundGreen:
372 attributes |= FOREGROUND_GREEN;
373 break;
374 case kwsysTerminal_Color_ForegroundYellow:
375 attributes |= FOREGROUND_RED | FOREGROUND_GREEN;
376 break;
377 case kwsysTerminal_Color_ForegroundBlue:
378 attributes |= FOREGROUND_BLUE;
379 break;
380 case kwsysTerminal_Color_ForegroundMagenta:
381 attributes |= FOREGROUND_RED | FOREGROUND_BLUE;
382 break;
383 case kwsysTerminal_Color_ForegroundCyan:
384 attributes |= FOREGROUND_BLUE | FOREGROUND_GREEN;
385 break;
386 case kwsysTerminal_Color_ForegroundWhite:
387 attributes |= FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
388 break;
390 switch(color & kwsysTerminal_Color_BackgroundMask)
392 case kwsysTerminal_Color_Normal:
393 attributes |= hOutInfo->wAttributes & KWSYS_TERMINAL_MASK_BACKGROUND;
394 break;
395 case kwsysTerminal_Color_BackgroundBlack:
396 attributes |= 0;
397 break;
398 case kwsysTerminal_Color_BackgroundRed:
399 attributes |= BACKGROUND_RED;
400 break;
401 case kwsysTerminal_Color_BackgroundGreen:
402 attributes |= BACKGROUND_GREEN;
403 break;
404 case kwsysTerminal_Color_BackgroundYellow:
405 attributes |= BACKGROUND_RED | BACKGROUND_GREEN;
406 break;
407 case kwsysTerminal_Color_BackgroundBlue:
408 attributes |= BACKGROUND_BLUE;
409 break;
410 case kwsysTerminal_Color_BackgroundMagenta:
411 attributes |= BACKGROUND_RED | BACKGROUND_BLUE;
412 break;
413 case kwsysTerminal_Color_BackgroundCyan:
414 attributes |= BACKGROUND_BLUE | BACKGROUND_GREEN;
415 break;
416 case kwsysTerminal_Color_BackgroundWhite:
417 attributes |= BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED;
418 break;
420 if(color & kwsysTerminal_Color_ForegroundBold)
422 attributes |= FOREGROUND_INTENSITY;
424 if(color & kwsysTerminal_Color_BackgroundBold)
426 attributes |= BACKGROUND_INTENSITY;
428 fflush(stream);
429 SetConsoleTextAttribute(hOut, attributes);
431 #endif