GCC Code Coverage Report


Directory: src/gate/
File: src/gate/system/terminals.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 97 455 21.3%
Functions: 15 67 22.4%
Branches: 14 154 9.1%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, Stefan Meislinger |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/system/terminals.h"
30 #include "gate/platforms.h"
31 #include "gate/atomics.h"
32 #include "gate/results.h"
33 #include "gate/debugging.h"
34 #include "gate/inputs.h"
35
36 #if defined(GATE_SYS_WIN) && !defined(GATE_SYS_WIN16)
37 # define GATE_SYSTEM_TERMINALS_WINAPI 1
38 #elif defined(GATE_SYS_POSIX)
39 # define GATE_SYSTEM_TERMINALS_POSIX 1
40 #elif defined(GATE_SYS_DOS)
41 # define GATE_SYSTEM_TERMINALS_DOS 1
42 #elif defined(GATE_SYS_EFI)
43 # define GATE_SYSTEM_TERMINALS_EFI 1
44 #else
45 # define GATE_SYSTEM_TERMINALS_NOIMPL 1
46 #endif
47
48
49 /* generic definitions and implementations */
50
51 static void gate_terminal_console_release(void* thisptr);
52 static int gate_terminal_console_retain(void* thisptr);
53 static char const* gate_terminal_console_get_interface_name(void* thisptr);
54
55 static gate_result_t gate_terminal_console_read(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned);
56 static gate_result_t gate_terminal_console_peek(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned);
57 static gate_result_t gate_terminal_console_write(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written);
58 static gate_result_t gate_terminal_console_flush(void* thisptr);
59
60 static gate_result_t gate_terminal_console_get_resource(void* thisptr, gate_uint32_t resource_type, gate_uintptr_t* resource);
61
62 static gate_result_t gate_terminal_console_await_char(void* thisptr, gate_uint32_t timeout_ms);
63 static gate_result_t gate_terminal_console_read_char(void* thisptr, gate_char32_t* ptr_char);
64 static gate_result_t gate_terminal_console_write_err(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written);
65 static gate_result_t gate_terminal_console_flush_err(void* thisptr);
66
67 static gate_result_t gate_terminal_console_get_type(void* thisptr);
68 static gate_result_t gate_terminal_console_get_size(void* thisptr, gate_uint16_t* ptr_width, gate_uint16_t* ptr_height);
69 static gate_result_t gate_terminal_console_get_cursor_pos(void* thisptr, gate_uint16_t* ptr_x, gate_uint16_t* ptr_y);
70 static gate_result_t gate_terminal_console_set_cursor_pos(void* thisptr, gate_uint16_t x, gate_uint16_t y);
71 static gate_result_t gate_terminal_console_set_cursor_mode(void* thisptr, gate_uint16_t mode);
72 static gate_result_t gate_terminal_console_clear(void* thisptr);
73
74 static gate_result_t gate_terminal_console_get_text_color(void* thisptr, gate_uint8_t* ptr_color_code);
75 static gate_result_t gate_terminal_console_set_text_color(void* thisptr, gate_uint8_t color_code);
76
77 static gate_result_t gate_terminal_console_get_back_color(void* thisptr, gate_uint8_t* ptr_color_code);
78 static gate_result_t gate_terminal_console_set_back_color(void* thisptr, gate_uint8_t color_code);
79
80
81 static GATE_INTERFACE_VTBL(gate_terminal) gate_terminal_console_vtbl;
82 2 static void gate_init_terminal_console_vtbl()
83 {
84
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (!gate_terminal_console_vtbl.get_interface_name)
85 {
86 GATE_INTERFACE_VTBL(gate_terminal) const local_vtbl =
87 {
88 &gate_terminal_console_get_interface_name,
89 &gate_terminal_console_release,
90 &gate_terminal_console_retain,
91
92 &gate_terminal_console_read,
93 &gate_terminal_console_peek,
94 &gate_terminal_console_write,
95 &gate_terminal_console_flush,
96
97 &gate_terminal_console_get_resource,
98
99 &gate_terminal_console_await_char,
100 &gate_terminal_console_read_char,
101 &gate_terminal_console_write_err,
102 &gate_terminal_console_flush_err,
103
104 &gate_terminal_console_get_type,
105 &gate_terminal_console_get_size,
106 &gate_terminal_console_get_cursor_pos,
107 &gate_terminal_console_set_cursor_pos,
108 &gate_terminal_console_set_cursor_mode,
109 &gate_terminal_console_clear,
110
111 &gate_terminal_console_get_text_color,
112 &gate_terminal_console_set_text_color,
113
114 &gate_terminal_console_get_back_color,
115 &gate_terminal_console_set_back_color
116 };
117 1 gate_terminal_console_vtbl = local_vtbl;
118 }
119 2 }
120
121
122
123 static gate_result_t gate_terminal_vt100_set_cursor_pos(void* thisptr, gate_uint16_t x, gate_uint16_t y)
124 {
125 char buffer[128];
126 static gate_size_t len = sizeof(buffer) - 1;
127 gate_size_t used = 0;
128 ++x;
129 ++y;
130
131 used += gate_str_print_text(&buffer[used], len - used, "\x1b[", 2);
132 used += gate_str_print_uint16(&buffer[used], len - used, y);
133 used += gate_str_print_text(&buffer[used], len - used, ";", 1);
134 used += gate_str_print_uint16(&buffer[used], len - used, x);
135 used += gate_str_print_text(&buffer[used], len - used, "H", 1);
136
137 return gate_terminal_console_write(thisptr, buffer, used, NULL);
138 }
139 static gate_result_t gate_terminal_vt100_clear(void* thisptr)
140 {
141 #define cmd_clear "\x1b[0;40;37m\x1b[1;1H\x1b[2J"
142 gate_size_t const cmd_clear_size = gate_str_length(cmd_clear);
143
144 return gate_terminal_console_write(thisptr, cmd_clear, cmd_clear_size, NULL);
145 }
146
147 8 static gate_result_t gate_terminal_get_text_color_code(int color_type, int* color_code, int* attr_code)
148 {
149
1/17
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
8 switch (color_type)
150 {
151 case GATE_TERMINAL_COLOR_BLACK: *color_code = 30; *attr_code = 0; break;
152 case GATE_TERMINAL_COLOR_BLUE: *color_code = 34; *attr_code = 0; break;
153 case GATE_TERMINAL_COLOR_GREEN: *color_code = 32; *attr_code = 0; break;
154 case GATE_TERMINAL_COLOR_CYAN: *color_code = 36; *attr_code = 0; break;
155 case GATE_TERMINAL_COLOR_RED: *color_code = 31; *attr_code = 0; break;
156 case GATE_TERMINAL_COLOR_MAGENTA: *color_code = 35; *attr_code = 0; break;
157 case GATE_TERMINAL_COLOR_ORANGE: *color_code = 33; *attr_code = 0; break;
158 8 case GATE_TERMINAL_COLOR_WHITE: *color_code = 37; *attr_code = 0; break;
159 case GATE_TERMINAL_COLOR_GRAY: *color_code = 30; *attr_code = 1; break;
160 case GATE_TERMINAL_COLOR_LIGHTBLUE: *color_code = 34; *attr_code = 1; break;
161 case GATE_TERMINAL_COLOR_LIGHTGREEN: *color_code = 32; *attr_code = 1; break;
162 case GATE_TERMINAL_COLOR_LIGHTCYAN: *color_code = 36; *attr_code = 1; break;
163 case GATE_TERMINAL_COLOR_LIGHTRED: *color_code = 31; *attr_code = 1; break;
164 case GATE_TERMINAL_COLOR_LIGHTMAGENTA: *color_code = 35; *attr_code = 1; break;
165 case GATE_TERMINAL_COLOR_YELLOW: *color_code = 33; *attr_code = 1; break;
166 case GATE_TERMINAL_COLOR_LIGHTWHITE: *color_code = 37; *attr_code = 1; break;
167 default: return false;
168 }
169 8 return true;
170 }
171
172 8 static gate_result_t gate_terminal_get_back_color_code(int color_type, int* color_code)
173 {
174
1/17
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
8 switch (color_type)
175 {
176 8 case GATE_TERMINAL_COLOR_BLACK: *color_code = 40; break;
177 case GATE_TERMINAL_COLOR_BLUE: *color_code = 44; break;
178 case GATE_TERMINAL_COLOR_GREEN: *color_code = 42; break;
179 case GATE_TERMINAL_COLOR_CYAN: *color_code = 46; break;
180 case GATE_TERMINAL_COLOR_RED: *color_code = 41; break;
181 case GATE_TERMINAL_COLOR_MAGENTA: *color_code = 45; break;
182 case GATE_TERMINAL_COLOR_ORANGE: *color_code = 43; break;
183 case GATE_TERMINAL_COLOR_WHITE: *color_code = 47; break;
184 case GATE_TERMINAL_COLOR_GRAY: *color_code = 40; break;
185 case GATE_TERMINAL_COLOR_LIGHTBLUE: *color_code = 44; break;
186 case GATE_TERMINAL_COLOR_LIGHTGREEN: *color_code = 42; break;
187 case GATE_TERMINAL_COLOR_LIGHTCYAN: *color_code = 46; break;
188 case GATE_TERMINAL_COLOR_LIGHTRED: *color_code = 41; break;
189 case GATE_TERMINAL_COLOR_LIGHTMAGENTA: *color_code = 45; break;
190 case GATE_TERMINAL_COLOR_YELLOW: *color_code = 43; break;
191 case GATE_TERMINAL_COLOR_LIGHTWHITE: *color_code = 47; break;
192 default: return false;
193 }
194 8 return true;
195 }
196
197 8 static gate_result_t gate_terminal_console_set_color(void* thisptr, int attr, int textcolor, int backcolor)
198 {
199 char buffer[128];
200 8 gate_size_t const len = sizeof(buffer);
201 8 gate_size_t used = 0;
202 8 used += gate_str_print_text(&buffer[used], len - used, "\x1b[", 2);
203 8 used += gate_str_print_int32(&buffer[used], len - used, attr);
204 8 used += gate_str_print_text(&buffer[used], len - used, ";", 1);
205 8 used += gate_str_print_int32(&buffer[used], len - used, textcolor);
206 8 used += gate_str_print_text(&buffer[used], len - used, ";", 1);
207 8 used += gate_str_print_int32(&buffer[used], len - used, backcolor);
208 8 used += gate_str_print_text(&buffer[used], len - used, "m", 1);
209
210 8 return gate_terminal_console_write(thisptr, buffer, used, NULL);
211 }
212
213 4 static gate_result_t gate_terminal_vt100_set_text_color(void* thisptr, gate_uint8_t text_color_code)
214 {
215 int attr;
216 4 gate_uint8_t back_color_code = 0;
217 int textcolor;
218 int backcolor;
219 4 gate_terminal_console_get_back_color(thisptr, &back_color_code);
220 4 gate_terminal_get_text_color_code(text_color_code, &textcolor, &attr);
221 4 gate_terminal_get_back_color_code(back_color_code, &backcolor);
222 4 return gate_terminal_console_set_color(thisptr, attr, textcolor, backcolor);
223 }
224 4 static gate_result_t gate_terminal_vt100_set_back_color(void* thisptr, gate_uint8_t back_color_code)
225 {
226 int attr;
227 int textcolor;
228 int backcolor;
229 gate_uint8_t text_color_code;
230 4 gate_terminal_console_get_text_color(thisptr, &text_color_code);
231 4 gate_terminal_get_text_color_code(text_color_code, &textcolor, &attr);
232 4 gate_terminal_get_back_color_code(back_color_code, &backcolor);
233 4 return gate_terminal_console_set_color(thisptr, attr, textcolor, backcolor);
234 }
235
236 static gate_result_t gate_terminal_vt100_get_size(void* thisptr, gate_uint16_t* ptr_width, gate_uint16_t* ptr_height)
237 {
238 GATE_UNUSED_ARG(thisptr);
239 GATE_UNUSED_ARG(ptr_width);
240 GATE_UNUSED_ARG(ptr_height);
241 /*TODO*/
242 return GATE_RESULT_NOTSUPPORTED;
243 }
244
245 static gate_result_t gate_terminal_vt100_get_cursor_pos(void* thisptr, gate_uint16_t* ptr_x, gate_uint16_t* ptr_y)
246 {
247 GATE_UNUSED_ARG(thisptr);
248 GATE_UNUSED_ARG(ptr_x);
249 GATE_UNUSED_ARG(ptr_y);
250 /*TODO*/
251 return GATE_RESULT_NOTSUPPORTED;
252 }
253 static gate_result_t gate_terminal_vt100_get_text_color(void* thisptr, gate_uint8_t* ptr_color_code)
254 {
255 GATE_UNUSED_ARG(thisptr);
256 GATE_UNUSED_ARG(ptr_color_code);
257 /*TODO*/
258 return GATE_RESULT_NOTSUPPORTED;
259 }
260 static gate_result_t gate_terminal_vt100_get_back_color(void* thisptr, gate_uint8_t* ptr_color_code)
261 {
262 GATE_UNUSED_ARG(thisptr);
263 GATE_UNUSED_ARG(ptr_color_code);
264 /*TODO*/
265 return GATE_RESULT_NOTSUPPORTED;
266 }
267
268 static gate_result_t gate_terminal_vt100_enable_cursor(void* thisptr, gate_bool_t enabled)
269 {
270 static char const* vt100_enable_cursor_code = "\x1b[25h";
271 static char const* vt100_disable_cursor_code = "\x1b[25l";
272 return gate_terminal_console_write(
273 thisptr,
274 (enabled ? vt100_enable_cursor_code : vt100_disable_cursor_code),
275 5,
276 NULL);
277 }
278
279
280
281
282 typedef struct vterm_cell_class
283 {
284 gate_char16_t character;
285 gate_uint8_t color;
286 gate_uint8_t flags;
287 } vterm_cell_t;
288
289 typedef struct vterm_class
290 {
291 GATE_INTERFACE_VTBL(gate_terminal) const* vtbl;
292
293 gate_atomic_int_t ref_counter;
294
295 gate_uint16_t cols;
296 gate_uint16_t rows;
297 gate_enumint_t flags;
298 gate_uint16_t cursor_x;
299 gate_uint16_t cursor_y;
300 gate_uint8_t cursor_color;
301 gate_terminal_read_char_t reader;
302 void* reader_param;
303 gate_terminal_write_char_t writer;
304 void* writer_param;
305 gate_char16_t input_buffer[4];
306 gate_uint32_t default_read_timeout_ms;
307
308 vterm_cell_t** lines;
309
310
311 } vterm_t;
312
313 static char const* vterm_get_interface_name(void* thisptr)
314 {
315 GATE_UNUSED_ARG(thisptr);
316 return GATE_INTERFACE_NAME_TERMINAL;
317 }
318
319 static void vterm_destroy(vterm_t* self)
320 {
321 gate_mem_dealloc(self);
322 }
323
324 static void vterm_release(void* thisptr)
325 {
326 vterm_t* self = (vterm_t*)thisptr;
327 if (gate_atomic_int_dec(&self->ref_counter) == 0)
328 {
329 vterm_destroy(self);
330 }
331 }
332 static int vterm_retain(void* thisptr)
333 {
334 vterm_t* self = (vterm_t*)thisptr;
335 return gate_atomic_int_inc(&self->ref_counter);
336 }
337
338 static gate_result_t vterm_read(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
339 {
340 vterm_t* self = (vterm_t*)thisptr;
341 GATE_UNUSED_ARG(self);
342 GATE_UNUSED_ARG(buffer);
343 GATE_UNUSED_ARG(bufferlength);
344 GATE_UNUSED_ARG(returned);
345 return GATE_RESULT_NOTIMPLEMENTED;
346 }
347 static gate_result_t vterm_peek(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
348 {
349 vterm_t* self = (vterm_t*)thisptr;
350 GATE_UNUSED_ARG(self);
351 GATE_UNUSED_ARG(buffer);
352 GATE_UNUSED_ARG(bufferlength);
353 GATE_UNUSED_ARG(returned);
354 return GATE_RESULT_NOTIMPLEMENTED;
355 }
356 static void vterm_scroll_line(vterm_t* self)
357 {
358 gate_size_t line_len = self->cols * sizeof(vterm_cell_t);
359 gate_size_t move_len = line_len * self->rows - 1;
360 vterm_cell_t* first_line = self->lines[0];
361 vterm_cell_t* second_line = self->lines[1];
362 vterm_cell_t* last_line = self->lines[self->rows - 1];
363 gate_size_t ndx;
364 gate_mem_move(first_line, second_line, move_len);
365 for (ndx = 0; ndx != self->cols; ++ndx)
366 {
367 last_line[ndx].character = ' ';
368 last_line[ndx].color = self->cursor_color;
369
370 }
371 }
372 static void vterm_newline(vterm_t* self)
373 {
374 self->cursor_x = 0;
375 ++self->cursor_y;
376 if (self->cursor_y >= self->rows)
377 {
378 self->cursor_y = self->rows - 1;
379 vterm_scroll_line(self);
380 }
381 }
382
383 static void vterm_set_char(vterm_t* self, gate_char16_t chr)
384 {
385 vterm_cell_t* ptr_cell = &self->lines[self->cursor_y][self->cursor_x];
386 ptr_cell->character = chr;
387 ptr_cell->color = self->cursor_color;
388 }
389 static void vterm_write_char(vterm_t* self, gate_char16_t chr)
390 {
391 switch (chr)
392 {
393 case 8: /* backspace */
394 {
395 if (self->cursor_x > 0)
396 {
397 vterm_set_char(self, ' ');
398 --self->cursor_x;
399 }
400 break;
401 }
402 case 9: /* tab */
403 {
404 self->cursor_x += 4;
405 self->cursor_x -= (self->cursor_x % 4);
406 if (self->cursor_x >= self->cols)
407 {
408 vterm_newline(self);
409 }
410 break;
411 }
412 case 10: /* newline */
413 {
414 vterm_newline(self);
415 break;
416 }
417 case 13: /* carriage return */
418 {
419 self->cursor_x = 0;
420 break;
421 }
422 default:
423 {
424 vterm_set_char(self, chr);
425 ++self->cursor_x;
426 if (self->cursor_x >= self->cols)
427 {
428 vterm_newline(self);
429 }
430 break;
431 }
432 }
433 }
434 static gate_result_t vterm_write(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
435 {
436 vterm_t* self = (vterm_t*)thisptr;
437 gate_result_t ret = GATE_RESULT_OK;
438 gate_size_t processed = 0;
439 gate_char16_t chr16;
440
441 while (bufferlength > 0)
442 {
443 chr16 = *buffer;
444 vterm_write_char(self, chr16);
445 if (self->writer)
446 {
447 self->writer(chr16, self->writer_param);
448 }
449
450 --bufferlength;
451 ++buffer;
452 ++processed;
453 }
454 if (written)
455 {
456 *written = processed;
457 }
458 return ret;
459 }
460 static gate_result_t vterm_flush(void* thisptr)
461 {
462 vterm_t* self = (vterm_t*)thisptr;
463 GATE_UNUSED_ARG(self);
464 return GATE_RESULT_OK;
465 }
466
467 static gate_result_t vterm_get_resource(void* thisptr, gate_uint32_t resource_type, gate_uintptr_t* resource)
468 {
469 vterm_t* self = (vterm_t*)thisptr;
470 GATE_UNUSED_ARG(self);
471 GATE_UNUSED_ARG(resource_type);
472 GATE_UNUSED_ARG(resource);
473 return GATE_RESULT_NOTIMPLEMENTED;
474 }
475
476 static gate_result_t vterm_await_char(void* thisptr, gate_uint32_t timeout_ms)
477 {
478 vterm_t* self = (vterm_t*)thisptr;
479 gate_result_t ret = GATE_RESULT_NOTAVAILABLE;
480 gate_char16_t chr16;
481
482 if (self->input_buffer[0])
483 {
484 /* we have something in the input buffer */
485 ret = GATE_RESULT_OK;
486 }
487 else
488 {
489 if (self->reader)
490 {
491 ret = self->reader(&chr16, timeout_ms, self->reader_param);
492 if (GATE_SUCCEEDED(ret))
493 {
494 self->input_buffer[0] = chr16;
495 }
496 }
497 }
498 return ret;
499 }
500 static gate_result_t vterm_read_char(void* thisptr, gate_char32_t* ptr_char)
501 {
502 vterm_t* self = (vterm_t*)thisptr;
503 gate_result_t ret = GATE_RESULT_NOTAVAILABLE;
504 do
505 {
506 ret = vterm_await_char(self, self->default_read_timeout_ms);
507 GATE_BREAK_IF_FAILED(ret);
508
509 if (self->input_buffer[0])
510 {
511 if (ptr_char)
512 {
513 *ptr_char = self->input_buffer[0];
514 }
515 self->input_buffer[0] = 0;
516 ret = GATE_RESULT_OK;
517 }
518 else
519 {
520 ret = GATE_RESULT_NOTAVAILABLE;
521 }
522 } while (0);
523
524 return ret;
525 }
526 static gate_result_t vterm_write_err(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
527 {
528 return vterm_write(thisptr, buffer, bufferlength, written);
529 }
530 static gate_result_t vterm_flush_err(void* thisptr)
531 {
532 return vterm_flush(thisptr);
533 }
534
535 static gate_enumint_t vterm_get_type(void* thisptr)
536 {
537 GATE_UNUSED_ARG(thisptr);
538 return GATE_TERMINAL_TYPE_VT100;
539 }
540
541 static gate_result_t vterm_get_size(void* thisptr, gate_uint16_t* ptr_width, gate_uint16_t* ptr_height)
542 {
543 vterm_t* self = (vterm_t*)thisptr;
544 if (ptr_width)
545 {
546 *ptr_width = self->cols;
547 }
548 if (ptr_height)
549 {
550 *ptr_height = self->rows;
551 }
552 return GATE_RESULT_OK;
553 }
554 static gate_result_t vterm_get_cursor_pos(void* thisptr, gate_uint16_t* ptr_x, gate_uint16_t* ptr_y)
555 {
556 vterm_t* self = (vterm_t*)thisptr;
557 if (ptr_x)
558 {
559 *ptr_x = self->cursor_x;
560 }
561 if (ptr_y)
562 {
563 *ptr_y = self->cursor_y;
564 }
565 return GATE_RESULT_OK;
566 }
567 static gate_result_t vterm_set_cursor_pos(void* thisptr, gate_uint16_t x, gate_uint16_t y)
568 {
569 vterm_t* self = (vterm_t*)thisptr;
570 if (x >= self->cols)
571 {
572 x = self->cols - 1;
573 }
574 if (y >= self->rows)
575 {
576 y = self->rows - 1;
577 }
578 self->cursor_x = x;
579 self->cursor_y = y;
580 return GATE_RESULT_OK;
581 }
582 static gate_result_t vterm_set_cursor_mode(void* thisptr, gate_uint16_t mode)
583 {
584 vterm_t* self = (vterm_t*)thisptr;
585 GATE_UNUSED_ARG(self);
586 GATE_UNUSED_ARG(mode);
587 return GATE_RESULT_NOTIMPLEMENTED;
588 }
589 static gate_result_t vterm_clear(void* thisptr)
590 {
591 vterm_t* self = (vterm_t*)thisptr;
592 unsigned x, y;
593 vterm_cell_t* ptr_cell;
594
595 for (y = 0; y != self->rows; ++y)
596 {
597 ptr_cell = self->lines[y];
598 for (x = 0; x != self->cols; ++x)
599 {
600 ptr_cell->character = ' ';
601 ptr_cell->color = self->cursor_color;
602 ptr_cell->flags = 0;
603 ++ptr_cell;
604 }
605 }
606
607 return GATE_RESULT_OK;
608 }
609
610 static gate_result_t vterm_get_text_color(void* thisptr, gate_uint8_t* ptr_color_code)
611 {
612 vterm_t* self = (vterm_t*)thisptr;
613 if (ptr_color_code)
614 {
615 *ptr_color_code = self->cursor_color & 0x0f;
616 }
617 return GATE_RESULT_OK;
618 }
619 static gate_result_t vterm_set_text_color(void* thisptr, gate_uint8_t color_code)
620 {
621 vterm_t* self = (vterm_t*)thisptr;
622 self->cursor_color = (self->cursor_color & 0xf0) | (color_code & 0xf);
623 return GATE_RESULT_OK;
624 }
625
626 static gate_result_t vterm_get_back_color(void* thisptr, gate_uint8_t* ptr_color_code)
627 {
628 vterm_t* self = (vterm_t*)thisptr;
629 if (ptr_color_code)
630 {
631 *ptr_color_code = ((self->cursor_color & 0xf0) >> 4);
632 }
633 return GATE_RESULT_OK;
634 }
635 static gate_result_t vterm_set_back_color(void* thisptr, gate_uint8_t color_code)
636 {
637 vterm_t* self = (vterm_t*)thisptr;
638 self->cursor_color = (self->cursor_color & 0x0f) | ((color_code & 0xf) << 4);
639 return GATE_RESULT_OK;
640 }
641
642
643 static GATE_INTERFACE_VTBL(gate_terminal) vterm_vtbl;
644
645 static void init_vterm_vtbl()
646 {
647 if (vterm_vtbl.get_interface_name == NULL)
648 {
649 GATE_INTERFACE_VTBL(gate_terminal) const vtbl = {
650 &vterm_get_interface_name,
651 &vterm_release,
652 &vterm_retain,
653 &vterm_read,
654 &vterm_peek,
655 &vterm_write,
656 &vterm_flush,
657 &vterm_get_resource,
658 &vterm_await_char,
659 &vterm_read_char,
660 &vterm_write_err,
661 &vterm_flush_err,
662 &vterm_get_type,
663 &vterm_get_size,
664 &vterm_get_cursor_pos,
665 &vterm_set_cursor_pos,
666 &vterm_set_cursor_mode,
667 &vterm_clear,
668 &vterm_get_text_color,
669 &vterm_set_text_color,
670 &vterm_get_back_color,
671 &vterm_set_back_color
672 };
673 vterm_vtbl = vtbl;
674 }
675 }
676
677 gate_terminal_t* gate_terminal_virtual_create(gate_uint16_t columns, gate_uint16_t rows, gate_enumint_t flags,
678 gate_terminal_read_char_t read_callback, void* read_param,
679 gate_terminal_write_char_t write_callback, void* write_param)
680 {
681 gate_terminal_t* ret = NULL;
682 vterm_t* ptr = NULL;
683 gate_size_t line_length;
684 gate_size_t additional_size;
685 char* first_line_ptr;
686 char* first_cell_ptr;
687 gate_size_t ndx;
688
689 do
690 {
691 if (columns == 0) columns = 80;
692 if (rows == 0) rows = 25;
693
694 line_length = sizeof(vterm_cell_t) * columns;
695 additional_size = rows * line_length + (rows * sizeof(vterm_cell_t*));
696
697 ptr = (vterm_t*)gate_mem_alloc(sizeof(vterm_t) + additional_size);
698 if (!ptr)
699 {
700 break;
701 }
702 gate_mem_clear(ptr, sizeof(vterm_t) + additional_size);
703 init_vterm_vtbl();
704 ptr->vtbl = &vterm_vtbl;
705 gate_atomic_int_init(&ptr->ref_counter, 1);
706 ptr->cols = columns;
707 ptr->rows = rows;
708 ptr->flags = flags;
709 ptr->cursor_x = 0;
710 ptr->cursor_y = 0;
711 ptr->cursor_color = 0x07;
712 ptr->reader = read_callback;
713 ptr->reader_param = read_param;
714 ptr->writer = write_callback;
715 ptr->writer_param = write_param;
716 ptr->default_read_timeout_ms = 4000;
717
718 first_line_ptr = (char*)ptr + sizeof(vterm_t);
719 first_cell_ptr = first_line_ptr + (sizeof(vterm_cell_t*) * rows);
720
721 ptr->lines = (vterm_cell_t**)first_line_ptr;
722
723 for (ndx = 0; ndx != rows; ++ndx)
724 {
725 ptr->lines[ndx] = (vterm_cell_t*)(first_cell_ptr + line_length * ndx);
726 }
727
728 ret = (gate_terminal_t*)ptr;
729 ptr = NULL;
730
731 } while (0);
732
733 if (ptr)
734 {
735 vterm_destroy(ptr);
736 }
737
738 return ret;
739 }
740
741
742
743
744
745 #if defined(GATE_SYSTEM_TERMINALS_WINAPI)
746
747 #include "gate/times.h"
748
749 #if defined(GATE_SYS_WINCE)
750 # include <stdio.h>
751 #endif
752
753 typedef struct gate_terminal_console_impl_class
754 {
755 GATE_INTERFACE_VTBL(gate_terminal) const* vtbl;
756
757 gate_atomic_int_t ref_counter;
758 gate_uint32_t flags;
759
760 HANDLE con_input;
761 HANDLE con_output;
762 HANDLE con_error;
763
764 gate_char32_t char_buffer[16];
765 gate_size_t char_buffer_used;
766
767 } gate_terminal_console_impl_t;
768
769 static void close_file_handle(HANDLE handle)
770 {
771 if ((handle != NULL) && (handle != INVALID_HANDLE_VALUE))
772 {
773 CloseHandle(handle);
774 }
775 }
776
777 #ifndef GATE_SYS_WINCE
778
779 #ifndef ENABLE_VIRTUAL_TERMINAL_INPUT
780 #define ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200
781 #endif
782
783 #ifndef ENABLE_QUICK_EDIT_MODE
784 #define ENABLE_QUICK_EDIT_MODE 0x0040
785 #endif
786
787 #ifndef ENABLE_INSERT_MODE
788 #define ENABLE_INSERT_MODE 0x0020
789 #endif
790
791 static BOOL gate_terminal_console_set_input_flags(HANDLE handle, gate_uint32_t flags)
792 {
793 BOOL ret = FALSE;
794 DWORD dwMode = 0;
795 if (!GetConsoleMode(handle, &dwMode))
796 {
797 return FALSE;
798 }
799
800 GATE_FLAG_SET(dwMode, ENABLE_WINDOW_INPUT, true);
801 GATE_FLAG_SET(dwMode, ENABLE_QUICK_EDIT_MODE, false);
802 GATE_FLAG_SET(dwMode, ENABLE_PROCESSED_INPUT, !GATE_FLAG_ENABLED(flags, GATE_TERMINAL_FLAG_GETCTRL));
803 GATE_FLAG_SET(dwMode, ENABLE_MOUSE_INPUT, true);
804 GATE_FLAG_SET(dwMode, ENABLE_INSERT_MODE, false);
805 GATE_FLAG_SET(dwMode, ENABLE_ECHO_INPUT, GATE_FLAG_ENABLED(flags, GATE_TERMINAL_FLAG_ECHO));
806 ret = SetConsoleMode(handle, dwMode);
807 if (GATE_SUCCEEDED(ret))
808 {
809 // VT100 support is optional (not available before Windows 10)
810 GATE_FLAG_SET(dwMode, ENABLE_VIRTUAL_TERMINAL_INPUT, GATE_FLAG_ENABLED(flags, GATE_TERMINAL_FLAG_VT100));
811 }
812 return ret;
813 }
814
815 #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
816 #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
817 #endif
818
819 static BOOL gate_terminal_console_set_output_flags(HANDLE handle, gate_uint32_t flags)
820 {
821 BOOL ret = FALSE;
822 DWORD dwMode = 0;
823 if (!GetConsoleMode(handle, &dwMode))
824 {
825 return FALSE;
826 }
827
828 GATE_FLAG_SET(dwMode, ENABLE_PROCESSED_OUTPUT, true);
829 GATE_FLAG_SET(dwMode, ENABLE_WRAP_AT_EOL_OUTPUT, true);
830 ret = SetConsoleMode(handle, dwMode);
831 if (GATE_SUCCEEDED(ret))
832 {
833 // VT100 support is optional (not available before Windows 10)
834 GATE_FLAG_SET(dwMode, ENABLE_VIRTUAL_TERMINAL_PROCESSING, GATE_FLAG_ENABLED(flags, GATE_TERMINAL_FLAG_VT100));
835 }
836 return ret;
837 }
838
839 #endif
840
841 gate_terminal_t* gate_terminal_console_get_current()
842 {
843 gate_terminal_t* ret = NULL;
844 gate_terminal_console_impl_t* impl = NULL;
845 HANDLE hProc = GetCurrentProcess();
846 HANDLE hConOut, hConIn, hConErr;
847 HANDLE hOutput = INVALID_HANDLE_VALUE;
848 HANDLE hInput = INVALID_HANDLE_VALUE;
849 HANDLE hError = INVALID_HANDLE_VALUE;
850
851 do
852 {
853 /* OUTPUT handle */
854 #if defined(GATE_SYS_WINCE)
855 # if defined(GATE_COMPILER_MSVC)
856 hConOut = (HANDLE)fileno(stdout);
857 hConIn = (HANDLE)fileno(stdin);
858 hConErr = (HANDLE)fileno(stderr);
859 # else
860 hConOut = (HANDLE)STDOUT_FILENO;
861 hConIn = (HANDLE)STDIN_FILENO;
862 hConErr = (HANDLE)STDERR_FILENO;
863 # endif
864 #else
865 hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
866 hConIn = GetStdHandle(STD_INPUT_HANDLE);
867 hConErr = GetStdHandle(STD_ERROR_HANDLE);
868 #endif
869 if ((hConOut == INVALID_HANDLE_VALUE) || (hConIn == INVALID_HANDLE_VALUE))
870 {
871 break;
872 }
873
874 if (!DuplicateHandle(hProc, hConOut, hProc, &hOutput, 0, FALSE, DUPLICATE_SAME_ACCESS))
875 {
876 break;
877 }
878 if (!DuplicateHandle(hProc, hConIn, hProc, &hInput, 0, FALSE, DUPLICATE_SAME_ACCESS))
879 {
880 break;
881 }
882 if (hConErr != INVALID_HANDLE_VALUE)
883 {
884 if (!DuplicateHandle(hProc, hConErr, hProc, &hError, 0, FALSE, DUPLICATE_SAME_ACCESS))
885 {
886 break;
887 }
888 }
889 else
890 {
891 hError = INVALID_HANDLE_VALUE;
892 }
893
894 impl = (gate_terminal_console_impl_t*)gate_mem_alloc(sizeof(gate_terminal_console_impl_t));
895 if (impl == NULL)
896 {
897 break;
898 }
899 gate_mem_clear(impl, sizeof(gate_terminal_console_impl_t));
900
901 gate_init_terminal_console_vtbl();
902 impl->vtbl = &gate_terminal_console_vtbl;
903 gate_atomic_int_init(&impl->ref_counter, 1);
904 impl->con_input = hInput;
905 impl->con_output = hOutput;
906 impl->con_error = hError;
907 hInput = NULL;
908 hOutput = NULL;
909 hError = NULL;
910
911 ret = (gate_terminal_t*)impl;
912 impl = NULL;
913
914 } while (0);
915
916 close_file_handle(hInput);
917 close_file_handle(hOutput);
918 close_file_handle(hError);
919
920 if (impl != NULL)
921 {
922 gate_mem_dealloc(impl);
923 }
924 return ret;
925 }
926
927
928 #ifdef GATE_SYS_WINCE
929
930 gate_terminal_t* gate_terminal_console_open(gate_enumint_t flags)
931 {
932 return gate_terminal_console_get_current();
933 }
934
935 #else
936
937 gate_terminal_t* gate_terminal_console_open(gate_enumint_t flags)
938 {
939 gate_terminal_t* ret = NULL;
940 gate_terminal_console_impl_t* impl = NULL;
941 HANDLE hProc = GetCurrentProcess();
942 HANDLE hCon = INVALID_HANDLE_VALUE;
943 HANDLE hInput = INVALID_HANDLE_VALUE;
944 HANDLE hOutput = INVALID_HANDLE_VALUE;
945 HANDLE hError = INVALID_HANDLE_VALUE;
946
947 do
948 {
949 AllocConsole();
950
951 /* open console input buffer */
952 hInput = gate_win32_createfile(_T("CONIN$"),
953 GENERIC_READ | GENERIC_WRITE,
954 FILE_SHARE_READ | FILE_SHARE_WRITE,
955 OPEN_EXISTING, 0, 0, NULL);
956 if (INVALID_HANDLE_VALUE == hInput)
957 {
958 /* try stdin as alternative */
959 if (!DuplicateHandle(hProc, GetStdHandle(STD_INPUT_HANDLE), hProc, &hInput, 0, FALSE, DUPLICATE_SAME_ACCESS))
960 {
961 break;
962 }
963 }
964
965 /* open console output buffer */
966 hCon = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
967 if (INVALID_HANDLE_VALUE == hCon)
968 {
969 break;
970 }
971
972 if (!DuplicateHandle(hProc, hCon, hProc, &hOutput, 0, FALSE, DUPLICATE_SAME_ACCESS))
973 {
974 break;
975 }
976 if (!DuplicateHandle(hProc, hCon, hProc, &hError, 0, FALSE, DUPLICATE_SAME_ACCESS))
977 {
978 break;
979 }
980
981 impl = (gate_terminal_console_impl_t*)gate_mem_alloc(sizeof(gate_terminal_console_impl_t));
982 if (impl == NULL)
983 {
984 break;
985 }
986
987 if (!SetConsoleActiveScreenBuffer(hOutput))
988 {
989 break;
990 }
991
992 if (!gate_terminal_console_set_output_flags(hOutput, flags))
993 {
994 break;
995 }
996 if (!gate_terminal_console_set_input_flags(hInput, flags))
997 {
998 break;
999 }
1000
1001 gate_mem_clear(impl, sizeof(gate_terminal_console_impl_t));
1002
1003 gate_init_terminal_console_vtbl();
1004 impl->vtbl = &gate_terminal_console_vtbl;
1005 gate_atomic_int_init(&impl->ref_counter, 1);
1006 impl->con_input = hInput;
1007 impl->con_output = hOutput;
1008 impl->con_error = hError;
1009 impl->flags = flags;
1010 hInput = NULL;
1011 hOutput = NULL;
1012 hError = NULL;
1013
1014 ret = (gate_terminal_t*)impl;
1015 impl = NULL;
1016
1017 } while (0);
1018
1019 close_file_handle(hCon);
1020 close_file_handle(hInput);
1021 close_file_handle(hOutput);
1022 close_file_handle(hError);
1023
1024 if (impl != NULL)
1025 {
1026 gate_mem_dealloc(impl);
1027 }
1028 return ret;
1029 }
1030 #endif
1031
1032 void gate_terminal_console_release(void* thisptr)
1033 {
1034 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
1035 if (0 == gate_atomic_int_dec(&impl->ref_counter))
1036 {
1037 close_file_handle(impl->con_input);
1038 close_file_handle(impl->con_output);
1039 close_file_handle(impl->con_error);
1040 gate_mem_dealloc(impl);
1041 }
1042 }
1043
1044 int gate_terminal_console_retain(void* thisptr)
1045 {
1046 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
1047 return gate_atomic_int_inc(&impl->ref_counter);
1048 }
1049
1050 char const* gate_terminal_console_get_interface_name(void* thisptr)
1051 {
1052 GATE_UNUSED_ARG(thisptr);
1053 return GATE_INTERFACE_NAME_TERMINAL;
1054 }
1055
1056 gate_result_t gate_terminal_console_read(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
1057 {
1058 gate_result_t ret = GATE_RESULT_FAILED;
1059 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
1060 DWORD chars_read;
1061 do
1062 {
1063 #ifdef GATE_SYS_WINCE
1064 if (!gate_win32_readfile(impl->con_input, buffer, (DWORD)bufferlength, &chars_read, NULL))
1065 #else
1066 if (!ReadConsole(impl->con_input, buffer, (DWORD)bufferlength, &chars_read, NULL))
1067 #endif
1068 {
1069 DWORD lasterr = GetLastError();
1070 if (lasterr != ERROR_INVALID_FUNCTION)
1071 {
1072 gate_win32_print_lasterror_code(lasterr, &ret, NULL, 0);
1073 break;
1074 }
1075 if (!gate_win32_readfile(impl->con_input, buffer, (DWORD)bufferlength, &chars_read, NULL))
1076 {
1077 lasterr = GetLastError();
1078 gate_win32_print_lasterror_code(lasterr, &ret, NULL, 0);
1079 break;
1080 }
1081 }
1082 if ((gate_size_t)chars_read < bufferlength)
1083 {
1084 buffer[chars_read] = 0;
1085 }
1086 if (returned)
1087 {
1088 *returned = (gate_size_t)chars_read;
1089 }
1090 ret = GATE_RESULT_OK;
1091 } while (0);
1092
1093 return ret;
1094 }
1095
1096 gate_result_t gate_terminal_console_peek(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
1097 {
1098 GATE_UNUSED_ARG(thisptr);
1099 GATE_UNUSED_ARG(buffer);
1100 GATE_UNUSED_ARG(bufferlength);
1101 GATE_UNUSED_ARG(returned);
1102 return GATE_RESULT_NOTSUPPORTED;
1103 }
1104
1105 static gate_result_t gate_terminal_console_write_to_handle(HANDLE handle, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
1106 {
1107 gate_result_t ret = GATE_RESULT_OK;
1108 DWORD chars_written = 0;
1109 TCHAR text_buffer[7168];
1110 TCHAR* ptr_text = &text_buffer[0];
1111 gate_size_t text_len = sizeof(text_buffer) / sizeof(text_buffer[0]);
1112 gate_size_t text_used;
1113 do
1114 {
1115 if (bufferlength > text_len)
1116 {
1117 text_len = bufferlength * sizeof(TCHAR);
1118 ptr_text = (TCHAR*)gate_mem_alloc(text_len);
1119 if (ptr_text == NULL)
1120 {
1121 ret = GATE_RESULT_FAILED;
1122 break;
1123 }
1124 }
1125
1126 text_used = gate_win32_utf8_2_winstr(buffer, bufferlength, ptr_text, text_len);
1127 #ifdef GATE_SYS_WINCE
1128 if (!gate_win32_writefile(handle, buffer, (DWORD)bufferlength, &chars_written, NULL))
1129 #else
1130 if (!WriteConsole(handle, ptr_text, (DWORD)text_used, &chars_written, NULL))
1131 #endif
1132 {
1133 DWORD lasterr = GetLastError();
1134 if (lasterr != ERROR_INVALID_FUNCTION)
1135 {
1136 gate_win32_print_lasterror_code(lasterr, &ret, NULL, 0);
1137 break;
1138 }
1139
1140 if (!gate_win32_writefile(handle, buffer, (DWORD)bufferlength, &chars_written, NULL))
1141 {
1142 lasterr = GetLastError();
1143 gate_win32_print_lasterror_code(lasterr, &ret, NULL, 0);
1144 break;
1145 }
1146 }
1147
1148 if (NULL != written)
1149 {
1150 if (chars_written == text_used)
1151 {
1152 *written = bufferlength;
1153 }
1154 else
1155 {
1156 *written = (gate_size_t)chars_written;
1157 }
1158 }
1159 ret = GATE_RESULT_OK;
1160 } while (0);
1161
1162 if ((ptr_text != NULL) && (ptr_text != &text_buffer[0]))
1163 {
1164 gate_mem_dealloc(ptr_text);
1165 }
1166
1167 return ret;
1168
1169 }
1170
1171 gate_result_t gate_terminal_console_write(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
1172 {
1173 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
1174 return gate_terminal_console_write_to_handle(impl->con_output, buffer, bufferlength, written);
1175 }
1176
1177 gate_result_t gate_terminal_console_flush(void* thisptr)
1178 {
1179 gate_result_t ret = GATE_RESULT_OK;
1180 GATE_UNUSED_ARG(thisptr);
1181 return ret;
1182 }
1183
1184 gate_result_t gate_terminal_console_get_resource(void* thisptr, gate_uint32_t resource_type, gate_uintptr_t* resource)
1185 {
1186 gate_result_t ret = GATE_RESULT_FAILED;
1187 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
1188 /* TODO */
1189 do
1190 {
1191 if (!resource)
1192 {
1193 ret = GATE_RESULT_NULLPOINTER;
1194 break;
1195 }
1196
1197 switch (resource_type)
1198 {
1199 case GATE_STREAM_RESOURCE_DEFAULT:
1200 case GATE_STREAM_RESOURCE_INPUT:
1201 {
1202 *resource = (gate_uintptr_t)impl->con_input;
1203 ret = GATE_RESULT_OK;
1204 }
1205 case GATE_STREAM_RESOURCE_OUTPUT:
1206 {
1207 *resource = (gate_uintptr_t)impl->con_output;
1208 ret = GATE_RESULT_OK;
1209 }
1210 case GATE_STREAM_RESOURCE_ERROR:
1211 {
1212 *resource = (gate_uintptr_t)impl->con_error;
1213 ret = GATE_RESULT_OK;
1214 }
1215 default:
1216 {
1217 ret = GATE_RESULT_NOTSUPPORTED;
1218 break;
1219 }
1220 }
1221
1222 } while (0);
1223
1224 return ret;
1225 }
1226
1227 static gate_char32_t map_scan_code_to_ctrl_ascii_code(WORD vkey_code)
1228 {
1229 if ((vkey_code >= 0x41) && (vkey_code <= 0x5A))
1230 {
1231 return GATE_TERMINAL_CHAR_CTRL_A + (vkey_code - 0x41);
1232 }
1233 return 0;
1234 }
1235
1236 static gate_char32_t gate_scan_code_to_alt_ascii_code(WORD vkey_code)
1237 {
1238 if ((vkey_code >= 0x41) && (vkey_code <= 0x5A))
1239 {
1240 switch ((vkey_code - 0x41))
1241 {
1242 case 0: return GATE_TERMINAL_CHAR_ALT_A;
1243 case 1: return GATE_TERMINAL_CHAR_ALT_B;
1244 case 2: return GATE_TERMINAL_CHAR_ALT_C;
1245 case 3: return GATE_TERMINAL_CHAR_ALT_D;
1246 case 4: return GATE_TERMINAL_CHAR_ALT_E;
1247 case 5: return GATE_TERMINAL_CHAR_ALT_F;
1248 case 6: return GATE_TERMINAL_CHAR_ALT_G;
1249 case 7: return GATE_TERMINAL_CHAR_ALT_H;
1250 case 8: return GATE_TERMINAL_CHAR_ALT_I;
1251 case 9: return GATE_TERMINAL_CHAR_ALT_J;
1252 case 10: return GATE_TERMINAL_CHAR_ALT_K;
1253 case 11: return GATE_TERMINAL_CHAR_ALT_L;
1254 case 12: return GATE_TERMINAL_CHAR_ALT_M;
1255 case 13: return GATE_TERMINAL_CHAR_ALT_N;
1256 case 14: return GATE_TERMINAL_CHAR_ALT_O;
1257 case 15: return GATE_TERMINAL_CHAR_ALT_P;
1258 case 16: return GATE_TERMINAL_CHAR_ALT_Q;
1259 case 17: return GATE_TERMINAL_CHAR_ALT_R;
1260 case 18: return GATE_TERMINAL_CHAR_ALT_S;
1261 case 19: return GATE_TERMINAL_CHAR_ALT_T;
1262 case 20: return GATE_TERMINAL_CHAR_ALT_U;
1263 case 21: return GATE_TERMINAL_CHAR_ALT_V;
1264 case 22: return GATE_TERMINAL_CHAR_ALT_W;
1265 case 23: return GATE_TERMINAL_CHAR_ALT_X;
1266 case 24: return GATE_TERMINAL_CHAR_ALT_Y;
1267 case 25: return GATE_TERMINAL_CHAR_ALT_Z;
1268 }
1269 }
1270 else
1271 {
1272 switch (vkey_code)
1273 {
1274 case VK_F1: return GATE_TERMINAL_CHAR_ALT_F1;
1275 case VK_F2: return GATE_TERMINAL_CHAR_ALT_F2;
1276 case VK_F3: return GATE_TERMINAL_CHAR_ALT_F3;
1277 case VK_F4: return GATE_TERMINAL_CHAR_ALT_F4;
1278 case VK_F5: return GATE_TERMINAL_CHAR_ALT_F5;
1279 case VK_F6: return GATE_TERMINAL_CHAR_ALT_F6;
1280 case VK_F7: return GATE_TERMINAL_CHAR_ALT_F7;
1281 case VK_F8: return GATE_TERMINAL_CHAR_ALT_F8;
1282 case VK_F9: return GATE_TERMINAL_CHAR_ALT_F9;
1283 case VK_F10: return GATE_TERMINAL_CHAR_ALT_F10;
1284 case VK_F11: return GATE_TERMINAL_CHAR_ALT_F11;
1285 case VK_F12: return GATE_TERMINAL_CHAR_ALT_F12;
1286 }
1287 }
1288 return 0;
1289 }
1290
1291 static gate_char32_t gate_special_key_to_ascii_code(WORD vkey)
1292 {
1293 switch (vkey)
1294 {
1295 case VK_PRIOR: return GATE_TERMINAL_CHAR_PGUP;
1296 case VK_NEXT: return GATE_TERMINAL_CHAR_PGDOWN;
1297 case VK_HOME: return GATE_TERMINAL_CHAR_HOME;
1298 case VK_END: return GATE_TERMINAL_CHAR_END;
1299 case VK_UP: return GATE_TERMINAL_CHAR_UPARROW;
1300 case VK_DOWN: return GATE_TERMINAL_CHAR_DOWNARROW;
1301 case VK_LEFT: return GATE_TERMINAL_CHAR_LEFTARROW;
1302 case VK_RIGHT: return GATE_TERMINAL_CHAR_RIGHTARROW;
1303
1304 case VK_F1: return GATE_TERMINAL_CHAR_F1;
1305 case VK_F2: return GATE_TERMINAL_CHAR_F2;
1306 case VK_F3: return GATE_TERMINAL_CHAR_F3;
1307 case VK_F4: return GATE_TERMINAL_CHAR_F4;
1308 case VK_F5: return GATE_TERMINAL_CHAR_F5;
1309 case VK_F6: return GATE_TERMINAL_CHAR_F6;
1310 case VK_F7: return GATE_TERMINAL_CHAR_F7;
1311 case VK_F8: return GATE_TERMINAL_CHAR_F8;
1312 case VK_F9: return GATE_TERMINAL_CHAR_F9;
1313 case VK_F10: return GATE_TERMINAL_CHAR_F10;
1314 case VK_F11: return GATE_TERMINAL_CHAR_F11;
1315 case VK_F12: return GATE_TERMINAL_CHAR_F12;
1316
1317 case VK_TAB:
1318 case VK_CAPITAL:
1319 case VK_BACK:
1320 case VK_RETURN:
1321 case VK_ESCAPE:
1322 case VK_INSERT:
1323 case VK_DELETE:
1324 case VK_PRINT:
1325 case VK_PAUSE:
1326 case VK_SCROLL:
1327 case VK_NUMLOCK:
1328 default:
1329 return 0;
1330 }
1331 }
1332
1333 gate_result_t gate_terminal_console_read_char_impl(void* thisptr, gate_char32_t* ptr_char, gate_uint32_t timeout_ms)
1334 {
1335 gate_result_t ret = GATE_RESULT_FAILED;
1336 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
1337 #ifdef GATE_SYS_WINCE
1338 ret = GATE_RESULT_NOTSUPPORTED;
1339 #else
1340 gate_timecounter_t tc_start;
1341 gate_timecounter_t tc_now;
1342 gate_int64_t time_diff;
1343 DWORD wait = timeout_ms;
1344 INPUT_RECORD input_record = GATE_INIT_EMPTY;
1345 DWORD event_count;
1346 DWORD wait_result;
1347 gate_char32_t chr;
1348
1349 /* TODO */
1350
1351 do
1352 {
1353 ret = gate_timecounter_now(&tc_start);
1354 GATE_BREAK_IF_FAILED(ret);
1355
1356 if (impl->char_buffer_used != 0)
1357 {
1358 if (ptr_char)
1359 {
1360 *ptr_char = impl->char_buffer[0];
1361 }
1362 if (--impl->char_buffer_used != 0)
1363 {
1364 gate_mem_copy(&impl->char_buffer[0], &impl->char_buffer[1], impl->char_buffer_used * sizeof(impl->char_buffer[0]));
1365 }
1366 return GATE_RESULT_OK;
1367 }
1368
1369 ret = GATE_RESULT_FAILED;
1370 while (WAIT_OBJECT_0 == (wait_result = WaitForSingleObject(impl->con_input, wait)))
1371 {
1372 event_count = 0;
1373 if (!ReadConsoleInput(impl->con_input, &input_record, 1, &event_count))
1374 {
1375 GATE_DEBUG_TRACE("ReadConsoleInput() failed");
1376 GATE_DEBUG_TRACE_VALUE(gate_win32_getlasterror());
1377 }
1378 else
1379 {
1380 if (input_record.EventType == KEY_EVENT)
1381 {
1382 if (input_record.Event.KeyEvent.bKeyDown)
1383 {
1384 if ((input_record.Event.KeyEvent.dwControlKeyState & LEFT_CTRL_PRESSED)
1385 || ((input_record.Event.KeyEvent.dwControlKeyState & RIGHT_CTRL_PRESSED)))
1386 {
1387 chr = map_scan_code_to_ctrl_ascii_code(input_record.Event.KeyEvent.wVirtualKeyCode);
1388 if (chr != 0)
1389 {
1390 if (ptr_char)
1391 {
1392 *ptr_char = chr;
1393 }
1394 else
1395 {
1396 impl->char_buffer[0] = chr;
1397 impl->char_buffer_used = 1;
1398 }
1399 ret = GATE_RESULT_OK;
1400 break;
1401 }
1402 }
1403
1404 if ((input_record.Event.KeyEvent.dwControlKeyState & LEFT_ALT_PRESSED)
1405 || ((input_record.Event.KeyEvent.dwControlKeyState & RIGHT_ALT_PRESSED)))
1406 {
1407 chr = gate_scan_code_to_alt_ascii_code(input_record.Event.KeyEvent.wVirtualScanCode);
1408 if (chr != 0)
1409 {
1410 if (ptr_char)
1411 {
1412 *ptr_char = 0;
1413 impl->char_buffer[0] = chr;
1414 impl->char_buffer_used = 1;
1415 }
1416 else
1417 {
1418 impl->char_buffer[0] = 0;
1419 impl->char_buffer[1] = chr;
1420 impl->char_buffer_used = 2;
1421 }
1422 ret = GATE_RESULT_OK;
1423 break;
1424 }
1425 }
1426
1427 chr = gate_special_key_to_ascii_code(input_record.Event.KeyEvent.wVirtualScanCode);
1428 if (chr != 0)
1429 {
1430 if (ptr_char)
1431 {
1432 *ptr_char = 0;
1433 impl->char_buffer[0] = chr;
1434 impl->char_buffer_used = 1;
1435 }
1436 else
1437 {
1438 impl->char_buffer[0] = 0;
1439 impl->char_buffer[1] = chr;
1440 impl->char_buffer_used = 2;
1441 }
1442 ret = GATE_RESULT_OK;
1443 break;
1444 }
1445
1446 if (input_record.Event.KeyEvent.uChar.UnicodeChar != 0)
1447 {
1448 /* we have an unicode character */
1449 if (ptr_char)
1450 {
1451 *ptr_char = input_record.Event.KeyEvent.uChar.UnicodeChar;
1452 }
1453 else
1454 {
1455 impl->char_buffer[0] = input_record.Event.KeyEvent.uChar.UnicodeChar;
1456 impl->char_buffer_used = 1;
1457 }
1458 ret = GATE_RESULT_OK;
1459 break;
1460 }
1461
1462 /* we could not deduce a code for an entered key -> ignore input */
1463 }
1464 }
1465 }
1466
1467 ret = gate_timecounter_now(&tc_now);
1468 GATE_BREAK_IF_FAILED(ret);
1469
1470 time_diff = gate_timecounter_diff(tc_now, tc_start) / 1000;
1471 if (time_diff >= timeout_ms)
1472 {
1473 ret = GATE_RESULT_TIMEOUT;
1474 break;
1475 }
1476 wait = (DWORD)(timeout_ms - time_diff);
1477 }
1478 if (wait_result == WAIT_TIMEOUT)
1479 {
1480 ret = GATE_RESULT_TIMEOUT;
1481 }
1482 else if (wait_result != WAIT_OBJECT_0)
1483 {
1484 ret = GATE_RESULT_FAILED;
1485 }
1486 } while (0);
1487 #endif
1488 return ret;
1489 }
1490
1491 static gate_bool_t is_control_key(WORD keyCode)
1492 {
1493 switch (keyCode)
1494 {
1495 case VK_SHIFT:
1496 case VK_CONTROL:
1497 case VK_MENU:
1498 case VK_LSHIFT:
1499 case VK_RSHIFT:
1500 case VK_LCONTROL:
1501 case VK_RCONTROL:
1502 case VK_LMENU:
1503 case VK_RMENU:
1504 return true;
1505 default:
1506 return false;
1507 }
1508 }
1509
1510 gate_result_t gate_terminal_console_await_char(void* thisptr, gate_uint32_t timeout_ms)
1511 {
1512 gate_result_t ret = GATE_RESULT_FAILED;
1513 gate_terminal_console_impl_t* ptr = (gate_terminal_console_impl_t*)thisptr;
1514 #ifdef GATE_SYS_WINCE
1515 ret = GATE_RESULT_NOTSUPPORTED;
1516 #else
1517 gate_timecounter_t tc_start;
1518 gate_timecounter_t tc_now;
1519 gate_int64_t time_diff;
1520 DWORD next_timeout = (timeout_ms == GATE_CONSOLE_TIMEOUT_NEVER) ? INFINITE : (DWORD)timeout_ms;
1521 INPUT_RECORD input_record = GATE_INIT_EMPTY;
1522 DWORD event_count;
1523 DWORD wait_result;
1524
1525 HANDLE input_handle = ptr->con_input;
1526
1527 do
1528 {
1529 ret = gate_timecounter_now(&tc_start);
1530 GATE_BREAK_IF_FAILED(ret);
1531
1532 ret = GATE_RESULT_FAILED;
1533 while (WAIT_OBJECT_0 == (wait_result = WaitForSingleObject(input_handle, next_timeout)))
1534 {
1535 event_count = 0;
1536 if (PeekConsoleInput(input_handle, &input_record, 1, &event_count))
1537 {
1538 if (input_record.EventType != KEY_EVENT)
1539 {
1540 /* not interested in out events -> remove event from buffer */
1541 ReadConsoleInput(input_handle, &input_record, 1, &event_count);
1542 }
1543 else if (!input_record.Event.KeyEvent.bKeyDown)
1544 {
1545 /* not interested in key_up -> remove event */
1546 ReadConsoleInput(input_handle, &input_record, 1, &event_count);
1547 }
1548 else if (is_control_key(input_record.Event.KeyEvent.wVirtualKeyCode))
1549 {
1550 /* ignore control keys -> remove event */
1551 ReadConsoleInput(input_handle, &input_record, 1, &event_count);
1552 }
1553 else
1554 {
1555 /* next event is a readable key */
1556 ret = GATE_RESULT_OK;
1557 break;
1558 }
1559 }
1560
1561 ret = gate_timecounter_now(&tc_now);
1562 GATE_BREAK_IF_FAILED(ret);
1563
1564 time_diff = gate_timecounter_diff(tc_now, tc_start) / 1000;
1565 if (time_diff >= timeout_ms)
1566 {
1567 ret = GATE_RESULT_TIMEOUT;
1568 break;
1569 }
1570 next_timeout = (DWORD)(timeout_ms - time_diff);
1571 }
1572 if (wait_result == WAIT_TIMEOUT)
1573 {
1574 ret = GATE_RESULT_TIMEOUT;
1575 }
1576 else if (wait_result != WAIT_OBJECT_0)
1577 {
1578 ret = GATE_RESULT_FAILED;
1579 }
1580 } while (0);
1581 #endif
1582 return ret;
1583 }
1584
1585 gate_result_t gate_terminal_console_read_char(void* thisptr, gate_char32_t* ptr_char)
1586 {
1587 gate_result_t ret = GATE_RESULT_FAILED;
1588 gate_terminal_console_impl_t* ptr = (gate_terminal_console_impl_t*)thisptr;
1589 #ifdef GATE_SYS_WINCE
1590 ret = GATE_RESULT_NOTSUPPORTED;
1591 #else
1592 INPUT_RECORD input_record = GATE_INIT_EMPTY;
1593 DWORD event_count = 0;
1594 gate_char32_t chr;
1595 HANDLE input_handle = ptr->con_input;
1596
1597 do
1598 {
1599 ret = gate_terminal_console_await_char(thisptr, GATE_CONSOLE_TIMEOUT_NEVER);
1600 GATE_BREAK_IF_FAILED(ret);
1601
1602 event_count = 0;
1603 if (!ReadConsoleInput(input_handle, &input_record, 1, &event_count))
1604 {
1605 ret = GATE_RESULT_FAILED;
1606 break;
1607 }
1608 if (input_record.EventType != KEY_EVENT)
1609 {
1610 ret = GATE_RESULT_FAILED;
1611 break;
1612 }
1613 if (!input_record.Event.KeyEvent.bKeyDown)
1614 {
1615 ret = GATE_RESULT_FAILED;
1616 break;
1617 }
1618
1619 #if defined(GATE_WIN32_UNICODE)
1620 chr = input_record.Event.KeyEvent.uChar.UnicodeChar;
1621 #else
1622 chr = input_record.Event.KeyEvent.uChar.AsciiChar;
1623 #endif
1624 if (chr == 0)
1625 {
1626 gate_keyboard_native_key_to_unicode(input_record.Event.KeyEvent.wVirtualKeyCode, &chr);
1627 }
1628 *ptr_char = chr;
1629
1630 } while (0);
1631 #endif
1632 return ret;
1633 }
1634
1635
1636 gate_result_t gate_terminal_console_write_err(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
1637 {
1638 gate_terminal_console_impl_t* const impl = (gate_terminal_console_impl_t*)thisptr;
1639 return gate_terminal_console_write_to_handle(impl->con_error, buffer, bufferlength, written);
1640 }
1641
1642 gate_result_t gate_terminal_console_flush_err(void* thisptr)
1643 {
1644 gate_result_t ret = GATE_RESULT_OK;
1645 GATE_UNUSED_ARG(thisptr);
1646 return ret;
1647 }
1648
1649 #ifndef GATE_SYS_WINCE
1650 static gate_bool_t is_real_console(gate_terminal_console_impl_t* impl)
1651 {
1652 DWORD con_mode = 0;
1653 BOOL is_console = GetConsoleMode(impl->con_output, &con_mode);
1654 return is_console ? true : false;
1655 }
1656 #endif
1657
1658 gate_enumint_t gate_terminal_console_get_type(void* thisptr)
1659 {
1660 #ifdef GATE_SYS_WINCE
1661 return GATE_TERMINAL_TYPE_CHARSTREAM;
1662 #else
1663 gate_terminal_console_impl_t* const impl = (gate_terminal_console_impl_t*)thisptr;
1664 return is_real_console(impl) ? GATE_TERMINAL_TYPE_UI : GATE_TERMINAL_TYPE_CHARSTREAM;
1665 #endif
1666 }
1667
1668 gate_result_t gate_terminal_console_get_size(void* thisptr, gate_uint16_t* ptr_width, gate_uint16_t* ptr_height)
1669 {
1670 gate_result_t ret = GATE_RESULT_FAILED;
1671 gate_terminal_console_impl_t* const impl = (gate_terminal_console_impl_t*)thisptr;
1672 do
1673 {
1674 #ifndef GATE_SYS_WINCE
1675 if (!GATE_FLAG_ENABLED(impl->flags, GATE_TERMINAL_FLAG_VT100))
1676 {
1677 CONSOLE_SCREEN_BUFFER_INFO info;
1678 if (!GetConsoleScreenBufferInfo(impl->con_output, &info))
1679 {
1680 DWORD lasterr = GetLastError();
1681 if (!is_real_console(impl))
1682 {
1683 if (ptr_width != NULL) *ptr_width = 80;
1684 if (ptr_height != NULL) *ptr_height = 25;
1685 ret = GATE_RESULT_OK;
1686 break;
1687 }
1688 gate_win32_print_lasterror_code(lasterr, &ret, NULL, 0);
1689 }
1690 else
1691 {
1692 if (ptr_width != NULL) *ptr_width = (gate_uint16_t)info.dwSize.X;
1693 if (ptr_height != NULL) *ptr_height = (gate_uint16_t)info.dwSize.Y;
1694 ret = GATE_RESULT_OK;
1695 }
1696 break;
1697 }
1698 #endif
1699 ret = gate_terminal_vt100_get_size(thisptr, ptr_width, ptr_height);
1700 } while (0);
1701 return ret;
1702 }
1703
1704 gate_result_t gate_terminal_console_get_cursor_pos(void* thisptr, gate_uint16_t* ptr_x, gate_uint16_t* ptr_y)
1705 {
1706 gate_result_t ret = GATE_RESULT_FAILED;
1707 gate_terminal_console_impl_t* const impl = (gate_terminal_console_impl_t*)thisptr;
1708 do
1709 {
1710 #ifndef GATE_SYS_WINCE
1711 if (!GATE_FLAG_ENABLED(impl->flags, GATE_TERMINAL_FLAG_VT100))
1712 {
1713 CONSOLE_SCREEN_BUFFER_INFO info;
1714 if (!GetConsoleScreenBufferInfo(impl->con_output, &info))
1715 {
1716 DWORD lasterr = GetLastError();
1717 if (!is_real_console(impl))
1718 {
1719 // return fake values
1720 if (ptr_x != NULL) *ptr_x = 0;
1721 if (ptr_y != NULL) *ptr_y = 0;
1722 ret = GATE_RESULT_OK;
1723 break;
1724 }
1725 gate_win32_print_lasterror_code(lasterr, &ret, NULL, 0);
1726 }
1727 else
1728 {
1729 if (ptr_x != NULL) *ptr_x = (gate_uint16_t)info.dwCursorPosition.X;
1730 if (ptr_y != NULL) *ptr_y = (gate_uint16_t)info.dwCursorPosition.Y;
1731 ret = GATE_RESULT_OK;
1732 break;
1733 }
1734 }
1735 #endif
1736 ret = gate_terminal_vt100_get_cursor_pos(thisptr, ptr_x, ptr_y);
1737 } while (0);
1738 return ret;
1739 }
1740
1741 gate_result_t gate_terminal_console_set_cursor_pos(void* thisptr, gate_uint16_t x, gate_uint16_t y)
1742 {
1743 gate_result_t ret = GATE_RESULT_FAILED;
1744 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
1745 do
1746 {
1747 #ifndef GATE_SYS_WINCE
1748 if (!GATE_FLAG_ENABLED(impl->flags, GATE_TERMINAL_FLAG_VT100))
1749 {
1750 COORD coord;
1751 coord.X = (SHORT)x;
1752 coord.Y = (SHORT)y;
1753 if (!SetConsoleCursorPosition(impl->con_output, coord))
1754 {
1755 DWORD lasterr = GetLastError();
1756 if (!is_real_console(impl))
1757 {
1758 /* no action, but simulate success */
1759 ret = GATE_RESULT_OK;
1760 break;
1761 }
1762 gate_win32_print_lasterror_code(lasterr, &ret, NULL, 0);
1763 }
1764 else
1765 {
1766 ret = GATE_RESULT_OK;
1767 break;
1768 }
1769 }
1770 #endif
1771 ret = gate_terminal_vt100_set_cursor_pos(thisptr, x, y);
1772
1773 } while (0);
1774 return ret;
1775 }
1776
1777 gate_result_t gate_terminal_console_set_cursor_mode(void* thisptr, gate_uint16_t mode)
1778 {
1779 gate_result_t ret = GATE_RESULT_FAILED;
1780 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
1781
1782 do
1783 {
1784 #ifndef GATE_SYS_WINCE
1785 if (!GATE_FLAG_ENABLED(impl->flags, GATE_TERMINAL_FLAG_VT100))
1786 {
1787 CONSOLE_CURSOR_INFO info = GATE_INIT_EMPTY;
1788
1789 switch (mode)
1790 {
1791 case GATE_TERMINAL_CURSOR_MODE_OFF:
1792 {
1793 info.bVisible = false;
1794 info.dwSize = 1;
1795 break;
1796 }
1797 case GATE_TERMINAL_CURSOR_MODE_SMALL:
1798 {
1799 info.bVisible = true;
1800 info.dwSize = 15;
1801 break;
1802 }
1803 case GATE_TERMINAL_CURSOR_MODE_MEDIUM:
1804 {
1805 info.bVisible = true;
1806 info.dwSize = 50;
1807 break;
1808 }
1809 case GATE_TERMINAL_CURSOR_MODE_LARGE:
1810 default:
1811 {
1812 info.bVisible = true;
1813 info.dwSize = 100;
1814 break;
1815 }
1816 }
1817 if (SetConsoleCursorInfo(impl->con_output, &info))
1818 {
1819 ret = GATE_RESULT_OK;
1820 break;
1821 }
1822 else
1823 {
1824 if (!is_real_console(impl))
1825 {
1826 /* simluate success */
1827 ret = GATE_RESULT_OK;
1828 break;
1829 }
1830 }
1831 }
1832 #endif
1833 ret = gate_terminal_vt100_enable_cursor(impl, (mode == GATE_TERMINAL_CURSOR_MODE_OFF) ? false : true);
1834
1835 } while (0);
1836 return ret;
1837 }
1838
1839 gate_result_t gate_terminal_console_clear(void* thisptr)
1840 {
1841 gate_result_t ret = GATE_RESULT_FAILED;
1842 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
1843 do
1844 {
1845 #ifndef GATE_SYS_WINCE
1846 if (!GATE_FLAG_ENABLED(impl->flags, GATE_TERMINAL_FLAG_VT100))
1847 {
1848 do
1849 {
1850 COORD coordScreen = { 0, 0 };
1851 DWORD cCharsWritten;
1852 CONSOLE_SCREEN_BUFFER_INFO csbi;
1853 DWORD dwConSize;
1854
1855 if (!GetConsoleScreenBufferInfo(impl->con_output, &csbi))
1856 {
1857 DWORD lasterr = GetLastError();
1858 if (!is_real_console(impl))
1859 {
1860 /* no change, simulate success */
1861 ret = GATE_RESULT_OK;
1862 break;
1863 }
1864 gate_win32_print_lasterror_code(lasterr, &ret, NULL, 0);
1865 break;
1866 }
1867 dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
1868
1869 if (!FillConsoleOutputCharacter(impl->con_output, _T(' '), dwConSize, coordScreen, &cCharsWritten))
1870 {
1871 gate_win32_print_lasterror(&ret, NULL, 0);
1872 break;
1873 }
1874 if (!GetConsoleScreenBufferInfo(impl->con_output, &csbi))
1875 {
1876 gate_win32_print_lasterror(&ret, NULL, 0);
1877 break;
1878 }
1879 if (!FillConsoleOutputAttribute(impl->con_output, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten))
1880 {
1881 gate_win32_print_lasterror(&ret, NULL, 0);
1882 break;
1883 }
1884 if (!SetConsoleCursorPosition(impl->con_output, coordScreen))
1885 {
1886 gate_win32_print_lasterror(&ret, NULL, 0);
1887 break;
1888 }
1889 ret = GATE_RESULT_OK;
1890 } while (0);
1891
1892 if (GATE_SUCCEEDED(ret))
1893 {
1894 break;
1895 }
1896 }
1897 #endif
1898 ret = gate_terminal_vt100_clear(thisptr);
1899 } while (0);
1900
1901 return ret;
1902 }
1903
1904 gate_result_t gate_terminal_console_get_text_color(void* thisptr, gate_uint8_t* ptr_color_code)
1905 {
1906 gate_result_t ret = GATE_RESULT_FAILED;
1907 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
1908
1909 do
1910 {
1911 #ifndef GATE_SYS_WINCE
1912 //if(!GATE_FLAG_ENABLED(impl->flags, GATE_TERMINAL_FLAG_VT100))
1913 {
1914 CONSOLE_SCREEN_BUFFER_INFO info;
1915 if (!GetConsoleScreenBufferInfo(impl->con_output, &info))
1916 {
1917 DWORD lasterr = GetLastError();
1918 if (!is_real_console(impl))
1919 {
1920 if (ptr_color_code != NULL) *ptr_color_code = GATE_TERMINAL_COLOR_WHITE;
1921 ret = GATE_RESULT_OK;
1922 break;
1923 }
1924 gate_win32_print_lasterror_code(lasterr, &ret, NULL, 0);
1925 }
1926 else
1927 {
1928 if (ptr_color_code != NULL)
1929 {
1930 *ptr_color_code = info.wAttributes & 0x0f;
1931 }
1932 ret = GATE_RESULT_OK;
1933 break;
1934 }
1935 }
1936 #endif
1937 ret = gate_terminal_vt100_get_text_color(thisptr, ptr_color_code);
1938 } while (0);
1939 return ret;
1940 }
1941
1942 gate_result_t gate_terminal_console_set_text_color(void* thisptr, gate_uint8_t color_code)
1943 {
1944 gate_result_t ret = GATE_RESULT_FAILED;
1945 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
1946
1947 do
1948 {
1949 #ifndef GATE_SYS_WINCE
1950 if (!GATE_FLAG_ENABLED(impl->flags, GATE_TERMINAL_FLAG_VT100))
1951 {
1952 CONSOLE_SCREEN_BUFFER_INFO info = GATE_INIT_EMPTY;
1953 GetConsoleScreenBufferInfo(impl->con_output, &info);
1954 info.wAttributes &= 0xfff0;
1955 info.wAttributes |= (gate_uint16_t)color_code;
1956 if (!SetConsoleTextAttribute(impl->con_output, info.wAttributes))
1957 {
1958 DWORD lasterr = GetLastError();
1959 if (!is_real_console(impl))
1960 {
1961 ret = GATE_RESULT_OK;
1962 break;
1963 }
1964 gate_win32_print_lasterror_code(lasterr, &ret, NULL, 0);
1965 }
1966 else
1967 {
1968 ret = GATE_RESULT_OK;
1969 break;
1970 }
1971 }
1972 #endif
1973 ret = gate_terminal_vt100_set_text_color(thisptr, color_code);
1974 } while (0);
1975 return ret;
1976 }
1977
1978 gate_result_t gate_terminal_console_get_back_color(void* thisptr, gate_uint8_t* ptr_color_code)
1979 {
1980 gate_result_t ret = GATE_RESULT_FAILED;
1981 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
1982 do
1983 {
1984 #ifndef GATE_SYS_WINCE
1985 //if(!GATE_FLAG_ENABLED(impl->flags, GATE_TERMINAL_FLAG_VT100))
1986 {
1987 CONSOLE_SCREEN_BUFFER_INFO info;
1988 if (!GetConsoleScreenBufferInfo(impl->con_output, &info))
1989 {
1990 DWORD lasterr = GetLastError();
1991 if (!is_real_console(impl))
1992 {
1993 if (ptr_color_code) *ptr_color_code = GATE_TERMINAL_COLOR_BLACK;
1994 ret = GATE_RESULT_OK;
1995 break;
1996 }
1997 gate_win32_print_lasterror_code(lasterr, &ret, NULL, 0);
1998 }
1999 else
2000 {
2001 if (NULL != ptr_color_code)
2002 {
2003 *ptr_color_code = (info.wAttributes >> 4) & 0x0f;
2004 }
2005 ret = GATE_RESULT_OK;
2006 break;
2007 }
2008 }
2009 #endif
2010 ret = gate_terminal_vt100_get_back_color(thisptr, ptr_color_code);
2011 } while (0);
2012 return ret;
2013 }
2014
2015 gate_result_t gate_terminal_console_set_back_color(void* thisptr, gate_uint8_t color_code)
2016 {
2017 gate_result_t ret = GATE_RESULT_FAILED;
2018 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2019 do
2020 {
2021 #ifndef GATE_SYS_WINCE
2022 if (!GATE_FLAG_ENABLED(impl->flags, GATE_TERMINAL_FLAG_VT100))
2023 {
2024 CONSOLE_SCREEN_BUFFER_INFO info = GATE_INIT_EMPTY;
2025 GetConsoleScreenBufferInfo(impl->con_output, &info);
2026 info.wAttributes &= 0xff0f;
2027 info.wAttributes |= (((gate_uint16_t)(color_code) << 4) & 0x00f0);
2028 if (!SetConsoleTextAttribute(impl->con_output, info.wAttributes))
2029 {
2030 DWORD lasterr = GetLastError();
2031 if (!is_real_console(impl))
2032 {
2033 /* no action, simulate success */
2034 ret = GATE_RESULT_OK;
2035 break;
2036 }
2037 gate_win32_print_lasterror_code(lasterr, &ret, NULL, 0);
2038 }
2039 else
2040 {
2041 ret = GATE_RESULT_OK;
2042 break;
2043 }
2044 }
2045 #endif
2046 ret = gate_terminal_vt100_set_back_color(thisptr, color_code);
2047 } while (0);
2048 return ret;
2049 }
2050
2051 #endif /* GATE_SYSTEM_TERMINALS_WINAPI */
2052
2053
2054 #if defined(GATE_SYSTEM_TERMINALS_POSIX)
2055
2056 # include <sys/ioctl.h>
2057 # include <sys/types.h>
2058 # include <sys/select.h>
2059 # include <sys/wait.h>
2060 # include <unistd.h>
2061 # include <stdio.h>
2062 # include <termios.h>
2063
2064 typedef struct gate_terminal_console_impl_class
2065 {
2066 GATE_INTERFACE_VTBL(gate_terminal) const* vtbl;
2067
2068 gate_atomic_int_t ref_counter;
2069
2070 int con_input;
2071 int con_output;
2072 int con_error;
2073 int text_color;
2074 int back_color;
2075
2076 gate_bool_t restore_termios;
2077 struct termios termios_attrs_backup;
2078
2079 } gate_terminal_console_impl_t;
2080
2081 2 static gate_terminal_console_impl_t* gate_terminal_console_create(int fd_in, int fd_out, int fd_err)
2082 {
2083 2 gate_terminal_console_impl_t* impl = gate_mem_alloc(sizeof(gate_terminal_console_impl_t));
2084
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (impl != NULL)
2085 {
2086 2 gate_mem_clear(impl, sizeof(gate_terminal_console_impl_t));
2087 2 gate_init_terminal_console_vtbl();
2088 2 impl->vtbl = &gate_terminal_console_vtbl;
2089 2 gate_atomic_int_init(&impl->ref_counter, 1);
2090 2 impl->con_input = fd_in; //STDIN_FILENO;
2091 2 impl->con_output = fd_out; //STDOUT_FILENO;
2092 2 impl->con_error = fd_err; //STDERR_FILENO;
2093 2 impl->text_color = GATE_TERMINAL_COLOR_WHITE;
2094 2 impl->back_color = GATE_TERMINAL_COLOR_BLACK;
2095 2 gate_terminal_set_text_color(impl, GATE_TERMINAL_COLOR_WHITE);
2096 2 gate_terminal_set_back_color(impl, GATE_TERMINAL_COLOR_BLACK);
2097 }
2098 2 return impl;
2099 }
2100
2101 1 gate_terminal_t* gate_terminal_console_get_current()
2102 {
2103 1 return gate_terminal_console_open(0);
2104 }
2105
2106 2 gate_terminal_t* gate_terminal_console_open(gate_enumint_t flags)
2107 {
2108 2 gate_terminal_console_impl_t* term = NULL;
2109 struct termios termios_attrs;
2110
2111 2 int fd_in = dup(STDIN_FILENO);
2112 2 int fd_out = dup(STDOUT_FILENO);
2113 2 int fd_err = dup(STDERR_FILENO);
2114
2115 2 term = gate_terminal_console_create(fd_in, fd_out, fd_err);
2116
2117
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!term)
2118 {
2119 gate_posix_close(fd_in);
2120 gate_posix_close(fd_out);
2121 gate_posix_close(fd_err);
2122 }
2123 else
2124 {
2125
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (0 == tcgetattr(term->con_input, &term->termios_attrs_backup))
2126 {
2127 gate_mem_copy(&termios_attrs, &term->termios_attrs_backup, sizeof(struct termios));
2128 term->restore_termios = true;
2129 GATE_FLAG_SET(termios_attrs.c_lflag, ICANON, false);
2130 GATE_FLAG_SET(termios_attrs.c_lflag, ECHO, GATE_FLAG_ENABLED(flags, GATE_TERMINAL_FLAG_ECHO));
2131 GATE_FLAG_SET(termios_attrs.c_lflag, ECHONL, GATE_FLAG_ENABLED(flags, GATE_TERMINAL_FLAG_ECHO));
2132 GATE_FLAG_SET(termios_attrs.c_lflag, ISIG, false);
2133 GATE_FLAG_SET(termios_attrs.c_lflag, IEXTEN, false);
2134 tcsetattr(term->con_input, TCSANOW, &termios_attrs);
2135 }
2136 }
2137 2 return (gate_terminal_t*)term;
2138 }
2139
2140
2141 2 static void gate_terminal_console_release(void* thisptr)
2142 {
2143 2 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2144
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (0 == gate_atomic_int_dec(&impl->ref_counter))
2145 {
2146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (impl->restore_termios)
2147 {
2148 tcsetattr(impl->con_input, TCSANOW, &impl->termios_attrs_backup);
2149 }
2150 2 gate_posix_close(impl->con_input);
2151 2 gate_posix_close(impl->con_output);
2152 2 gate_posix_close(impl->con_error);
2153 2 gate_mem_dealloc(impl);
2154 }
2155 2 }
2156 static int gate_terminal_console_retain(void* thisptr)
2157 {
2158 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2159 return gate_atomic_int_dec(&impl->ref_counter);
2160 }
2161 static char const* gate_terminal_console_get_interface_name(void* thisptr)
2162 {
2163 return GATE_INTERFACE_NAME_TERMINAL;
2164 }
2165
2166 static gate_result_t gate_terminal_console_read(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
2167 {
2168 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2169 gate_result_t ret;
2170 ptrdiff_t result = gate_posix_read(impl->con_input, buffer, bufferlength);
2171 if (result < 0)
2172 {
2173 gate_posix_errno(&ret);
2174 }
2175 else
2176 {
2177 if (NULL != returned)
2178 {
2179 *returned = (gate_size_t)result;
2180 }
2181 ret = GATE_RESULT_OK;
2182 }
2183 return ret;
2184 }
2185 static gate_result_t gate_terminal_console_peek(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
2186 {
2187 return GATE_RESULT_NOTSUPPORTED;
2188 }
2189 12 static gate_result_t gate_terminal_console_write(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
2190 {
2191 12 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2192 gate_result_t ret;
2193 12 ptrdiff_t result = gate_posix_write(impl->con_output, buffer, bufferlength);
2194
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (result < 0)
2195 {
2196 gate_posix_errno(&ret);
2197 }
2198 else
2199 {
2200
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 8 times.
12 if (NULL != written)
2201 {
2202 4 *written = (gate_size_t)result;
2203 }
2204 12 ret = GATE_RESULT_OK;
2205 }
2206 12 return ret;
2207 }
2208 static gate_result_t gate_terminal_console_flush(void* thisptr)
2209 {
2210 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2211 gate_result_t ret;
2212 if (fsync(impl->con_output) < 0)
2213 {
2214 gate_posix_errno(&ret);
2215 }
2216 else
2217 {
2218 ret = GATE_RESULT_OK;
2219 }
2220 return ret;
2221 }
2222
2223 static gate_result_t gate_terminal_console_get_resource(void* thisptr, gate_uint32_t resource_type, gate_uintptr_t* ptr_resource)
2224 {
2225 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2226 gate_uintptr_t res = 0;
2227 gate_result_t ret = GATE_RESULT_OK;
2228
2229 switch (resource_type)
2230 {
2231 case GATE_STREAM_RESOURCE_INPUT: res = impl->con_input; break;
2232 case GATE_STREAM_RESOURCE_OUTPUT: res = impl->con_output; break;
2233 case GATE_STREAM_RESOURCE_ERROR: res = impl->con_error; break;
2234 case GATE_STREAM_RESOURCE_DEFAULT: res = impl->con_input; break;
2235 default: ret = GATE_RESULT_INVALIDARG; break;
2236 }
2237
2238 if (ptr_resource)
2239 {
2240 *ptr_resource = res;
2241 }
2242 return ret;
2243 }
2244 static gate_result_t gate_terminal_console_await_char(void* thisptr, gate_uint32_t timeout_ms)
2245 {
2246 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2247 return gate_posix_await_read(impl->con_input, timeout_ms);
2248 }
2249 static gate_result_t gate_terminal_console_read_char(void* thisptr, gate_char32_t* ptr_char)
2250 {
2251 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2252 gate_result_t ret;
2253 char buffer[8];
2254 ret = gate_terminal_console_read(impl, buffer, 1, NULL);
2255 if (ptr_char)
2256 {
2257 *ptr_char = (gate_char32_t)(gate_uint8_t)buffer[0];
2258 }
2259 return ret;
2260 }
2261 static gate_result_t gate_terminal_console_write_err(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
2262 {
2263 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2264 gate_result_t ret;
2265 ptrdiff_t result = gate_posix_write(impl->con_error, buffer, bufferlength);
2266 if (result < 0)
2267 {
2268 gate_posix_errno(&ret);
2269 }
2270 else
2271 {
2272 if (NULL != written)
2273 {
2274 *written = (gate_size_t)result;
2275 }
2276 ret = GATE_RESULT_OK;
2277 }
2278 return ret;
2279 }
2280 static gate_result_t gate_terminal_console_flush_err(void* thisptr)
2281 {
2282 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2283 gate_result_t ret;
2284 if (fsync(impl->con_error) < 0)
2285 {
2286 gate_posix_errno(&ret);
2287 }
2288 else
2289 {
2290 ret = GATE_RESULT_OK;
2291 }
2292 return ret;
2293 }
2294
2295
2296 gate_enumint_t gate_terminal_console_get_type(void* thisptr)
2297 {
2298 return GATE_TERMINAL_TYPE_VT100;
2299 }
2300
2301 //"\x1b[0;40;37m\x1b[1;1H\x1b[2J"
2302 static gate_result_t gate_terminal_console_get_size(void* thisptr, gate_uint16_t* ptr_width, gate_uint16_t* ptr_height)
2303 {
2304 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2305 gate_result_t ret;
2306 struct winsize ws = { 0, 0, 0, 0 };
2307
2308 if (ioctl(impl->con_output, TIOCGWINSZ, &ws) != -1)
2309 {
2310 if (NULL != ptr_width) *ptr_width = (gate_uint16_t)ws.ws_col;
2311 if (NULL != ptr_height) *ptr_height = (gate_uint16_t)ws.ws_row;
2312 ret = GATE_RESULT_OK;
2313 }
2314 else
2315 {
2316 gate_posix_errno(&ret);
2317 }
2318 return ret;
2319 }
2320 static gate_result_t gate_terminal_console_get_cursor_pos(void* thisptr, gate_uint16_t* ptr_x, gate_uint16_t* ptr_y)
2321 {
2322 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2323 gate_result_t ret = GATE_RESULT_NOTSUPPORTED;
2324 struct termios t;
2325 /*TODO implementation*/
2326 (void)impl;
2327 (void)t;
2328 (void)ptr_x;
2329 (void)ptr_y;
2330 return ret;
2331 }
2332 static gate_result_t gate_terminal_console_set_cursor_pos(void* thisptr, gate_uint16_t x, gate_uint16_t y)
2333 {
2334 return gate_terminal_vt100_set_cursor_pos(thisptr, x, y);
2335 }
2336 static gate_result_t gate_terminal_console_set_cursor_mode(void* thisptr, gate_uint16_t mode)
2337 {
2338 return gate_terminal_vt100_enable_cursor(thisptr, (mode == GATE_TERMINAL_CURSOR_MODE_OFF) ? false : true);
2339 }
2340 static gate_result_t gate_terminal_console_clear(void* thisptr)
2341 {
2342 return gate_terminal_vt100_clear(thisptr);
2343 }
2344
2345
2346 6 static gate_result_t gate_terminal_console_get_text_color(void* thisptr, gate_uint8_t* ptr_color_code)
2347 {
2348 6 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2349 6 *ptr_color_code = impl->text_color;
2350 6 return GATE_RESULT_OK;
2351 }
2352
2353
2354 4 static gate_result_t gate_terminal_console_set_text_color(void* thisptr, gate_uint8_t color_code)
2355 {
2356 4 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2357 4 gate_result_t ret = gate_terminal_vt100_set_text_color(thisptr, color_code);
2358
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (GATE_SUCCEEDED(ret))
2359 {
2360 4 impl->text_color = color_code;
2361 }
2362 4 return ret;
2363 }
2364
2365 6 static gate_result_t gate_terminal_console_get_back_color(void* thisptr, gate_uint8_t* ptr_color_code)
2366 {
2367 6 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2368 6 *ptr_color_code = impl->back_color;
2369 6 return GATE_RESULT_OK;
2370 }
2371 4 static gate_result_t gate_terminal_console_set_back_color(void* thisptr, gate_uint8_t color_code)
2372 {
2373 4 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2374 4 gate_result_t ret = gate_terminal_vt100_set_back_color(thisptr, color_code);
2375
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (GATE_SUCCEEDED(ret))
2376 {
2377 4 impl->back_color = color_code;
2378 }
2379 4 return ret;
2380 }
2381
2382 #endif /* GATE_SYSTEM_TERMINALS_POSIX */
2383
2384
2385
2386 #if defined(GATE_SYSTEM_TERMINALS_DOS)
2387
2388 #include <graph.h>
2389 #include <conio.h>
2390
2391 static void gate_term_init()
2392 {
2393 _setvideomode(_TEXTC80);
2394 }
2395 static void gate_term_text_color(int textcol)
2396 {
2397 _settextcolor(textcol);
2398 }
2399 static void gate_term_back_color(int bkcol)
2400 {
2401 _setbkcolor(bkcol);
2402 }
2403 static void gate_term_text_cursor_size(int sz_0_to_3)
2404 {
2405 int value = 0;
2406 switch (sz_0_to_3)
2407 {
2408 case 3: value = 0x0007; break; /* full block */
2409 case 2: value = 0x0407; break; /* half size */
2410 case 1: value = 0x0607; break; /* underline cursor */
2411 default: value = 0x2000; break; /* no cursor /invisible */
2412 }
2413 _settextcursor(value);
2414 }
2415 static void gate_term_text_cursor_pos(char y_1_to_25, char x_1_to_80)
2416 {
2417 _settextposition(y_1_to_25, x_1_to_80);
2418 }
2419 static void gate_term_print_char(char chr)
2420 {
2421 char buf[2] = { chr, 0 };
2422 _outtext(buf);
2423 }
2424 static void gate_term_text_cursor_enable(gate_bool_t enabled)
2425 {
2426 _displaycursor(enabled ? _GCURSORON : _GCURSOROFF);
2427 }
2428 static void gate_term_print_text(char const* text)
2429 {
2430 char buffer[GATE_MAX_BLOCK_COPYBUFFER_LENGTH];
2431 gate_str_print_text(buffer, sizeof(buffer), text, gate_str_length(text));
2432 _outtext(buffer);
2433 }
2434
2435 typedef struct gate_terminal_console_impl_class
2436 {
2437 GATE_INTERFACE_VTBL(gate_terminal) const* vtbl;
2438
2439 gate_atomic_int_t ref_counter;
2440 gate_uint32_t flags;
2441 gate_uint8_t text_color;
2442 gate_uint8_t back_color;
2443 char read_buffer[64];
2444 gate_size_t read_buffer_used;
2445
2446 } gate_terminal_console_impl_t;
2447
2448 void gate_terminal_console_release(void* thisptr)
2449 {
2450 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2451 if (0 == gate_atomic_int_dec(&impl->ref_counter))
2452 {
2453 gate_mem_dealloc(impl);
2454 }
2455 }
2456 int gate_terminal_console_retain(void* thisptr)
2457 {
2458 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2459 return gate_atomic_int_inc(&impl->ref_counter);
2460 }
2461 char const* gate_terminal_console_get_interface_name(void* thisptr)
2462 {
2463 (void)thisptr;
2464 return GATE_INTERFACE_NAME_TERMINAL;
2465 }
2466
2467 static gate_size_t gate_term_read_buffer(char* buffer, gate_size_t buffer_length)
2468 {
2469 gate_size_t count = 0;
2470 unsigned int ch;
2471 while ((buffer_length > 0) && gate_dos_has_kbd_event())
2472 {
2473 if (!gate_dos_get_next_kbd_event(&ch))
2474 {
2475 break;
2476 }
2477 *buffer = (char)ch;
2478 ++buffer;
2479 ++count;
2480 --buffer_length;
2481 }
2482 return count;
2483 }
2484
2485 gate_result_t gate_terminal_console_read(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
2486 {
2487 gate_result_t ret = GATE_RESULT_FAILED;
2488 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2489 gate_size_t len = 0;
2490 unsigned int ch;
2491
2492 do
2493 {
2494 if (!buffer || !bufferlength)
2495 {
2496 ret = GATE_RESULT_INVALIDARG;
2497 break;
2498 }
2499
2500 if (impl->read_buffer_used == 0)
2501 {
2502 if (!gate_dos_get_next_kbd_event(&ch))
2503 {
2504 break;
2505 }
2506 impl->read_buffer[0] = (char)ch;
2507 impl->read_buffer_used = 1;
2508 impl->read_buffer_used += gate_term_read_buffer(&impl->read_buffer[1], sizeof(impl->read_buffer) - 1);
2509 }
2510
2511 ret = GATE_RESULT_OK;
2512 len = (bufferlength > impl->read_buffer_used) ? impl->read_buffer_used : bufferlength;
2513 gate_mem_copy(buffer, impl->read_buffer, len);
2514 if (returned)
2515 {
2516 *returned = len;
2517 }
2518
2519 if (len >= impl->read_buffer_used)
2520 {
2521 impl->read_buffer_used = 0;
2522 }
2523 else if (len > 0)
2524 {
2525 gate_mem_copy(&impl->read_buffer[0], &impl->read_buffer[len], impl->read_buffer_used - len);
2526 impl->read_buffer_used -= len;
2527 }
2528 } while (0);
2529
2530 return ret;
2531 }
2532 gate_result_t gate_terminal_console_peek(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
2533 {
2534 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2535 gate_size_t len;
2536
2537 if (!buffer || !bufferlength)
2538 {
2539 return GATE_RESULT_INVALIDARG;
2540 }
2541
2542 if (impl->read_buffer_used < sizeof(impl->read_buffer))
2543 {
2544 len = gate_term_read_buffer(&impl->read_buffer[impl->read_buffer_used], sizeof(impl->read_buffer) - impl->read_buffer_used);
2545 impl->read_buffer_used += len;
2546 }
2547
2548 len = (bufferlength > impl->read_buffer_used) ? impl->read_buffer_used : bufferlength;
2549 gate_mem_copy(buffer, impl->read_buffer, len);
2550 if (returned)
2551 {
2552 *returned = len;
2553 }
2554 return GATE_RESULT_OK;
2555 }
2556 gate_result_t gate_terminal_console_write(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
2557 {
2558 gate_result_t ret = GATE_RESULT_OK;
2559 gate_size_t processed = 0;
2560
2561 GATE_UNUSED_ARG(thisptr);
2562
2563 while (bufferlength > 0)
2564 {
2565 gate_term_print_char(*buffer);
2566 ++buffer;
2567 ++processed;
2568 --bufferlength;
2569 }
2570 if (written)
2571 {
2572 *written = processed;
2573 }
2574 return ret;
2575 }
2576 gate_result_t gate_terminal_console_flush(void* thisptr)
2577 {
2578 GATE_UNUSED_ARG(thisptr);
2579 return GATE_RESULT_OK;
2580 }
2581
2582 gate_result_t gate_terminal_console_get_resource(void* thisptr, gate_uint32_t resource_type, gate_uintptr_t* resource)
2583 {
2584 GATE_UNUSED_ARG(thisptr);
2585 GATE_UNUSED_ARG(resource_type);
2586 GATE_UNUSED_ARG(resource);
2587 return GATE_RESULT_NOTIMPLEMENTED;
2588 }
2589
2590 gate_result_t gate_terminal_console_await_char(void* thisptr, gate_uint32_t timeout_ms)
2591 {
2592 GATE_UNUSED_ARG(thisptr);
2593 return gate_dos_await_and_read_kbd(NULL, timeout_ms);
2594 }
2595 gate_result_t gate_terminal_console_read_char(void* thisptr, gate_char32_t* ptr_char)
2596 {
2597 GATE_UNUSED_ARG(thisptr);
2598 return gate_dos_await_and_read_kbd(ptr_char, -1);
2599 }
2600
2601 gate_result_t gate_terminal_console_write_err(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
2602 {
2603 GATE_UNUSED_ARG(thisptr);
2604 GATE_UNUSED_ARG(buffer);
2605 GATE_UNUSED_ARG(bufferlength);
2606 GATE_UNUSED_ARG(written);
2607 return GATE_RESULT_NOTIMPLEMENTED;
2608 }
2609 gate_result_t gate_terminal_console_flush_err(void* thisptr)
2610 {
2611 GATE_UNUSED_ARG(thisptr);
2612 return GATE_RESULT_OK;
2613 }
2614
2615 gate_enumint_t gate_terminal_console_get_type(void* thisptr)
2616 {
2617 return GATE_TERMINAL_TYPE_UI;
2618 }
2619
2620 gate_result_t gate_terminal_console_get_size(void* thisptr, gate_uint16_t* ptr_width, gate_uint16_t* ptr_height)
2621 {
2622 GATE_UNUSED_ARG(thisptr);
2623 if (ptr_width) *ptr_width = 80;
2624 if (ptr_height) *ptr_height = 25;
2625 return GATE_RESULT_OK;
2626 }
2627 gate_result_t gate_terminal_console_get_cursor_pos(void* thisptr, gate_uint16_t* ptr_x, gate_uint16_t* ptr_y)
2628 {
2629 GATE_UNUSED_ARG(thisptr);
2630 GATE_UNUSED_ARG(ptr_x);
2631 GATE_UNUSED_ARG(ptr_y);
2632 return GATE_RESULT_NOTIMPLEMENTED;
2633 }
2634 gate_result_t gate_terminal_console_set_cursor_pos(void* thisptr, gate_uint16_t x, gate_uint16_t y)
2635 {
2636 GATE_UNUSED_ARG(thisptr);
2637 if (x > 79) x = 79;
2638 if (y > 24) y = 24;
2639 gate_term_text_cursor_pos(y + 1, x + 1);
2640 return GATE_RESULT_OK;
2641 }
2642 gate_result_t gate_terminal_console_set_cursor_mode(void* thisptr, gate_uint16_t mode)
2643 {
2644 GATE_UNUSED_ARG(thisptr);
2645 gate_term_text_cursor_enable(mode == GATE_TERMINAL_CURSOR_MODE_OFF ? false : true);
2646 return GATE_RESULT_OK;
2647 }
2648 gate_result_t gate_terminal_console_clear(void* thisptr)
2649 {
2650 (void)thisptr;
2651 return GATE_RESULT_NOTIMPLEMENTED;
2652 }
2653
2654 gate_result_t gate_terminal_console_get_text_color(void* thisptr, gate_uint8_t* ptr_color_code)
2655 {
2656 (void)thisptr;
2657 (void)ptr_color_code;
2658 return GATE_RESULT_NOTIMPLEMENTED;
2659 }
2660 gate_result_t gate_terminal_console_set_text_color(void* thisptr, gate_uint8_t color_code)
2661 {
2662 (void)thisptr;
2663 gate_term_text_color(color_code);
2664 return GATE_RESULT_OK;
2665 }
2666
2667 gate_result_t gate_terminal_console_get_back_color(void* thisptr, gate_uint8_t* ptr_color_code)
2668 {
2669 (void)thisptr;
2670 (void)ptr_color_code;
2671 return GATE_RESULT_NOTIMPLEMENTED;
2672 }
2673 gate_result_t gate_terminal_console_set_back_color(void* thisptr, gate_uint8_t color_code)
2674 {
2675 (void)thisptr;
2676 gate_term_back_color(color_code);
2677 return GATE_RESULT_OK;
2678 }
2679
2680 gate_terminal_t* gate_terminal_console_get_current()
2681 {
2682 gate_terminal_console_impl_t* impl = gate_mem_alloc(sizeof(gate_terminal_console_impl_t));
2683 if (impl != NULL)
2684 {
2685 gate_mem_clear(impl, sizeof(gate_terminal_console_impl_t));
2686 gate_init_terminal_console_vtbl();
2687 impl->vtbl = &gate_terminal_console_vtbl;
2688 gate_atomic_int_init(&impl->ref_counter, 1);
2689 impl->text_color = GATE_TERMINAL_COLOR_WHITE;
2690 impl->back_color = GATE_TERMINAL_COLOR_BLACK;
2691 impl->read_buffer_used = 0;
2692 gate_term_init();
2693 }
2694 return (gate_terminal_t*)impl;
2695 }
2696
2697 gate_terminal_t* gate_terminal_console_open(gate_enumint_t flags)
2698 {
2699 (void)flags;
2700 return gate_terminal_console_get_current();
2701 }
2702
2703
2704 #endif /* GATE_SYSTEM_TERMINALS_DOS */
2705
2706
2707
2708 #if defined(GATE_SYSTEM_TERMINALS_EFI)
2709
2710 #include "gate/platform/efi/efi_gate.h"
2711
2712 typedef struct
2713 {
2714 GATE_INTERFACE_VTBL(gate_terminal)* vtbl;
2715
2716 } gate_terminal_console_efi_singleton;
2717
2718 static gate_terminal_t efi_terminal_singleton =
2719 {
2720 &gate_terminal_console_vtbl
2721 };
2722
2723
2724
2725 void gate_terminal_console_release(void* thisptr)
2726 {
2727 GATE_UNUSED_ARG(thisptr);
2728 }
2729 int gate_terminal_console_retain(void* thisptr)
2730 {
2731 GATE_UNUSED_ARG(thisptr);
2732 return 1;
2733 }
2734 char const* gate_terminal_console_get_interface_name(void* thisptr)
2735 {
2736 GATE_UNUSED_ARG(thisptr);
2737 return GATE_INTERFACE_NAME_TERMINAL;
2738 }
2739
2740 gate_result_t gate_terminal_console_read(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
2741 {
2742 gate_result_t result = GATE_RESULT_INVALIDARG;
2743 gate_uint32_t next_timeout = (gate_uint32_t)-1;
2744 gate_char16_t chr;
2745 gate_uint16_t scancode;
2746 gate_size_t len;
2747 gate_size_t len_returned = 0;
2748 GATE_UNUSED_ARG(thisptr);
2749
2750 while (buffer && (bufferlength > 0))
2751 {
2752 result = gate_platform_efi_console_await_char(next_timeout);
2753 GATE_BREAK_IF_FAILED(result);
2754 next_timeout = 0;
2755 result = gate_platform_efi_console_read_char(&chr, &scancode, true);
2756 GATE_BREAK_IF_FAILED(result);
2757
2758 len = gate_char_write_utf8((gate_char32_t)chr, buffer, bufferlength);
2759 len_returned += len;
2760 buffer += len;
2761 bufferlength -= len;
2762 }
2763
2764 if (returned)
2765 {
2766 *returned = len_returned;
2767 }
2768 if ((result == GATE_RESULT_TIMEOUT) && (len_returned > 0))
2769 {
2770 result = GATE_RESULT_OK;
2771 }
2772 return result;
2773 }
2774 gate_result_t gate_terminal_console_peek(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
2775 {
2776 GATE_UNUSED_ARG(thisptr);
2777 GATE_UNUSED_ARG(buffer);
2778 GATE_UNUSED_ARG(bufferlength);
2779 GATE_UNUSED_ARG(returned);
2780
2781 return GATE_RESULT_NOTIMPLEMENTED;
2782 }
2783 gate_result_t gate_terminal_console_write(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
2784 {
2785 gate_result_t result;
2786 gate_char32_t chr32;
2787 gate_size_t length;
2788 gate_size_t bytes_written = 0;
2789
2790 GATE_UNUSED_ARG(thisptr);
2791
2792 while (buffer && (bufferlength > 0))
2793 {
2794 length = gate_char_read_utf8(buffer, bufferlength, &chr32);
2795 buffer += length;
2796 bufferlength -= length;
2797 result = gate_platform_efi_console_write_char((gate_char16_t)chr32);
2798 GATE_BREAK_IF_FAILED(result);
2799 bytes_written += length;
2800 }
2801 if (written)
2802 {
2803 *written = bytes_written;
2804 }
2805 if (GATE_FAILED(result) && (bytes_written > 0))
2806 {
2807 result = GATE_RESULT_OK;
2808 }
2809 return result;
2810 }
2811 gate_result_t gate_terminal_console_flush(void* thisptr)
2812 {
2813 GATE_UNUSED_ARG(thisptr);
2814 return GATE_RESULT_OK;
2815 }
2816
2817 gate_result_t gate_terminal_console_get_resource(void* thisptr, gate_uint32_t resource_type, gate_uintptr_t* resource)
2818 {
2819 GATE_UNUSED_ARG(thisptr);
2820 GATE_UNUSED_ARG(resource_type);
2821 GATE_UNUSED_ARG(resource);
2822 return GATE_RESULT_NOTIMPLEMENTED;
2823 }
2824
2825 gate_result_t gate_terminal_console_await_char(void* thisptr, gate_uint32_t timeout_ms)
2826 {
2827 gate_result_t result;
2828 GATE_UNUSED_ARG(thisptr);
2829
2830 result = gate_platform_efi_console_await_char(timeout_ms == GATE_CONSOLE_TIMEOUT_NEVER ? (gate_uint32_t)-1 : timeout_ms);
2831 return result;
2832 }
2833 gate_result_t gate_terminal_console_read_char(void* thisptr, gate_char32_t* ptr_char)
2834 {
2835 gate_result_t result;
2836 gate_char16_t chr16 = 0;
2837 gate_uint16_t scan_code = 0;
2838 GATE_UNUSED_ARG(thisptr);
2839 result = gate_platform_efi_console_read_char(&chr16, &scan_code, false);
2840 if (ptr_char)
2841 {
2842 *ptr_char = (gate_char32_t)chr16;
2843 }
2844 return result;
2845 }
2846 gate_result_t gate_terminal_console_write_err(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
2847 {
2848 GATE_UNUSED_ARG(thisptr);
2849 GATE_UNUSED_ARG(buffer);
2850 GATE_UNUSED_ARG(bufferlength);
2851 GATE_UNUSED_ARG(written);
2852 return GATE_RESULT_NOTIMPLEMENTED;
2853 }
2854 gate_result_t gate_terminal_console_flush_err(void* thisptr)
2855 {
2856 (void)thisptr;
2857 return GATE_RESULT_NOTIMPLEMENTED;
2858 }
2859
2860 gate_enumint_t gate_terminal_console_get_type(void* thisptr)
2861 {
2862 return GATE_TERMINAL_TYPE_UI;
2863 }
2864
2865 gate_result_t gate_terminal_console_get_size(void* thisptr, gate_uint16_t* ptr_width, gate_uint16_t* ptr_height)
2866 {
2867 GATE_UNUSED_ARG(thisptr);
2868 return gate_platform_efi_console_get_size(ptr_width, ptr_height);
2869 }
2870 gate_result_t gate_terminal_console_get_cursor_pos(void* thisptr, gate_uint16_t* ptr_x, gate_uint16_t* ptr_y)
2871 {
2872 GATE_UNUSED_ARG(thisptr);
2873 return gate_platform_efi_console_get_cursor_pos(ptr_x, ptr_y);
2874 }
2875 gate_result_t gate_terminal_console_set_cursor_pos(void* thisptr, gate_uint16_t x, gate_uint16_t y)
2876 {
2877 GATE_UNUSED_ARG(thisptr);
2878 return gate_platform_efi_console_set_cursor_pos(x, y);
2879 }
2880 gate_result_t gate_terminal_console_set_cursor_mode(void* thisptr, gate_uint16_t mode)
2881 {
2882 GATE_UNUSED_ARG(thisptr);
2883 return gate_platform_efi_console_enable_cursor(mode == GATE_TERMINAL_CURSOR_MODE_OFF ? false : true);
2884 }
2885
2886 gate_result_t gate_terminal_console_clear(void* thisptr)
2887 {
2888 GATE_UNUSED_ARG(thisptr);
2889 return gate_platform_efi_console_clear();
2890 }
2891
2892 gate_result_t gate_terminal_console_get_text_color(void* thisptr, gate_uint8_t* ptr_color_code)
2893 {
2894 GATE_UNUSED_ARG(thisptr);
2895 gate_uint8_t dummy = 0;
2896 return gate_platform_efi_console_get_color(ptr_color_code, &dummy);
2897 }
2898 gate_result_t gate_terminal_console_set_text_color(void* thisptr, gate_uint8_t color_code)
2899 {
2900 GATE_UNUSED_ARG(thisptr);
2901 gate_uint8_t dummy = 0;
2902 gate_uint8_t backcolor = 0;
2903 gate_platform_efi_console_get_color(&dummy, &backcolor);
2904 return gate_platform_efi_console_set_color(color_code, backcolor);
2905 }
2906
2907 gate_result_t gate_terminal_console_get_back_color(void* thisptr, gate_uint8_t* ptr_color_code)
2908 {
2909 GATE_UNUSED_ARG(thisptr);
2910 gate_uint8_t dummy = 0;
2911 return gate_platform_efi_console_get_color(&dummy, ptr_color_code);
2912 }
2913 gate_result_t gate_terminal_console_set_back_color(void* thisptr, gate_uint8_t color_code)
2914 {
2915 GATE_UNUSED_ARG(thisptr);
2916 gate_uint8_t dummy = 0;
2917 gate_uint8_t textcolor = 0;
2918 gate_platform_efi_console_get_color(&textcolor, &dummy);
2919 return gate_platform_efi_console_set_color(textcolor, color_code);
2920 }
2921
2922 gate_terminal_t* gate_terminal_console_get_current()
2923 {
2924 gate_init_terminal_console_vtbl();
2925 return &efi_terminal_singleton;
2926 }
2927
2928 gate_terminal_t* gate_terminal_console_open(gate_enumint_t flags)
2929 {
2930 GATE_UNUSED_ARG(flags);
2931 gate_init_terminal_console_vtbl();
2932 return &efi_terminal_singleton;
2933 }
2934
2935 #endif /* GATE_SYSTEM_TERMINALS_EFI*/
2936
2937
2938
2939 #if defined(GATE_SYSTEM_TERMINALS_NOIMPL)
2940
2941 void gate_terminal_console_release(void* thisptr)
2942 {
2943 GATE_UNUSED_ARG(thisptr);
2944 }
2945 int gate_terminal_console_retain(void* thisptr)
2946 {
2947 GATE_UNUSED_ARG(thisptr);
2948 return 1;
2949 }
2950 char const* gate_terminal_console_get_interface_name(void* thisptr)
2951 {
2952 GATE_UNUSED_ARG(thisptr);
2953 return NULL;
2954 }
2955
2956 gate_result_t gate_terminal_console_read(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
2957 {
2958 GATE_UNUSED_ARG(thisptr);
2959 GATE_UNUSED_ARG(buffer);
2960 GATE_UNUSED_ARG(bufferlength);
2961 GATE_UNUSED_ARG(returned);
2962 return GATE_RESULT_NOTIMPLEMENTED;
2963 }
2964 gate_result_t gate_terminal_console_peek(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
2965 {
2966 GATE_UNUSED_ARG(thisptr);
2967 GATE_UNUSED_ARG(buffer);
2968 GATE_UNUSED_ARG(bufferlength);
2969 GATE_UNUSED_ARG(returned);
2970 return GATE_RESULT_NOTIMPLEMENTED;
2971 }
2972 gate_result_t gate_terminal_console_write(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
2973 {
2974 GATE_UNUSED_ARG(thisptr);
2975 GATE_UNUSED_ARG(buffer);
2976 GATE_UNUSED_ARG(bufferlength);
2977 GATE_UNUSED_ARG(written);
2978 return GATE_RESULT_NOTIMPLEMENTED;
2979 }
2980 gate_result_t gate_terminal_console_flush(void* thisptr)
2981 {
2982 GATE_UNUSED_ARG(thisptr);
2983 return GATE_RESULT_NOTIMPLEMENTED;
2984 }
2985
2986 gate_result_t gate_terminal_console_get_resource(void* thisptr, gate_uint32_t resource_type, gate_uintptr_t* resource)
2987 {
2988 GATE_UNUSED_ARG(thisptr);
2989 GATE_UNUSED_ARG(resource_type);
2990 GATE_UNUSED_ARG(resource);
2991 return GATE_RESULT_NOTIMPLEMENTED;
2992 }
2993
2994 gate_result_t gate_terminal_console_await_char(void* thisptr, gate_uint32_t timeout_ms)
2995 {
2996 GATE_UNUSED_ARG(thisptr);
2997 GATE_UNUSED_ARG(timeout_ms);
2998 return GATE_RESULT_NOTIMPLEMENTED;
2999 }
3000 gate_result_t gate_terminal_console_read_char(void* thisptr, gate_char32_t* ptr_char)
3001 {
3002 GATE_UNUSED_ARG(thisptr);
3003 GATE_UNUSED_ARG(ptr_char);
3004 return GATE_RESULT_NOTIMPLEMENTED;
3005 }
3006 gate_result_t gate_terminal_console_write_err(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
3007 {
3008 GATE_UNUSED_ARG(thisptr);
3009 GATE_UNUSED_ARG(buffer);
3010 GATE_UNUSED_ARG(bufferlength);
3011 GATE_UNUSED_ARG(written);
3012 return GATE_RESULT_NOTIMPLEMENTED;
3013 }
3014 gate_result_t gate_terminal_console_flush_err(void* thisptr)
3015 {
3016 (void)thisptr;
3017 return GATE_RESULT_NOTIMPLEMENTED;
3018 }
3019
3020 gate_enumint_t gate_terminal_console_get_type(void* thisptr)
3021 {
3022 return GATE_TERMINAL_TYPE_UNKNOWN;
3023 }
3024
3025 gate_result_t gate_terminal_console_get_size(void* thisptr, gate_uint16_t* ptr_width, gate_uint16_t* ptr_height)
3026 {
3027 GATE_UNUSED_ARG(thisptr);
3028 GATE_UNUSED_ARG(ptr_width);
3029 GATE_UNUSED_ARG(ptr_height);
3030 return GATE_RESULT_NOTIMPLEMENTED;
3031 }
3032 gate_result_t gate_terminal_console_get_cursor_pos(void* thisptr, gate_uint16_t* ptr_x, gate_uint16_t* ptr_y)
3033 {
3034 GATE_UNUSED_ARG(thisptr);
3035 GATE_UNUSED_ARG(ptr_x);
3036 GATE_UNUSED_ARG(ptr_y);
3037 return GATE_RESULT_NOTIMPLEMENTED;
3038 }
3039 gate_result_t gate_terminal_console_set_cursor_pos(void* thisptr, gate_uint16_t x, gate_uint16_t y)
3040 {
3041 GATE_UNUSED_ARG(thisptr);
3042 GATE_UNUSED_ARG(x);
3043 GATE_UNUSED_ARG(y);
3044 return GATE_RESULT_NOTIMPLEMENTED;
3045 }
3046 gate_result_t gate_terminal_console_set_cursor_mode(void* thisptr, gate_uint16_t mode)
3047 {
3048 GATE_UNUSED_ARG(thisptr);
3049 GATE_UNUSED_ARG(mode);
3050 return GATE_RESULT_NOTIMPLEMENTED;
3051 }
3052 gate_result_t gate_terminal_console_clear(void* thisptr)
3053 {
3054 GATE_UNUSED_ARG(thisptr);
3055 return GATE_RESULT_NOTIMPLEMENTED;
3056 }
3057
3058 gate_result_t gate_terminal_console_get_text_color(void* thisptr, gate_uint8_t* ptr_color_code)
3059 {
3060 GATE_UNUSED_ARG(thisptr);
3061 GATE_UNUSED_ARG(ptr_color_code);
3062 return GATE_RESULT_NOTIMPLEMENTED;
3063 }
3064 gate_result_t gate_terminal_console_set_text_color(void* thisptr, gate_uint8_t color_code)
3065 {
3066 GATE_UNUSED_ARG(thisptr);
3067 GATE_UNUSED_ARG(color_code);
3068 return GATE_RESULT_NOTIMPLEMENTED;
3069 }
3070
3071 gate_result_t gate_terminal_console_get_back_color(void* thisptr, gate_uint8_t* ptr_color_code)
3072 {
3073 GATE_UNUSED_ARG(thisptr);
3074 GATE_UNUSED_ARG(ptr_color_code);
3075 return GATE_RESULT_NOTIMPLEMENTED;
3076 }
3077 gate_result_t gate_terminal_console_set_back_color(void* thisptr, gate_uint8_t color_code)
3078 {
3079 GATE_UNUSED_ARG(thisptr);
3080 GATE_UNUSED_ARG(color_code);
3081 return GATE_RESULT_NOTIMPLEMENTED;
3082 }
3083
3084 gate_terminal_t* gate_terminal_console_get_current()
3085 {
3086 return NULL;
3087 }
3088
3089 gate_terminal_t* gate_terminal_console_open(gate_enumint_t flags)
3090 {
3091 GATE_UNUSED_ARG(flags);
3092 return NULL;
3093 }
3094
3095 #endif /* GATE_SYSTEM_TERMINALS_NOIMPL */
3096