%% options copyright owner = Dirk Krause copyright year = 2015-xxxx license = bsd %% header /** @file Get language, region and encoding. CRT on Windows: Optional, disabling CRT degrades performance. */ #ifndef DK4CONF_H_INCLUDED #include "dk4conf.h" #endif #ifndef DK4TYPES_H_INCLUDED #include "dk4types.h" #endif #ifndef DK4ERROR_H_INCLUDED #include "dk4error.h" #endif #ifdef __cplusplus extern "C" { #endif /** Retrieve localization settings. @param lang Result buffer for language name. @param szlang Size of result buffer (number of dkChar). @param reg Result buffer for region or country name. @param szreg Size of result buffer (number of dkChar). @param enc Address of result variable for encoding. @param erp Error report, may be NULL. @return 1 on success, 0 on error. Error codes: - DK4_E_INVALID_ARGUMENTS
if one of lang, reg or enc is NULL or szlang or szreg is 0, - DK4_E_BUFFER_TOO_SMALL
if one of the involved buffers is too small, */ int dk4loc_get_settings( dkChar *lang, size_t szlang, dkChar *reg, size_t szreg, int *enc, dk4_er_t *erp ); #ifdef __cplusplus } #endif %% module #include "dk4loc.h" #ifndef STDLIB_H_INCLUDED #include #define STDLIB_H_INCLUDED 1 #endif #if DK4_HAVE_STRING_H #ifndef STRING_H_INCLUDED #include #define STRING_H_INCLUDED 1 #endif #endif #if DK4_HAVE_CTYPE_H #ifndef CTYPE_H_INCLUDED #include #define CTYPE_H_INCLUDED 1 #endif #endif #ifndef DK4ENC_H_INCLUDED #include "dk4enc.h" #endif #ifndef DK4STR8_H_INCLUDED #include "dk4str8.h" #endif #if DK4_ON_WINDOWS #ifndef DK4WREG8_H_INCLUDED #include "dk4wreg8.h" #endif #ifndef DK4WREGC_H_INCLUDED #include "dk4wregc.h" #endif #endif $!trace-include /** Keywords used by the module. */ static const char * const dk4loc_mod_kw_8[] = { $!string-table # # 0 Environment variable name for Linux/Unix. # LANG # # 1 2 Encoding names for UTF-8 # utf8 UTF-8 # # 3 4 5 Registry key and entry for localization # Control Panel\\International LocaleName sLanguage $!end }; static int dk4loc_use_default(dkChar *lptr, size_t szl, dk4_er_t *erp) { int back = 0; if ((NULL != lptr) && (2 < szl)) { lptr[0] = dkT('e'); lptr[1] = dkT('n'); lptr[2] = dkT('\0'); back = 1; } else { dk4error_set_simple_error_code(erp, DK4_E_BUFFER_TOO_SMALL); } return back; } int dk4loc_get_settings( dkChar *lang, size_t szlang, dkChar *reg, size_t szreg, int *enc, dk4_er_t *erp ) { #if DK4_ON_WINDOWS char buf[64]; /* Buffer to process getenv result */ void *kptr; /* Registry key pointer */ dkChar *pd; /* Copy string */ char *p3; /* Region */ char *p4; /* Copy string */ size_t sz; /* String length */ int res; /* Result from RegQueryValueEx() */ int expand = 0; /* Flag: Expansion necessary. */ #else char buf[64]; /* Buffer to process getenv result */ dkChar *pd; /* Copy string */ char *p1; /* Result from getenv */ char *p2; /* Encoding */ char *p3; /* Region */ char *p4; /* Copy string */ size_t sz; /* String length */ #endif int back = 0; $? "+ dk4loc_get_settings %d %u %d %u %d %d", TR_IPTR(lang), (unsigned)szlang, TR_IPTR(reg), (unsigned)szreg, TR_IPTR(enc), TR_IPTR(erp) if ((NULL != lang) && (0 < szlang)) { *lang = dkT('\0'); } if ((NULL != reg ) && (0 < szreg )) { *reg = dkT('\0'); } if (NULL != enc) { *enc = DK4_ENCODING_ASCII; } if ((NULL != lang) && (NULL != reg) && (NULL != enc)) { if ((0 < szlang) && (0 < szreg)) { #if DK4_ON_WINDOWS #if DK4_CHAR_SIZE > 1 *enc = DK4_ENCODING_UTF16; #else *enc = DK4_ENCODING_ASCII; #endif kptr = dk4wreg_open_key_c8(DK4_WREGKEY_HKCU, dk4loc_mod_kw_8[3], 0, erp); if (NULL != kptr) { res = dk4wreg_get_string_c8( kptr, dk4loc_mod_kw_8[4], buf, sizeof(buf), &expand, erp ); if (0 != res) { p3 = dk4str8_chr(buf, '-'); if (NULL != p3) { *(p3++) = '\0'; } dk4str8_normalize(buf, NULL); if (NULL != p3) { dk4str8_normalize(p3, NULL); } sz = dk4str8_len(buf); if (0 < sz) { if (szlang > sz) { /* strcpy(lang, buf); */ pd = lang; p4 = buf; while('\0' != *p4) { *(pd++) = (dkChar)dk4str8_tolower(*(p4++)); } *pd = dkT('\0'); back = 1; sz = dk4str8_len(p3); if (0 < sz) { if (szreg > sz) { /* strcpy(reg, p3); */ pd = reg; p4 = p3; while('\0' != *p4) { #if 0 *(pd++) = (dkChar)(tolower((unsigned char)(*(p4++)))); #endif *(pd++) = (dkChar)dk4str8_tolower(*(p4++)); } *pd = dkT('\0'); } else { dk4error_set_simple_error_code(erp, DK4_E_BUFFER_TOO_SMALL); back = 0; } } } else { dk4error_set_simple_error_code(erp, DK4_E_BUFFER_TOO_SMALL); } } else { back = dk4loc_use_default(lang, szlang, erp); } } else { res = dk4wreg_get_string_c8( kptr, dk4loc_mod_kw_8[5], buf, sizeof(buf), &expand, erp ); if (0 != res) { dk4str8_normalize(buf, NULL); sz = dk4str8_len(buf); if (2 < sz) { buf[2] = '\0'; } sz = dk4str8_len(buf); if (0 < sz) { if (szlang > sz) { pd = lang; p4 = buf; while ('\0' != *p4) { *(pd++) = (dkChar)(tolower((unsigned char)(*(p4++)))); } *pd = dkT('\0'); back = 1; } else { dk4error_set_simple_error_code(erp, DK4_E_BUFFER_TOO_SMALL); } } else { back = dk4loc_use_default(lang, szlang, erp); } } else { back = dk4loc_use_default(lang, szlang, erp); } } dk4wreg_close_key(kptr); } else { back = dk4loc_use_default(lang, szlang, erp); } #else p1 = getenv(dk4loc_mod_kw_8[0]); if (NULL != p1) { $? ". getenv ok" if (sizeof(buf) > dk4str8_len(p1)) { $? ". length ok" dk4str8_cpy_s(buf, sizeof(buf), p1, NULL); p2 = dk4str8_chr(buf, '.'); if (NULL != p2) { $? ". p2 has encoding" *(p2++) = '\0'; $? ". encoding \"%!8s\"", p2 } p3 = dk4str8_chr(buf, '_'); if (NULL != p3) { $? ". p3 has region" *(p3++) = '\0'; $? ". region \"%!8s\"", p3 } $? ". language \"%!8s\"", buf dk4str8_normalize(buf, NULL); $? ". normalized" if (NULL != p2) { dk4str8_normalize(p2, NULL); } if (NULL != p3) { dk4str8_normalize(p3, NULL); } sz = dk4str8_len(buf); $? ". buf lgt %u", (unsigned)sz if (0 < sz) { if (szlang > sz) { /* strcpy(lang, buf); */ pd = lang; p4 = buf; while('\0' != *p4) { *(pd++) = (dkChar)(tolower((unsigned char)(*(p4++)))); } *pd = dkT('\0'); back = 1; if (NULL != p3) { sz = dk4str8_len(p3); if (0 < sz) { if (szreg > sz) { /* strcpy(reg, p3); */ pd = reg; p4 = p3; while('\0' != *p4) { *(pd++) = (dkChar)(tolower((unsigned char)(*(p4++)))); } *pd = dkT('\0'); } else { dk4error_set_simple_error_code(erp, DK4_E_BUFFER_TOO_SMALL); back = 0; } } } #if DK4_CHAR_SIZE > 1 #if DK4_CHAR_SIZE > 2 $? ". 32 bit" *enc = DK4_ENCODING_32; #else $? ". 16 bit" *enc = DK4_ENCODING_UTF16; #endif #else $? ". 8 bit" *enc = DK4_ENCODING_ASCII; if (NULL != p2) { if (0 == dk4str8_casecmp(p2, dk4loc_mod_kw_8[1])) { *enc = DK4_ENCODING_UTF8; } else { if (0 == dk4str8_casecmp(p2, dk4loc_mod_kw_8[2])) { *enc = DK4_ENCODING_UTF8; } } } #endif } else { $? "! LANG too long" dk4error_set_simple_error_code(erp, DK4_E_BUFFER_TOO_SMALL); } } else { $? "! zero length LANG" back = dk4loc_use_default(lang, szlang, erp); } } else { $? "! LANG env too long" dk4error_set_simple_error_code(erp, DK4_E_BUFFER_TOO_SMALL); } } else { $? "! getenv" back = dk4loc_use_default(lang, szlang, erp); } #endif } else { $? "! invalid args" dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } } else { $? "! invalid args" dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } $? "- dk4loc_get_settings %d", back return back; }