Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | pmbaty | 1 | /* |
2 | * This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>. |
||
3 | * It is copyright by its individual contributors, as recorded in the |
||
4 | * project's Git history. See COPYING.txt at the top level for license |
||
5 | * terms and a link to the Git history. |
||
6 | */ |
||
7 | /* |
||
8 | * |
||
9 | * SDL keyboard input support |
||
10 | * |
||
11 | * |
||
12 | */ |
||
13 | |||
14 | #include <algorithm> |
||
15 | #include <stdio.h> |
||
16 | #include <stdlib.h> |
||
17 | |||
18 | #include <SDL.h> |
||
19 | #include <SDL_version.h> |
||
20 | #if SDL_MAJOR_VERSION == 2 |
||
21 | #include <SDL_keycode.h> |
||
22 | #endif |
||
23 | |||
24 | #include "event.h" |
||
25 | #include "dxxerror.h" |
||
26 | #include "key.h" |
||
27 | #include "timer.h" |
||
28 | #include "window.h" |
||
29 | #include "console.h" |
||
30 | #include "args.h" |
||
31 | |||
32 | #include "dxxsconf.h" |
||
33 | #include "dsx-ns.h" |
||
34 | #include "compiler-range_for.h" |
||
35 | #include <array> |
||
36 | |||
37 | namespace dcx { |
||
38 | |||
39 | //-------- Variable accessed by outside functions --------- |
||
40 | static bool keyd_repeat; // 1 = use repeats, 0 no repeats |
||
41 | pressed_keys keyd_pressed; |
||
42 | fix64 keyd_time_when_last_pressed; |
||
43 | std::array<unsigned char, KEY_BUFFER_SIZE> unicode_frame_buffer; |
||
44 | |||
45 | const std::array<key_props, 256> key_properties = {{ |
||
46 | { "", 255, SDLK_UNKNOWN }, // 0 |
||
47 | { "ESC", 255, SDLK_ESCAPE }, |
||
48 | { "1", '1', SDLK_1 }, |
||
49 | { "2", '2', SDLK_2 }, |
||
50 | { "3", '3', SDLK_3 }, |
||
51 | { "4", '4', SDLK_4 }, |
||
52 | { "5", '5', SDLK_5 }, |
||
53 | { "6", '6', SDLK_6 }, |
||
54 | { "7", '7', SDLK_7 }, |
||
55 | { "8", '8', SDLK_8 }, |
||
56 | { "9", '9', SDLK_9 }, // 10 |
||
57 | { "0", '0', SDLK_0 }, |
||
58 | { "-", '-', SDLK_MINUS }, |
||
59 | { "=", '=', SDLK_EQUALS }, |
||
60 | { "BSPC", 255, SDLK_BACKSPACE }, |
||
61 | { "TAB", 255, SDLK_TAB }, |
||
62 | { "Q", 'q', SDLK_q }, |
||
63 | { "W", 'w', SDLK_w }, |
||
64 | { "E", 'e', SDLK_e }, |
||
65 | { "R", 'r', SDLK_r }, |
||
66 | { "T", 't', SDLK_t }, // 20 |
||
67 | { "Y", 'y', SDLK_y }, |
||
68 | { "U", 'u', SDLK_u }, |
||
69 | { "I", 'i', SDLK_i }, |
||
70 | { "O", 'o', SDLK_o }, |
||
71 | { "P", 'p', SDLK_p }, |
||
72 | { "[", '[', SDLK_LEFTBRACKET }, |
||
73 | { "]", ']', SDLK_RIGHTBRACKET }, |
||
74 | { "ENTER", 255, SDLK_RETURN }, |
||
75 | { "LCTRL", 255, SDLK_LCTRL }, |
||
76 | { "A", 'a', SDLK_a }, // 30 |
||
77 | { "S", 's', SDLK_s }, |
||
78 | { "D", 'd', SDLK_d }, |
||
79 | { "F", 'f', SDLK_f }, |
||
80 | { "G", 'g', SDLK_g }, |
||
81 | { "H", 'h', SDLK_h }, |
||
82 | { "J", 'j', SDLK_j }, |
||
83 | { "K", 'k', SDLK_k }, |
||
84 | { "L", 'l', SDLK_l }, |
||
85 | { ";", ';', SDLK_SEMICOLON }, |
||
86 | { "'", '\'', SDLK_QUOTE }, // 40 |
||
87 | { "`", '`', SDLK_BACKQUOTE }, |
||
88 | { "LSHFT", 255, SDLK_LSHIFT }, |
||
89 | { "\\", '\\', SDLK_BACKSLASH }, |
||
90 | { "Z", 'z', SDLK_z }, |
||
91 | { "X", 'x', SDLK_x }, |
||
92 | { "C", 'c', SDLK_c }, |
||
93 | { "V", 'v', SDLK_v }, |
||
94 | { "B", 'b', SDLK_b }, |
||
95 | { "N", 'n', SDLK_n }, |
||
96 | { "M", 'm', SDLK_m }, // 50 |
||
97 | { ",", ',', SDLK_COMMA }, |
||
98 | { ".", '.', SDLK_PERIOD }, |
||
99 | { "/", '/', SDLK_SLASH }, |
||
100 | { "RSHFT", 255, SDLK_RSHIFT }, |
||
101 | { "PAD*", '*', SDLK_KP_MULTIPLY }, |
||
102 | { "LALT", 255, SDLK_LALT }, |
||
103 | { "SPC", ' ', SDLK_SPACE }, |
||
104 | { "CPSLK", 255, SDLK_CAPSLOCK }, |
||
105 | { "F1", 255, SDLK_F1 }, |
||
106 | { "F2", 255, SDLK_F2 }, // 60 |
||
107 | { "F3", 255, SDLK_F3 }, |
||
108 | { "F4", 255, SDLK_F4 }, |
||
109 | { "F5", 255, SDLK_F5 }, |
||
110 | { "F6", 255, SDLK_F6 }, |
||
111 | { "F7", 255, SDLK_F7 }, |
||
112 | { "F8", 255, SDLK_F8 }, |
||
113 | { "F9", 255, SDLK_F9 }, |
||
114 | { "F10", 255, SDLK_F10 }, |
||
115 | #if SDL_MAJOR_VERSION == 1 |
||
116 | #define SDLK_NUMLOCKCLEAR SDLK_NUMLOCK |
||
117 | #define SDLK_SCROLLLOCK SDLK_SCROLLOCK |
||
118 | #define SDLK_KP_0 SDLK_KP0 |
||
119 | #define SDLK_KP_1 SDLK_KP1 |
||
120 | #define SDLK_KP_2 SDLK_KP2 |
||
121 | #define SDLK_KP_3 SDLK_KP3 |
||
122 | #define SDLK_KP_4 SDLK_KP4 |
||
123 | #define SDLK_KP_5 SDLK_KP5 |
||
124 | #define SDLK_KP_6 SDLK_KP6 |
||
125 | #define SDLK_KP_7 SDLK_KP7 |
||
126 | #define SDLK_KP_8 SDLK_KP8 |
||
127 | #define SDLK_KP_9 SDLK_KP9 |
||
128 | #endif |
||
129 | { "NMLCK", 255, SDLK_NUMLOCKCLEAR }, |
||
130 | { "SCLK", 255, SDLK_SCROLLLOCK }, // 70 |
||
131 | { "PAD7", 255, SDLK_KP_7 }, |
||
132 | { "PAD8", 255, SDLK_KP_8 }, |
||
133 | { "PAD9", 255, SDLK_KP_9 }, |
||
134 | { "PAD-", 255, SDLK_KP_MINUS }, |
||
135 | { "PAD4", 255, SDLK_KP_4 }, |
||
136 | { "PAD5", 255, SDLK_KP_5 }, |
||
137 | { "PAD6", 255, SDLK_KP_6 }, |
||
138 | { "PAD+", 255, SDLK_KP_PLUS }, |
||
139 | { "PAD1", 255, SDLK_KP_1 }, |
||
140 | { "PAD2", 255, SDLK_KP_2 }, // 80 |
||
141 | { "PAD3", 255, SDLK_KP_3 }, |
||
142 | { "PAD0", 255, SDLK_KP_0 }, |
||
143 | { "PAD.", 255, SDLK_KP_PERIOD }, |
||
144 | { "", 255, SDLK_UNKNOWN }, |
||
145 | { "", 255, SDLK_UNKNOWN }, |
||
146 | { "", 255, SDLK_UNKNOWN }, |
||
147 | { "F11", 255, SDLK_F11 }, |
||
148 | { "F12", 255, SDLK_F12 }, |
||
149 | { "", 255, SDLK_UNKNOWN }, |
||
150 | { "", 255, SDLK_UNKNOWN }, // 90 |
||
151 | { "", 255, SDLK_UNKNOWN }, |
||
152 | { "", 255, SDLK_UNKNOWN }, |
||
153 | { "", 255, SDLK_UNKNOWN }, |
||
154 | { "", 255, SDLK_UNKNOWN }, |
||
155 | { "", 255, SDLK_UNKNOWN }, |
||
156 | { "", 255, SDLK_UNKNOWN }, |
||
157 | { "PAUSE", 255, SDLK_PAUSE }, |
||
158 | #if SDL_MAJOR_VERSION == 2 |
||
159 | #define SDLK_WORLD_0 SDLK_UNKNOWN |
||
160 | #define SDLK_WORLD_1 SDLK_UNKNOWN |
||
161 | #define SDLK_WORLD_2 SDLK_UNKNOWN |
||
162 | #define SDLK_WORLD_3 SDLK_UNKNOWN |
||
163 | #define SDLK_WORLD_4 SDLK_UNKNOWN |
||
164 | #define SDLK_WORLD_5 SDLK_UNKNOWN |
||
165 | #define SDLK_WORLD_6 SDLK_UNKNOWN |
||
166 | #define SDLK_WORLD_7 SDLK_UNKNOWN |
||
167 | #define SDLK_WORLD_8 SDLK_UNKNOWN |
||
168 | #define SDLK_WORLD_9 SDLK_UNKNOWN |
||
169 | #define SDLK_WORLD_10 SDLK_UNKNOWN |
||
170 | #define SDLK_WORLD_11 SDLK_UNKNOWN |
||
171 | #define SDLK_WORLD_12 SDLK_UNKNOWN |
||
172 | #define SDLK_WORLD_13 SDLK_UNKNOWN |
||
173 | #define SDLK_WORLD_14 SDLK_UNKNOWN |
||
174 | #define SDLK_WORLD_15 SDLK_UNKNOWN |
||
175 | #define SDLK_WORLD_16 SDLK_UNKNOWN |
||
176 | #define SDLK_WORLD_17 SDLK_UNKNOWN |
||
177 | #define SDLK_WORLD_18 SDLK_UNKNOWN |
||
178 | #define SDLK_WORLD_19 SDLK_UNKNOWN |
||
179 | #define SDLK_WORLD_20 SDLK_UNKNOWN |
||
180 | #define SDLK_WORLD_21 SDLK_UNKNOWN |
||
181 | #define SDLK_WORLD_22 SDLK_UNKNOWN |
||
182 | #define SDLK_WORLD_23 SDLK_UNKNOWN |
||
183 | #define SDLK_WORLD_24 SDLK_UNKNOWN |
||
184 | #define SDLK_WORLD_25 SDLK_UNKNOWN |
||
185 | #define SDLK_WORLD_26 SDLK_UNKNOWN |
||
186 | #define SDLK_WORLD_27 SDLK_UNKNOWN |
||
187 | #define SDLK_WORLD_28 SDLK_UNKNOWN |
||
188 | #define SDLK_WORLD_29 SDLK_UNKNOWN |
||
189 | #define SDLK_WORLD_30 SDLK_UNKNOWN |
||
190 | #define SDLK_WORLD_31 SDLK_UNKNOWN |
||
191 | #define SDLK_WORLD_32 SDLK_UNKNOWN |
||
192 | #define SDLK_WORLD_33 SDLK_UNKNOWN |
||
193 | #define SDLK_WORLD_34 SDLK_UNKNOWN |
||
194 | #define SDLK_WORLD_35 SDLK_UNKNOWN |
||
195 | #define SDLK_WORLD_36 SDLK_UNKNOWN |
||
196 | #define SDLK_WORLD_37 SDLK_UNKNOWN |
||
197 | #define SDLK_WORLD_38 SDLK_UNKNOWN |
||
198 | #define SDLK_WORLD_39 SDLK_UNKNOWN |
||
199 | #define SDLK_WORLD_40 SDLK_UNKNOWN |
||
200 | #define SDLK_WORLD_41 SDLK_UNKNOWN |
||
201 | #define SDLK_WORLD_42 SDLK_UNKNOWN |
||
202 | #define SDLK_WORLD_43 SDLK_UNKNOWN |
||
203 | #define SDLK_WORLD_44 SDLK_UNKNOWN |
||
204 | #define SDLK_WORLD_45 SDLK_UNKNOWN |
||
205 | #define SDLK_WORLD_46 SDLK_UNKNOWN |
||
206 | #define SDLK_WORLD_47 SDLK_UNKNOWN |
||
207 | #define SDLK_WORLD_48 SDLK_UNKNOWN |
||
208 | #define SDLK_WORLD_49 SDLK_UNKNOWN |
||
209 | #define SDLK_WORLD_50 SDLK_UNKNOWN |
||
210 | #define SDLK_WORLD_51 SDLK_UNKNOWN |
||
211 | #endif |
||
212 | { "W0", 255, SDLK_WORLD_0 }, |
||
213 | { "W1", 255, SDLK_WORLD_1 }, |
||
214 | { "W2", 255, SDLK_WORLD_2 }, // 100 |
||
215 | { "W3", 255, SDLK_WORLD_3 }, |
||
216 | { "W4", 255, SDLK_WORLD_4 }, |
||
217 | { "W5", 255, SDLK_WORLD_5 }, |
||
218 | { "W6", 255, SDLK_WORLD_6 }, |
||
219 | { "W7", 255, SDLK_WORLD_7 }, |
||
220 | { "W8", 255, SDLK_WORLD_8 }, |
||
221 | { "W9", 255, SDLK_WORLD_9 }, |
||
222 | { "W10", 255, SDLK_WORLD_10 }, |
||
223 | { "W11", 255, SDLK_WORLD_11 }, |
||
224 | { "W12", 255, SDLK_WORLD_12 }, // 110 |
||
225 | { "W13", 255, SDLK_WORLD_13 }, |
||
226 | { "W14", 255, SDLK_WORLD_14 }, |
||
227 | { "W15", 255, SDLK_WORLD_15 }, |
||
228 | { "W16", 255, SDLK_WORLD_16 }, |
||
229 | { "W17", 255, SDLK_WORLD_17 }, |
||
230 | { "W18", 255, SDLK_WORLD_18 }, |
||
231 | { "W19", 255, SDLK_WORLD_19 }, |
||
232 | { "W20", 255, SDLK_WORLD_20 }, |
||
233 | { "W21", 255, SDLK_WORLD_21 }, |
||
234 | { "W22", 255, SDLK_WORLD_22 }, // 120 |
||
235 | { "W23", 255, SDLK_WORLD_23 }, |
||
236 | { "W24", 255, SDLK_WORLD_24 }, |
||
237 | { "W25", 255, SDLK_WORLD_25 }, |
||
238 | { "W26", 255, SDLK_WORLD_26 }, |
||
239 | { "W27", 255, SDLK_WORLD_27 }, |
||
240 | { "W28", 255, SDLK_WORLD_28 }, |
||
241 | { "W29", 255, SDLK_WORLD_29 }, |
||
242 | { "W30", 255, SDLK_WORLD_30 }, |
||
243 | { "W31", 255, SDLK_WORLD_31 }, |
||
244 | { "W32", 255, SDLK_WORLD_32 }, // 130 |
||
245 | { "W33", 255, SDLK_WORLD_33 }, |
||
246 | { "W34", 255, SDLK_WORLD_34 }, |
||
247 | { "W35", 255, SDLK_WORLD_35 }, |
||
248 | { "W36", 255, SDLK_WORLD_36 }, |
||
249 | { "W37", 255, SDLK_WORLD_37 }, |
||
250 | { "W38", 255, SDLK_WORLD_38 }, |
||
251 | { "W39", 255, SDLK_WORLD_39 }, |
||
252 | { "W40", 255, SDLK_WORLD_40 }, |
||
253 | { "W41", 255, SDLK_WORLD_41 }, |
||
254 | { "W42", 255, SDLK_WORLD_42 }, // 140 |
||
255 | { "W43", 255, SDLK_WORLD_43 }, |
||
256 | { "W44", 255, SDLK_WORLD_44 }, |
||
257 | { "W45", 255, SDLK_WORLD_45 }, |
||
258 | { "W46", 255, SDLK_WORLD_46 }, |
||
259 | { "W47", 255, SDLK_WORLD_47 }, |
||
260 | { "W48", 255, SDLK_WORLD_48 }, |
||
261 | { "W49", 255, SDLK_WORLD_49 }, |
||
262 | { "W50", 255, SDLK_WORLD_50 }, |
||
263 | { "W51", 255, SDLK_WORLD_51 }, |
||
264 | { "", 255, SDLK_UNKNOWN }, // 150 |
||
265 | { "", 255, SDLK_UNKNOWN }, |
||
266 | { "", 255, SDLK_UNKNOWN }, |
||
267 | { "", 255, SDLK_UNKNOWN }, |
||
268 | { "", 255, SDLK_UNKNOWN }, |
||
269 | { "", 255, SDLK_UNKNOWN }, |
||
270 | { "PAD", 255, SDLK_KP_ENTER }, |
||
271 | { "RCTRL", 255, SDLK_RCTRL }, |
||
272 | #if SDL_MAJOR_VERSION == 2 |
||
273 | #define SDLK_LMETA SDLK_UNKNOWN |
||
274 | #define SDLK_RMETA SDLK_UNKNOWN |
||
275 | #endif |
||
276 | { "LCMD", 255, SDLK_LMETA }, |
||
277 | { "RCMD", 255, SDLK_RMETA }, |
||
278 | { "", 255, SDLK_UNKNOWN }, // 160 |
||
279 | { "", 255, SDLK_UNKNOWN }, |
||
280 | { "", 255, SDLK_UNKNOWN }, |
||
281 | { "", 255, SDLK_UNKNOWN }, |
||
282 | { "", 255, SDLK_UNKNOWN }, |
||
283 | { "", 255, SDLK_UNKNOWN }, |
||
284 | { "", 255, SDLK_UNKNOWN }, |
||
285 | { "", 255, SDLK_UNKNOWN }, |
||
286 | { "", 255, SDLK_UNKNOWN }, |
||
287 | { "", 255, SDLK_UNKNOWN }, |
||
288 | { "", 255, SDLK_UNKNOWN }, // 170 |
||
289 | { "", 255, SDLK_UNKNOWN }, |
||
290 | { "", 255, SDLK_UNKNOWN }, |
||
291 | { "", 255, SDLK_UNKNOWN }, |
||
292 | { "", 255, SDLK_UNKNOWN }, |
||
293 | { "", 255, SDLK_UNKNOWN }, |
||
294 | { "", 255, SDLK_UNKNOWN }, |
||
295 | { "", 255, SDLK_UNKNOWN }, |
||
296 | { "", 255, SDLK_UNKNOWN }, |
||
297 | { "", 255, SDLK_UNKNOWN }, |
||
298 | { "", 255, SDLK_UNKNOWN }, // 180 |
||
299 | { "PAD/", 255, SDLK_KP_DIVIDE }, |
||
300 | { "", 255, SDLK_UNKNOWN }, |
||
301 | #if SDL_MAJOR_VERSION == 1 |
||
302 | #define SDLK_PRINTSCREEN SDLK_PRINT |
||
303 | #endif |
||
304 | { "PRSCR", 255, SDLK_PRINTSCREEN }, |
||
305 | { "RALT", 255, SDLK_RALT }, |
||
306 | { "", 255, SDLK_UNKNOWN }, |
||
307 | { "", 255, SDLK_UNKNOWN }, |
||
308 | { "", 255, SDLK_UNKNOWN }, |
||
309 | { "", 255, SDLK_UNKNOWN }, |
||
310 | { "", 255, SDLK_UNKNOWN }, |
||
311 | { "", 255, SDLK_UNKNOWN }, // 190 |
||
312 | { "", 255, SDLK_UNKNOWN }, |
||
313 | { "", 255, SDLK_UNKNOWN }, |
||
314 | { "", 255, SDLK_UNKNOWN }, |
||
315 | { "", 255, SDLK_UNKNOWN }, |
||
316 | { "", 255, SDLK_UNKNOWN }, |
||
317 | { "", 255, SDLK_UNKNOWN }, |
||
318 | { "", 255, SDLK_UNKNOWN }, |
||
319 | { "", 255, SDLK_UNKNOWN }, |
||
320 | { "HOME", 255, SDLK_HOME }, |
||
321 | { "UP", 255, SDLK_UP }, // 200 |
||
322 | { "PGUP", 255, SDLK_PAGEUP }, |
||
323 | { "", 255, SDLK_UNKNOWN }, |
||
324 | { "LEFT", 255, SDLK_LEFT }, |
||
325 | { "", 255, SDLK_UNKNOWN }, |
||
326 | { "RIGHT", 255, SDLK_RIGHT }, |
||
327 | { "", 255, SDLK_UNKNOWN }, |
||
328 | { "END", 255, SDLK_END }, |
||
329 | { "DOWN", 255, SDLK_DOWN }, |
||
330 | { "PGDN", 255, SDLK_PAGEDOWN }, |
||
331 | { "INS", 255, SDLK_INSERT }, // 210 |
||
332 | { "DEL", 255, SDLK_DELETE }, |
||
333 | #if SDL_MAJOR_VERSION == 1 |
||
334 | { "W52", 255, SDLK_WORLD_52 }, |
||
335 | { "W53", 255, SDLK_WORLD_53 }, |
||
336 | { "W54", 255, SDLK_WORLD_54 }, |
||
337 | { "W55", 255, SDLK_WORLD_55 }, |
||
338 | { "W56", 255, SDLK_WORLD_56 }, |
||
339 | { "W57", 255, SDLK_WORLD_57 }, |
||
340 | { "W58", 255, SDLK_WORLD_58 }, |
||
341 | { "W59", 255, SDLK_WORLD_59 }, |
||
342 | { "W60", 255, SDLK_WORLD_60 }, // 220 |
||
343 | { "W61", 255, SDLK_WORLD_61 }, |
||
344 | { "W62", 255, SDLK_WORLD_62 }, |
||
345 | { "W63", 255, SDLK_WORLD_63 }, |
||
346 | { "W64", 255, SDLK_WORLD_64 }, |
||
347 | { "W65", 255, SDLK_WORLD_65 }, |
||
348 | { "W66", 255, SDLK_WORLD_66 }, |
||
349 | { "W67", 255, SDLK_WORLD_67 }, |
||
350 | { "W68", 255, SDLK_WORLD_68 }, |
||
351 | { "W69", 255, SDLK_WORLD_69 }, |
||
352 | { "W70", 255, SDLK_WORLD_70 }, // 230 |
||
353 | { "W71", 255, SDLK_WORLD_71 }, |
||
354 | { "W72", 255, SDLK_WORLD_72 }, |
||
355 | { "W73", 255, SDLK_WORLD_73 }, |
||
356 | { "W74", 255, SDLK_WORLD_74 }, |
||
357 | { "W75", 255, SDLK_WORLD_75 }, |
||
358 | { "W76", 255, SDLK_WORLD_76 }, |
||
359 | { "W77", 255, SDLK_WORLD_77 }, |
||
360 | { "W78", 255, SDLK_WORLD_78 }, |
||
361 | { "W79", 255, SDLK_WORLD_79 }, |
||
362 | { "W80", 255, SDLK_WORLD_80 }, // 240 |
||
363 | { "W81", 255, SDLK_WORLD_81 }, |
||
364 | { "W82", 255, SDLK_WORLD_82 }, |
||
365 | { "W83", 255, SDLK_WORLD_83 }, |
||
366 | { "W84", 255, SDLK_WORLD_84 }, |
||
367 | { "W85", 255, SDLK_WORLD_85 }, |
||
368 | { "W86", 255, SDLK_WORLD_86 }, |
||
369 | { "W87", 255, SDLK_WORLD_87 }, |
||
370 | { "W88", 255, SDLK_WORLD_88 }, |
||
371 | { "W89", 255, SDLK_WORLD_89 }, |
||
372 | { "W90", 255, SDLK_WORLD_90 }, // 250 |
||
373 | { "W91", 255, SDLK_WORLD_91 }, |
||
374 | { "W92", 255, SDLK_WORLD_92 }, |
||
375 | { "W93", 255, SDLK_WORLD_93 }, |
||
376 | { "W94", 255, SDLK_WORLD_94 }, |
||
377 | { "W95", 255, SDLK_WORLD_95 }, // 255 |
||
378 | #endif |
||
379 | }}; |
||
380 | |||
381 | namespace { |
||
382 | |||
383 | struct d_event_keycommand : d_event |
||
384 | { |
||
385 | const unsigned keycode; |
||
386 | constexpr d_event_keycommand(const event_type t, const unsigned k) : |
||
387 | d_event(t), keycode(k) |
||
388 | { |
||
389 | } |
||
390 | }; |
||
391 | |||
392 | } |
||
393 | |||
394 | static int key_ismodlck(int keycode) |
||
395 | { |
||
396 | switch (keycode) |
||
397 | { |
||
398 | case KEY_LSHIFT: |
||
399 | case KEY_RSHIFT: |
||
400 | case KEY_LALT: |
||
401 | case KEY_RALT: |
||
402 | case KEY_LCTRL: |
||
403 | case KEY_RCTRL: |
||
404 | case KEY_LMETA: |
||
405 | case KEY_RMETA: |
||
406 | return KEY_ISMOD; |
||
407 | case KEY_NUMLOCK: |
||
408 | case KEY_SCROLLOCK: |
||
409 | case KEY_CAPSLOCK: |
||
410 | return KEY_ISLCK; |
||
411 | default: |
||
412 | return 0; |
||
413 | } |
||
414 | } |
||
415 | |||
416 | unsigned char key_ascii() |
||
417 | { |
||
418 | using std::move; |
||
419 | using std::next; |
||
420 | static std::array<unsigned char, KEY_BUFFER_SIZE> unibuffer; |
||
421 | auto src = begin(unicode_frame_buffer); |
||
422 | auto dst = next(begin(unibuffer), strlen(reinterpret_cast<const char *>(&unibuffer[0]))); |
||
423 | |||
424 | // move temporal chars from unicode_frame_buffer to empty space behind last unibuffer char (if any) |
||
425 | for (; dst != end(unibuffer); ++dst) |
||
426 | if (*src != '\0') |
||
427 | { |
||
428 | *dst = *src; |
||
429 | *src = '\0'; |
||
430 | ++src; |
||
431 | } |
||
432 | |||
433 | // unibuffer is not empty. store first char, remove it, shift all chars one step left and then print our char |
||
434 | if (unibuffer[0] != '\0') |
||
435 | { |
||
436 | unsigned char retval = unibuffer[0]; |
||
437 | *move(next(unibuffer.begin()), unibuffer.end(), unibuffer.begin()) = 0; |
||
438 | return retval; |
||
439 | } |
||
440 | else |
||
441 | return 255; |
||
442 | } |
||
443 | |||
444 | void pressed_keys::update(const std::size_t keycode, const uint8_t down) |
||
445 | { |
||
446 | constexpr unsigned all_modifiers_combined = KEY_SHIFTED | KEY_ALTED | KEY_CTRLED | KEY_DEBUGGED | KEY_METAED; |
||
447 | constexpr unsigned all_modifiers_shifted = all_modifiers_combined >> modifier_shift; |
||
448 | static_assert(all_modifiers_combined == all_modifiers_shifted << modifier_shift, "shift error"); |
||
449 | static_assert(all_modifiers_shifted == static_cast<uint8_t>(all_modifiers_shifted), "truncation error"); |
||
450 | uint8_t mask; |
||
451 | keyd_pressed.update_pressed(keycode, down); |
||
452 | switch (keycode) |
||
453 | { |
||
454 | case KEY_LSHIFT: |
||
455 | case KEY_RSHIFT: |
||
456 | mask = KEY_SHIFTED >> modifier_shift; |
||
457 | break; |
||
458 | case KEY_LALT: |
||
459 | case KEY_RALT: |
||
460 | mask = KEY_ALTED >> modifier_shift; |
||
461 | break; |
||
462 | case KEY_LCTRL: |
||
463 | case KEY_RCTRL: |
||
464 | mask = KEY_CTRLED >> modifier_shift; |
||
465 | break; |
||
466 | case KEY_DELETE: |
||
467 | mask = KEY_DEBUGGED >> modifier_shift; |
||
468 | break; |
||
469 | case KEY_LMETA: |
||
470 | case KEY_RMETA: |
||
471 | mask = KEY_METAED >> modifier_shift; |
||
472 | break; |
||
473 | default: |
||
474 | return; |
||
475 | } |
||
476 | if (down) |
||
477 | modifier_cache |= mask; |
||
478 | else |
||
479 | modifier_cache &= ~mask; |
||
480 | } |
||
481 | |||
482 | window_event_result key_handler(const SDL_KeyboardEvent *const kevent) |
||
483 | { |
||
484 | // Read SDLK symbol and state |
||
485 | const auto event_keysym = kevent->keysym.sym; |
||
486 | if (event_keysym == SDLK_UNKNOWN) |
||
487 | return window_event_result::ignored; |
||
488 | const auto key_state = (kevent->state != SDL_RELEASED); |
||
489 | |||
490 | // fill the unicode frame-related unicode buffer |
||
491 | if (key_state) |
||
492 | { |
||
493 | #if SDL_MAJOR_VERSION == 1 |
||
494 | const auto sym = kevent->keysym.unicode; |
||
495 | #elif SDL_MAJOR_VERSION == 2 |
||
496 | const auto sym = kevent->keysym.sym; |
||
497 | #endif |
||
498 | if (sym > 31 && sym < 255) |
||
499 | { |
||
500 | range_for (auto &i, unicode_frame_buffer) |
||
501 | if (i == '\0') |
||
502 | { |
||
503 | i = sym; |
||
504 | break; |
||
505 | } |
||
506 | } |
||
507 | } |
||
508 | |||
509 | //===================================================== |
||
510 | auto re = key_properties.rend(); |
||
511 | auto fi = std::find_if(key_properties.rbegin(), re, [event_keysym](const key_props &k) { return k.sym == event_keysym; }); |
||
512 | if (fi == re) |
||
513 | return window_event_result::ignored; |
||
514 | unsigned keycode = std::distance(key_properties.begin(), std::next(fi).base()); |
||
515 | if (keycode == 0) |
||
516 | return window_event_result::ignored; |
||
517 | |||
518 | /* |
||
519 | * process the key if: |
||
520 | * - it's a valid key AND |
||
521 | * - if the keystate has changed OR |
||
522 | * - key state same as last one and game accepts key repeats but keep out mod/lock keys |
||
523 | */ |
||
524 | if (key_state != keyd_pressed[keycode] || (keyd_repeat && !key_ismodlck(keycode))) |
||
525 | { |
||
526 | // now update the key props |
||
527 | keyd_pressed.update(keycode, key_state); |
||
528 | const auto raw_keycode = keycode; |
||
529 | keycode |= keyd_pressed.get_modifiers(); |
||
530 | |||
531 | // We allowed the key to be added to the queue for now, |
||
532 | // because there are still input loops without associated windows |
||
533 | const d_event_keycommand event{key_state ? EVENT_KEY_COMMAND : EVENT_KEY_RELEASE, keycode}; |
||
534 | con_printf(CON_DEBUG, "Sending event %s: %s %s %s %s %s %s", |
||
535 | (key_state) ? "EVENT_KEY_COMMAND": "EVENT_KEY_RELEASE", |
||
536 | (keycode & KEY_METAED) ? "META" : "", |
||
537 | (keycode & KEY_DEBUGGED) ? "DEBUG" : "", |
||
538 | (keycode & KEY_CTRLED) ? "CTRL" : "", |
||
539 | (keycode & KEY_ALTED) ? "ALT" : "", |
||
540 | (keycode & KEY_SHIFTED) ? "SHIFT" : "", |
||
541 | key_properties[raw_keycode].key_text |
||
542 | ); |
||
543 | return event_send(event); |
||
544 | } |
||
545 | return window_event_result::ignored; |
||
546 | } |
||
547 | |||
548 | void key_init() |
||
549 | { |
||
550 | #if SDL_MAJOR_VERSION == 1 |
||
551 | SDL_EnableUNICODE(1); |
||
552 | #endif |
||
553 | key_toggle_repeat(1); |
||
554 | |||
555 | keyd_time_when_last_pressed = timer_query(); |
||
556 | // Clear the keyboard array |
||
557 | key_flush(); |
||
558 | } |
||
559 | |||
560 | static void restore_sticky_key(const uint8_t *keystate, const unsigned i) |
||
561 | { |
||
562 | #if SDL_MAJOR_VERSION == 1 |
||
563 | const auto ki = key_properties[i].sym; |
||
564 | #elif SDL_MAJOR_VERSION == 2 |
||
565 | const auto ki = i; |
||
566 | #endif |
||
567 | const auto v = keystate[ki]; // do not flush status of sticky keys |
||
568 | keyd_pressed.update_pressed(i, v); |
||
569 | } |
||
570 | |||
571 | void key_flush() |
||
572 | { |
||
573 | //Clear the unicode buffer |
||
574 | unicode_frame_buffer = {}; |
||
575 | keyd_pressed = {}; |
||
576 | if (unlikely(CGameArg.CtlNoStickyKeys)) |
||
577 | return; |
||
578 | #if SDL_MAJOR_VERSION == 1 |
||
579 | const auto &keystate = SDL_GetKeyState(nullptr); |
||
580 | #define DXX_SDL_STICKY_KEYS {KEY_CAPSLOCK, KEY_NUMLOCK, KEY_SCROLLOCK} |
||
581 | #elif SDL_MAJOR_VERSION == 2 |
||
582 | const auto &keystate = SDL_GetKeyboardState(nullptr); |
||
583 | #define DXX_SDL_STICKY_KEYS {SDL_SCANCODE_CAPSLOCK, SDL_SCANCODE_SCROLLLOCK, SDL_SCANCODE_NUMLOCKCLEAR} |
||
584 | #endif |
||
585 | range_for (const auto key, DXX_SDL_STICKY_KEYS) |
||
586 | #undef DXX_SDL_STICKY_KEYS |
||
587 | restore_sticky_key(keystate, key); |
||
588 | } |
||
589 | |||
590 | void event_keycommand_send(unsigned key) { |
||
591 | const d_event_keycommand event{EVENT_KEY_COMMAND, key}; |
||
592 | event_send(event); |
||
593 | } |
||
594 | |||
595 | int event_key_get(const d_event &event) |
||
596 | { |
||
597 | auto &e = static_cast<const d_event_keycommand &>(event); |
||
598 | Assert(e.type == EVENT_KEY_COMMAND || e.type == EVENT_KEY_RELEASE); |
||
599 | return e.keycode; |
||
600 | } |
||
601 | |||
602 | // same as above but without mod states |
||
603 | int event_key_get_raw(const d_event &event) |
||
604 | { |
||
605 | return event_key_get(event) & ~(KEY_SHIFTED | KEY_ALTED | KEY_CTRLED | KEY_DEBUGGED | KEY_METAED); |
||
606 | } |
||
607 | |||
608 | void key_toggle_repeat1() |
||
609 | { |
||
610 | #if SDL_MAJOR_VERSION == 1 |
||
611 | if (SDL_EnableKeyRepeat(KEY_REPEAT_DELAY, KEY_REPEAT_INTERVAL) == 0) |
||
612 | #endif |
||
613 | keyd_repeat = 1; |
||
614 | key_flush(); |
||
615 | } |
||
616 | |||
617 | void key_toggle_repeat0() |
||
618 | { |
||
619 | #if SDL_MAJOR_VERSION == 1 |
||
620 | SDL_EnableKeyRepeat(0, 0); |
||
621 | #endif |
||
622 | keyd_repeat = 0; |
||
623 | key_flush(); |
||
624 | } |
||
625 | |||
626 | } |