GCC Code Coverage Report


Directory: src/gate/
File: src/gate/system/terminals.c
Date: 2025-12-12 23:40:09
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 y;
593 for (y = 0; y != self->rows; ++y)
594 {
595 unsigned x;
596 vterm_cell_t* ptr_cell = self->lines[y];
597 for (x = 0; x != self->cols; ++x)
598 {
599 ptr_cell->character = ' ';
600 ptr_cell->color = self->cursor_color;
601 ptr_cell->flags = 0;
602 ++ptr_cell;
603 }
604 }
605
606 return GATE_RESULT_OK;
607 }
608
609 static gate_result_t vterm_get_text_color(void* thisptr, gate_uint8_t* ptr_color_code)
610 {
611 vterm_t* self = (vterm_t*)thisptr;
612 if (ptr_color_code)
613 {
614 *ptr_color_code = self->cursor_color & 0x0f;
615 }
616 return GATE_RESULT_OK;
617 }
618 static gate_result_t vterm_set_text_color(void* thisptr, gate_uint8_t color_code)
619 {
620 vterm_t* self = (vterm_t*)thisptr;
621 self->cursor_color = (self->cursor_color & 0xf0) | (color_code & 0xf);
622 return GATE_RESULT_OK;
623 }
624
625 static gate_result_t vterm_get_back_color(void* thisptr, gate_uint8_t* ptr_color_code)
626 {
627 vterm_t* self = (vterm_t*)thisptr;
628 if (ptr_color_code)
629 {
630 *ptr_color_code = ((self->cursor_color & 0xf0) >> 4);
631 }
632 return GATE_RESULT_OK;
633 }
634 static gate_result_t vterm_set_back_color(void* thisptr, gate_uint8_t color_code)
635 {
636 vterm_t* self = (vterm_t*)thisptr;
637 self->cursor_color = (self->cursor_color & 0x0f) | ((color_code & 0xf) << 4);
638 return GATE_RESULT_OK;
639 }
640
641
642 static GATE_INTERFACE_VTBL(gate_terminal) vterm_vtbl;
643
644 static void init_vterm_vtbl()
645 {
646 if (vterm_vtbl.get_interface_name == NULL)
647 {
648 GATE_INTERFACE_VTBL(gate_terminal) const vtbl = {
649 &vterm_get_interface_name,
650 &vterm_release,
651 &vterm_retain,
652 &vterm_read,
653 &vterm_peek,
654 &vterm_write,
655 &vterm_flush,
656 &vterm_get_resource,
657 &vterm_await_char,
658 &vterm_read_char,
659 &vterm_write_err,
660 &vterm_flush_err,
661 &vterm_get_type,
662 &vterm_get_size,
663 &vterm_get_cursor_pos,
664 &vterm_set_cursor_pos,
665 &vterm_set_cursor_mode,
666 &vterm_clear,
667 &vterm_get_text_color,
668 &vterm_set_text_color,
669 &vterm_get_back_color,
670 &vterm_set_back_color
671 };
672 vterm_vtbl = vtbl;
673 }
674 }
675
676 gate_terminal_t* gate_terminal_virtual_create(gate_uint16_t columns, gate_uint16_t rows, gate_enumint_t flags,
677 gate_terminal_read_char_t read_callback, void* read_param,
678 gate_terminal_write_char_t write_callback, void* write_param)
679 {
680 gate_terminal_t* ret = NULL;
681 vterm_t* ptr = NULL;
682
683 do
684 {
685 gate_size_t line_length;
686 gate_size_t additional_size;
687 char* first_line_ptr;
688 char* first_cell_ptr;
689 gate_size_t ndx;
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 #include "gate/platforms.h"
749
750 #if defined(GATE_SYS_WINCE)
751 # include <stdio.h>
752 #endif
753
754 typedef struct gate_terminal_console_impl_class
755 {
756 GATE_INTERFACE_VTBL(gate_terminal) const* vtbl;
757
758 gate_atomic_int_t ref_counter;
759 gate_uint32_t flags;
760
761 HANDLE con_input; /**< stdin */
762 HANDLE con_output; /**< stdout */
763 HANDLE con_error; /**< stderr */
764
765 gate_bool_t is_native_input; /**< stdin is from native console (false: redirected stream) */
766 gate_bool_t is_native_output; /**< stdout is on native console (false: redirected stream/pipe) */
767 gate_bool_t is_native_error; /**< stderr is on native console (false: redirected stream/pipe) */
768
769 gate_char32_t char_buffer[16];
770 gate_size_t char_buffer_used;
771
772 } gate_terminal_console_impl_t;
773
774 static gate_bool_t check_if_native_console_handle(HANDLE h)
775 {
776 #if defined(GATE_SYS_WINCE)
777 return false;
778 #else
779 DWORD dummy = 0;
780 const gate_bool_t is_char_device = GetFileType(h) == FILE_TYPE_CHAR;
781 const gate_bool_t can_get_con_mode = GetConsoleMode(h, &dummy) == TRUE;
782 return is_char_device && can_get_con_mode;
783 #endif
784 }
785
786 static void close_file_handle(HANDLE handle)
787 {
788 if ((handle != NULL) && (handle != INVALID_HANDLE_VALUE))
789 {
790 CloseHandle(handle);
791 }
792 }
793
794 #ifndef GATE_SYS_WINCE
795
796 #ifndef ENABLE_VIRTUAL_TERMINAL_INPUT
797 #define ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200
798 #endif
799
800 #ifndef ENABLE_QUICK_EDIT_MODE
801 #define ENABLE_QUICK_EDIT_MODE 0x0040
802 #endif
803
804 #ifndef ENABLE_INSERT_MODE
805 #define ENABLE_INSERT_MODE 0x0020
806 #endif
807
808 static BOOL gate_terminal_console_set_input_flags(HANDLE handle, gate_uint32_t flags)
809 {
810 BOOL ret = FALSE;
811 DWORD dwMode = 0;
812 if (!GetConsoleMode(handle, &dwMode))
813 {
814 return FALSE;
815 }
816
817 GATE_FLAG_SET(dwMode, ENABLE_WINDOW_INPUT, true);
818 GATE_FLAG_SET(dwMode, ENABLE_QUICK_EDIT_MODE, false);
819 GATE_FLAG_SET(dwMode, ENABLE_PROCESSED_INPUT, !GATE_FLAG_ENABLED(flags, GATE_TERMINAL_FLAG_GETCTRL));
820 GATE_FLAG_SET(dwMode, ENABLE_MOUSE_INPUT, true);
821 GATE_FLAG_SET(dwMode, ENABLE_INSERT_MODE, false);
822 GATE_FLAG_SET(dwMode, ENABLE_ECHO_INPUT, GATE_FLAG_ENABLED(flags, GATE_TERMINAL_FLAG_ECHO));
823 ret = SetConsoleMode(handle, dwMode);
824 if (GATE_SUCCEEDED(ret))
825 {
826 // VT100 support is optional (not available before Windows 10)
827 GATE_FLAG_SET(dwMode, ENABLE_VIRTUAL_TERMINAL_INPUT, GATE_FLAG_ENABLED(flags, GATE_TERMINAL_FLAG_VT100));
828 }
829 return ret;
830 }
831
832 #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
833 #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
834 #endif
835
836 static BOOL gate_terminal_console_set_output_flags(HANDLE handle, gate_uint32_t flags)
837 {
838 BOOL ret = FALSE;
839 DWORD dwMode = 0;
840 if (!GetConsoleMode(handle, &dwMode))
841 {
842 return FALSE;
843 }
844
845 GATE_FLAG_SET(dwMode, ENABLE_PROCESSED_OUTPUT, true);
846 GATE_FLAG_SET(dwMode, ENABLE_WRAP_AT_EOL_OUTPUT, true);
847 ret = SetConsoleMode(handle, dwMode);
848 if (GATE_SUCCEEDED(ret))
849 {
850 // VT100 support is optional (not available before Windows 10)
851 GATE_FLAG_SET(dwMode, ENABLE_VIRTUAL_TERMINAL_PROCESSING, GATE_FLAG_ENABLED(flags, GATE_TERMINAL_FLAG_VT100));
852 SetConsoleMode(handle, dwMode);
853 }
854 return ret;
855 }
856
857 #endif
858
859 gate_terminal_t* gate_terminal_console_get_current()
860 {
861 gate_terminal_t* ret = NULL;
862 gate_terminal_console_impl_t* impl = NULL;
863 HANDLE hProc = GetCurrentProcess();
864 HANDLE hConOut, hConIn, hConErr;
865 HANDLE hOutput = INVALID_HANDLE_VALUE;
866 HANDLE hInput = INVALID_HANDLE_VALUE;
867 HANDLE hError = INVALID_HANDLE_VALUE;
868
869 do
870 {
871 /* OUTPUT handle */
872 #if defined(GATE_SYS_WINCE)
873 # if defined(GATE_COMPILER_MSVC)
874 hConOut = (HANDLE)fileno(stdout);
875 hConIn = (HANDLE)fileno(stdin);
876 hConErr = (HANDLE)fileno(stderr);
877 # else
878 hConOut = (HANDLE)STDOUT_FILENO;
879 hConIn = (HANDLE)STDIN_FILENO;
880 hConErr = (HANDLE)STDERR_FILENO;
881 # endif
882 #else
883 hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
884 hConIn = GetStdHandle(STD_INPUT_HANDLE);
885 hConErr = GetStdHandle(STD_ERROR_HANDLE);
886 #endif
887 if ((hConOut == INVALID_HANDLE_VALUE) || (hConIn == INVALID_HANDLE_VALUE))
888 {
889 break;
890 }
891
892 if (!DuplicateHandle(hProc, hConOut, hProc, &hOutput, 0, FALSE, DUPLICATE_SAME_ACCESS))
893 {
894 break;
895 }
896 if (!DuplicateHandle(hProc, hConIn, hProc, &hInput, 0, FALSE, DUPLICATE_SAME_ACCESS))
897 {
898 break;
899 }
900 if (hConErr != INVALID_HANDLE_VALUE)
901 {
902 if (!DuplicateHandle(hProc, hConErr, hProc, &hError, 0, FALSE, DUPLICATE_SAME_ACCESS))
903 {
904 break;
905 }
906 }
907 else
908 {
909 hError = INVALID_HANDLE_VALUE;
910 }
911
912 impl = (gate_terminal_console_impl_t*)gate_mem_alloc(sizeof(gate_terminal_console_impl_t));
913 if (impl == NULL)
914 {
915 break;
916 }
917 gate_mem_clear(impl, sizeof(gate_terminal_console_impl_t));
918
919 gate_init_terminal_console_vtbl();
920 impl->vtbl = &gate_terminal_console_vtbl;
921 gate_atomic_int_init(&impl->ref_counter, 1);
922 impl->con_input = hInput;
923 impl->con_output = hOutput;
924 impl->con_error = hError;
925 impl->is_native_input = check_if_native_console_handle(impl->con_input);
926 impl->is_native_output = check_if_native_console_handle(impl->con_output);
927 impl->is_native_error = check_if_native_console_handle(impl->con_error);
928 hInput = NULL;
929 hOutput = NULL;
930 hError = NULL;
931
932 ret = (gate_terminal_t*)impl;
933 impl = NULL;
934
935 } while (0);
936
937 close_file_handle(hInput);
938 close_file_handle(hOutput);
939 close_file_handle(hError);
940
941 if (impl != NULL)
942 {
943 gate_mem_dealloc(impl);
944 }
945 return ret;
946 }
947
948
949 #ifdef GATE_SYS_WINCE
950
951 gate_terminal_t* gate_terminal_console_open(gate_enumint_t flags)
952 {
953 return gate_terminal_console_get_current();
954 }
955
956 #else
957
958 gate_terminal_t* gate_terminal_console_open(gate_enumint_t flags)
959 {
960 gate_terminal_t* ret = NULL;
961 gate_terminal_console_impl_t* impl = NULL;
962 HANDLE hProc = GetCurrentProcess();
963 HANDLE hCon = INVALID_HANDLE_VALUE;
964 HANDLE hInput = INVALID_HANDLE_VALUE;
965 HANDLE hOutput = INVALID_HANDLE_VALUE;
966 HANDLE hError = INVALID_HANDLE_VALUE;
967
968 do
969 {
970 AllocConsole();
971
972 /* open console input buffer */
973 hInput = gate_win32_createfile(_T("CONIN$"),
974 GENERIC_READ | GENERIC_WRITE,
975 FILE_SHARE_READ | FILE_SHARE_WRITE,
976 OPEN_EXISTING, 0, 0, NULL);
977 if (INVALID_HANDLE_VALUE == hInput)
978 {
979 /* try stdin as alternative */
980 if (!DuplicateHandle(hProc, GetStdHandle(STD_INPUT_HANDLE), hProc, &hInput, 0, FALSE, DUPLICATE_SAME_ACCESS))
981 {
982 break;
983 }
984 }
985
986 /* open console output buffer */
987 hCon = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
988 if (INVALID_HANDLE_VALUE == hCon)
989 {
990 break;
991 }
992
993 if (!DuplicateHandle(hProc, hCon, hProc, &hOutput, 0, FALSE, DUPLICATE_SAME_ACCESS))
994 {
995 break;
996 }
997 if (!DuplicateHandle(hProc, hCon, hProc, &hError, 0, FALSE, DUPLICATE_SAME_ACCESS))
998 {
999 break;
1000 }
1001
1002 impl = (gate_terminal_console_impl_t*)gate_mem_alloc(sizeof(gate_terminal_console_impl_t));
1003 if (impl == NULL)
1004 {
1005 break;
1006 }
1007
1008 if (!SetConsoleActiveScreenBuffer(hOutput))
1009 {
1010 break;
1011 }
1012
1013 if (!gate_terminal_console_set_output_flags(hOutput, flags))
1014 {
1015 break;
1016 }
1017 if (!gate_terminal_console_set_input_flags(hInput, flags))
1018 {
1019 break;
1020 }
1021
1022 gate_mem_clear(impl, sizeof(gate_terminal_console_impl_t));
1023
1024 gate_init_terminal_console_vtbl();
1025 impl->vtbl = &gate_terminal_console_vtbl;
1026 gate_atomic_int_init(&impl->ref_counter, 1);
1027 impl->con_input = hInput;
1028 impl->con_output = hOutput;
1029 impl->con_error = hError;
1030 impl->is_native_input = check_if_native_console_handle(impl->con_input);
1031 impl->is_native_output = check_if_native_console_handle(impl->con_output);
1032 impl->is_native_error = check_if_native_console_handle(impl->con_error);
1033 impl->flags = flags;
1034 hInput = NULL;
1035 hOutput = NULL;
1036 hError = NULL;
1037
1038 ret = (gate_terminal_t*)impl;
1039 impl = NULL;
1040
1041 } while (0);
1042
1043 close_file_handle(hCon);
1044 close_file_handle(hInput);
1045 close_file_handle(hOutput);
1046 close_file_handle(hError);
1047
1048 if (impl != NULL)
1049 {
1050 gate_mem_dealloc(impl);
1051 }
1052 return ret;
1053 }
1054 #endif
1055
1056 void gate_terminal_console_release(void* thisptr)
1057 {
1058 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
1059 if (0 == gate_atomic_int_dec(&impl->ref_counter))
1060 {
1061 close_file_handle(impl->con_input);
1062 close_file_handle(impl->con_output);
1063 close_file_handle(impl->con_error);
1064 gate_mem_dealloc(impl);
1065 }
1066 }
1067
1068 int gate_terminal_console_retain(void* thisptr)
1069 {
1070 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
1071 return gate_atomic_int_inc(&impl->ref_counter);
1072 }
1073
1074 char const* gate_terminal_console_get_interface_name(void* thisptr)
1075 {
1076 GATE_UNUSED_ARG(thisptr);
1077 return GATE_INTERFACE_NAME_TERMINAL;
1078 }
1079
1080 #ifdef GATE_SYS_WINCE
1081 # define winapi_console_read(handle, ptr_buffer, bufferlength, ptr_bufferused) gate_win32_readfile(handle, ptr_buffer, bufferlength, ptr_bufferused, NULL)
1082 #else
1083 # define winapi_console_read(handle, ptr_buffer, bufferlength, ptr_bufferused) ReadConsole(handle, ptr_buffer, bufferlength, ptr_bufferused, NULL)
1084 #endif
1085
1086 gate_result_t gate_terminal_console_read(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
1087 {
1088 gate_result_t ret = GATE_RESULT_FAILED;
1089 gate_terminal_console_impl_t* const impl = (gate_terminal_console_impl_t*)thisptr;
1090 do
1091 {
1092 DWORD chars_read = 0;
1093 BOOL succeeded;
1094
1095
1096 if (impl->is_native_input)
1097 {
1098 succeeded = winapi_console_read(impl->con_input, buffer, (DWORD)bufferlength, &chars_read);
1099 }
1100 else
1101 {
1102 succeeded = gate_win32_readfile(impl->con_input, buffer, (DWORD)bufferlength, &chars_read, NULL);
1103 }
1104
1105 if (!succeeded)
1106 {
1107 DWORD lasterr = GetLastError();
1108 if (lasterr != ERROR_INVALID_FUNCTION)
1109 {
1110 gate_win32_print_lasterror_code(lasterr, &ret, NULL, 0);
1111 break;
1112 }
1113 if (!gate_win32_readfile(impl->con_input, buffer, (DWORD)bufferlength, &chars_read, NULL))
1114 {
1115 lasterr = GetLastError();
1116 gate_win32_print_lasterror_code(lasterr, &ret, NULL, 0);
1117 break;
1118 }
1119 }
1120 if ((gate_size_t)chars_read < bufferlength)
1121 {
1122 buffer[chars_read] = 0;
1123 }
1124 if (returned)
1125 {
1126 *returned = (gate_size_t)chars_read;
1127 }
1128 ret = GATE_RESULT_OK;
1129 } while (0);
1130
1131 return ret;
1132 }
1133
1134 gate_result_t gate_terminal_console_peek(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
1135 {
1136 GATE_UNUSED_ARG(thisptr);
1137 GATE_UNUSED_ARG(buffer);
1138 GATE_UNUSED_ARG(bufferlength);
1139 GATE_UNUSED_ARG(returned);
1140 return GATE_RESULT_NOTSUPPORTED;
1141 }
1142
1143 #if defined(GATE_SYS_WINCE)
1144 # define winapi_write_console(handle, ptr_buffer, bufferlength, ptr_bufferprocessed) gate_win32_writefile(handle, ptr_buffer, bufferlength, ptr_bufferprocessed, NULL)
1145 #else
1146 # define winapi_write_console(handle, ptr_buffer, bufferlength, ptr_bufferprocessed) WriteConsole(handle, ptr_buffer, bufferlength, ptr_bufferprocessed, NULL)
1147 #endif
1148
1149 static gate_result_t gate_terminal_console_write_to_handle(HANDLE handle, gate_bool_t is_native_con, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
1150 {
1151 gate_result_t ret = GATE_RESULT_OK;
1152 DWORD chars_written = 0;
1153 TCHAR text_buffer[7168];
1154 TCHAR* ptr_text = &text_buffer[0];
1155 gate_size_t text_len = sizeof(text_buffer) / sizeof(text_buffer[0]);
1156 gate_size_t text_used;
1157 do
1158 {
1159 BOOL succeeded;
1160 if (bufferlength > text_len)
1161 {
1162 text_len = bufferlength * sizeof(TCHAR);
1163 ptr_text = (TCHAR*)gate_mem_alloc(text_len);
1164 if (ptr_text == NULL)
1165 {
1166 ret = GATE_RESULT_FAILED;
1167 break;
1168 }
1169 }
1170
1171 text_used = gate_win32_utf8_2_winstr(buffer, bufferlength, ptr_text, text_len);
1172 if (is_native_con)
1173 {
1174 succeeded = winapi_write_console(handle, ptr_text, (DWORD)text_used, &chars_written);
1175 }
1176 else
1177 {
1178 succeeded = gate_win32_writefile(handle, buffer, (DWORD)bufferlength, &chars_written, NULL);
1179 }
1180 if (!succeeded && is_native_con)
1181 {
1182 DWORD lasterr = GetLastError();
1183 if (lasterr != ERROR_INVALID_FUNCTION)
1184 {
1185 gate_win32_print_lasterror_code(lasterr, &ret, NULL, 0);
1186 break;
1187 }
1188
1189 if (!gate_win32_writefile(handle, buffer, (DWORD)bufferlength, &chars_written, NULL))
1190 {
1191 lasterr = GetLastError();
1192 gate_win32_print_lasterror_code(lasterr, &ret, NULL, 0);
1193 break;
1194 }
1195 }
1196
1197 if (NULL != written)
1198 {
1199 if (chars_written == text_used)
1200 {
1201 *written = bufferlength;
1202 }
1203 else
1204 {
1205 *written = (gate_size_t)chars_written;
1206 }
1207 }
1208 ret = GATE_RESULT_OK;
1209 } while (0);
1210
1211 if ((ptr_text != NULL) && (ptr_text != &text_buffer[0]))
1212 {
1213 gate_mem_dealloc(ptr_text);
1214 }
1215
1216 return ret;
1217
1218 }
1219
1220 gate_result_t gate_terminal_console_write(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
1221 {
1222 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
1223 return gate_terminal_console_write_to_handle(impl->con_output, impl->is_native_output, buffer, bufferlength, written);
1224 }
1225
1226 gate_result_t gate_terminal_console_flush(void* thisptr)
1227 {
1228 gate_result_t ret = GATE_RESULT_OK;
1229 GATE_UNUSED_ARG(thisptr);
1230 return ret;
1231 }
1232
1233 gate_result_t gate_terminal_console_get_resource(void* thisptr, gate_uint32_t resource_type, gate_uintptr_t* resource)
1234 {
1235 gate_result_t ret = GATE_RESULT_FAILED;
1236 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
1237 /* TODO */
1238 do
1239 {
1240 if (!resource)
1241 {
1242 ret = GATE_RESULT_NULLPOINTER;
1243 break;
1244 }
1245
1246 switch (resource_type)
1247 {
1248 case GATE_STREAM_RESOURCE_DEFAULT:
1249 case GATE_STREAM_RESOURCE_INPUT:
1250 {
1251 *resource = (gate_uintptr_t)impl->con_input;
1252 ret = GATE_RESULT_OK;
1253 }
1254 case GATE_STREAM_RESOURCE_OUTPUT:
1255 {
1256 *resource = (gate_uintptr_t)impl->con_output;
1257 ret = GATE_RESULT_OK;
1258 }
1259 case GATE_STREAM_RESOURCE_ERROR:
1260 {
1261 *resource = (gate_uintptr_t)impl->con_error;
1262 ret = GATE_RESULT_OK;
1263 }
1264 default:
1265 {
1266 ret = GATE_RESULT_NOTSUPPORTED;
1267 break;
1268 }
1269 }
1270
1271 } while (0);
1272
1273 return ret;
1274 }
1275
1276 static gate_char32_t map_scan_code_to_ctrl_ascii_code(WORD vkey_code)
1277 {
1278 if ((vkey_code >= 0x41) && (vkey_code <= 0x5A))
1279 {
1280 return GATE_TERMINAL_CHAR_CTRL_A + (vkey_code - 0x41);
1281 }
1282 return 0;
1283 }
1284
1285 static gate_char32_t gate_scan_code_to_alt_ascii_code(WORD vkey_code)
1286 {
1287 if ((vkey_code >= 0x41) && (vkey_code <= 0x5A))
1288 {
1289 switch ((vkey_code - 0x41))
1290 {
1291 case 0: return GATE_TERMINAL_CHAR_ALT_A;
1292 case 1: return GATE_TERMINAL_CHAR_ALT_B;
1293 case 2: return GATE_TERMINAL_CHAR_ALT_C;
1294 case 3: return GATE_TERMINAL_CHAR_ALT_D;
1295 case 4: return GATE_TERMINAL_CHAR_ALT_E;
1296 case 5: return GATE_TERMINAL_CHAR_ALT_F;
1297 case 6: return GATE_TERMINAL_CHAR_ALT_G;
1298 case 7: return GATE_TERMINAL_CHAR_ALT_H;
1299 case 8: return GATE_TERMINAL_CHAR_ALT_I;
1300 case 9: return GATE_TERMINAL_CHAR_ALT_J;
1301 case 10: return GATE_TERMINAL_CHAR_ALT_K;
1302 case 11: return GATE_TERMINAL_CHAR_ALT_L;
1303 case 12: return GATE_TERMINAL_CHAR_ALT_M;
1304 case 13: return GATE_TERMINAL_CHAR_ALT_N;
1305 case 14: return GATE_TERMINAL_CHAR_ALT_O;
1306 case 15: return GATE_TERMINAL_CHAR_ALT_P;
1307 case 16: return GATE_TERMINAL_CHAR_ALT_Q;
1308 case 17: return GATE_TERMINAL_CHAR_ALT_R;
1309 case 18: return GATE_TERMINAL_CHAR_ALT_S;
1310 case 19: return GATE_TERMINAL_CHAR_ALT_T;
1311 case 20: return GATE_TERMINAL_CHAR_ALT_U;
1312 case 21: return GATE_TERMINAL_CHAR_ALT_V;
1313 case 22: return GATE_TERMINAL_CHAR_ALT_W;
1314 case 23: return GATE_TERMINAL_CHAR_ALT_X;
1315 case 24: return GATE_TERMINAL_CHAR_ALT_Y;
1316 case 25: return GATE_TERMINAL_CHAR_ALT_Z;
1317 }
1318 }
1319 else
1320 {
1321 switch (vkey_code)
1322 {
1323 case VK_F1: return GATE_TERMINAL_CHAR_ALT_F1;
1324 case VK_F2: return GATE_TERMINAL_CHAR_ALT_F2;
1325 case VK_F3: return GATE_TERMINAL_CHAR_ALT_F3;
1326 case VK_F4: return GATE_TERMINAL_CHAR_ALT_F4;
1327 case VK_F5: return GATE_TERMINAL_CHAR_ALT_F5;
1328 case VK_F6: return GATE_TERMINAL_CHAR_ALT_F6;
1329 case VK_F7: return GATE_TERMINAL_CHAR_ALT_F7;
1330 case VK_F8: return GATE_TERMINAL_CHAR_ALT_F8;
1331 case VK_F9: return GATE_TERMINAL_CHAR_ALT_F9;
1332 case VK_F10: return GATE_TERMINAL_CHAR_ALT_F10;
1333 case VK_F11: return GATE_TERMINAL_CHAR_ALT_F11;
1334 case VK_F12: return GATE_TERMINAL_CHAR_ALT_F12;
1335 }
1336 }
1337 return 0;
1338 }
1339
1340 static gate_char32_t gate_special_key_to_ascii_code(WORD vkey)
1341 {
1342 switch (vkey)
1343 {
1344 case VK_PRIOR: return GATE_TERMINAL_CHAR_PGUP;
1345 case VK_NEXT: return GATE_TERMINAL_CHAR_PGDOWN;
1346 case VK_HOME: return GATE_TERMINAL_CHAR_HOME;
1347 case VK_END: return GATE_TERMINAL_CHAR_END;
1348 case VK_UP: return GATE_TERMINAL_CHAR_UPARROW;
1349 case VK_DOWN: return GATE_TERMINAL_CHAR_DOWNARROW;
1350 case VK_LEFT: return GATE_TERMINAL_CHAR_LEFTARROW;
1351 case VK_RIGHT: return GATE_TERMINAL_CHAR_RIGHTARROW;
1352
1353 case VK_F1: return GATE_TERMINAL_CHAR_F1;
1354 case VK_F2: return GATE_TERMINAL_CHAR_F2;
1355 case VK_F3: return GATE_TERMINAL_CHAR_F3;
1356 case VK_F4: return GATE_TERMINAL_CHAR_F4;
1357 case VK_F5: return GATE_TERMINAL_CHAR_F5;
1358 case VK_F6: return GATE_TERMINAL_CHAR_F6;
1359 case VK_F7: return GATE_TERMINAL_CHAR_F7;
1360 case VK_F8: return GATE_TERMINAL_CHAR_F8;
1361 case VK_F9: return GATE_TERMINAL_CHAR_F9;
1362 case VK_F10: return GATE_TERMINAL_CHAR_F10;
1363 case VK_F11: return GATE_TERMINAL_CHAR_F11;
1364 case VK_F12: return GATE_TERMINAL_CHAR_F12;
1365
1366 case VK_TAB:
1367 case VK_CAPITAL:
1368 case VK_BACK:
1369 case VK_RETURN:
1370 case VK_ESCAPE:
1371 case VK_INSERT:
1372 case VK_DELETE:
1373 case VK_PRINT:
1374 case VK_PAUSE:
1375 case VK_SCROLL:
1376 case VK_NUMLOCK:
1377 default:
1378 return 0;
1379 }
1380 }
1381
1382 gate_result_t gate_terminal_console_read_char_impl(void* thisptr, gate_char32_t* ptr_char, gate_uint32_t timeout_ms)
1383 {
1384 gate_result_t ret = GATE_RESULT_FAILED;
1385 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
1386 #ifdef GATE_SYS_WINCE
1387 ret = GATE_RESULT_NOTSUPPORTED;
1388 #else
1389 gate_timecounter_t tc_start;
1390 gate_timecounter_t tc_now;
1391 gate_int64_t time_diff;
1392 DWORD wait = timeout_ms;
1393 INPUT_RECORD input_record = GATE_INIT_EMPTY;
1394 DWORD event_count;
1395 DWORD wait_result;
1396 gate_char32_t chr;
1397
1398 /* TODO */
1399
1400 do
1401 {
1402 ret = gate_timecounter_now(&tc_start);
1403 GATE_BREAK_IF_FAILED(ret);
1404
1405 if (impl->char_buffer_used != 0)
1406 {
1407 if (ptr_char)
1408 {
1409 *ptr_char = impl->char_buffer[0];
1410 }
1411 if (--impl->char_buffer_used != 0)
1412 {
1413 gate_mem_copy(&impl->char_buffer[0], &impl->char_buffer[1], impl->char_buffer_used * sizeof(impl->char_buffer[0]));
1414 }
1415 return GATE_RESULT_OK;
1416 }
1417
1418 ret = GATE_RESULT_FAILED;
1419 while (WAIT_OBJECT_0 == (wait_result = WaitForSingleObject(impl->con_input, wait)))
1420 {
1421 event_count = 0;
1422 if (!ReadConsoleInput(impl->con_input, &input_record, 1, &event_count))
1423 {
1424 GATE_DEBUG_TRACE("ReadConsoleInput() failed");
1425 GATE_DEBUG_TRACE_VALUE(gate_win32_getlasterror());
1426 }
1427 else
1428 {
1429 if (input_record.EventType == KEY_EVENT)
1430 {
1431 if (input_record.Event.KeyEvent.bKeyDown)
1432 {
1433 if ((input_record.Event.KeyEvent.dwControlKeyState & LEFT_CTRL_PRESSED)
1434 || ((input_record.Event.KeyEvent.dwControlKeyState & RIGHT_CTRL_PRESSED)))
1435 {
1436 chr = map_scan_code_to_ctrl_ascii_code(input_record.Event.KeyEvent.wVirtualKeyCode);
1437 if (chr != 0)
1438 {
1439 if (ptr_char)
1440 {
1441 *ptr_char = chr;
1442 }
1443 else
1444 {
1445 impl->char_buffer[0] = chr;
1446 impl->char_buffer_used = 1;
1447 }
1448 ret = GATE_RESULT_OK;
1449 break;
1450 }
1451 }
1452
1453 if ((input_record.Event.KeyEvent.dwControlKeyState & LEFT_ALT_PRESSED)
1454 || ((input_record.Event.KeyEvent.dwControlKeyState & RIGHT_ALT_PRESSED)))
1455 {
1456 chr = gate_scan_code_to_alt_ascii_code(input_record.Event.KeyEvent.wVirtualScanCode);
1457 if (chr != 0)
1458 {
1459 if (ptr_char)
1460 {
1461 *ptr_char = 0;
1462 impl->char_buffer[0] = chr;
1463 impl->char_buffer_used = 1;
1464 }
1465 else
1466 {
1467 impl->char_buffer[0] = 0;
1468 impl->char_buffer[1] = chr;
1469 impl->char_buffer_used = 2;
1470 }
1471 ret = GATE_RESULT_OK;
1472 break;
1473 }
1474 }
1475
1476 chr = gate_special_key_to_ascii_code(input_record.Event.KeyEvent.wVirtualScanCode);
1477 if (chr != 0)
1478 {
1479 if (ptr_char)
1480 {
1481 *ptr_char = 0;
1482 impl->char_buffer[0] = chr;
1483 impl->char_buffer_used = 1;
1484 }
1485 else
1486 {
1487 impl->char_buffer[0] = 0;
1488 impl->char_buffer[1] = chr;
1489 impl->char_buffer_used = 2;
1490 }
1491 ret = GATE_RESULT_OK;
1492 break;
1493 }
1494
1495 if (input_record.Event.KeyEvent.uChar.UnicodeChar != 0)
1496 {
1497 /* we have an unicode character */
1498 if (ptr_char)
1499 {
1500 *ptr_char = input_record.Event.KeyEvent.uChar.UnicodeChar;
1501 }
1502 else
1503 {
1504 impl->char_buffer[0] = input_record.Event.KeyEvent.uChar.UnicodeChar;
1505 impl->char_buffer_used = 1;
1506 }
1507 ret = GATE_RESULT_OK;
1508 break;
1509 }
1510
1511 /* we could not deduce a code for an entered key -> ignore input */
1512 }
1513 }
1514 }
1515
1516 ret = gate_timecounter_now(&tc_now);
1517 GATE_BREAK_IF_FAILED(ret);
1518
1519 time_diff = gate_timecounter_diff(tc_now, tc_start) / 1000;
1520 if (time_diff >= timeout_ms)
1521 {
1522 ret = GATE_RESULT_TIMEOUT;
1523 break;
1524 }
1525 wait = (DWORD)(timeout_ms - time_diff);
1526 }
1527 if (wait_result == WAIT_TIMEOUT)
1528 {
1529 ret = GATE_RESULT_TIMEOUT;
1530 }
1531 else if (wait_result != WAIT_OBJECT_0)
1532 {
1533 ret = GATE_RESULT_FAILED;
1534 }
1535 } while (0);
1536 #endif
1537 return ret;
1538 }
1539
1540 static gate_bool_t is_control_key(WORD keyCode)
1541 {
1542 switch (keyCode)
1543 {
1544 case VK_SHIFT:
1545 case VK_CONTROL:
1546 case VK_MENU:
1547 case VK_LSHIFT:
1548 case VK_RSHIFT:
1549 case VK_LCONTROL:
1550 case VK_RCONTROL:
1551 case VK_LMENU:
1552 case VK_RMENU:
1553 return true;
1554 default:
1555 return false;
1556 }
1557 }
1558
1559 gate_result_t gate_terminal_console_await_char(void* thisptr, gate_uint32_t timeout_ms)
1560 {
1561 gate_result_t ret = GATE_RESULT_FAILED;
1562 gate_terminal_console_impl_t* ptr = (gate_terminal_console_impl_t*)thisptr;
1563 #ifdef GATE_SYS_WINCE
1564 ret = GATE_RESULT_NOTSUPPORTED;
1565 #else
1566 gate_timecounter_t tc_start;
1567 gate_timecounter_t tc_now;
1568 gate_int64_t time_diff;
1569 DWORD next_timeout = (timeout_ms == GATE_CONSOLE_TIMEOUT_NEVER) ? INFINITE : (DWORD)timeout_ms;
1570 INPUT_RECORD input_record = GATE_INIT_EMPTY;
1571 DWORD event_count;
1572 DWORD wait_result;
1573
1574 HANDLE input_handle = ptr->con_input;
1575
1576 do
1577 {
1578 ret = gate_timecounter_now(&tc_start);
1579 GATE_BREAK_IF_FAILED(ret);
1580
1581 ret = GATE_RESULT_FAILED;
1582 while (WAIT_OBJECT_0 == (wait_result = WaitForSingleObject(input_handle, next_timeout)))
1583 {
1584 event_count = 0;
1585 if (PeekConsoleInput(input_handle, &input_record, 1, &event_count))
1586 {
1587 if (input_record.EventType != KEY_EVENT)
1588 {
1589 /* not interested in out events -> remove event from buffer */
1590 ReadConsoleInput(input_handle, &input_record, 1, &event_count);
1591 }
1592 else if (!input_record.Event.KeyEvent.bKeyDown)
1593 {
1594 /* not interested in key_up -> remove event */
1595 ReadConsoleInput(input_handle, &input_record, 1, &event_count);
1596 }
1597 else if (is_control_key(input_record.Event.KeyEvent.wVirtualKeyCode))
1598 {
1599 /* ignore control keys -> remove event */
1600 ReadConsoleInput(input_handle, &input_record, 1, &event_count);
1601 }
1602 else
1603 {
1604 /* next event is a readable key */
1605 ret = GATE_RESULT_OK;
1606 break;
1607 }
1608 }
1609
1610 ret = gate_timecounter_now(&tc_now);
1611 GATE_BREAK_IF_FAILED(ret);
1612
1613 time_diff = gate_timecounter_diff(tc_now, tc_start) / 1000;
1614 if (time_diff >= timeout_ms)
1615 {
1616 ret = GATE_RESULT_TIMEOUT;
1617 break;
1618 }
1619 next_timeout = (DWORD)(timeout_ms - time_diff);
1620 }
1621 if (wait_result == WAIT_TIMEOUT)
1622 {
1623 ret = GATE_RESULT_TIMEOUT;
1624 }
1625 else if (wait_result != WAIT_OBJECT_0)
1626 {
1627 ret = GATE_RESULT_FAILED;
1628 }
1629 } while (0);
1630 #endif
1631 return ret;
1632 }
1633
1634 gate_result_t gate_terminal_console_read_char(void* thisptr, gate_char32_t* ptr_char)
1635 {
1636 gate_result_t ret = GATE_RESULT_FAILED;
1637 gate_terminal_console_impl_t* ptr = (gate_terminal_console_impl_t*)thisptr;
1638 #ifdef GATE_SYS_WINCE
1639 ret = GATE_RESULT_NOTSUPPORTED;
1640 #else
1641 INPUT_RECORD input_record = GATE_INIT_EMPTY;
1642 DWORD event_count = 0;
1643 gate_char32_t chr;
1644 HANDLE input_handle = ptr->con_input;
1645
1646 do
1647 {
1648 ret = gate_terminal_console_await_char(thisptr, GATE_CONSOLE_TIMEOUT_NEVER);
1649 GATE_BREAK_IF_FAILED(ret);
1650
1651 event_count = 0;
1652 if (!ReadConsoleInput(input_handle, &input_record, 1, &event_count))
1653 {
1654 ret = GATE_RESULT_FAILED;
1655 break;
1656 }
1657 if (input_record.EventType != KEY_EVENT)
1658 {
1659 ret = GATE_RESULT_FAILED;
1660 break;
1661 }
1662 if (!input_record.Event.KeyEvent.bKeyDown)
1663 {
1664 ret = GATE_RESULT_FAILED;
1665 break;
1666 }
1667
1668 #if defined(GATE_WIN32_UNICODE)
1669 chr = input_record.Event.KeyEvent.uChar.UnicodeChar;
1670 #else
1671 chr = input_record.Event.KeyEvent.uChar.AsciiChar;
1672 #endif
1673 if (chr == 0)
1674 {
1675 gate_keyboard_native_key_to_unicode(input_record.Event.KeyEvent.wVirtualKeyCode, &chr);
1676 }
1677 *ptr_char = chr;
1678
1679 } while (0);
1680 #endif
1681 return ret;
1682 }
1683
1684
1685 gate_result_t gate_terminal_console_write_err(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
1686 {
1687 gate_terminal_console_impl_t* const impl = (gate_terminal_console_impl_t*)thisptr;
1688 return gate_terminal_console_write_to_handle(impl->con_error, impl->is_native_error, buffer, bufferlength, written);
1689 }
1690
1691 gate_result_t gate_terminal_console_flush_err(void* thisptr)
1692 {
1693 gate_result_t ret = GATE_RESULT_OK;
1694 GATE_UNUSED_ARG(thisptr);
1695 return ret;
1696 }
1697
1698 #ifndef GATE_SYS_WINCE
1699 static gate_bool_t is_real_console(gate_terminal_console_impl_t* impl)
1700 {
1701 DWORD con_mode = 0;
1702 BOOL is_console = GetConsoleMode(impl->con_output, &con_mode);
1703 return is_console ? true : false;
1704 }
1705 #endif
1706
1707 gate_enumint_t gate_terminal_console_get_type(void* thisptr)
1708 {
1709 #ifdef GATE_SYS_WINCE
1710 return GATE_TERMINAL_TYPE_CHARSTREAM;
1711 #else
1712 gate_terminal_console_impl_t* const impl = (gate_terminal_console_impl_t*)thisptr;
1713 return is_real_console(impl) ? GATE_TERMINAL_TYPE_UI : GATE_TERMINAL_TYPE_CHARSTREAM;
1714 #endif
1715 }
1716
1717 gate_result_t gate_terminal_console_get_size(void* thisptr, gate_uint16_t* ptr_width, gate_uint16_t* ptr_height)
1718 {
1719 gate_result_t ret = GATE_RESULT_FAILED;
1720 gate_terminal_console_impl_t* const impl = (gate_terminal_console_impl_t*)thisptr;
1721 do
1722 {
1723 #ifndef GATE_SYS_WINCE
1724 if (!GATE_FLAG_ENABLED(impl->flags, GATE_TERMINAL_FLAG_VT100))
1725 {
1726 CONSOLE_SCREEN_BUFFER_INFO info;
1727 if (!GetConsoleScreenBufferInfo(impl->con_output, &info))
1728 {
1729 DWORD lasterr = GetLastError();
1730 if (!is_real_console(impl))
1731 {
1732 if (ptr_width != NULL) *ptr_width = 80;
1733 if (ptr_height != NULL) *ptr_height = 25;
1734 ret = GATE_RESULT_OK;
1735 break;
1736 }
1737 gate_win32_print_lasterror_code(lasterr, &ret, NULL, 0);
1738 }
1739 else
1740 {
1741 if (ptr_width != NULL) *ptr_width = (gate_uint16_t)info.dwSize.X;
1742 if (ptr_height != NULL) *ptr_height = (gate_uint16_t)info.dwSize.Y;
1743 ret = GATE_RESULT_OK;
1744 }
1745 break;
1746 }
1747 #endif
1748 ret = gate_terminal_vt100_get_size(thisptr, ptr_width, ptr_height);
1749 } while (0);
1750 return ret;
1751 }
1752
1753 gate_result_t gate_terminal_console_get_cursor_pos(void* thisptr, gate_uint16_t* ptr_x, gate_uint16_t* ptr_y)
1754 {
1755 gate_result_t ret = GATE_RESULT_FAILED;
1756 gate_terminal_console_impl_t* const impl = (gate_terminal_console_impl_t*)thisptr;
1757 do
1758 {
1759 #ifndef GATE_SYS_WINCE
1760 if (!GATE_FLAG_ENABLED(impl->flags, GATE_TERMINAL_FLAG_VT100))
1761 {
1762 CONSOLE_SCREEN_BUFFER_INFO info;
1763 if (!GetConsoleScreenBufferInfo(impl->con_output, &info))
1764 {
1765 DWORD lasterr = GetLastError();
1766 if (!is_real_console(impl))
1767 {
1768 // return fake values
1769 if (ptr_x != NULL) *ptr_x = 0;
1770 if (ptr_y != NULL) *ptr_y = 0;
1771 ret = GATE_RESULT_OK;
1772 break;
1773 }
1774 gate_win32_print_lasterror_code(lasterr, &ret, NULL, 0);
1775 }
1776 else
1777 {
1778 if (ptr_x != NULL) *ptr_x = (gate_uint16_t)info.dwCursorPosition.X;
1779 if (ptr_y != NULL) *ptr_y = (gate_uint16_t)info.dwCursorPosition.Y;
1780 ret = GATE_RESULT_OK;
1781 break;
1782 }
1783 }
1784 #endif
1785 ret = gate_terminal_vt100_get_cursor_pos(thisptr, ptr_x, ptr_y);
1786 } while (0);
1787 return ret;
1788 }
1789
1790 gate_result_t gate_terminal_console_set_cursor_pos(void* thisptr, gate_uint16_t x, gate_uint16_t y)
1791 {
1792 gate_result_t ret = GATE_RESULT_FAILED;
1793 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
1794 do
1795 {
1796 #ifndef GATE_SYS_WINCE
1797 if (!GATE_FLAG_ENABLED(impl->flags, GATE_TERMINAL_FLAG_VT100))
1798 {
1799 COORD coord;
1800 coord.X = (SHORT)x;
1801 coord.Y = (SHORT)y;
1802 if (!SetConsoleCursorPosition(impl->con_output, coord))
1803 {
1804 DWORD lasterr = GetLastError();
1805 if (!is_real_console(impl))
1806 {
1807 /* no action, but simulate success */
1808 ret = GATE_RESULT_OK;
1809 break;
1810 }
1811 gate_win32_print_lasterror_code(lasterr, &ret, NULL, 0);
1812 }
1813 else
1814 {
1815 ret = GATE_RESULT_OK;
1816 break;
1817 }
1818 }
1819 #endif
1820 ret = gate_terminal_vt100_set_cursor_pos(thisptr, x, y);
1821
1822 } while (0);
1823 return ret;
1824 }
1825
1826 gate_result_t gate_terminal_console_set_cursor_mode(void* thisptr, gate_uint16_t mode)
1827 {
1828 gate_result_t ret = GATE_RESULT_FAILED;
1829 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
1830
1831 do
1832 {
1833 #ifndef GATE_SYS_WINCE
1834 if (!GATE_FLAG_ENABLED(impl->flags, GATE_TERMINAL_FLAG_VT100))
1835 {
1836 CONSOLE_CURSOR_INFO info = GATE_INIT_EMPTY;
1837
1838 switch (mode)
1839 {
1840 case GATE_TERMINAL_CURSOR_MODE_OFF:
1841 {
1842 info.bVisible = false;
1843 info.dwSize = 1;
1844 break;
1845 }
1846 case GATE_TERMINAL_CURSOR_MODE_SMALL:
1847 {
1848 info.bVisible = true;
1849 info.dwSize = 15;
1850 break;
1851 }
1852 case GATE_TERMINAL_CURSOR_MODE_MEDIUM:
1853 {
1854 info.bVisible = true;
1855 info.dwSize = 50;
1856 break;
1857 }
1858 case GATE_TERMINAL_CURSOR_MODE_LARGE:
1859 default:
1860 {
1861 info.bVisible = true;
1862 info.dwSize = 100;
1863 break;
1864 }
1865 }
1866 if (SetConsoleCursorInfo(impl->con_output, &info))
1867 {
1868 ret = GATE_RESULT_OK;
1869 break;
1870 }
1871 else
1872 {
1873 if (!is_real_console(impl))
1874 {
1875 /* simluate success */
1876 ret = GATE_RESULT_OK;
1877 break;
1878 }
1879 }
1880 }
1881 #endif
1882 ret = gate_terminal_vt100_enable_cursor(impl, (mode == GATE_TERMINAL_CURSOR_MODE_OFF) ? false : true);
1883
1884 } while (0);
1885 return ret;
1886 }
1887
1888 gate_result_t gate_terminal_console_clear(void* thisptr)
1889 {
1890 gate_result_t ret = GATE_RESULT_FAILED;
1891 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
1892 do
1893 {
1894 #ifndef GATE_SYS_WINCE
1895 if (!GATE_FLAG_ENABLED(impl->flags, GATE_TERMINAL_FLAG_VT100))
1896 {
1897 do
1898 {
1899 COORD coordScreen = { 0, 0 };
1900 DWORD cCharsWritten;
1901 CONSOLE_SCREEN_BUFFER_INFO csbi;
1902 DWORD dwConSize;
1903
1904 if (!GetConsoleScreenBufferInfo(impl->con_output, &csbi))
1905 {
1906 DWORD lasterr = GetLastError();
1907 if (!is_real_console(impl))
1908 {
1909 /* no change, simulate success */
1910 ret = GATE_RESULT_OK;
1911 break;
1912 }
1913 gate_win32_print_lasterror_code(lasterr, &ret, NULL, 0);
1914 break;
1915 }
1916 dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
1917
1918 if (!FillConsoleOutputCharacter(impl->con_output, _T(' '), dwConSize, coordScreen, &cCharsWritten))
1919 {
1920 gate_win32_print_lasterror(&ret, NULL, 0);
1921 break;
1922 }
1923 if (!GetConsoleScreenBufferInfo(impl->con_output, &csbi))
1924 {
1925 gate_win32_print_lasterror(&ret, NULL, 0);
1926 break;
1927 }
1928 if (!FillConsoleOutputAttribute(impl->con_output, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten))
1929 {
1930 gate_win32_print_lasterror(&ret, NULL, 0);
1931 break;
1932 }
1933 if (!SetConsoleCursorPosition(impl->con_output, coordScreen))
1934 {
1935 gate_win32_print_lasterror(&ret, NULL, 0);
1936 break;
1937 }
1938 ret = GATE_RESULT_OK;
1939 } while (0);
1940
1941 if (GATE_SUCCEEDED(ret))
1942 {
1943 break;
1944 }
1945 }
1946 #endif
1947 ret = gate_terminal_vt100_clear(thisptr);
1948 } while (0);
1949
1950 return ret;
1951 }
1952
1953 gate_result_t gate_terminal_console_get_text_color(void* thisptr, gate_uint8_t* ptr_color_code)
1954 {
1955 gate_result_t ret = GATE_RESULT_FAILED;
1956 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
1957
1958 do
1959 {
1960 #ifndef GATE_SYS_WINCE
1961 //if(!GATE_FLAG_ENABLED(impl->flags, GATE_TERMINAL_FLAG_VT100))
1962 {
1963 CONSOLE_SCREEN_BUFFER_INFO info;
1964 if (!GetConsoleScreenBufferInfo(impl->con_output, &info))
1965 {
1966 DWORD lasterr = GetLastError();
1967 if (!is_real_console(impl))
1968 {
1969 if (ptr_color_code != NULL) *ptr_color_code = GATE_TERMINAL_COLOR_WHITE;
1970 ret = GATE_RESULT_OK;
1971 break;
1972 }
1973 gate_win32_print_lasterror_code(lasterr, &ret, NULL, 0);
1974 }
1975 else
1976 {
1977 if (ptr_color_code != NULL)
1978 {
1979 *ptr_color_code = info.wAttributes & 0x0f;
1980 }
1981 ret = GATE_RESULT_OK;
1982 break;
1983 }
1984 }
1985 #endif
1986 ret = gate_terminal_vt100_get_text_color(thisptr, ptr_color_code);
1987 } while (0);
1988 return ret;
1989 }
1990
1991 gate_result_t gate_terminal_console_set_text_color(void* thisptr, gate_uint8_t color_code)
1992 {
1993 gate_result_t ret = GATE_RESULT_FAILED;
1994 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
1995
1996 do
1997 {
1998 #ifndef GATE_SYS_WINCE
1999 if (!GATE_FLAG_ENABLED(impl->flags, GATE_TERMINAL_FLAG_VT100))
2000 {
2001 CONSOLE_SCREEN_BUFFER_INFO info = GATE_INIT_EMPTY;
2002 GetConsoleScreenBufferInfo(impl->con_output, &info);
2003 info.wAttributes &= 0xfff0;
2004 info.wAttributes |= (gate_uint16_t)color_code;
2005 if (!SetConsoleTextAttribute(impl->con_output, info.wAttributes))
2006 {
2007 DWORD lasterr = GetLastError();
2008 if (!is_real_console(impl))
2009 {
2010 ret = GATE_RESULT_OK;
2011 break;
2012 }
2013 gate_win32_print_lasterror_code(lasterr, &ret, NULL, 0);
2014 }
2015 else
2016 {
2017 ret = GATE_RESULT_OK;
2018 break;
2019 }
2020 }
2021 #endif
2022 ret = gate_terminal_vt100_set_text_color(thisptr, color_code);
2023 } while (0);
2024 return ret;
2025 }
2026
2027 gate_result_t gate_terminal_console_get_back_color(void* thisptr, gate_uint8_t* ptr_color_code)
2028 {
2029 gate_result_t ret = GATE_RESULT_FAILED;
2030 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2031 do
2032 {
2033 #ifndef GATE_SYS_WINCE
2034 //if(!GATE_FLAG_ENABLED(impl->flags, GATE_TERMINAL_FLAG_VT100))
2035 {
2036 CONSOLE_SCREEN_BUFFER_INFO info;
2037 if (!GetConsoleScreenBufferInfo(impl->con_output, &info))
2038 {
2039 DWORD lasterr = GetLastError();
2040 if (!is_real_console(impl))
2041 {
2042 if (ptr_color_code) *ptr_color_code = GATE_TERMINAL_COLOR_BLACK;
2043 ret = GATE_RESULT_OK;
2044 break;
2045 }
2046 gate_win32_print_lasterror_code(lasterr, &ret, NULL, 0);
2047 }
2048 else
2049 {
2050 if (NULL != ptr_color_code)
2051 {
2052 *ptr_color_code = (info.wAttributes >> 4) & 0x0f;
2053 }
2054 ret = GATE_RESULT_OK;
2055 break;
2056 }
2057 }
2058 #endif
2059 ret = gate_terminal_vt100_get_back_color(thisptr, ptr_color_code);
2060 } while (0);
2061 return ret;
2062 }
2063
2064 gate_result_t gate_terminal_console_set_back_color(void* thisptr, gate_uint8_t color_code)
2065 {
2066 gate_result_t ret = GATE_RESULT_FAILED;
2067 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2068 do
2069 {
2070 #ifndef GATE_SYS_WINCE
2071 if (!GATE_FLAG_ENABLED(impl->flags, GATE_TERMINAL_FLAG_VT100))
2072 {
2073 CONSOLE_SCREEN_BUFFER_INFO info = GATE_INIT_EMPTY;
2074 GetConsoleScreenBufferInfo(impl->con_output, &info);
2075 info.wAttributes &= 0xff0f;
2076 info.wAttributes |= (((gate_uint16_t)(color_code) << 4) & 0x00f0);
2077 if (!SetConsoleTextAttribute(impl->con_output, info.wAttributes))
2078 {
2079 DWORD lasterr = GetLastError();
2080 if (!is_real_console(impl))
2081 {
2082 /* no action, simulate success */
2083 ret = GATE_RESULT_OK;
2084 break;
2085 }
2086 gate_win32_print_lasterror_code(lasterr, &ret, NULL, 0);
2087 }
2088 else
2089 {
2090 ret = GATE_RESULT_OK;
2091 break;
2092 }
2093 }
2094 #endif
2095 ret = gate_terminal_vt100_set_back_color(thisptr, color_code);
2096 } while (0);
2097 return ret;
2098 }
2099
2100 #endif /* GATE_SYSTEM_TERMINALS_WINAPI */
2101
2102
2103 #if defined(GATE_SYSTEM_TERMINALS_POSIX)
2104
2105 # include <sys/ioctl.h>
2106 # include <sys/types.h>
2107 # include <sys/select.h>
2108 # include <sys/wait.h>
2109 # include <unistd.h>
2110 # include <stdio.h>
2111 # include <termios.h>
2112
2113 typedef struct gate_terminal_console_impl_class
2114 {
2115 GATE_INTERFACE_VTBL(gate_terminal) const* vtbl;
2116
2117 gate_atomic_int_t ref_counter;
2118
2119 int con_input;
2120 int con_output;
2121 int con_error;
2122 int text_color;
2123 int back_color;
2124
2125 gate_bool_t restore_termios;
2126 struct termios termios_attrs_backup;
2127
2128 } gate_terminal_console_impl_t;
2129
2130 2 static gate_terminal_console_impl_t* gate_terminal_console_create(int fd_in, int fd_out, int fd_err)
2131 {
2132 2 gate_terminal_console_impl_t* impl = gate_mem_alloc(sizeof(gate_terminal_console_impl_t));
2133
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (impl != NULL)
2134 {
2135 2 gate_mem_clear(impl, sizeof(gate_terminal_console_impl_t));
2136 2 gate_init_terminal_console_vtbl();
2137 2 impl->vtbl = &gate_terminal_console_vtbl;
2138 2 gate_atomic_int_init(&impl->ref_counter, 1);
2139 2 impl->con_input = fd_in; //STDIN_FILENO;
2140 2 impl->con_output = fd_out; //STDOUT_FILENO;
2141 2 impl->con_error = fd_err; //STDERR_FILENO;
2142 2 impl->text_color = GATE_TERMINAL_COLOR_WHITE;
2143 2 impl->back_color = GATE_TERMINAL_COLOR_BLACK;
2144 2 gate_terminal_set_text_color(impl, GATE_TERMINAL_COLOR_WHITE);
2145 2 gate_terminal_set_back_color(impl, GATE_TERMINAL_COLOR_BLACK);
2146 }
2147 2 return impl;
2148 }
2149
2150 1 gate_terminal_t* gate_terminal_console_get_current()
2151 {
2152 1 return gate_terminal_console_open(0);
2153 }
2154
2155 2 gate_terminal_t* gate_terminal_console_open(gate_enumint_t flags)
2156 {
2157 2 gate_terminal_console_impl_t* term = NULL;
2158 struct termios termios_attrs;
2159
2160 2 int fd_in = dup(STDIN_FILENO);
2161 2 int fd_out = dup(STDOUT_FILENO);
2162 2 int fd_err = dup(STDERR_FILENO);
2163
2164 2 term = gate_terminal_console_create(fd_in, fd_out, fd_err);
2165
2166
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!term)
2167 {
2168 gate_posix_close(fd_in);
2169 gate_posix_close(fd_out);
2170 gate_posix_close(fd_err);
2171 }
2172 else
2173 {
2174
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (0 == tcgetattr(term->con_input, &term->termios_attrs_backup))
2175 {
2176 gate_mem_copy(&termios_attrs, &term->termios_attrs_backup, sizeof(struct termios));
2177 term->restore_termios = true;
2178 GATE_FLAG_SET(termios_attrs.c_lflag, ICANON, false);
2179 GATE_FLAG_SET(termios_attrs.c_lflag, ECHO, GATE_FLAG_ENABLED(flags, GATE_TERMINAL_FLAG_ECHO));
2180 GATE_FLAG_SET(termios_attrs.c_lflag, ECHONL, GATE_FLAG_ENABLED(flags, GATE_TERMINAL_FLAG_ECHO));
2181 GATE_FLAG_SET(termios_attrs.c_lflag, ISIG, false);
2182 GATE_FLAG_SET(termios_attrs.c_lflag, IEXTEN, false);
2183 tcsetattr(term->con_input, TCSANOW, &termios_attrs);
2184 }
2185 }
2186 2 return (gate_terminal_t*)term;
2187 }
2188
2189
2190 2 static void gate_terminal_console_release(void* thisptr)
2191 {
2192 2 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2193
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (0 == gate_atomic_int_dec(&impl->ref_counter))
2194 {
2195
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (impl->restore_termios)
2196 {
2197 tcsetattr(impl->con_input, TCSANOW, &impl->termios_attrs_backup);
2198 }
2199 2 gate_posix_close(impl->con_input);
2200 2 gate_posix_close(impl->con_output);
2201 2 gate_posix_close(impl->con_error);
2202 2 gate_mem_dealloc(impl);
2203 }
2204 2 }
2205 static int gate_terminal_console_retain(void* thisptr)
2206 {
2207 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2208 return gate_atomic_int_dec(&impl->ref_counter);
2209 }
2210 static char const* gate_terminal_console_get_interface_name(void* thisptr)
2211 {
2212 return GATE_INTERFACE_NAME_TERMINAL;
2213 }
2214
2215 static gate_result_t gate_terminal_console_read(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
2216 {
2217 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2218 gate_result_t ret;
2219 ptrdiff_t result = gate_posix_read(impl->con_input, buffer, bufferlength);
2220 if (result < 0)
2221 {
2222 gate_posix_errno(&ret);
2223 }
2224 else
2225 {
2226 if (NULL != returned)
2227 {
2228 *returned = (gate_size_t)result;
2229 }
2230 ret = GATE_RESULT_OK;
2231 }
2232 return ret;
2233 }
2234 static gate_result_t gate_terminal_console_peek(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
2235 {
2236 return GATE_RESULT_NOTSUPPORTED;
2237 }
2238 12 static gate_result_t gate_terminal_console_write(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
2239 {
2240 12 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2241 gate_result_t ret;
2242 12 ptrdiff_t result = gate_posix_write(impl->con_output, buffer, bufferlength);
2243
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (result < 0)
2244 {
2245 gate_posix_errno(&ret);
2246 }
2247 else
2248 {
2249
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 8 times.
12 if (NULL != written)
2250 {
2251 4 *written = (gate_size_t)result;
2252 }
2253 12 ret = GATE_RESULT_OK;
2254 }
2255 12 return ret;
2256 }
2257 static gate_result_t gate_terminal_console_flush(void* thisptr)
2258 {
2259 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2260 gate_result_t ret;
2261 if (fsync(impl->con_output) < 0)
2262 {
2263 gate_posix_errno(&ret);
2264 }
2265 else
2266 {
2267 ret = GATE_RESULT_OK;
2268 }
2269 return ret;
2270 }
2271
2272 static gate_result_t gate_terminal_console_get_resource(void* thisptr, gate_uint32_t resource_type, gate_uintptr_t* ptr_resource)
2273 {
2274 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2275 gate_uintptr_t res = 0;
2276 gate_result_t ret = GATE_RESULT_OK;
2277
2278 switch (resource_type)
2279 {
2280 case GATE_STREAM_RESOURCE_INPUT: res = impl->con_input; break;
2281 case GATE_STREAM_RESOURCE_OUTPUT: res = impl->con_output; break;
2282 case GATE_STREAM_RESOURCE_ERROR: res = impl->con_error; break;
2283 case GATE_STREAM_RESOURCE_DEFAULT: res = impl->con_input; break;
2284 default: ret = GATE_RESULT_INVALIDARG; break;
2285 }
2286
2287 if (ptr_resource)
2288 {
2289 *ptr_resource = res;
2290 }
2291 return ret;
2292 }
2293 static gate_result_t gate_terminal_console_await_char(void* thisptr, gate_uint32_t timeout_ms)
2294 {
2295 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2296 return gate_posix_await_read(impl->con_input, timeout_ms);
2297 }
2298 static gate_result_t gate_terminal_console_read_char(void* thisptr, gate_char32_t* ptr_char)
2299 {
2300 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2301 gate_result_t ret;
2302 char buffer[8];
2303 ret = gate_terminal_console_read(impl, buffer, 1, NULL);
2304 if (ptr_char)
2305 {
2306 *ptr_char = (gate_char32_t)(gate_uint8_t)buffer[0];
2307 }
2308 return ret;
2309 }
2310 static gate_result_t gate_terminal_console_write_err(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
2311 {
2312 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2313 gate_result_t ret;
2314 ptrdiff_t result = gate_posix_write(impl->con_error, buffer, bufferlength);
2315 if (result < 0)
2316 {
2317 gate_posix_errno(&ret);
2318 }
2319 else
2320 {
2321 if (NULL != written)
2322 {
2323 *written = (gate_size_t)result;
2324 }
2325 ret = GATE_RESULT_OK;
2326 }
2327 return ret;
2328 }
2329 static gate_result_t gate_terminal_console_flush_err(void* thisptr)
2330 {
2331 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2332 gate_result_t ret;
2333 if (fsync(impl->con_error) < 0)
2334 {
2335 gate_posix_errno(&ret);
2336 }
2337 else
2338 {
2339 ret = GATE_RESULT_OK;
2340 }
2341 return ret;
2342 }
2343
2344
2345 gate_enumint_t gate_terminal_console_get_type(void* thisptr)
2346 {
2347 return GATE_TERMINAL_TYPE_VT100;
2348 }
2349
2350 //"\x1b[0;40;37m\x1b[1;1H\x1b[2J"
2351 static gate_result_t gate_terminal_console_get_size(void* thisptr, gate_uint16_t* ptr_width, gate_uint16_t* ptr_height)
2352 {
2353 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2354 gate_result_t ret;
2355 struct winsize ws = { 0, 0, 0, 0 };
2356
2357 if (ioctl(impl->con_output, TIOCGWINSZ, &ws) != -1)
2358 {
2359 if (NULL != ptr_width) *ptr_width = (gate_uint16_t)ws.ws_col;
2360 if (NULL != ptr_height) *ptr_height = (gate_uint16_t)ws.ws_row;
2361 ret = GATE_RESULT_OK;
2362 }
2363 else
2364 {
2365 gate_posix_errno(&ret);
2366 }
2367 return ret;
2368 }
2369 static gate_result_t gate_terminal_console_get_cursor_pos(void* thisptr, gate_uint16_t* ptr_x, gate_uint16_t* ptr_y)
2370 {
2371 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2372 gate_result_t ret = GATE_RESULT_NOTSUPPORTED;
2373 struct termios t;
2374 /*TODO implementation*/
2375 (void)impl;
2376 (void)t;
2377 (void)ptr_x;
2378 (void)ptr_y;
2379 return ret;
2380 }
2381 static gate_result_t gate_terminal_console_set_cursor_pos(void* thisptr, gate_uint16_t x, gate_uint16_t y)
2382 {
2383 return gate_terminal_vt100_set_cursor_pos(thisptr, x, y);
2384 }
2385 static gate_result_t gate_terminal_console_set_cursor_mode(void* thisptr, gate_uint16_t mode)
2386 {
2387 return gate_terminal_vt100_enable_cursor(thisptr, (mode == GATE_TERMINAL_CURSOR_MODE_OFF) ? false : true);
2388 }
2389 static gate_result_t gate_terminal_console_clear(void* thisptr)
2390 {
2391 return gate_terminal_vt100_clear(thisptr);
2392 }
2393
2394
2395 6 static gate_result_t gate_terminal_console_get_text_color(void* thisptr, gate_uint8_t* ptr_color_code)
2396 {
2397 6 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2398 6 *ptr_color_code = impl->text_color;
2399 6 return GATE_RESULT_OK;
2400 }
2401
2402
2403 4 static gate_result_t gate_terminal_console_set_text_color(void* thisptr, gate_uint8_t color_code)
2404 {
2405 4 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2406 4 gate_result_t ret = gate_terminal_vt100_set_text_color(thisptr, color_code);
2407
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (GATE_SUCCEEDED(ret))
2408 {
2409 4 impl->text_color = color_code;
2410 }
2411 4 return ret;
2412 }
2413
2414 6 static gate_result_t gate_terminal_console_get_back_color(void* thisptr, gate_uint8_t* ptr_color_code)
2415 {
2416 6 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2417 6 *ptr_color_code = impl->back_color;
2418 6 return GATE_RESULT_OK;
2419 }
2420 4 static gate_result_t gate_terminal_console_set_back_color(void* thisptr, gate_uint8_t color_code)
2421 {
2422 4 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2423 4 gate_result_t ret = gate_terminal_vt100_set_back_color(thisptr, color_code);
2424
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (GATE_SUCCEEDED(ret))
2425 {
2426 4 impl->back_color = color_code;
2427 }
2428 4 return ret;
2429 }
2430
2431 #endif /* GATE_SYSTEM_TERMINALS_POSIX */
2432
2433
2434
2435 #if defined(GATE_SYSTEM_TERMINALS_DOS)
2436
2437 #include <graph.h>
2438 #include <conio.h>
2439
2440 static void gate_term_init()
2441 {
2442 _setvideomode(_TEXTC80);
2443 }
2444 static void gate_term_text_color(int textcol)
2445 {
2446 _settextcolor(textcol);
2447 }
2448 static void gate_term_back_color(int bkcol)
2449 {
2450 _setbkcolor(bkcol);
2451 }
2452 static void gate_term_text_cursor_size(int sz_0_to_3)
2453 {
2454 int value = 0;
2455 switch (sz_0_to_3)
2456 {
2457 case 3: value = 0x0007; break; /* full block */
2458 case 2: value = 0x0407; break; /* half size */
2459 case 1: value = 0x0607; break; /* underline cursor */
2460 default: value = 0x2000; break; /* no cursor /invisible */
2461 }
2462 _settextcursor(value);
2463 }
2464 static void gate_term_text_cursor_pos(char y_1_to_25, char x_1_to_80)
2465 {
2466 _settextposition(y_1_to_25, x_1_to_80);
2467 }
2468 static void gate_term_print_char(char chr)
2469 {
2470 char buf[2] = { chr, 0 };
2471 _outtext(buf);
2472 }
2473 static void gate_term_text_cursor_enable(gate_bool_t enabled)
2474 {
2475 _displaycursor(enabled ? _GCURSORON : _GCURSOROFF);
2476 }
2477 static void gate_term_print_text(char const* text)
2478 {
2479 char buffer[GATE_MAX_BLOCK_COPYBUFFER_LENGTH];
2480 gate_str_print_text(buffer, sizeof(buffer), text, gate_str_length(text));
2481 _outtext(buffer);
2482 }
2483
2484 typedef struct gate_terminal_console_impl_class
2485 {
2486 GATE_INTERFACE_VTBL(gate_terminal) const* vtbl;
2487
2488 gate_atomic_int_t ref_counter;
2489 gate_uint32_t flags;
2490 gate_uint8_t text_color;
2491 gate_uint8_t back_color;
2492 char read_buffer[64];
2493 gate_size_t read_buffer_used;
2494
2495 } gate_terminal_console_impl_t;
2496
2497 void gate_terminal_console_release(void* thisptr)
2498 {
2499 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2500 if (0 == gate_atomic_int_dec(&impl->ref_counter))
2501 {
2502 gate_mem_dealloc(impl);
2503 }
2504 }
2505 int gate_terminal_console_retain(void* thisptr)
2506 {
2507 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2508 return gate_atomic_int_inc(&impl->ref_counter);
2509 }
2510 char const* gate_terminal_console_get_interface_name(void* thisptr)
2511 {
2512 (void)thisptr;
2513 return GATE_INTERFACE_NAME_TERMINAL;
2514 }
2515
2516 static gate_size_t gate_term_read_buffer(char* buffer, gate_size_t buffer_length)
2517 {
2518 gate_size_t count = 0;
2519 unsigned int ch;
2520 while ((buffer_length > 0) && gate_dos_has_kbd_event())
2521 {
2522 if (!gate_dos_get_next_kbd_event(&ch))
2523 {
2524 break;
2525 }
2526 *buffer = (char)ch;
2527 ++buffer;
2528 ++count;
2529 --buffer_length;
2530 }
2531 return count;
2532 }
2533
2534 gate_result_t gate_terminal_console_read(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
2535 {
2536 gate_result_t ret = GATE_RESULT_FAILED;
2537 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2538 gate_size_t len = 0;
2539 unsigned int ch;
2540
2541 do
2542 {
2543 if (!buffer || !bufferlength)
2544 {
2545 ret = GATE_RESULT_INVALIDARG;
2546 break;
2547 }
2548
2549 if (impl->read_buffer_used == 0)
2550 {
2551 if (!gate_dos_get_next_kbd_event(&ch))
2552 {
2553 break;
2554 }
2555 impl->read_buffer[0] = (char)ch;
2556 impl->read_buffer_used = 1;
2557 impl->read_buffer_used += gate_term_read_buffer(&impl->read_buffer[1], sizeof(impl->read_buffer) - 1);
2558 }
2559
2560 ret = GATE_RESULT_OK;
2561 len = (bufferlength > impl->read_buffer_used) ? impl->read_buffer_used : bufferlength;
2562 gate_mem_copy(buffer, impl->read_buffer, len);
2563 if (returned)
2564 {
2565 *returned = len;
2566 }
2567
2568 if (len >= impl->read_buffer_used)
2569 {
2570 impl->read_buffer_used = 0;
2571 }
2572 else if (len > 0)
2573 {
2574 gate_mem_copy(&impl->read_buffer[0], &impl->read_buffer[len], impl->read_buffer_used - len);
2575 impl->read_buffer_used -= len;
2576 }
2577 } while (0);
2578
2579 return ret;
2580 }
2581 gate_result_t gate_terminal_console_peek(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
2582 {
2583 gate_terminal_console_impl_t* impl = (gate_terminal_console_impl_t*)thisptr;
2584 gate_size_t len;
2585
2586 if (!buffer || !bufferlength)
2587 {
2588 return GATE_RESULT_INVALIDARG;
2589 }
2590
2591 if (impl->read_buffer_used < sizeof(impl->read_buffer))
2592 {
2593 len = gate_term_read_buffer(&impl->read_buffer[impl->read_buffer_used], sizeof(impl->read_buffer) - impl->read_buffer_used);
2594 impl->read_buffer_used += len;
2595 }
2596
2597 len = (bufferlength > impl->read_buffer_used) ? impl->read_buffer_used : bufferlength;
2598 gate_mem_copy(buffer, impl->read_buffer, len);
2599 if (returned)
2600 {
2601 *returned = len;
2602 }
2603 return GATE_RESULT_OK;
2604 }
2605 gate_result_t gate_terminal_console_write(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
2606 {
2607 gate_result_t ret = GATE_RESULT_OK;
2608 gate_size_t processed = 0;
2609
2610 GATE_UNUSED_ARG(thisptr);
2611
2612 while (bufferlength > 0)
2613 {
2614 gate_term_print_char(*buffer);
2615 ++buffer;
2616 ++processed;
2617 --bufferlength;
2618 }
2619 if (written)
2620 {
2621 *written = processed;
2622 }
2623 return ret;
2624 }
2625 gate_result_t gate_terminal_console_flush(void* thisptr)
2626 {
2627 GATE_UNUSED_ARG(thisptr);
2628 return GATE_RESULT_OK;
2629 }
2630
2631 gate_result_t gate_terminal_console_get_resource(void* thisptr, gate_uint32_t resource_type, gate_uintptr_t* resource)
2632 {
2633 GATE_UNUSED_ARG(thisptr);
2634 GATE_UNUSED_ARG(resource_type);
2635 GATE_UNUSED_ARG(resource);
2636 return GATE_RESULT_NOTIMPLEMENTED;
2637 }
2638
2639 gate_result_t gate_terminal_console_await_char(void* thisptr, gate_uint32_t timeout_ms)
2640 {
2641 GATE_UNUSED_ARG(thisptr);
2642 return gate_dos_await_and_read_kbd(NULL, timeout_ms);
2643 }
2644 gate_result_t gate_terminal_console_read_char(void* thisptr, gate_char32_t* ptr_char)
2645 {
2646 GATE_UNUSED_ARG(thisptr);
2647 return gate_dos_await_and_read_kbd(ptr_char, -1);
2648 }
2649
2650 gate_result_t gate_terminal_console_write_err(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
2651 {
2652 GATE_UNUSED_ARG(thisptr);
2653 GATE_UNUSED_ARG(buffer);
2654 GATE_UNUSED_ARG(bufferlength);
2655 GATE_UNUSED_ARG(written);
2656 return GATE_RESULT_NOTIMPLEMENTED;
2657 }
2658 gate_result_t gate_terminal_console_flush_err(void* thisptr)
2659 {
2660 GATE_UNUSED_ARG(thisptr);
2661 return GATE_RESULT_OK;
2662 }
2663
2664 gate_enumint_t gate_terminal_console_get_type(void* thisptr)
2665 {
2666 GATE_UNUSED_ARG(thisptr);
2667 return GATE_TERMINAL_TYPE_UI;
2668 }
2669
2670 gate_result_t gate_terminal_console_get_size(void* thisptr, gate_uint16_t* ptr_width, gate_uint16_t* ptr_height)
2671 {
2672 GATE_UNUSED_ARG(thisptr);
2673 if (ptr_width) *ptr_width = 80;
2674 if (ptr_height) *ptr_height = 25;
2675 return GATE_RESULT_OK;
2676 }
2677 gate_result_t gate_terminal_console_get_cursor_pos(void* thisptr, gate_uint16_t* ptr_x, gate_uint16_t* ptr_y)
2678 {
2679 GATE_UNUSED_ARG(thisptr);
2680 GATE_UNUSED_ARG(ptr_x);
2681 GATE_UNUSED_ARG(ptr_y);
2682 return GATE_RESULT_NOTIMPLEMENTED;
2683 }
2684 gate_result_t gate_terminal_console_set_cursor_pos(void* thisptr, gate_uint16_t x, gate_uint16_t y)
2685 {
2686 GATE_UNUSED_ARG(thisptr);
2687 if (x > 79) x = 79;
2688 if (y > 24) y = 24;
2689 gate_term_text_cursor_pos(y + 1, x + 1);
2690 return GATE_RESULT_OK;
2691 }
2692 gate_result_t gate_terminal_console_set_cursor_mode(void* thisptr, gate_uint16_t mode)
2693 {
2694 GATE_UNUSED_ARG(thisptr);
2695 if (mode == GATE_TERMINAL_CURSOR_MODE_OFF)
2696 {
2697 gate_term_text_cursor_enable(false);
2698 }
2699 else
2700 {
2701 int cur_sz;
2702 switch(mode)
2703 {
2704 case GATE_TERMINAL_CURSOR_MODE_SMALL: cur_sz = 1; break;
2705 case GATE_TERMINAL_CURSOR_MODE_MEDIUM: cur_sz = 2; break;
2706 default:
2707 case GATE_TERMINAL_CURSOR_MODE_LARGE: cur_sz = 3; break;
2708 }
2709 gate_term_text_cursor_enable(true);
2710 gate_term_text_cursor_size(cur_sz);
2711 }
2712 return GATE_RESULT_OK;
2713 }
2714 gate_result_t gate_terminal_console_clear(void* thisptr)
2715 {
2716 (void)thisptr;
2717 return GATE_RESULT_NOTIMPLEMENTED;
2718 }
2719
2720 gate_result_t gate_terminal_console_get_text_color(void* thisptr, gate_uint8_t* ptr_color_code)
2721 {
2722 (void)thisptr;
2723 (void)ptr_color_code;
2724 return GATE_RESULT_NOTIMPLEMENTED;
2725 }
2726 gate_result_t gate_terminal_console_set_text_color(void* thisptr, gate_uint8_t color_code)
2727 {
2728 (void)thisptr;
2729 gate_term_text_color(color_code);
2730 return GATE_RESULT_OK;
2731 }
2732
2733 gate_result_t gate_terminal_console_get_back_color(void* thisptr, gate_uint8_t* ptr_color_code)
2734 {
2735 (void)thisptr;
2736 (void)ptr_color_code;
2737 return GATE_RESULT_NOTIMPLEMENTED;
2738 }
2739 gate_result_t gate_terminal_console_set_back_color(void* thisptr, gate_uint8_t color_code)
2740 {
2741 (void)thisptr;
2742 gate_term_back_color(color_code);
2743 return GATE_RESULT_OK;
2744 }
2745
2746 gate_terminal_t* gate_terminal_console_get_current()
2747 {
2748 gate_terminal_console_impl_t* impl = gate_mem_alloc(sizeof(gate_terminal_console_impl_t));
2749 if (impl != NULL)
2750 {
2751 gate_mem_clear(impl, sizeof(gate_terminal_console_impl_t));
2752 gate_init_terminal_console_vtbl();
2753 impl->vtbl = &gate_terminal_console_vtbl;
2754 gate_atomic_int_init(&impl->ref_counter, 1);
2755 impl->text_color = GATE_TERMINAL_COLOR_WHITE;
2756 impl->back_color = GATE_TERMINAL_COLOR_BLACK;
2757 impl->read_buffer_used = 0;
2758 gate_term_init();
2759 }
2760 return (gate_terminal_t*)impl;
2761 }
2762
2763 gate_terminal_t* gate_terminal_console_open(gate_enumint_t flags)
2764 {
2765 (void)flags;
2766 return gate_terminal_console_get_current();
2767 }
2768
2769
2770 #endif /* GATE_SYSTEM_TERMINALS_DOS */
2771
2772
2773
2774 #if defined(GATE_SYSTEM_TERMINALS_EFI)
2775
2776 #include "gate/platform/efi/efi_gate.h"
2777
2778 typedef struct
2779 {
2780 GATE_INTERFACE_VTBL(gate_terminal)* vtbl;
2781
2782 } gate_terminal_console_efi_singleton;
2783
2784 static gate_terminal_t efi_terminal_singleton =
2785 {
2786 &gate_terminal_console_vtbl
2787 };
2788
2789
2790
2791 void gate_terminal_console_release(void* thisptr)
2792 {
2793 GATE_UNUSED_ARG(thisptr);
2794 }
2795 int gate_terminal_console_retain(void* thisptr)
2796 {
2797 GATE_UNUSED_ARG(thisptr);
2798 return 1;
2799 }
2800 char const* gate_terminal_console_get_interface_name(void* thisptr)
2801 {
2802 GATE_UNUSED_ARG(thisptr);
2803 return GATE_INTERFACE_NAME_TERMINAL;
2804 }
2805
2806 gate_result_t gate_terminal_console_read(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
2807 {
2808 gate_result_t result = GATE_RESULT_INVALIDARG;
2809 gate_uint32_t next_timeout = (gate_uint32_t)-1;
2810 gate_char16_t chr;
2811 gate_uint16_t scancode;
2812 gate_size_t len;
2813 gate_size_t len_returned = 0;
2814 GATE_UNUSED_ARG(thisptr);
2815
2816 while (buffer && (bufferlength > 0))
2817 {
2818 result = gate_platform_efi_console_await_char(next_timeout);
2819 GATE_BREAK_IF_FAILED(result);
2820 next_timeout = 0;
2821 result = gate_platform_efi_console_read_char(&chr, &scancode, true);
2822 GATE_BREAK_IF_FAILED(result);
2823
2824 len = gate_char_write_utf8((gate_char32_t)chr, buffer, bufferlength);
2825 len_returned += len;
2826 buffer += len;
2827 bufferlength -= len;
2828 }
2829
2830 if (returned)
2831 {
2832 *returned = len_returned;
2833 }
2834 if ((result == GATE_RESULT_TIMEOUT) && (len_returned > 0))
2835 {
2836 result = GATE_RESULT_OK;
2837 }
2838 return result;
2839 }
2840 gate_result_t gate_terminal_console_peek(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
2841 {
2842 GATE_UNUSED_ARG(thisptr);
2843 GATE_UNUSED_ARG(buffer);
2844 GATE_UNUSED_ARG(bufferlength);
2845 GATE_UNUSED_ARG(returned);
2846
2847 return GATE_RESULT_NOTIMPLEMENTED;
2848 }
2849 gate_result_t gate_terminal_console_write(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
2850 {
2851 gate_result_t result;
2852 gate_char32_t chr32;
2853 gate_size_t length;
2854 gate_size_t bytes_written = 0;
2855
2856 GATE_UNUSED_ARG(thisptr);
2857
2858 while (buffer && (bufferlength > 0))
2859 {
2860 length = gate_char_read_utf8(buffer, bufferlength, &chr32);
2861 buffer += length;
2862 bufferlength -= length;
2863 result = gate_platform_efi_console_write_char((gate_char16_t)chr32);
2864 GATE_BREAK_IF_FAILED(result);
2865 bytes_written += length;
2866 }
2867 if (written)
2868 {
2869 *written = bytes_written;
2870 }
2871 if (GATE_FAILED(result) && (bytes_written > 0))
2872 {
2873 result = GATE_RESULT_OK;
2874 }
2875 return result;
2876 }
2877 gate_result_t gate_terminal_console_flush(void* thisptr)
2878 {
2879 GATE_UNUSED_ARG(thisptr);
2880 return GATE_RESULT_OK;
2881 }
2882
2883 gate_result_t gate_terminal_console_get_resource(void* thisptr, gate_uint32_t resource_type, gate_uintptr_t* resource)
2884 {
2885 GATE_UNUSED_ARG(thisptr);
2886 GATE_UNUSED_ARG(resource_type);
2887 GATE_UNUSED_ARG(resource);
2888 return GATE_RESULT_NOTIMPLEMENTED;
2889 }
2890
2891 gate_result_t gate_terminal_console_await_char(void* thisptr, gate_uint32_t timeout_ms)
2892 {
2893 gate_result_t result;
2894 GATE_UNUSED_ARG(thisptr);
2895
2896 result = gate_platform_efi_console_await_char(timeout_ms == GATE_CONSOLE_TIMEOUT_NEVER ? (gate_uint32_t)-1 : timeout_ms);
2897 return result;
2898 }
2899 gate_result_t gate_terminal_console_read_char(void* thisptr, gate_char32_t* ptr_char)
2900 {
2901 gate_result_t result;
2902 gate_char16_t chr16 = 0;
2903 gate_uint16_t scan_code = 0;
2904 GATE_UNUSED_ARG(thisptr);
2905 result = gate_platform_efi_console_read_char(&chr16, &scan_code, false);
2906 if (ptr_char)
2907 {
2908 *ptr_char = (gate_char32_t)chr16;
2909 }
2910 return result;
2911 }
2912 gate_result_t gate_terminal_console_write_err(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
2913 {
2914 GATE_UNUSED_ARG(thisptr);
2915 GATE_UNUSED_ARG(buffer);
2916 GATE_UNUSED_ARG(bufferlength);
2917 GATE_UNUSED_ARG(written);
2918 return GATE_RESULT_NOTIMPLEMENTED;
2919 }
2920 gate_result_t gate_terminal_console_flush_err(void* thisptr)
2921 {
2922 (void)thisptr;
2923 return GATE_RESULT_NOTIMPLEMENTED;
2924 }
2925
2926 gate_enumint_t gate_terminal_console_get_type(void* thisptr)
2927 {
2928 return GATE_TERMINAL_TYPE_UI;
2929 }
2930
2931 gate_result_t gate_terminal_console_get_size(void* thisptr, gate_uint16_t* ptr_width, gate_uint16_t* ptr_height)
2932 {
2933 GATE_UNUSED_ARG(thisptr);
2934 return gate_platform_efi_console_get_size(ptr_width, ptr_height);
2935 }
2936 gate_result_t gate_terminal_console_get_cursor_pos(void* thisptr, gate_uint16_t* ptr_x, gate_uint16_t* ptr_y)
2937 {
2938 GATE_UNUSED_ARG(thisptr);
2939 return gate_platform_efi_console_get_cursor_pos(ptr_x, ptr_y);
2940 }
2941 gate_result_t gate_terminal_console_set_cursor_pos(void* thisptr, gate_uint16_t x, gate_uint16_t y)
2942 {
2943 GATE_UNUSED_ARG(thisptr);
2944 return gate_platform_efi_console_set_cursor_pos(x, y);
2945 }
2946 gate_result_t gate_terminal_console_set_cursor_mode(void* thisptr, gate_uint16_t mode)
2947 {
2948 GATE_UNUSED_ARG(thisptr);
2949 return gate_platform_efi_console_enable_cursor(mode == GATE_TERMINAL_CURSOR_MODE_OFF ? false : true);
2950 }
2951
2952 gate_result_t gate_terminal_console_clear(void* thisptr)
2953 {
2954 GATE_UNUSED_ARG(thisptr);
2955 return gate_platform_efi_console_clear();
2956 }
2957
2958 gate_result_t gate_terminal_console_get_text_color(void* thisptr, gate_uint8_t* ptr_color_code)
2959 {
2960 GATE_UNUSED_ARG(thisptr);
2961 gate_uint8_t dummy = 0;
2962 return gate_platform_efi_console_get_color(ptr_color_code, &dummy);
2963 }
2964 gate_result_t gate_terminal_console_set_text_color(void* thisptr, gate_uint8_t color_code)
2965 {
2966 GATE_UNUSED_ARG(thisptr);
2967 gate_uint8_t dummy = 0;
2968 gate_uint8_t backcolor = 0;
2969 gate_platform_efi_console_get_color(&dummy, &backcolor);
2970 return gate_platform_efi_console_set_color(color_code, backcolor);
2971 }
2972
2973 gate_result_t gate_terminal_console_get_back_color(void* thisptr, gate_uint8_t* ptr_color_code)
2974 {
2975 GATE_UNUSED_ARG(thisptr);
2976 gate_uint8_t dummy = 0;
2977 return gate_platform_efi_console_get_color(&dummy, ptr_color_code);
2978 }
2979 gate_result_t gate_terminal_console_set_back_color(void* thisptr, gate_uint8_t color_code)
2980 {
2981 GATE_UNUSED_ARG(thisptr);
2982 gate_uint8_t dummy = 0;
2983 gate_uint8_t textcolor = 0;
2984 gate_platform_efi_console_get_color(&textcolor, &dummy);
2985 return gate_platform_efi_console_set_color(textcolor, color_code);
2986 }
2987
2988 gate_terminal_t* gate_terminal_console_get_current()
2989 {
2990 gate_init_terminal_console_vtbl();
2991 return &efi_terminal_singleton;
2992 }
2993
2994 gate_terminal_t* gate_terminal_console_open(gate_enumint_t flags)
2995 {
2996 GATE_UNUSED_ARG(flags);
2997 gate_init_terminal_console_vtbl();
2998 return &efi_terminal_singleton;
2999 }
3000
3001 #endif /* GATE_SYSTEM_TERMINALS_EFI*/
3002
3003
3004
3005 #if defined(GATE_SYSTEM_TERMINALS_NOIMPL)
3006
3007 void gate_terminal_console_release(void* thisptr)
3008 {
3009 GATE_UNUSED_ARG(thisptr);
3010 }
3011 int gate_terminal_console_retain(void* thisptr)
3012 {
3013 GATE_UNUSED_ARG(thisptr);
3014 return 1;
3015 }
3016 char const* gate_terminal_console_get_interface_name(void* thisptr)
3017 {
3018 GATE_UNUSED_ARG(thisptr);
3019 return NULL;
3020 }
3021
3022 gate_result_t gate_terminal_console_read(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
3023 {
3024 GATE_UNUSED_ARG(thisptr);
3025 GATE_UNUSED_ARG(buffer);
3026 GATE_UNUSED_ARG(bufferlength);
3027 GATE_UNUSED_ARG(returned);
3028 return GATE_RESULT_NOTIMPLEMENTED;
3029 }
3030 gate_result_t gate_terminal_console_peek(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
3031 {
3032 GATE_UNUSED_ARG(thisptr);
3033 GATE_UNUSED_ARG(buffer);
3034 GATE_UNUSED_ARG(bufferlength);
3035 GATE_UNUSED_ARG(returned);
3036 return GATE_RESULT_NOTIMPLEMENTED;
3037 }
3038 gate_result_t gate_terminal_console_write(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
3039 {
3040 GATE_UNUSED_ARG(thisptr);
3041 GATE_UNUSED_ARG(buffer);
3042 GATE_UNUSED_ARG(bufferlength);
3043 GATE_UNUSED_ARG(written);
3044 return GATE_RESULT_NOTIMPLEMENTED;
3045 }
3046 gate_result_t gate_terminal_console_flush(void* thisptr)
3047 {
3048 GATE_UNUSED_ARG(thisptr);
3049 return GATE_RESULT_NOTIMPLEMENTED;
3050 }
3051
3052 gate_result_t gate_terminal_console_get_resource(void* thisptr, gate_uint32_t resource_type, gate_uintptr_t* resource)
3053 {
3054 GATE_UNUSED_ARG(thisptr);
3055 GATE_UNUSED_ARG(resource_type);
3056 GATE_UNUSED_ARG(resource);
3057 return GATE_RESULT_NOTIMPLEMENTED;
3058 }
3059
3060 gate_result_t gate_terminal_console_await_char(void* thisptr, gate_uint32_t timeout_ms)
3061 {
3062 GATE_UNUSED_ARG(thisptr);
3063 GATE_UNUSED_ARG(timeout_ms);
3064 return GATE_RESULT_NOTIMPLEMENTED;
3065 }
3066 gate_result_t gate_terminal_console_read_char(void* thisptr, gate_char32_t* ptr_char)
3067 {
3068 GATE_UNUSED_ARG(thisptr);
3069 GATE_UNUSED_ARG(ptr_char);
3070 return GATE_RESULT_NOTIMPLEMENTED;
3071 }
3072 gate_result_t gate_terminal_console_write_err(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
3073 {
3074 GATE_UNUSED_ARG(thisptr);
3075 GATE_UNUSED_ARG(buffer);
3076 GATE_UNUSED_ARG(bufferlength);
3077 GATE_UNUSED_ARG(written);
3078 return GATE_RESULT_NOTIMPLEMENTED;
3079 }
3080 gate_result_t gate_terminal_console_flush_err(void* thisptr)
3081 {
3082 (void)thisptr;
3083 return GATE_RESULT_NOTIMPLEMENTED;
3084 }
3085
3086 gate_enumint_t gate_terminal_console_get_type(void* thisptr)
3087 {
3088 return GATE_TERMINAL_TYPE_UNKNOWN;
3089 }
3090
3091 gate_result_t gate_terminal_console_get_size(void* thisptr, gate_uint16_t* ptr_width, gate_uint16_t* ptr_height)
3092 {
3093 GATE_UNUSED_ARG(thisptr);
3094 GATE_UNUSED_ARG(ptr_width);
3095 GATE_UNUSED_ARG(ptr_height);
3096 return GATE_RESULT_NOTIMPLEMENTED;
3097 }
3098 gate_result_t gate_terminal_console_get_cursor_pos(void* thisptr, gate_uint16_t* ptr_x, gate_uint16_t* ptr_y)
3099 {
3100 GATE_UNUSED_ARG(thisptr);
3101 GATE_UNUSED_ARG(ptr_x);
3102 GATE_UNUSED_ARG(ptr_y);
3103 return GATE_RESULT_NOTIMPLEMENTED;
3104 }
3105 gate_result_t gate_terminal_console_set_cursor_pos(void* thisptr, gate_uint16_t x, gate_uint16_t y)
3106 {
3107 GATE_UNUSED_ARG(thisptr);
3108 GATE_UNUSED_ARG(x);
3109 GATE_UNUSED_ARG(y);
3110 return GATE_RESULT_NOTIMPLEMENTED;
3111 }
3112 gate_result_t gate_terminal_console_set_cursor_mode(void* thisptr, gate_uint16_t mode)
3113 {
3114 GATE_UNUSED_ARG(thisptr);
3115 GATE_UNUSED_ARG(mode);
3116 return GATE_RESULT_NOTIMPLEMENTED;
3117 }
3118 gate_result_t gate_terminal_console_clear(void* thisptr)
3119 {
3120 GATE_UNUSED_ARG(thisptr);
3121 return GATE_RESULT_NOTIMPLEMENTED;
3122 }
3123
3124 gate_result_t gate_terminal_console_get_text_color(void* thisptr, gate_uint8_t* ptr_color_code)
3125 {
3126 GATE_UNUSED_ARG(thisptr);
3127 GATE_UNUSED_ARG(ptr_color_code);
3128 return GATE_RESULT_NOTIMPLEMENTED;
3129 }
3130 gate_result_t gate_terminal_console_set_text_color(void* thisptr, gate_uint8_t color_code)
3131 {
3132 GATE_UNUSED_ARG(thisptr);
3133 GATE_UNUSED_ARG(color_code);
3134 return GATE_RESULT_NOTIMPLEMENTED;
3135 }
3136
3137 gate_result_t gate_terminal_console_get_back_color(void* thisptr, gate_uint8_t* ptr_color_code)
3138 {
3139 GATE_UNUSED_ARG(thisptr);
3140 GATE_UNUSED_ARG(ptr_color_code);
3141 return GATE_RESULT_NOTIMPLEMENTED;
3142 }
3143 gate_result_t gate_terminal_console_set_back_color(void* thisptr, gate_uint8_t color_code)
3144 {
3145 GATE_UNUSED_ARG(thisptr);
3146 GATE_UNUSED_ARG(color_code);
3147 return GATE_RESULT_NOTIMPLEMENTED;
3148 }
3149
3150 gate_terminal_t* gate_terminal_console_get_current()
3151 {
3152 return NULL;
3153 }
3154
3155 gate_terminal_t* gate_terminal_console_open(gate_enumint_t flags)
3156 {
3157 GATE_UNUSED_ARG(flags);
3158 return NULL;
3159 }
3160
3161 #endif /* GATE_SYSTEM_TERMINALS_NOIMPL */
3162