1 /*
2 onscreen_keyboard.c
3
4 Copyright (c) 2020
5 http://www.tuxpaint.org/
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 (See COPYING.txt)
21 */
22
23 #include "onscreen_keyboard.h"
24
25 //#define DEBUG_OSK_COMPOSEMAP
26
27 static SDL_Color def_bgcolor = { 255, 255, 255, 255 };
28 static SDL_Color def_fgcolor = { 0, 0, 0, 0 };
29
30 static void load_hlayout(osk_layout * layout, char *layout_name);
31 static void load_keymap(osk_layout * layout, char *keymap_name);
32 static void load_composemap(osk_layout * layout, char *composemap_name);
33
34 static int is_blank_or_comment(char *line);
35
36 /* static int isw_blank_or_comment(wchar_t *line); */
37
38
39 static void keybd_prepare(on_screen_keyboard * keyboard);
40
41 static void draw_key(osk_key key, on_screen_keyboard * keyboard, int hot);
42
43 static void label_key(osk_key key, on_screen_keyboard * keyboard);
44 static void draw_keyboard(on_screen_keyboard * keyboard);
45 static osk_key *find_key(on_screen_keyboard * keyboard, int x, int y);
46 static void set_key(osk_key * orig, osk_key * dest, int firsttime);
47 static void load_keysymdefs(osk_layout * layout, char *keysymdefs_name);
48 static struct osk_layout *load_layout(on_screen_keyboard * keyboard, char *layout_name);
49
50 #ifdef DEBUG_OSK_COMPOSEMAP
51 static void print_composemap(osk_composenode * composemap, char *sp);
52 #endif
53
54 #ifdef WIN32
55 #include <iconv.h>
56 #define wcstok(line, delim, pointer) wcstok(line, delim)
57 #define strtok_r(line, delim, pointer) strtok(line, delim)
58
59 static void mtw(wchar_t * wtok, char *tok);
60
mtw(wchar_t * wtok,char * tok)61 static void mtw(wchar_t * wtok, char *tok)
62 {
63 /* workaround using iconv to get a functionallity somewhat approximate as mbstowcs() */
64 Uint16 *ui16;
65 char *wrptr;
66 size_t n, in, out;
67 iconv_t trans;
68
69 n = 255;
70 in = 250;
71 out = 250;
72 ui16 = malloc(sizeof(Uint16) * 255);
73 wrptr = (char *)ui16;
74
75 trans = iconv_open("WCHAR_T", "UTF-8");
76 iconv(trans, (const char **)&tok, &in, &wrptr, &out);
77 *((wchar_t *) wrptr) = L'\0';
78 swprintf(wtok, L"%ls", ui16);
79 free(ui16);
80 iconv_close(trans);
81 }
82
83 #define mbstowcs(wtok, tok, size) mtw(wtok, tok)
84 #endif
85
osk_create(char * layout_name,SDL_Surface * canvas,SDL_Surface * LG_button_up,SDL_Surface * LG_button_down,SDL_Surface * LG_button_off,SDL_Surface * LG_button_nav,SDL_Surface * LG_button_hold,SDL_Surface * LG_oskdel,SDL_Surface * LG_osktab,SDL_Surface * LG_oskenter,SDL_Surface * LG_oskcapslock,SDL_Surface * LG_oskshift,SDL_Surface * SM_button_up,SDL_Surface * SM_button_down,SDL_Surface * SM_button_off,SDL_Surface * SM_button_nav,SDL_Surface * SM_button_hold,SDL_Surface * SM_oskdel,SDL_Surface * SM_osktab,SDL_Surface * SM_oskenter,SDL_Surface * SM_oskcapslock,SDL_Surface * SM_oskshift,int disable_change)86 struct osk_keyboard *osk_create(char * layout_name, SDL_Surface * canvas,
87 SDL_Surface * LG_button_up, SDL_Surface * LG_button_down,
88 SDL_Surface * LG_button_off, SDL_Surface * LG_button_nav,
89 SDL_Surface * LG_button_hold,
90 SDL_Surface * LG_oskdel, SDL_Surface * LG_osktab, SDL_Surface * LG_oskenter,
91 SDL_Surface * LG_oskcapslock, SDL_Surface * LG_oskshift,
92 SDL_Surface * SM_button_up, SDL_Surface * SM_button_down,
93 SDL_Surface * SM_button_off, SDL_Surface * SM_button_nav,
94 SDL_Surface * SM_button_hold,
95 SDL_Surface * SM_oskdel, SDL_Surface * SM_osktab, SDL_Surface * SM_oskenter,
96 SDL_Surface * SM_oskcapslock, SDL_Surface * SM_oskshift,
97 int disable_change)
98 {
99 SDL_Surface * surface;
100 SDL_Surface * button_up, * button_down;
101 SDL_Surface * button_off, * button_nav;
102 SDL_Surface * button_hold;
103 SDL_Surface * oskdel, * osktab, * oskenter;
104 SDL_Surface * oskcapslock, * oskshift;
105 osk_layout * layout;
106 on_screen_keyboard * keyboard;
107
108 keyboard = malloc(sizeof(on_screen_keyboard));
109
110 keyboard->osk_fonty = NULL;
111
112 keyboard->disable_change = disable_change;
113 layout = load_layout(keyboard, layout_name);
114 if (!layout)
115 {
116 fprintf(stderr, "Error trying to load the required layout %s\n", layout_name);
117 layout = load_layout(keyboard, strdup("default.layout"));
118 if (!layout)
119 {
120 fprintf(stderr, "Error trying to load the default layout\n");
121 return NULL;
122 }
123 fprintf(stderr, "Loaded the default layout instead.\n");
124 }
125
126 #ifdef DEBUG
127 printf("w %i, h %i\n", layout->width, layout->height);
128 #endif
129
130 if (layout->width * LG_button_up->w >= (canvas->w - 48 * 4) * 0.9 ||
131 layout->height * LG_button_up->h >= canvas->h * 0.5) {
132 /* Full-size buttons too large, use small buttons */
133 button_up = SM_button_up;
134 button_down = SM_button_down;
135 button_off = SM_button_off;
136 button_nav = SM_button_nav;
137 button_hold = SM_button_hold;
138 oskdel = SM_oskdel;
139 osktab = SM_osktab;
140 oskenter = SM_oskenter;
141 oskcapslock = SM_oskcapslock;
142 oskshift = SM_oskshift;
143 } else {
144 button_up = LG_button_up;
145 button_down = LG_button_down;
146 button_off = LG_button_off;
147 button_nav = LG_button_nav;
148 button_hold = LG_button_hold;
149 oskdel = LG_oskdel;
150 osktab = LG_osktab;
151 oskenter = LG_oskenter;
152 oskcapslock = LG_oskcapslock;
153 oskshift = LG_oskshift;
154 }
155
156 surface = SDL_CreateRGBSurface(canvas->flags,
157 layout->width * button_up->w,
158 layout->height * button_up->h,
159 canvas->format->BitsPerPixel,
160 canvas->format->Rmask, canvas->format->Gmask, canvas->format->Bmask, 0);
161 if (!surface)
162 {
163 fprintf(stderr, "Error creating the onscreen keyboard surface\n");
164 return NULL;
165 }
166 // keyboard->name = layout_name;
167 keyboard->canvas_ptr = canvas;
168 keyboard->layout = layout;
169 keyboard->surface = surface;
170 keyboard->rect.x = 0;
171 keyboard->rect.y = 0;
172 keyboard->rect.w = keyboard->surface->w;
173 keyboard->rect.h = keyboard->surface->h;
174 keyboard->button_up = button_up;
175 keyboard->button_down = button_down;
176 keyboard->button_off = button_off;
177 keyboard->button_nav = button_nav;
178 keyboard->button_hold = button_hold;
179 keyboard->oskdel = oskdel;
180 keyboard->osktab = osktab;
181 keyboard->oskenter = oskenter;
182 keyboard->oskcapslock = oskcapslock;
183 keyboard->oskshift = oskshift;
184 keyboard->composing = layout->composemap;
185 keyboard->composed = NULL;
186 keyboard->last_key_pressed = NULL;
187 keyboard->modifiers = 0;
188
189 set_key(NULL, &keyboard->keymodifiers.shift, 1);
190 set_key(NULL, &keyboard->keymodifiers.altgr, 1);
191 set_key(NULL, &keyboard->keymodifiers.compose, 1);
192 set_key(NULL, &keyboard->keymodifiers.dead, 1);
193
194 keyboard->kmdf.shift = NULL;
195 keyboard->kmdf.altgr = NULL;
196 keyboard->kmdf.dead = NULL;
197 keyboard->kmdf.dead2 = NULL;
198 keyboard->kmdf.dead3 = NULL;
199 keyboard->kmdf.dead4 = NULL;
200
201 keyboard->LG_button_up = LG_button_up;
202 keyboard->LG_button_down = LG_button_down;
203 keyboard->LG_button_off = LG_button_off;
204 keyboard->LG_button_nav = LG_button_nav;
205 keyboard->LG_button_hold = LG_button_hold;
206 keyboard->LG_oskdel = LG_oskdel;
207 keyboard->LG_osktab = LG_osktab;
208 keyboard->LG_oskenter = LG_oskenter;
209 keyboard->LG_oskcapslock = LG_oskcapslock;
210 keyboard->LG_oskshift = LG_oskshift;
211 keyboard->SM_button_up = SM_button_up;
212 keyboard->SM_button_down = SM_button_down;
213 keyboard->SM_button_off = SM_button_off;
214 keyboard->SM_button_nav = SM_button_nav;
215 keyboard->SM_button_hold = SM_button_hold;
216 keyboard->SM_oskdel = SM_oskdel;
217 keyboard->SM_osktab = SM_osktab;
218 keyboard->SM_oskenter = SM_oskenter;
219 keyboard->SM_oskcapslock = SM_oskcapslock;
220 keyboard->SM_oskshift = SM_oskshift;
221
222 SDL_FillRect(surface, NULL,
223 SDL_MapRGB(surface->format, keyboard->layout->bgcolor.r, keyboard->layout->bgcolor.g,
224 keyboard->layout->bgcolor.b));
225
226 keybd_prepare(keyboard);
227
228 draw_keyboard(keyboard);
229 return keyboard;
230 }
231
load_layout(on_screen_keyboard * keyboard,char * layout_name)232 static struct osk_layout *load_layout(on_screen_keyboard * keyboard, char *layout_name)
233 {
234 FILE *fi;
235 int hlayout_loaded;
236 char *line;
237 char *filename;
238 char *key, *value;
239 osk_layout *layout;
240 char * __attribute__((unused)) tmp_ptr;
241
242 layout = malloc(sizeof(osk_layout));
243 layout->name = NULL;
244 hlayout_loaded = 0;
245 #ifdef DEBUG
246 printf("load_layout %s\n", layout_name);
247 #endif
248 filename = malloc(sizeof(char) * 255);
249 if (layout_name != NULL)
250 {
251 keyboard->name = strdup(layout_name);
252 /* Try full path */
253 fi = fopen(layout_name, "r");
254 if (fi == NULL)
255 {
256 /* Try with DATA_PREFIX */
257
258 snprintf(filename, 255, "%sosk/%s", DATA_PREFIX, layout_name);
259 fi = fopen(filename, "r");
260 if (fi == NULL)
261 {
262 fprintf(stderr, "Can't open either %s nor %s\n", layout_name, filename);
263 /* Fallback to default */
264 snprintf(filename, 255, "%sosk/default.layout", DATA_PREFIX);
265 fi = fopen(filename, "r");
266 keyboard->name = strdup("default.layout");
267 }
268 }
269 }
270 else
271 {
272 snprintf(filename, 255, "%sosk/default.layout", DATA_PREFIX);
273 fi = fopen(filename, "r");
274 keyboard->name = strdup("default.layout");
275 }
276
277 free(filename);
278 if (fi == NULL)
279 {
280 fprintf(stderr, "Can't load the on screen keyboard layout\n");
281 return NULL;
282 }
283
284
285 line = malloc(sizeof(char) * 1024);
286 key = malloc(sizeof(char) * 255);
287 value = malloc(sizeof(char) * 255);
288
289 while (!feof(fi))
290 {
291 tmp_ptr = fgets(line, 1023, fi);
292
293 if (is_blank_or_comment(line))
294 continue;
295
296 sscanf(line, "%s %s", key, value);
297 if (strcmp("layout", key) == 0 && !hlayout_loaded)
298 {
299 #ifdef DEBUG
300 printf("layout found: %s\n", value);
301 #endif
302
303 load_hlayout(layout, value);
304 hlayout_loaded = 1;
305 }
306 else if (strncmp("keymap", key, 6) == 0)
307 {
308 #ifdef DEBUG
309 printf("keymap found: %s\n", value);
310 #endif
311 load_keymap(layout, value);
312 }
313 else if (strncmp("composemap", key, 10) == 0)
314 {
315 #ifdef DEBUG
316 printf("composemap found: %s\n", value);
317 #endif
318 load_composemap(layout, value);
319 }
320 else if (strncmp("keysymdefs", key, 10) == 0)
321 {
322 load_keysymdefs(layout, value);
323 }
324 else if (strncmp("keyboardlist", key, 12) == 0)
325 {
326 strcpy(value, &line[13]);
327 keyboard->keyboard_list = strdup(value);
328 }
329
330 #ifdef DEBUG
331 printf("key %s, value %s\n", key, value);
332 #endif
333 key[0] = '\0';
334 value[0] = '\0';
335 }
336
337
338
339 free(key);
340 free(value);
341 free(line);
342 fclose(fi);
343 return layout;
344 }
345
346 /* A hlayout contains the definitions of the keyboard as seen in the screen.
347 Things like the number of rows of the keyboard, the font used to render the keys,
348 the width of the keys, and a code that matches each key like in real hardware keyboards */
load_hlayout(osk_layout * layout,char * hlayout_name)349 void load_hlayout(osk_layout * layout, char *hlayout_name)
350 {
351 int width, height;
352 int key_number, line_number;
353 int keycode, shiftcaps;
354 int allocated, have_fontpath;
355 int i;
356 int r, g, b;
357 int key_width, key_width_decimal;
358 char *filename;
359 char *line;
360 char *key, *fontpath;
361 char *plain_label, *top_label, *altgr_label, *shift_altgr_label;
362 FILE *fi;
363 char * __attribute__((unused)) tmp_ptr;
364
365 key_number = line_number = 0;
366 width = height = 0;
367 allocated = 0;
368 have_fontpath = 0;
369
370 filename = malloc(sizeof(char) * 255);
371
372 /* Try full path */
373 fi = fopen(hlayout_name, "r");
374 if (fi == NULL)
375 {
376 /* Try with DATA_PREFIX */
377
378 snprintf(filename, 255, "%sosk/%s", DATA_PREFIX, hlayout_name);
379 fi = fopen(filename, "r");
380 if (fi == NULL)
381 {
382 fprintf(stderr, "Can't open either %s nor %s\n", hlayout_name, filename);
383 layout->keys = NULL;
384 free(filename);
385 return;
386 }
387 }
388
389 free(filename);
390
391 line = malloc(sizeof(char) * 1024);
392 key = malloc(sizeof(char) * 255);
393 fontpath = malloc(sizeof(char) * 255);
394 r = g = b = 256;
395
396 layout->fgcolor.r = def_fgcolor.r;
397 layout->fgcolor.g = def_fgcolor.g;
398 layout->fgcolor.b = def_fgcolor.b;
399
400 layout->bgcolor.r = def_bgcolor.r;
401 layout->bgcolor.g = def_bgcolor.g;
402 layout->bgcolor.b = def_bgcolor.b;
403
404
405 while (!feof(fi))
406 {
407 if (width && height && !allocated)
408 {
409 layout->keys = malloc(height * sizeof(osk_key *));
410 layout->keys[0] = malloc(width * sizeof(osk_key));
411
412 for (i = 0; i < width; i++)
413 {
414 layout->keys[0][i].width = 0;
415 layout->keys[0][i].plain_label = NULL;
416 layout->keys[line_number][i].top_label = NULL;
417 layout->keys[line_number][i].altgr_label = NULL;
418 layout->keys[line_number][i].shift_altgr_label = NULL;
419 }
420 layout->width = width;
421 layout->height = height;
422
423 #ifdef DEBUG
424 printf("w %i, h %i\n", layout->width, layout->height);
425 #endif
426 allocated = 1;
427 }
428
429 tmp_ptr = fgets(line, 1023, fi);
430
431 if (is_blank_or_comment(line))
432 continue;
433
434 if (strncmp(line, "WIDTH", 5) == 0)
435 sscanf(line, "%s %i", key, &width);
436
437 else if (strncmp(line, "HEIGHT", 5) == 0)
438 sscanf(line, "%s %i", key, &height);
439
440 else if (strncmp(line, "FONTPATH", 8) == 0)
441 {
442 #ifdef DEBUG
443 printf("linefont %s\n", line);
444 #endif
445 sscanf(line, "%s %s", key, fontpath);
446 if (!is_blank_or_comment(fontpath))
447 have_fontpath = 1;
448 }
449 else if (strncmp(line, "FGCOLOR", 5) == 0)
450 {
451 #ifdef DEBUG
452 printf("linefont %s\n", line);
453 #endif
454 sscanf(line, "%s %i %i %i", key, &r, &g, &b);
455 if (r > 0 && r < 256 && g > 0 && g < 256 && b > 0 && b < 256)
456 {
457 layout->fgcolor.r = r;
458 layout->fgcolor.g = g;
459 layout->fgcolor.b = b;
460 r = g = b = 256;
461 }
462 }
463 else if (strncmp(line, "BGCOLOR", 5) == 0)
464 {
465 #ifdef DEBUG
466 printf("linefont %s\n", line);
467 #endif
468 sscanf(line, "%s %i %i %i", key, &r, &g, &b);
469 if (r > 0 && r < 256 && g > 0 && g < 256 && b > 0 && b < 256)
470 {
471 layout->bgcolor.r = r;
472 layout->bgcolor.g = g;
473 layout->bgcolor.b = b;
474 r = g = b = 256;
475 }
476 }
477 else if (strncmp(line, "NEWLINE", 7) == 0)
478 {
479 line_number++;
480 key_number = 0;
481 layout->keys[line_number] = malloc(width * sizeof(osk_key));
482 for (i = 0; i < width; i++)
483 {
484 layout->keys[line_number][i].width = 0;
485 layout->keys[line_number][i].plain_label = NULL;
486 layout->keys[line_number][i].top_label = NULL;
487 layout->keys[line_number][i].altgr_label = NULL;
488 layout->keys[line_number][i].shift_altgr_label = NULL;
489 }
490 }
491 else if (width && height && allocated && strncmp(line, "KEY ", 4) == 0 && key_number < width)
492 {
493 plain_label = malloc(sizeof(char) * 64);
494 top_label = malloc(sizeof(char) * 64);
495 altgr_label = malloc(sizeof(char) * 64);
496 shift_altgr_label = malloc(sizeof(char) * 64);
497
498 sscanf(line,
499 "%s %i %i.%i %s %s %s %s %i",
500 key,
501 &keycode,
502 &key_width, &key_width_decimal, plain_label, top_label, altgr_label, shift_altgr_label, &shiftcaps);
503 layout->keys[line_number][key_number].keycode = keycode;
504 layout->keys[line_number][key_number].width = (float)0.1 *key_width_decimal + key_width;
505
506 layout->keys[line_number][key_number].plain_label = plain_label;
507 layout->keys[line_number][key_number].top_label = top_label;
508 layout->keys[line_number][key_number].altgr_label = altgr_label;
509 layout->keys[line_number][key_number].shift_altgr_label = shift_altgr_label;
510 layout->keys[line_number][key_number].shiftcaps = shiftcaps;
511 layout->keys[line_number][key_number].stick = 0;
512 key_number++;
513 }
514 }
515
516 if (have_fontpath)
517 layout->fontpath = fontpath;
518 else
519 {
520 free(fontpath);
521 layout->fontpath = NULL;
522 }
523
524 free(line);
525 free(key);
526 fclose(fi);
527 /* int j; */
528 /* for(i = 0; i<= line_number; i++) */
529 /* { */
530 /* printf("Line %i\n", i); */
531 /* for (j =0; j < width; j++) */
532 /* { */
533 /* printf(" %i, \n ", j); */
534 /* if(layout.keys[i][j].width) */
535 /* printf("keycode %d, width %f, plain %ls, caps %ls\n", */
536 /* layout.keys[i][j].keycode, */
537 /* layout.keys[i][j].width, */
538 /* layout.keys[i][j].plain_label, */
539 /* layout.keys[i][j].caps_label); */
540 /* } */
541 /* } */
542 }
543
544
545 /* A keymap contains the keysyms (X keysym mnemonics) associated to each keycode in the hlayout.*/
load_keymap(osk_layout * layout,char * keymap_name)546 void load_keymap(osk_layout * layout, char *keymap_name)
547 {
548 int i, keycode, readed;
549 char *filename;
550 char *ksname1, *ksname2, *ksname3, *ksname4;
551 char *line;
552 FILE *fi;
553 char * __attribute__((unused)) tmp_ptr;
554
555 filename = malloc(sizeof(char) * 255);
556
557 /* Try full path */
558 fi = fopen(keymap_name, "r");
559 if (fi == NULL)
560 {
561 /* Try with DATA_PREFIX */
562
563 snprintf(filename, 255, "%sosk/%s", DATA_PREFIX, keymap_name);
564 fi = fopen(filename, "r");
565 if (fi == NULL)
566 {
567 fprintf(stderr, "Can't open either %s nor %s\n", keymap_name, filename);
568 layout->keys = NULL;
569 free(filename);
570 return;
571 }
572 }
573
574 free(filename);
575
576 line = malloc(sizeof(char) * 1024);
577 layout->keymap = malloc(256 * sizeof(osk_keymap));
578
579 for (i = 0; i < 256; i++)
580 {
581 layout->keymap[i].plain = NULL;
582 layout->keymap[i].caps = NULL;
583 layout->keymap[i].altgr = NULL;
584 layout->keymap[i].shiftaltgr = NULL;
585 }
586
587
588 while (!feof(fi))
589 {
590 tmp_ptr = fgets(line, 1023, fi);
591
592 if (is_blank_or_comment(line))
593 continue;
594
595 ksname1 = malloc(sizeof(char) * 64);
596 ksname2 = malloc(sizeof(char) * 64);
597 ksname3 = malloc(sizeof(char) * 64);
598 ksname4 = malloc(sizeof(char) * 64);
599 ksname1[0] = '\0';
600 ksname2[0] = '\0';
601 ksname3[0] = '\0';
602 ksname4[0] = '\0';
603
604 /* FIXME: Why is the us-intl keymap duplicating the two first entries of every keycode? */
605 /* And why is the arabic keymap using the 5th and 6th entries as plain/shifted keys? */
606 readed = sscanf(line, "keycode %i = %s %s %s %s", &keycode, ksname1, ksname2, ksname3, ksname4);
607
608 if (readed == 5 && keycode > 8 && keycode < 256)
609 {
610 layout->keymap[keycode].plain = ksname1;
611 layout->keymap[keycode].caps = ksname2;
612 layout->keymap[keycode].altgr = ksname3;
613 layout->keymap[keycode].shiftaltgr = ksname4;
614 }
615 else
616 {
617 free(ksname1);
618 free(ksname2);
619 free(ksname3);
620 free(ksname4);
621 layout->keymap[keycode].plain = NULL;
622 layout->keymap[keycode].caps = NULL;
623 layout->keymap[keycode].altgr = NULL;
624 layout->keymap[keycode].shiftaltgr = NULL;
625 }
626 }
627
628 free(line);
629 fclose(fi);
630 /* int i; */
631 /* for (i = 0; i < 256; i++) */
632 /* { */
633 /* if (layout.keymap[i].plain) */
634 /* printf("%i, %i, %i, %i, %i\n", i, */
635 /* layout.keymap[i].plain, */
636 /* layout.keymap[i].caps, */
637 /* layout.keymap[i].altgr, */
638 /* layout.keymap[i].shiftaltgr); */
639 /* } */
640
641
642
643 }
644
645 /* Scans a line of keysyms and result and classifies them. */
gettokens(char * line,char * delim,char ** pointer,osk_composenode * composenode,osk_layout * layout)646 static void gettokens(char *line, char *delim, char **pointer, osk_composenode * composenode, osk_layout * layout)
647 {
648 int i;
649 char *tok;
650 wchar_t *result, *wtok;
651 osk_composenode *auxnode;
652
653 wtok = malloc(sizeof(wchar_t) * 255);
654
655 tok = strdup(strtok_r(line, delim, pointer));
656
657 if (!tok)
658 return;
659
660 if (tok[0] == ':') /* End of precompose keysyms, next will be the result in UTF-8. */
661 {
662 free(tok);
663 tok = strdup(strtok_r(line, ": \"\t", pointer));
664
665 mbstowcs(wtok, tok, 255);
666
667 result = wcsdup(wtok);
668 /* printf("->%ls<-\n", wtok); */
669 free(wtok);
670 free(tok);
671 composenode->result = result;
672 return;
673 }
674 else
675 {
676 if (composenode->size == 0)
677 {
678 composenode->size = 1;
679 auxnode = malloc(sizeof(osk_composenode));
680 composenode->childs = malloc(sizeof(osk_composenode *));
681 composenode->childs[0] = auxnode;
682 mbstowcs(wtok, tok, 254); /* <<< CRASH */
683 composenode->childs[0]->keysym = wcsdup(wtok);
684 composenode->childs[0]->result = NULL;
685 composenode->childs[0]->size = 0;
686
687 /* printf("size %d, keysym %ls => ", composenode->size, composenode->childs[0]->keysym); */
688
689 gettokens(NULL, delim, pointer, composenode->childs[0], layout);
690 free(wtok);
691 free(tok);
692 return;
693 }
694 else
695 {
696 for (i = 0; i < composenode->size; i++)
697 {
698 mbstowcs(wtok, tok, 255);
699 if (wcscmp(composenode->childs[i]->keysym, wtok) == 0)
700 {
701
702 /* printf("Size %d, keysym %ls =>", composenode->size, composenode->childs[i]->keysym); */
703
704 gettokens(NULL, delim, pointer, composenode->childs[i], layout);
705 free(tok);
706 free(wtok);
707 return;
708 }
709 }
710 }
711
712 composenode->size = composenode->size + 1;
713 composenode->childs = realloc(composenode->childs, composenode->size * sizeof(osk_composenode *));
714
715 mbstowcs(wtok, tok, 255);
716 auxnode = malloc(sizeof(osk_composenode));
717 composenode->childs[composenode->size - 1] = auxnode; //malloc(sizeof(osk_composenode));
718 composenode->childs[composenode->size - 1]->keysym = wtok;
719 composenode->childs[composenode->size - 1]->result = NULL;
720 composenode->childs[composenode->size - 1]->size = 0;
721
722 /* printf("size %d, keysym %ls =>", composenode->size, composenode->childs[composenode->size - 1]->keysym); */
723
724 gettokens(NULL, delim, pointer, composenode->childs[composenode->size - 1], layout);
725 free(tok);
726 return;
727 }
728 }
729
730
731 /* A compose map contains the sequences of keysyms (X keysym mnemonics) needed to generate another keysym.
732 The last in the sequence is the result, the others will be searched in the order they appear.
733 They will be classified in a multiway tree.*/
load_composemap(osk_layout * layout,char * composemap_name)734 static void load_composemap(osk_layout * layout, char *composemap_name)
735 {
736 char *filename;
737 char **pointer;
738 char *line;
739 FILE *fi;
740 char * __attribute__((unused)) tmp_ptr;
741
742 pointer = malloc(sizeof(wchar_t *));
743 filename = malloc(sizeof(char) * 255);
744
745 /* Try full path */
746 fi = fopen(composemap_name, "r");
747 if (fi == NULL)
748 {
749 /* Try with DATA_PREFIX */
750
751 snprintf(filename, 255, "%sosk/%s", DATA_PREFIX, composemap_name);
752 fi = fopen(filename, "r");
753 if (fi == NULL)
754 {
755 fprintf(stderr, "Can't open either %s nor %s\n", composemap_name, filename);
756 layout->keys = NULL;
757 free(filename);
758 return;
759 }
760 }
761
762 free(filename);
763
764 layout->composemap = malloc(sizeof(osk_composenode));
765 layout->composemap[0].keysym = NULL;
766 layout->composemap[0].result = NULL;
767
768 layout->composemap->size = 0;
769 line = malloc(1024 * sizeof(char));
770
771 while (!feof(fi))
772 {
773 tmp_ptr = fgets(line, 1023, fi);
774
775 if (is_blank_or_comment(line))
776 continue;
777
778 gettokens(line, (char *)">< \t", pointer, layout->composemap, layout);
779 }
780
781 fclose(fi);
782 free(line);
783 free(pointer);
784 #ifdef DEBUG_OSK_COMPOSEMAP
785 print_composemap(layout->composemap, NULL);
786 #endif
787 }
788
789 #ifdef DEBUG_OSK_COMPOSEMAP
print_composemap(osk_composenode * composemap,char * sp)790 static void print_composemap(osk_composenode * composemap, char *sp)
791 {
792 int i;
793 char *space;
794
795 space = malloc(sizeof(char) * 255);
796
797 #ifdef DEBUG
798 printf("%ls, ", composemap->keysym);
799 printf("%d ==> ", composemap->size);
800 #endif
801 if (composemap->size == 0)
802 {
803 #ifdef DEBUG
804 printf("result %ls\n", composemap->result);
805 #endif
806 return;
807 }
808 if (sp)
809 {
810 sprintf(space, "%s\t", sp);
811 }
812 else
813 {
814 sprintf(space, " ");
815 }
816 #ifdef DEBUG
817 printf("%s", space);
818 #endif
819
820 for (i = 0; i < composemap->size; i++)
821 {
822 print_composemap(composemap->childs[i], space);
823 // free(space);
824 }
825 /* for (i = 0; i < composemap->size; i++) */
826 /* { */
827 /* printf("aaa %ls, ", composemap->keysym); */
828 /* printf("%d ==> ", composemap->size); */
829 /* printf("%ls, ", composemap->childs[i]->keysym); */
830 /* printf("childs %d ==> ", composemap->childs[i]->size); */
831
832 /* if (composemap->childs[i]->size == 0) */
833 /* printf("result %ls\n", composemap->childs[i]->result); */
834 /* else */
835 /* print_composemap(composemap->childs[i], space); */
836 /* // free(space); */
837 /* } */
838 }
839 #endif
840
841 /* This parses the contents of keysymdef.h from the source of xorg.
842 Therefore, if somebody wants to provide custom keysymdefs, he has to follow its syntax. */
load_keysymdefs(osk_layout * layout,char * keysymdefs_name)843 static void load_keysymdefs(osk_layout * layout, char *keysymdefs_name)
844 {
845 int i;
846 char *filename;
847 char *line;
848 FILE *fi;
849 char * __attribute__((unused)) tmp_ptr;
850
851 filename = malloc(sizeof(char) * 255);
852
853 /* Try full path */
854 fi = fopen(keysymdefs_name, "r");
855 if (fi == NULL)
856 {
857 /* Try with DATA_PREFIX */
858
859 snprintf(filename, 255, "%sosk/%s", DATA_PREFIX, keysymdefs_name);
860 fi = fopen(filename, "r");
861 if (fi == NULL)
862 {
863 fprintf(stderr, "Can't open either %s nor %s\n", keysymdefs_name, filename);
864 layout->keysymdefs = NULL;
865 free(filename);
866 return;
867 }
868 }
869
870 free(filename);
871
872 layout->keysymdefs = malloc(sizeof(keysymdefs));
873 layout->keysymdefs[0].unicode = 0;
874 i = 0;
875 line = malloc(1024 * sizeof(wchar_t));
876
877 while (!feof(fi))
878 {
879 tmp_ptr = fgets(line, 1023, fi);
880 if (strncmp("#define XK_", line, 11) != 0)
881 continue;
882
883 layout->sizeofkeysymdefs = i;
884 layout->keysymdefs = realloc(layout->keysymdefs, sizeof(keysymdefs) * (i + 1));
885
886 /* Some keysyms doesn't correspond to any unicode value, ej. BackSpace */
887 layout->keysymdefs[i].unicode = 0;
888 layout->keysymdefs[i].mnemo = malloc(sizeof(char) * 128);
889 sscanf(line, "#define XK_%s %x /* U+%x",
890 layout->keysymdefs[i].mnemo, &layout->keysymdefs[i].keysym, &layout->keysymdefs[i].unicode);
891 i++;
892 }
893
894 fclose(fi);
895 free(line);
896 }
897
898 /* /\* Return the mnemonic string of a x keysym as defined in the source of xorg in keysymdef.h *\/ */
899 /* static char * keysym2mnemo(int keysym, on_screen_keyboard * keyboard) */
900 /* { */
901 /* unsigned int i; */
902 /* for (i = 0; i < keyboard->layout->sizeofkeysymdefs ;i++) */
903 /* if (keysym == keyboard->layout->keysymdefs[i].keysym) */
904 /* return(keyboard->layout->keysymdefs[i].mnemo); */
905
906 /* /\* For the purpose of onscreen keyboard we don't need the conversion to strings in the form U0000 *\/ */
907 /* return(NULL); */
908 /* } */
909
910 /* Returns the x keysym corresponding to a mnemonic string */
mnemo2keysym(char * mnemo,on_screen_keyboard * keyboard)911 static int mnemo2keysym(char *mnemo, on_screen_keyboard * keyboard)
912 {
913 unsigned int i;
914
915 for (i = 0; i < keyboard->layout->sizeofkeysymdefs; i++)
916 {
917 if (strcmp(mnemo, keyboard->layout->keysymdefs[i].mnemo) == 0)
918 return (keyboard->layout->keysymdefs[i].keysym);
919 }
920 i = 0;
921
922 /* Perhaps the mnemo is in UXXXX format? */
923 if (sscanf(mnemo, "U%x", &i))
924 return (i | 0x01000000);
925
926 /* Or maybe mnemo is already a keysym? */
927 if (sscanf(mnemo, "0x%x", &i))
928 return (i);
929
930 return (0);
931 }
932
933 /* Returns the unicode value of a x keysym if any, otherwise returns 0 */
keysym2unicode(int keysym,on_screen_keyboard * keyboard)934 static int keysym2unicode(int keysym, on_screen_keyboard * keyboard)
935 {
936 unsigned int i;
937
938 /* Credits for the conversion from xkeysyms to unicode values, code taken from the source code of xterm, file keysym2ucs.c.
939 *Author: Markus G. Kuhn <mkuhn@acm.org>, University of Cambridge, April 2001
940 *
941 * Special thanks to Richard Verhoeven <river@win.tue.nl> for preparing
942 * an initial draft of the mapping table.
943 *
944 * This software is in the public domain. Share and enjoy!
945 */
946 /* first check for Latin-1 characters (1:1 mapping) */
947 if ((keysym >= 0x0020 && keysym <= 0x007e) || (keysym >= 0x00a0 && keysym <= 0x00ff))
948 return keysym;
949
950 /* also check for directly encoded 24-bit UCS characters */
951 if ((keysym & 0xff000000) == 0x01000000)
952 return keysym & 0x00ffffff;
953
954
955
956 for (i = 0; i < keyboard->layout->sizeofkeysymdefs; i++)
957 if (keysym == keyboard->layout->keysymdefs[i].keysym)
958 return (keyboard->layout->keysymdefs[i].unicode);
959
960 return (keysym);
961 }
962
963
964 /* Searches in the tree for composing stuff */
get_composed_keysym(on_screen_keyboard * keyboard,osk_composenode * composenode,wchar_t * keysym)965 static void get_composed_keysym(on_screen_keyboard * keyboard, osk_composenode * composenode, wchar_t * keysym)
966 {
967 int i;
968
969 /* If there is not a compose table return the keysym */
970 if (!composenode)
971 {
972 if (keyboard->composed)
973 free(keyboard->composed);
974 keyboard->composed = wcsdup(keysym);
975 keyboard->composed_type = 0;
976 return;
977 }
978
979 /* If there is a compose table, lookup for matches */
980 for (i = 0; i < composenode->size; i++)
981 {
982 /* If matches, set either the result or the next node */
983 if (wcscmp(composenode->childs[i]->keysym, keysym) == 0)
984 {
985 if (composenode->childs[i]->result)
986 {
987 if (keyboard->composed)
988 free(keyboard->composed);
989 keyboard->composed = wcsdup(composenode->childs[i]->result);
990 keyboard->composing = keyboard->layout->composemap;
991 /* The result in the Compose files from xorg is yet in unicode */
992 keyboard->composed_type = 1;
993 return;
994 }
995 else
996 {
997 if (keyboard->composed)
998 free(keyboard->composed);
999 keyboard->composed = NULL;
1000 keyboard->composing = composenode->childs[i];
1001 return;
1002 }
1003 }
1004 }
1005
1006 /* No matches found, if we were in the middle of a sequence, reset the compose stuff,
1007 if we were in the beginning node, set the keysym */
1008
1009 if (keyboard->layout->composemap == composenode)
1010 {
1011 if (keyboard->composed)
1012 free(keyboard->composed);
1013 keyboard->composed = wcsdup(keysym);
1014 keyboard->composed_type = 0;
1015 }
1016 else /* reset */
1017 {
1018 keyboard->composing = keyboard->layout->composemap;
1019 if (keyboard->composed)
1020 free(keyboard->composed);
1021 keyboard->composed = NULL;
1022 keyboard->composed_type = 0;
1023 }
1024 }
1025
1026
is_blank_or_comment(char * line)1027 static int is_blank_or_comment(char *line)
1028 {
1029 int i;
1030
1031 i = 0;
1032
1033 if (strlen(line) == 0)
1034 return 0;
1035 while (line[i] != '\n')
1036 {
1037 if (line[i] == '#')
1038 return 1;
1039 else if (line[i] == ' ' || line[i] == '\t')
1040 i++;
1041 else
1042 return 0;
1043 }
1044 return 1;
1045 }
1046
1047
1048 /* static int isw_blank_or_comment(wchar_t *line) */
1049 /* { */
1050 /* int i; */
1051
1052 /* i = 0; */
1053 /* if (wcslen(line) == 0) */
1054 /* return 0; */
1055 /* while (line[i] != L'\n') */
1056 /* { */
1057 /* if (line[i] == L'#') */
1058 /* return 1; */
1059 /* else if (line[i] == L' ' || line[i] == L'\t') */
1060 /* i++; */
1061 /* else */
1062 /* return 0; */
1063 /* } */
1064 /* return 1; */
1065 /* } */
1066
1067
1068 /* FIXME: Is it safe to supose that if a font is loaded at one size, it will be loaded at any size? */
1069 /* FIXME: starting a layout with one font causes all other layouts be in that font */
keybd_prepare(on_screen_keyboard * keyboard)1070 static void keybd_prepare(on_screen_keyboard * keyboard)
1071 {
1072 char *fontname;
1073 int font_height;
1074
1075 /* Pick a height (e.g., 16pt for small (24x24), 32pt for large (48x48) buttons) */
1076 font_height = ((keyboard->button_up->h * 2) / 3);
1077
1078 fontname = malloc(sizeof(char) * 255);
1079 if (keyboard->osk_fonty == NULL)
1080 {
1081
1082 if (keyboard->layout->fontpath)
1083 {
1084 /* First try if it is an absolute path */
1085 keyboard->osk_fonty = TTF_OpenFont(keyboard->layout->fontpath, font_height);
1086 if (keyboard->osk_fonty == NULL)
1087 {
1088 /* Now trying if it is relative to DATA_PREFIX/fonts/ */
1089 snprintf(fontname, 255, "%s/fonts/%s", DATA_PREFIX, keyboard->layout->fontpath);
1090
1091 keyboard->osk_fonty = TTF_OpenFont(fontname, font_height);
1092 if (keyboard->osk_fonty == NULL)
1093 {
1094 /* Perhaps it is relative to DATA_PREFIX only? */
1095 snprintf(fontname, 255, "%s/%s", DATA_PREFIX, keyboard->layout->fontpath);
1096 keyboard->osk_fonty = TTF_OpenFont(fontname, font_height);
1097 if (keyboard->osk_fonty == NULL)
1098 {
1099 /* Or to DATA_PREFIX/fonts/locale/ ? */
1100 snprintf(fontname, 255, "%s/fonts/locale/%s", DATA_PREFIX, keyboard->layout->fontpath);
1101 keyboard->osk_fonty = TTF_OpenFont(fontname, font_height);
1102 }
1103 }
1104 }
1105 }
1106
1107 if (keyboard->osk_fonty == NULL)
1108 {
1109 /* Going with the default */
1110 sprintf(fontname, "%s/fonts/FreeSansBold.ttf", DATA_PREFIX);
1111 keyboard->osk_fonty = TTF_OpenFont(fontname, font_height);
1112 }
1113
1114 if (keyboard->osk_fonty == NULL)
1115 {
1116 fprintf(stderr, "\nError: Can't open the font!\n"
1117 "The Simple DirectMedia Layer error that occurred was:\n" "%s\n\n", SDL_GetError());
1118 free(fontname);
1119 exit(1);
1120 }
1121
1122 free(fontname);
1123 }
1124 }
1125
1126
apply_surface(int x,int y,SDL_Surface * source,SDL_Surface * destination,SDL_Rect * clip)1127 static void apply_surface(int x, int y, SDL_Surface * source, SDL_Surface * destination, SDL_Rect * clip)
1128 {
1129 SDL_Rect offset;
1130
1131 offset.x = x;
1132 offset.y = y;
1133
1134 SDL_BlitSurface(source, clip, destination, &offset);
1135 }
1136
1137
1138 /* /\* NOTE: This is a duplicate of wcstou16 in tuxpaint.c */
1139
1140 /* This conversion is required on platforms where Uint16 doesn't match wchar_t. */
1141 /* On Windows, wchar_t is 16-bit, elsewhere it is 32-bit. */
1142 /* Mismatch caused by the use of Uint16 for unicode characters by SDL, SDL_ttf. */
1143 /* I guess wchar_t is really only suitable for internal use ... *\/ */
1144 /* static Uint16 *wcstou16(const wchar_t * str) */
1145 /* { */
1146 /* unsigned int i, len = wcslen(str); */
1147 /* Uint16 *res = malloc((len + 1) * sizeof(Uint16)); */
1148
1149 /* for (i = 0; i < len + 1; ++i) */
1150 /* { */
1151 /* /\* This is a bodge, but it seems unlikely that a case-conversion */
1152 /* will cause a change from one utf16 character into two.... */
1153 /* (though at least UTF-8 suffers from this problem) *\/ */
1154
1155 /* // FIXME: mangles non-BMP characters rather than using UTF-16 surrogates! */
1156 /* res[i] = (Uint16) str[i]; */
1157 /* } */
1158
1159 /* return res; */
1160 /* } */
1161
1162 /* Stretches a button from the middle, keeping the extrems intact */
stretch_surface(SDL_Surface * orig,int width)1163 static SDL_Surface *stretch_surface(SDL_Surface * orig, int width)
1164 {
1165 int i;
1166 SDL_Surface *dest;
1167 SDL_Rect rect;
1168 SDL_Rect orig_rect;
1169
1170 orig_rect.x = orig->w / 2;
1171 orig_rect.y = 0;
1172 orig_rect.w = 1;
1173 orig_rect.h = orig->h;
1174
1175 dest = SDL_CreateRGBSurface(orig->flags,
1176 width,
1177 orig->h,
1178 orig->format->BitsPerPixel,
1179 orig->format->Rmask, orig->format->Gmask, orig->format->Bmask, 0);
1180
1181 SDL_BlitSurface(orig, NULL, dest, NULL);
1182 rect.y = 0;
1183
1184 if (width > orig->w)
1185 {
1186 rect.x = width - orig->w;
1187 rect.h = orig->h;
1188 rect.w = orig->w;
1189 SDL_BlitSurface(orig, NULL, dest, &rect);
1190
1191 rect.w = 1;
1192 for (i = orig->w / 2; i < width - orig->w / 2; i++)
1193 {
1194 rect.x = i;
1195 SDL_BlitSurface(orig, &orig_rect, dest, &rect);
1196 }
1197 }
1198 else if (width < orig->w)
1199 {
1200 rect.y = 0;
1201 rect.w = 1;
1202 rect.h = dest->h;
1203
1204 orig_rect.y = 0;
1205 orig_rect.w = 1;
1206 orig_rect.h = orig->h;
1207
1208 for (i = 0; i <= width / 2; i++)
1209 {
1210 rect.x = dest->w - i;
1211 orig_rect.x = orig->w - i;
1212 SDL_BlitSurface(orig, &orig_rect, dest, &rect);
1213 }
1214 }
1215
1216 return dest;
1217 }
1218
1219 /* Draws the keyboard surface */
draw_keyboard(on_screen_keyboard * keyboard)1220 static void draw_keyboard(on_screen_keyboard * keyboard)
1221 {
1222 int i, j;
1223 int key_height, accumulated_width, accumulated_height;
1224 float key_width;
1225
1226 key_width = keyboard->button_up->w;
1227 key_height = keyboard->button_up->h;
1228
1229 accumulated_height = 0;
1230
1231 for (j = 0; j < keyboard->layout->height; j++)
1232 {
1233 accumulated_width = 0;
1234 for (i = 0; i < keyboard->layout->width; i++)
1235 {
1236 if (keyboard->layout->keys[j][i].width)
1237 {
1238
1239 keyboard->layout->keys[j][i].row = j;
1240 keyboard->layout->keys[j][i].x = accumulated_width;
1241 keyboard->layout->keys[j][i].y = accumulated_height;
1242
1243 draw_key(keyboard->layout->keys[j][i], keyboard, 0);
1244 }
1245 accumulated_width += (keyboard->layout->keys[j][i].width * key_width);
1246 }
1247 accumulated_height += key_height;
1248 }
1249
1250 /* draw_key(keyboard->keymodifiers.shift, keyboard, 0); */
1251 /* draw_key(keyboard->keymodifiers.altgr, keyboard, 0); */
1252 /* draw_key(keyboard->keymodifiers.compose, keyboard, 0); */
1253 /* draw_key(keyboard->keymodifiers.dead, keyboard, 0); */
1254 }
1255
draw_key(osk_key key,on_screen_keyboard * keyboard,int hot)1256 static void draw_key(osk_key key, on_screen_keyboard * keyboard, int hot)
1257 {
1258 char *text;
1259 SDL_Surface *skey;
1260
1261 if (!key.width)
1262 return;
1263
1264 text = malloc(sizeof(char) * 255);
1265
1266 snprintf(text, 6, "%s", key.plain_label);
1267
1268 if (strncmp("NULL", text, 4) != 0 && key.keycode != 0)
1269 {
1270 if (hot)
1271 skey = stretch_surface(keyboard->button_down, key.width * keyboard->button_down->w);
1272
1273 else if (key.stick)
1274 skey = stretch_surface(keyboard->button_hold, key.width * keyboard->button_hold->w);
1275
1276 else
1277 {
1278 if (key.keycode == 1 || key.keycode == 2)
1279 {
1280 if (keyboard->disable_change)
1281 skey = stretch_surface(keyboard->button_off, key.width * keyboard->button_off->w);
1282 else
1283 skey = stretch_surface(keyboard->button_nav, key.width * keyboard->button_nav->w);
1284 }
1285 else
1286 skey = stretch_surface(keyboard->button_up, key.width * keyboard->button_up->w);
1287 }
1288 }
1289 else
1290 skey = stretch_surface(keyboard->button_off, key.width * keyboard->button_off->w);
1291
1292 apply_surface(key.x, key.y, skey, keyboard->surface, NULL);
1293
1294 SDL_FreeSurface(skey);
1295 free(text);
1296 label_key(key, keyboard);
1297 }
1298
1299
1300 /* FIXME: TODO draw top and bottom_right (altgr) labels */
label_key(osk_key key,on_screen_keyboard * keyboard)1301 static void label_key(osk_key key, on_screen_keyboard * keyboard)
1302 {
1303 SDL_Surface *messager;
1304 int modstate;
1305 char *text;
1306
1307 /* To remove a warning... */
1308 text = NULL;
1309
1310 modstate = keyboard->modifiers;
1311
1312 /* FIXME There MUST be a simpler way to do this. Pere 2011/8/3 */
1313 /* First the plain ones */
1314 if (modstate == KMOD_NONE || (modstate == (KMOD_NONE | KMOD_LALT)))
1315 text = strdup(key.plain_label);
1316
1317 else if (modstate == KMOD_SHIFT)
1318 {
1319 text = strdup(key.top_label);
1320 }
1321
1322 else if (modstate == KMOD_RALT)
1323 {
1324 text = strdup(key.altgr_label);
1325 }
1326
1327 else if (modstate == KMOD_CAPS)
1328 {
1329 if (key.shiftcaps == 1)
1330 text = strdup(key.top_label);
1331
1332 else
1333 text = strdup(key.plain_label);
1334 }
1335
1336 /* Now the combined ones */
1337 else if (modstate & KMOD_RALT && modstate & KMOD_SHIFT)
1338 {
1339 if (modstate & KMOD_CAPS)
1340 {
1341 if (key.shiftcaps)
1342 text = strdup(key.altgr_label);
1343 else
1344 text = strdup(key.shift_altgr_label);
1345 }
1346 else
1347 {
1348 text = strdup(key.shift_altgr_label);
1349 }
1350 }
1351
1352 else if (modstate & KMOD_RALT && modstate & KMOD_CAPS && !(modstate & KMOD_SHIFT))
1353 {
1354 if (key.shiftcaps)
1355 text = strdup(key.shift_altgr_label);
1356 else
1357 text = strdup(key.altgr_label);
1358 }
1359
1360 else if (modstate & KMOD_SHIFT && modstate & KMOD_CAPS)
1361 {
1362 if (key.shiftcaps == 1)
1363 text = strdup(key.plain_label);
1364 else
1365 text = strdup(key.top_label);
1366 }
1367
1368 if (strncmp("DELETE", text, 6) == 0)
1369 {
1370 apply_surface(key.x, key.y, keyboard->oskdel, keyboard->surface, NULL);
1371 }
1372
1373 else if (strncmp("TAB", text, 3) == 0)
1374 {
1375 apply_surface(key.x, key.y, keyboard->osktab, keyboard->surface, NULL);
1376 }
1377
1378 else if (strncmp("ENTER", text, 5) == 0)
1379 {
1380 apply_surface(key.x, key.y, keyboard->oskenter, keyboard->surface, NULL);
1381 }
1382
1383 else if (strncmp("CAPSLOCK", text, 8) == 0)
1384 {
1385 apply_surface(key.x, key.y, keyboard->oskcapslock, keyboard->surface, NULL);
1386 }
1387
1388 else if (strncmp("SHIFT", text, 5) == 0)
1389 {
1390 apply_surface(key.x, key.y, keyboard->oskshift, keyboard->surface, NULL);
1391 }
1392
1393 else if (strncmp("SPACE", text, 5) != 0 && strncmp("NULL", text, 4) != 0)
1394 {
1395 messager = TTF_RenderUTF8_Blended(keyboard->osk_fonty, text, keyboard->layout->fgcolor);
1396
1397 apply_surface(key.x + 5, key.y, messager, keyboard->surface, NULL);
1398 SDL_FreeSurface(messager);
1399 }
1400 free(text);
1401 }
1402
1403 /* Searches the key corresponding to coordinates */
find_key(on_screen_keyboard * keyboard,int x,int y)1404 static osk_key *find_key(on_screen_keyboard * keyboard, int x, int y)
1405 {
1406 int i, j;
1407 osk_key *key;
1408
1409 key = NULL;
1410 for (j = 0; j < keyboard->layout->height; j++)
1411 {
1412 if (keyboard->layout->keys[j][0].y < y && keyboard->layout->keys[j][0].y + keyboard->button_up->h > y)
1413 for (i = 0; i < keyboard->layout->width; i++)
1414 if (keyboard->layout->keys[j][i].x < x &&
1415 keyboard->layout->keys[j][i].x + keyboard->layout->keys[j][i].width * keyboard->button_up->w > x)
1416 {
1417 key = &keyboard->layout->keys[j][i];
1418 return key;
1419 }
1420 }
1421
1422 return NULL;
1423 }
1424
1425 /* Copies orig to dest or sets dest to defaults if orig is NULL.
1426 if firstime is setted, don't frees the strings as there aren't. */
set_key(osk_key * orig,osk_key * dest,int firsttime)1427 static void set_key(osk_key * orig, osk_key * dest, int firsttime)
1428 {
1429 if (orig == NULL)
1430 {
1431 dest->keycode = 0;
1432 dest->row = 0;
1433 dest->x = 0;
1434 dest->y = 0;
1435 dest->width = 0;
1436 if (!firsttime && dest->plain_label != NULL)
1437 free(dest->plain_label);
1438 dest->plain_label = NULL;
1439 if (!firsttime && dest->top_label != NULL)
1440 free(dest->top_label);
1441 dest->top_label = NULL;
1442 if (!firsttime && dest->altgr_label != NULL)
1443 free(dest->altgr_label);
1444 dest->altgr_label = NULL;
1445 dest->shiftcaps = 0;
1446 }
1447 else
1448 {
1449 dest->keycode = orig->keycode;
1450 dest->row = orig->row;
1451 dest->x = orig->x;
1452 dest->y = orig->y;
1453 dest->width = orig->width;
1454
1455 if (dest->plain_label != NULL)
1456 free(dest->plain_label);
1457 dest->plain_label = strdup(orig->plain_label);
1458
1459 if (dest->top_label != NULL)
1460 free(dest->top_label);
1461 dest->top_label = strdup(orig->top_label);
1462
1463 if (dest->altgr_label != NULL)
1464 free(dest->altgr_label);
1465 dest->altgr_label = strdup(orig->altgr_label);
1466
1467 dest->shiftcaps = orig->shiftcaps;
1468 }
1469 }
1470
find_keysym(osk_key key,on_screen_keyboard * keyboard)1471 static char *find_keysym(osk_key key, on_screen_keyboard * keyboard)
1472 {
1473 int keycode;
1474 char *keysym;
1475 osk_keymap keysyms;
1476 SDLMod modstate;
1477
1478 keycode = key.keycode;
1479 keysyms = keyboard->layout->keymap[keycode];
1480 keysym = NULL;
1481
1482 modstate = keyboard->modifiers;
1483
1484 /* FIXME There MUST be a simpler way to do this. Pere 2011/8/3 */
1485 /* First the plain ones */
1486 if (modstate == KMOD_NONE || (modstate == (KMOD_NONE | KMOD_LALT)))
1487 keysym = keysyms.plain;
1488
1489 else if (modstate == KMOD_SHIFT)
1490 {
1491 keysym = keysyms.caps;
1492 }
1493
1494 else if (modstate == KMOD_RALT)
1495 {
1496 keysym = keysyms.altgr;
1497 }
1498
1499 else if (modstate == KMOD_CAPS)
1500 {
1501 if (key.shiftcaps == 1)
1502 keysym = keysyms.caps;
1503 else
1504 keysym = keysyms.plain;
1505 }
1506
1507 /* Now the combined ones */
1508 else if (modstate & KMOD_RALT && modstate & KMOD_SHIFT)
1509 {
1510 if (modstate & KMOD_CAPS)
1511 {
1512 if (key.shiftcaps)
1513 keysym = keysyms.altgr;
1514 else
1515 keysym = keysyms.shiftaltgr;
1516 }
1517 else
1518 {
1519 keysym = keysyms.shiftaltgr;
1520 }
1521 }
1522
1523 else if (modstate & KMOD_RALT && modstate & KMOD_CAPS && !(modstate & KMOD_SHIFT))
1524 {
1525 if (key.shiftcaps)
1526 keysym = keysyms.shiftaltgr;
1527 else
1528 keysym = keysyms.altgr;
1529 }
1530
1531 else if (modstate & KMOD_SHIFT && modstate & KMOD_CAPS)
1532 {
1533 if (key.shiftcaps == 1)
1534 keysym = keysyms.plain;
1535 else
1536 keysym = keysyms.caps;
1537 }
1538
1539 return (keysym);
1540 }
1541
1542 /* We lose the SDL ModState by leaving and entering the tuxpaint window, so using a custom state */
handle_keymods(char * keysym,osk_key * key,on_screen_keyboard * keyboard)1543 static int handle_keymods(char *keysym, osk_key * key, on_screen_keyboard * keyboard)
1544 {
1545 SDLMod mod;
1546 SDL_Event ev;
1547
1548 mod = keyboard->modifiers;
1549
1550 if (strncmp("Shift", keysym, 5) == 0)
1551 {
1552 if (mod & KMOD_SHIFT)
1553 {
1554 keyboard->modifiers = mod & 0xFFF0;
1555 key->stick = 0;
1556 keyboard->kmdf.shift->stick = 0;
1557 }
1558 else
1559 {
1560 keyboard->modifiers = mod | KMOD_SHIFT;
1561 key->stick = 1;
1562 keyboard->kmdf.shift = key;
1563 }
1564 return 1;
1565 }
1566 else if (strncmp("Alt_L", keysym, 5) == 0)
1567 {
1568 ev.key.keysym.sym = SDLK_LALT;
1569 ev.key.keysym.unicode = 0; // FIXME is 0 the right value here?
1570 ev.type = SDL_KEYDOWN;
1571 SDL_PushEvent(&ev);
1572 ev.type = SDL_KEYUP;
1573 SDL_PushEvent(&ev);
1574
1575 return 1;
1576 }
1577
1578 /* Seems ISO_Level3_Shift and ISO_Next_Group are used too for right Alt */
1579 else if (strncmp("ISO_Level3_Shift", keysym, 16) == 0 ||
1580 strncmp("ISO_Next_Group", keysym, 14) == 0 || strncmp("ALT_R", keysym, 5) == 0)
1581 {
1582 if (mod & KMOD_RALT)
1583 {
1584 keyboard->modifiers = mod & 0xF0FF;
1585 keyboard->kmdf.altgr->stick = 0;
1586 }
1587 else
1588 {
1589 keyboard->modifiers = mod | KMOD_RALT;
1590 key->stick = 1;
1591 keyboard->kmdf.altgr = key;
1592
1593 return 1;
1594 }
1595 return 0;
1596 }
1597
1598 else if (strncmp("Caps_Lock", keysym, 9) == 0)
1599 {
1600 if (mod & KMOD_CAPS)
1601 {
1602 keyboard->modifiers = mod & 0x0FFF;
1603 key->stick = 0;
1604 }
1605 else
1606 {
1607 keyboard->modifiers = mod | KMOD_CAPS;
1608 key->stick = 1;
1609 }
1610
1611
1612 return 1;
1613 }
1614
1615 if (mod & KMOD_CAPS)
1616 {
1617 keyboard->modifiers = KMOD_CAPS;
1618 }
1619 else
1620 keyboard->modifiers = KMOD_NONE;
1621
1622 if (keyboard->kmdf.shift)
1623 keyboard->kmdf.shift->stick = 0;
1624 if (keyboard->kmdf.altgr)
1625 keyboard->kmdf.altgr->stick = 0;
1626
1627 return 0;
1628 }
1629
1630 /* set_dead_sticks and clear_dead_sticks deals with the persistence of
1631 the keys that are still affecting other key presses. */
set_dead_sticks(osk_key * key,on_screen_keyboard * keyboard)1632 static void set_dead_sticks(osk_key * key, on_screen_keyboard * keyboard)
1633 {
1634 key->stick = 1;
1635 if (!keyboard->kmdf.dead)
1636 keyboard->kmdf.dead = key;
1637 else if (!keyboard->kmdf.dead2)
1638 keyboard->kmdf.dead2 = key;
1639 else if (!keyboard->kmdf.dead3)
1640 keyboard->kmdf.dead3 = key;
1641 else if (!keyboard->kmdf.dead4)
1642 keyboard->kmdf.dead4 = key;
1643 }
1644
clear_dead_sticks(on_screen_keyboard * keyboard)1645 static void clear_dead_sticks(on_screen_keyboard * keyboard)
1646 {
1647 if (keyboard->kmdf.dead)
1648 {
1649 keyboard->kmdf.dead->stick = 0;
1650 keyboard->kmdf.dead = NULL;
1651 }
1652 if (keyboard->kmdf.dead2)
1653 {
1654 keyboard->kmdf.dead2->stick = 0;
1655 keyboard->kmdf.dead2 = NULL;
1656 }
1657 if (keyboard->kmdf.dead3)
1658 {
1659 keyboard->kmdf.dead3->stick = 0;
1660 keyboard->kmdf.dead3 = NULL;
1661 }
1662 if (keyboard->kmdf.dead4)
1663 {
1664 keyboard->kmdf.dead4->stick = 0;
1665 keyboard->kmdf.dead4 = NULL;
1666 }
1667 }
1668
osk_clicked(on_screen_keyboard * keyboard,int x,int y)1669 struct osk_keyboard *osk_clicked(on_screen_keyboard * keyboard, int x, int y)
1670 {
1671 int i;
1672 osk_key *key;
1673 SDL_Event event;
1674 char *keysym, *mnemo;
1675 char *name, *aux_name, *aux_list, *aux_list_ptr;
1676 wchar_t *wkeysym;
1677 wchar_t *ks;
1678 on_screen_keyboard *new_keyboard;
1679
1680 #ifdef DEBUG
1681 printf("list: %s\n", keyboard->keyboard_list);
1682 #endif
1683
1684 event.key.keysym.mod = KMOD_NONE;
1685 event.key.keysym.sym = 0;
1686 event.key.keysym.unicode = 0;
1687
1688 key = find_key(keyboard, x, y);
1689
1690 if (key)
1691 {
1692 /* First the reserved keycodes */
1693 /* Select next or previous keyboard */
1694 if (key->keycode == 1 || key->keycode == 2)
1695 {
1696 if (keyboard->disable_change)
1697 {
1698 // free(key);
1699 return (keyboard);
1700 }
1701
1702 aux_list = strdup(keyboard->keyboard_list);
1703 aux_list_ptr = aux_list;
1704
1705 #ifdef DEBUG
1706 printf("auxlist: %s\n", aux_list);
1707 printf("kn %s\n", keyboard->name);
1708 #endif
1709
1710 if (key->keycode == 1)
1711 {
1712 for (i = 0;; i++, aux_list = NULL)
1713 {
1714 name = strtok(aux_list, " \n\r\t");
1715
1716 if (i == 0)
1717 aux_name = name;
1718
1719 if (strcmp(name, keyboard->name) == 0)
1720 {
1721 name = strtok(NULL, " \n\r\t");
1722 if (name == NULL)
1723 name = aux_name;
1724 break;
1725 }
1726 }
1727 }
1728 else
1729 {
1730 aux_name = NULL;
1731 for (i = 0;; i++, aux_list = NULL)
1732 {
1733 name = strtok(aux_list, " \n\r\t");
1734
1735 if (name == NULL)
1736 {
1737 name = aux_name;
1738 break;
1739 }
1740
1741 if (strstr(name, keyboard->name))
1742 {
1743 name = aux_name;
1744 if (name != NULL)
1745 break;
1746 }
1747
1748 aux_name = name;
1749 }
1750 }
1751
1752
1753 new_keyboard =
1754 osk_create(name, keyboard->canvas_ptr,
1755 keyboard->LG_button_up, keyboard->LG_button_down,
1756 keyboard->LG_button_off, keyboard->LG_button_nav,
1757 keyboard->LG_button_hold,
1758 keyboard->LG_oskdel, keyboard->LG_osktab,
1759 keyboard->LG_oskenter, keyboard->LG_oskcapslock,
1760 keyboard->LG_oskshift,
1761 keyboard->SM_button_up, keyboard->SM_button_down,
1762 keyboard->SM_button_off, keyboard->SM_button_nav,
1763 keyboard->SM_button_hold,
1764 keyboard->SM_oskdel, keyboard->SM_osktab,
1765 keyboard->SM_oskenter, keyboard->SM_oskcapslock,
1766 keyboard->SM_oskshift,
1767 keyboard->disable_change);
1768
1769 free(aux_list_ptr);
1770
1771 if (new_keyboard == NULL)
1772 {
1773 // free(key);
1774 return (keyboard); /* Don't break here, at least the old keyboard should work */
1775 }
1776 else
1777 {
1778 free(new_keyboard->keyboard_list);
1779 new_keyboard->keyboard_list = strdup(keyboard->keyboard_list);
1780 // free(key);
1781 osk_free(keyboard);
1782 return (new_keyboard);
1783 }
1784 }
1785
1786
1787 keysym = find_keysym(*key, keyboard);
1788 if (!keysym)
1789 {
1790 return (keyboard);
1791 }
1792
1793 draw_key(*key, keyboard, 1);
1794
1795 if (handle_keymods(keysym, key, keyboard))
1796 {
1797 return (keyboard); /* no more processing is needed */
1798 }
1799
1800 wkeysym = malloc(sizeof(wchar_t) * (strlen(keysym) + 1));
1801
1802 mbsrtowcs(wkeysym, (const char **)&keysym, strlen(keysym) + 1, NULL);
1803
1804 #ifdef DEBUG
1805 printf("wkeysym %ls %i\n\n", wkeysym, (int)wcslen(wkeysym));
1806 #endif
1807
1808
1809 get_composed_keysym(keyboard, keyboard->composing, wkeysym);
1810
1811 if (keyboard->composed)
1812 {
1813 keyboard->last_key_pressed = key;
1814 set_key(NULL, &keyboard->keymodifiers.compose, 0);
1815 ks = keyboard->composed;
1816
1817 #ifdef DEBUG
1818 printf("keysym found %ls\n", ks);
1819 #endif
1820
1821 mnemo = malloc(sizeof(char) * 32);
1822 snprintf(mnemo, 31, "%ls", ks);
1823
1824 if (wcsncmp(L"Return", ks, 6) == 0)
1825 {
1826 event.key.keysym.sym = SDLK_RETURN;
1827 event.key.keysym.unicode = '\r';
1828 }
1829 else if (wcsncmp(L"Tab", ks, 3) == 0 || wcsncmp(L"ISO_Left_Tab", ks, 12) == 0)
1830 {
1831 event.key.keysym.sym = SDLK_TAB;
1832 event.key.keysym.unicode = '\t';
1833 }
1834 else if (wcsncmp(L"BackSpace", ks, 9) == 0)
1835 {
1836 event.key.keysym.sym = SDLK_BACKSPACE;
1837 event.key.keysym.unicode = '\b';
1838 }
1839 else if (wcsncmp(L"NoSymbol", ks, 8) == 0)
1840 return (keyboard);
1841
1842 else if (keyboard->composed_type == 1)
1843 event.key.keysym.unicode = *keyboard->composed;
1844 else
1845 event.key.keysym.unicode = keysym2unicode(mnemo2keysym(mnemo, keyboard), keyboard);
1846
1847 clear_dead_sticks(keyboard);
1848 event.type = SDL_KEYDOWN;
1849 SDL_PushEvent(&event);
1850 free(mnemo);
1851 }
1852 else
1853 {
1854 if (keyboard->composing == keyboard->layout->composemap)
1855 {
1856 #ifdef DEBUG
1857 printf("compose sequence resetted\n");
1858 #endif
1859 set_key(NULL, &keyboard->keymodifiers.compose, 0);
1860 keyboard->last_key_pressed = key;
1861 clear_dead_sticks(keyboard);
1862 }
1863 else
1864 {
1865 set_key(key, &keyboard->keymodifiers.compose, 0);
1866 #ifdef DEBUG
1867 printf("still composing\n");
1868 #endif
1869 set_dead_sticks(key, keyboard);
1870 /* Fixme: Would be nice if we can highlight next available-to-compose keys, but how? */
1871 }
1872 }
1873 free(wkeysym);
1874 }
1875
1876 return (keyboard);
1877 }
1878
osk_released(on_screen_keyboard * keyboard)1879 void osk_released(on_screen_keyboard * keyboard)
1880 {
1881 osk_key *key;
1882
1883 key = keyboard->last_key_pressed;
1884 if (key)
1885 {
1886 draw_key(*key, keyboard, 0);
1887 // free(key);
1888 }
1889 keyboard->last_key_pressed = NULL;
1890 draw_keyboard(keyboard);
1891 }
1892
1893
free_keymap(osk_keymap * keymap)1894 static void free_keymap(osk_keymap * keymap)
1895 {
1896 int i;
1897
1898 for (i = 0; i < 256; i++)
1899 {
1900 if (keymap[i].plain)
1901 free(keymap[i].plain);
1902 if (keymap[i].caps)
1903 free(keymap[i].caps);
1904 if (keymap[i].altgr)
1905 free(keymap[i].altgr);
1906 if (keymap[i].shiftaltgr)
1907 free(keymap[i].shiftaltgr);
1908 }
1909 free(keymap);
1910 }
1911
free_composemap(osk_composenode * composenode)1912 static void free_composemap(osk_composenode * composenode)
1913 {
1914 int i;
1915
1916 for (i = 0; i < composenode->size; i++)
1917 {
1918 free_composemap(composenode->childs[i]);
1919 free(composenode->childs[i]);
1920 }
1921 if (composenode->result)
1922 free(composenode->result);
1923 else
1924 free(composenode->childs);
1925
1926 if (composenode->keysym)
1927 free(composenode->keysym);
1928 }
1929
free_keysymdefs(keysymdefs * ksd,int size)1930 static void free_keysymdefs(keysymdefs * ksd, int size)
1931 {
1932 int i;
1933
1934 for (i = 0; i <= size; i++)
1935 free(ksd[i].mnemo);
1936 }
1937
free_keys(osk_layout * layout)1938 static void free_keys(osk_layout * layout)
1939 {
1940 int i, j;
1941
1942 for (j = 0; j < layout->height; j++)
1943 {
1944 for (i = 0; i < layout->width; i++)
1945 {
1946 if (layout->keys[j][i].plain_label)
1947 free(layout->keys[j][i].plain_label);
1948 if (layout->keys[j][i].top_label)
1949 free(layout->keys[j][i].top_label);
1950 if (layout->keys[j][i].altgr_label)
1951 free(layout->keys[j][i].altgr_label);
1952 if (layout->keys[j][i].shift_altgr_label)
1953 free(layout->keys[j][i].shift_altgr_label);
1954
1955 }
1956 free(layout->keys[j]);
1957 }
1958 free(layout->keys);
1959 }
1960
free_layout(osk_layout * layout)1961 static void free_layout(osk_layout * layout)
1962 {
1963 if (layout->name != NULL)
1964 free(layout->name);
1965 // free(layout->rows);
1966 free(layout->fontpath);
1967 free_keys(layout);
1968 free_keymap(layout->keymap);
1969 free_composemap(layout->composemap);
1970 free(layout->composemap);
1971
1972 free_keysymdefs(layout->keysymdefs, layout->sizeofkeysymdefs);
1973 free(layout->keysymdefs);
1974 free(layout);
1975 }
1976
osk_free(on_screen_keyboard * keyboard)1977 void osk_free(on_screen_keyboard * keyboard)
1978 {
1979 free(keyboard->name);
1980 free_layout(keyboard->layout);
1981 if (keyboard->composed)
1982 free(keyboard->composed);
1983 if (keyboard->last_key_pressed)
1984 free(keyboard->last_key_pressed);
1985 if (keyboard->keyboard_list)
1986 free(keyboard->keyboard_list);
1987 SDL_FreeSurface(keyboard->surface);
1988 set_key(NULL, &keyboard->keymodifiers.shift, 0);
1989 set_key(NULL, &keyboard->keymodifiers.altgr, 0);
1990 set_key(NULL, &keyboard->keymodifiers.compose, 0);
1991 set_key(NULL, &keyboard->keymodifiers.dead, 0);
1992 if (keyboard->osk_fonty != NULL)
1993 TTF_CloseFont(keyboard->osk_fonty);
1994
1995 free(keyboard);
1996 }
1997
1998
1999
2000 /* static void on_screen_keyboardd(void ) */
2001 /* { */
2002 /* int i; */
2003 /* if (key_board != NULL) */
2004 /* SDL_FreeSurface(key_board); */
2005
2006 /* key_board = SDL_CreateRGBSurface(canvas->flags, */
2007 /* key_width * 19, */
2008 /* key_height * 3, */
2009 /* canvas->format->BitsPerPixel, */
2010 /* canvas->format->Rmask, */
2011 /* canvas->format->Gmask, */
2012 /* canvas->format->Bmask, 0); */
2013 /* key_board_color_r = 255; */
2014 /* key_board_color_g = 255; */
2015 /* key_board_color_b = 255; */
2016
2017 /* SDL_FillRect(key_board, NULL, SDL_MapRGB(key_board->format, 255, 255, 255)); */
2018 /* if (keybd_position == 0) */
2019 /* { */
2020 /* initial_y = 400; */
2021 /* } */
2022 /* else */
2023 /* { */
2024 /* initial_y = 5; */
2025 /* } */
2026 /* apply_surface( initial_x, initial_y, key_board, screen, NULL); */
2027
2028 /* keybd_prepare(); */
2029
2030 /* for (i = 1; i <= 15 ; i++) */
2031 /* button (i, initial_x + (key_width)*(i-1), initial_y); */
2032
2033 /* for (i = 1; i <= 19; i++) */
2034 /* button (i+15, initial_x + (key_width)*(i-1), initial_y + key_height); */
2035
2036 /* for (i = 1; i <= 19; i++) */
2037 /* button (i+34, initial_x + (key_width)*(i-1), initial_y + 2*key_height); */
2038
2039 /* drawkeybd(); */
2040
2041 /* keybd_finish(); */
2042
2043 /* SDL_UpdateRect(screen, 0, 0, 640, 480); */
2044
2045 /* /\* SDL_Delay(10); *\/ /\* FIXME: This should not be necessary! -bjk 2011.04.21 *\/ */
2046
2047 /* keybd_flag = 1; */
2048 /* } */
2049
2050
2051
2052
2053
2054
2055
2056 /* // Check whether current mouse position is within a rectangle */
2057 /* int regionhit(int x, int y, int w, int h) */
2058 /* { */
2059 /* if (uistate.mousex < x || */
2060 /* uistate.mousey < y || */
2061 /* uistate.mousex >= x + w || */
2062 /* uistate.mousey >= y + h) */
2063 /* return 0; */
2064 /* return 1; */
2065 /* } */
2066
2067
2068
2069
2070 /* void button(int id, int x, int y) */
2071 /* { */
2072 /* SDL_Rect dest,desti; */
2073 /* SDL_Surface *tmp_imgup; */
2074 /* SDL_Event event; */
2075 /* dest.x = x; */
2076 /* dest.y = y; */
2077
2078 /* // Check whether the button should be hot */
2079 /* if (regionhit(x, y, 24, 24)) */
2080 /* { */
2081 /* uistate.hotitem = id; */
2082
2083 /* if (uistate.activeitem == 0 && uistate.mousedown) */
2084 /* { */
2085 /* uistate.activeitem = id; */
2086 /* activeflag = 1; */
2087 /* } */
2088 /* } */
2089
2090 /* // Render button */
2091 /* SDL_BlitSurface(img_btnsm_up, NULL, screen, &dest); */
2092 /* if (caps_flag % 2 != 0) */
2093 /* { */
2094 /* desti.x = initial_x; */
2095 /* desti.y = initial_y + key_height; */
2096 /* SDL_BlitSurface(img_btnsm_down, NULL, screen, &desti); */
2097 /* } */
2098 /* if (uistate.hotitem == id) */
2099 /* { */
2100 /* if (uistate.activeitem == id) */
2101 /* { */
2102 /* // Button is both 'hot' and 'active' */
2103 /* if (activeflag == 1) */
2104 /* { */
2105 /* ide = id; */
2106 /* gen_key_flag = 1; */
2107 /* activeflag = 0; */
2108 /* uistate.activeitem = 0; */
2109 /* } */
2110 /* SDL_BlitSurface(img_btnsm_down, NULL, screen, &dest); */
2111 /* } */
2112 /* else */
2113 /* { */
2114 /* // Button is merely 'hot' */
2115 /* SDL_BlitSurface(img_btnsm_down, NULL, screen, &dest); */
2116 /* } */
2117 /* } */
2118 /* else */
2119 /* { */
2120 /* // button is not hot, but it may be active */
2121 /* SDL_BlitSurface(img_btnsm_up, NULL, screen, &dest); */
2122 /* } */
2123
2124 /* if (gen_key_flag == 1) */
2125 /* { */
2126 /* int i,j; */
2127 /* gen_key_flag = 0; */
2128 /* enter_flag = 0; */
2129 /* SDL_EnableUNICODE(1); */
2130 /* // printf("\n entered here %d th time \n", k); */
2131 /* // k++; */
2132 /* if (ide == 1) */
2133 /* { */
2134 /* event.key.keysym.sym = SDLK_ESCAPE; */
2135 /* event.key.keysym.mod = KMOD_NONE; */
2136 /* event.key.keysym.unicode = 27; */
2137
2138 /* } */
2139 /* else if (ide == 2) */
2140 /* { */
2141 /* event.key.keysym.sym = SDLK_BACKQUOTE; */
2142 /* event.key.keysym.mod = KMOD_NONE; */
2143 /* event.key.keysym.unicode = 96; */
2144 /* } */
2145
2146
2147 //....................................................
2148
2149 /* if (enter_flag == 0) */
2150 /* { */
2151
2152 /* event.key.type=SDL_KEYDOWN; */
2153 /* SDL_PushEvent(&event); */
2154 /* event.key.type=SDL_KEYUP; */
2155 /* SDL_PushEvent(&event); */
2156
2157
2158 /* } */
2159 /* } */
2160 /* } */
2161