kernel32: Rewrote the locale matching to match more elements and to support Windows-format locale names.
Added implementation for LocaleNameToLCID and LCIDToLocaleName.
This commit is contained in:
parent
241336c749
commit
123b6fec22
|
@ -130,20 +130,30 @@ static const struct charset_entry
|
|||
{ "UTF8", CP_UTF8 }
|
||||
};
|
||||
|
||||
#define NLS_MAX_LANGUAGES 20
|
||||
typedef struct {
|
||||
WCHAR lang[128];
|
||||
WCHAR country[4];
|
||||
LANGID found_lang_id[NLS_MAX_LANGUAGES];
|
||||
int n_found;
|
||||
} LANG_FIND_DATA;
|
||||
|
||||
|
||||
/* copy Unicode string to Ascii without using codepages */
|
||||
static inline void strcpyWtoA( char *dst, const WCHAR *src )
|
||||
struct locale_name
|
||||
{
|
||||
while ((*dst++ = *src++));
|
||||
}
|
||||
WCHAR win_name[128]; /* Windows name ("en-US") */
|
||||
WCHAR lang[128]; /* language ("en") (note: buffer contains the other strings too) */
|
||||
WCHAR *country; /* country ("US") */
|
||||
WCHAR *charset; /* charset ("UTF-8") for Unix format only */
|
||||
WCHAR *script; /* script ("Latn") for Windows format only */
|
||||
WCHAR *modifier; /* modifier or sort order */
|
||||
LCID lcid; /* corresponding LCID */
|
||||
int matches; /* number of elements matching LCID (0..4) */
|
||||
UINT codepage; /* codepage corresponding to charset */
|
||||
};
|
||||
|
||||
/* locale ids corresponding to the various Unix locale parameters */
|
||||
static LCID lcid_LC_COLLATE;
|
||||
static LCID lcid_LC_CTYPE;
|
||||
static LCID lcid_LC_MESSAGES;
|
||||
static LCID lcid_LC_MONETARY;
|
||||
static LCID lcid_LC_NUMERIC;
|
||||
static LCID lcid_LC_TIME;
|
||||
static LCID lcid_LC_PAPER;
|
||||
static LCID lcid_LC_MEASUREMENT;
|
||||
static LCID lcid_LC_TELEPHONE;
|
||||
|
||||
/* Copy Ascii string to Unicode without using codepages */
|
||||
static inline void strcpynAtoW( WCHAR *dst, const char *src, size_t n )
|
||||
|
@ -156,20 +166,6 @@ static inline void strcpynAtoW( WCHAR *dst, const char *src, size_t n )
|
|||
if (n) *dst = 0;
|
||||
}
|
||||
|
||||
/* return a printable string for a language id */
|
||||
static const char *debugstr_lang( LANGID lang )
|
||||
{
|
||||
WCHAR langW[4], countryW[4];
|
||||
char buffer[8];
|
||||
LCID lcid = MAKELCID( lang, SORT_DEFAULT );
|
||||
|
||||
GetLocaleInfoW(lcid, LOCALE_SISO639LANGNAME|LOCALE_NOUSEROVERRIDE, langW, sizeof(langW)/sizeof(WCHAR));
|
||||
GetLocaleInfoW(lcid, LOCALE_SISO3166CTRYNAME|LOCALE_NOUSEROVERRIDE, countryW, sizeof(countryW)/sizeof(WCHAR));
|
||||
strcpyWtoA( buffer, langW );
|
||||
strcat( buffer, "_" );
|
||||
strcpyWtoA( buffer + strlen(buffer), countryW );
|
||||
return wine_dbg_sprintf( "%s", buffer );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* get_lcid_codepage
|
||||
|
@ -220,6 +216,195 @@ static const union cptable *get_codepage_table( unsigned int codepage )
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* charset_cmp (internal)
|
||||
*/
|
||||
static int charset_cmp( const void *name, const void *entry )
|
||||
{
|
||||
const struct charset_entry *charset = (const struct charset_entry *)entry;
|
||||
return strcasecmp( (const char *)name, charset->charset_name );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* find_charset
|
||||
*/
|
||||
static UINT find_charset( const WCHAR *name )
|
||||
{
|
||||
const struct charset_entry *entry;
|
||||
char charset_name[16];
|
||||
size_t i, j;
|
||||
|
||||
/* remove punctuation characters from charset name */
|
||||
for (i = j = 0; name[i] && j < sizeof(charset_name)-1; i++)
|
||||
if (isalnum((unsigned char)name[i])) charset_name[j++] = name[i];
|
||||
charset_name[j] = 0;
|
||||
|
||||
entry = bsearch( charset_name, charset_names,
|
||||
sizeof(charset_names)/sizeof(charset_names[0]),
|
||||
sizeof(charset_names[0]), charset_cmp );
|
||||
if (entry) return entry->codepage;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* find_locale_id_callback
|
||||
*/
|
||||
static BOOL CALLBACK find_locale_id_callback( HMODULE hModule, LPCWSTR type,
|
||||
LPCWSTR name, WORD LangID, LPARAM lParam )
|
||||
{
|
||||
struct locale_name *data = (struct locale_name *)lParam;
|
||||
WCHAR buffer[128];
|
||||
int matches = 0;
|
||||
LCID lcid = MAKELCID( LangID, SORT_DEFAULT ); /* FIXME: handle sort order */
|
||||
|
||||
if (PRIMARYLANGID(LangID) == LANG_NEUTRAL) return TRUE; /* continue search */
|
||||
|
||||
/* first check exact name */
|
||||
if (data->win_name[0] &&
|
||||
GetLocaleInfoW( lcid, LOCALE_SNAME | LOCALE_NOUSEROVERRIDE,
|
||||
buffer, sizeof(buffer)/sizeof(WCHAR) ))
|
||||
{
|
||||
if (!strcmpW( data->win_name, buffer ))
|
||||
{
|
||||
matches = 4; /* everything matches */
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (!GetLocaleInfoW( lcid, LOCALE_SISO639LANGNAME | LOCALE_NOUSEROVERRIDE,
|
||||
buffer, sizeof(buffer)/sizeof(WCHAR) ))
|
||||
return TRUE;
|
||||
if (strcmpW( buffer, data->lang )) return TRUE;
|
||||
matches++; /* language name matched */
|
||||
|
||||
if (data->country)
|
||||
{
|
||||
if (GetLocaleInfoW( lcid, LOCALE_SISO3166CTRYNAME|LOCALE_NOUSEROVERRIDE,
|
||||
buffer, sizeof(buffer)/sizeof(WCHAR) ))
|
||||
{
|
||||
if (strcmpW( buffer, data->country )) goto done;
|
||||
matches++; /* country name matched */
|
||||
}
|
||||
}
|
||||
else /* match default language */
|
||||
{
|
||||
if (SUBLANGID(LangID) == SUBLANG_DEFAULT) matches++;
|
||||
}
|
||||
|
||||
if (data->codepage)
|
||||
{
|
||||
UINT unix_cp;
|
||||
if (GetLocaleInfoW( lcid, LOCALE_IDEFAULTUNIXCODEPAGE | LOCALE_RETURN_NUMBER,
|
||||
(LPWSTR)&unix_cp, sizeof(unix_cp)/sizeof(WCHAR) ))
|
||||
{
|
||||
if (unix_cp == data->codepage) matches++;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: check sort order */
|
||||
|
||||
done:
|
||||
if (matches > data->matches)
|
||||
{
|
||||
data->lcid = lcid;
|
||||
data->matches = matches;
|
||||
}
|
||||
return (data->matches < 4); /* no need to continue for perfect match */
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* parse_locale_name
|
||||
*
|
||||
* Parse a locale name into a struct locale_name, handling both Windows and Unix formats.
|
||||
* Unix format is: lang[_country][.charset][@modifier]
|
||||
* Windows format is: lang[-script][-country][_modifier]
|
||||
*/
|
||||
static void parse_locale_name( const WCHAR *str, struct locale_name *name )
|
||||
{
|
||||
static const WCHAR sepW[] = {'-','_','.','@'};
|
||||
static const WCHAR winsepW[] = {'-','_'};
|
||||
static const WCHAR posixW[] = {'P','O','S','I','X',0};
|
||||
static const WCHAR cW[] = {'C',0};
|
||||
static const WCHAR latinW[] = {'l','a','t','i','n',0};
|
||||
static const WCHAR latnW[] = {'-','L','a','t','n',0};
|
||||
WCHAR *p;
|
||||
|
||||
name->country = name->charset = name->script = name->modifier = NULL;
|
||||
name->lcid = MAKELCID( MAKELANGID(LANG_ENGLISH,SUBLANG_DEFAULT), SORT_DEFAULT );
|
||||
name->matches = 0;
|
||||
name->codepage = 0;
|
||||
name->win_name[0] = 0;
|
||||
lstrcpynW( name->lang, str, sizeof(name->lang)/sizeof(WCHAR) );
|
||||
|
||||
if (!(p = strpbrkW( name->lang, sepW )))
|
||||
{
|
||||
if (!strcmpW( name->lang, posixW ) || !strcmpW( name->lang, cW ))
|
||||
{
|
||||
name->matches = 4; /* perfect match for default English lcid */
|
||||
return;
|
||||
}
|
||||
strcpyW( name->win_name, name->lang );
|
||||
}
|
||||
else if (*p == '-') /* Windows format */
|
||||
{
|
||||
strcpyW( name->win_name, name->lang );
|
||||
*p++ = 0;
|
||||
name->country = p;
|
||||
if (!(p = strpbrkW( p, winsepW ))) goto done;
|
||||
if (*p == '-')
|
||||
{
|
||||
*p++ = 0;
|
||||
name->script = name->country;
|
||||
name->country = p;
|
||||
if (!(p = strpbrkW( p, winsepW ))) goto done;
|
||||
}
|
||||
*p++ = 0;
|
||||
name->modifier = p;
|
||||
}
|
||||
else /* Unix format */
|
||||
{
|
||||
if (*p == '_')
|
||||
{
|
||||
*p++ = 0;
|
||||
name->country = p;
|
||||
p = strpbrkW( p, sepW + 2 );
|
||||
}
|
||||
if (p && *p == '.')
|
||||
{
|
||||
*p++ = 0;
|
||||
name->charset = p;
|
||||
name->codepage = find_charset( name->charset );
|
||||
p = strchrW( p, '@' );
|
||||
}
|
||||
if (p)
|
||||
{
|
||||
*p++ = 0;
|
||||
name->modifier = p;
|
||||
}
|
||||
|
||||
/* rebuild a Windows name if possible */
|
||||
|
||||
if (name->charset) goto done; /* can't specify charset in Windows format */
|
||||
if (name->modifier && strcmpW( name->modifier, latinW ))
|
||||
goto done; /* only Latn script supported for now */
|
||||
strcpyW( name->win_name, name->lang );
|
||||
if (name->modifier) strcatW( name->win_name, latnW );
|
||||
if (name->country)
|
||||
{
|
||||
p = name->win_name + strlenW(name->win_name);
|
||||
*p++ = '-';
|
||||
strcpyW( p, name->country );
|
||||
}
|
||||
}
|
||||
done:
|
||||
EnumResourceLanguagesW( kernel32_handle, (LPCWSTR)RT_STRING, (LPCWSTR)LOCALE_ILANGUAGE,
|
||||
find_locale_id_callback, (LPARAM)name );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* create_registry_key
|
||||
*
|
||||
|
@ -348,217 +533,59 @@ void LOCALE_InitRegistry(void)
|
|||
|
||||
|
||||
/***********************************************************************
|
||||
* find_language_id_proc
|
||||
* setup_unix_locales
|
||||
*/
|
||||
static BOOL CALLBACK find_language_id_proc( HMODULE hModule, LPCWSTR type,
|
||||
LPCWSTR name, WORD LangID, LPARAM lParam )
|
||||
static UINT setup_unix_locales(void)
|
||||
{
|
||||
LANG_FIND_DATA *l_data = (LANG_FIND_DATA *)lParam;
|
||||
LCID lcid = MAKELCID(LangID, SORT_DEFAULT);
|
||||
WCHAR buf_language[128];
|
||||
WCHAR buf_country[128];
|
||||
WCHAR buf_en_language[128];
|
||||
struct locale_name locale_name;
|
||||
WCHAR buffer[128], ctype_buff[128];
|
||||
char *locale;
|
||||
UINT unix_cp = 0;
|
||||
|
||||
if(PRIMARYLANGID(LangID) == LANG_NEUTRAL)
|
||||
return TRUE; /* continue search */
|
||||
|
||||
buf_language[0] = 0;
|
||||
buf_country[0] = 0;
|
||||
|
||||
GetLocaleInfoW(lcid, LOCALE_SISO639LANGNAME|LOCALE_NOUSEROVERRIDE,
|
||||
buf_language, sizeof(buf_language)/sizeof(WCHAR));
|
||||
GetLocaleInfoW(lcid, LOCALE_SISO3166CTRYNAME|LOCALE_NOUSEROVERRIDE,
|
||||
buf_country, sizeof(buf_country)/sizeof(WCHAR));
|
||||
|
||||
if(l_data->lang[0] && !strcmpiW(l_data->lang, buf_language))
|
||||
if ((locale = setlocale( LC_CTYPE, NULL )))
|
||||
{
|
||||
if(l_data->country[0])
|
||||
{
|
||||
if(!strcmpiW(l_data->country, buf_country))
|
||||
{
|
||||
l_data->found_lang_id[0] = LangID;
|
||||
l_data->n_found = 1;
|
||||
TRACE("Found id %04X for lang %s country %s\n",
|
||||
LangID, debugstr_w(l_data->lang), debugstr_w(l_data->country));
|
||||
return FALSE; /* stop enumeration */
|
||||
}
|
||||
}
|
||||
else goto found; /* l_data->country not specified */
|
||||
strcpynAtoW( ctype_buff, locale, sizeof(ctype_buff)/sizeof(WCHAR) );
|
||||
parse_locale_name( ctype_buff, &locale_name );
|
||||
lcid_LC_CTYPE = locale_name.lcid;
|
||||
unix_cp = locale_name.codepage;
|
||||
}
|
||||
if (!lcid_LC_CTYPE) /* this one needs a default value */
|
||||
lcid_LC_CTYPE = MAKELCID( MAKELANGID(LANG_ENGLISH,SUBLANG_DEFAULT), SORT_DEFAULT );
|
||||
|
||||
/* Just in case, check LOCALE_SENGLANGUAGE too,
|
||||
* in hope that possible alias name might have that value.
|
||||
*/
|
||||
buf_en_language[0] = 0;
|
||||
GetLocaleInfoW(lcid, LOCALE_SENGLANGUAGE|LOCALE_NOUSEROVERRIDE,
|
||||
buf_en_language, sizeof(buf_en_language)/sizeof(WCHAR));
|
||||
TRACE( "got lcid %04x (%d matches) for LC_CTYPE=%s\n",
|
||||
locale_name.lcid, locale_name.matches, debugstr_a(locale) );
|
||||
|
||||
if(l_data->lang[0] && !strcmpiW(l_data->lang, buf_en_language)) goto found;
|
||||
return TRUE; /* not found, continue search */
|
||||
#define GET_UNIX_LOCALE(cat) do \
|
||||
if ((locale = setlocale( cat, NULL ))) \
|
||||
{ \
|
||||
strcpynAtoW( buffer, locale, sizeof(buffer)/sizeof(WCHAR) ); \
|
||||
if (!strcmpW( buffer, ctype_buff )) lcid_##cat = lcid_LC_CTYPE; \
|
||||
else { \
|
||||
parse_locale_name( buffer, &locale_name ); \
|
||||
lcid_##cat = locale_name.lcid; \
|
||||
TRACE( "got lcid %04x (%d matches) for " #cat "=%s\n", \
|
||||
locale_name.lcid, locale_name.matches, debugstr_a(locale) ); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
found:
|
||||
l_data->found_lang_id[l_data->n_found] = LangID;
|
||||
l_data->n_found++;
|
||||
TRACE("Found id %04X for lang %s\n", LangID, debugstr_w(l_data->lang));
|
||||
return (l_data->n_found < NLS_MAX_LANGUAGES); /* continue search, unless we have enough */
|
||||
}
|
||||
GET_UNIX_LOCALE( LC_COLLATE );
|
||||
GET_UNIX_LOCALE( LC_MESSAGES );
|
||||
GET_UNIX_LOCALE( LC_MONETARY );
|
||||
GET_UNIX_LOCALE( LC_NUMERIC );
|
||||
GET_UNIX_LOCALE( LC_TIME );
|
||||
#ifdef LC_PAPER
|
||||
GET_UNIX_LOCALE( LC_PAPER );
|
||||
#endif
|
||||
#ifdef LC_MEASUREMENT
|
||||
GET_UNIX_LOCALE( LC_MEASUREMENT );
|
||||
#endif
|
||||
#ifdef LC_TELEPHONE
|
||||
GET_UNIX_LOCALE( LC_TELEPHONE );
|
||||
#endif
|
||||
|
||||
#undef GET_UNIX_LOCALE
|
||||
|
||||
/***********************************************************************
|
||||
* get_language_id
|
||||
*
|
||||
* INPUT:
|
||||
* Lang: a string whose two first chars are the iso name of a language.
|
||||
* Country: a string whose two first chars are the iso name of country
|
||||
* Charset: a string defining the chosen charset encoding
|
||||
* Dialect: a string defining a variation of the locale
|
||||
*
|
||||
* all those values are from the standardized format of locale
|
||||
* name in unix which is: Lang[_Country][.Charset][@Dialect]
|
||||
*
|
||||
* RETURNS:
|
||||
* the numeric code of the language used by Windows
|
||||
*
|
||||
* FIXME: Charset and Dialect are not handled
|
||||
*/
|
||||
static LANGID get_language_id(LPCSTR Lang, LPCSTR Country, LPCSTR Charset, LPCSTR Dialect)
|
||||
{
|
||||
LANG_FIND_DATA l_data;
|
||||
|
||||
if(!Lang)
|
||||
{
|
||||
l_data.found_lang_id[0] = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
|
||||
goto END;
|
||||
}
|
||||
|
||||
l_data.n_found = 0;
|
||||
strcpynAtoW(l_data.lang, Lang, sizeof(l_data.lang)/sizeof(WCHAR));
|
||||
|
||||
if (Country) strcpynAtoW(l_data.country, Country, sizeof(l_data.country)/sizeof(WCHAR));
|
||||
else l_data.country[0] = 0;
|
||||
|
||||
EnumResourceLanguagesW(kernel32_handle, (LPCWSTR)RT_STRING, (LPCWSTR)LOCALE_ILANGUAGE,
|
||||
find_language_id_proc, (LPARAM)&l_data);
|
||||
|
||||
if (l_data.n_found == 1) goto END;
|
||||
|
||||
if(!l_data.n_found)
|
||||
{
|
||||
if(l_data.country[0])
|
||||
{
|
||||
/* retry without country name */
|
||||
l_data.country[0] = 0;
|
||||
EnumResourceLanguagesW(kernel32_handle, (LPCWSTR)RT_STRING, (LPCWSTR)LOCALE_ILANGUAGE,
|
||||
find_language_id_proc, (LONG_PTR)&l_data);
|
||||
if (!l_data.n_found)
|
||||
{
|
||||
MESSAGE("Warning: Language '%s_%s' was not recognized, defaulting to English.\n",
|
||||
Lang, Country);
|
||||
l_data.found_lang_id[0] = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
|
||||
}
|
||||
else MESSAGE("Warning: Language '%s_%s' was not recognized, defaulting to '%s'.\n",
|
||||
Lang, Country, debugstr_lang(l_data.found_lang_id[0]) );
|
||||
}
|
||||
else
|
||||
{
|
||||
MESSAGE("Warning: Language '%s' was not recognized, defaulting to English.\n", Lang);
|
||||
l_data.found_lang_id[0] = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
|
||||
if (Country && Country[0])
|
||||
MESSAGE("For language '%s_%s' several language ids were found:\n", Lang, Country);
|
||||
else
|
||||
MESSAGE("For language '%s' several language ids were found:\n", Lang);
|
||||
|
||||
/* print a list of languages with their description */
|
||||
for (i = 0; i < l_data.n_found; i++)
|
||||
{
|
||||
WCHAR buffW[128];
|
||||
char buffA[128];
|
||||
GetLocaleInfoW( MAKELCID( l_data.found_lang_id[i], SORT_DEFAULT ),
|
||||
LOCALE_SLANGUAGE|LOCALE_NOUSEROVERRIDE, buffW, sizeof(buffW)/sizeof(WCHAR));
|
||||
strcpyWtoA( buffA, buffW );
|
||||
MESSAGE( " %s (%04X) - %s\n", debugstr_lang(l_data.found_lang_id[i]),
|
||||
l_data.found_lang_id[i], buffA );
|
||||
}
|
||||
MESSAGE("Defaulting to '%s'. You should specify the exact language you want\n"
|
||||
"by defining your LANG environment variable like this: LANG=%s\n",
|
||||
debugstr_lang(l_data.found_lang_id[0]), debugstr_lang(l_data.found_lang_id[0]) );
|
||||
}
|
||||
END:
|
||||
TRACE("Returning %04X (%s)\n", l_data.found_lang_id[0], debugstr_lang(l_data.found_lang_id[0]));
|
||||
return l_data.found_lang_id[0];
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* charset_cmp (internal)
|
||||
*/
|
||||
static int charset_cmp( const void *name, const void *entry )
|
||||
{
|
||||
const struct charset_entry *charset = (const struct charset_entry *)entry;
|
||||
return strcasecmp( (const char *)name, charset->charset_name );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* get_env_lcid
|
||||
*/
|
||||
static LCID get_env_lcid( UINT *unix_cp, int category )
|
||||
{
|
||||
char *buf, *lang,*country,*charset,*dialect,*next;
|
||||
LCID ret = 0;
|
||||
|
||||
if ((lang = setlocale( category, NULL )) && *lang)
|
||||
{
|
||||
if (!strcmp(lang,"POSIX") || !strcmp(lang,"C")) goto done;
|
||||
|
||||
buf = RtlAllocateHeap( GetProcessHeap(), 0, strlen(lang) + 1 );
|
||||
strcpy( buf, lang );
|
||||
lang=buf;
|
||||
|
||||
do {
|
||||
next=strchr(lang,':'); if (next) *next++='\0';
|
||||
dialect=strchr(lang,'@'); if (dialect) *dialect++='\0';
|
||||
charset=strchr(lang,'.'); if (charset) *charset++='\0';
|
||||
country=strchr(lang,'_'); if (country) *country++='\0';
|
||||
|
||||
ret = get_language_id(lang, country, charset, dialect);
|
||||
if (ret && charset && unix_cp)
|
||||
{
|
||||
const struct charset_entry *entry;
|
||||
char charset_name[16];
|
||||
size_t i, j;
|
||||
|
||||
/* remove punctuation characters from charset name */
|
||||
for (i = j = 0; charset[i] && j < sizeof(charset_name)-1; i++)
|
||||
if (isalnum(charset[i])) charset_name[j++] = charset[i];
|
||||
charset_name[j] = 0;
|
||||
|
||||
entry = bsearch( charset_name, charset_names,
|
||||
sizeof(charset_names)/sizeof(charset_names[0]),
|
||||
sizeof(charset_names[0]), charset_cmp );
|
||||
if (entry)
|
||||
{
|
||||
*unix_cp = entry->codepage;
|
||||
TRACE("charset %s was mapped to cp %u\n", charset, *unix_cp);
|
||||
}
|
||||
else
|
||||
FIXME("charset %s was not recognized\n", charset);
|
||||
}
|
||||
lang=next;
|
||||
} while (lang && !ret);
|
||||
|
||||
if (!ret) MESSAGE("Warning: language '%s' not recognized, defaulting to English\n", buf);
|
||||
RtlFreeHeap( GetProcessHeap(), 0, buf );
|
||||
}
|
||||
|
||||
done:
|
||||
if (!ret) ret = MAKELCID( MAKELANGID(LANG_ENGLISH,SUBLANG_DEFAULT), SORT_DEFAULT) ;
|
||||
return ret;
|
||||
return unix_cp;
|
||||
}
|
||||
|
||||
|
||||
|
@ -673,6 +700,41 @@ LANGID WINAPI GetSystemDefaultUILanguage(void)
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* LocaleNameToLCID (KERNEL32.@)
|
||||
*/
|
||||
LCID WINAPI LocaleNameToLCID( LPCWSTR name, DWORD flags )
|
||||
{
|
||||
struct locale_name locale_name;
|
||||
|
||||
if (flags) FIXME( "unsupported flags %x\n", flags );
|
||||
|
||||
parse_locale_name( name, &locale_name );
|
||||
|
||||
TRACE( "found lcid %x for %s, matches %d\n",
|
||||
locale_name.lcid, debugstr_w(name), locale_name.matches );
|
||||
|
||||
if (!locale_name.matches)
|
||||
WARN( "locale %s not recognized, defaulting to English\n", debugstr_w(name) );
|
||||
else if (locale_name.matches == 1)
|
||||
WARN( "locale %s not recognized, defaulting to %s\n",
|
||||
debugstr_w(name), debugstr_w(locale_name.lang) );
|
||||
|
||||
return locale_name.lcid;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* LCIDToLocaleName (KERNEL32.@)
|
||||
*/
|
||||
INT WINAPI LCIDToLocaleName( LCID lcid, LPWSTR name, INT count, DWORD flags )
|
||||
{
|
||||
if (flags) FIXME( "unsupported flags %x\n", flags );
|
||||
|
||||
return GetLocaleInfoW( lcid, LOCALE_SNAME | LOCALE_NOUSEROVERRIDE, name, count );
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* get_locale_value_name
|
||||
*
|
||||
|
@ -2579,8 +2641,7 @@ void LOCALE_Init(void)
|
|||
extern void __wine_init_codepages( const union cptable *ansi_cp, const union cptable *oem_cp,
|
||||
const union cptable *unix_cp );
|
||||
|
||||
UINT ansi_cp = 1252, oem_cp = 437, mac_cp = 10000, unix_cp = ~0U;
|
||||
LCID lcid;
|
||||
UINT ansi_cp = 1252, oem_cp = 437, mac_cp = 10000, unix_cp;
|
||||
|
||||
#ifdef __APPLE__
|
||||
/* MacOS doesn't set the locale environment variables so we have to do it ourselves */
|
||||
|
@ -2597,23 +2658,20 @@ void LOCALE_Init(void)
|
|||
#endif
|
||||
setlocale( LC_ALL, "" );
|
||||
|
||||
lcid = get_env_lcid( NULL, LC_NUMERIC );
|
||||
NtSetDefaultLocale( TRUE, lcid );
|
||||
unix_cp = setup_unix_locales();
|
||||
if (!lcid_LC_MESSAGES) lcid_LC_MESSAGES = lcid_LC_CTYPE;
|
||||
NtSetDefaultUILanguage( LANGIDFROMLCID(lcid_LC_MESSAGES) );
|
||||
NtSetDefaultLocale( TRUE, lcid_LC_MESSAGES );
|
||||
NtSetDefaultLocale( FALSE, lcid_LC_CTYPE );
|
||||
|
||||
lcid = get_env_lcid( NULL, LC_MESSAGES );
|
||||
NtSetDefaultUILanguage( LANGIDFROMLCID(lcid) );
|
||||
|
||||
lcid = get_env_lcid( &unix_cp, LC_CTYPE );
|
||||
NtSetDefaultLocale( FALSE, lcid );
|
||||
|
||||
ansi_cp = get_lcid_codepage(lcid);
|
||||
GetLocaleInfoW( lcid, LOCALE_IDEFAULTMACCODEPAGE | LOCALE_RETURN_NUMBER,
|
||||
ansi_cp = get_lcid_codepage( LOCALE_USER_DEFAULT );
|
||||
GetLocaleInfoW( LOCALE_USER_DEFAULT, LOCALE_IDEFAULTMACCODEPAGE | LOCALE_RETURN_NUMBER,
|
||||
(LPWSTR)&mac_cp, sizeof(mac_cp)/sizeof(WCHAR) );
|
||||
GetLocaleInfoW( lcid, LOCALE_IDEFAULTCODEPAGE | LOCALE_RETURN_NUMBER,
|
||||
GetLocaleInfoW( LOCALE_USER_DEFAULT, LOCALE_IDEFAULTCODEPAGE | LOCALE_RETURN_NUMBER,
|
||||
(LPWSTR)&oem_cp, sizeof(oem_cp)/sizeof(WCHAR) );
|
||||
if (unix_cp == ~0U)
|
||||
GetLocaleInfoW( lcid, LOCALE_IDEFAULTUNIXCODEPAGE | LOCALE_RETURN_NUMBER,
|
||||
(LPWSTR)&unix_cp, sizeof(unix_cp)/sizeof(WCHAR) );
|
||||
if (!unix_cp)
|
||||
GetLocaleInfoW( LOCALE_USER_DEFAULT, LOCALE_IDEFAULTUNIXCODEPAGE | LOCALE_RETURN_NUMBER,
|
||||
(LPWSTR)&unix_cp, sizeof(unix_cp)/sizeof(WCHAR) );
|
||||
|
||||
if (!(ansi_cptable = wine_cp_get_table( ansi_cp )))
|
||||
ansi_cptable = wine_cp_get_table( 1252 );
|
||||
|
|
|
@ -259,6 +259,25 @@ extern "C" {
|
|||
#define LOCALE_FONTSIGNATURE 0x0058
|
||||
#define LOCALE_SISO639LANGNAME 0x0059
|
||||
#define LOCALE_SISO3166CTRYNAME 0x005A
|
||||
#define LOCALE_SNAME 0x005C
|
||||
#define LOCALE_SDURATION 0x005D
|
||||
#define LOCALE_SKEYBOARDSTOINSTALL 0x005E
|
||||
#define LOCALE_SSHORTESTDAYNAME1 0x0060
|
||||
#define LOCALE_SSHORTESTDAYNAME2 0x0061
|
||||
#define LOCALE_SSHORTESTDAYNAME3 0x0062
|
||||
#define LOCALE_SSHORTESTDAYNAME4 0x0063
|
||||
#define LOCALE_SSHORTESTDAYNAME5 0x0064
|
||||
#define LOCALE_SSHORTESTDAYNAME6 0x0065
|
||||
#define LOCALE_SSHORTESTDAYNAME7 0x0066
|
||||
#define LOCALE_SISO639LANGNAME2 0x0067
|
||||
#define LOCALE_SISO3166CTRYNAME2 0x0068
|
||||
#define LOCALE_SNAN 0x0069
|
||||
#define LOCALE_SPOSINFINITY 0x006A
|
||||
#define LOCALE_SNEGINFINITY 0x006B
|
||||
#define LOCALE_SSCRIPTS 0x006C
|
||||
#define LOCALE_SPARENT 0x006D
|
||||
#define LOCALE_SCONSOLEFALLBACKNAME 0x006E
|
||||
#define LOCALE_SLANGDISPLAYNAME 0x006F
|
||||
|
||||
#define LOCALE_IDEFAULTEBCDICCODEPAGE 0x1012
|
||||
#define LOCALE_IPAPERSIZE 0x100A
|
||||
|
@ -743,9 +762,11 @@ BOOL WINAPI IsDBCSLeadByteEx(UINT,BYTE);
|
|||
BOOL WINAPI IsValidCodePage(UINT);
|
||||
BOOL WINAPI IsValidLocale(LCID,DWORD);
|
||||
BOOL WINAPI IsValidLanguageGroup(LGRPID,DWORD);
|
||||
INT WINAPI LCIDToLocaleName(LCID,LPWSTR,INT,DWORD);
|
||||
INT WINAPI LCMapStringA(LCID,DWORD,LPCSTR,INT,LPSTR,INT);
|
||||
INT WINAPI LCMapStringW(LCID,DWORD,LPCWSTR,INT,LPWSTR,INT);
|
||||
#define LCMapString WINELIB_NAME_AW(LCMapString)
|
||||
LCID WINAPI LocaleNameToLCID(LPCWSTR,DWORD);
|
||||
INT WINAPI MultiByteToWideChar(UINT,DWORD,LPCSTR,INT,LPWSTR,INT);
|
||||
INT WINAPI SetCalendarInfoA(LCID,CALID,CALTYPE,LPCSTR);
|
||||
INT WINAPI SetCalendarInfoW(LCID,CALID,CALTYPE,LPCWSTR);
|
||||
|
|
Loading…
Reference in New Issue