/* * Locale functions * * Copyright 2004, 2019 Alexandre Julliard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include "config.h" #include "wine/port.h" #include #include #include #include #include "ntstatus.h" #define WIN32_NO_STATUS #include "ntdll_misc.h" #include "wine/unicode.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(nls); LCID user_lcid = 0, system_lcid = 0; static LANGID user_ui_language, system_ui_language; static const union cptable *unix_table; /* NULL if UTF8 */ #if !defined(__APPLE__) && !defined(__ANDROID__) /* these platforms always use UTF-8 */ /* charset to codepage map, sorted by name */ static const struct { const char *name; UINT cp; } charset_names[] = { { "ANSIX341968", 20127 }, { "BIG5", 950 }, { "BIG5HKSCS", 950 }, { "CP1250", 1250 }, { "CP1251", 1251 }, { "CP1252", 1252 }, { "CP1253", 1253 }, { "CP1254", 1254 }, { "CP1255", 1255 }, { "CP1256", 1256 }, { "CP1257", 1257 }, { "CP1258", 1258 }, { "CP932", 932 }, { "CP936", 936 }, { "CP949", 949 }, { "CP950", 950 }, { "EUCJP", 20932 }, { "EUCKR", 949 }, { "GB18030", 936 /* 54936 */ }, { "GB2312", 936 }, { "GBK", 936 }, { "IBM037", 37 }, { "IBM1026", 1026 }, { "IBM424", 424 }, { "IBM437", 437 }, { "IBM500", 500 }, { "IBM850", 850 }, { "IBM852", 852 }, { "IBM855", 855 }, { "IBM857", 857 }, { "IBM860", 860 }, { "IBM861", 861 }, { "IBM862", 862 }, { "IBM863", 863 }, { "IBM864", 864 }, { "IBM865", 865 }, { "IBM866", 866 }, { "IBM869", 869 }, { "IBM874", 874 }, { "IBM875", 875 }, { "ISO88591", 28591 }, { "ISO885910", 28600 }, { "ISO885911", 28601 }, { "ISO885913", 28603 }, { "ISO885914", 28604 }, { "ISO885915", 28605 }, { "ISO885916", 28606 }, { "ISO88592", 28592 }, { "ISO88593", 28593 }, { "ISO88594", 28594 }, { "ISO88595", 28595 }, { "ISO88596", 28596 }, { "ISO88597", 28597 }, { "ISO88598", 28598 }, { "ISO88599", 28599 }, { "KOI8R", 20866 }, { "KOI8U", 21866 }, { "TIS620", 28601 }, { "UTF8", CP_UTF8 } }; void init_unix_codepage(void) { char charset_name[16]; const char *name; size_t i, j; int min = 0, max = ARRAY_SIZE(charset_names) - 1; setlocale( LC_CTYPE, "" ); if (!(name = nl_langinfo( CODESET ))) return; /* 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; while (min <= max) { int pos = (min + max) / 2; int res = _strnicmp( charset_names[pos].name, charset_name, -1 ); if (!res) { if (charset_names[pos].cp == CP_UTF8) return; unix_table = wine_cp_get_table( charset_names[pos].cp ); return; } if (res > 0) max = pos - 1; else min = pos + 1; } ERR( "unrecognized charset '%s'\n", name ); } #else /* __APPLE__ || __ANDROID__ */ void init_unix_codepage(void) { } #endif /* __APPLE__ || __ANDROID__ */ /****************************************************************** * ntdll_umbstowcs */ int ntdll_umbstowcs( DWORD flags, const char *src, int srclen, WCHAR *dst, int dstlen ) { #ifdef __APPLE__ /* work around broken Mac OS X filesystem that enforces decomposed Unicode */ flags |= MB_COMPOSITE; #endif return unix_table ? wine_cp_mbstowcs( unix_table, flags, src, srclen, dst, dstlen ) : wine_utf8_mbstowcs( flags, src, srclen, dst, dstlen ); } /****************************************************************** * ntdll_wcstoumbs */ int ntdll_wcstoumbs( DWORD flags, const WCHAR *src, int srclen, char *dst, int dstlen, const char *defchar, int *used ) { if (unix_table) return wine_cp_wcstombs( unix_table, flags, src, srclen, dst, dstlen, defchar, used ); if (used) *used = 0; /* all chars are valid for UTF-8 */ return wine_utf8_wcstombs( flags, src, srclen, dst, dstlen ); } /****************************************************************** * __wine_get_unix_codepage (NTDLL.@) */ UINT CDECL __wine_get_unix_codepage(void) { if (!unix_table) return CP_UTF8; return unix_table->info.codepage; } /********************************************************************** * NtQueryDefaultLocale (NTDLL.@) */ NTSTATUS WINAPI NtQueryDefaultLocale( BOOLEAN user, LCID *lcid ) { *lcid = user ? user_lcid : system_lcid; return STATUS_SUCCESS; } /********************************************************************** * NtSetDefaultLocale (NTDLL.@) */ NTSTATUS WINAPI NtSetDefaultLocale( BOOLEAN user, LCID lcid ) { if (user) user_lcid = lcid; else { system_lcid = lcid; system_ui_language = LANGIDFROMLCID(lcid); /* there is no separate call to set it */ } return STATUS_SUCCESS; } /********************************************************************** * NtQueryDefaultUILanguage (NTDLL.@) */ NTSTATUS WINAPI NtQueryDefaultUILanguage( LANGID *lang ) { *lang = user_ui_language; return STATUS_SUCCESS; } /********************************************************************** * NtSetDefaultUILanguage (NTDLL.@) */ NTSTATUS WINAPI NtSetDefaultUILanguage( LANGID lang ) { user_ui_language = lang; return STATUS_SUCCESS; } /********************************************************************** * NtQueryInstallUILanguage (NTDLL.@) */ NTSTATUS WINAPI NtQueryInstallUILanguage( LANGID *lang ) { *lang = system_ui_language; return STATUS_SUCCESS; }