Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/src/onscreen_keyboard.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/onscreen_keyboard.c')
-rw-r--r--src/onscreen_keyboard.c1656
1 files changed, 1656 insertions, 0 deletions
diff --git a/src/onscreen_keyboard.c b/src/onscreen_keyboard.c
new file mode 100644
index 0000000..edf9647
--- /dev/null
+++ b/src/onscreen_keyboard.c
@@ -0,0 +1,1656 @@
+#include "onscreen_keyboard.h"
+
+//#define DEBUG_OSK_COMPOSEMAP
+
+static TTF_Font * osk_fonty;
+static TTF_Font * osk_fonty10;
+static TTF_Font * osk_fonty8;
+static SDL_Color def_bgcolor = {255, 255, 255, 255};
+static SDL_Color def_fgcolor = {0, 0, 0, 0};
+
+static void load_hlayout(osk_layout *layout, char * layout_name);
+static void load_keymap(osk_layout *layout, char * keymap_name);
+static void load_composemap(osk_layout *layout, char * composemap_name);
+
+static int is_blank_or_comment(char *line);
+static int isw_blank_or_comment(wchar_t *line);
+
+
+static void keybd_prepare(on_screen_keyboard *keyboard);
+
+static void draw_key(osk_key key, on_screen_keyboard * keyboard, int hot);
+
+static void label_key(osk_key key, on_screen_keyboard *keyboard);
+static void draw_keyboard(on_screen_keyboard *keyboard);
+static osk_key * find_key(on_screen_keyboard * keyboard, int x, int y);
+static void set_key(osk_key *orig, osk_key *dest, int firsttime);
+static void load_keysymdefs(osk_layout * layout, char * keysymdefs_name);
+static struct osk_layout *load_layout(on_screen_keyboard *keyboard, char *layout_name);
+
+#ifdef DEBUG_OSK_COMPOSEMAP
+static void print_composemap(osk_composenode *composemap, char * sp);
+#endif
+
+struct osk_keyboard *osk_create(char *layout_name, SDL_Surface *canvas, SDL_Surface *button_up, SDL_Surface *button_down, SDL_Surface *button_off)
+{
+ SDL_Surface *surface;
+ osk_layout *layout;
+ on_screen_keyboard * keyboard;
+
+ keyboard = malloc(sizeof(on_screen_keyboard));
+
+
+ layout = load_layout(keyboard, layout_name);
+ if (!layout)
+ {
+ printf("Error trying to load the required layout %s\n", layout_name);
+ layout = load_layout(keyboard, layout_name); //FIXME, this should try to load the default layout
+ if (!layout)
+ {
+ printf("Error trying to load the default layout\n");
+ return NULL;
+ }
+ printf("Loaded the default layout instead.\n");
+ }
+
+ printf("w %i, h %i\n", layout->width, layout->height);
+
+ surface = SDL_CreateRGBSurface(canvas->flags,
+ layout->width * button_up->w,
+ layout->height * button_up->h,
+ canvas->format->BitsPerPixel,
+ canvas->format->Rmask,
+ canvas->format->Gmask,
+ canvas->format->Bmask, 0);
+ if (!surface)
+ {
+ printf("Error creating the onscreen keyboard surface\n");
+ return NULL;
+ }
+ keyboard->name = layout_name;
+ keyboard->layout = layout;
+ keyboard->surface = surface;
+ keyboard->rect.x = 0;
+ keyboard->rect.y = 0;
+ keyboard->rect.w = keyboard->surface->w;
+ keyboard->rect.h = keyboard->surface->h;
+ keyboard->button_up = button_up;
+ keyboard->button_down = button_down;
+ keyboard->button_off = button_off;
+ keyboard->composing = layout->composemap;
+ keyboard->composed = NULL;
+ keyboard->last_key_pressed = NULL;
+ keyboard->modifiers = 0;
+
+ set_key(NULL, &keyboard->keymodifiers.shift, 1);
+ set_key(NULL, &keyboard->keymodifiers.altgr, 1);
+ set_key(NULL, &keyboard->keymodifiers.compose, 1);
+ set_key(NULL, &keyboard->keymodifiers.dead, 1);
+
+ SDL_FillRect(surface, NULL, SDL_MapRGB(surface->format, keyboard->layout->bgcolor.r, keyboard->layout->bgcolor.g, keyboard->layout->bgcolor.b));
+
+ keybd_prepare(keyboard);
+
+ draw_keyboard(keyboard);
+ return keyboard;
+}
+
+static struct osk_layout *load_layout(on_screen_keyboard *keyboard, char *layout_name)
+{
+ FILE *fi;
+ int hlayout_loaded;
+ char * line;
+ char * filename;
+ char *key, *value;
+ osk_layout *layout;
+
+ layout = malloc(sizeof(osk_layout));
+ hlayout_loaded = 0;
+ printf("load_layout %s\n", layout_name);
+ filename = malloc(255);
+ if (layout_name != NULL)
+ {
+ /* Try full path */
+ fi = fopen(layout_name, "r");
+ if (fi == NULL)
+ {
+ /* Try with DATA_PREFIX */
+
+ snprintf(filename, 255, "%sosk/%s", DATA_PREFIX, layout_name);
+ fi = fopen(filename, "r");
+ if (fi == NULL)
+ {
+ printf("Can't open either %s nor %s\n", layout_name, filename);
+ /* Fallback to default */
+ snprintf(filename, 255, "%sosk/default.layout", DATA_PREFIX);
+ fi = fopen(filename, "r");
+ }
+ }
+ }
+ else
+ {
+ snprintf(filename, 255, "%sosk/default.layout", DATA_PREFIX);
+ fi = fopen(filename, "r");
+ }
+
+ free(filename);
+ if (fi == NULL)
+ {
+ printf("Can't load the on screen keyboard layout\n");
+ return NULL;
+ }
+
+
+ line = malloc(1024);
+ key = malloc(255);
+ value = malloc(255);
+
+ while (!feof(fi))
+ {
+ fgets(line, 1023, fi);
+
+ if (is_blank_or_comment(line))
+ continue;
+
+ sscanf(line, "%s %s", key, value);
+ if (strcmp("layout", key) == 0 && !hlayout_loaded)
+ {
+ printf("layout found: %s\n", value);
+
+ load_hlayout(layout, value);
+ hlayout_loaded = 1;
+ }
+ else if (strncmp("keymap", key, 6) == 0)
+ {
+ printf("keymap found: %s\n", value);
+ load_keymap(layout, value);
+ }
+ else if (strncmp("composemap", key, 10) == 0)
+ {
+ printf("composemap found: %s\n", value);
+ load_composemap(layout, value);
+ }
+ else if (strncmp("keysymdefs", key, 10) == 0)
+ load_keysymdefs(layout, value);
+
+ else if (strncmp("keyboardlist", key, 12) == 0)
+ {
+ char * pointer; strtok_r(line, " \t", &pointer);
+ keyboard->keyboard_list = strdup( pointer);
+ }
+
+ printf("key %s, value %s\n", key, value);
+ key[0] = '\0';
+ value[0] = '\0';
+ }
+
+
+
+ free(key);
+ free(value);
+ free(line);
+ fclose(fi);
+ return layout;
+}
+
+/* A hlayout contains the definitions of the keyboard as seen in the screen.
+ Things like the number of rows of the keyboard, the font used to render the keys,
+ the width of the keys, and a code that matches each key like in real hardware keyboards */
+void load_hlayout(osk_layout *layout, char * hlayout_name)
+{
+ int width, height;
+ int key_number, line_number;
+ int keycode, shiftcaps;
+ int allocated, have_fontpath;
+ int i;
+ int r, g, b;
+ int key_width, key_width_decimal;
+ char *filename;
+ char *line;
+ char *key, *fontpath;
+ wchar_t *plain_label, *top_label, *altgr_label;
+ FILE * fi;
+
+ key_number = line_number = 0;
+ width = height = 0;
+ allocated = 0;
+ have_fontpath = 0;
+
+ filename = malloc(255);
+
+ /* Try full path */
+ fi = fopen(hlayout_name, "r");
+ if (fi == NULL)
+ {
+ /* Try with DATA_PREFIX */
+
+ snprintf(filename, 255, "%sosk/%s", DATA_PREFIX, hlayout_name);
+ fi = fopen(filename, "r");
+ if (fi == NULL)
+ {
+ printf("Can't open either %s nor %s\n", hlayout_name, filename);
+ layout->keys = NULL;
+ free(filename);
+ return;
+ }
+ }
+
+ free(filename);
+
+ line = malloc(1024);
+ key = malloc(255);
+ fontpath = malloc(255);
+ r = g = b = 256;
+
+ layout->fgcolor.r = def_fgcolor.r;
+ layout->fgcolor.g = def_fgcolor.g;
+ layout->fgcolor.b = def_fgcolor.b;
+
+ layout->bgcolor.r = def_bgcolor.r;
+ layout->bgcolor.g = def_bgcolor.g;
+ layout->bgcolor.b = def_bgcolor.b;
+
+
+ while (!feof(fi))
+ {
+ if(width && height && !allocated)
+ {
+ layout->keys = malloc(height * sizeof(osk_key *));
+ layout->keys[0] = malloc(width * sizeof(osk_key ));
+
+ for (i = 0; i< width; i++)
+ {
+ layout->keys[0][i].width = 0;
+ layout->keys[0][i].plain_label = NULL;
+ }
+ layout->width = width;
+ layout->height = height;
+
+ printf("w %i, h %i\n" , layout->width, layout->height);
+ allocated = 1;
+ }
+
+ fgets(line, 1023, fi);
+
+ if (is_blank_or_comment(line))
+ continue;
+
+ if (strncmp(line, "WIDTH", 5) == 0)
+ sscanf(line, "%s %i", key, &width);
+
+ else if (strncmp(line, "HEIGHT", 5) == 0)
+ sscanf(line, "%s %i", key, &height);
+
+ else if (strncmp(line, "FONTPATH", 8) == 0)
+ {
+ printf("linefont %s\n", line);
+ sscanf(line, "%s %s", key, fontpath);
+ if (!is_blank_or_comment(fontpath))
+ have_fontpath = 1;
+ }
+ else if (strncmp(line, "FGCOLOR", 5) == 0)
+ {
+ printf("linefont %s\n", line);
+ sscanf(line, "%s %i %i %i", key, &r, &g, &b);
+ if (r > 0 && r< 256 && g > 0 && g< 256 && b > 0 && b< 256)
+ {
+ layout->fgcolor.r = r;
+ layout->fgcolor.g = g;
+ layout->fgcolor.b = b;
+ r = g = b = 256;
+ }
+ }
+ else if (strncmp(line, "BGCOLOR", 5) == 0)
+ {
+ printf("linefont %s\n", line);
+ sscanf(line, "%s %i %i %i", key, &r, &g, &b);
+ if (r > 0 && r< 256 && g > 0 && g< 256 && b > 0 && b< 256)
+ {
+ layout->bgcolor.r = r;
+ layout->bgcolor.g = g;
+ layout->bgcolor.b = b;
+ r = g = b = 256;
+ }
+ }
+ else if (strncmp(line, "NEWLINE", 7) == 0)
+ {
+ line_number ++;
+ key_number = 0;
+ layout->keys[line_number] = malloc(width * sizeof(osk_key));
+ for (i = 0; i< width; i++)
+ layout->keys[line_number][i].width = 0;
+ }
+
+
+ else if (width && height && allocated && strncmp(line, "KEY ", 4) == 0 && key_number < width)
+ {
+ plain_label = malloc(64);
+ top_label = malloc(64);
+ altgr_label = malloc(64);
+
+ sscanf(line,
+ "%s %i %i.%i %ls %ls %ls %i",
+ key,
+ &keycode,
+ &key_width,
+ &key_width_decimal,
+ plain_label,
+ top_label,
+ altgr_label,
+ &shiftcaps);
+ layout->keys[line_number][key_number].keycode = keycode;
+ layout->keys[line_number][key_number].width = (float)0.1 * key_width_decimal + key_width;
+ layout->keys[line_number][key_number].plain_label = plain_label;
+ layout->keys[line_number][key_number].top_label = top_label;
+ layout->keys[line_number][key_number].altgr_label = altgr_label;
+ layout->keys[line_number][key_number].shiftcaps = shiftcaps;
+ key_number ++;
+ }
+ }
+
+ if (have_fontpath)
+ layout->fontpath = fontpath;
+ else
+ {
+ free(fontpath);
+ layout->fontpath = NULL;
+ }
+ /* int j; */
+ /* for(i = 0; i<= line_number; i++) */
+ /* { */
+ /* printf("Line %i\n", i); */
+ /* for (j =0; j < width; j++) */
+ /* { */
+ /* printf(" %i, \n ", j); */
+ /* if(layout.keys[i][j].width) */
+ /* printf("keycode %d, width %f, plain %ls, caps %ls\n", */
+ /* layout.keys[i][j].keycode, */
+ /* layout.keys[i][j].width, */
+ /* layout.keys[i][j].plain_label, */
+ /* layout.keys[i][j].caps_label); */
+ /* } */
+ /* } */
+}
+
+
+/* A keymap contains the keysyms (X keysym mnemonics) associated to each keycode in the hlayout.*/
+void load_keymap(osk_layout *layout, char * keymap_name)
+{
+ int keycode, readed;
+ char *filename;
+ char *ksname1, *ksname2, *ksname3, *ksname4;
+ char *line;
+ FILE * fi;
+
+ filename = malloc(255);
+
+ /* Try full path */
+ fi = fopen(keymap_name, "r");
+ if (fi == NULL)
+ {
+ /* Try with DATA_PREFIX */
+
+ snprintf(filename, 255, "%sosk/%s", DATA_PREFIX, keymap_name);
+ fi = fopen(filename, "r");
+ if (fi == NULL)
+ {
+ printf("Can't open either %s nor %s\n", keymap_name, filename);
+ layout->keys = NULL;
+ free(filename);
+ return;
+ }
+ }
+
+ free(filename);
+
+ line = malloc(1024);
+ layout->keymap = malloc(256 * sizeof(osk_keymap));
+
+ while (!feof(fi))
+ {
+
+ fgets(line, 1023, fi);
+
+ if (is_blank_or_comment(line))
+ continue;
+
+ ksname1 = malloc(64);
+ ksname2 = malloc(64);
+ ksname3 = malloc(64);
+ ksname4 = malloc(64);
+ ksname1[0] = '\0';
+ ksname2[0] = '\0';
+ ksname3[0] = '\0';
+ ksname4[0] = '\0';
+
+ /* FIXME: Why is the us-intl keymap duplicating the two first entries of every keycode? */
+ readed = sscanf(line, "keycode %i = %s %s %*s %*s %s %s", &keycode,
+ ksname1, ksname2, ksname3, ksname4);
+
+ if (readed == 5 && keycode > 8 && keycode < 256)
+ {
+ layout->keymap[keycode].plain = ksname1;
+ layout->keymap[keycode].caps = ksname2;
+ layout->keymap[keycode].altgr = ksname3;
+ layout->keymap[keycode].shiftaltgr = ksname4;
+ }
+ else
+ {
+ free(ksname1);
+ free(ksname2);
+ free(ksname3);
+ free(ksname4);
+ layout->keymap[keycode].plain = NULL;
+ layout->keymap[keycode].caps = NULL;
+ layout->keymap[keycode].altgr = NULL;
+ layout->keymap[keycode].shiftaltgr = NULL;
+ }
+ }
+
+ /* int i; */
+ /* for (i = 0; i < 256; i++) */
+ /* { */
+ /* if (layout.keymap[i].plain) */
+ /* printf("%i, %i, %i, %i, %i\n", i, */
+ /* layout.keymap[i].plain, */
+ /* layout.keymap[i].caps, */
+ /* layout.keymap[i].altgr, */
+ /* layout.keymap[i].shiftaltgr); */
+ /* } */
+
+
+
+}
+
+/* Scans a line of keysyms and result and classifies them. */
+static void gettokens(wchar_t * line, wchar_t * delim, wchar_t ** pointer, osk_composenode *composenode, osk_layout *layout)
+{
+ int i;
+ wchar_t *tok;
+ wchar_t * result;
+ osk_composenode *auxnode;
+
+ tok = wcsdup(wcstok(line, delim, pointer));
+ if(!tok)
+ return;
+
+ if (tok[0] == L':') /* End of precompose keysyms, next will be the result in unicode. */
+ {
+ result = wcsdup(wcstok(line, L": \"\t", pointer));
+ // printf("result %ls\n", result);
+ composenode->result = result;
+ return;
+ }
+ else
+ {
+ if (composenode->size == 0)
+ {
+ composenode->size = 1;
+ auxnode = malloc(sizeof(osk_composenode));
+ composenode->childs = malloc(sizeof(osk_composenode *));
+ composenode->childs[0] = auxnode;
+ composenode->childs[0]->keysym = tok;
+ composenode->childs[0]->result = NULL;
+ composenode->childs[0]->size = 0;
+
+ // printf("size %d, keysym %ls => ", composenode->size, composenode->childs[0]->keysym);
+
+ gettokens(NULL, delim, pointer, composenode->childs[0], layout);
+ return;
+ }
+ else
+ {
+ for (i = 0; i < composenode->size; i++)
+ {
+ if(wcscmp(composenode->childs[i]->keysym, tok) == 0)
+ {
+
+ // printf("Size %d, keysym %ls =>", composenode->size, composenode->childs[i]->keysym);
+
+ gettokens(NULL, delim, pointer, composenode->childs[i], layout);
+ return;
+ }
+ }
+ }
+
+ composenode->size = composenode->size + 1;
+ composenode->childs = realloc(composenode->childs,composenode->size * sizeof(osk_composenode *));
+
+
+ auxnode = malloc(sizeof(osk_composenode));
+ composenode->childs[composenode->size - 1] = auxnode;//malloc(sizeof(osk_composenode));
+ composenode->childs[composenode->size - 1]->keysym = tok;
+ composenode->childs[composenode->size - 1]->result = NULL;
+ composenode->childs[composenode->size - 1]->size = 0;
+
+ // printf("size %d, keysym %ls =>", composenode->size, composenode->childs[composenode->size - 1]->keysym);
+
+ gettokens(NULL, delim, pointer, composenode->childs[composenode->size - 1], layout);
+ return;
+ }
+}
+
+
+/* A compose map contains the sequences of keysyms (X keysym mnemonics) needed to generate another keysym.
+ The last in the sequence is the result, the others will be searched in the order they appear.
+ They will be classified in a multiway tree.*/
+static void load_composemap(osk_layout *layout, char * composemap_name)
+{
+ char *filename;
+ wchar_t **pointer;
+ wchar_t *line;
+ FILE * fi;
+
+ pointer = malloc(sizeof(wchar_t *));
+ filename = malloc(255);
+
+ /* Try full path */
+ fi = fopen(composemap_name, "r");
+ if (fi == NULL)
+ {
+ /* Try with DATA_PREFIX */
+
+ snprintf(filename, 255, "%sosk/%s", DATA_PREFIX, composemap_name);
+ fi = fopen(filename, "r");
+ if (fi == NULL)
+ {
+ printf("Can't open either %s nor %s\n", composemap_name, filename);
+ layout->keys = NULL;
+ free(filename);
+ return;
+ }
+ }
+
+ free(filename);
+
+ layout->composemap = malloc(sizeof(osk_composenode));
+ layout->composemap[0].keysym = NULL;
+ layout->composemap->size = 0;
+ line = malloc(1024*sizeof(wchar_t));
+
+ while (!feof(fi))
+ {
+ fgetws(line, 1023, fi);
+
+ if (isw_blank_or_comment(line))
+ continue;
+
+ gettokens(line, (wchar_t *) L">< \t", pointer, layout->composemap, layout);
+ }
+
+ fclose(fi);
+ free(line);
+
+#ifdef DEBUG_OSK_COMPOSEMAP
+ print_composemap(layout->composemap, NULL);
+#endif
+}
+
+#ifdef DEBUG_OSK_COMPOSEMAP
+static void print_composemap(osk_composenode *composemap, char * sp)
+{
+ int i;
+ char * space;
+ space = malloc(255);
+
+
+
+ printf("%ls, ", composemap->keysym);
+ printf("%d ==> ", composemap->size);
+ if (composemap->size == 0)
+ { printf("result %ls\n", composemap->result);
+ return;}
+ if (sp)
+ {
+ sprintf(space, "%s\t", sp);
+ }
+ else
+ sprintf(space, " ");
+ printf("%s", space);
+
+ for (i = 0; i < composemap->size; i++)
+ {
+ print_composemap(composemap->childs[i], space);
+ // free(space);
+ }
+ /* for (i = 0; i < composemap->size; i++) */
+ /* { */
+ /* printf("aaa %ls, ", composemap->keysym); */
+ /* printf("%d ==> ", composemap->size); */
+ /* printf("%ls, ", composemap->childs[i]->keysym); */
+ /* printf("childs %d ==> ", composemap->childs[i]->size); */
+
+ /* if (composemap->childs[i]->size == 0) */
+ /* printf("result %ls\n", composemap->childs[i]->result); */
+ /* else */
+ /* print_composemap(composemap->childs[i], space); */
+ /* // free(space); */
+ /* } */
+}
+#endif
+
+/* This parses the contents of keysymdef.h from the source of xorg.
+ Therefore, if somebody wants to provide custom keysymdefs, he has to follow its syntax. */
+static void load_keysymdefs(osk_layout *layout, char * keysymdefs_name)
+{
+ int i;
+ char *filename;
+ char *line;
+ FILE * fi;
+
+ filename = malloc(255);
+
+ /* Try full path */
+ fi = fopen(keysymdefs_name, "r");
+ if (fi == NULL)
+ {
+ /* Try with DATA_PREFIX */
+
+ snprintf(filename, 255, "%sosk/%s", DATA_PREFIX, keysymdefs_name);
+ fi = fopen(filename, "r");
+ if (fi == NULL)
+ {
+ printf("Can't open either %s nor %s\n", keysymdefs_name, filename);
+ layout->keysymdefs = NULL;
+ free(filename);
+ return;
+ }
+ }
+
+ free(filename);
+
+ layout->keysymdefs = malloc(sizeof(keysymdefs));
+ layout->keysymdefs[0].unicode = 0;
+ i = 0;
+ line = malloc(1024*sizeof(wchar_t));
+
+ while (!feof(fi))
+ {
+ fgets(line, 1023, fi);
+ if (strncmp("#define XK_", line, 11) != 0)
+ continue;
+
+ layout->sizeofkeysymdefs = i;
+ layout->keysymdefs = realloc(layout->keysymdefs, sizeof(keysymdefs) * (i + 1));
+
+ /* Some keysyms doesn't correspond to any unicode value, ej. BackSpace */
+ layout->keysymdefs[i].unicode = 0;
+ sscanf(line, "#define XK_%ms %x /* U+%x",
+ &layout->keysymdefs[i].mnemo,
+ &layout->keysymdefs[i].keysym,
+ &layout->keysymdefs[i].unicode);
+ i++;
+ }
+
+ fclose(fi);
+ free(line);
+}
+
+/* Return the mnemonic string of a x keysym as defined in the source of xorg in keysymdef.h */
+static char * keysym2mnemo(int keysym, on_screen_keyboard * keyboard)
+{
+ uint i;
+ for (i = 0; i < keyboard->layout->sizeofkeysymdefs ;i++)
+ if (keysym == keyboard->layout->keysymdefs[i].keysym)
+ return(keyboard->layout->keysymdefs[i].mnemo);
+
+ /* For the purpose of onscreen keyboard we don't need the conversion to strings in the form U0000 */
+ return(NULL);
+}
+
+/* Returns the x keysym corresponding to a mnemonic string */
+static int mnemo2keysym(char * mnemo, on_screen_keyboard * keyboard)
+{
+ uint i;
+
+ for (i = 0; i < keyboard->layout->sizeofkeysymdefs; i++)
+ {
+ if (strcmp(mnemo , keyboard->layout->keysymdefs[i].mnemo) == 0)
+ return(keyboard->layout->keysymdefs[i].keysym);
+ }
+ i = 0;
+
+ /* Perhaps the mnemo is in UXXXX format? */
+ if(sscanf(mnemo, "U%x", &i))
+ return(i | 0x01000000);
+
+ /* Or maybe mnemo is already a keysym? */
+ if (sscanf(mnemo, "0x%x", &i))
+ return(i);
+
+ return(0);
+}
+
+/* Returns the unicode value of a x keysym if any, otherwise returns 0 */
+static int keysym2unicode(int keysym, on_screen_keyboard * keyboard)
+{
+ uint i;
+
+ /* Credits for the conversion from xkeysyms to unicode values, code taken from the source code of xterm, file keysym2ucs.c.
+ *Author: Markus G. Kuhn <mkuhn@acm.org>, University of Cambridge, April 2001
+ *
+ * Special thanks to Richard Verhoeven <river@win.tue.nl> for preparing
+ * an initial draft of the mapping table.
+ *
+ * This software is in the public domain. Share and enjoy!
+ */
+ /* first check for Latin-1 characters (1:1 mapping) */
+ if ((keysym >= 0x0020 && keysym <= 0x007e) ||
+ (keysym >= 0x00a0 && keysym <= 0x00ff))
+ return keysym;
+
+ /* also check for directly encoded 24-bit UCS characters */
+ if ((keysym & 0xff000000) == 0x01000000)
+ return keysym & 0x00ffffff;
+
+
+
+ for (i = 0; i < keyboard->layout->sizeofkeysymdefs; i++)
+ if (keysym == keyboard->layout->keysymdefs[i].keysym)
+ return(keyboard->layout->keysymdefs[i].unicode);
+
+ return(keysym);
+}
+
+
+/* Searches in the tree for composing stuff */
+static void get_composed_keysym(on_screen_keyboard * keyboard, osk_composenode * composenode, wchar_t * keysym)
+{
+ int i;
+
+ /* If there is not a compose table return the keysym */
+ if (! composenode)
+ {
+ keyboard->composed = keysym;
+ keyboard->composed_type = 0;
+ return;
+ }
+
+ /* If there is a compose table, lookup for matches */
+ for (i = 0; i < composenode->size; i++)
+ {
+ /* If matches, set either the result or the next node */
+ if (wcscmp(composenode->childs[i]->keysym, keysym) == 0)
+ {
+ if (composenode->childs[i]->result)
+ {
+ keyboard->composed = composenode->childs[i]->result;
+ keyboard->composing = keyboard->layout->composemap;
+ /* The result in the Compose files from xorg is yet in unicode */
+ keyboard->composed_type = 1;
+ return;
+ }
+ else
+ {
+ keyboard->composed = NULL;
+ keyboard->composing = composenode->childs[i];
+ return;
+ }
+ }
+ }
+
+ /* No matches found, if we were in the middle of a sequence, reset the compose stuff,
+ if we were in the beginning node, set the keysym */
+
+ if (keyboard->layout->composemap == composenode)
+ {
+ keyboard->composed = keysym;
+ keyboard->composed_type = 0;
+ }
+ else /* reset */
+ {
+ keyboard->composing = keyboard->layout->composemap;
+ keyboard->composed = NULL;
+ keyboard->composed_type = 0;
+ }
+}
+
+
+static int is_blank_or_comment(char *line)
+{
+ int i;
+
+ i = 0;
+
+ if (strlen(line) == 0)
+ return 0;
+ while (line[i] != '\n')
+ {
+ if (line[i] == '#')
+ return 1;
+ else if (line[i] == ' ' || line[i] == '\t')
+ i++;
+ else
+ return 0;
+ }
+ return 1;
+}
+
+
+static int isw_blank_or_comment(wchar_t *line)
+{
+ int i;
+
+ i = 0;
+ if (wcslen(line) == 0)
+ return 0;
+ while (line[i] != L'\n')
+ {
+ if (line[i] == L'#')
+ return 1;
+ else if (line[i] == L' ' || line[i] == L'\t')
+ i++;
+ else
+ return 0;
+ }
+ return 1;
+}
+
+
+/* Fixme: Is it safe to supose that if a font is loaded at one size, it will be loaded at any size? */
+static void keybd_prepare(on_screen_keyboard *keyboard)
+{
+ char * fontname;
+ fontname = malloc(255);
+
+ if (keyboard->layout->fontpath)
+ {
+ /* First try if it is an absolute path */
+ osk_fonty = TTF_OpenFont( keyboard->layout->fontpath, 12 );
+ osk_fonty10 = TTF_OpenFont( keyboard->layout->fontpath, 10 );
+ osk_fonty8 = TTF_OpenFont( keyboard->layout->fontpath, 8 );
+ if (osk_fonty == NULL)
+ {
+ /* Now trying if it is relative to DATA_PREFIX/fonts/ */
+ snprintf(fontname, 255, "%s/fonts/%s", DATA_PREFIX, keyboard->layout->fontpath);
+
+ osk_fonty = TTF_OpenFont( fontname, 12 );
+ osk_fonty10 = TTF_OpenFont( fontname, 10 );
+ osk_fonty8 = TTF_OpenFont( fontname, 8 );
+ if (osk_fonty == NULL)
+ {
+ /* Perhaps it is relative to DATA_PREFIX only? */
+ snprintf(fontname, 255, "%s/%s", DATA_PREFIX, keyboard->layout->fontpath);
+ osk_fonty = TTF_OpenFont( fontname, 12 );
+ osk_fonty10 = TTF_OpenFont( fontname, 10 );
+ osk_fonty8 = TTF_OpenFont( fontname, 8 );
+ if (osk_fonty == NULL)
+ {
+ /* Or to DATA_PREFIX/fonts/locale/ ? */
+ snprintf(fontname, 255, "%s/fonts/locale/%s", DATA_PREFIX, keyboard->layout->fontpath);
+ osk_fonty = TTF_OpenFont( fontname, 12 );
+ osk_fonty10 = TTF_OpenFont( fontname, 10 );
+ osk_fonty8 = TTF_OpenFont( fontname, 8 );
+ }
+ }
+ }
+ }
+
+ if (osk_fonty == NULL)
+ {
+ /* Going with the default */
+ sprintf(fontname, "%s/fonts/FreeSansBold.ttf", DATA_PREFIX);
+ osk_fonty = TTF_OpenFont( fontname, 12 );
+ osk_fonty10 = TTF_OpenFont( fontname, 10 );
+ osk_fonty8 = TTF_OpenFont( fontname, 8 );
+ }
+
+ if (osk_fonty == NULL)
+ {
+ fprintf(stderr, "\nError: Can't open the font!\n"
+ "The Simple DirectMedia Layer error that occurred was:\n"
+ "%s\n\n", SDL_GetError());
+ free(fontname);
+ exit(1);
+ }
+
+ free(fontname);
+}
+
+
+static void apply_surface (int x, int y, SDL_Surface *source, SDL_Surface *destination, SDL_Rect *clip)
+{
+ SDL_Rect offset;
+
+ offset.x = x;
+ offset.y = y;
+
+ SDL_BlitSurface( source, clip, destination, &offset );
+}
+
+
+/* NOTE: This is a duplicate of wcstou16 in tuxpaint.c
+
+ This conversion is required on platforms where Uint16 doesn't match wchar_t.
+ On Windows, wchar_t is 16-bit, elsewhere it is 32-bit.
+ Mismatch caused by the use of Uint16 for unicode characters by SDL, SDL_ttf.
+ I guess wchar_t is really only suitable for internal use ... */
+static Uint16 *wcstou16(const wchar_t * str)
+{
+ unsigned int i, len = wcslen(str);
+ Uint16 *res = malloc((len + 1) * sizeof(Uint16));
+
+ for (i = 0; i < len + 1; ++i)
+ {
+ /* This is a bodge, but it seems unlikely that a case-conversion
+ will cause a change from one utf16 character into two....
+ (though at least UTF-8 suffers from this problem) */
+
+ // FIXME: mangles non-BMP characters rather than using UTF-16 surrogates!
+ res[i] = (Uint16) str[i];
+ }
+
+ return res;
+}
+
+/* Stretches a button from the middle, keeping the extrems intact */
+static SDL_Surface * stretch_surface(SDL_Surface * orig, int width)
+{
+ int i;
+ SDL_Surface * dest;
+ SDL_Rect rect;
+ SDL_Rect orig_rect;
+
+ orig_rect.x = orig->w / 2;
+ orig_rect.y = 0;
+ orig_rect.w = 1;
+ orig_rect.h = orig->h;
+
+ dest = SDL_CreateRGBSurface(orig->flags,
+ width,
+ orig->h,
+ orig->format->BitsPerPixel,
+ orig->format->Rmask,
+ orig->format->Gmask,
+ orig->format->Bmask, 0);
+
+ SDL_BlitSurface(orig, NULL, dest, NULL);
+ rect.y = 0;
+
+ if (width > orig->w)
+ {
+ rect.x = width - orig->w;
+ rect.h = orig->h;
+ rect.w = orig->w;
+ SDL_BlitSurface(orig, NULL, dest, &rect);
+
+ rect.w = 1;
+ for (i = orig->w / 2; i < width - orig->w / 2; i++)
+ {
+ rect.x = i;
+ SDL_BlitSurface(orig, &orig_rect, dest, &rect);
+ }
+ }
+ else if (width < orig->w)
+ {
+ rect.y = 0;
+ rect.w = 1;
+ rect.h = dest->h;
+
+ orig_rect.y = 0;
+ orig_rect.w = 1;
+ orig_rect.h = orig->h;
+
+ for (i = 0; i <= width / 2; i++)
+ {
+ rect.x = dest->w - i;
+ orig_rect.x = orig->w - i;
+ SDL_BlitSurface(orig, &orig_rect, dest, &rect);
+ }
+ }
+
+ return dest;
+}
+
+/* Draws the keyboard surface */
+static void draw_keyboard(on_screen_keyboard *keyboard)
+{
+ int i, j;
+ int key_height, accumulated_width, accumulated_height;
+ float key_width;
+ key_width = keyboard->button_up->w;
+ key_height = keyboard->button_up->h;
+
+ accumulated_height = 0;
+
+ for (j = 0; j < keyboard->layout->height; j++)
+ {
+ accumulated_width = 0;
+ for (i = 0; i < keyboard->layout->width; i++)
+ {
+ if (keyboard->layout->keys[j][i].width)
+ {
+
+ keyboard->layout->keys[j][i].row = j;
+ keyboard->layout->keys[j][i].x = accumulated_width;
+ keyboard->layout->keys[j][i].y = accumulated_height;
+
+ draw_key(keyboard->layout->keys[j][i], keyboard, 0); }
+ accumulated_width += (keyboard->layout->keys[j][i].width * key_width);
+ }
+ accumulated_height += key_height;
+ }
+}
+
+static void draw_key(osk_key key, on_screen_keyboard * keyboard, int hot)
+{
+ char *text;
+ SDL_Surface *skey;
+ if (!key.width)
+ return;
+ text = malloc(255);
+
+ snprintf(text, 6,"%ls", key.plain_label);
+
+
+ if( strncmp("NULL", text, 4) != 0 && key.keycode != 0)
+ {
+ if (!hot)
+ skey = stretch_surface(keyboard->button_up, key.width * keyboard->button_up->w);
+ else
+ skey = stretch_surface(keyboard->button_down, key.width * keyboard->button_down->w);
+ }
+ else
+ skey = stretch_surface(keyboard->button_off, key.width * keyboard->button_up->w);
+
+ apply_surface(key.x, key.y, skey, keyboard->surface, NULL);
+
+ SDL_FreeSurface(skey);
+ free(text);
+ label_key(key, keyboard);
+}
+
+
+/* FIXME: TODO draw top and bottom_right (altgr) labels */
+static void label_key(osk_key key, on_screen_keyboard *keyboard)
+{
+ Uint16 *ustr;
+ SDL_Surface *messager;
+ char *text;
+ text = malloc(255);
+ snprintf(text, 6,"%ls", key.plain_label);
+
+ if( strncmp("SPACE", text, 5) != 0 && strncmp("NULL",text, 4) != 0)
+ {
+ ustr = wcstou16(key.plain_label);
+ //messager = TTF_RenderUNICODE_Solid(
+ messager = TTF_RenderUNICODE_Blended(osk_fonty, ustr, keyboard->layout->fgcolor);
+
+ free(ustr);
+ apply_surface( key.x + 5, key.y, messager, keyboard->surface, NULL);
+ SDL_FreeSurface(messager);
+ }
+ free(text);
+}
+
+/* Searches the key corresponding to coordinates */
+static osk_key * find_key(on_screen_keyboard * keyboard, int x, int y)
+{
+ int i, j;
+ osk_key *key;
+ key =malloc(sizeof(osk_key));
+
+ for (j = 0; j <keyboard->layout->height; j++)
+ {
+ if (keyboard->layout->keys[j][0].y < y &&
+ keyboard->layout->keys[j][0].y + keyboard->button_up->h > y)
+ for (i = 0; i < keyboard->layout->width; i++)
+ if (keyboard->layout->keys[j][i].x < x &&
+ keyboard->layout->keys[j][i].x + keyboard->layout->keys[j][i].width * keyboard->button_up->w > x)
+ {
+ *key = keyboard->layout->keys[j][i];
+ return key;
+ }
+ }
+ return NULL;
+}
+
+/* Copies orig to dest or sets dest to defaults if orig is NULL.
+ if firstime is setted, don't frees the strings as there aren't. */
+static void set_key(osk_key *orig, osk_key *dest, int firsttime)
+{
+ if (orig == NULL)
+ {
+ dest->keycode = 0;
+ dest->row = 0;
+ dest->x = 0;
+ dest->y = 0;
+ dest->width = 0;
+ if (!firsttime && dest->plain_label != NULL)
+ free(dest->plain_label);
+ dest->plain_label = NULL;
+ if (!firsttime && dest->top_label != NULL)
+ free(dest->top_label);
+ dest->top_label = NULL;
+ if (!firsttime && dest->altgr_label != NULL)
+ free(dest->altgr_label);
+ dest->altgr_label = NULL;
+ dest->shiftcaps = 0;
+ }
+ else
+ {
+ dest->keycode = orig->keycode;
+ dest->row = orig->row;
+ dest->x = orig->x;
+ dest->y = orig->y;
+ dest->width = orig->width;
+
+ if (dest->plain_label != NULL)
+ free(dest->plain_label);
+ dest->plain_label = wcsdup(orig->plain_label);
+
+ if (dest->top_label != NULL)
+ free(dest->top_label);
+ dest->top_label = wcsdup(orig->top_label);
+
+ if (dest->altgr_label != NULL)
+ free(dest->altgr_label);
+ dest->altgr_label = wcsdup(orig->altgr_label);
+
+ dest->shiftcaps = orig->shiftcaps;
+ }
+}
+
+static char * find_keysym(osk_key key, on_screen_keyboard *keyboard)
+{
+ int keycode;
+ char *keysym;
+ osk_keymap keysyms;
+ SDLMod modstate;
+
+ keycode = key.keycode;
+ keysyms = keyboard->layout->keymap[keycode];
+ keysym = NULL;
+
+ modstate = keyboard->modifiers;
+
+ /* FIXME There MUST be a simpler way to do this. Pere 2011/8/3 */
+ /* First the plain ones */
+ if (modstate == KMOD_NONE || (modstate == (KMOD_NONE | KMOD_LALT)))
+ keysym = keysyms.plain;
+
+ else if (modstate == KMOD_SHIFT)
+ {
+ keysym = keysyms.caps;
+ }
+
+ else if (modstate == KMOD_RALT)
+ {
+ keysym = keysyms.altgr;
+ }
+
+ else if (modstate == KMOD_CAPS)
+ {
+ if (key.shiftcaps)
+ keysym = keysyms.caps;
+ else
+ keysym = keysyms.plain;
+ }
+
+ /* Now the combined ones */
+ else if (modstate & KMOD_RALT && modstate & KMOD_SHIFT)
+ {
+ if (modstate & KMOD_CAPS)
+ {
+ if (key.shiftcaps)
+ keysym = keysyms.altgr;
+ else
+ keysym = keysyms.shiftaltgr;
+ }
+ else
+ {
+ keysym = keysyms.shiftaltgr;
+ }
+ }
+
+ else if (modstate & KMOD_RALT && modstate & KMOD_CAPS && !(modstate & KMOD_SHIFT))
+ {
+ if (key.shiftcaps)
+ keysym = keysyms.shiftaltgr;
+ else
+ keysym = keysyms.altgr;
+ }
+
+ else if (modstate & KMOD_SHIFT && modstate & KMOD_CAPS)
+ {
+ if (key.shiftcaps)
+ keysym = keysyms.plain;
+ else
+ keysym = keysyms.caps;
+ }
+
+ return(keysym);
+}
+
+/* We lose the SDL ModState by leaving and entering the tuxpaint window, so using a custom state */
+static int handle_keymods(char * keysym, osk_key key, on_screen_keyboard *keyboard)
+{
+ SDLMod mod;
+ SDL_Event ev;
+
+ mod = keyboard->modifiers;
+
+ if (strncmp("Shift", keysym, 5) == 0)
+ {
+ if (mod & KMOD_SHIFT)
+ {
+ draw_key(key, keyboard, 0);
+ keyboard->modifiers = mod & 0xFFF0;
+ }
+ else
+ {
+ draw_key(key, keyboard, 1);
+ keyboard->modifiers = mod | KMOD_SHIFT;
+ set_key(&key, &keyboard->keymodifiers.shift, 0);
+ }
+
+ return 1;
+ }
+ else if (strncmp("Alt_L", keysym, 5) == 0)
+ {
+ ev.key.keysym.sym = SDLK_LALT;
+ ev.key.keysym.unicode = 0; // FIXME is 0 the right value here?
+ ev.type = SDL_KEYDOWN;
+ SDL_PushEvent(&ev);
+ ev.type = SDL_KEYUP;
+ SDL_PushEvent(&ev);
+
+ return 1;
+ }
+
+ /* Seems ISO_Level3_Shift and ISO_Next_Group are used too for right Alt */
+ else if (strncmp("ISO_Level3_Shift", keysym, 16) == 0||
+ strncmp("ISO_Next_Group", keysym, 14) == 0||
+ strncmp("ALT_R", keysym, 5) == 0)
+ {
+ if (mod & KMOD_RALT)
+ keyboard->modifiers = mod & 0xF0FF;
+ else
+ {
+ keyboard->modifiers = mod | KMOD_RALT;
+ draw_key(key, keyboard, 1);
+ set_key(&key, &keyboard->keymodifiers.altgr, 0);
+
+ return 1;
+ }
+ return 0;
+ }
+
+ else if (strncmp("Caps_Lock", keysym, 9) == 0)
+ {
+ if (mod & KMOD_CAPS)
+ {
+ draw_key(key, keyboard, 0);
+ keyboard->modifiers = mod & 0x0FFF;
+ }
+ else
+ {
+ keyboard->modifiers = mod | KMOD_CAPS;
+ draw_key(key, keyboard, 1);
+ }
+
+ return 1;
+ }
+ if (mod & KMOD_CAPS)
+ {
+ keyboard->modifiers = KMOD_CAPS;
+ }
+ else
+ keyboard->modifiers = KMOD_NONE;
+
+ draw_key(keyboard->keymodifiers.shift, keyboard, 0);
+ draw_key(keyboard->keymodifiers.altgr, keyboard, 0);
+
+ return 0;
+}
+
+struct osk_keyboard * osk_clicked(on_screen_keyboard *keyboard, int x, int y)
+{
+ int i;
+ osk_key *key;
+ SDL_Event event;
+ char *keysym, *mnemo;
+ char *name, *aux_name, *aux_list;
+ wchar_t *wkeysym;
+ on_screen_keyboard * new_keyboard;
+
+ printf("list: %s\n", keyboard->keyboard_list);
+
+ key = find_key(keyboard, x, y);
+
+ if (key)
+ {
+ /* First the reserved keycodes */
+ /* Select next or previous keyboard */
+ if (key->keycode == 1 || key->keycode == 2)
+ {
+ aux_list = strdup(keyboard->keyboard_list);
+ printf("auxlist: %s\n", aux_list);
+ printf("kn %s\n", keyboard->name);
+ if (key->keycode == 1)
+ {
+ for (i = 0;;i++, aux_list = NULL)
+ {
+ name = strtok(aux_list, " \n\r\t");
+
+ if (i == 0)
+ aux_name = name;
+
+ if(strcmp(name, keyboard->name) == 0)
+ {
+ name = strtok(NULL, " \n\r\t");
+ if (name == NULL)
+ name = aux_name;
+ break;
+ }
+ }
+ }
+ else
+ {
+ aux_name = NULL;
+ for (i = 0;;i++, aux_list = NULL)
+ {
+ name = strtok(aux_list, " \n\r\t");
+
+ if(name == NULL)
+ {
+ name = aux_name;
+ break;
+ }
+
+ if(strstr(name, keyboard->name))
+ {
+ name = aux_name;
+ if (name != NULL)
+ break;
+ }
+
+ aux_name = name;
+ }
+ }
+
+
+ new_keyboard = osk_create(strdup(name), keyboard->surface, keyboard->button_up, keyboard->button_down, keyboard->button_off);
+ printf("freeeeeeeeeeeeeeeeeeeeeee\n");
+ free(aux_list);
+
+ if (new_keyboard == NULL)
+ return(keyboard); /* Don't break here, at least the old keyboard should work */
+ else
+ {
+ free(new_keyboard->keyboard_list);
+ new_keyboard->keyboard_list = strdup(keyboard->keyboard_list);
+ osk_free(keyboard);
+ return(new_keyboard);
+ }
+ }
+
+
+ keysym = find_keysym(*key, keyboard);
+ if (!keysym) return(keyboard);
+
+ if (handle_keymods(keysym, *key, keyboard))
+ return(keyboard); /* no more processing is needed */
+
+ draw_key(*key, keyboard, 1);
+
+ wkeysym = malloc(sizeof(wchar_t) * (strlen(keysym) + 1));
+
+ mbsrtowcs(wkeysym, (const char **) &keysym,
+ strlen(keysym)+1,
+ NULL);
+
+ printf("wkeysym %ls %i\n", wkeysym, wcslen(wkeysym));
+ printf("\n");
+
+
+ get_composed_keysym(keyboard, keyboard->composing, wkeysym);
+ wchar_t *ks;
+ draw_key(keyboard->keymodifiers.compose, keyboard, 0);
+
+ if (keyboard->composed)
+ {
+ keyboard->last_key_pressed = key;
+ set_key(NULL, &keyboard->keymodifiers.compose, 0);
+ ks = keyboard->composed;
+ printf("keysym found %ls\n", ks);
+
+ mnemo = malloc(32);
+ snprintf(mnemo, 31, "%ls", ks);
+
+ if (wcsncmp(L"Return", ks, 6) == 0)
+ {
+ event.key.keysym.sym = SDLK_RETURN;
+ event.key.keysym.unicode = '\r';
+ }
+ else if (wcsncmp(L"Tab", ks, 3) == 0 ||
+ wcsncmp(L"ISO_Left_Tab", ks, 12) == 0)
+ {
+ event.key.keysym.sym = SDLK_TAB;
+ event.key.keysym.unicode = '\t';
+ }
+ else if (wcsncmp(L"BackSpace", ks, 9) == 0)
+ {
+ event.key.keysym.sym = SDLK_BACKSPACE;
+ event.key.keysym.unicode = '\b';
+ }
+ else if (wcsncmp(L"NoSymbol", ks, 8 == 0))
+ return(keyboard);
+
+ else
+ if (keyboard->composed_type == 1)
+ event.key.keysym.unicode = *keyboard->composed;
+ else
+ event.key.keysym.unicode = keysym2unicode(mnemo2keysym(mnemo, keyboard), keyboard);
+
+ event.type = SDL_KEYDOWN;
+ SDL_PushEvent(&event);
+ free(mnemo);
+ }
+ else
+ {
+ if (keyboard->composing == keyboard->layout->composemap)
+ {
+ printf("compose sequence resetted %d\n", (int)keyboard->composing);
+ set_key(NULL, &keyboard->keymodifiers.compose, 0);
+ keyboard->last_key_pressed = key;
+ }
+ else
+ {
+ set_key(key, &keyboard->keymodifiers.compose, 0);
+ printf("still composing %d\n", (int)keyboard->composing);
+ }
+ }
+
+ }
+ return(keyboard);
+}
+
+void osk_released(on_screen_keyboard *keyboard)
+{
+ osk_key *key;
+ key = keyboard->last_key_pressed;
+ if (key)
+ {
+ draw_key(*key, keyboard, 0);
+ free(key);
+ }
+ keyboard->last_key_pressed = NULL;
+
+}
+
+
+
+void osk_free(on_screen_keyboard *osk)
+{
+ /* FILLME */
+ printf("osk_free: FILLME.\n");
+
+
+
+}
+
+
+
+/* static void on_screen_keyboardd(void ) */
+/* { */
+/* int i; */
+/* if (key_board != NULL) */
+/* SDL_FreeSurface(key_board); */
+
+/* key_board = SDL_CreateRGBSurface(canvas->flags, */
+/* key_width * 19, */
+/* key_height * 3, */
+/* canvas->format->BitsPerPixel, */
+/* canvas->format->Rmask, */
+/* canvas->format->Gmask, */
+/* canvas->format->Bmask, 0); */
+/* key_board_color_r = 255; */
+/* key_board_color_g = 255; */
+/* key_board_color_b = 255; */
+
+/* SDL_FillRect(key_board, NULL, SDL_MapRGB(key_board->format, 255, 255, 255)); */
+/* if (keybd_position == 0) */
+/* { */
+/* initial_y = 400; */
+/* } */
+/* else */
+/* { */
+/* initial_y = 5; */
+/* } */
+/* apply_surface( initial_x, initial_y, key_board, screen, NULL); */
+
+/* keybd_prepare(); */
+
+/* for (i = 1; i <= 15 ; i++) */
+/* button (i, initial_x + (key_width)*(i-1), initial_y); */
+
+/* for (i = 1; i <= 19; i++) */
+/* button (i+15, initial_x + (key_width)*(i-1), initial_y + key_height); */
+
+/* for (i = 1; i <= 19; i++) */
+/* button (i+34, initial_x + (key_width)*(i-1), initial_y + 2*key_height); */
+
+/* drawkeybd(); */
+
+/* keybd_finish(); */
+
+/* SDL_UpdateRect(screen, 0, 0, 640, 480); */
+
+/* /\* SDL_Delay(10); *\/ /\* FIXME: This should not be necessary! -bjk 2011.04.21 *\/ */
+
+/* keybd_flag = 1; */
+/* } */
+
+
+
+
+
+
+
+/* // Check whether current mouse position is within a rectangle */
+/* int regionhit(int x, int y, int w, int h) */
+/* { */
+/* if (uistate.mousex < x || */
+/* uistate.mousey < y || */
+/* uistate.mousex >= x + w || */
+/* uistate.mousey >= y + h) */
+/* return 0; */
+/* return 1; */
+/* } */
+
+
+
+
+/* void button(int id, int x, int y) */
+/* { */
+/* SDL_Rect dest,desti; */
+/* SDL_Surface *tmp_imgup; */
+/* SDL_Event event; */
+/* dest.x = x; */
+/* dest.y = y; */
+
+/* // Check whether the button should be hot */
+/* if (regionhit(x, y, 24, 24)) */
+/* { */
+/* uistate.hotitem = id; */
+
+/* if (uistate.activeitem == 0 && uistate.mousedown) */
+/* { */
+/* uistate.activeitem = id; */
+/* activeflag = 1; */
+/* } */
+/* } */
+
+/* // Render button */
+/* SDL_BlitSurface(img_btnsm_up, NULL, screen, &dest); */
+/* if (caps_flag % 2 != 0) */
+/* { */
+/* desti.x = initial_x; */
+/* desti.y = initial_y + key_height; */
+/* SDL_BlitSurface(img_btnsm_down, NULL, screen, &desti); */
+/* } */
+/* if (uistate.hotitem == id) */
+/* { */
+/* if (uistate.activeitem == id) */
+/* { */
+/* // Button is both 'hot' and 'active' */
+/* if (activeflag == 1) */
+/* { */
+/* ide = id; */
+/* gen_key_flag = 1; */
+/* activeflag = 0; */
+/* uistate.activeitem = 0; */
+/* } */
+/* SDL_BlitSurface(img_btnsm_down, NULL, screen, &dest); */
+/* } */
+/* else */
+/* { */
+/* // Button is merely 'hot' */
+/* SDL_BlitSurface(img_btnsm_down, NULL, screen, &dest); */
+/* } */
+/* } */
+/* else */
+/* { */
+/* // button is not hot, but it may be active */
+/* SDL_BlitSurface(img_btnsm_up, NULL, screen, &dest); */
+/* } */
+
+/* if (gen_key_flag == 1) */
+/* { */
+/* int i,j; */
+/* gen_key_flag = 0; */
+/* enter_flag = 0; */
+/* SDL_EnableUNICODE(1); */
+/* // printf("\n entered here %d th time \n", k); */
+/* // k++; */
+/* if (ide == 1) */
+/* { */
+/* event.key.keysym.sym = SDLK_ESCAPE; */
+/* event.key.keysym.mod = KMOD_NONE; */
+/* event.key.keysym.unicode = 27; */
+
+/* } */
+/* else if (ide == 2) */
+/* { */
+/* event.key.keysym.sym = SDLK_BACKQUOTE; */
+/* event.key.keysym.mod = KMOD_NONE; */
+/* event.key.keysym.unicode = 96; */
+/* } */
+
+
+//....................................................
+
+/* if (enter_flag == 0) */
+/* { */
+
+ /* event.key.type=SDL_KEYDOWN; */
+ /* SDL_PushEvent(&event); */
+ /* event.key.type=SDL_KEYUP; */
+ /* SDL_PushEvent(&event); */
+
+
+/* } */
+/* } */
+/* } */
+