Files
reactos/rosapps/smartpdf/src/translations.cpp
T
Daniel Reimer a7fddf9c07 Delete all Trailing spaces in code.
svn path=/trunk/; revision=29689
2007-10-19 23:05:02 +00:00

236 lines
6.2 KiB
C++

#include "base_util.h"
#include "translations.h"
#include "translations_txt.h"
#include "str_util.h"
/*
This code relies on the following variables that must be defined in a
separate file (translations_txt.h and translations_txt.c).
The idea is that those files are automatically generated
by a script from translations file.
// number of languages we support
int g_transLangsCount;
// array of language names so that g_transLangs[i] is a name of
// language. i is 0..g_transLangsCount-1
const char **g_transLangs;
// total number of translated strings
int g_transTranslationsCount;
// array of translated strings.
// it has g_transLangsCount * g_translationsCount elements
// (for simplicity). Translation i for language n is at position
// (n * g_transTranslationsCount) + i
const char **g_transTranslations;
*/
// numeric index of the current language. 0 ... g_transLangsCount-1
static int currLangIdx = 0;
/* 'data'/'data_len' is a text describing all texts we translate.
It builds data structures need for quick lookup of translations
as well as a list of available languages.
It returns a list of available languages.
The list is not valid after a call to Translations_FreeData.
The function must be called before any other function in this module.
It can be called multiple times. This is to make debugging of translations
easier by allowing re-loading translation file at runtime.
*/
bool Translations_FromData(const char* langs, const char* data, size_t data_len)
{
assert(0); // TODO: implement me
return false;
}
bool Translations_SetCurrentLanguage(const char* lang)
{
for (int i=0; i < g_transLangsCount; i++) {
if (str_eq(lang, g_transLangs[i])) {
currLangIdx = i;
return true;
}
}
return false;
}
const char* Translatations_GetTranslation(const char* txt)
{
// perf shortcut: don't bother translating if we use default lanuage
if (0 == currLangIdx)
return txt;
for (int i=0; i < g_transTranslationsCount; i++) {
// TODO: translations are sorted so can use binary search
const char *tmp = g_transTranslations[i];
int cmp_res = strcmp(txt, tmp);
if (0 == cmp_res) {
tmp = g_transTranslations[(currLangIdx * g_transTranslationsCount) + i];
if (NULL == tmp)
return txt;
return tmp;
} else if (cmp_res < 0) {
assert(0); // bad - didn't find a translation
return txt;
}
}
assert(0); // bad - didn't find a translation
return txt;
}
static WCHAR* lastTxtCached = NULL;
#define UTF8_END -1
#define UTF8_ERROR -2
typedef struct json_utf8_decode
{
int the_index;
const char *the_input;
int the_length;
int the_char;
int the_byte;
} json_utf8_decode;
void
utf8_decode_init(json_utf8_decode *utf8, const char *p, int length)
{
utf8->the_index = 0;
utf8->the_input = p;
utf8->the_length = length;
utf8->the_char = 0;
utf8->the_byte = 0;
}
static int
get(json_utf8_decode *utf8)
{
int c;
if (utf8->the_index >= utf8->the_length) {
return UTF8_END;
}
c = utf8->the_input[utf8->the_index] & 0xFF;
utf8->the_index += 1;
return c;
}
static int
cont(json_utf8_decode *utf8)
{
int c = get(utf8);
return ((c & 0xC0) == 0x80) ? (c & 0x3F) : UTF8_ERROR;
}
int
utf8_decode_next(json_utf8_decode *utf8)
{
int c; /* the first byte of the character */
int r; /* the result */
if (utf8->the_index >= utf8->the_length) {
return utf8->the_index == utf8->the_length ? UTF8_END : UTF8_ERROR;
}
utf8->the_byte = utf8->the_index;
utf8->the_char += 1;
c = get(utf8);
/*
Zero continuation (0 to 127)
*/
if ((c & 0x80) == 0) {
return c;
}
/*
One contination (128 to 2047)
*/
if ((c & 0xE0) == 0xC0) {
int c1 = cont(utf8);
if (c1 < 0) {
return UTF8_ERROR;
}
r = ((c & 0x1F) << 6) | c1;
return r >= 128 ? r : UTF8_ERROR;
}
/*
Two continuation (2048 to 55295 and 57344 to 65535)
*/
if ((c & 0xF0) == 0xE0) {
int c1 = cont(utf8);
int c2 = cont(utf8);
if (c1 < 0 || c2 < 0) {
return UTF8_ERROR;
}
r = ((c & 0x0F) << 12) | (c1 << 6) | c2;
return r >= 2048 && (r < 55296 || r > 57343) ? r : UTF8_ERROR;
}
/*
Three continuation (65536 to 1114111)
*/
if ((c & 0xF1) == 0xF0) {
int c1 = cont(utf8);
int c2 = cont(utf8);
int c3 = cont(utf8);
if (c1 < 0 || c2 < 0 || c3 < 0) {
return UTF8_ERROR;
}
r = ((c & 0x0F) << 18) | (c1 << 12) | (c2 << 6) | c3;
return r >= 65536 && r <= 1114111 ? r : UTF8_ERROR;
}
return UTF8_ERROR;
}
static int json_utf8_to_utf16(unsigned short *w, const char *p, int length)
{
int c;
int the_index = 0;
json_utf8_decode utf8;
utf8_decode_init(&utf8, p, length);
for (;;) {
c = utf8_decode_next(&utf8);
if (c < 0) {
return UTF8_END ? the_index : UTF8_ERROR;
}
if (c < 0x10000) {
w[the_index] = (unsigned short)c;
the_index += 1;
} else {
c &= 0xFFFF;
w[the_index] = (unsigned short)(0xD800 | (c >> 10));
the_index += 1;
w[the_index] = (unsigned short)(0xDC00 | (c & 0x3FF));
the_index += 1;
}
}
}
WCHAR* utf8_to_utf16(const char *txt)
{
// TODO: this is not correct, need real conversion
size_t len = strlen(txt);
WCHAR* wstr = (WCHAR*)zmalloc((len+1) * sizeof(WCHAR));
if (!wstr) return NULL;
int res = json_utf8_to_utf16((unsigned short*)wstr, txt, len);
assert(UTF8_ERROR != res);
return wstr;
}
// TODO: this is not thread-safe. lastTxtCached should be per-thread
const WCHAR* Translatations_GetTranslationW(const char* txt)
{
txt = Translatations_GetTranslation(txt);
if (!txt) return NULL;
if (lastTxtCached)
free(lastTxtCached);
lastTxtCached = utf8_to_utf16(txt);
return (const WCHAR*)lastTxtCached;
}
void Translations_FreeData()
{
// TODO: will be more when we implement Translations_FromData
free(lastTxtCached);
lastTxtCached = NULL;
}