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