1 /*
2 * vkbd.c - SDL virtual keyboard.
3 *
4 * Written by
5 * Hannu Nuotio <hannu.nuotio@tut.fi>
6 *
7 * Based on code by
8 * Mike Dawson <mike@gp2x.org>
9 *
10 * This file is part of VICE, the Versatile Commodore Emulator.
11 * See README for copyright notice.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 * 02111-1307 USA.
27 *
28 */
29
30 #include "vice.h"
31
32 #include <stdio.h>
33
34 #include "joy.h"
35 #include "kbd.h"
36 #include "keyboard.h"
37 #include "menu_common.h"
38 #include "types.h"
39 #include "ui.h"
40 #include "uimenu.h"
41 #include "uipoll.h"
42 #include "videoarch.h"
43 #include "vkbd.h"
44
45 int sdl_vkbd_state = 0;
46
47 /* ------------------------------------------------------------------ */
48 /* static functions/variables */
49
50 static int vkbd_pos_x = 0;
51 static int vkbd_pos_y = 0;
52 static int vkbd_pos_max_x = 0;
53 static int vkbd_pos_max_y = 0;
54
55 static vkbd_t *vkbd = NULL;
56 static int vkbd_w = 0;
57 static int vkbd_h = 0;
58
59 static int vkbd_x = 0;
60 static int vkbd_y = 0;
61
62 static int vkbd_move = 0;
63
64 static int vkbd_shiftflags;
65
UI_MENU_CALLBACK(custom_shift_callback)66 static UI_MENU_CALLBACK(custom_shift_callback)
67 {
68 int flag = (1 << (vice_ptr_to_int(param)));
69
70 if (activated) {
71 vkbd_shiftflags ^= flag;
72 } else {
73 if (vkbd_shiftflags & flag) {
74 return sdl_menu_text_tick;
75 }
76 }
77 return NULL;
78 }
79
80 static const ui_menu_entry_t define_shift_options_menu[] = {
81 { "Virtual shift",
82 MENU_ENTRY_OTHER,
83 custom_shift_callback,
84 (ui_callback_data_t)0 },
85 { "Left shift",
86 MENU_ENTRY_OTHER,
87 custom_shift_callback,
88 (ui_callback_data_t)1 },
89 { "Right shift",
90 MENU_ENTRY_OTHER,
91 custom_shift_callback,
92 (ui_callback_data_t)2 },
93 { "Allow shift",
94 MENU_ENTRY_OTHER,
95 custom_shift_callback,
96 (ui_callback_data_t)3 },
97 { "Deshift shift",
98 MENU_ENTRY_OTHER,
99 custom_shift_callback,
100 (ui_callback_data_t)4 },
101 { "Allow other",
102 MENU_ENTRY_OTHER,
103 custom_shift_callback,
104 (ui_callback_data_t)5 },
105 { "Alt map",
106 MENU_ENTRY_OTHER,
107 custom_shift_callback,
108 (ui_callback_data_t)8 },
109 SDL_MENU_LIST_END
110 };
111
112 static const ui_menu_entry_t shift_menu[] = {
113 { "Define shift options",
114 MENU_ENTRY_SUBMENU,
115 submenu_radio_callback,
116 (ui_callback_data_t)define_shift_options_menu },
117 SDL_MENU_LIST_END
118 };
119
120 #define VKBD_COMMAND_MOVE 0xff
121 #define VKBD_COMMAND_CLOSE 0xfe
122
sdl_vkbd_key_press(int value,int shift)123 static void sdl_vkbd_key_press(int value, int shift)
124 {
125 int mr, mc, neg;
126 uint8_t b, sb;
127
128 b = vkbd->keytable[vkbd_x + vkbd_y * vkbd_w];
129
130 if ((b == VKBD_COMMAND_CLOSE) && (value)) {
131 sdl_vkbd_close();
132 return;
133 }
134
135 if (b == VKBD_COMMAND_MOVE) {
136 if (value && shift) {
137 sdl_vkbd_close();
138 } else {
139 vkbd_move = value;
140 }
141 return;
142 }
143
144 neg = b & 0x08;
145
146 if (shift && !neg) {
147 sb = vkbd->shift;
148 mc = (int)(sb & 0xf);
149 mr = (int)((sb >> 4) & 0xf);
150 keyboard_set_keyarr(mr, mc, value);
151 }
152
153 mc = (int)(b & 0x7);
154 mr = (int)((b >> 4) & 0xf);
155
156 if (neg) {
157 mr = -mr;
158 }
159
160 keyboard_set_keyarr_any(mr, mc, value);
161 }
162
sdl_vkbd_key_map(void)163 static void sdl_vkbd_key_map(void)
164 {
165 int mr, mc, neg, i, j;
166 uint8_t b;
167 SDL_Event e;
168 int unmap = 0;
169 char keyname[10];
170
171 b = vkbd->keytable[vkbd_x + vkbd_y * vkbd_w];
172
173 if (b == VKBD_COMMAND_CLOSE) {
174 return;
175 }
176 sdl_vkbd_state &= SDL_VKBD_REPAINT;
177
178 sdl_ui_activate_pre_action();
179
180 /* Use blank for unmapping */
181 if (b == VKBD_COMMAND_MOVE) {
182 unmap = 1;
183 } else {
184 /* get the key name for displaying */
185 for (j = vkbd_x; (j > -1) && (vkbd->keytable[j + vkbd_y * vkbd_w] == b); --j) {
186 }
187 ++j;
188
189 for (i = 0; ((i + j) < vkbd_w) && (vkbd->keytable[i + j + vkbd_y * vkbd_w] == b); ++i) {
190 keyname[i] = vkbd->keyb[vkbd_y][i + j];
191 }
192
193 keyname[i] = 0;
194 }
195
196 neg = b & 0x08;
197 mc = (int)(b & 0x7);
198 mr = (int)((b >> 4) & 0xf);
199
200 if (neg) {
201 mr = -mr;
202 }
203
204 e = sdl_ui_poll_event("key or joystick event", unmap ? "(unmap)" : keyname, SDL_POLL_KEYBOARD | SDL_POLL_MODIFIER | SDL_POLL_JOYSTICK, 5);
205
206 /* TODO check if key/event is suitable */
207 switch (e.type) {
208 case SDL_KEYDOWN:
209 if (!unmap) {
210 vkbd_shiftflags = (1 << 3);
211 sdl_ui_external_menu_activate((ui_menu_entry_t *)shift_menu);
212 keyboard_set_map_any((signed long)SDL2x_to_SDL1x_Keys(e.key.keysym.sym), mr, mc, vkbd_shiftflags);
213 } else {
214 keyboard_set_unmap_any((signed long)SDL2x_to_SDL1x_Keys(e.key.keysym.sym));
215 }
216 break;
217 #ifdef HAVE_SDL_NUMJOYSTICKS
218 case SDL_JOYAXISMOTION:
219 case SDL_JOYBUTTONDOWN:
220 case SDL_JOYHATMOTION:
221 if (unmap) {
222 sdljoy_unset(e);
223 } else {
224 sdljoy_set_keypress(e, mr, mc);
225 }
226 break;
227 #endif
228 default:
229 break;
230 }
231
232 sdl_ui_activate_post_action();
233 sdl_vkbd_state = SDL_VKBD_ACTIVE;
234 }
235
sdl_vkbd_move(int * var,int amount,int min,int max)236 static inline void sdl_vkbd_move(int *var, int amount, int min, int max)
237 {
238 *var += amount;
239
240 if (*var < min) {
241 *var = max - 1;
242 } else if (*var >= max) {
243 *var = min;
244 }
245
246 sdl_vkbd_state |= SDL_VKBD_REPAINT;
247 }
248
249 /* ------------------------------------------------------------------ */
250 /* External interface */
251
sdl_vkbd_set_vkbd(const vkbd_t * machine_vkbd)252 void sdl_vkbd_set_vkbd(const vkbd_t *machine_vkbd)
253 {
254 vkbd = (vkbd_t *)machine_vkbd;
255
256 if (vkbd == NULL) {
257 return;
258 }
259
260 for (vkbd_h = 0; vkbd->keyb[vkbd_h] != NULL; ++vkbd_h) {
261 }
262
263 if (vkbd_h > 0) {
264 for (vkbd_w = 0; vkbd->keyb[0][vkbd_w] != 0; ++vkbd_w) {
265 }
266 }
267 }
268
sdl_vkbd_activate(void)269 void sdl_vkbd_activate(void)
270 {
271 menu_draw_t *limits = NULL;
272
273 if (vkbd == NULL) {
274 return;
275 }
276
277 sdl_ui_init_draw_params();
278 limits = sdl_ui_get_menu_param();
279
280 vkbd_pos_max_x = limits->max_text_x - vkbd_w + 1;
281 vkbd_pos_max_y = limits->max_text_y - vkbd_h + 1;
282
283 if (vkbd_pos_x >= vkbd_pos_max_x) {
284 vkbd_pos_x = vkbd_pos_max_x - 1;
285 }
286
287 if (vkbd_pos_y >= vkbd_pos_max_y) {
288 vkbd_pos_y = vkbd_pos_max_y - 1;
289 }
290
291 sdl_vkbd_state = SDL_VKBD_ACTIVE | SDL_VKBD_REPAINT;
292 vkbd_move = 0;
293 }
294
sdl_vkbd_close(void)295 void sdl_vkbd_close(void)
296 {
297 keyboard_key_clear();
298 sdl_vkbd_state = SDL_VKBD_REPAINT;
299 }
300
sdl_vkbd_draw(void)301 void sdl_vkbd_draw(void)
302 {
303 int i;
304 sdl_ui_set_active_font(MENU_FONT_MONITOR);
305
306 for (i = 0; i < vkbd_h; ++i) {
307 sdl_ui_print(vkbd->keyb[i], vkbd_pos_x, vkbd_pos_y + i);
308 }
309
310 sdl_ui_invert_char(vkbd_pos_x + vkbd_x, vkbd_pos_y + vkbd_y);
311
312 sdl_ui_set_active_font(MENU_FONT_ASCII);
313
314 }
315
sdl_vkbd_process(ui_menu_action_t input)316 int sdl_vkbd_process(ui_menu_action_t input)
317 {
318 int retval = 1;
319
320 switch (input) {
321 case MENU_ACTION_UP:
322 if (vkbd_move) {
323 sdl_vkbd_move(&vkbd_pos_y, -1, 0, vkbd_pos_max_y);
324 } else {
325 sdl_vkbd_move(&vkbd_y, -1, 0, vkbd_h);
326 }
327 break;
328 case MENU_ACTION_DOWN:
329 if (vkbd_move) {
330 sdl_vkbd_move(&vkbd_pos_y, 1, 0, vkbd_pos_max_y);
331 } else {
332 sdl_vkbd_move(&vkbd_y, 1, 0, vkbd_h);
333 }
334 break;
335 case MENU_ACTION_LEFT:
336 if (vkbd_move) {
337 sdl_vkbd_move(&vkbd_pos_x, -1, 0, vkbd_pos_max_x);
338 } else {
339 sdl_vkbd_move(&vkbd_x, -1, 0, vkbd_w);
340 }
341 break;
342 case MENU_ACTION_RIGHT:
343 if (vkbd_move) {
344 sdl_vkbd_move(&vkbd_pos_x, 1, 0, vkbd_pos_max_x);
345 } else {
346 sdl_vkbd_move(&vkbd_x, 1, 0, vkbd_w);
347 }
348 break;
349 case MENU_ACTION_SELECT:
350 sdl_vkbd_key_press(1, 0);
351 break;
352 case MENU_ACTION_SELECT_RELEASE:
353 sdl_vkbd_key_press(0, 0);
354 break;
355 case MENU_ACTION_CANCEL:
356 sdl_vkbd_key_press(1, 1);
357 break;
358 case MENU_ACTION_CANCEL_RELEASE:
359 sdl_vkbd_key_press(0, 1);
360 break;
361 case MENU_ACTION_MAP:
362 sdl_vkbd_key_map();
363 retval = 0;
364 break;
365 case MENU_ACTION_EXIT:
366 sdl_vkbd_close();
367 retval = 0;
368 break;
369 default:
370 retval = 0;
371 break;
372 }
373
374 return retval;
375 }
376
377 /* ------------------------------------------------------------------ */
378 /* virtual keyboards */
379
380 static const char *keyb_c64[] = {
381 "X \x5f 1234567890+-\x5ch del F1",
382 "ctrl QWERTYUIOP@*\x5e rstr F3",
383 "r/s ASDFGHJKL:;= rtrn F5",
384 "c= sh ZXCVBNM,./v> sh F7",
385 " space ",
386 NULL
387 };
388
389 static const uint8_t keytable_c64[] =
390 "\xfe\xff\x71\xff\x70\x73\x10\x13\x20\x23\x30\x33\x40\x43\x50\x53\x60\x63\xff\x00\x00\x00\xff\xff\x04\x04"
391 "\x72\x72\x72\x72\xff\x76\x11\x16\x21\x26\x31\x36\x41\x46\x51\x56\x61\x66\xff\x38\x38\x38\x38\xff\x05\x05"
392 "\x77\x77\x77\xff\xff\xff\x12\x15\x22\x25\x32\x35\x42\x45\x52\x55\x62\x65\xff\x01\x01\x01\x01\xff\x06\x06"
393 "\x75\x75\xff\x17\x17\xff\xff\x14\x27\x24\x37\x34\x47\x44\x57\x54\x67\x07\x02\xff\x64\x64\xff\xff\x03\x03"
394 "\xff\xff\xff\xff\xff\xff\xff\xff\x74\x74\x74\x74\x74\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
395
396 static const uint8_t keytable_vic20[] =
397 "\xfe\xff\x01\xff\x00\x07\x10\x17\x20\x27\x30\x37\x40\x47\x50\x57\x60\x67\xff\x70\x70\x70\xff\xff\x74\x74"
398 "\x02\x02\x02\x02\xff\x06\x11\x16\x21\x26\x31\x36\x41\x46\x51\x56\x61\x66\xff\x38\x38\x38\x38\xff\x75\x75"
399 "\x03\x03\x03\xff\xff\xff\x12\x15\x22\x25\x32\x35\x42\x45\x52\x55\x62\x65\xff\x71\x71\x71\x71\xff\x76\x76"
400 "\x05\x05\xff\x13\x13\xff\xff\x14\x23\x24\x33\x34\x43\x44\x53\x54\x63\x73\x72\xff\x64\x64\xff\xff\x77\x77"
401 "\xff\xff\xff\xff\xff\xff\xff\xff\x04\x04\x04\x04\x04\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
402
403 vkbd_t vkbd_c64 = {
404 keyb_c64,
405 keytable_c64,
406 '\x17'
407 };
408
409 vkbd_t vkbd_vic20 = {
410 keyb_c64,
411 keytable_vic20,
412 '\x13'
413 };
414
415 static const char *keyb_c64dtv[] = {
416 "X \x5f 1234567890+-\x5ch del F1",
417 "ctrl QWERTYUIOP@*\x5e rstr F3",
418 "r/s ASDFGHJKL:;= rtrn F5",
419 "c= sh ZXCVBNM,./v> sh F7",
420 " space ABCD R ",
421 NULL
422 };
423
424 static const uint8_t keytable_c64dtv[] =
425 "\xfe\xff\x71\xff\x70\x73\x10\x13\x20\x23\x30\x33\x40\x43\x50\x53\x60\x63\xff\x00\x00\x00\xff\xff\x04\x04"
426 "\x72\x72\x72\x72\xff\x76\x11\x16\x21\x26\x31\x36\x41\x46\x51\x56\x61\x66\xff\x38\x38\x38\x38\xff\x05\x05"
427 "\x77\x77\x77\xff\xff\xff\x12\x15\x22\x25\x32\x35\x42\x45\x52\x55\x62\x65\xff\x01\x01\x01\x01\xff\x06\x06"
428 "\x75\x75\xff\x17\x17\xff\xff\x14\x27\x24\x37\x34\x47\x44\x57\x54\x67\x07\x02\xff\x64\x64\xff\xff\x03\x03"
429 "\xff\xff\xff\xff\xff\xff\xff\xff\x74\x74\x74\x74\x74\xff\xff\xff\xff\xff\xff\x04\x00\x01\x02\xff\x03\xff";
430
431 vkbd_t vkbd_c64dtv = {
432 keyb_c64dtv,
433 keytable_c64dtv,
434 '\x17'
435 };
436
437 static const char *keyb_c128[] = {
438 "X etac hldn \x5ev<> f1 f3 f5 f7",
439 " \x5f 1234567890+-\x5ch del 789+",
440 "ctrl QWERTYUIOP@*\x5e rstr 456-",
441 "r/s ASDFGHJKL:;= rtrn 123e",
442 "c= sh ZXCVBNM,./v> sh 0 .e",
443 " space ",
444 NULL
445 };
446
447 static const uint8_t keytable_c128[] =
448 "\xfe\xff\x90\x83\xa0\x49\xff\x80\x93\x48\xa7\xff\xa3\xa4\xa5\xa6\xff\x04\x04\xff\x05\x05\xff\x06\x06\xff\x03\x03"
449 "\xff\xff\x71\xff\x70\x73\x10\x13\x20\x23\x30\x33\x40\x43\x50\x53\x60\x63\xff\xff\x00\x00\x00\xff\x86\x81\x96\x91"
450 "\x72\x72\x72\x72\xff\x76\x11\x16\x21\x26\x31\x36\x41\x46\x51\x56\x61\x66\xff\x38\x38\x38\x38\xff\x85\x82\x95\x92"
451 "\x77\x77\x77\xff\xff\xff\x12\x15\x22\x25\x32\x35\x42\x45\x52\x55\x62\x65\xff\x01\x01\x01\x01\xff\x87\x84\x97\x94"
452 "\x75\x75\xff\x17\x17\xff\xff\x14\x27\x24\x37\x34\x47\x44\x57\x54\x67\x07\x02\xff\x64\x64\xff\xff\xa1\xff\xa2\x94"
453 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\x74\x74\x74\x74\x74\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
454
455 vkbd_t vkbd_c128 = {
456 keyb_c128,
457 keytable_c128,
458 '\x17'
459 };
460
461 static const char *keyb_plus4[] = {
462 "X F1 F2 F3 Help ",
463 "esc 1234567890+-=h del",
464 "ctrl QWERTYUIOP@\x5c* ctrl",
465 "rs sh ASDFGHJKL:; rtrn ",
466 "c= sh ZXCVBNM,./ sh \x5e ",
467 " space \x5fv>",
468 NULL
469 };
470
471 static const uint8_t keytable_plus4[] =
472 "\xfe\xff\xff\x04\x04\xff\x05\x05\xff\x06\x06\xff\x03\x03\x03\x03\xff\xff\xff\xff\xff\xff\xff"
473 "\x64\x64\x64\xff\x70\x73\x10\x13\x20\x23\x30\x33\x40\x43\x66\x56\x65\x71\xff\xff\x00\x00\x00"
474 "\x72\x72\x72\x72\xff\x76\x11\x16\x21\x26\x31\x36\x41\x46\x51\x07\x02\x61\xff\x72\x72\x72\x72"
475 "\x77\x77\xff\x17\x17\xff\x12\x15\x22\x25\x32\x35\x42\x45\x52\x55\x62\xff\x01\x01\x01\x01\xff"
476 "\x75\x75\xff\xff\x17\x17\xff\x14\x27\x24\x37\x34\x47\x44\x57\x54\x67\xff\x17\x17\xff\x53\xff"
477 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\x74\x74\x74\x74\x74\xff\xff\xff\xff\xff\xff\x60\x50\x63";
478
479 vkbd_t vkbd_plus4 = {
480 keyb_plus4,
481 keytable_plus4,
482 '\x17'
483 };
484
485 static const char *keyb_cbm2[] = {
486 "X f1234567890 v\x5e<> conr/s",
487 "esc 1234567890-=\x5ci/d ?c*/",
488 "tab QWERTYUIOP()rtn 789-",
489 "shift ASDFGHJKL;'_rt 456+",
490 " shift ZXCVBNM,./sc= 123e",
491 " ctrl space 0.0e",
492 NULL
493 };
494
495 static const uint8_t keytable_cbm2[] =
496 "\xfe\xff\x80\x80\x90\xa0\xb0\xc0\xd0\xe0\xf0\x00\x10\xff\x20\x30\x31\x32\xff\x40\x50\x60\x70\x70\x70"
497 "\x70\x70\x70\xff\x91\xa1\xb1\xc1\xd1\xd2\xe1\xf1\x01\x11\x12\x21\x22\x33\x33\x33\xff\x41\x51\x61\x71"
498 "\x82\x82\x82\xff\xff\x92\xa2\xb2\xc2\xc3\xd3\xe2\xf2\x02\x13\x14\x23\x24\x24\x24\xff\x42\x52\x62\x72"
499 "\x84\x84\x84\x84\x84\xff\x93\xa3\xb3\xb4\xc4\xd4\xe3\xf3\x03\x04\x15\x25\x24\x24\xff\x43\x53\x63\x73"
500 "\xff\x84\x84\x84\x84\x84\xff\x94\xa4\xa5\xb5\xc5\xd5\xe4\xf4\xf5\x05\x83\x34\x34\xff\x44\x54\x64\x74"
501 "\xff\xff\xff\xff\x85\x85\x85\x85\xff\xe5\xe5\xe5\xe5\xe5\xff\xff\xff\xff\xff\xff\xff\x45\x55\x65\x74";
502
503 vkbd_t vkbd_cbm2 = {
504 keyb_cbm2,
505 keytable_cbm2,
506 '\x84'
507 };
508
509 /* FIXME: support all PET keyboards (see pet-resources.h) */
510
511 static const char *keyb_pet_uk[] = {
512 "X \x5f 1234567890:-\x5e> r/s 789",
513 "tab QWERTYUIOP\x5b\\v del 456",
514 "esc ASDFGHJKL;@\x5d rtrn 123",
515 "rvs sh ZXCVBNM,./ sh rh 0 .",
516 " space ",
517 NULL
518 };
519
520 static const uint8_t keytable_pet_uk[] =
521 "\xfe\xff\x90\xff\x10\x00\x91\x11\x01\x92\x12\x02\x93\x13\x95\x03\x15\x05\xff\x20\x20\x20\xff\xff\x14\x04\x17"
522 "\x40\x40\x40\xff\x50\x41\x51\x42\x52\x43\x53\x45\x55\x46\x56\x44\x54\xff\x47\x47\x47\xff\xff\xff\x57\x27\x37"
523 "\x20\x20\x20\xff\x30\x21\x31\x22\x32\x23\x33\x25\x35\x26\x36\x24\xff\xff\x34\x34\x34\x34\xff\xff\x87\x77\x67"
524 "\x80\x80\x80\xff\x60\x60\xff\x70\x81\x61\x71\x62\x72\x83\x73\x63\x86\xff\x66\x66\xff\x76\x84\xff\x74\xff\x64"
525 "\xff\xff\xff\xff\xff\xff\xff\xff\x74\x74\x74\x74\x74\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
526
527 vkbd_t vkbd_pet_uk = {
528 keyb_pet_uk,
529 keytable_pet_uk,
530 '\x60'
531 };
532
533 static const char *keyb_pet_gr[] = {
534 "X @!\"#$%'&\\()\x5f[] hv<i",
535 "rvs QWERTYUIOP\x5e<> 789/",
536 " ASDFGHJKL: rs rtn 456*",
537 " sh ZXCVBNM,;? sh 123+",
538 " space 0.-=",
539 NULL
540 };
541
542 static const uint8_t keytable_pet_gr[] =
543 "\xfe\xff\xff\xff\x81\x00\x10\x01\x11\x02\x12\x03\x13\x04\x14\x05\x91\x82\xff\xff\xff\xff\x06\x16\x07\x18"
544 "\x90\x90\x90\xff\x20\x30\x21\x31\x22\x32\x23\x33\x24\x34\x25\x93\x84\xff\xff\xff\xff\xff\x26\x36\x27\x37"
545 "\xff\xff\xff\xff\x40\x50\x41\x51\x42\x52\x43\x53\x44\x54\xff\x94\x94\xff\x65\x65\x65\xff\x46\x56\x47\xff"
546 "\xff\x80\x80\xff\x60\x70\x61\x71\x62\x72\x63\x73\x64\x74\xff\x85\x85\xff\xff\xff\xff\xff\x66\x76\x67\x77"
547 "\xff\xff\xff\xff\xff\xff\xff\xff\x92\x92\x92\x92\x92\xff\xff\xff\xff\xff\xff\xff\xff\xff\x86\x96\x87\x97";
548
549 vkbd_t vkbd_pet_gr = {
550 keyb_pet_gr,
551 keytable_pet_gr,
552 '\x80'
553 };
554