30#include "themelocale.h"
38#include <tqiodevice.h>
41#ifdef HAVE_SYS_TYPES_H
46# define W(flag, data) ((flag) ? SWAP (data) : (data))
49typedef TQ_UINT32 nls_uint32;
56 struct string_desc *orig_tab;
57 struct string_desc *trans_tab;
62static inline nls_uint32 SWAP (nls_uint32 i)
64 return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24);
70#define _MAGIC 0x950412de
71#define _MAGIC_SWAPPED 0xde120495
74#define MO_REVISION_NUMBER 0
80static inline unsigned long hash_string (
const char *__str_param);
94 nls_uint32 orig_tab_offset;
96 nls_uint32 trans_tab_offset;
98 nls_uint32 hash_tab_size;
100 nls_uint32 hash_tab_offset;
111void tl_nl_load_domain(TQIODevice* device,
int size,
115void tl_nl_unload_domain(
struct loaded_domain *domain);
117ThemeLocale::ThemeLocale(
ThemeFile* theme)
120 setLanguage(languageList());
123ThemeLocale::~ThemeLocale()
128void ThemeLocale::unload()
132 tl_nl_unload_domain((
struct loaded_domain *)m_domain.data);
137TQString ThemeLocale::translate(TQString text)
const
143 TQString result = TQString::fromUtf8(tl_nl_find_msg(&m_domain, text.ascii()));
152void ThemeLocale::setLanguage(
const TQStringList &languages)
155 for(TQStringList::ConstIterator it = languages.begin();
156 it != languages.end();
160 TQString(
"locale/%1/LC_MESSAGES/%2.mo").arg(*it).arg(m_theme->mo());
162 if(m_theme->fileExists(file))
164 TQBuffer buffer(m_theme->readThemeFile(file));
165 tl_nl_load_domain(&buffer, buffer.size(), &m_domain);
172TQStringList ThemeLocale::languageList()
174 TDEConfig* config = TDEGlobal::instance()->config();
176 TQStringList languageList;
178 TQStringList::split(
':', TQFile::decodeName(::getenv(
"TDE_LANG")));
180 languageList += config->readListEntry(
"Language",
':');
186 langs << TQFile::decodeName(::getenv(
"LC_ALL"));
187 langs << TQFile::decodeName(::getenv(
"LC_MESSAGES"));
188 langs << TQFile::decodeName(::getenv(
"LANG"));
190 for(TQStringList::Iterator it = langs.begin();
194 TQString ln, ct, chrset;
195 TDELocale::splitLocale(*it, ln, ct, chrset);
205 langs.insert(it, ln);
207 languageList += langs;
209 TQStringList::Iterator end( languageList.end() );
210 for(TQStringList::Iterator it=languageList.begin(); it!=end;)
213 it = languageList.remove(it);
223 size_t top, act, bottom;
224 struct loaded_domain *domain;
226 if (domain_file->decided == 0)
229 if (domain_file->data == NULL)
232 domain = (
struct loaded_domain *) domain_file->data;
235 if (domain->hash_size > 2 && domain->hash_tab != NULL)
238 nls_uint32 len = strlen (msgid);
239 nls_uint32 hash_val = hash_string (msgid);
240 nls_uint32 idx = hash_val % domain->hash_size;
241 nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
242 nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]);
248 if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len
250 domain->data + W (domain->must_swap,
251 domain->orig_tab[nstr - 1].offset)) == 0)
252 return (
char *) domain->data + W (domain->must_swap,
253 domain->trans_tab[nstr - 1].offset);
257 if (idx >= domain->hash_size - incr)
258 idx -= domain->hash_size - incr;
262 nstr = W (domain->must_swap, domain->hash_tab[idx]);
267 if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len
269 domain->data + W (domain->must_swap,
270 domain->orig_tab[nstr - 1].offset))
272 return (
char *) domain->data
273 + W (domain->must_swap, domain->trans_tab[nstr - 1].offset);
281 top = domain->nstrings;
287 act = (bottom + top) / 2;
288 cmp_val = strcmp (msgid, domain->data
289 + W (domain->must_swap,
290 domain->orig_tab[act].offset));
293 else if (cmp_val > 0)
300 return bottom >= top ? NULL : (
char *) domain->data
301 + W (domain->must_swap,
302 domain->trans_tab[act].offset);
307#define HASHWORDBITS 32
309static inline unsigned long
310hash_string (
const char *str_param)
312 unsigned long int hval, g;
313 const char *str = str_param;
320 hval += (
unsigned long) *str++;
321 g = hval & ((
unsigned long) 0xf << (HASHWORDBITS - 4));
324 hval ^= g >> (HASHWORDBITS - 8);
333void tl_nl_load_domain (TQIODevice* device,
int size,
336 struct mo_file_header *data = (
struct mo_file_header *) -1;
337 struct loaded_domain *domain;
339 domain_file->decided = 1;
340 domain_file->data = NULL;
350 if (device->open(IO_ReadOnly) ==
false)
354 if (size < (off_t)
sizeof (
struct mo_file_header))
363 if (data == (
struct mo_file_header *) -1)
368 data = (
struct mo_file_header *) malloc (size);
373 read_ptr = (
char *) data;
376 long int nb = (
long int) device->readBlock (read_ptr, to_read);
393 if (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED)
401 = (
struct loaded_domain *) malloc (
sizeof (
struct loaded_domain));
402 if (domain_file->data == NULL)
405 domain = (
struct loaded_domain *) domain_file->data;
406 domain->data = (
char *) data;
407 domain->must_swap = data->magic != _MAGIC;
410 switch (W (domain->must_swap, data->revision))
413 domain->nstrings = W (domain->must_swap, data->nstrings);
414 domain->orig_tab = (
struct string_desc *)
415 ((
char *) data + W (domain->must_swap,
416 data->orig_tab_offset));
417 domain->trans_tab = (
struct string_desc *)
418 ((
char *) data + W (domain->must_swap,
419 data->trans_tab_offset));
420 domain->hash_size = W (domain->must_swap, data->hash_tab_size);
421 domain->hash_tab = (nls_uint32 *)
422 ((
char *) data + W (domain->must_swap,
423 data->hash_tab_offset));
429 domain_file->data = NULL;
434void tl_nl_unload_domain (
struct loaded_domain *domain)
436 free ((
void *) domain->data);