Survival Royale 1.0.0
A very simple yet funny card game.
Loading...
Searching...
No Matches
ansi.c
Go to the documentation of this file.
1// Copyright (C) 2025 Giulio Salvi, Jacopo Paradisi
2//
3// This program is free software: you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation, either version 3 of the License, or
6// (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with this program. If not, see <https://www.gnu.org/licenses/>.
15
26
27#include "ansi.h"
28
29// BUILDERS section
30
32 rgb rgb = {
33 .r = 0,
34 .g = 0,
35 .b = 0
36 };
37
38 return rgb;
39}
40
42 ansiRgbColor c = {
43 .fgRgb = buildRgb(),
44 .bgRgb = buildRgb()
45 };
46
47 return c;
48}
49
52 .fgColor = NONE,
53 .bgColor = NONE
54 };
55
56 return c;
57}
58
60 color c = {
61 .isRgbColor = false,
62 .color = {
63 .stdColor = buildAnsiStandardColor()
64 }
65 };
66
67 return c;
68}
69
71 graphicRendition gr = {
72 .bold = false,
73 .italic = false,
74 .underlined = NONE,
75 .color = buildColor()
76 };
77
78 return gr;
79}
80
81//BUILDERS section end
82
83// UTILITY FUNCTIONS section
84
88
89 cursorPosition(1, 1);
90}
91
98
105
110
111void printGraphicRendition(char* text, graphicRendition rendition) {
112 if(rendition.bold)
113 bold();
114 if(rendition.italic)
115 italic();
116 if(rendition.underlined == 1)
117 underlined();
118 else if(rendition.underlined == 2)
120 if(rendition.color.isRgbColor)
121 setColor(rendition.color);
122
123 printf("%s", text);
124 graphicReset();
125}
126
127void printgr(const char* text) {
128 for(int i = 0; i < strlen(text); i++) {
129 if(text[i] == '#') {
130 int offset = 0;
131 if(containsFrom(text, '#', i + 1))
132 offset = offsetFromNext(text, '#', ++i);
133 else
134 continue;
135
136 errno = 0;
137 char* substr = substring(text, i, offset), *endptr;
138 int n = 0;
139
140 if(isDecimalDigit(text[i]))
141 n = strtol(substr, &endptr, 10);
142
143 if(offset == 0)
144 printf("#");
145 if(offset >= 8) { // rgb
146 int semicolonCount = count(substr, ';', 0);
147
148 if(semicolonCount == 3) { // valid rgb (#fg;r;g;b# or #bg;r;g;b#)
149 int semicolonOffset = offsetFromNext(text, ';', i) - 1;
150
151 if(semicolonOffset != 1)
152 continue;
153
154 char* str = substring(text, i, 2);
155 bool fg = strcmp("fg", str) == 0;
156 free(str);
157 i += 3;
158 rgb rgb = buildRgb();
159
160 for(int j = 0; j <= 2; j++) {
161 semicolonOffset = j == 2 ? offsetFromNext(text, '#', i) - 1 : offsetFromNext(text, ';', i);
162
163 errno = 0;
164 char* v = substring(text, i, semicolonOffset), *endptr_;
165 int n = strtol(v, &endptr_, 10);
166 free(v);
167 if(errno == ERANGE || *endptr_ != '\0' && endptr_ == NULL)
168 break;
169
170 if(j == 0)
171 rgb.r = n;
172 else if(j == 1)
173 rgb.g = n;
174 else if(j == 2)
175 rgb.b = n;
176
177 i += j == 2 ? semicolonOffset : semicolonOffset + 1;
178 }
179
180 if(fg)
182 else
184 }
185 } else if((n >= 30 && n <= 37) || (n >= 90 && n <= 97) || (n >= 40 && n <= 47) || (n >= 100 && n <= 107)) { // standard
186 if((n >= 30 && n <= 37) || (n >= 90 && n <= 97)) {
188 i += offset;
189 } else if((n >= 40 && n <= 47) || (n >= 100 && n <= 107)) {
191 i += offset;
192 }
193 } else if(strcmp(substr, "b") == 0) {
194 i++;
195 bold();
196 } else if(strcmp(substr, "i") == 0) {
197 i++;
198 italic();
199 } else if(strcmp(substr, "u") == 0) {
200 i++;
201 underlined();
202 } else if(strcmp(substr, "du") == 0) {
203 i += 2;
205 } else if(strcmp(substr, "bl") == 0) {
206 i += 2;
207 slowBlinking();
208 } else if(strcmp(substr, "r") == 0) {
209 i++;
210 graphicReset();
211 }
212
213 free(substr);
214 } else
215 printf("%c", text[i]);
216
217
218 fflush(stdout);
219 }
220}
221
222void printfgr(char* text, ...) {
223 va_list args;
224 va_start(args, text);
225
226 vector* t = buildVector();
227
228 for(int i = 0; i < strlen(text); i++) {
229 if(text[i] != '%')
230 pushBack(t, text[i]);
231 else {
232 i++;
233
234 if(text[i] == '%')
235 pushBack(t, '%');
236 else if(text[i] == 'd' || text[i] == 'i' || text[i] == 'u' || text[i] == 'x' || text[i] == 'X') {
237 int n = va_arg(args, int), snLen = nDigits(n) + 2;
238 char* sn = (char*)malloc(snLen*sizeof(char));
239 if(sn == NULL)
240 exit(EXIT_ALLOC_FAILURE);
241
242 snprintf(sn, snLen, "%d", n);
243
244 for(int j = 0; j < strlen(sn); j++)
245 pushBack(t, sn[j]);
246
247 free(sn);
248 } else if(text[i] == 'f' || text[i] == 'F') {
249 double n = va_arg(args, double);
250 char format[16];
251 snprintf(format, 16, "%%.%df", NUMBER_DECIMALS_DIGITS);
252
253 int snLen = NUMBER_DECIMALS_DIGITS + nDigits(floor(n)) + 3;
254 char* sn = (char*)malloc(snLen*sizeof(char));
255 if(sn == NULL)
256 exit(EXIT_ALLOC_FAILURE);
257
258 snprintf(sn, snLen, format, n);
259
260 for(int j = 0; j < strlen(sn); j++)
261 pushBack(t, sn[j]);
262
263 free(sn);
264 } else if(text[i] == 's') {
265 char* s = va_arg(args, char*);
266
267 for(int j = 0; j < strlen(s); j++)
268 pushBack(t, *(s + j));
269
270 } else if(text[i] == 'n')
271 ;
272 }
273 }
274
275 pushBack(t, '\0');
276 printgr(t->data);
277
278 freeVector(t);
279}
280
281char getChar() {
282 fflush(stdin);
283
284 #ifndef _WIN32
285 struct termios term;
286 tcgetattr(STDIN_FILENO, &term);
287
288 term.c_lflag &= ~(ICANON | ECHO);
289 tcsetattr(STDIN_FILENO, TCSANOW, &term);
290
291 char c;
292 int rs = read(STDIN_FILENO, &c, 1);
293
294 tcgetattr(STDIN_FILENO, &term);
295
296 term.c_lflag |= (ICANON | ECHO);
297 tcsetattr(STDIN_FILENO, TCSANOW, &term);
298
299 return rs == 1 ? c : -1;
300 #else
301 return getch();
302 #endif
303}
304
305void Pause(bool clear) {
306 getChar();
307
308 if(clear)
309 clearScreen();
310}
311
312void screenSize(int* width, int* height) {
313 #ifndef _WIN32
314 struct winsize ws;
315
316 if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) {
317 *width = ws.ws_col;
318 *height = ws.ws_row;
319 } else {
320 *width = -1;
321 *height = -1;
322 }
323 #else
324 CONSOLE_SCREEN_BUFFER_INFO csbi;
325 HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
326
327 if (GetConsoleScreenBufferInfo(hStdout, &csbi)) {
328 *width = csbi.dwSize.X;
329 *height = csbi.dwSize.Y;
330 }
331
332 CloseHandle(hStdout);
333 #endif
334}
335
336// UTILITY FUNCTIONS section end
337
338// CSI section
339
340void cursorUp(int n) {
341 if(n <= 0)
342 return;
343
344 printf("\e[%dA", n);
345}
346
347void cursorDown(int n) {
348 if(n <= 0)
349 return;
350
351 printf("\e[%dB", n);
352}
353
354void cursorForward(int n) {
355 if(n <= 0)
356 return;
357
358 printf("\e[%dC", n);
359}
360
361void cursorBack(int n) {
362 if(n <= 0)
363 return;
364
365 printf("\e[%dD", n);
366}
367
368void cursorNextLine(int n) {
369 if(n <= 0)
370 return;
371
372 printf("\e[%dE", n);
373}
374
376 if(n <= 0)
377 return;
378
379 printf("\e[%dF", n);
380}
381
383 if(n <= 0)
384 return;
385
386 printf("\e[%dG", n);
387}
388
389void cursorPosition(int n, int m) {
390 if(n <= 0)
391 return;
392 if(m <= 0)
393 return;
394
395 printf("\e[%d;%dH", n, m);
396}
397
398void eraseInDisplay(int n) {
399 if(n < 0 || n > 3)
400 return;
401
402 printf("\e[%dJ", n);
403}
404
405void eraseInLine(int n) {
406 if(n < 0 || n > 2)
407 return;
408
409 printf("\e[%dK", n);
410}
411
412void scrollUp(int n) {
413 if(n <= 0)
414 return;
415
416 printf("\e[%dS", n);
417}
418
419void scrollDown(int n) {
420 if(n <= 0)
421 return;
422
423 printf("\e[%dT", n);
424}
425
426void deviceStatusReport(int* row, int* col) {
427 #ifndef _WIN32
428 printgr("\e[6n");
429 int _ = scanf("\e[%d;%dR", row, col);
430 #else
431 CONSOLE_SCREEN_BUFFER_INFO csbi;
432 HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
433
434 if (GetConsoleScreenBufferInfo(hStdout, &csbi)) {
435 *col = csbi.dwCursorPosition.X + 1;
436 *row = csbi.dwCursorPosition.Y + 1;
437 }
438
439 CloseHandle(hStdout);
440 #endif
441}
442
443// CSI section end
444
445// SGR section
446
448 printf("\e[0m");
449}
450
451void bold() {
452 printf("\e[1m");
453}
454
455void italic() {
456 printf("\e[3m");
457}
458
460 printf("\e[4m");
461}
462
464 printf("\e[5m");
465}
466
468 printf("\e[21m");
469}
470
472 printf("\e[%dm", (int)foregroundColor);
473}
474
476 printf("\e[38;2;%d;%d;%dm", rgbColor.r, rgbColor.g, rgbColor.b);
477}
478
480 printf("\e[39m");
481}
482
484 printf("\e[%dm", (int)backgroundColor);
485}
486
488 printf("\e[48;2;%d;%d;%dm", rgbColor.r, rgbColor.g, rgbColor.b);
489}
490
492 printf("\e[49m");
493}
494
495// SGR section end
void underlined()
Toggles singled underlined text.
Definition ansi.c:459
rgb buildRgb()
Builds a rgb struct.
Definition ansi.c:31
void Pause(bool clear)
Waits for the user to press a key without waiting for 'Enter' to be pressed.
Definition ansi.c:305
void cursorDown(int n)
Moves the cursor down by n rows.
Definition ansi.c:347
void printgr(const char *text)
Prints a text with the graphic rendition specified with custom graphic rendition format specifiers.
Definition ansi.c:127
void setColor(color color)
Sets both terminal's foreground color and background color, if specified.
Definition ansi.c:106
void eraseInDisplay(int n)
Clears part of the screen.
Definition ansi.c:398
void setForegroundColor(color color)
Sets the terminal's foreground color.
Definition ansi.c:92
void setRGBBackgroundColor(rgb rgbColor)
Sets the RGB background color.
Definition ansi.c:487
void deviceStatusReport(int *row, int *col)
Gets the cursor position.
Definition ansi.c:426
void printGraphicRendition(char *text, graphicRendition rendition)
Prints a text with the graphic rendition specified with the struct. Standard C format specifiers are ...
Definition ansi.c:111
void defaultBackgroundColor()
Resets the background color.
Definition ansi.c:491
void eraseInLine(int n)
Erases part of the line.
Definition ansi.c:405
void graphicReset()
Resets the graphic rendition.
Definition ansi.c:447
void bold()
Toggles bold text.
Definition ansi.c:451
ansiStandardColor buildAnsiStandardColor()
Builds a ANSI standard color struct.
Definition ansi.c:50
ansiRgbColor buildAnsiRgbColor()
Builds a ANSI rgb color struct.
Definition ansi.c:41
void defaultForegroundColor()
Resets the foreground color.
Definition ansi.c:479
void cursorUp(int n)
Moves the cursor up by n rows.
Definition ansi.c:340
void scrollDown(int n)
Scrolls the whole page down by n rows.
Definition ansi.c:419
void doublyUnderlined()
Toggles doubly underlined text.
Definition ansi.c:467
void cursorHorizontalAbsolute(int n)
Moves the cursor to column n.
Definition ansi.c:382
void cursorPosition(int n, int m)
Moves the cursor at n-th row and at the m-th column.
Definition ansi.c:389
void screenSize(int *width, int *height)
It returns the width and the height of the screen. On unix-like platforms, in case of errors,...
Definition ansi.c:312
char getChar()
Gets the char pressed on the keyboard without waiting for 'Enter' to be pressed.
Definition ansi.c:281
void setRGBForegroundColor(rgb rgbColor)
Sets the RGB foreground color.
Definition ansi.c:475
void clearScreen()
Clears the entire terminal's window's content.
Definition ansi.c:85
graphicRendition buildGraphicRendition()
Builds a graphic rendition struct.
Definition ansi.c:70
void cursorBack(int n)
Moves the cursor to the left by n columns.
Definition ansi.c:361
void italic()
Toggles italic text.
Definition ansi.c:455
void setBackgroundColor(color color)
Sets the terminal's background color.
Definition ansi.c:99
void cursorPreviousLine(int n)
Moves the cursor at the beginning of the line n rows up.
Definition ansi.c:375
void setStandardForegroundColor(ansiStandardColors foregroundColor)
Sets the ANSI standard foreground color.
Definition ansi.c:471
void scrollUp(int n)
Scrolls the whole page up by n rows.
Definition ansi.c:412
void setStandardBackgroundColor(ansiStandardColors backgroundColor)
Sets the ANSI standard background color.
Definition ansi.c:483
void slowBlinking()
Toggles slow blinking.
Definition ansi.c:463
color buildColor()
Builds a color struct.
Definition ansi.c:59
void printfgr(char *text,...)
Prints text as printgr but handles standard C format specifiers %, d, i, u, x, X, f,...
Definition ansi.c:222
void cursorNextLine(int n)
Moves the cursor at the beginning of the line n rows down.
Definition ansi.c:368
void cursorForward(int n)
Moves the cursor to the right by n columns.
Definition ansi.c:354
Implemented following https://en.wikipedia.org/wiki/ANSI_escape_code.
#define NUMBER_DECIMALS_DIGITS
Defines how many decimals digits should use printfgr when printing floating-point numbers....
Definition ansi.h:35
uint8_t ansiStandardColors
Defines the type ansiStandardColors as unsigned integer 1 byte large.
Definition ansi.h:40
#define EXIT_ALLOC_FAILURE
Exit code when dynamic memory allocation fails.
Definition consts.h:22
#define NONE
Used in some structure for meaning that a field is unset, instead of using NULL.
Definition includes.h:22
Defines a basic structure for RGB foreground color and background color for a piece of printable text...
Definition ansi.h:61
rgb bgRgb
Background RGB color field.
Definition ansi.h:65
rgb fgRgb
Foreground RGB color field.
Definition ansi.h:63
Defines a basic structure for standard ANSI foreground color and background color for a piece of prin...
Definition ansi.h:53
ansiStandardColors fgColor
Foreground ANSI standard color field.
Definition ansi.h:55
ansiStandardColors bgColor
Background ANSI standard color field.
Definition ansi.h:57
Defines a struct for representing a generic color.
Definition ansi.h:77
__color color
Color field.
Definition ansi.h:81
bool isRgbColor
Boolean flag for determining if the color field is an ansiRgbColor or an ansiStandardColor.
Definition ansi.h:79
Defines a struct for graphic rendition including properties for bold, italic, underlined and colored ...
Definition ansi.h:85
bool bold
Boolean flag to determine if the text has to be bold.
Definition ansi.h:87
color color
The color for the text and the its background.
Definition ansi.h:93
underline underlined
Flag to determine if the text has to be underlined, singly or doubly.
Definition ansi.h:91
bool italic
Boolean flag to determine if the text has to be italic.
Definition ansi.h:89
Defines a basic structure for RGB colors.
Definition ansi.h:43
uint8_t g
Green component field.
Definition ansi.h:47
uint8_t b
Blue component field.
Definition ansi.h:49
uint8_t r
Red component field.
Definition ansi.h:45
The vector structure.
Definition vector.h:39
data_type * data
Contiguous memory segment with in data is stored.
Definition vector.h:45
ansiRgbColor rgbColor
RGB color field.
Definition ansi.h:71
ansiStandardColor stdColor
ANSI standard color field.
Definition ansi.h:73
bool containsFrom(const char *string, char character, int startPosition)
Checks if there is an occoruncy of the passed char from the passed position in the passed string.
Definition utility.c:63
int count(const char *string, char character, int startPosition)
Counts the number of occoruncies in the string, from a passed position, of the passed char.
Definition utility.c:50
bool isDecimalDigit(char character)
Checks if a char is a decimal digit.
Definition utility.c:97
int offsetFromNext(const char *string, char character, int startPosition)
Counts the offset in the string between the position and the next occoruncy of the passed char.
Definition utility.c:38
int nDigits(int number)
Evalutates the number of digits of a number. The time complexity of this function is constant (O(1)).
Definition utility.c:138
char * substring(const char *string, int startPosition, int length)
Copies a substring (heap-allocated) from the passed string. If fails when allocating memory for the s...
Definition utility.c:23
void freeVector(vector *const vector)
Frees the memory used from the vector structure.
Definition vector.c:43
vector * buildVector()
Builds a vector structure initializing its fields. If vector's allocation or data's block allocation ...
Definition vector.c:23
void pushBack(vector *const vector, const data_type element)
Pushes an element at the back of the vector.
Definition vector.c:63