gwion-util
utilities for the Gwion project
Loading...
Searching...
No Matches
Macros | Enumerations | Functions | Variables
termcolor.c File Reference
#include "termcolor.h"
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>

Go to the source code of this file.

Macros

#define __APPEND(c)
 

Enumerations

enum  _termcolor_internal_color {
  _termcolor_internal_color_BOLD = 1 << 1 , _termcolor_internal_color_FANT = 1 << 2 , _termcolor_internal_color_UNDR = 1 << 3 , _termcolor_internal_color_BLNK = 1 << 4 ,
  _termcolor_internal_color_STRK = 1 << 5 , _termcolor_internal_color_ITLC = 1 << 6
}
 

Functions

const char * tcol_errorstr (const enum term_color_error_t err)
 
bool tcol_has_color (void)
 
void tcol_override_color_checks (bool enable_color)
 
int _termcolor_internal_lookup (const char color_name)
 
int _tcol_color_generate (char *dst, size_t dstn, size_t *len, int rep, int foreground, int background)
 
int tcol_color_parse (char *dst, size_t dstn, char color[16], size_t k, size_t *len)
 
static int tcol_fmt_parse (char *dst, size_t dstn, const char *src, size_t srcn)
 
static int tcol_vsnprintf (char *stream, size_t N, const char *fmt, va_list ap)
 
static int tcol_vfprintf (FILE *stream, const char *fmt, va_list ap)
 
int tcol_fprintf (FILE *stream, const char *fmt,...)
 
int tcol_printf (const char *fmt,...)
 
int tcol_snprintf (char *stream, size_t N, const char *fmt,...)
 

Variables

static bool use_color = true
 
const char * tcol_errorstrs [TERM_COLOR_ERROR_COUNT]
 

Macro Definition Documentation

◆ __APPEND

#define __APPEND ( c)
Value:
do { \
dst[j++] = (c); \
if (j >= dstn) return TermColorErrorNone; \
} while (0)
@ TermColorErrorNone
Definition termcolor.h:39

Enumeration Type Documentation

◆ _termcolor_internal_color

Enumerator
_termcolor_internal_color_BOLD 
_termcolor_internal_color_FANT 
_termcolor_internal_color_UNDR 
_termcolor_internal_color_BLNK 
_termcolor_internal_color_STRK 
_termcolor_internal_color_ITLC 

Definition at line 67 of file termcolor.c.

67 {
74};
@ _termcolor_internal_color_FANT
Definition termcolor.c:69
@ _termcolor_internal_color_BOLD
Definition termcolor.c:68
@ _termcolor_internal_color_UNDR
Definition termcolor.c:70
@ _termcolor_internal_color_STRK
Definition termcolor.c:72
@ _termcolor_internal_color_BLNK
Definition termcolor.c:71
@ _termcolor_internal_color_ITLC
Definition termcolor.c:73

Function Documentation

◆ _tcol_color_generate()

int _tcol_color_generate ( char * dst,
size_t dstn,
size_t * len,
int rep,
int foreground,
int background )

Definition at line 76 of file termcolor.c.

77 {
78 /* Much of the code here was informed by the following gist:
79 https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797 */
80
81 size_t j = 0;
82
83 /* This macro checks to make sure we don't overrun the buffer when we add
84 a new character, */
85 #define __APPEND(c) do { \
86 dst[j++] = (c); \
87 if (j >= dstn) return TermColorErrorNone; \
88 } while (0)
89
90 /* Every escape code begins with "\e[" */
91 __APPEND('\033');
92 __APPEND('[');
93
94 /* Add the appropriate parameters to our escape sequence depending on the
95 flags set in rep(resentation). */
97 __APPEND('1');
98 __APPEND(';');
99 }
101 __APPEND('2');
102 __APPEND(';');
103 }
105 __APPEND('3');
106 __APPEND(';');
107 }
109 __APPEND('4');
110 __APPEND(';');
111 }
113 __APPEND('5');
114 __APPEND(';');
115 }
117 __APPEND('9');
118 __APPEND(';');
119 }
120
121 /* If foreground and background colors were provided, snprintf them to dst. */
122 if (foreground != -1) {
123 j += snprintf(dst + j, dstn - j, "%d;", foreground);
124 if (j >= dstn) return TermColorErrorNone;
125 }
126 if (background != -1) {
127 j += snprintf(dst + j, dstn - j, "%d;", background + 10);
128 if (j >= dstn) return TermColorErrorNone;
129 }
130
131 if (dst[j - 1] == ';') {
132 j--;
133 }
134
135 /* Graphics mode escape sequences end with 'm' */
136 __APPEND('m');
137
138 *len = j;
139 return TermColorErrorNone;
140}
#define __APPEND(c)

◆ _termcolor_internal_lookup()

int _termcolor_internal_lookup ( const char color_name)

Definition at line 44 of file termcolor.c.

44 {
45 switch (color_name) {
46 case 'N':
47 return 30;
48 case 'R':
49 return 31;
50 case 'G':
51 return 32;
52 case 'Y':
53 return 33;
54 case 'B':
55 return 34;
56 case 'M':
57 return 35;
58 case 'C':
59 return 36;
60 case 'W':
61 return 37;
62 default:
63 return -1;
64 }
65}

◆ tcol_color_parse()

int tcol_color_parse ( char * dst,
size_t dstn,
char color[16],
size_t k,
size_t * len )

Definition at line 142 of file termcolor.c.

143 {
144 if (!use_color) {
145 *len = 0;
146 return TermColorErrorNone;
147 }
148
149 /* '0' signifies no color, i.e. a reset */
150 if (k == 1 && *color == '0') {
151 size_t j = 0;
152 __APPEND('\033');
153 __APPEND('[');
154 __APPEND('m');
155 *len = j;
156 return TermColorErrorNone;
157 }
158
159 /* As -1 they are ignored. Otherwise they are set to the foreground color
160 code. The backround code is later added 10 to. */
161 int foreground = -1;
162 int background = -1;
163
164 enum _termcolor_internal_color rep = 0;
165 size_t i;
166 for (i = 0; i < k; i++) {
167 switch (color[i]) {
168 /* Farily straightforward; just sets the flags corresponding to the
169 color attributes. */
170 case '+':
172 break;
173 case '-':
175 break;
176 case '_':
178 break;
179 case '*':
181 break;
182 case '~':
184 break;
185 case '/':
187 break;
188
189 /* Here we take the character after the ',' and use that as our
190 background color code, like Nano does. */
191 case ',': {
192 if (i + 1 >= k) {
194 }
195 const int result = _termcolor_internal_lookup(color[i + 1]);
196 if (result == -1) {
198 }
199 background = result;
200 i++;
201 break;
202 }
203 default: {
204 /* If we haven't matched anything, we assume its a foreground
205 color. Make sure it is and error if not. */
206 const int result = _termcolor_internal_lookup(color[i]);
207 if (result != -1) {
208 foreground = result;
209 break;
210 }
212 }
213 }
214 }
215
216 return _tcol_color_generate(dst, dstn, len, rep, foreground, background);
217}
int _tcol_color_generate(char *dst, size_t dstn, size_t *len, int rep, int foreground, int background)
Definition termcolor.c:76
_termcolor_internal_color
Definition termcolor.c:67
static bool use_color
Definition termcolor.c:22
int _termcolor_internal_lookup(const char color_name)
Definition termcolor.c:44
@ TermColorErrorInvalidColor
Definition termcolor.h:42

◆ tcol_errorstr()

const char * tcol_errorstr ( const enum term_color_error_t err)
inline

Definition at line 32 of file termcolor.c.

32 {
33 return tcol_errorstrs[err];
34}
const char * tcol_errorstrs[TERM_COLOR_ERROR_COUNT]
Definition termcolor.c:24

◆ tcol_fmt_parse()

static int tcol_fmt_parse ( char * dst,
size_t dstn,
const char * src,
size_t srcn )
inlinestatic

Definition at line 219 of file termcolor.c.

220 {
221 /* Variables:
222 i = index in source
223 j = index in destination
224
225 1. We loop throughout the source until we reach the end or until we
226 cannot write into dst anymore. */
227 if (dstn == 0) {
228 return TermColorErrorNone;
229 }
230 size_t j = 0, i;
231 dstn--;
232 for (i = 0; i < srcn && j < dstn; i++) {
233 loop_top:
234 /* 2. We check if the current character is '{'. */
235 if (src[i] == '{') {
236 /* 3.B. If it is, we make sure it's not escaped with "{{". */
237 if (i + 1 < srcn && src[i + 1] == '{') {
238 i++;
239 dst[j++] = '{';
240 } else {
241 i++;
242
243 /* 4. If not escape, we obtain the color and parse it. */
244 char color[16];
245 int k = 0;
246 while (i < srcn && src[i] != '}') {
247 /* Allow spaces in the color */
248 if (src[i] == ' ') {
249 i++;
250 if (src[i] == '}') {
251 i++;
252 /* If the color is all spaces, ignore it. */
253 goto loop_top;
254 }
255 continue;
256 }
257
258 /* Copy over the contents of the source to the color buffer. */
259 color[k++] = src[i++];
260
261 /* Make sure no bounds are overrun. */
262 if (k > 16) {
264 }
265 }
266
267 /* Confirm we ended on a right bracket */
268 if (src[i] != '}') {
270 }
271
272 /* Create the escape sequence. */
273 size_t len = 0;
274 int status = tcol_color_parse(dst + j, dstn - j, color, k,
275 &len);
276 if (status != TermColorErrorNone) {
277 return status;
278 }
279 j += len;
280 }
281 } else {
282 /* 3.A. If not, just write the character to the destination to
283 copy verbatim. */
284 dst[j++] = src[i];
285 }
286 }
287 dst[dstn] = 0;
288 dst[j] = 0;
289 return TermColorErrorNone;
290}
int tcol_color_parse(char *dst, size_t dstn, char color[16], size_t k, size_t *len)
Definition termcolor.c:142
@ TermColorErrorUnterminatedColor
Definition termcolor.h:43

◆ tcol_fprintf()

int tcol_fprintf ( FILE * stream,
const char * fmt,
... )

Definition at line 365 of file termcolor.c.

365 {
366 va_list ap;
367 va_start(ap, fmt);
368 const int status = tcol_vfprintf(stream, fmt, ap);
369 va_end(ap);
370 return status;
371}
char const char * fmt
Definition gwion_print.h:2
static int tcol_vfprintf(FILE *stream, const char *fmt, va_list ap)
Definition termcolor.c:324

◆ tcol_has_color()

bool tcol_has_color ( void )

Definition at line 36 of file termcolor.c.

36 {
37 return use_color;
38}

◆ tcol_override_color_checks()

void tcol_override_color_checks ( bool enable_color)

Definition at line 40 of file termcolor.c.

40 {
41 use_color = enable_color;
42}

◆ tcol_printf()

int tcol_printf ( const char * fmt,
... )

Definition at line 373 of file termcolor.c.

373 {
374 va_list ap;
375 va_start(ap, fmt);
376 const int status = tcol_vfprintf(stdout, fmt, ap);
377 va_end(ap);
378 return status;
379}

◆ tcol_snprintf()

int tcol_snprintf ( char * stream,
size_t N,
const char * fmt,
... )

Definition at line 382 of file termcolor.c.

382 {
383 va_list ap;
384 va_start(ap, fmt);
385 const int status = tcol_vsnprintf(stream, N, fmt, ap);
386 va_end(ap);
387 return status;
388}
static int tcol_vsnprintf(char *stream, size_t N, const char *fmt, va_list ap)
Definition termcolor.c:292

◆ tcol_vfprintf()

static int tcol_vfprintf ( FILE * stream,
const char * fmt,
va_list ap )
inlinestatic

Definition at line 324 of file termcolor.c.

324 {
325 /* Gets the length of the format string and calculates a length for the new
326 format string to be created. */
327 const size_t l = strlen(fmt);
328 const size_t n = l * 2 + 16;
329
330 /* Allocates and produces the new format string. */
331 char *buffer = malloc(n);
332 if (buffer == NULL) {
334 }
335 const int status = tcol_fmt_parse(buffer, n, fmt, l);
336 if (status != TermColorErrorNone) {
337 free(buffer);
338 return status;
339 }
340 #ifdef TERMCOLOR_OS_WIN
341 HANDLE output = GetStdHandle(STD_OUTPUT_HANDLE); /* Console Output */
342 DWORD mode;
343 GetConsoleMode(output, &mode);
344 mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; /* Process ANSI Escape */
345 mode |= ENABLE_PROCESSED_OUTPUT; /* Process ASCII Escape */
346 WINBOOL set = !SetConsoleMode(output, mode);
347 if (set) { /* If we could not set the console mode, we cannot print it */
349 }
350 #endif
351 /* Perform the printf itself. */
352 if (vfprintf(stream, buffer, ap) < 0) {
353 free(buffer);
355 }
356
357 /* Cleanup resources. */
358 free(buffer);
359
360 return TermColorErrorNone;
361}
static int tcol_fmt_parse(char *dst, size_t dstn, const char *src, size_t srcn)
Definition termcolor.c:219
@ TermColorErrorAllocationFailed
Definition termcolor.h:40
@ TermColorErrorPrintingFailed
Definition termcolor.h:41

◆ tcol_vsnprintf()

static int tcol_vsnprintf ( char * stream,
size_t N,
const char * fmt,
va_list ap )
inlinestatic

Definition at line 292 of file termcolor.c.

293 {
294 /* Gets the length of the format string and calculates a length for the new
295 format string to be created. */
296 const size_t l = strlen(fmt);
297 const size_t n = l * 2 + 16;
298
299 /* Allocates and produces the new format string. */
300 char *buffer = malloc(n);
301 if (buffer == NULL) {
303 }
304 const int status = tcol_fmt_parse(buffer, n, fmt, l);
305 if (status != TermColorErrorNone) {
306 free(buffer);
307 return status;
308 }
309
310 /* Perform the snprintf itself. */
311 if (vsnprintf(stream, N, buffer, ap) < 0) {
312 free(buffer);
314 }
315
316 /* Cleanup resources. */
317 free(buffer);
318
319 return TermColorErrorNone;
320}

Variable Documentation

◆ tcol_errorstrs

const char* tcol_errorstrs[TERM_COLOR_ERROR_COUNT]
Initial value:
= {
"Success",
"Virtual memory exhausted",
"Printing failed",
"Invalid color provided",
"Color was not terminated with '}'"
}

Definition at line 24 of file termcolor.c.

24 {
25 "Success",
26 "Virtual memory exhausted",
27 "Printing failed",
28 "Invalid color provided",
29 "Color was not terminated with '}'"
30};

◆ use_color

bool use_color = true
static

Definition at line 22 of file termcolor.c.