Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / kwsys / Terminal.c
blob335d89452a4fa3cdae699a114a98bacaa477dadb
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 "console",
145 "cygwin",
146 "konsole",
147 "konsole-256color",
148 "linux",
149 "msys",
150 "rxvt",
151 "rxvt-unicode",
152 "screen",
153 "screen-256color",
154 "vt100",
155 "xterm",
156 "xterm-color",
157 "xterm-256color",
161 /*--------------------------------------------------------------------------*/
162 /* Detect whether a stream is displayed in a VT100-compatible terminal. */
163 static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100,
164 int default_tty)
166 /* If running inside emacs the terminal is not VT100. Some emacs
167 seem to claim the TERM is xterm even though they do not support
168 VT100 escapes. */
169 const char* emacs = getenv("EMACS");
170 if(emacs && *emacs == 't')
172 return 0;
175 /* Check for a valid terminal. */
176 if(!default_vt100)
178 const char** t = 0;
179 const char* term = getenv("TERM");
180 if(term)
182 for(t = kwsysTerminalVT100Names; *t && strcmp(term, *t) != 0; ++t) {}
184 if(!(t && *t))
186 return 0;
190 #if defined(KWSYS_TERMINAL_ISATTY_WORKS)
191 /* Make sure the stream is a tty. */
192 (void)default_tty;
193 return isatty(fileno(stream))? 1:0;
194 #else
195 /* Check for cases in which the stream is definately not a tty. */
196 if(kwsysTerminalStreamIsNotInteractive(stream))
198 return 0;
201 /* Use the provided default for whether this is a tty. */
202 return default_tty;
203 #endif
206 /*--------------------------------------------------------------------------*/
207 /* VT100 escape sequence strings. */
208 #define KWSYS_TERMINAL_VT100_NORMAL "\33[0m"
209 #define KWSYS_TERMINAL_VT100_BOLD "\33[1m"
210 #define KWSYS_TERMINAL_VT100_UNDERLINE "\33[4m"
211 #define KWSYS_TERMINAL_VT100_BLINK "\33[5m"
212 #define KWSYS_TERMINAL_VT100_INVERSE "\33[7m"
213 #define KWSYS_TERMINAL_VT100_FOREGROUND_BLACK "\33[30m"
214 #define KWSYS_TERMINAL_VT100_FOREGROUND_RED "\33[31m"
215 #define KWSYS_TERMINAL_VT100_FOREGROUND_GREEN "\33[32m"
216 #define KWSYS_TERMINAL_VT100_FOREGROUND_YELLOW "\33[33m"
217 #define KWSYS_TERMINAL_VT100_FOREGROUND_BLUE "\33[34m"
218 #define KWSYS_TERMINAL_VT100_FOREGROUND_MAGENTA "\33[35m"
219 #define KWSYS_TERMINAL_VT100_FOREGROUND_CYAN "\33[36m"
220 #define KWSYS_TERMINAL_VT100_FOREGROUND_WHITE "\33[37m"
221 #define KWSYS_TERMINAL_VT100_BACKGROUND_BLACK "\33[40m"
222 #define KWSYS_TERMINAL_VT100_BACKGROUND_RED "\33[41m"
223 #define KWSYS_TERMINAL_VT100_BACKGROUND_GREEN "\33[42m"
224 #define KWSYS_TERMINAL_VT100_BACKGROUND_YELLOW "\33[43m"
225 #define KWSYS_TERMINAL_VT100_BACKGROUND_BLUE "\33[44m"
226 #define KWSYS_TERMINAL_VT100_BACKGROUND_MAGENTA "\33[45m"
227 #define KWSYS_TERMINAL_VT100_BACKGROUND_CYAN "\33[46m"
228 #define KWSYS_TERMINAL_VT100_BACKGROUND_WHITE "\33[47m"
230 /*--------------------------------------------------------------------------*/
231 /* Write VT100 escape sequences to the stream for the given color. */
232 static void kwsysTerminalSetVT100Color(FILE* stream, int color)
234 if(color == kwsysTerminal_Color_Normal)
236 fprintf(stream, KWSYS_TERMINAL_VT100_NORMAL);
237 return;
240 switch(color & kwsysTerminal_Color_ForegroundMask)
242 case kwsysTerminal_Color_Normal:
243 fprintf(stream, KWSYS_TERMINAL_VT100_NORMAL);
244 break;
245 case kwsysTerminal_Color_ForegroundBlack:
246 fprintf(stream, KWSYS_TERMINAL_VT100_FOREGROUND_BLACK);
247 break;
248 case kwsysTerminal_Color_ForegroundRed:
249 fprintf(stream, KWSYS_TERMINAL_VT100_FOREGROUND_RED);
250 break;
251 case kwsysTerminal_Color_ForegroundGreen:
252 fprintf(stream, KWSYS_TERMINAL_VT100_FOREGROUND_GREEN);
253 break;
254 case kwsysTerminal_Color_ForegroundYellow:
255 fprintf(stream, KWSYS_TERMINAL_VT100_FOREGROUND_YELLOW);
256 break;
257 case kwsysTerminal_Color_ForegroundBlue:
258 fprintf(stream, KWSYS_TERMINAL_VT100_FOREGROUND_BLUE);
259 break;
260 case kwsysTerminal_Color_ForegroundMagenta:
261 fprintf(stream, KWSYS_TERMINAL_VT100_FOREGROUND_MAGENTA);
262 break;
263 case kwsysTerminal_Color_ForegroundCyan:
264 fprintf(stream, KWSYS_TERMINAL_VT100_FOREGROUND_CYAN);
265 break;
266 case kwsysTerminal_Color_ForegroundWhite:
267 fprintf(stream, KWSYS_TERMINAL_VT100_FOREGROUND_WHITE);
268 break;
270 switch(color & kwsysTerminal_Color_BackgroundMask)
272 case kwsysTerminal_Color_BackgroundBlack:
273 fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_BLACK);
274 break;
275 case kwsysTerminal_Color_BackgroundRed:
276 fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_RED);
277 break;
278 case kwsysTerminal_Color_BackgroundGreen:
279 fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_GREEN);
280 break;
281 case kwsysTerminal_Color_BackgroundYellow:
282 fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_YELLOW);
283 break;
284 case kwsysTerminal_Color_BackgroundBlue:
285 fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_BLUE);
286 break;
287 case kwsysTerminal_Color_BackgroundMagenta:
288 fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_MAGENTA);
289 break;
290 case kwsysTerminal_Color_BackgroundCyan:
291 fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_CYAN);
292 break;
293 case kwsysTerminal_Color_BackgroundWhite:
294 fprintf(stream, KWSYS_TERMINAL_VT100_BACKGROUND_WHITE);
295 break;
297 if(color & kwsysTerminal_Color_ForegroundBold)
299 fprintf(stream, KWSYS_TERMINAL_VT100_BOLD);
303 /*--------------------------------------------------------------------------*/
304 #if defined(KWSYS_TERMINAL_SUPPORT_CONSOLE)
306 # define KWSYS_TERMINAL_MASK_FOREGROUND \
307 (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY)
308 # define KWSYS_TERMINAL_MASK_BACKGROUND \
309 (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)
311 /* Get the Windows handle for a FILE stream. */
312 static HANDLE kwsysTerminalGetStreamHandle(FILE* stream)
314 /* Get the C-library file descriptor from the stream. */
315 int fd = fileno(stream);
317 # if defined(__CYGWIN__)
318 /* Cygwin seems to have an extra pipe level. If the file descriptor
319 corresponds to stdout or stderr then obtain the matching windows
320 handle directly. */
321 if(fd == fileno(stdout))
323 return GetStdHandle(STD_OUTPUT_HANDLE);
325 else if(fd == fileno(stderr))
327 return GetStdHandle(STD_ERROR_HANDLE);
329 # endif
331 /* Get the underlying Windows handle for the descriptor. */
332 return (HANDLE)_get_osfhandle(fd);
335 /* Set color attributes in a Windows console. */
336 static void kwsysTerminalSetConsoleColor(HANDLE hOut,
337 CONSOLE_SCREEN_BUFFER_INFO* hOutInfo,
338 FILE* stream,
339 int color)
341 WORD attributes = 0;
342 switch(color & kwsysTerminal_Color_ForegroundMask)
344 case kwsysTerminal_Color_Normal:
345 attributes |= hOutInfo->wAttributes & KWSYS_TERMINAL_MASK_FOREGROUND;
346 break;
347 case kwsysTerminal_Color_ForegroundBlack:
348 attributes |= 0;
349 break;
350 case kwsysTerminal_Color_ForegroundRed:
351 attributes |= FOREGROUND_RED;
352 break;
353 case kwsysTerminal_Color_ForegroundGreen:
354 attributes |= FOREGROUND_GREEN;
355 break;
356 case kwsysTerminal_Color_ForegroundYellow:
357 attributes |= FOREGROUND_RED | FOREGROUND_GREEN;
358 break;
359 case kwsysTerminal_Color_ForegroundBlue:
360 attributes |= FOREGROUND_BLUE;
361 break;
362 case kwsysTerminal_Color_ForegroundMagenta:
363 attributes |= FOREGROUND_RED | FOREGROUND_BLUE;
364 break;
365 case kwsysTerminal_Color_ForegroundCyan:
366 attributes |= FOREGROUND_BLUE | FOREGROUND_GREEN;
367 break;
368 case kwsysTerminal_Color_ForegroundWhite:
369 attributes |= FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
370 break;
372 switch(color & kwsysTerminal_Color_BackgroundMask)
374 case kwsysTerminal_Color_Normal:
375 attributes |= hOutInfo->wAttributes & KWSYS_TERMINAL_MASK_BACKGROUND;
376 break;
377 case kwsysTerminal_Color_BackgroundBlack:
378 attributes |= 0;
379 break;
380 case kwsysTerminal_Color_BackgroundRed:
381 attributes |= BACKGROUND_RED;
382 break;
383 case kwsysTerminal_Color_BackgroundGreen:
384 attributes |= BACKGROUND_GREEN;
385 break;
386 case kwsysTerminal_Color_BackgroundYellow:
387 attributes |= BACKGROUND_RED | BACKGROUND_GREEN;
388 break;
389 case kwsysTerminal_Color_BackgroundBlue:
390 attributes |= BACKGROUND_BLUE;
391 break;
392 case kwsysTerminal_Color_BackgroundMagenta:
393 attributes |= BACKGROUND_RED | BACKGROUND_BLUE;
394 break;
395 case kwsysTerminal_Color_BackgroundCyan:
396 attributes |= BACKGROUND_BLUE | BACKGROUND_GREEN;
397 break;
398 case kwsysTerminal_Color_BackgroundWhite:
399 attributes |= BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED;
400 break;
402 if(color & kwsysTerminal_Color_ForegroundBold)
404 attributes |= FOREGROUND_INTENSITY;
406 if(color & kwsysTerminal_Color_BackgroundBold)
408 attributes |= BACKGROUND_INTENSITY;
410 fflush(stream);
411 SetConsoleTextAttribute(hOut, attributes);
413 #endif