📄 c_locale_win32.c
字号:
/*
* Copyright (c) 1999
* Silicon Graphics Computer Systems, Inc.
*
* Copyright (c) 1999
* Boris Fomitchev
*
* Written 2000
* Anton Lapach
*
* This material is provided "as is", with absolutely no warranty expressed
* or implied. Any use is at your own risk.
*
* Permission to use or copy this software for any purpose is hereby granted
* without fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is granted,
* provided the above notices are retained, and a notice that the code was
* modified is included with the above copyright notice.
*
*/
#include <windows.h>
#include <limits.h>
#if defined (_STLP_MSVC) || defined (__ICL)
# include <memory.h>
#endif
#include <string.h>
#include <locale.h>
#include <stdlib.h>
#include <stdio.h>
#if defined (_STLP_USE_SAFE_STRING_FUNCTIONS)
# define _STLP_STRCPY(D, S) strcpy_s(_STLP_ARRAY_AND_SIZE(D), S)
# define _STLP_STRCPY2(D, DS, S) strcpy_s(D, DS, S)
# define _STLP_RETURN_STRCPY2(D, DS, S) strcpy_s(D, DS, S); return D
# define _STLP_STRNCPY(D, DS, S, C) strncpy_s(D, DS, S, C)
# define _STLP_STRCAT(D, S) strcat_s(_STLP_ARRAY_AND_SIZE(D), S)
# define _STLP_STRCAT2(D, DS, S) strcat_s(D, DS, S)
# if !defined (_STLP_NO_WCHAR_T)
# define _STLP_WCSNCPY(D, DS, S, C) wcsncpy_s(D, DS, S, C)
# endif
#else
# define _STLP_STRCPY(D, S) strcpy(D, S)
# define _STLP_STRCPY2(D, DS, S) strcpy(D, S)
# define _STLP_RETURN_STRCPY2(D, DS, S) return strcpy(D, S)
# define _STLP_STRNCPY(D, DS, S, C) strncpy(D, S, C)
# define _STLP_STRCAT(D, S) strcat(D, S)
# define _STLP_STRCAT2(D, DS, S) strcat(D, S)
# if !defined (_STLP_NO_WCHAR_T)
# define _STLP_WCSNCPY(D, DS, S, C) wcsncpy(D, S, C)
# endif
#endif
#if defined (__cplusplus)
extern "C" {
#endif
/* Framework functions */
/*
locale :: "lang[_country[.code_page]]"
| ".code_page"
| ""
| NULL
*/
#if !defined (_LEADBYTE)
/* multibyte leadbyte */
# define _LEADBYTE 0x8000
#endif
typedef struct _LOCALECONV {
const char* name;
const char* abbrev;
} LOCALECONV;
#define MAX_LANG_LEN 64 /* max language name length */
#define MAX_CTRY_LEN 64 /* max country name length */
#define MAX_MODIFIER_LEN 0 /* max modifier name length - n/a */
#define MAX_LC_LEN (MAX_LANG_LEN+MAX_CTRY_LEN+MAX_MODIFIER_LEN+3)
/* max entire locale string length */
#define MAX_CP_LEN 5 /* max code page name length */
/* Metrowerks has different define here */
#if !defined (LC_MAX)
# if defined (LC_LAST)
# define LC_MAX LC_LAST
# endif
#endif
/* non-NLS language string table */
static LOCALECONV __rg_language[] = {
{"american", "ENU"},
{"american english", "ENU"},
{"american-english", "ENU"},
{"australian", "ENA"},
{"belgian", "NLB"},
{"canadian", "ENC"},
{"chh", "ZHH"},
{"chi", "ZHI"},
{"chinese", "CHS"},
{"chinese-hongkong", "ZHH"},
{"chinese-simplified", "CHS"},
{"chinese-singapore", "ZHI"},
{"chinese-traditional", "CHT"},
{"dutch-belgian", "NLB"},
{"english-american", "ENU"},
{"english-aus", "ENA"},
{"english-belize", "ENL"},
{"english-can", "ENC"},
{"english-caribbean", "ENB"},
{"english-ire", "ENI"},
{"english-jamaica", "ENJ"},
{"english-nz", "ENZ"},
{"english-south africa", "ENS"},
{"english-trinidad y tobago", "ENT"},
{"english-uk", "ENG"},
{"english-us", "ENU"},
{"english-usa", "ENU"},
{"french-belgian", "FRB"},
{"french-canadian", "FRC"},
{"french-luxembourg", "FRL"},
{"french-swiss", "FRS"},
{"german-austrian", "DEA"},
{"german-lichtenstein", "DEC"},
{"german-luxembourg", "DEL"},
{"german-swiss", "DES"},
{"irish-english", "ENI"},
{"italian-swiss", "ITS"},
{"norwegian", "NOR"},
{"norwegian-bokmal", "NOR"},
{"norwegian-nynorsk", "NON"},
{"portuguese-brazilian", "PTB"},
{"spanish-argentina", "ESS"},
{"spanish-bolivia", "ESB"},
{"spanish-chile", "ESL"},
{"spanish-colombia", "ESO"},
{"spanish-costa rica", "ESC"},
{"spanish-dominican republic", "ESD"},
{"spanish-ecuador", "ESF"},
{"spanish-el salvador", "ESE"},
{"spanish-guatemala", "ESG"},
{"spanish-honduras", "ESH"},
{"spanish-mexican", "ESM"},
{"spanish-modern", "ESN"},
{"spanish-nicaragua", "ESI"},
{"spanish-panama", "ESA"},
{"spanish-paraguay", "ESZ"},
{"spanish-peru", "ESR"},
{"spanish-puerto rico", "ESU"},
{"spanish-uruguay", "ESY"},
{"spanish-venezuela", "ESV"},
{"swedish-finland", "SVF"},
{"swiss", "DES"},
{"uk", "ENG"},
{"us", "ENU"},
{"usa", "ENU"}
};
/* non-NLS country string table */
static LOCALECONV __rg_country[] = {
{"america", "USA"},
{"britain", "GBR"},
{"china", "CHN"},
{"czech", "CZE"},
{"england", "GBR"},
{"great britain", "GBR"},
{"holland", "NLD"},
{"hong-kong", "HKG"},
{"new-zealand", "NZL"},
{"nz", "NZL"},
{"pr china", "CHN"},
{"pr-china", "CHN"},
{"puerto-rico", "PRI"},
{"slovak", "SVK"},
{"south africa", "ZAF"},
{"south korea", "KOR"},
{"south-africa", "ZAF"},
{"south-korea", "KOR"},
{"trinidad & tobago", "TTO"},
{"uk", "GBR"},
{"united-kingdom", "GBR"},
{"united-states", "USA"},
{"us", "USA"},
};
typedef struct _Locale_name_hint {
LCID id;
} _Locale_lcid_t;
typedef struct _Locale_ctype {
_Locale_lcid_t lc;
UINT cp;
unsigned int ctable[256];
} _Locale_ctype_t;
typedef struct _Locale_numeric {
_Locale_lcid_t lc;
char cp[MAX_CP_LEN + 1];
char decimal_point[4];
char thousands_sep[4];
char *grouping;
} _Locale_numeric_t;
typedef struct _Locale_time {
_Locale_lcid_t lc;
char cp[MAX_CP_LEN + 1];
char *month[12];
char *abbrev_month[12];
char *dayofweek[7];
char *abbrev_dayofweek[7];
char *date_time_format;
char *long_date_time_format;
char *date_format;
char *long_date_format;
char *time_format;
char am[9];
char pm[9];
} _Locale_time_t;
typedef struct _Locale_collate {
_Locale_lcid_t lc;
char cp[MAX_CP_LEN + 1];
} _Locale_collate_t;
typedef struct _Locale_monetary {
_Locale_lcid_t lc;
char cp[MAX_CP_LEN + 1];
char decimal_point[4];
char thousands_sep[4];
char *grouping;
char int_curr_symbol[5]; /* 3 + 1 + 1 */
char curr_symbol[6];
char negative_sign[5];
char positive_sign[5];
int frac_digits;
int int_frac_digits;
} _Locale_monetary_t;
typedef struct _Locale_messages {
_Locale_lcid_t lc;
char cp[MAX_CP_LEN + 1];
} _Locale_messages_t;
/* Internal function */
static void __FixGrouping(char *grouping);
static const char* __ConvertName(const char* lname, LOCALECONV* ConvTable, int TableSize);
static int __ParseLocaleString(const char* lname, char* lang, char* ctry, char* page);
static int __GetLCID(const char* lang, const char* ctry, LCID* lcid);
static int __GetLCIDFromName(const char* lname, LCID* lcid, char *cp, _Locale_lcid_t *hint);
static char const* __GetLocaleName(LCID lcid, const char* cp, char* buf);
static char const* __Extract_locale_name(const char* loc, int category, char* buf);
static char const* __TranslateToSystem(const char* lname, char* buf, _Locale_lcid_t* hint);
static void __GetLocaleInfoUsingACP(LCID lcid, const char* cp, LCTYPE lctype, char* buf, int buf_size);
static int __intGetACP(LCID lcid);
static int __intGetOCP(LCID lcid);
static int __GetDefaultCP(LCID lcid);
static char* __ConvertToCP(int from_cp, int to_cp, const char *from, size_t size, size_t *ret_buf_size);
static void my_ltoa(long __x, char* buf);
void my_ltoa(long __x, char* buf) {
char rbuf[64];
char* ptr = rbuf;
if (__x == 0)
*ptr++ = '0';
else {
for (; __x != 0; __x /= 10)
*ptr++ = (char)(__x % 10) + '0';
}
while(ptr > rbuf) *buf++ = *--ptr;
/* psw */
*buf = '\0';
}
#if defined (__cplusplus)
_STLP_BEGIN_NAMESPACE
extern "C" {
#endif
_Locale_lcid_t* _Locale_get_ctype_hint(_Locale_ctype_t* ltype)
{ return (ltype != 0) ? <ype->lc : 0; }
_Locale_lcid_t* _Locale_get_numeric_hint(_Locale_numeric_t* lnumeric)
{ return (lnumeric != 0) ? &lnumeric->lc : 0; }
_Locale_lcid_t* _Locale_get_time_hint(_Locale_time_t* ltime)
{ return (ltime != 0) ? <ime->lc : 0; }
_Locale_lcid_t* _Locale_get_collate_hint(_Locale_collate_t* lcollate)
{ return (lcollate != 0) ? &lcollate->lc : 0; }
_Locale_lcid_t* _Locale_get_monetary_hint(_Locale_monetary_t* lmonetary)
{ return (lmonetary != 0) ? &lmonetary->lc : 0; }
_Locale_lcid_t* _Locale_get_messages_hint(_Locale_messages_t* lmessages)
{ return (lmessages != 0) ? &lmessages->lc : 0; }
void* _Locale_ctype_create(const char * name, _Locale_lcid_t* lc_hint) {
char cname[_Locale_MAX_SIMPLE_NAME];
char cp_name[MAX_CP_LEN + 1];
int NativeCP;
unsigned char Buffer[256];
unsigned char *ptr;
unsigned short ctable[256];
CPINFO CPInfo;
int i;
wchar_t *wbuffer;
int BufferSize;
_Locale_ctype_t *ltype = (_Locale_ctype_t*)malloc(sizeof(_Locale_ctype_t));
if (!ltype) return ltype;
memset(ltype, 0, sizeof(_Locale_ctype_t));
__Extract_locale_name(name, LC_CTYPE, cname);
if (__GetLCIDFromName(cname, <ype->lc.id, cp_name, lc_hint) == -1)
{ free(ltype); return NULL; }
ltype->cp = atoi(cp_name);
NativeCP = __GetDefaultCP(ltype->lc.id);
/* Make table with all characters. */
for (i = 0; i < 256; ++i) Buffer[i] = (unsigned char)i;
if (!GetCPInfo(NativeCP, &CPInfo)) { free(ltype); return NULL; }
if (CPInfo.MaxCharSize > 1) {
for (ptr = (unsigned char*)CPInfo.LeadByte; *ptr && *(ptr + 1); ptr+=2)
for (i = *ptr; i <= *(ptr + 1); ++i) Buffer[i] = 0;
}
if ((UINT)NativeCP != ltype->cp) {
OSVERSIONINFO ver_info;
ver_info.dwOSVersionInfoSize = sizeof(ver_info);
GetVersionEx(&ver_info);
if (ver_info.dwPlatformId == VER_PLATFORM_WIN32_NT) {
/* Convert character sequence to Unicode. */
BufferSize = MultiByteToWideChar(ltype->cp, MB_PRECOMPOSED, (const char*)Buffer, 256, NULL, 0);
wbuffer = (wchar_t*)malloc(BufferSize*sizeof(wchar_t));
if (!MultiByteToWideChar(ltype->cp, MB_PRECOMPOSED, (const char*)Buffer, 256, wbuffer, BufferSize))
{ free(wbuffer); free(ltype); return NULL; }
GetStringTypeW(CT_CTYPE1, wbuffer, 256, ctable);
for (i = 0; i < 256; ++i)
ltype->ctable[i]=(unsigned int)ctable[i];
if (CPInfo.MaxCharSize > 1) {
for (ptr = (unsigned char*)CPInfo.LeadByte; *ptr && *(ptr + 1); ptr+=2)
for (i = *ptr; i <= *(ptr + 1); i++) ltype->ctable[i] = _LEADBYTE;
}
free(wbuffer);
}
else {
unsigned char TargetBuffer[256];
GetStringTypeA(ltype->lc.id, CT_CTYPE1, (const char*)Buffer, 256, ctable);
/* Convert character sequence to target code page. */
BufferSize = MultiByteToWideChar(NativeCP, MB_PRECOMPOSED, (const char*)Buffer, 256, NULL, 0);
wbuffer = (wchar_t*)malloc(BufferSize*sizeof(wchar_t));
if (!MultiByteToWideChar(NativeCP, MB_PRECOMPOSED, (const char*)Buffer, 256, wbuffer, BufferSize))
{ free(wbuffer); free(ltype); return NULL; }
if (!WideCharToMultiByte(ltype->cp, WC_COMPOSITECHECK | WC_SEPCHARS, wbuffer, BufferSize, (char*)TargetBuffer, 256, NULL, FALSE))
{ free(wbuffer); free(ltype); return NULL; }
free(wbuffer);
/* Translate ctype table. */
for (i = 0; i < 256; ++i) {
if (!TargetBuffer[i]) continue;
ltype->ctable[TargetBuffer[i]] = ctable[i];
}
/* Mark lead byte. */
if (!GetCPInfo(ltype->cp, &CPInfo)) { free(ltype); return NULL; }
if (CPInfo.MaxCharSize > 1) {
for (ptr = (unsigned char*)CPInfo.LeadByte; *ptr && *(ptr + 1); ptr+=2)
for (i = *ptr; i <= *(ptr + 1); ++i) ltype->ctable[i] = _LEADBYTE;
}
}
}
else {
GetStringTypeA(ltype->lc.id, CT_CTYPE1, (const char*)Buffer, 256, ctable);
for (i = 0; i < 256; ++i)
ltype->ctable[i]=(unsigned int)ctable[i];
if (CPInfo.MaxCharSize > 1) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -