libfreerdp-locale: refactoring of locale detection code

This commit is contained in:
Marc-André Moreau 2012-02-18 23:36:48 -05:00
parent 94900c7836
commit 0e861b1bcb
6 changed files with 81 additions and 54 deletions

View File

@ -34,14 +34,14 @@ struct rdp_keyboard_layout
};
typedef struct rdp_keyboard_layout rdpKeyboardLayout;
struct _virtualKey
struct _VIRTUAL_KEY
{
uint32 scancode; /* Windows "scan code", aka keycode in RDP */
boolean extended; /* Windows "extended" flag, boolean */
const char* name; /* Windows virtual key name */
const char* x_keyname; /* XKB keyname */
};
typedef struct _virtualKey virtualKey;
typedef struct _VIRTUAL_KEY VIRTUAL_KEY;
/* Mouse buttons */
@ -476,7 +476,7 @@ typedef struct _virtualKey virtualKey;
FREERDP_API uint32 freerdp_keyboard_init(uint32 keyboard_layout_id);
FREERDP_API rdpKeyboardLayout* freerdp_keyboard_get_layouts(uint32 types);
FREERDP_API const char* get_layout_name(uint32 keyboardLayoutID);
FREERDP_API const char* freerdp_keyboard_get_layout_name_from_id(uint32 keyboardLayoutID);
FREERDP_API uint32 freerdp_keyboard_get_scancode_from_keycode(uint32 keycode, boolean* extended);
FREERDP_API uint32 freerdp_keyboard_get_keycode_from_scancode(uint32 scancode, boolean extended);
FREERDP_API uint32 freerdp_keyboard_get_scancode_from_vkcode(uint32 vkcode, boolean* extended);

View File

@ -230,6 +230,6 @@
#define YORUBA 0x046A
#define ZULU 0x0435
FREERDP_API uint32 detect_keyboard_layout_from_locale();
FREERDP_API uint32 freerdp_detect_keyboard_layout_from_locale();
#endif /* __FREERDP_LOCALE_H */

View File

@ -45,7 +45,7 @@
#include "keyboard.h"
extern const virtualKey virtualKeyboard[258];
extern const VIRTUAL_KEY virtualKeyboard[258];
/*
* The actual mapping from X keycodes to RDP keycodes, initialized from xkb keycodes or similar.
@ -64,7 +64,7 @@ uint32 freerdp_detect_keyboard(uint32 keyboardLayoutID)
if (keyboardLayoutID == 0)
{
keyboardLayoutID = detect_keyboard_layout_from_locale();
keyboardLayoutID = freerdp_detect_keyboard_layout_from_locale();
DEBUG_KBD("detect_keyboard_layout_from_locale: %X", keyboardLayoutID);
}
@ -113,7 +113,7 @@ uint32 freerdp_keyboard_init_x11(uint32 keyboardLayoutId)
if (keyboardLayoutId == 0)
{
keyboardLayoutId = detect_keyboard_layout_from_locale();
keyboardLayoutId = freerdp_detect_keyboard_layout_from_locale();
DEBUG_KBD("using keyboard layout: %X", keyboardLayoutID);
}
@ -258,7 +258,7 @@ static int freerdp_keyboard_load_map(KeycodeToVkcode map, char* name)
break;
/* Load this key mapping in the keyboard mapping */
for(i = 0; i < sizeof(virtualKeyboard) / sizeof(virtualKey); i++)
for(i = 0; i < sizeof(virtualKeyboard) / sizeof(VIRTUAL_KEY); i++)
{
if (strcmp(vkcodeName, virtualKeyboard[i].name) == 0)
{

View File

@ -215,7 +215,7 @@ static const keyboardIME keyboardIMEs[] =
{ KBD_CHINESE_TRADITIONAL_ALPHANUMERIC, "romanime.ime", "Chinese (Traditional) - Alphanumeric" }
};
const virtualKey virtualKeyboard[] =
const VIRTUAL_KEY virtualKeyboard[] =
{
{ 0x00, 0, "" , NULL },
{ 0x00, 0, "VK_LBUTTON" , NULL },
@ -526,7 +526,7 @@ rdpKeyboardLayout* freerdp_keyboard_get_layouts(uint32 types)
return layouts;
}
const char* get_layout_name(uint32 keyboardLayoutID)
const char* freerdp_keyboard_get_layout_name_from_id(uint32 keyboardLayoutID)
{
int i;

View File

@ -23,7 +23,7 @@
#include "keyboard_x11.h"
#include <freerdp/locale/keyboard.h>
extern const virtualKey virtualKeyboard[258];
extern const VIRTUAL_KEY virtualKeyboard[258];
#include <X11/Xlib.h>
#include <X11/XKBlib.h>

View File

@ -24,20 +24,20 @@
#include <freerdp/locale/locale.h>
struct _locale
struct _SYSTEM_LOCALE
{
char language[4]; /* Two or three letter language code */
char country[10]; /* Two or three letter country code (Sometimes with Cyrl_ prefix) */
uint32 code; /* 32-bit unsigned integer corresponding to the locale */
};
typedef struct _locale locale;
typedef struct _SYSTEM_LOCALE SYSTEM_LOCALE;
/*
* Refer to MSDN article "Locale Identifier Constants and Strings":
* http://msdn.microsoft.com/en-us/library/ms776260.aspx
*/
static const locale locales[] =
static const SYSTEM_LOCALE SystemLocaleTable[] =
{
{ "af", "ZA", AFRIKAANS }, /* Afrikaans (South Africa) */
{ "sq", "AL", ALBANIAN }, /* Albanian (Albania) */
@ -241,15 +241,13 @@ static const locale locales[] =
};
typedef struct
struct _localeAndKeyboardLayout
{
/* Locale ID */
unsigned int locale;
uint32 locale; /* Locale ID */
uint32 keyboardLayouts[5]; /* array of associated keyboard layouts */
/* Array of associated keyboard layouts */
unsigned int keyboardLayouts[5];
} localeAndKeyboardLayout;
};
typedef struct _localeAndKeyboardLayout localeAndKeyboardLayout;
/* TODO: Use KBD_* defines instead of hardcoded values */
@ -416,76 +414,105 @@ static const localeAndKeyboardLayout defaultKeyboardLayouts[] =
{ XHOSA, { 0x00000409, 0x00000409, 0x0, 0x0, 0x0 } },
};
uint32 detect_keyboard_layout_from_locale()
boolean freerdp_get_system_language_and_country_codes(char* language, char* country)
{
int dot;
int i, j, k;
int underscore;
char language[4];
char country[10];
char* env_lang;
/* LANG = <language>_<country>.<encoding> */
char* envLang = getenv("LANG"); /* Get locale from environment variable LANG */
env_lang = getenv("LANG"); /* Get locale from environment variable LANG */
if (envLang == NULL)
return 0; /* LANG environment variable was not set */
if (env_lang == NULL)
return false; /* LANG environment variable was not set */
underscore = strcspn(envLang, "_");
underscore = strcspn(env_lang, "_");
if (underscore > 3)
return 0; /* The language name should not be more than 3 letters long */
{
return false; /* The language name should not be more than 3 letters long */
}
else
{
/* Get language code */
strncpy(language, envLang, underscore);
strncpy(language, env_lang, underscore);
language[underscore] = '\0';
}
/*
* There is always the special case of "C" or "POSIX" as locale name
* In this case, use a U.S. keyboard and a U.S. keyboard layout
*/
if ((strcmp(language, "C") == 0) || (strcmp(language, "POSIX") == 0))
return ENGLISH_UNITED_STATES; /* U.S. Keyboard Layout */
dot = strcspn(envLang, ".");
dot = strcspn(env_lang, ".");
/* Get country code */
if (dot > underscore)
{
strncpy(country, &envLang[underscore + 1], dot - underscore - 1);
strncpy(country, &env_lang[underscore + 1], dot - underscore - 1);
country[dot - underscore - 1] = '\0';
}
else
return 0; /* Invalid locale */
for (i = 0; i < sizeof(locales) / sizeof(locale); i++)
{
if ((strcmp(language, locales[i].language) == 0) && (strcmp(country, locales[i].country) == 0))
break;
return false; /* Invalid locale */
}
DEBUG_KBD("Found locale : %s_%s", locales[i].language, locales[i].country);
return true;
}
for (j = 0; j < sizeof(defaultKeyboardLayouts) / sizeof(localeAndKeyboardLayout); j++)
SYSTEM_LOCALE* freerdp_detect_system_locale()
{
int i;
char language[4];
char country[10];
SYSTEM_LOCALE* locale = NULL;
freerdp_get_system_language_and_country_codes(language, country);
for (i = 0; i < sizeof(SystemLocaleTable) / sizeof(SYSTEM_LOCALE); i++)
{
if (defaultKeyboardLayouts[j].locale == locales[i].code)
if ((strcmp(language, SystemLocaleTable[i].language) == 0) && (strcmp(country, SystemLocaleTable[i].country) == 0))
{
locale = (SYSTEM_LOCALE*) &SystemLocaleTable[i];
break;
}
}
return locale;
}
uint32 freerdp_detect_keyboard_layout_from_locale()
{
int i, j;
char language[4];
char country[10];
SYSTEM_LOCALE* locale;
freerdp_get_system_language_and_country_codes(language, country);
if ((strcmp(language, "C") == 0) || (strcmp(language, "POSIX") == 0))
return ENGLISH_UNITED_STATES; /* U.S. Keyboard Layout */
locale = freerdp_detect_system_locale();
if (locale == NULL)
return 0;
DEBUG_KBD("Found locale : %s_%s", locale.language, locale.country);
for (i = 0; i < sizeof(defaultKeyboardLayouts) / sizeof(localeAndKeyboardLayout); i++)
{
if (defaultKeyboardLayouts[i].locale == locale->code)
{
/* Locale found in list of default keyboard layouts */
for (k = 0; k < 5; k++)
for (j = 0; j < 5; j++)
{
if (defaultKeyboardLayouts[j].keyboardLayouts[k] == ENGLISH_UNITED_STATES)
if (defaultKeyboardLayouts[i].keyboardLayouts[j] == ENGLISH_UNITED_STATES)
{
continue; /* Skip, try to get a more localized keyboard layout */
}
else if (defaultKeyboardLayouts[j].keyboardLayouts[k] == 0)
else if (defaultKeyboardLayouts[i].keyboardLayouts[j] == 0)
{
break; /* No more keyboard layouts */
}
else
{
return defaultKeyboardLayouts[j].keyboardLayouts[k];
return defaultKeyboardLayouts[i].keyboardLayouts[j];
}
}
@ -494,7 +521,7 @@ uint32 detect_keyboard_layout_from_locale()
* other possible keyboard layout for the locale, we end up here with k > 1
*/
if (k >= 1)
if (j >= 1)
return ENGLISH_UNITED_STATES;
else
return 0;