• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • superkaramba
 

superkaramba

  • superkaramba
  • src
themelocale.cpp
1/*
2 * languageList from tdelocale.cpp
3 * Copyright (c) 1997,2001 Stephan Kulow <coolo@kde.org>
4 * Copyright (c) 1999 Preston Brown <pbrown@kde.org>
5 * Copyright (c) 1999-2002 Hans Petter Bieker <bieker@kde.org>
6 * Copyright (c) 2002 Lukas Tinkl <lukas@kde.org>
7 *
8 * libintl.cpp -- gettext related functions from glibc-2.0.5
9 * Copyright (C) 1995 Software Foundation, Inc.
10 *
11 * This file is part of SuperKaramba.
12 * Copyright (c) 2005 Petri Damsten <damu@iki.fi>
13 *
14 * SuperKaramba is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * SuperKaramba is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with SuperKaramba; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 ****************************************************************************/
28#include <config.h>
29
30#include "themelocale.h"
31#include "themefile.h"
32#include <kdebug.h>
33#include <tdeconfig.h>
34#include <tdeglobal.h>
35#include <tdelocale.h>
36#include <tqbuffer.h>
37#include <tqglobal.h>
38#include <tqiodevice.h>
39#include <stdlib.h>
40
41#ifdef HAVE_SYS_TYPES_H
42#include <sys/types.h>
43#endif
44
45#ifndef W
46# define W(flag, data) ((flag) ? SWAP (data) : (data))
47#endif
48
49typedef TQ_UINT32 nls_uint32;
50
51struct loaded_domain
52{
53 const char *data;
54 int must_swap;
55 nls_uint32 nstrings;
56 struct string_desc *orig_tab;
57 struct string_desc *trans_tab;
58 nls_uint32 hash_size;
59 nls_uint32 *hash_tab;
60};
61
62static inline nls_uint32 SWAP (nls_uint32 i)
63{
64 return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24);
65}
66
67/* @@ end of prolog @@ */
68
69/* The magic number of the GNU message catalog format. */
70#define _MAGIC 0x950412de
71#define _MAGIC_SWAPPED 0xde120495
72
73/* Revision number of the currently used .mo (binary) file format. */
74#define MO_REVISION_NUMBER 0
75
76
77/* Defines the so called `hashpjw' function by P.J. Weinberger
78 [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
79 1986, 1987 Bell Telephone Laboratories, Inc.] */
80static inline unsigned long hash_string (const char *__str_param);
81
82/* @@ end of prolog @@ */
83
84/* Header for binary .mo file format. */
85struct mo_file_header
86{
87 /* The magic number. */
88 nls_uint32 magic;
89 /* The revision number of the file format. */
90 nls_uint32 revision;
91 /* The number of strings pairs. */
92 nls_uint32 nstrings;
93 /* Offset of table with start offsets of original strings. */
94 nls_uint32 orig_tab_offset;
95 /* Offset of table with start offsets of translation strings. */
96 nls_uint32 trans_tab_offset;
97 /* Size of hashing table. */
98 nls_uint32 hash_tab_size;
99 /* Offset of first hashing entry. */
100 nls_uint32 hash_tab_offset;
101};
102
103struct string_desc
104{
105 /* Length of addressed string. */
106 nls_uint32 length;
107 /* Offset of string in file. */
108 nls_uint32 offset;
109};
110
111void tl_nl_load_domain(TQIODevice* device, int size,
112 struct sk_kde_loaded_l10nfile *domain_file);
113char* tl_nl_find_msg(const struct sk_kde_loaded_l10nfile *domain_file,
114 const char *msgid);
115void tl_nl_unload_domain(struct loaded_domain *domain);
116
117ThemeLocale::ThemeLocale(ThemeFile* theme)
118 : m_theme(theme)
119{
120 setLanguage(languageList());
121}
122
123ThemeLocale::~ThemeLocale()
124{
125 unload();
126}
127
128void ThemeLocale::unload()
129{
130 if(m_domain.data)
131 {
132 tl_nl_unload_domain((struct loaded_domain *)m_domain.data);
133 m_domain.data = 0;
134 }
135}
136
137TQString ThemeLocale::translate(TQString text) const
138{
139 if(text == 0)
140 return TQString();
141 if(m_domain.data)
142 {
143 TQString result = TQString::fromUtf8(tl_nl_find_msg(&m_domain, text.ascii()));
144 if(result.isEmpty())
145 return text;
146 else
147 return result;
148 }
149 return text;
150}
151
152void ThemeLocale::setLanguage(const TQStringList &languages)
153{
154 unload();
155 for(TQStringList::ConstIterator it = languages.begin();
156 it != languages.end();
157 ++it)
158 {
159 TQString file =
160 TQString("locale/%1/LC_MESSAGES/%2.mo").arg(*it).arg(m_theme->mo());
161
162 if(m_theme->fileExists(file))
163 {
164 TQBuffer buffer(m_theme->readThemeFile(file));
165 tl_nl_load_domain(&buffer, buffer.size(), &m_domain);
166 m_language = *it;
167 return;
168 }
169 }
170}
171
172TQStringList ThemeLocale::languageList()
173{
174 TDEConfig* config = TDEGlobal::instance()->config();
175 // Reset the list and add the new languages
176 TQStringList languageList;
177 languageList +=
178 TQStringList::split(':', TQFile::decodeName(::getenv("TDE_LANG")));
179
180 languageList += config->readListEntry("Language", ':');
181
182 // same order as setlocale use
183 // HPB: Only run splitLocale on the environment variables..
184 TQStringList langs;
185
186 langs << TQFile::decodeName(::getenv("LC_ALL"));
187 langs << TQFile::decodeName(::getenv("LC_MESSAGES"));
188 langs << TQFile::decodeName(::getenv("LANG"));
189
190 for(TQStringList::Iterator it = langs.begin();
191 it != langs.end();
192 ++it )
193 {
194 TQString ln, ct, chrset;
195 TDELocale::splitLocale(*it, ln, ct, chrset);
196 /*
197 We don't use these in zip themes...
198 if (!ct.isEmpty())
199 {
200 langs.insert(it, ln + '_' + ct);
201 if (!chrset.isEmpty())
202 langs.insert(it, ln + '_' + ct + '.' + chrset);
203 }
204 */
205 langs.insert(it, ln);
206 }
207 languageList += langs;
208 // Remove empty strings
209 TQStringList::Iterator end( languageList.end() );
210 for(TQStringList::Iterator it=languageList.begin(); it!=end;)
211 {
212 if((*it).isEmpty())
213 it = languageList.remove(it);
214 else
215 ++it;
216 }
217 return languageList;
218}
219
220char* tl_nl_find_msg (const struct sk_kde_loaded_l10nfile *domain_file,
221 const char *msgid)
222{
223 size_t top, act, bottom;
224 struct loaded_domain *domain;
225
226 if (domain_file->decided == 0)
227 return NULL;
228
229 if (domain_file->data == NULL)
230 return NULL;
231
232 domain = (struct loaded_domain *) domain_file->data;
233
234 /* Locate the MSGID and its translation. */
235 if (domain->hash_size > 2 && domain->hash_tab != NULL)
236 {
237 /* Use the hashing table. */
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]);
243
244 if (nstr == 0)
245 /* Hash table entry is empty. */
246 return NULL;
247
248 if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len
249 && strcmp (msgid,
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);
254
255 while (1)
256 {
257 if (idx >= domain->hash_size - incr)
258 idx -= domain->hash_size - incr;
259 else
260 idx += incr;
261
262 nstr = W (domain->must_swap, domain->hash_tab[idx]);
263 if (nstr == 0)
264 /* Hash table entry is empty. */
265 return NULL;
266
267 if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len
268 && strcmp (msgid,
269 domain->data + W (domain->must_swap,
270 domain->orig_tab[nstr - 1].offset))
271 == 0)
272 return (char *) domain->data
273 + W (domain->must_swap, domain->trans_tab[nstr - 1].offset);
274 }
275 /* NOTREACHED */
276 }
277
278 /* Now we try the default method: binary search in the sorted
279 array of messages. */
280 bottom = 0;
281 top = domain->nstrings;
282 act = top;
283 while (bottom < top)
284 {
285 int cmp_val;
286
287 act = (bottom + top) / 2;
288 cmp_val = strcmp (msgid, domain->data
289 + W (domain->must_swap,
290 domain->orig_tab[act].offset));
291 if (cmp_val < 0)
292 top = act;
293 else if (cmp_val > 0)
294 bottom = act + 1;
295 else
296 break;
297 }
298
299 /* If an translation is found return this. */
300 return bottom >= top ? NULL : (char *) domain->data
301 + W (domain->must_swap,
302 domain->trans_tab[act].offset);
303}
304
305/* @@ begin of epilog @@ */
306/* We assume to have `unsigned long int' value with at least 32 bits. */
307#define HASHWORDBITS 32
308
309static inline unsigned long
310hash_string (const char *str_param)
311{
312 unsigned long int hval, g;
313 const char *str = str_param;
314
315 /* Compute the hash value for the given string. */
316 hval = 0;
317 while (*str != '\0')
318 {
319 hval <<= 4;
320 hval += (unsigned long) *str++;
321 g = hval & ((unsigned long) 0xf << (HASHWORDBITS - 4));
322 if (g != 0)
323 {
324 hval ^= g >> (HASHWORDBITS - 8);
325 hval ^= g;
326 }
327 }
328 return hval;
329}
330
331/* Load the message catalogs specified by device. If it is no valid
332 message catalog do nothing. */
333void tl_nl_load_domain (TQIODevice* device, int size,
334 struct sk_kde_loaded_l10nfile *domain_file)
335{
336 struct mo_file_header *data = (struct mo_file_header *) -1;
337 struct loaded_domain *domain;
338
339 domain_file->decided = 1;
340 domain_file->data = NULL;
341
342 /* If the record does not represent a valid locale the FILENAME
343 might be NULL. This can happen when according to the given
344 specification the locale file name is different for XPG and CEN
345 syntax. */
346 if (device == NULL)
347 return;
348
349 /* Try to open the addressed file. */
350 if (device->open(IO_ReadOnly) == false)
351 return;
352
353 /* We must know about the size of the file. */
354 if (size < (off_t) sizeof (struct mo_file_header))
355 {
356 /* Something went wrong. */
357 device->close();
358 return;
359 }
360
361 /* If the data is not yet available (i.e. mmap'ed) we try to load
362 it manually. */
363 if (data == (struct mo_file_header *) -1)
364 {
365 off_t to_read;
366 char *read_ptr;
367
368 data = (struct mo_file_header *) malloc (size);
369 if (data == NULL)
370 return;
371
372 to_read = size;
373 read_ptr = (char *) data;
374 do
375 {
376 long int nb = (long int) device->readBlock (read_ptr, to_read);
377 if (nb == -1)
378 {
379 device->close();
380 return;
381 }
382
383 read_ptr += nb;
384 to_read -= nb;
385 }
386 while (to_read > 0);
387
388 device->close();
389 }
390
391 /* Using the magic number we can test whether it really is a message
392 catalog file. */
393 if (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED)
394 {
395 /* The magic number is wrong: not a message catalog file. */
396 free (data);
397 return;
398 }
399
400 domain_file->data
401 = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
402 if (domain_file->data == NULL)
403 return;
404
405 domain = (struct loaded_domain *) domain_file->data;
406 domain->data = (char *) data;
407 domain->must_swap = data->magic != _MAGIC;
408
409 /* Fill in the information about the available tables. */
410 switch (W (domain->must_swap, data->revision))
411 {
412 case 0:
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));
424 break;
425 default:
426 /* This is an illegal revision. */
427 free (data);
428 free (domain);
429 domain_file->data = NULL;
430 return;
431 }
432}
433
434void tl_nl_unload_domain (struct loaded_domain *domain)
435{
436 free ((void *) domain->data);
437 free (domain);
438}
ThemeFile
Definition: themefile.h:43
sk_kde_loaded_l10nfile
Definition: themelocale.h:33

superkaramba

Skip menu "superkaramba"
  • Main Page
  • Alphabetical List
  • Class List
  • File List
  • Class Members

superkaramba

Skip menu "superkaramba"
  • kcalc
  •   knumber
  • superkaramba
Generated for superkaramba by doxygen 1.9.4
This website is maintained by Timothy Pearson.