Elaztek Developer Hub
Blamite Game Engine - Strings  00402.09.29.23.0627.blamite
A library containing general purpose utilities and classes for use in multiple projects.
termcolor.hpp
Go to the documentation of this file.
1 
12 #ifndef TERMCOLOR_HPP_
13 #define TERMCOLOR_HPP_
14 
15 #include <iostream>
16 #include <cstdio>
17 
18 // Detect target's platform and set some macros in order to wrap platform
19 // specific code this library depends on.
20 #if defined(_WIN32) || defined(_WIN64)
21 # define TERMCOLOR_TARGET_WINDOWS
22 #elif defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))
23 # define TERMCOLOR_TARGET_POSIX
24 #endif
25 
26 // If implementation has not been explicitly set, try to choose one based on
27 // target platform.
28 #if !defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES) && !defined(TERMCOLOR_USE_WINDOWS_API) && !defined(TERMCOLOR_USE_NOOP)
29 # if defined(TERMCOLOR_TARGET_POSIX)
30 # define TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES
31 # define TERMCOLOR_AUTODETECTED_IMPLEMENTATION
32 # elif defined(TERMCOLOR_TARGET_WINDOWS)
33 # define TERMCOLOR_USE_WINDOWS_API
34 # define TERMCOLOR_AUTODETECTED_IMPLEMENTATION
35 # endif
36 #endif
37 
38 // These headers provide isatty()/fileno() functions, which are used for
39 // testing whether a standard stream refers to the terminal.
40 #if defined(TERMCOLOR_TARGET_POSIX)
41 # include <unistd.h>
42 #elif defined(TERMCOLOR_TARGET_WINDOWS)
43 # include <io.h>
44 # include <windows.h>
45 #endif
46 
47 
48 namespace termcolor
49 {
50  // Forward declaration of the `_internal` namespace.
51  // All comments are below.
52  namespace _internal
53  {
54  inline int colorize_index();
55  inline FILE* get_standard_stream(const std::ostream& stream);
56  inline bool is_colorized(std::ostream& stream);
57  inline bool is_atty(const std::ostream& stream);
58 
59 #if defined(TERMCOLOR_TARGET_WINDOWS)
60  inline void win_change_attributes(std::ostream& stream, int foreground, int background = -1);
61 #endif
62  }
63 
64  inline
65  std::ostream& colorize(std::ostream& stream)
66  {
67  stream.iword(_internal::colorize_index()) = 1L;
68  return stream;
69  }
70 
71  inline
72  std::ostream& nocolorize(std::ostream& stream)
73  {
74  stream.iword(_internal::colorize_index()) = 0L;
75  return stream;
76  }
77 
78  inline
79  std::ostream& reset(std::ostream& stream)
80  {
81  if (_internal::is_colorized(stream))
82  {
83 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
84  stream << "\033[00m";
85 #elif defined(TERMCOLOR_USE_WINDOWS_API)
86  _internal::win_change_attributes(stream, -1, -1);
87 #endif
88  }
89  return stream;
90  }
91 
92  inline
93  std::ostream& bold(std::ostream& stream)
94  {
95  if (_internal::is_colorized(stream))
96  {
97 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
98  stream << "\033[1m";
99 #elif defined(TERMCOLOR_USE_WINDOWS_API)
100 #endif
101  }
102  return stream;
103  }
104 
105  inline
106  std::ostream& dark(std::ostream& stream)
107  {
108  if (_internal::is_colorized(stream))
109  {
110 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
111  stream << "\033[2m";
112 #elif defined(TERMCOLOR_USE_WINDOWS_API)
113 #endif
114  }
115  return stream;
116  }
117 
118  inline
119  std::ostream& italic(std::ostream& stream)
120  {
121  if (_internal::is_colorized(stream))
122  {
123 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
124  stream << "\033[3m";
125 #elif defined(TERMCOLOR_USE_WINDOWS_API)
126 #endif
127  }
128  return stream;
129  }
130 
131  inline
132  std::ostream& underline(std::ostream& stream)
133  {
134  if (_internal::is_colorized(stream))
135  {
136 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
137  stream << "\033[4m";
138 #elif defined(TERMCOLOR_USE_WINDOWS_API)
139  _internal::win_change_attributes(stream, -1, COMMON_LVB_UNDERSCORE);
140 #endif
141  }
142  return stream;
143  }
144 
145  inline
146  std::ostream& blink(std::ostream& stream)
147  {
148  if (_internal::is_colorized(stream))
149  {
150 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
151  stream << "\033[5m";
152 #elif defined(TERMCOLOR_USE_WINDOWS_API)
153 #endif
154  }
155  return stream;
156  }
157 
158  inline
159  std::ostream& reverse(std::ostream& stream)
160  {
161  if (_internal::is_colorized(stream))
162  {
163 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
164  stream << "\033[7m";
165 #elif defined(TERMCOLOR_USE_WINDOWS_API)
166 #endif
167  }
168  return stream;
169  }
170 
171  inline
172  std::ostream& concealed(std::ostream& stream)
173  {
174  if (_internal::is_colorized(stream))
175  {
176 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
177  stream << "\033[8m";
178 #elif defined(TERMCOLOR_USE_WINDOWS_API)
179 #endif
180  }
181  return stream;
182  }
183 
184  inline
185  std::ostream& crossed(std::ostream& stream)
186  {
187  if (_internal::is_colorized(stream))
188  {
189 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
190  stream << "\033[9m";
191 #elif defined(TERMCOLOR_USE_WINDOWS_API)
192 #endif
193  }
194  return stream;
195  }
196 
197  template <uint8_t code> inline
198  std::ostream& color(std::ostream& stream)
199  {
200  if (_internal::is_colorized(stream))
201  {
202 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
203  char command[12];
204  std::snprintf(command, sizeof(command), "\033[38;5;%dm", code);
205  stream << command;
206 #elif defined(TERMCOLOR_USE_WINDOWS_API)
207 #endif
208  }
209  return stream;
210  }
211 
212  template <uint8_t code> inline
213  std::ostream& on_color(std::ostream& stream)
214  {
215  if (_internal::is_colorized(stream))
216  {
217 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
218  char command[12];
219  std::snprintf(command, sizeof(command), "\033[48;5;%dm", code);
220  stream << command;
221 #elif defined(TERMCOLOR_USE_WINDOWS_API)
222 #endif
223  }
224  return stream;
225  }
226 
227  template <uint8_t r, uint8_t g, uint8_t b> inline
228  std::ostream& color(std::ostream& stream)
229  {
230  if (_internal::is_colorized(stream))
231  {
232 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
233  char command[20];
234  std::snprintf(command, sizeof(command), "\033[38;2;%d;%d;%dm", r, g, b);
235  stream << command;
236 #elif defined(TERMCOLOR_USE_WINDOWS_API)
237 #endif
238  }
239  return stream;
240  }
241 
242  template <uint8_t r, uint8_t g, uint8_t b> inline
243  std::ostream& on_color(std::ostream& stream)
244  {
245  if (_internal::is_colorized(stream))
246  {
247 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
248  char command[20];
249  std::snprintf(command, sizeof(command), "\033[48;2;%d;%d;%dm", r, g, b);
250  stream << command;
251 #elif defined(TERMCOLOR_USE_WINDOWS_API)
252 #endif
253  }
254  return stream;
255  }
256 
257  inline
258  std::ostream& grey(std::ostream& stream)
259  {
260  if (_internal::is_colorized(stream))
261  {
262 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
263  stream << "\033[30m";
264 #elif defined(TERMCOLOR_USE_WINDOWS_API)
265  _internal::win_change_attributes(stream,
266  0 // grey (black)
267  );
268 #endif
269  }
270  return stream;
271  }
272 
273  inline
274  std::ostream& red(std::ostream& stream)
275  {
276  if (_internal::is_colorized(stream))
277  {
278 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
279  stream << "\033[31m";
280 #elif defined(TERMCOLOR_USE_WINDOWS_API)
281  _internal::win_change_attributes(stream,
282  FOREGROUND_RED
283  );
284 #endif
285  }
286  return stream;
287  }
288 
289  inline
290  std::ostream& green(std::ostream& stream)
291  {
292  if (_internal::is_colorized(stream))
293  {
294 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
295  stream << "\033[32m";
296 #elif defined(TERMCOLOR_USE_WINDOWS_API)
297  _internal::win_change_attributes(stream,
298  FOREGROUND_GREEN
299  );
300 #endif
301  }
302  return stream;
303  }
304 
305  inline
306  std::ostream& yellow(std::ostream& stream)
307  {
308  if (_internal::is_colorized(stream))
309  {
310 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
311  stream << "\033[33m";
312 #elif defined(TERMCOLOR_USE_WINDOWS_API)
313  _internal::win_change_attributes(stream,
314  FOREGROUND_GREEN | FOREGROUND_RED
315  );
316 #endif
317  }
318  return stream;
319  }
320 
321  inline
322  std::ostream& blue(std::ostream& stream)
323  {
324  if (_internal::is_colorized(stream))
325  {
326 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
327  stream << "\033[34m";
328 #elif defined(TERMCOLOR_USE_WINDOWS_API)
329  _internal::win_change_attributes(stream,
330  FOREGROUND_BLUE
331  );
332 #endif
333  }
334  return stream;
335  }
336 
337  inline
338  std::ostream& magenta(std::ostream& stream)
339  {
340  if (_internal::is_colorized(stream))
341  {
342 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
343  stream << "\033[35m";
344 #elif defined(TERMCOLOR_USE_WINDOWS_API)
345  _internal::win_change_attributes(stream,
346  FOREGROUND_BLUE | FOREGROUND_RED
347  );
348 #endif
349  }
350  return stream;
351  }
352 
353  inline
354  std::ostream& cyan(std::ostream& stream)
355  {
356  if (_internal::is_colorized(stream))
357  {
358 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
359  stream << "\033[36m";
360 #elif defined(TERMCOLOR_USE_WINDOWS_API)
361  _internal::win_change_attributes(stream,
362  FOREGROUND_BLUE | FOREGROUND_GREEN
363  );
364 #endif
365  }
366  return stream;
367  }
368 
369  inline
370  std::ostream& white(std::ostream& stream)
371  {
372  if (_internal::is_colorized(stream))
373  {
374 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
375  stream << "\033[37m";
376 #elif defined(TERMCOLOR_USE_WINDOWS_API)
377  _internal::win_change_attributes(stream,
378  FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
379  );
380 #endif
381  }
382  return stream;
383  }
384 
385 
386  inline
387  std::ostream& bright_grey(std::ostream& stream)
388  {
389  if (_internal::is_colorized(stream))
390  {
391 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
392  stream << "\033[90m";
393 #elif defined(TERMCOLOR_USE_WINDOWS_API)
394  _internal::win_change_attributes(stream,
395  0 | FOREGROUND_INTENSITY // grey (black)
396  );
397 #endif
398  }
399  return stream;
400  }
401 
402  inline
403  std::ostream& bright_red(std::ostream& stream)
404  {
405  if (_internal::is_colorized(stream))
406  {
407 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
408  stream << "\033[91m";
409 #elif defined(TERMCOLOR_USE_WINDOWS_API)
410  _internal::win_change_attributes(stream,
411  FOREGROUND_RED | FOREGROUND_INTENSITY
412  );
413 #endif
414  }
415  return stream;
416  }
417 
418  inline
419  std::ostream& bright_green(std::ostream& stream)
420  {
421  if (_internal::is_colorized(stream))
422  {
423 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
424  stream << "\033[92m";
425 #elif defined(TERMCOLOR_USE_WINDOWS_API)
426  _internal::win_change_attributes(stream,
427  FOREGROUND_GREEN | FOREGROUND_INTENSITY
428  );
429 #endif
430  }
431  return stream;
432  }
433 
434  inline
435  std::ostream& bright_yellow(std::ostream& stream)
436  {
437  if (_internal::is_colorized(stream))
438  {
439 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
440  stream << "\033[93m";
441 #elif defined(TERMCOLOR_USE_WINDOWS_API)
442  _internal::win_change_attributes(stream,
443  FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY
444  );
445 #endif
446  }
447  return stream;
448  }
449 
450  inline
451  std::ostream& bright_blue(std::ostream& stream)
452  {
453  if (_internal::is_colorized(stream))
454  {
455 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
456  stream << "\033[94m";
457 #elif defined(TERMCOLOR_USE_WINDOWS_API)
458  _internal::win_change_attributes(stream,
459  FOREGROUND_BLUE | FOREGROUND_INTENSITY
460  );
461 #endif
462  }
463  return stream;
464  }
465 
466  inline
467  std::ostream& bright_magenta(std::ostream& stream)
468  {
469  if (_internal::is_colorized(stream))
470  {
471 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
472  stream << "\033[95m";
473 #elif defined(TERMCOLOR_USE_WINDOWS_API)
474  _internal::win_change_attributes(stream,
475  FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY
476  );
477 #endif
478  }
479  return stream;
480  }
481 
482  inline
483  std::ostream& bright_cyan(std::ostream& stream)
484  {
485  if (_internal::is_colorized(stream))
486  {
487 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
488  stream << "\033[96m";
489 #elif defined(TERMCOLOR_USE_WINDOWS_API)
490  _internal::win_change_attributes(stream,
491  FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY
492  );
493 #endif
494  }
495  return stream;
496  }
497 
498  inline
499  std::ostream& bright_white(std::ostream& stream)
500  {
501  if (_internal::is_colorized(stream))
502  {
503 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
504  stream << "\033[97m";
505 #elif defined(TERMCOLOR_USE_WINDOWS_API)
506  _internal::win_change_attributes(stream,
507  FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY
508  );
509 #endif
510  }
511  return stream;
512  }
513 
514 
515  inline
516  std::ostream& on_grey(std::ostream& stream)
517  {
518  if (_internal::is_colorized(stream))
519  {
520 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
521  stream << "\033[40m";
522 #elif defined(TERMCOLOR_USE_WINDOWS_API)
523  _internal::win_change_attributes(stream, -1,
524  0 // grey (black)
525  );
526 #endif
527  }
528  return stream;
529  }
530 
531  inline
532  std::ostream& on_red(std::ostream& stream)
533  {
534  if (_internal::is_colorized(stream))
535  {
536 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
537  stream << "\033[41m";
538 #elif defined(TERMCOLOR_USE_WINDOWS_API)
539  _internal::win_change_attributes(stream, -1,
540  BACKGROUND_RED
541  );
542 #endif
543  }
544  return stream;
545  }
546 
547  inline
548  std::ostream& on_green(std::ostream& stream)
549  {
550  if (_internal::is_colorized(stream))
551  {
552 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
553  stream << "\033[42m";
554 #elif defined(TERMCOLOR_USE_WINDOWS_API)
555  _internal::win_change_attributes(stream, -1,
556  BACKGROUND_GREEN
557  );
558 #endif
559  }
560  return stream;
561  }
562 
563  inline
564  std::ostream& on_yellow(std::ostream& stream)
565  {
566  if (_internal::is_colorized(stream))
567  {
568 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
569  stream << "\033[43m";
570 #elif defined(TERMCOLOR_USE_WINDOWS_API)
571  _internal::win_change_attributes(stream, -1,
572  BACKGROUND_GREEN | BACKGROUND_RED
573  );
574 #endif
575  }
576  return stream;
577  }
578 
579  inline
580  std::ostream& on_blue(std::ostream& stream)
581  {
582  if (_internal::is_colorized(stream))
583  {
584 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
585  stream << "\033[44m";
586 #elif defined(TERMCOLOR_USE_WINDOWS_API)
587  _internal::win_change_attributes(stream, -1,
588  BACKGROUND_BLUE
589  );
590 #endif
591  }
592  return stream;
593  }
594 
595  inline
596  std::ostream& on_magenta(std::ostream& stream)
597  {
598  if (_internal::is_colorized(stream))
599  {
600 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
601  stream << "\033[45m";
602 #elif defined(TERMCOLOR_USE_WINDOWS_API)
603  _internal::win_change_attributes(stream, -1,
604  BACKGROUND_BLUE | BACKGROUND_RED
605  );
606 #endif
607  }
608  return stream;
609  }
610 
611  inline
612  std::ostream& on_cyan(std::ostream& stream)
613  {
614  if (_internal::is_colorized(stream))
615  {
616 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
617  stream << "\033[46m";
618 #elif defined(TERMCOLOR_USE_WINDOWS_API)
619  _internal::win_change_attributes(stream, -1,
620  BACKGROUND_GREEN | BACKGROUND_BLUE
621  );
622 #endif
623  }
624  return stream;
625  }
626 
627  inline
628  std::ostream& on_white(std::ostream& stream)
629  {
630  if (_internal::is_colorized(stream))
631  {
632 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
633  stream << "\033[47m";
634 #elif defined(TERMCOLOR_USE_WINDOWS_API)
635  _internal::win_change_attributes(stream, -1,
636  BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED
637  );
638 #endif
639  }
640 
641  return stream;
642  }
643 
644 
645  inline
646  std::ostream& on_bright_grey(std::ostream& stream)
647  {
648  if (_internal::is_colorized(stream))
649  {
650 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
651  stream << "\033[100m";
652 #elif defined(TERMCOLOR_USE_WINDOWS_API)
653  _internal::win_change_attributes(stream, -1,
654  0 | BACKGROUND_INTENSITY // grey (black)
655  );
656 #endif
657  }
658  return stream;
659  }
660 
661  inline
662  std::ostream& on_bright_red(std::ostream& stream)
663  {
664  if (_internal::is_colorized(stream))
665  {
666 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
667  stream << "\033[101m";
668 #elif defined(TERMCOLOR_USE_WINDOWS_API)
669  _internal::win_change_attributes(stream, -1,
670  BACKGROUND_RED | BACKGROUND_INTENSITY
671  );
672 #endif
673  }
674  return stream;
675  }
676 
677  inline
678  std::ostream& on_bright_green(std::ostream& stream)
679  {
680  if (_internal::is_colorized(stream))
681  {
682 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
683  stream << "\033[102m";
684 #elif defined(TERMCOLOR_USE_WINDOWS_API)
685  _internal::win_change_attributes(stream, -1,
686  BACKGROUND_GREEN | BACKGROUND_INTENSITY
687  );
688 #endif
689  }
690  return stream;
691  }
692 
693  inline
694  std::ostream& on_bright_yellow(std::ostream& stream)
695  {
696  if (_internal::is_colorized(stream))
697  {
698 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
699  stream << "\033[103m";
700 #elif defined(TERMCOLOR_USE_WINDOWS_API)
701  _internal::win_change_attributes(stream, -1,
702  BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY
703  );
704 #endif
705  }
706  return stream;
707  }
708 
709  inline
710  std::ostream& on_bright_blue(std::ostream& stream)
711  {
712  if (_internal::is_colorized(stream))
713  {
714 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
715  stream << "\033[104m";
716 #elif defined(TERMCOLOR_USE_WINDOWS_API)
717  _internal::win_change_attributes(stream, -1,
718  BACKGROUND_BLUE | BACKGROUND_INTENSITY
719  );
720 #endif
721  }
722  return stream;
723  }
724 
725  inline
726  std::ostream& on_bright_magenta(std::ostream& stream)
727  {
728  if (_internal::is_colorized(stream))
729  {
730 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
731  stream << "\033[105m";
732 #elif defined(TERMCOLOR_USE_WINDOWS_API)
733  _internal::win_change_attributes(stream, -1,
734  BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY
735  );
736 #endif
737  }
738  return stream;
739  }
740 
741  inline
742  std::ostream& on_bright_cyan(std::ostream& stream)
743  {
744  if (_internal::is_colorized(stream))
745  {
746 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
747  stream << "\033[106m";
748 #elif defined(TERMCOLOR_USE_WINDOWS_API)
749  _internal::win_change_attributes(stream, -1,
750  BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY
751  );
752 #endif
753  }
754  return stream;
755  }
756 
757  inline
758  std::ostream& on_bright_white(std::ostream& stream)
759  {
760  if (_internal::is_colorized(stream))
761  {
762 #if defined(TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES)
763  stream << "\033[107m";
764 #elif defined(TERMCOLOR_USE_WINDOWS_API)
765  _internal::win_change_attributes(stream, -1,
766  BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY
767  );
768 #endif
769  }
770 
771  return stream;
772  }
773 
774 
775 
780  namespace _internal
781  {
782  // An index to be used to access a private storage of I/O streams. See
783  // colorize / nocolorize I/O manipulators for details. Due to the fact
784  // that static variables ain't shared between translation units, inline
785  // function with local static variable is used to do the trick and share
786  // the variable value between translation units.
787  inline int colorize_index()
788  {
789  static int colorize_index = std::ios_base::xalloc();
790  return colorize_index;
791  }
792 
796  inline
797  FILE* get_standard_stream(const std::ostream& stream)
798  {
799  if (&stream == &std::cout)
800  return stdout;
801  else if ((&stream == &std::cerr) || (&stream == &std::clog))
802  return stderr;
803 
804  return nullptr;
805  }
806 
807  // Say whether a given stream should be colorized or not. It's always
808  // true for ATTY streams and may be true for streams marked with
809  // colorize flag.
810  inline
811  bool is_colorized(std::ostream& stream)
812  {
813  return is_atty(stream) || static_cast<bool>(stream.iword(colorize_index()));
814  }
815 
818  inline
819  bool is_atty(const std::ostream& stream)
820  {
821  FILE* std_stream = get_standard_stream(stream);
822 
823  // Unfortunately, fileno() ends with segmentation fault
824  // if invalid file descriptor is passed. So we need to
825  // handle this case gracefully and assume it's not a tty
826  // if standard stream is not detected, and 0 is returned.
827  if (!std_stream)
828  return false;
829 
830 #if defined(TERMCOLOR_TARGET_POSIX)
831  return ::isatty(fileno(std_stream));
832 #elif defined(TERMCOLOR_TARGET_WINDOWS)
833  return ::_isatty(_fileno(std_stream));
834 #else
835  return false;
836 #endif
837  }
838 
839 #if defined(TERMCOLOR_TARGET_WINDOWS)
840  inline void win_change_attributes(std::ostream& stream, int foreground, int background)
843  {
844  // yeah, i know.. it's ugly, it's windows.
845  static WORD defaultAttributes = 0;
846 
847  // Windows doesn't have ANSI escape sequences and so we use special
848  // API to change Terminal output color. That means we can't
849  // manipulate colors by means of "std::stringstream" and hence
850  // should do nothing in this case.
851  if (!_internal::is_atty(stream))
852  return;
853 
854  // get terminal handle
855  HANDLE hTerminal = INVALID_HANDLE_VALUE;
856  if (&stream == &std::cout)
857  hTerminal = GetStdHandle(STD_OUTPUT_HANDLE);
858  else if (&stream == &std::cerr)
859  hTerminal = GetStdHandle(STD_ERROR_HANDLE);
860 
861  // save default terminal attributes if it unsaved
862  if (!defaultAttributes)
863  {
864  CONSOLE_SCREEN_BUFFER_INFO info;
865  if (!GetConsoleScreenBufferInfo(hTerminal, &info))
866  return;
867  defaultAttributes = info.wAttributes;
868  }
869 
870  // restore all default settings
871  if (foreground == -1 && background == -1)
872  {
873  SetConsoleTextAttribute(hTerminal, defaultAttributes);
874  return;
875  }
876 
877  // get current settings
878  CONSOLE_SCREEN_BUFFER_INFO info;
879  if (!GetConsoleScreenBufferInfo(hTerminal, &info))
880  return;
881 
882  if (foreground != -1)
883  {
884  info.wAttributes &= ~(info.wAttributes & 0x0F);
885  info.wAttributes |= static_cast<WORD>(foreground);
886  }
887 
888  if (background != -1)
889  {
890  info.wAttributes &= ~(info.wAttributes & 0xF0);
891  info.wAttributes |= static_cast<WORD>(background);
892  }
893 
894  SetConsoleTextAttribute(hTerminal, info.wAttributes);
895  }
896 #endif // TERMCOLOR_TARGET_WINDOWS
897 
898  } // namespace _internal
899 
900 } // namespace termcolor
901 
902 
903 #undef TERMCOLOR_TARGET_POSIX
904 #undef TERMCOLOR_TARGET_WINDOWS
905 
906 #if defined(TERMCOLOR_AUTODETECTED_IMPLEMENTATION)
907 # undef TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES
908 # undef TERMCOLOR_USE_WINDOWS_API
909 #endif
910 
911 #endif // TERMCOLOR_HPP_
io.h