Onscreen keyboard for Win32

This commit is contained in:
Pere Pujal i Carabantes 2012-03-21 20:34:07 +00:00
parent 5db75e7a50
commit 50b0e70eac
3 changed files with 139 additions and 102 deletions

View file

@ -88,7 +88,7 @@ PNG:=$(if $(PNG),$(PNG),$(call linktest,-lpng12,))
FRIBIDI_LIB:=$(shell $(PKG_CONFIG) --libs fribidi) FRIBIDI_LIB:=$(shell $(PKG_CONFIG) --libs fribidi)
FRIBIDI_CFLAGS:=$(shell $(PKG_CONFIG) --cflags fribidi) FRIBIDI_CFLAGS:=$(shell $(PKG_CONFIG) --cflags fribidi)
windows_ARCH_LINKS:=-lintl $(PNG) -lzdll -lwinspool -lshlwapi $(FRIBIDI_LIB) windows_ARCH_LINKS:=-lintl $(PNG) -lzdll -lwinspool -lshlwapi $(FRIBIDI_LIB) -liconv
osx_ARCH_LINKS:=$(PAPER_LIB) $(FRIBIDI_LIB) osx_ARCH_LINKS:=$(PAPER_LIB) $(FRIBIDI_LIB)
beos_ARCH_LINKS:="-lintl $(PNG) -lz -lbe -lnetwork -liconv $(FRIBIDI_LIB) $(PAPER_LIB) -lstdc++" beos_ARCH_LINKS:="-lintl $(PNG) -lz -lbe -lnetwork -liconv $(FRIBIDI_LIB) $(PAPER_LIB) -lstdc++"
linux_ARCH_LINKS:=$(PAPER_LIB) $(FRIBIDI_LIB) linux_ARCH_LINKS:=$(PAPER_LIB) $(FRIBIDI_LIB)

View file

@ -13,7 +13,7 @@ static void load_keymap(osk_layout *layout, char * keymap_name);
static void load_composemap(osk_layout *layout, char * composemap_name); static void load_composemap(osk_layout *layout, char * composemap_name);
static int is_blank_or_comment(char *line); static int is_blank_or_comment(char *line);
static int isw_blank_or_comment(wchar_t *line); /* static int isw_blank_or_comment(wchar_t *line); */
static void keybd_prepare(on_screen_keyboard *keyboard); static void keybd_prepare(on_screen_keyboard *keyboard);
@ -32,7 +32,35 @@ static void print_composemap(osk_composenode *composemap, char * sp);
#endif #endif
#ifdef WIN32 #ifdef WIN32
#include <iconv.h>
#define wcstok(line, delim, pointer) wcstok(line, delim) #define wcstok(line, delim, pointer) wcstok(line, delim)
#define strtok_r(line, delim, pointer) strtok(line, delim)
static void mtw(wchar_t * wtok, char * tok);
static void mtw(wchar_t * wtok, char * tok)
{
/* workaround using iconv to get a functionallity somewhat approximate as mbstowcs() */
Uint16 *ui16;
ui16 = malloc(255);
char *wrptr = (char *) ui16;
size_t n, in, out;
iconv_t trans;
wchar_t * wch;
n = 255;
in = 250;
out = 250;
wch =malloc(255);
trans = iconv_open("WCHAR_T", "UTF-8");
iconv(trans, (const char **) &tok, &in, &wrptr, &out);
*((wchar_t *) wrptr) = L'\0';
swprintf(wtok, L"%ls", ui16);
free(ui16);
iconv_close(trans);
}
#define mbstowcs(wtok, tok, size) mtw(wtok, tok)
#endif #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 *button_nav, SDL_Surface *button_hold, int disable_change) 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 *button_nav, SDL_Surface *button_hold, int disable_change)
@ -224,7 +252,7 @@ void load_hlayout(osk_layout *layout, char * hlayout_name)
char *filename; char *filename;
char *line; char *line;
char *key, *fontpath; char *key, *fontpath;
wchar_t *plain_label, *top_label, *altgr_label, *shift_altgr_label; char *plain_label, *top_label, *altgr_label, *shift_altgr_label;
FILE * fi; FILE * fi;
key_number = line_number = 0; key_number = line_number = 0;
@ -355,7 +383,7 @@ void load_hlayout(osk_layout *layout, char * hlayout_name)
shift_altgr_label = malloc(64); shift_altgr_label = malloc(64);
sscanf(line, sscanf(line,
"%s %i %i.%i %ls %ls %ls %ls %i", "%s %i %i.%i %s %s %s %s %i",
key, key,
&keycode, &keycode,
&key_width, &key_width,
@ -506,23 +534,28 @@ void load_keymap(osk_layout *layout, char * keymap_name)
} }
/* Scans a line of keysyms and result and classifies them. */ /* 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) static void gettokens(char * line, char * delim, char ** pointer, osk_composenode *composenode, osk_layout *layout)
{ {
int i; int i;
wchar_t *tok; char *tok;
wchar_t * result; wchar_t *result, *wtok;
osk_composenode *auxnode; osk_composenode *auxnode;
wtok=malloc(255);
tok = strdup(strtok_r(line, delim, pointer));
tok = wcsdup(wcstok(line, delim, pointer));
if(!tok) if(!tok)
return; return;
if (tok[0] == ':') /* End of precompose keysyms, next will be the result in UTF-8. */
if (tok[0] == L':') /* End of precompose keysyms, next will be the result in unicode. */
{ {
result = wcsdup(wcstok(line, L": \"\t", pointer)); tok = strdup(strtok_r(line, ": \"\t", pointer));
// printf("result %ls\n", result);
composenode->result = result; mbstowcs(wtok, tok, 255);
result = wcsdup(wtok);
/* printf("->%ls<-\n", wtok); */
free(wtok);
free(tok); free(tok);
composenode->result = result;
return; return;
} }
else else
@ -533,26 +566,32 @@ static void gettokens(wchar_t * line, wchar_t * delim, wchar_t ** pointer, osk_c
auxnode = malloc(sizeof(osk_composenode)); auxnode = malloc(sizeof(osk_composenode));
composenode->childs = malloc(sizeof(osk_composenode *)); composenode->childs = malloc(sizeof(osk_composenode *));
composenode->childs[0] = auxnode; composenode->childs[0] = auxnode;
composenode->childs[0]->keysym = tok; mbstowcs(wtok, tok, 255);
composenode->childs[0]->keysym = wcsdup(wtok);
composenode->childs[0]->result = NULL; composenode->childs[0]->result = NULL;
composenode->childs[0]->size = 0; composenode->childs[0]->size = 0;
// printf("size %d, keysym %ls => ", composenode->size, composenode->childs[0]->keysym); /* printf("size %d, keysym %ls => ", composenode->size, composenode->childs[0]->keysym); */
gettokens(NULL, delim, pointer, composenode->childs[0], layout); gettokens(NULL, delim, pointer, composenode->childs[0], layout);
free(wtok);
free(tok);
return; return;
} }
else else
{ {
for (i = 0; i < composenode->size; i++) for (i = 0; i < composenode->size; i++)
{ {
if(wcscmp(composenode->childs[i]->keysym, tok) == 0) mbstowcs(wtok, tok, 255);
if(wcscmp(composenode->childs[i]->keysym, wtok) == 0)
{ {
// printf("Size %d, keysym %ls =>", composenode->size, composenode->childs[i]->keysym); /* printf("Size %d, keysym %ls =>", composenode->size, composenode->childs[i]->keysym); */
gettokens(NULL, delim, pointer, composenode->childs[i], layout); gettokens(NULL, delim, pointer, composenode->childs[i], layout);
free(tok); free(tok);
free(wtok);
return; return;
} }
} }
@ -561,14 +600,14 @@ static void gettokens(wchar_t * line, wchar_t * delim, wchar_t ** pointer, osk_c
composenode->size = composenode->size + 1; composenode->size = composenode->size + 1;
composenode->childs = realloc(composenode->childs,composenode->size * sizeof(osk_composenode *)); composenode->childs = realloc(composenode->childs,composenode->size * sizeof(osk_composenode *));
mbstowcs(wtok, tok, 255);
auxnode = malloc(sizeof(osk_composenode)); auxnode = malloc(sizeof(osk_composenode));
composenode->childs[composenode->size - 1] = 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]->keysym = wtok;
composenode->childs[composenode->size - 1]->result = NULL; composenode->childs[composenode->size - 1]->result = NULL;
composenode->childs[composenode->size - 1]->size = 0; composenode->childs[composenode->size - 1]->size = 0;
// printf("size %d, keysym %ls =>", composenode->size, composenode->childs[composenode->size - 1]->keysym); /* printf("size %d, keysym %ls =>", composenode->size, composenode->childs[composenode->size - 1]->keysym); */
gettokens(NULL, delim, pointer, composenode->childs[composenode->size - 1], layout); gettokens(NULL, delim, pointer, composenode->childs[composenode->size - 1], layout);
return; return;
@ -582,8 +621,8 @@ static void gettokens(wchar_t * line, wchar_t * delim, wchar_t ** pointer, osk_c
static void load_composemap(osk_layout *layout, char * composemap_name) static void load_composemap(osk_layout *layout, char * composemap_name)
{ {
char *filename; char *filename;
wchar_t **pointer; char **pointer;
wchar_t *line; char *line;
FILE * fi; FILE * fi;
pointer = malloc(sizeof(wchar_t *)); pointer = malloc(sizeof(wchar_t *));
@ -613,16 +652,16 @@ static void load_composemap(osk_layout *layout, char * composemap_name)
layout->composemap[0].result = NULL; layout->composemap[0].result = NULL;
layout->composemap->size = 0; layout->composemap->size = 0;
line = malloc(1024*sizeof(wchar_t)); line = malloc(1024*sizeof(char));
while (!feof(fi)) while (!feof(fi))
{ {
fgetws(line, 1023, fi); fgets(line, 1023, fi);
if (isw_blank_or_comment(line)) if (is_blank_or_comment(line))
continue; continue;
gettokens(line, (wchar_t *) L">< \t", pointer, layout->composemap, layout); gettokens(line, (char *) ">< \t", pointer, layout->composemap, layout);
} }
fclose(fi); fclose(fi);
@ -734,17 +773,17 @@ static void load_keysymdefs(osk_layout *layout, char * keysymdefs_name)
free(line); free(line);
} }
/* Return the mnemonic string of a x keysym as defined in the source of xorg in keysymdef.h */ /* /\* 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) /* static char * keysym2mnemo(int keysym, on_screen_keyboard * keyboard) */
{ /* { */
unsigned int i; /* unsigned int i; */
for (i = 0; i < keyboard->layout->sizeofkeysymdefs ;i++) /* for (i = 0; i < keyboard->layout->sizeofkeysymdefs ;i++) */
if (keysym == keyboard->layout->keysymdefs[i].keysym) /* if (keysym == keyboard->layout->keysymdefs[i].keysym) */
return(keyboard->layout->keysymdefs[i].mnemo); /* return(keyboard->layout->keysymdefs[i].mnemo); */
/* For the purpose of onscreen keyboard we don't need the conversion to strings in the form U0000 */ /* /\* For the purpose of onscreen keyboard we don't need the conversion to strings in the form U0000 *\/ */
return(NULL); /* return(NULL); */
} /* } */
/* Returns the x keysym corresponding to a mnemonic string */ /* Returns the x keysym corresponding to a mnemonic string */
static int mnemo2keysym(char * mnemo, on_screen_keyboard * keyboard) static int mnemo2keysym(char * mnemo, on_screen_keyboard * keyboard)
@ -885,24 +924,24 @@ static int is_blank_or_comment(char *line)
} }
static int isw_blank_or_comment(wchar_t *line) /* static int isw_blank_or_comment(wchar_t *line) */
{ /* { */
int i; /* int i; */
i = 0; /* i = 0; */
if (wcslen(line) == 0) /* if (wcslen(line) == 0) */
return 0; /* return 0; */
while (line[i] != L'\n') /* while (line[i] != L'\n') */
{ /* { */
if (line[i] == L'#') /* if (line[i] == L'#') */
return 1; /* return 1; */
else if (line[i] == L' ' || line[i] == L'\t') /* else if (line[i] == L' ' || line[i] == L'\t') */
i++; /* i++; */
else /* else */
return 0; /* return 0; */
} /* } */
return 1; /* return 1; */
} /* } */
/* Fixme: Is it safe to supose that if a font is loaded at one size, it will be loaded at any size? */ /* Fixme: Is it safe to supose that if a font is loaded at one size, it will be loaded at any size? */
@ -979,29 +1018,29 @@ static void apply_surface (int x, int y, SDL_Surface *source, SDL_Surface *desti
} }
/* NOTE: This is a duplicate of wcstou16 in tuxpaint.c /* /\* NOTE: This is a duplicate of wcstou16 in tuxpaint.c */
This conversion is required on platforms where Uint16 doesn't match wchar_t. /* 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. /* 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. /* 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 ... */ /* I guess wchar_t is really only suitable for internal use ... *\/ */
static Uint16 *wcstou16(const wchar_t * str) /* static Uint16 *wcstou16(const wchar_t * str) */
{ /* { */
unsigned int i, len = wcslen(str); /* unsigned int i, len = wcslen(str); */
Uint16 *res = malloc((len + 1) * sizeof(Uint16)); /* Uint16 *res = malloc((len + 1) * sizeof(Uint16)); */
for (i = 0; i < len + 1; ++i) /* for (i = 0; i < len + 1; ++i) */
{ /* { */
/* This is a bodge, but it seems unlikely that a case-conversion /* /\* This is a bodge, but it seems unlikely that a case-conversion */
will cause a change from one utf16 character into two.... /* will cause a change from one utf16 character into two.... */
(though at least UTF-8 suffers from this problem) */ /* (though at least UTF-8 suffers from this problem) *\/ */
// FIXME: mangles non-BMP characters rather than using UTF-16 surrogates! /* // FIXME: mangles non-BMP characters rather than using UTF-16 surrogates! */
res[i] = (Uint16) str[i]; /* res[i] = (Uint16) str[i]; */
} /* } */
return res; /* return res; */
} /* } */
/* Stretches a button from the middle, keeping the extrems intact */ /* Stretches a button from the middle, keeping the extrems intact */
static SDL_Surface * stretch_surface(SDL_Surface * orig, int width) static SDL_Surface * stretch_surface(SDL_Surface * orig, int width)
@ -1070,7 +1109,7 @@ static void draw_keyboard(on_screen_keyboard *keyboard)
float key_width; float key_width;
key_width = keyboard->button_up->w; key_width = keyboard->button_up->w;
key_height = keyboard->button_up->h; key_height = keyboard->button_up->h;
printf("dkbd\n");
accumulated_height = 0; accumulated_height = 0;
for (j = 0; j < keyboard->layout->height; j++) for (j = 0; j < keyboard->layout->height; j++)
@ -1105,7 +1144,7 @@ static void draw_key(osk_key key, on_screen_keyboard * keyboard, int hot)
return; return;
text = malloc(255); text = malloc(255);
snprintf(text, 6,"%ls", key.plain_label); snprintf(text, 6,"%s", key.plain_label);
if( strncmp("NULL", text, 4) != 0 && key.keycode != 0) if( strncmp("NULL", text, 4) != 0 && key.keycode != 0)
@ -1143,10 +1182,9 @@ static void draw_key(osk_key key, on_screen_keyboard * keyboard, int hot)
/* FIXME: TODO draw top and bottom_right (altgr) labels */ /* FIXME: TODO draw top and bottom_right (altgr) labels */
static void label_key(osk_key key, on_screen_keyboard *keyboard) static void label_key(osk_key key, on_screen_keyboard *keyboard)
{ {
Uint16 *ustr;
SDL_Surface *messager; SDL_Surface *messager;
int modstate; int modstate;
wchar_t *text; char *text;
/* To remove a warning... */ /* To remove a warning... */
text = NULL; text = NULL;
@ -1156,24 +1194,25 @@ static void label_key(osk_key key, on_screen_keyboard *keyboard)
/* FIXME There MUST be a simpler way to do this. Pere 2011/8/3 */ /* FIXME There MUST be a simpler way to do this. Pere 2011/8/3 */
/* First the plain ones */ /* First the plain ones */
if (modstate == KMOD_NONE || (modstate == (KMOD_NONE | KMOD_LALT))) if (modstate == KMOD_NONE || (modstate == (KMOD_NONE | KMOD_LALT)))
text = wcsdup(key.plain_label); text=strdup(key.plain_label);
else if (modstate == KMOD_SHIFT) else if (modstate == KMOD_SHIFT)
{ {
text = wcsdup(key.top_label); text = strdup(key.top_label);
} }
else if (modstate == KMOD_RALT) else if (modstate == KMOD_RALT)
{ {
text = wcsdup(key.altgr_label); text = strdup(key.altgr_label);
} }
else if (modstate == KMOD_CAPS) else if (modstate == KMOD_CAPS)
{ {
if (key.shiftcaps == 1) if (key.shiftcaps == 1)
text = wcsdup(key.top_label); text = strdup(key.top_label);
else else
text = wcsdup(key.plain_label); text = strdup(key.plain_label);
} }
/* Now the combined ones */ /* Now the combined ones */
@ -1182,38 +1221,36 @@ static void label_key(osk_key key, on_screen_keyboard *keyboard)
if (modstate & KMOD_CAPS) if (modstate & KMOD_CAPS)
{ {
if (key.shiftcaps) if (key.shiftcaps)
text = wcsdup(key.altgr_label); text = strdup(key.altgr_label);
else else
text = wcsdup(key.shift_altgr_label); text = strdup(key.shift_altgr_label);
} }
else else
{ {
text = wcsdup(key.shift_altgr_label); text = strdup(key.shift_altgr_label);
} }
} }
else if (modstate & KMOD_RALT && modstate & KMOD_CAPS && !(modstate & KMOD_SHIFT)) else if (modstate & KMOD_RALT && modstate & KMOD_CAPS && !(modstate & KMOD_SHIFT))
{ {
if (key.shiftcaps) if (key.shiftcaps)
text = wcsdup(key.shift_altgr_label); text = strdup(key.shift_altgr_label);
else else
text = wcsdup(key.altgr_label); text = strdup(key.altgr_label);
} }
else if (modstate & KMOD_SHIFT && modstate & KMOD_CAPS) else if (modstate & KMOD_SHIFT && modstate & KMOD_CAPS)
{ {
if (key.shiftcaps == 1) if (key.shiftcaps == 1)
text = wcsdup(key.plain_label); text = strdup(key.plain_label);
else else
text = wcsdup(key.top_label); text = strdup(key.top_label);
} }
if( wcsncmp(L"SPACE", text, 5) != 0 && wcsncmp(L"NULL", text, 4) != 0) if( strncmp("SPACE", text, 5) != 0 && strncmp("NULL", text, 4) != 0)
{ {
ustr = wcstou16(text); messager = TTF_RenderUTF8_Blended(osk_fonty, text, keyboard->layout->fgcolor);
messager = TTF_RenderUNICODE_Blended(osk_fonty, ustr, keyboard->layout->fgcolor);
free(ustr);
apply_surface( key.x + 5, key.y, messager, keyboard->surface, NULL); apply_surface( key.x + 5, key.y, messager, keyboard->surface, NULL);
SDL_FreeSurface(messager); SDL_FreeSurface(messager);
} }
@ -1275,15 +1312,15 @@ static void set_key(osk_key *orig, osk_key *dest, int firsttime)
if (dest->plain_label != NULL) if (dest->plain_label != NULL)
free(dest->plain_label); free(dest->plain_label);
dest->plain_label = wcsdup(orig->plain_label); dest->plain_label = strdup(orig->plain_label);
if (dest->top_label != NULL) if (dest->top_label != NULL)
free(dest->top_label); free(dest->top_label);
dest->top_label = wcsdup(orig->top_label); dest->top_label = strdup(orig->top_label);
if (dest->altgr_label != NULL) if (dest->altgr_label != NULL)
free(dest->altgr_label); free(dest->altgr_label);
dest->altgr_label = wcsdup(orig->altgr_label); dest->altgr_label = strdup(orig->altgr_label);
dest->shiftcaps = orig->shiftcaps; dest->shiftcaps = orig->shiftcaps;
} }
@ -1605,7 +1642,7 @@ struct osk_keyboard * osk_clicked(on_screen_keyboard *keyboard, int x, int y)
strlen(keysym)+1, strlen(keysym)+1,
NULL); NULL);
printf("wkeysym %ls %i\n\n", wkeysym, wcslen(wkeysym)); printf("wkeysym %ls %i\n\n", wkeysym, (int)wcslen(wkeysym));
get_composed_keysym(keyboard, keyboard->composing, wkeysym); get_composed_keysym(keyboard, keyboard->composing, wkeysym);
@ -1654,7 +1691,7 @@ struct osk_keyboard * osk_clicked(on_screen_keyboard *keyboard, int x, int y)
{ {
if (keyboard->composing == keyboard->layout->composemap) if (keyboard->composing == keyboard->layout->composemap)
{ {
printf("compose sequence resetted %d\n", (int)keyboard->composing); printf("compose sequence resetted\n");
set_key(NULL, &keyboard->keymodifiers.compose, 0); set_key(NULL, &keyboard->keymodifiers.compose, 0);
keyboard->last_key_pressed = key; keyboard->last_key_pressed = key;
clear_dead_sticks(keyboard); clear_dead_sticks(keyboard);
@ -1662,7 +1699,7 @@ struct osk_keyboard * osk_clicked(on_screen_keyboard *keyboard, int x, int y)
else else
{ {
set_key(key, &keyboard->keymodifiers.compose, 0); set_key(key, &keyboard->keymodifiers.compose, 0);
printf("still composing %d\n", (int)keyboard->composing); printf("still composing\n");
set_dead_sticks(key, keyboard); set_dead_sticks(key, keyboard);
/* Fixme: Would be nice if we can highlight next available-to-compose keys, but how? */ /* Fixme: Would be nice if we can highlight next available-to-compose keys, but how? */
} }

View file

@ -41,10 +41,10 @@ typedef struct osk_key
int x; int x;
int y; int y;
float width; /* The width in buttons */ float width; /* The width in buttons */
wchar_t *plain_label; /* The text that will show the key */ char *plain_label; /* The text that will show the key */
wchar_t *top_label; /* The text that will show the key above the plain label. */ char *top_label; /* The text that will show the key above the plain label. */
wchar_t *altgr_label; /* The text that will show the key at the right of the plain label */ char *altgr_label; /* The text that will show the key at the right of the plain label */
wchar_t *shift_altgr_label; /* The text that will show the key when shift and altgr are activeted */ char *shift_altgr_label; /* The text that will show the key when shift and altgr are activated */
int shiftcaps; /* If the value of the key should be shifted when capslock is active */ int shiftcaps; /* If the value of the key should be shifted when capslock is active */
int stick; /* If the key currently affects the others */ int stick; /* If the key currently affects the others */
} osk_key; } osk_key;