This repository was archived by the owner on Jun 24, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathconsole_handler.c
More file actions
163 lines (123 loc) · 4.25 KB
/
console_handler.c
File metadata and controls
163 lines (123 loc) · 4.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#include <stdarg.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include "atomic_bridge.h"
#include "console_handler.h"
/* Use C++ for atomic */
static uint16_t last_line_y;
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void console_set_nextline_number(const uint16_t n) {
atomicb_store_explicit_u16(&last_line_y, n, memory_order_bridge_seq_cst);
}
void console_modify_nextline_number(const uint16_t n) {
atomicb_fetch_add_explicit_u16(&last_line_y, n, memory_order_bridge_seq_cst);
}
/* Prints to a single line with an option to clear */
int print_to_console_pos_internal(const COORD pos, const HANDLE to, const int clear, const char *message) {
if (!to || to == INVALID_HANDLE_VALUE) {
SetLastError(ERROR_INVALID_PARAMETER);
return -1;
}
if (pos.Y >= CONSOLE_MAX_CHARACTERS_LINE) {
return 0;
}
const size_t max = CONSOLE_MAX_CHARACTERS_LINE - pos.Y;
size_t len = strlen(message);
if (len > max) {
len = max;
}
CHAR_INFO writebuffer[CONSOLE_MAX_CHARACTERS_LINE];
memset(writebuffer, 0, sizeof(writebuffer));
for (size_t i = 0; i < len; ++i) {
CHAR_INFO *current = writebuffer + i;
current->Char.AsciiChar = message[i];
current->Attributes = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN;
}
if (clear) {
CHAR_INFO reference;
memset(&reference, 0, sizeof(reference));
reference.Char.AsciiChar = ' ';
reference.Attributes = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN;
for (size_t i = len; i < max; ++i) {
writebuffer[i] = reference;
}
len = max;
}
if (!len) {
return 0;
}
COORD buffer_size;
buffer_size.X = (SHORT)len;
buffer_size.Y = 1;
COORD buffer_coord;
memset(&buffer_coord, 0, sizeof(buffer_coord));
SMALL_RECT region;
region.Left = (SHORT)pos.X;
region.Top = region.Bottom = (SHORT)pos.Y;
region.Right = (SHORT)(pos.X + len);
const BOOL err = WriteConsoleOutput(to, writebuffer, buffer_size, buffer_coord, ®ion);
return err ? (int) len : -1;
}
static size_t split_message(const char *message, const char **buff, const char splitter, const size_t max) {
size_t i;
for (i = 0; i < max; ++i) {
const char *index = strchr(message, splitter);
if (!index) {
break;
}
const ptrdiff_t len = message - index;
char *line = (char *) malloc(len + 1);
if (!line) {
// TODO
}
memcpy(line, message, len);
line[len] = '\0';
buff[i] = line;
message = index + 1;
}
return i;
}
static void free_split_messages(const char **messages, size_t n) {
for (size_t i = 0; i < n; ++i) {
free((void *) messages[i]);
}
}
int print_to_console_pos(COORD pos, const char *message, const int clear) {
char *messages[CONSOLE_MAX_CHARACTERS_LINE];
const size_t lines = split_message(message, messages, '\n', sizeof(messages) / sizeof(*messages));
const HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
int ret = 0;
for (size_t i = 0; i < lines; ++i, ++pos.Y) {
const int r = print_to_console_pos_internal(pos, out, clear, messages[i]);
if (r < 0) {
return r;
}
ret += r;
}
return ret + (int) lines;
}
int print_to_console(const char *message, const int clear) {
char *messages[CONSOLE_MAX_CHARACTERS_LINE];
const size_t lines = split_message(message, messages, '\n', sizeof(messages) / sizeof(*messages));
const uint16_t start = atomicb_fetch_add_explicit_u16(&last_line_y, (uint16_t) lines, memory_order_bridge_seq_cst);
const HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos;
pos.X = 0;
pos.Y = start;
int ret = 0;
for (size_t i = 0; i < lines; ++i, ++pos.Y) {
const int r = print_to_console_pos_internal(pos, out, clear, messages[i]);
if (r < 0) {
return r;
}
ret += r;
}
return ret + (int) lines;
}
#ifdef __cplusplus
}
#endif /* __cplusplus */