%% 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;
}