summaryrefslogtreecommitdiffabout
path: root/microkde/kdecore/klocale_new.cpp
Unidiff
Diffstat (limited to 'microkde/kdecore/klocale_new.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--microkde/kdecore/klocale_new.cpp2441
1 files changed, 2441 insertions, 0 deletions
diff --git a/microkde/kdecore/klocale_new.cpp b/microkde/kdecore/klocale_new.cpp
new file mode 100644
index 0000000..223b6c4
--- a/dev/null
+++ b/microkde/kdecore/klocale_new.cpp
@@ -0,0 +1,2441 @@
1// -*- c-basic-offset: 2 -*-
2/* This file is part of the KDE libraries
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 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
17
18 You should have received a copy of the GNU Library General Public License
19 along with this library; see the file COPYING.LIB. If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.
22*/
23
24//US#include <config.h>
25
26#include <stdlib.h> // getenv
27#include <assert.h>
28
29#include <qtextcodec.h>
30#include <qfile.h>
31#include <qdict.h>
32#include <qprinter.h>
33#include <qdatetime.h>
34#include <qfileinfo.h>
35#include <qregexp.h>
36
37#include "kcatalogue.h"
38#include "kglobal.h"
39#include "kstandarddirs.h"
40#include "ksimpleconfig.h"
41//US #include "kinstance.h"
42#include "kconfig.h"
43#include "kconfigbase.h"
44#include "kdebug.h"
45#include "kcalendarsystem.h"
46
47//US we use no factory. Simply use the gregorian calendar
48//US #include "kcalendarsystemfactory.h"
49#include "kcalendarsystemgregorian.h"
50
51#include "klocale.h"
52
53static const char * const SYSTEM_MESSAGES = "kdelibs";
54
55static const char *maincatalogue = 0;
56
57QDict<char> *mLocaleDict = 0;
58
59void setLocaleDict( QDict<char> * dict )
60{
61 mLocaleDict = dict;
62
63}
64
65class KLocalePrivate
66{
67public:
68 int weekStartDay;
69 int plural_form;
70 bool nounDeclension;
71 bool dateMonthNamePossessive;
72 QStringList languageList;
73 QValueList<KCatalogue> catalogues;
74 QString encoding;
75 QTextCodec * codecForEncoding;
76 KConfig * config;
77 bool formatInited;
78 int /*QPrinter::PageSize*/ pageSize;
79 KLocale::MeasureSystem measureSystem;
80 QStringList langTwoAlpha;
81 KConfig *languages;
82
83 QString calendarType;
84 KCalendarSystem * calendar;
85 QString first_language;
86 bool utf8FileEncoding;
87};
88
89static KLocale *this_klocale = 0;
90
91KLocale::KLocale( const QString & catalogue, KConfig * config )
92{
93 d = new KLocalePrivate;
94 d->config = config;
95 d->languages = 0;
96 d->calendar = 0;
97
98 initCatalogue(catalogue);
99 initEncoding(0);
100 initFileNameEncoding(0);
101
102 KConfig *cfg = d->config;
103 this_klocale = this;
104//US if (!cfg) cfg = KGlobal::instance()->config();
105 if (!cfg) cfg = KGlobal::config();
106 this_klocale = 0;
107//US Q_ASSERT( cfg );
108 ASSERT( cfg );
109
110 if (m_language.isEmpty())
111 initLanguage(cfg, config == 0);
112
113
114/*US
115//US mDateFormat = "%a %Y %b %d";
116//US mDateFormatShort = "%Y-%m-%d";
117 mTimeZoneList << i18n ("-11:00 US/Samoa")
118 << i18n ("-10:00 US/Hawaii")
119 << i18n ("-09:00 US/Alaska")
120 << i18n ("-08:00 US/Pacific")
121 << i18n ("-07:00 US/Mountain")
122 << i18n ("-06:00 US/Central")
123 << i18n ("-05:00 US/Eastern")
124 << i18n ("-04:00 Brazil/West")
125 << i18n ("-03:00 Brazil/East")
126 << i18n ("-02:00 Brazil/DeNoronha")
127 << i18n ("-01:00 Atlantic/Azores")
128 << i18n (" 00:00 Europe/London(UTC)")
129 << i18n ("+01:00 Europe/Oslo(CET)")
130 << i18n ("+02:00 Europe/Helsinki")
131 << i18n ("+03:00 Europe/Moscow")
132 << i18n ("+04:00 Indian/Mauritius")
133 << i18n ("+05:00 Indian/Maldives")
134 << i18n ("+06:00 Indian/Chagos")
135 << i18n ("+07:00 Asia/Bangkok")
136 << i18n ("+08:00 Asia/Hongkong")
137 << i18n ("+09:00 Asia/Tokyo")
138 << i18n ("+10:00 Asia/Vladivostok")
139 << i18n ("+11:00 Asia/Magadan")
140 << i18n ("+12:00 Asia/Kamchatka")
141 // << i18n (" xx:xx User defined offset")
142 << i18n (" Local Time");
143*/
144 mTimeZoneList << "-11:00 US/Samoa"
145 << "-10:00 US/Hawaii"
146 << "-09:00 US/Alaska"
147 << "-08:00 US/Pacific"
148 << "-07:00 US/Mountain"
149 << "-06:00 US/Central"
150 << "-05:00 US/Eastern"
151 << "-04:00 Brazil/West"
152 << "-03:00 Brazil/East"
153 << "-02:00 Brazil/DeNoronha"
154 << "-01:00 Atlantic/Azores"
155 << " 00:00 Europe/London(UTC)"
156 << "+01:00 Europe/Oslo(CET)"
157 << "+02:00 Europe/Helsinki"
158 << "+03:00 Europe/Moscow"
159 << "+04:00 Indian/Mauritius"
160 << "+05:00 Indian/Maldives"
161 << "+06:00 Indian/Chagos"
162 << "+07:00 Asia/Bangkok"
163 << "+08:00 Asia/Hongkong"
164 << "+09:00 Asia/Tokyo"
165 << "+10:00 Asia/Vladivostok"
166 << "+11:00 Asia/Magadan"
167 << "+12:00 Asia/Kamchatka"
168 // << " xx:xx User defined offset"
169 << " Local Time";
170
171 mSouthDaylight = false;
172 mTimeZoneOffset = 0;
173 daylightEnabled = false;
174
175 mWeekStartsMonday = true;
176 mHourF24Format = true;
177 mIntDateFormat = 0;
178 mLanguage = 0;
179
180}
181
182
183QString KLocale::_initLanguage(KConfigBase *config)
184{
185 if (this_klocale)
186 {
187 // ### HPB Why this cast??
188 this_klocale->initLanguage((KConfig *) config, true);
189 return this_klocale->language();
190 }
191 return QString::null;
192}
193
194void KLocale::initCatalogue(const QString & catalogue)
195{
196 // Use the first non-null string.
197 QString mainCatalogue = catalogue;
198 if (maincatalogue)
199 mainCatalogue = QString::fromLatin1(maincatalogue);
200
201 if (mainCatalogue.isEmpty()) {
202 kdDebug(173) << "KLocale instance created called without valid "
203 << "catalogue! Give an argument or call setMainCatalogue "
204 << "before init" << endl;
205 }
206 else
207 d->catalogues.append( KCatalogue(mainCatalogue ) );
208
209 // always include kdelibs.mo
210 d->catalogues.append( KCatalogue( SYSTEM_MESSAGES ) );
211}
212
213void KLocale::initLanguage(KConfig * config, bool useEnv)
214{
215 KConfigGroupSaver saver(config, "Locale");
216
217 m_country = config->readEntry( "Country" );
218 if ( m_country.isEmpty() )
219 m_country = defaultCountry();
220
221 // Reset the list and add the new languages
222 QStringList languageList;
223 if ( useEnv )
224 languageList += QStringList::split
225 (':', QFile::decodeName( ::getenv("KDE_LANG") ));
226
227//US languageList += config->readListEntry("Language", ':');
228 languageList += config->readListEntry("Language");
229
230 // same order as setlocale use
231 if ( useEnv )
232 {
233 // HPB: Only run splitLocale on the environment variables..
234 QStringList langs;
235
236 langs << QFile::decodeName( ::getenv("LC_ALL") );
237 langs << QFile::decodeName( ::getenv("LC_MESSAGES") );
238 langs << QFile::decodeName( ::getenv("LANG") );
239 langs << QFile::decodeName( ::getenv("LC_CTYPE") );
240
241 for ( QStringList::Iterator it = langs.begin();
242 it != langs.end();
243 ++it )
244 {
245 QString ln, ct, chrset;
246 splitLocale(*it, ln, ct, chrset);
247
248 if (!ct.isEmpty()) {
249 langs.insert(it, ln + '_' + ct);
250 if (!chrset.isEmpty())
251 langs.insert(it, ln + '_' + ct + '.' + chrset);
252 }
253
254 langs.insert(it, ln);
255 }
256
257 languageList += langs;
258 }
259
260 // now we have a language list -- let's use the first OK language
261 setLanguage( languageList );
262}
263
264void KLocale::doBindInit()
265{
266 return; // LR
267 for ( QValueList<KCatalogue>::Iterator it = d->catalogues.begin();
268 it != d->catalogues.end();
269 ++it )
270 initCatalogue( *it );
271
272 if ( useDefaultLanguage() )
273 d->plural_form = -1;
274 else
275 {
276 QString pf = translate_priv
277 ( I18N_NOOP("_: Dear translator, please do not translate this string "
278 "in any form, but pick the _right_ value out of "
279 "NoPlural/TwoForms/French... If not sure what to do mail "
280 "thd@kde.org and coolo@kde.org, they will tell you. "
281 "Better leave that out if unsure, the programs will "
282 "crash!!\nDefinition of PluralForm - to be set by the "
283 "translator of kdelibs.po"), 0);
284 if ( pf.isEmpty() ) {
285 kdWarning(173) << "found no definition of PluralForm for " << m_language << endl;
286 d->plural_form = -1;
287 } else if ( pf == "NoPlural" )
288 d->plural_form = 0;
289 else if ( pf == "TwoForms" )
290 d->plural_form = 1;
291 else if ( pf == "French" )
292 d->plural_form = 2;
293 else if ( pf == "OneTwoRest" || pf == "Gaeilge" ) // Gaelige is the old name
294 d->plural_form = 3;
295 else if ( pf == "Russian" )
296 d->plural_form = 4;
297 else if ( pf == "Polish" )
298 d->plural_form = 5;
299 else if ( pf == "Slovenian" )
300 d->plural_form = 6;
301 else if ( pf == "Lithuanian" )
302 d->plural_form = 7;
303 else if ( pf == "Czech" )
304 d->plural_form = 8;
305 else if ( pf == "Slovak" )
306 d->plural_form = 9;
307 else if ( pf == "Maltese" )
308 d->plural_form = 10;
309 else if ( pf == "Arabic" )
310 d->plural_form = 11;
311 else if ( pf == "Balcan" )
312 d->plural_form = 12;
313 else {
314 kdWarning(173) << "Definition of PluralForm is none of "
315 << "NoPlural/"
316 << "TwoForms/"
317 << "French/"
318 << "OneTwoRest/"
319 << "Russian/"
320 << "Polish/"
321 << "Slovenian/"
322 << "Lithuanian/"
323 << "Czech/"
324 << "Slovak/"
325 << "Arabic/"
326 << "Balcan/"
327 << "Maltese: " << pf << endl;
328 exit(1);
329 }
330 }
331
332 d->formatInited = false;
333}
334
335void KLocale::doFormatInit() const
336{
337 if ( d->formatInited ) return;
338
339 KLocale * that = const_cast<KLocale *>(this);
340 that->initFormat();
341
342 d->formatInited = true;
343}
344
345void KLocale::initFormat()
346{
347 KConfig *config = d->config;
348//US if (!config) config = KGlobal::instance()->config();
349 if (!config) config = KGlobal::config();
350 ASSERT( config );
351
352 kdDebug(173) << "KLocale::initFormat" << endl;
353
354 // make sure the config files are read using the correct locale
355 // ### Why not add a KConfigBase::setLocale( const KLocale * )?
356 // ### Then we could remove this hack
357//US
358//US KLocale *lsave = KGlobal::_locale;
359//US KGlobal::_locale = this;
360 KLocale *lsave = KGlobal::locale();
361 KGlobal::setLocale(this);
362
363 KConfigGroupSaver saver(config, "Locale");
364
365
366
367//US in kabc/adress.cpp we have a similar setup. Check there in case of problems
368 KSimpleConfig entry(locateLocal("locale",
369 QString::fromLatin1("l10n/%1/entry.desktop")
370 .arg(m_country)) );
371
372 entry.setGroup("KCM Locale");
373
374 // Numeric
375#define readConfigEntry(key, default, save) \
376 save = entry.readEntry(key, QString::fromLatin1(default)); \
377 save = config->readEntry(key, save);
378
379#define readConfigNumEntry(key, default, save, type) \
380 save = (type)entry.readNumEntry(key, default); \
381 save = (type)config->readNumEntry(key, save);
382
383#define readConfigBoolEntry(key, default, save) \
384 save = entry.readBoolEntry(key, default); \
385 save = config->readBoolEntry(key, save);
386
387 readConfigEntry("DecimalSymbol", ".", m_decimalSymbol);
388 readConfigEntry("ThousandsSeparator", ",", m_thousandsSeparator);
389 m_thousandsSeparator.replace( QString::fromLatin1("$0"), QString::null );
390 //kdDebug(173) << "m_thousandsSeparator=" << m_thousandsSeparator << endl;
391
392 readConfigEntry("PositiveSign", "", m_positiveSign);
393 readConfigEntry("NegativeSign", "-", m_negativeSign);
394
395 // Monetary
396 readConfigEntry("CurrencySymbol", "$", m_currencySymbol);
397 readConfigEntry("MonetaryDecimalSymbol", ".", m_monetaryDecimalSymbol);
398 readConfigEntry("MonetaryThousandsSeparator", ",",
399 m_monetaryThousandsSeparator);
400 m_monetaryThousandsSeparator.replace(QString::fromLatin1("$0"), QString::null);
401
402 readConfigNumEntry("FracDigits", 2, m_fracDigits, int);
403 readConfigBoolEntry("PositivePrefixCurrencySymbol", true,
404 m_positivePrefixCurrencySymbol);
405 readConfigBoolEntry("NegativePrefixCurrencySymbol", true,
406 m_negativePrefixCurrencySymbol);
407 readConfigNumEntry("PositiveMonetarySignPosition", (int)BeforeQuantityMoney,
408 m_positiveMonetarySignPosition, SignPosition);
409 readConfigNumEntry("NegativeMonetarySignPosition", (int)ParensAround,
410 m_negativeMonetarySignPosition, SignPosition);
411
412 //Grammatical
413 readConfigBoolEntry("NounDeclension", false, d->nounDeclension);
414
415 // Date and time
416 readConfigEntry("TimeFormat", "%H:%M:%S", m_timeFormat);
417 readConfigEntry("DateFormat", "%A %d %B %Y", m_dateFormat);
418 readConfigEntry("DateFormatShort", "%Y-%m-%d", m_dateFormatShort);
419 readConfigBoolEntry("DateMonthNamePossessive", false,
420 d->dateMonthNamePossessive);
421 readConfigNumEntry("WeekStartDay", 1, d->weekStartDay, int);
422
423 // other
424//US readConfigNumEntry("PageSize", (int)QPrinter::A4, d->pageSize, int);
425 readConfigNumEntry("MeasureSystem", (int)Metric, d->measureSystem,
426 MeasureSystem);
427 readConfigEntry("CalendarSystem", "gregorian", d->calendarType);
428 delete d->calendar;
429 d->calendar = 0; // ### HPB Is this the correct place?
430
431 // end of hack
432//US KGlobal::_locale = lsave;
433 KGlobal::setLocale(lsave);
434}
435
436bool KLocale::setCountry(const QString & country)
437{
438 // Check if the file exists too??
439 if ( country.isEmpty() )
440 return false;
441
442 m_country = country;
443
444 d->formatInited = false;
445
446 return true;
447}
448
449QString KLocale::catalogueFileName(const QString & language,
450 const KCatalogue & catalogue)
451{
452 QString path = QString::fromLatin1("%1/LC_MESSAGES/%2.mo")
453 .arg( language )
454 .arg( catalogue.name() );
455
456 return locate( "locale", path );
457}
458
459bool KLocale::isLanguageInstalled(const QString & language) const
460{
461 // Do not allow empty languages
462 if ( language.isEmpty() ) return false;
463
464 bool bRes = true;
465 if ( language != defaultLanguage() )
466 for ( QValueList<KCatalogue>::ConstIterator it = d->catalogues.begin();
467 it != d->catalogues.end() && bRes;
468 ++it )
469 {
470 bRes = !catalogueFileName( language, *it ).isNull();
471 if ( !bRes )
472 kdDebug(173) << "message catalogue not found: "
473 << (*it).name() << endl;
474 }
475
476 return bRes;
477}
478
479bool KLocale::setLanguage(const QString & language)
480{
481 bool bRes = true;
482
483 if (d->first_language.isNull() || language != d->first_language)
484 bRes = isLanguageInstalled( language );
485
486 if ( bRes )
487 {
488 m_language = language;
489
490 // remember our first time - it will be our true love
491 if (d->first_language.isNull())
492 d->first_language = language;
493
494 doBindInit();
495 }
496
497 return bRes;
498}
499
500bool KLocale::setLanguage(const QStringList & languages)
501{
502 QStringList languageList(languages);
503
504 // Remove duplicate entries in reverse so that we
505 // can keep user's language preference order intact. (DA)
506 for( QStringList::Iterator it = languageList.fromLast();
507 it != languageList.begin();
508 --it )
509 if ( languageList.contains(*it) > 1 || (*it).isEmpty() )
510 it = languageList.remove( it );
511
512 bool bRes = false;
513 for ( QStringList::ConstIterator it = languageList.begin();
514 it != languageList.end();
515 ++it )
516 if ( bRes = setLanguage( *it ) )
517 break;
518
519 if ( !bRes )
520 setLanguage(defaultLanguage());
521
522 d->languageList = languageList;
523 d->langTwoAlpha.clear(); // Flush cache
524
525 return bRes;
526}
527
528void KLocale::splitLocale(const QString & aStr,
529 QString & language,
530 QString & country,
531 QString & chrset)
532{
533 QString str = aStr;
534
535 // just in case, there is another language appended
536 int f = str.find(':');
537 if (f >= 0)
538 str.truncate(f);
539
540 country = QString::null;
541 chrset = QString::null;
542 language = QString::null;
543
544 f = str.find('.');
545 if (f >= 0)
546 {
547 chrset = str.mid(f + 1);
548 str.truncate(f);
549 }
550
551 f = str.find('_');
552 if (f >= 0)
553 {
554 country = str.mid(f + 1);
555 str.truncate(f);
556 }
557
558 language = str;
559}
560
561QString KLocale::language() const
562{
563 return m_language;
564}
565
566QString KLocale::country() const
567{
568 return m_country;
569}
570
571QString KLocale::monthName(int i, bool shortName) const
572{
573 if ( shortName )
574 switch ( i )
575 {
576 case 1: return translate("January", "Jan");
577 case 2: return translate("February", "Feb");
578 case 3: return translate("March", "Mar");
579 case 4: return translate("April", "Apr");
580 case 5: return translate("May short", "May");
581 case 6: return translate("June", "Jun");
582 case 7: return translate("July", "Jul");
583 case 8: return translate("August", "Aug");
584 case 9: return translate("September", "Sep");
585 case 10: return translate("October", "Oct");
586 case 11: return translate("November", "Nov");
587 case 12: return translate("December", "Dec");
588 }
589 else
590 switch (i)
591 {
592 case 1: return translate("January");
593 case 2: return translate("February");
594 case 3: return translate("March");
595 case 4: return translate("April");
596 case 5: return translate("May long", "May");
597 case 6: return translate("June");
598 case 7: return translate("July");
599 case 8: return translate("August");
600 case 9: return translate("September");
601 case 10: return translate("October");
602 case 11: return translate("November");
603 case 12: return translate("December");
604 }
605
606 return QString::null;
607}
608
609QString KLocale::monthNamePossessive(int i, bool shortName) const
610{
611 if ( shortName )
612 switch ( i )
613 {
614 case 1: return translate("of January", "of Jan");
615 case 2: return translate("of February", "of Feb");
616 case 3: return translate("of March", "of Mar");
617 case 4: return translate("of April", "of Apr");
618 case 5: return translate("of May short", "of May");
619 case 6: return translate("of June", "of Jun");
620 case 7: return translate("of July", "of Jul");
621 case 8: return translate("of August", "of Aug");
622 case 9: return translate("of September", "of Sep");
623 case 10: return translate("of October", "of Oct");
624 case 11: return translate("of November", "of Nov");
625 case 12: return translate("of December", "of Dec");
626 }
627 else
628 switch (i)
629 {
630 case 1: return translate("of January");
631 case 2: return translate("of February");
632 case 3: return translate("of March");
633 case 4: return translate("of April");
634 case 5: return translate("of May long", "of May");
635 case 6: return translate("of June");
636 case 7: return translate("of July");
637 case 8: return translate("of August");
638 case 9: return translate("of September");
639 case 10: return translate("of October");
640 case 11: return translate("of November");
641 case 12: return translate("of December");
642 }
643
644 return QString::null;
645}
646
647QString KLocale::weekDayName (int i, bool shortName) const
648{
649 if ( shortName )
650 switch ( i )
651 {
652 case 1: return translate("Monday", "Mon");
653 case 2: return translate("Tuesday", "Tue");
654 case 3: return translate("Wednesday", "Wed");
655 case 4: return translate("Thursday", "Thu");
656 case 5: return translate("Friday", "Fri");
657 case 6: return translate("Saturday", "Sat");
658 case 7: return translate("Sunday", "Sun");
659 }
660 else
661 switch ( i )
662 {
663 case 1: return translate("Monday");
664 case 2: return translate("Tuesday");
665 case 3: return translate("Wednesday");
666 case 4: return translate("Thursday");
667 case 5: return translate("Friday");
668 case 6: return translate("Saturday");
669 case 7: return translate("Sunday");
670 }
671
672 return QString::null;
673}
674
675void KLocale::insertCatalogue( const QString & catalogue )
676{
677 KCatalogue cat( catalogue );
678
679 initCatalogue( cat );
680
681 d->catalogues.append( cat );
682}
683
684void KLocale::removeCatalogue(const QString &catalogue)
685{
686 for ( QValueList<KCatalogue>::Iterator it = d->catalogues.begin();
687 it != d->catalogues.end(); )
688 if ((*it).name() == catalogue) {
689 it = d->catalogues.remove(it);
690 return;
691 } else
692 ++it;
693}
694
695void KLocale::setActiveCatalogue(const QString &catalogue)
696{
697 for ( QValueList<KCatalogue>::Iterator it = d->catalogues.begin();
698 it != d->catalogues.end(); ++it)
699 if ((*it).name() == catalogue) {
700 KCatalogue save = *it;
701 d->catalogues.remove(it);
702 d->catalogues.prepend(save);
703 return;
704 }
705}
706
707KLocale::~KLocale()
708{
709 delete d->languages;
710 delete d;
711}
712
713QString KLocale::translate_priv(const char *msgid,
714 const char *fallback,
715 const char **translated) const
716{
717 if (!msgid || !msgid[0])
718 {
719 kdWarning() << "KLocale: trying to look up \"\" in catalogue. "
720 << "Fix the program" << endl;
721 return QString::null;
722 }
723
724 if ( useDefaultLanguage() )
725 return QString::fromUtf8( fallback );
726
727 for ( QValueList<KCatalogue>::ConstIterator it = d->catalogues.begin();
728 it != d->catalogues.end();
729 ++it )
730 {
731 // kdDebug(173) << "translate " << msgid << " " << (*it).name() << " " << (!KGlobal::activeInstance() ? QCString("no instance") : KGlobal::activeInstance()->instanceName()) << endl;
732 const char * text = (*it).translate( msgid );
733
734 if ( text )
735 {
736 // we found it
737 if (translated)
738 *translated = text;
739 return QString::fromUtf8( text );
740 }
741 }
742
743 // Always use UTF-8 if the string was not found
744 return QString::fromUtf8( fallback );
745}
746
747QString KLocale::translate(const char* msgid) const
748{
749 return translate_priv(msgid, msgid);
750}
751
752QString KLocale::translate( const char *index, const char *fallback) const
753{
754 if (!index || !index[0] || !fallback || !fallback[0])
755 {
756 kdDebug(173) << "KLocale: trying to look up \"\" in catalogue. "
757 << "Fix the program" << endl;
758 return QString::null;
759 }
760
761 if ( useDefaultLanguage() )
762 return QString::fromUtf8( fallback );
763
764 char *newstring = new char[strlen(index) + strlen(fallback) + 5];
765 sprintf(newstring, "_: %s\n%s", index, fallback);
766 // as copying QString is very fast, it looks slower as it is ;/
767 QString r = translate_priv(newstring, fallback);
768 delete [] newstring;
769
770 return r;
771}
772
773static QString put_n_in(const QString &orig, unsigned long n)
774{
775 QString ret = orig;
776 int index = ret.find("%n");
777 if (index == -1)
778 return ret;
779 ret.replace(index, 2, QString::number(n));
780 return ret;
781}
782
783#define EXPECT_LENGTH(x) \
784 if (forms.count() != x) { \
785 kdError() << "translation of \"" << singular << "\" doesn't contain " << x << " different plural forms as expected\n"; \
786 return QString( "BROKEN TRANSLATION %1" ).arg( singular ); }
787
788QString KLocale::translate( const char *singular, const char *plural,
789 unsigned long n ) const
790{
791 if (!singular || !singular[0] || !plural || !plural[0])
792 {
793 kdWarning() << "KLocale: trying to look up \"\" in catalogue. "
794 << "Fix the program" << endl;
795 return QString::null;
796 }
797
798 char *newstring = new char[strlen(singular) + strlen(plural) + 6];
799 sprintf(newstring, "_n: %s\n%s", singular, plural);
800 // as copying QString is very fast, it looks slower as it is ;/
801 QString r = translate_priv(newstring, 0);
802 delete [] newstring;
803
804 if ( r.isEmpty() || useDefaultLanguage() || d->plural_form == -1) {
805 if ( n == 1 ) {
806 return put_n_in( QString::fromUtf8( singular ), n );
807 } else {
808 QString tmp = QString::fromUtf8( plural );
809#ifndef NDEBUG
810 if (tmp.find("%n") == -1) {
811 kdWarning() << "the message for i18n should contain a '%n'! " << plural << endl;
812 }
813#endif
814 return put_n_in( tmp, n );
815 }
816 }
817
818 QStringList forms = QStringList::split( "\n", r, false );
819 switch ( d->plural_form ) {
820 case 0: // NoPlural
821 EXPECT_LENGTH( 1 );
822 return put_n_in( forms[0], n);
823 case 1: // TwoForms
824 EXPECT_LENGTH( 2 );
825 if ( n == 1 )
826 return put_n_in( forms[0], n);
827 else
828 return put_n_in( forms[1], n);
829 case 2: // French
830 EXPECT_LENGTH( 2 );
831 if ( n == 1 || n == 0 )
832 return put_n_in( forms[0], n);
833 else
834 return put_n_in( forms[1], n);
835 case 3: // Gaeilge
836 EXPECT_LENGTH( 3 );
837 if ( n == 1 )
838 return put_n_in( forms[0], n);
839 else if ( n == 2 )
840 return put_n_in( forms[1], n);
841 else
842 return put_n_in( forms[2], n);
843 case 4: // Russian, corrected by mok
844 EXPECT_LENGTH( 3 );
845 if ( n%10 == 1 && n%100 != 11)
846 return put_n_in( forms[0], n); // odin fail
847 else if (( n%10 >= 2 && n%10 <=4 ) && (n%100<10 || n%100>20))
848 return put_n_in( forms[1], n); // dva faila
849 else
850 return put_n_in( forms[2], n); // desyat' failov
851 case 5: // Polish
852 EXPECT_LENGTH( 3 );
853 if ( n == 1 )
854 return put_n_in( forms[0], n);
855 else if ( n%10 >= 2 && n%10 <=4 && (n%100<10 || n%100>=20) )
856 return put_n_in( forms[1], n);
857 else
858 return put_n_in( forms[2], n);
859 case 6: // Slovenian
860 EXPECT_LENGTH( 4 );
861 if ( n%100 == 1 )
862 return put_n_in( forms[1], n); // ena datoteka
863 else if ( n%100 == 2 )
864 return put_n_in( forms[2], n); // dve datoteki
865 else if ( n%100 == 3 || n%100 == 4 )
866 return put_n_in( forms[3], n); // tri datoteke
867 else
868 return put_n_in( forms[0], n); // sto datotek
869 case 7: // Lithuanian
870 EXPECT_LENGTH( 3 );
871 if ( n%10 == 0 || (n%100>=11 && n%100<=19) )
872 return put_n_in( forms[2], n);
873 else if ( n%10 == 1 )
874 return put_n_in( forms[0], n);
875 else
876 return put_n_in( forms[1], n);
877 case 8: // Czech
878 EXPECT_LENGTH( 3 );
879 if ( n%100 == 1 )
880 return put_n_in( forms[0], n);
881 else if (( n%100 >= 2 ) && ( n%100 <= 4 ))
882 return put_n_in( forms[1], n);
883 else
884 return put_n_in( forms[2], n);
885 case 9: // Slovak
886 EXPECT_LENGTH( 3 );
887 if ( n == 1 )
888 return put_n_in( forms[0], n);
889 else if (( n >= 2 ) && ( n <= 4 ))
890 return put_n_in( forms[1], n);
891 else
892 return put_n_in( forms[2], n);
893 case 10: // Maltese
894 EXPECT_LENGTH( 4 );
895 if ( n == 1 )
896 return put_n_in( forms[0], n );
897 else if ( ( n == 0 ) || ( n%100 > 0 && n%100 <= 10 ) )
898 return put_n_in( forms[1], n );
899 else if ( n%100 > 10 && n%100 < 20 )
900 return put_n_in( forms[2], n );
901 else
902 return put_n_in( forms[3], n );
903 case 11: // Arabic
904 EXPECT_LENGTH( 4 );
905 if (n == 1)
906 return put_n_in(forms[0], n);
907 else if (n == 2)
908 return put_n_in(forms[1], n);
909 else if ( n < 11)
910 return put_n_in(forms[2], n);
911 else
912 return put_n_in(forms[3], n);
913 case 12: // Balcan
914 EXPECT_LENGTH( 3 );
915 if (n != 11 && n % 10 == 1)
916 return put_n_in(forms[0], n);
917 else if (n / 10 != 1 && n % 10 >= 2 && n % 10 <= 4)
918 return put_n_in(forms[1], n);
919 else
920 return put_n_in(forms[2], n);
921 }
922 kdError() << "The function should have been returned in another way\n";
923
924 return QString::null;
925}
926
927QString KLocale::translateQt( const char *context, const char *source,
928 const char *message) const
929{
930 if (!source || !source[0]) {
931 kdWarning() << "KLocale: trying to look up \"\" in catalogue. "
932 << "Fix the program" << endl;
933 return QString::null;
934 }
935
936 if ( useDefaultLanguage() ) {
937 return QString::null;
938 }
939
940 char *newstring = 0;
941 const char *translation = 0;
942 QString r;
943
944 if ( message && message[0]) {
945 char *newstring = new char[strlen(source) + strlen(message) + 5];
946 sprintf(newstring, "_: %s\n%s", source, message);
947 const char *translation = 0;
948 // as copying QString is very fast, it looks slower as it is ;/
949 r = translate_priv(newstring, source, &translation);
950 delete [] newstring;
951 if (translation)
952 return r;
953 }
954
955 if ( context && context[0] && message && message[0]) {
956 newstring = new char[strlen(context) + strlen(message) + 5];
957 sprintf(newstring, "_: %s\n%s", context, message);
958 // as copying QString is very fast, it looks slower as it is ;/
959 r = translate_priv(newstring, source, &translation);
960 delete [] newstring;
961 if (translation)
962 return r;
963 }
964
965 r = translate_priv(source, source, &translation);
966 if (translation)
967 return r;
968 return QString::null;
969}
970
971bool KLocale::nounDeclension() const
972{
973 doFormatInit();
974 return d->nounDeclension;
975}
976
977bool KLocale::dateMonthNamePossessive() const
978{
979 doFormatInit();
980 return d->dateMonthNamePossessive;
981}
982
983int KLocale::weekStartDay() const
984{
985 doFormatInit();
986 return d->weekStartDay;
987}
988
989bool KLocale::weekStartsMonday() const //deprecated
990{
991 doFormatInit();
992 return (d->weekStartDay==1);
993}
994
995QString KLocale::decimalSymbol() const
996{
997 doFormatInit();
998 return m_decimalSymbol;
999}
1000
1001QString KLocale::thousandsSeparator() const
1002{
1003 doFormatInit();
1004 return m_thousandsSeparator;
1005}
1006
1007QString KLocale::currencySymbol() const
1008{
1009 doFormatInit();
1010 return m_currencySymbol;
1011}
1012
1013QString KLocale::monetaryDecimalSymbol() const
1014{
1015 doFormatInit();
1016 return m_monetaryDecimalSymbol;
1017}
1018
1019QString KLocale::monetaryThousandsSeparator() const
1020{
1021 doFormatInit();
1022 return m_monetaryThousandsSeparator;
1023}
1024
1025QString KLocale::positiveSign() const
1026{
1027 doFormatInit();
1028 return m_positiveSign;
1029}
1030
1031QString KLocale::negativeSign() const
1032{
1033 doFormatInit();
1034 return m_negativeSign;
1035}
1036
1037int KLocale::fracDigits() const
1038{
1039 doFormatInit();
1040 return m_fracDigits;
1041}
1042
1043bool KLocale::positivePrefixCurrencySymbol() const
1044{
1045 doFormatInit();
1046 return m_positivePrefixCurrencySymbol;
1047}
1048
1049bool KLocale::negativePrefixCurrencySymbol() const
1050{
1051 doFormatInit();
1052 return m_negativePrefixCurrencySymbol;
1053}
1054
1055KLocale::SignPosition KLocale::positiveMonetarySignPosition() const
1056{
1057 doFormatInit();
1058 return m_positiveMonetarySignPosition;
1059}
1060
1061KLocale::SignPosition KLocale::negativeMonetarySignPosition() const
1062{
1063 doFormatInit();
1064 return m_negativeMonetarySignPosition;
1065}
1066
1067static inline void put_it_in( QChar *buffer, uint& index, const QString &s )
1068{
1069 for ( uint l = 0; l < s.length(); l++ )
1070 buffer[index++] = s.at( l );
1071}
1072
1073static inline void put_it_in( QChar *buffer, uint& index, int number )
1074{
1075 buffer[index++] = number / 10 + '0';
1076 buffer[index++] = number % 10 + '0';
1077}
1078
1079QString KLocale::formatMoney(double num,
1080 const QString & symbol,
1081 int precision) const
1082{
1083 // some defaults
1084 QString currency = symbol.isNull()
1085 ? currencySymbol()
1086 : symbol;
1087 if (precision < 0) precision = fracDigits();
1088
1089 // the number itself
1090 bool neg = num < 0;
1091 QString res = QString::number(neg?-num:num, 'f', precision);
1092 int pos = res.find('.');
1093 if (pos == -1) pos = res.length();
1094 else res.replace(pos, 1, monetaryDecimalSymbol());
1095
1096 while (0 < (pos -= 3))
1097 res.insert(pos, monetaryThousandsSeparator()); // thousend sep
1098
1099 // set some variables we need later
1100 int signpos = neg
1101 ? negativeMonetarySignPosition()
1102 : positiveMonetarySignPosition();
1103 QString sign = neg
1104 ? negativeSign()
1105 : positiveSign();
1106
1107 switch (signpos)
1108 {
1109 case ParensAround:
1110 res.prepend('(');
1111 res.append (')');
1112 break;
1113 case BeforeQuantityMoney:
1114 res.prepend(sign);
1115 break;
1116 case AfterQuantityMoney:
1117 res.append(sign);
1118 break;
1119 case BeforeMoney:
1120 currency.prepend(sign);
1121 break;
1122 case AfterMoney:
1123 currency.append(sign);
1124 break;
1125 }
1126
1127 if (neg?negativePrefixCurrencySymbol():
1128 positivePrefixCurrencySymbol())
1129 {
1130 res.prepend(' ');
1131 res.prepend(currency);
1132 } else {
1133 res.append (' ');
1134 res.append (currency);
1135 }
1136
1137 return res;
1138}
1139
1140QString KLocale::formatMoney(const QString &numStr) const
1141{
1142 return formatMoney(numStr.toDouble());
1143}
1144
1145QString KLocale::formatNumber(double num, int precision) const
1146{
1147 bool neg = num < 0;
1148 if (precision == -1) precision = 2;
1149 QString res = QString::number(neg?-num:num, 'f', precision);
1150 int pos = res.find('.');
1151 if (pos == -1) pos = res.length();
1152 else res.replace(pos, 1, decimalSymbol());
1153
1154 while (0 < (pos -= 3))
1155 res.insert(pos, thousandsSeparator()); // thousand sep
1156
1157 // How can we know where we should put the sign?
1158 res.prepend(neg?negativeSign():positiveSign());
1159
1160 return res;
1161}
1162
1163QString KLocale::formatLong(long num) const
1164{
1165 return formatNumber((double)num, 0);
1166}
1167
1168QString KLocale::formatNumber(const QString &numStr) const
1169{
1170 return formatNumber(numStr.toDouble());
1171}
1172
1173QString KLocale::formatDate(const QDate &pDate, bool shortFormat) const
1174{
1175 const QString rst = shortFormat?dateFormatShort():dateFormat();
1176
1177 // I'm rather safe than sorry
1178 QChar *buffer = new QChar[rst.length() * 3 / 2 + 50];
1179
1180 unsigned int index = 0;
1181 bool escape = false;
1182 int number = 0;
1183
1184 int year = calendar()->year(pDate);
1185 int month = calendar()->month(pDate);
1186 int day = calendar()->day(pDate);
1187
1188 for ( uint format_index = 0; format_index < rst.length(); ++format_index )
1189 {
1190 if ( !escape )
1191 {
1192 if ( rst.at( format_index ).unicode() == '%' )
1193 escape = true;
1194 else
1195 buffer[index++] = rst.at( format_index );
1196 }
1197 else
1198 {
1199 switch ( rst.at( format_index ).unicode() )
1200 {
1201 case '%':
1202 buffer[index++] = '%';
1203 break;
1204 case 'Y':
1205 put_it_in( buffer, index, year / 100 );
1206 case 'y':
1207 put_it_in( buffer, index, year % 100 );
1208 break;
1209 case 'n':
1210 number = month;
1211 case 'e':
1212 // to share the code
1213 if ( rst.at( format_index ).unicode() == 'e' )
1214 number = day;
1215 if ( number / 10 )
1216 buffer[index++] = number / 10 + '0';
1217 buffer[index++] = number % 10 + '0';
1218 break;
1219 case 'm':
1220 put_it_in( buffer, index, month );
1221 break;
1222 case 'b':
1223 if (d->nounDeclension && d->dateMonthNamePossessive)
1224 //US put_it_in( buffer, index, calendar()->monthNamePossessive(month, year, true) );
1225 put_it_in( buffer, index, calendar()->monthNamePossessive(month, true) );
1226 else
1227 //US put_it_in( buffer, index, calendar()->monthName(month, year, true) );
1228 put_it_in( buffer, index, calendar()->monthName(month, true) );
1229 break;
1230 case 'B':
1231 if (d->nounDeclension && d->dateMonthNamePossessive)
1232 //US put_it_in( buffer, index, calendar()->monthNamePossessive(month, year, false) );
1233 put_it_in( buffer, index, calendar()->monthNamePossessive(month, false) );
1234 else
1235 //US put_it_in( buffer, index, calendar()->monthName(month, year, false) );
1236 put_it_in( buffer, index, calendar()->monthName(month, false) );
1237 break;
1238 case 'd':
1239 put_it_in( buffer, index, day );
1240 break;
1241 case 'a':
1242 put_it_in( buffer, index, calendar()->weekDayName(pDate, true) );
1243 break;
1244 case 'A':
1245 put_it_in( buffer, index, calendar()->weekDayName(pDate, false) );
1246 break;
1247 default:
1248 buffer[index++] = rst.at( format_index );
1249 break;
1250 }
1251 escape = false;
1252 }
1253 }
1254 QString ret( buffer, index );
1255 delete [] buffer;
1256 return ret;
1257}
1258
1259void KLocale::setMainCatalogue(const char *catalogue)
1260{
1261 maincatalogue = catalogue;
1262}
1263
1264double KLocale::readNumber(const QString &_str, bool * ok) const
1265{
1266 QString str = _str.stripWhiteSpace();
1267 bool neg = str.find(negativeSign()) == 0;
1268 if (neg)
1269 str.remove( 0, negativeSign().length() );
1270
1271 /* will hold the scientific notation portion of the number.
1272 Example, with 2.34E+23, exponentialPart == "E+23"
1273 */
1274 QString exponentialPart;
1275 int EPos;
1276
1277 EPos = str.find('E', 0, false);
1278
1279 if (EPos != -1)
1280 {
1281 exponentialPart = str.mid(EPos);
1282 str = str.left(EPos);
1283 }
1284
1285 int pos = str.find(decimalSymbol());
1286 QString major;
1287 QString minor;
1288 if ( pos == -1 )
1289 major = str;
1290 else
1291 {
1292 major = str.left(pos);
1293 minor = str.mid(pos + decimalSymbol().length());
1294 }
1295
1296 // Remove thousand separators
1297 int thlen = thousandsSeparator().length();
1298 int lastpos = 0;
1299 while ( ( pos = major.find( thousandsSeparator() ) ) > 0 )
1300 {
1301 // e.g. 12,,345,,678,,922 Acceptable positions (from the end) are 5, 10, 15... i.e. (3+thlen)*N
1302 int fromEnd = major.length() - pos;
1303 if ( fromEnd % (3+thlen) != 0 // Needs to be a multiple, otherwise it's an error
1304 || pos - lastpos > 3 // More than 3 digits between two separators -> error
1305 || pos == 0 // Can't start with a separator
1306 || (lastpos>0 && pos-lastpos!=3)) // Must have exactly 3 digits between two separators
1307 {
1308 if (ok) *ok = false;
1309 return 0.0;
1310 }
1311
1312 lastpos = pos;
1313 major.remove( pos, thlen );
1314 }
1315 if (lastpos>0 && major.length()-lastpos!=3) // Must have exactly 3 digits after the last separator
1316 {
1317 if (ok) *ok = false;
1318 return 0.0;
1319 }
1320
1321 QString tot;
1322 if (neg) tot = '-';
1323
1324 tot += major + '.' + minor + exponentialPart;
1325
1326 return tot.toDouble(ok);
1327}
1328
1329double KLocale::readMoney(const QString &_str, bool * ok) const
1330{
1331 QString str = _str.stripWhiteSpace();
1332 bool neg = false;
1333 bool currencyFound = false;
1334 // First try removing currency symbol from either end
1335 int pos = str.find(currencySymbol());
1336 if ( pos == 0 || pos == (int) str.length()-1 )
1337 {
1338 str.remove(pos,currencySymbol().length());
1339 str = str.stripWhiteSpace();
1340 currencyFound = true;
1341 }
1342 if (str.isEmpty())
1343 {
1344 if (ok) *ok = false;
1345 return 0;
1346 }
1347 // Then try removing negative sign from either end
1348 // (with a special case for parenthesis)
1349 if (negativeMonetarySignPosition() == ParensAround)
1350 {
1351 if (str.at(0) == '(' && str.at(str.length()-1) == ')')
1352 {
1353 neg = true;
1354 str.remove(str.length()-1,1);
1355 str.remove(0,1);
1356 }
1357 }
1358 else
1359 {
1360 int i1 = str.find(negativeSign());
1361 if ( i1 == 0 || i1 == (int) str.length()-1 )
1362 {
1363 neg = true;
1364 str.remove(i1,negativeSign().length());
1365 }
1366 }
1367 if (neg) str = str.stripWhiteSpace();
1368
1369 // Finally try again for the currency symbol, if we didn't find
1370 // it already (because of the negative sign being in the way).
1371 if ( !currencyFound )
1372 {
1373 pos = str.find(currencySymbol());
1374 if ( pos == 0 || pos == (int) str.length()-1 )
1375 {
1376 str.remove(pos,currencySymbol().length());
1377 str = str.stripWhiteSpace();
1378 }
1379 }
1380
1381 // And parse the rest as a number
1382 pos = str.find(monetaryDecimalSymbol());
1383 QString major;
1384 QString minior;
1385 if (pos == -1)
1386 major = str;
1387 else
1388 {
1389 major = str.left(pos);
1390 minior = str.mid(pos + monetaryDecimalSymbol().length());
1391 }
1392
1393 // Remove thousand separators
1394 int thlen = monetaryThousandsSeparator().length();
1395 int lastpos = 0;
1396 while ( ( pos = major.find( monetaryThousandsSeparator() ) ) > 0 )
1397 {
1398 // e.g. 12,,345,,678,,922 Acceptable positions (from the end) are 5, 10, 15... i.e. (3+thlen)*N
1399 int fromEnd = major.length() - pos;
1400 if ( fromEnd % (3+thlen) != 0 // Needs to be a multiple, otherwise it's an error
1401 || pos - lastpos > 3 // More than 3 digits between two separators -> error
1402 || pos == 0 // Can't start with a separator
1403 || (lastpos>0 && pos-lastpos!=3)) // Must have exactly 3 digits between two separators
1404 {
1405 if (ok) *ok = false;
1406 return 0.0;
1407 }
1408 lastpos = pos;
1409 major.remove( pos, thlen );
1410 }
1411 if (lastpos>0 && major.length()-lastpos!=3) // Must have exactly 3 digits after the last separator
1412 {
1413 if (ok) *ok = false;
1414 return 0.0;
1415 }
1416
1417 QString tot;
1418 if (neg) tot = '-';
1419 tot += major + '.' + minior;
1420 return tot.toDouble(ok);
1421}
1422
1423/**
1424 * helper function to read integers
1425 * @param str
1426 * @param pos the position to start at. It will be updated when we parse it.
1427 * @return the integer read in the string, or -1 if no string
1428 */
1429static int readInt(const QString &str, uint &pos)
1430{
1431 if (!str.at(pos).isDigit()) return -1;
1432 int result = 0;
1433 for (; str.length() > pos && str.at(pos).isDigit(); pos++)
1434 {
1435 result *= 10;
1436 result += str.at(pos).digitValue();
1437 }
1438
1439 return result;
1440}
1441
1442QDate KLocale::readDate(const QString &intstr, bool* ok) const
1443{
1444 QDate date;
1445 date = readDate(intstr, ShortFormat, ok);
1446 if (date.isValid()) return date;
1447 return readDate(intstr, NormalFormat, ok);
1448}
1449
1450QDate KLocale::readDate(const QString &intstr, ReadDateFlags flags, bool* ok) const
1451{
1452 QString fmt = ((flags & ShortFormat) ? dateFormatShort() : dateFormat()).simplifyWhiteSpace();
1453 return readDate( intstr, fmt, ok );
1454}
1455
1456QDate KLocale::readDate(const QString &intstr, const QString &fmt, bool* ok) const
1457{
1458 //kdDebug() << "KLocale::readDate intstr=" << intstr << " fmt=" << fmt << endl;
1459 QString str = intstr.simplifyWhiteSpace().lower();
1460 int day = -1, month = -1;
1461 // allow the year to be omitted if not in the format
1462 int year = calendar()->year(QDate::currentDate());
1463 uint strpos = 0;
1464 uint fmtpos = 0;
1465
1466 bool error = false;
1467
1468 while (fmt.length() > fmtpos && str.length() > strpos && !error)
1469 {
1470
1471 QChar c = fmt.at(fmtpos++);
1472
1473 if (c != '%') {
1474 if (c.isSpace() && str.at(strpos).isSpace())
1475 strpos++;
1476 else if (c != str.at(strpos++))
1477 error = true;
1478 }
1479 else
1480 {
1481 int j;
1482 // remove space at the begining
1483 if (str.length() > strpos && str.at(strpos).isSpace())
1484 strpos++;
1485
1486 c = fmt.at(fmtpos++);
1487 switch (c)
1488 {
1489 case 'a':
1490 case 'A':
1491
1492 error = true;
1493 j = 1;
1494 while (error && (j < 8)) {
1495 QString s = weekDayName(j, c == 'a').lower();
1496 int len = s.length();
1497 if (str.mid(strpos, len) == s)
1498 {
1499 strpos += len;
1500 error = false;
1501 }
1502 j++;
1503 }
1504 break;
1505 case 'b':
1506 case 'B':
1507
1508 error = true;
1509 if (d->nounDeclension && d->dateMonthNamePossessive) {
1510 j = 1;
1511 while (error && (j < 13)) {
1512 //US QString s = calendar()->monthNamePossessive(j, year, c == 'b').lower();
1513 QString s = calendar()->monthNamePossessive(j, c == 'b').lower();
1514 int len = s.length();
1515 if (str.mid(strpos, len) == s) {
1516 month = j;
1517 strpos += len;
1518 error = false;
1519 }
1520 j++;
1521 }
1522 }
1523 j = 1;
1524 while (error && (j < 13)) {
1525 //US QString s = calendar()->monthName(j, year, c == 'b').lower();
1526 QString s = calendar()->monthName(j, c == 'b').lower();
1527 int len = s.length();
1528 if (str.mid(strpos, len) == s) {
1529 month = j;
1530 strpos += len;
1531 error = false;
1532 }
1533 j++;
1534 }
1535 break;
1536 case 'd':
1537 case 'e':
1538 day = readInt(str, strpos);
1539 error = (day < 1 || day > 31);
1540 break;
1541
1542 case 'n':
1543 case 'm':
1544 month = readInt(str, strpos);
1545 error = (month < 1 || month > 12);
1546 break;
1547
1548 case 'Y':
1549 case 'y':
1550 year = readInt(str, strpos);
1551 error = (year < 0);
1552 // Qt treats a year in the range 0-100 as 1900-1999.
1553 // It is nicer for the user if we treat 0-68 as 2000-2068
1554 if (c == 'y' && year < 69)
1555 // eg. gregorian += 2000
1556 year += (calendar()->year(QDate::currentDate()) / 100) * 100;
1557 else if (c == 'y' && year < 100)
1558 // eg. gregorian += 1900
1559 year += (calendar()->year(QDate::currentDate()) / 100) * 100 - 100;
1560 break;
1561 }
1562 }
1563 }
1564
1565 /* for a match, we should reach the end of both strings, not just one of
1566 them */
1567 if ( fmt.length() > fmtpos || str.length() > strpos )
1568 {
1569 error = true;
1570 }
1571
1572 //kdDebug(173) << "KLocale::readDate day=" << day << " month=" << month << " year=" << year << endl;
1573 if ( year != -1 && month != -1 && day != -1 && !error)
1574 {
1575 if (ok) *ok = true;
1576
1577 QDate result;
1578 calendar()->setYMD(result, year, month, day);
1579
1580 return result;
1581 }
1582 else
1583 {
1584 if (ok) *ok = false;
1585 return QDate(); // invalid date
1586 }
1587}
1588
1589QTime KLocale::readTime(const QString &intstr, bool *ok) const
1590{
1591 QTime _time;
1592 _time = readTime(intstr, WithSeconds, ok);
1593 if (_time.isValid()) return _time;
1594 return readTime(intstr, WithoutSeconds, ok);
1595}
1596
1597QTime KLocale::readTime(const QString &intstr, ReadTimeFlags flags, bool *ok) const
1598{
1599 QString str = intstr.simplifyWhiteSpace().lower();
1600 QString Format = timeFormat().simplifyWhiteSpace();
1601 if (flags & WithoutSeconds)
1602 {
1603//US remove not available in my QT version
1604//US Format.remove(QRegExp(".%S"));
1605 Format.replace(QRegExp(".%S"), "");
1606 }
1607
1608 int hour = -1, minute = -1;
1609 int second = ( (flags & WithoutSeconds) == 0 ) ? -1 : 0; // don't require seconds
1610 bool g_12h = false;
1611 bool pm = false;
1612 uint strpos = 0;
1613 uint Formatpos = 0;
1614
1615 while (Format.length() > Formatpos || str.length() > strpos)
1616 {
1617 if ( !(Format.length() > Formatpos && str.length() > strpos) ) goto error;
1618
1619 QChar c = Format.at(Formatpos++);
1620
1621 if (c != '%')
1622 {
1623 if (c.isSpace())
1624 strpos++;
1625 else if (c != str.at(strpos++))
1626 goto error;
1627 continue;
1628 }
1629
1630 // remove space at the begining
1631 if (str.length() > strpos && str.at(strpos).isSpace())
1632 strpos++;
1633
1634 c = Format.at(Formatpos++);
1635 switch (c)
1636 {
1637 case 'p':
1638 {
1639 QString s;
1640 s = translate("pm").lower();
1641 int len = s.length();
1642 if (str.mid(strpos, len) == s)
1643 {
1644 pm = true;
1645 strpos += len;
1646 }
1647 else
1648 {
1649 s = translate("am").lower();
1650 len = s.length();
1651 if (str.mid(strpos, len) == s) {
1652 pm = false;
1653 strpos += len;
1654 }
1655 else
1656 goto error;
1657 }
1658 }
1659 break;
1660
1661 case 'k':
1662 case 'H':
1663 g_12h = false;
1664 hour = readInt(str, strpos);
1665 if (hour < 0 || hour > 23)
1666 goto error;
1667
1668 break;
1669
1670 case 'l':
1671 case 'I':
1672 g_12h = true;
1673 hour = readInt(str, strpos);
1674 if (hour < 1 || hour > 12)
1675 goto error;
1676
1677 break;
1678
1679 case 'M':
1680 minute = readInt(str, strpos);
1681 if (minute < 0 || minute > 59)
1682 goto error;
1683
1684 break;
1685
1686 case 'S':
1687 second = readInt(str, strpos);
1688 if (second < 0 || second > 59)
1689 goto error;
1690
1691 break;
1692 }
1693 }
1694 if (g_12h) {
1695 hour %= 12;
1696 if (pm) hour += 12;
1697 }
1698
1699 if (ok) *ok = true;
1700 return QTime(hour, minute, second);
1701
1702 error:
1703 if (ok) *ok = false;
1704 return QTime(-1, -1, -1); // return invalid date if it didn't work
1705}
1706
1707QString KLocale::formatTime(const QTime &pTime, bool includeSecs) const
1708{
1709 const QString rst = timeFormat();
1710
1711 // only "pm/am" here can grow, the rest shrinks, but
1712 // I'm rather safe than sorry
1713 QChar *buffer = new QChar[rst.length() * 3 / 2 + 30];
1714
1715 uint index = 0;
1716 bool escape = false;
1717 int number = 0;
1718
1719 for ( uint format_index = 0; format_index < rst.length(); format_index++ )
1720 {
1721 if ( !escape )
1722 {
1723 if ( rst.at( format_index ).unicode() == '%' )
1724 escape = true;
1725 else
1726 buffer[index++] = rst.at( format_index );
1727 }
1728 else
1729 {
1730 switch ( rst.at( format_index ).unicode() )
1731 {
1732 case '%':
1733 buffer[index++] = '%';
1734 break;
1735 case 'H':
1736 put_it_in( buffer, index, pTime.hour() );
1737 break;
1738 case 'I':
1739 put_it_in( buffer, index, ( pTime.hour() + 11) % 12 + 1 );
1740 break;
1741 case 'M':
1742 put_it_in( buffer, index, pTime.minute() );
1743 break;
1744 case 'S':
1745 if (includeSecs)
1746 put_it_in( buffer, index, pTime.second() );
1747 else if ( index > 0 )
1748 {
1749 // we remove the seperator sign before the seconds and
1750 // assume that works everywhere
1751 --index;
1752 break;
1753 }
1754 break;
1755 case 'k':
1756 number = pTime.hour();
1757 case 'l':
1758 // to share the code
1759 if ( rst.at( format_index ).unicode() == 'l' )
1760 number = (pTime.hour() + 11) % 12 + 1;
1761 if ( number / 10 )
1762 buffer[index++] = number / 10 + '0';
1763 buffer[index++] = number % 10 + '0';
1764 break;
1765 case 'p':
1766 {
1767 QString s;
1768 if ( pTime.hour() >= 12 )
1769 put_it_in( buffer, index, translate("pm") );
1770 else
1771 put_it_in( buffer, index, translate("am") );
1772 break;
1773 }
1774 default:
1775 buffer[index++] = rst.at( format_index );
1776 break;
1777 }
1778 escape = false;
1779 }
1780 }
1781 QString ret( buffer, index );
1782 delete [] buffer;
1783 return ret;
1784}
1785
1786bool KLocale::use12Clock() const
1787{
1788 if ((timeFormat().contains(QString::fromLatin1("%I")) > 0) ||
1789 (timeFormat().contains(QString::fromLatin1("%l")) > 0))
1790 return true;
1791 else
1792 return false;
1793}
1794
1795QString KLocale::languages() const
1796{
1797 return d->languageList.join( QString::fromLatin1(":") );
1798}
1799
1800QStringList KLocale::languageList() const
1801{
1802 return d->languageList;
1803}
1804
1805QString KLocale::formatDateTime(const QDateTime &pDateTime,
1806 bool shortFormat,
1807 bool includeSeconds) const
1808{
1809 return translate("concatenation of dates and time", "%1 %2")
1810 .arg( formatDate( pDateTime.date(), shortFormat ) )
1811 .arg( formatTime( pDateTime.time(), includeSeconds ) );
1812}
1813
1814QString i18n(const char* text)
1815{
1816 /*
1817 register KLocale *instance = KGlobal::locale();
1818 if (instance)
1819 return instance->translate(text);
1820 */
1821 return QString::fromUtf8(text);
1822}
1823
1824QString i18n(const char* index, const char *text)
1825{
1826 /*
1827 register KLocale *instance = KGlobal::locale();
1828 if (instance)
1829 return instance->translate(index, text);
1830 */
1831 return QString::fromUtf8(text);
1832}
1833
1834QString i18n(const char* singular, const char* plural, unsigned long n)
1835{
1836 return (QString::fromUtf8(plural)); // hack! remove this line!
1837 register KLocale *instance = KGlobal::locale();
1838 if (instance)
1839 return instance->translate(singular, plural, n);
1840 if (n == 1)
1841 return put_n_in(QString::fromUtf8(singular), n);
1842 else
1843 return put_n_in(QString::fromUtf8(plural), n);
1844}
1845
1846void KLocale::initInstance()
1847{
1848 if (KGlobal::locale())
1849 return;
1850
1851/*US lets change the whole way how to create a KLocale
1852 KInstance *app = KGlobal::instance();
1853 if (app) {
1854 KGlobal::_locale = new KLocale(QString::fromLatin1(app->instanceName()));
1855
1856 // only do this for the global instance
1857 QTextCodec::setCodecForLocale(KGlobal::_locale->codecForEncoding());
1858 }
1859 else
1860 kdDebug(173) << "no app name available using KLocale - nothing to do\n";
1861*/
1862//US new implementation
1863 QString appname = KGlobal::getAppName();
1864 if (appname) {
1865 KLocale *l = new KLocale(appname);
1866 KGlobal::setLocale(l);
1867
1868 // only do this for the global instance
1869//US
1870//US QTextCodec::setCodecForLocale(KGlobal::locale())->codecForEncoding());
1871//US qt_set_locale_codec( KGlobal::locale()->codecForEncoding() );
1872 qDebug("KLocale::initInstance we have to do here something !!!");
1873 }
1874 else
1875 kdDebug(173) << "no app name available using KLocale - nothing to do\n";
1876
1877}
1878
1879QString KLocale::langLookup(const QString &fname, const char *rtype)
1880{
1881 QStringList search;
1882
1883 // assemble the local search paths
1884//US we have only one resourcedir. So use it !!
1885/*US original
1886 const QStringList localDoc = KGlobal::dirs()->resourceDirs(rtype);
1887 // look up the different languages
1888 for (int id=localDoc.count()-1; id >= 0; --id)
1889 {
1890 QStringList langs = KGlobal::locale()->languageList();
1891 langs.append( "en" );
1892 langs.remove( defaultLanguage() );
1893 QStringList::ConstIterator lang;
1894 for (lang = langs.begin(); lang != langs.end(); ++lang)
1895 search.append(QString("%1%2/%3").arg(localDoc[id]).arg(*lang).arg(fname));
1896 }
1897*/
1898//US new code
1899//US What is here correct??? const QString localDoc = KGlobal::dirs()->findResourceDir(rtype);
1900 const QString localDoc = rtype;
1901 // look up the different languages
1902 QStringList langs = KGlobal::locale()->languageList();
1903 langs.append( "en" );
1904 langs.remove( defaultLanguage() );
1905 QStringList::ConstIterator lang;
1906 for (lang = langs.begin(); lang != langs.end(); ++lang)
1907 search.append(QString("%1%2/%3").arg(localDoc).arg(*lang).arg(fname));
1908
1909 // try to locate the file
1910 QStringList::Iterator it;
1911 for (it = search.begin(); it != search.end(); ++it)
1912 {
1913 kdDebug(173) << "Looking for help in: " << *it << endl;
1914
1915 QFileInfo info(*it);
1916 if (info.exists() && info.isFile() && info.isReadable())
1917 return *it;
1918 }
1919
1920 return QString::null;
1921}
1922
1923bool KLocale::useDefaultLanguage() const
1924{
1925 return language() == defaultLanguage();
1926}
1927
1928void KLocale::initEncoding(KConfig *)
1929{
1930 const int mibDefault = 4; // ISO 8859-1
1931
1932 // This all made more sense when we still had the EncodingEnum config key.
1933 setEncoding( QTextCodec::codecForLocale()->mibEnum() );
1934
1935 if ( !d->codecForEncoding )
1936 {
1937 kdWarning(173) << " Defaulting to ISO 8859-1 encoding." << endl;
1938 setEncoding(mibDefault);
1939 }
1940
1941 ASSERT( d->codecForEncoding );
1942}
1943
1944void KLocale::initFileNameEncoding(KConfig *)
1945{
1946 // If the following environment variable is set, assume all filenames
1947 // are in UTF-8 regardless of the current C locale.
1948 d->utf8FileEncoding = getenv("KDE_UTF8_FILENAMES") != 0;
1949 if (d->utf8FileEncoding)
1950 {
1951 QFile::setEncodingFunction(KLocale::encodeFileNameUTF8);
1952 QFile::setDecodingFunction(KLocale::decodeFileNameUTF8);
1953 }
1954 // Otherwise, stay with QFile's default filename encoding functions
1955 // which, on Unix platforms, use the locale's codec.
1956}
1957
1958QCString KLocale::encodeFileNameUTF8( const QString & fileName )
1959{
1960 return fileName.utf8();
1961}
1962
1963QString KLocale::decodeFileNameUTF8( const QCString & localFileName )
1964{
1965 return QString::fromUtf8(localFileName);
1966}
1967
1968void KLocale::initCatalogue( KCatalogue & catalogue )
1969{
1970 catalogue.setFileName( catalogueFileName( language(), catalogue ) );
1971}
1972
1973void KLocale::setDateFormat(const QString & format)
1974{
1975 doFormatInit();
1976 m_dateFormat = format.stripWhiteSpace();
1977}
1978
1979void KLocale::setDateFormatShort(const QString & format)
1980{
1981 doFormatInit();
1982 m_dateFormatShort = format.stripWhiteSpace();
1983}
1984
1985void KLocale::setDateMonthNamePossessive(bool possessive)
1986{
1987 doFormatInit();
1988 d->dateMonthNamePossessive = possessive;
1989}
1990
1991void KLocale::setTimeFormat(const QString & format)
1992{
1993 doFormatInit();
1994 m_timeFormat = format.stripWhiteSpace();
1995}
1996
1997void KLocale::setWeekStartsMonday(bool start) //deprecated
1998{
1999 doFormatInit();
2000 if (start)
2001 d->weekStartDay = 1;
2002 else
2003 d->weekStartDay = 7;
2004}
2005
2006void KLocale::setWeekStartDay(int day)
2007{
2008 doFormatInit();
2009 if (day>7 || day<1)
2010 d->weekStartDay = 1; //Monday is default
2011 else
2012 d->weekStartDay = day;
2013}
2014
2015QString KLocale::dateFormat() const
2016{
2017 doFormatInit();
2018 return m_dateFormat;
2019}
2020
2021QString KLocale::dateFormatShort() const
2022{
2023 doFormatInit();
2024 return m_dateFormatShort;
2025}
2026
2027QString KLocale::timeFormat() const
2028{
2029 doFormatInit();
2030 return m_timeFormat;
2031}
2032
2033void KLocale::setDecimalSymbol(const QString & symbol)
2034{
2035 doFormatInit();
2036 m_decimalSymbol = symbol.stripWhiteSpace();
2037}
2038
2039void KLocale::setThousandsSeparator(const QString & separator)
2040{
2041 doFormatInit();
2042 // allow spaces here
2043 m_thousandsSeparator = separator;
2044}
2045
2046void KLocale::setPositiveSign(const QString & sign)
2047{
2048 doFormatInit();
2049 m_positiveSign = sign.stripWhiteSpace();
2050}
2051
2052void KLocale::setNegativeSign(const QString & sign)
2053{
2054 doFormatInit();
2055 m_negativeSign = sign.stripWhiteSpace();
2056}
2057
2058void KLocale::setPositiveMonetarySignPosition(SignPosition signpos)
2059{
2060 doFormatInit();
2061 m_positiveMonetarySignPosition = signpos;
2062}
2063
2064void KLocale::setNegativeMonetarySignPosition(SignPosition signpos)
2065{
2066 doFormatInit();
2067 m_negativeMonetarySignPosition = signpos;
2068}
2069
2070void KLocale::setPositivePrefixCurrencySymbol(bool prefix)
2071{
2072 doFormatInit();
2073 m_positivePrefixCurrencySymbol = prefix;
2074}
2075
2076void KLocale::setNegativePrefixCurrencySymbol(bool prefix)
2077{
2078 doFormatInit();
2079 m_negativePrefixCurrencySymbol = prefix;
2080}
2081
2082void KLocale::setFracDigits(int digits)
2083{
2084 doFormatInit();
2085 m_fracDigits = digits;
2086}
2087
2088void KLocale::setMonetaryThousandsSeparator(const QString & separator)
2089{
2090 doFormatInit();
2091 // allow spaces here
2092 m_monetaryThousandsSeparator = separator;
2093}
2094
2095void KLocale::setMonetaryDecimalSymbol(const QString & symbol)
2096{
2097 doFormatInit();
2098 m_monetaryDecimalSymbol = symbol.stripWhiteSpace();
2099}
2100
2101void KLocale::setCurrencySymbol(const QString & symbol)
2102{
2103 doFormatInit();
2104 m_currencySymbol = symbol.stripWhiteSpace();
2105}
2106
2107int KLocale::pageSize() const
2108{
2109 doFormatInit();
2110 return d->pageSize;
2111}
2112
2113void KLocale::setPageSize(int pageSize)
2114{
2115 // #### check if it's in range??
2116 doFormatInit();
2117 d->pageSize = pageSize;
2118}
2119
2120KLocale::MeasureSystem KLocale::measureSystem() const
2121{
2122 doFormatInit();
2123 return d->measureSystem;
2124}
2125
2126void KLocale::setMeasureSystem(MeasureSystem value)
2127{
2128 doFormatInit();
2129 d->measureSystem = value;
2130}
2131
2132QString KLocale::defaultLanguage()
2133{
2134 return QString::fromLatin1("en_US");
2135}
2136
2137QString KLocale::defaultCountry()
2138{
2139 return QString::fromLatin1("C");
2140}
2141
2142const char * KLocale::encoding() const
2143{
2144 return codecForEncoding()->name();
2145}
2146
2147int KLocale::encodingMib() const
2148{
2149 return codecForEncoding()->mibEnum();
2150}
2151
2152int KLocale::fileEncodingMib() const
2153{
2154 if (d->utf8FileEncoding)
2155 return 106;
2156 return codecForEncoding()->mibEnum();
2157}
2158
2159QTextCodec * KLocale::codecForEncoding() const
2160{
2161 return d->codecForEncoding;
2162}
2163
2164bool KLocale::setEncoding(int mibEnum)
2165{
2166 QTextCodec * codec = QTextCodec::codecForMib(mibEnum);
2167 if (codec)
2168 d->codecForEncoding = codec;
2169
2170 return codec != 0;
2171}
2172
2173QStringList KLocale::languagesTwoAlpha() const
2174{
2175 if (d->langTwoAlpha.count())
2176 return d->langTwoAlpha;
2177
2178 const QStringList &origList = languageList();
2179
2180 QStringList result;
2181
2182//US KConfig config(QString::fromLatin1("language.codes"), true, false);
2183 KConfig config(locateLocal("config", QString::fromLatin1("language.codes")));
2184 config.setGroup("TwoLetterCodes");
2185
2186 for ( QStringList::ConstIterator it = origList.begin();
2187 it != origList.end();
2188 ++it )
2189 {
2190 QString lang = *it;
2191 QStringList langLst;
2192
2193/*US I changed the following code, because hasKey is not available.
2194!!! check if my version is correct
2195 if (config.hasKey( lang ))
2196 langLst = config.readListEntry( lang );
2197 else
2198 {
2199 int i = lang.find('_');
2200 if (i >= 0)
2201 lang.truncate(i);
2202 langLst << lang;
2203 }
2204*/
2205 langLst = config.readListEntry( lang );
2206 if (langLst.isEmpty())
2207 {
2208 int i = lang.find('_');
2209 if (i >= 0)
2210 lang.truncate(i);
2211 langLst << lang;
2212 }
2213
2214
2215 for ( QStringList::ConstIterator langIt = langLst.begin();
2216 langIt != langLst.end();
2217 ++langIt )
2218 {
2219 if ( !(*langIt).isEmpty() && !result.contains( *langIt ) )
2220 result += *langIt;
2221 }
2222 }
2223 d->langTwoAlpha = result;
2224 return result;
2225}
2226
2227QStringList KLocale::allLanguagesTwoAlpha() const
2228{
2229 if (!d->languages)
2230//US d->languages = new KConfig("all_languages", true, false, "locale");
2231 d->languages = new KConfig(locateLocal( "locale", "all_languages"));
2232
2233//US return d->languages->groupList();
2234 qDebug("KLocale::allLanguagesTwoAlpha has to be fixed.");
2235 return *(new QStringList());
2236
2237}
2238
2239QString KLocale::twoAlphaToLanguageName(const QString &code) const
2240{
2241 if (!d->languages)
2242//US d->languages = new KConfig("all_languages", true, false, "locale");
2243 d->languages = new KConfig(locateLocal( "locale", "all_languages"));
2244
2245 d->languages->setGroup(code.lower());
2246 return d->languages->readEntry("Name");
2247}
2248
2249QStringList KLocale::allCountriesTwoAlpha() const
2250{
2251 QStringList countries;
2252
2253 qDebug("KLocale::allCountriesTwoAlpha has to be fixed.");
2254//US QStringList paths = KGlobal::dirs()->findAllResources("locale", "l10n/*/entry.desktop");
2255 QStringList paths = KGlobal::dirs()->findAllResources("locale", "l10n/*/entry.desktop", true, true);
2256
2257 for(QStringList::ConstIterator it = paths.begin();
2258 it != paths.end(); ++it)
2259 {
2260 QString code = (*it).mid((*it).length()-16, 2);
2261 if (code != "/C")
2262 countries.append(code);
2263 }
2264 return countries;
2265}
2266
2267QString KLocale::twoAlphaToCountryName(const QString &code) const
2268{
2269//US KConfig cfg("l10n/"+code.lower()+"/entry.desktop", true, false, "locale");
2270 KConfig cfg(locateLocal("locale", "l10n/"+code.lower()+"/entry.desktop"));
2271 cfg.setGroup("KCM Locale");
2272 return cfg.readEntry("Name");
2273}
2274
2275void KLocale::setCalendar(const QString & calType)
2276{
2277 doFormatInit();
2278
2279 d->calendarType = calType;
2280
2281 delete d->calendar;
2282 d->calendar = 0;
2283}
2284
2285QString KLocale::calendarType() const
2286{
2287 doFormatInit();
2288
2289 return d->calendarType;
2290}
2291
2292const KCalendarSystem * KLocale::calendar() const
2293{
2294 doFormatInit();
2295
2296 // Check if it's the correct calendar?!?
2297//US we are always using the gregorian calendar
2298//US if ( !d->calendar )
2299//US d->calendar = KCalendarSystemFactory::create( d->calendarType, this );
2300 if ( !d->calendar )
2301 d->calendar = new KCalendarSystemGregorian;
2302
2303 return d->calendar;
2304}
2305
2306KLocale::KLocale(const KLocale & rhs)
2307{
2308 d = new KLocalePrivate;
2309
2310 *this = rhs;
2311}
2312
2313KLocale & KLocale::operator=(const KLocale & rhs)
2314{
2315 // Numbers and money
2316 m_decimalSymbol = rhs.m_decimalSymbol;
2317 m_thousandsSeparator = rhs.m_thousandsSeparator;
2318 m_currencySymbol = rhs.m_currencySymbol;
2319 m_monetaryDecimalSymbol = rhs.m_monetaryDecimalSymbol;
2320 m_monetaryThousandsSeparator = rhs.m_monetaryThousandsSeparator;
2321 m_positiveSign = rhs.m_positiveSign;
2322 m_negativeSign = rhs.m_negativeSign;
2323 m_fracDigits = rhs.m_fracDigits;
2324 m_positivePrefixCurrencySymbol = rhs.m_positivePrefixCurrencySymbol;
2325 m_negativePrefixCurrencySymbol = rhs.m_negativePrefixCurrencySymbol;
2326 m_positiveMonetarySignPosition = rhs.m_positiveMonetarySignPosition;
2327 m_negativeMonetarySignPosition = rhs.m_negativeMonetarySignPosition;
2328
2329 // Date and time
2330 m_timeFormat = rhs.m_timeFormat;
2331 m_dateFormat = rhs.m_dateFormat;
2332 m_dateFormatShort = rhs.m_dateFormatShort;
2333
2334 m_language = rhs.m_language;
2335 m_country = rhs.m_country;
2336
2337 // the assignment operator works here
2338 *d = *rhs.d;
2339 d->languages = 0; // Don't copy languages
2340 d->calendar = 0; // Don't copy the calendar
2341
2342 return *this;
2343}
2344
2345bool KLocale::setCharset(const QString & ) { return true; }
2346QString KLocale::charset() const { return QString::fromLatin1("UTF-8"); }
2347
2348
2349int KLocale::timezoneOffset( QString timeZone )
2350{
2351 int ret = 1001;
2352 int index = mTimeZoneList.findIndex( timeZone );
2353 if ( index < 24 )
2354 ret = ( index-11 ) * 60 ;
2355 return ret;
2356}
2357
2358QStringList KLocale::timeZoneList() const
2359{
2360 return mTimeZoneList;
2361}
2362void KLocale::setTimezone( const QString &timeZone )
2363{
2364 mTimeZoneOffset = timezoneOffset( timeZone );
2365}
2366
2367void KLocale::setDaylightSaving( bool b, int start , int end )
2368{
2369 daylightEnabled = b;
2370 daylightStart = start;
2371 daylightEnd = end;
2372 mSouthDaylight = (end < start);
2373 // qDebug("klocale daylight %d %d %d ", b, start , end );
2374}
2375
2376int KLocale::localTimeOffset( const QDateTime &dt )
2377{
2378 bool addDaylight = false;
2379 if ( daylightEnabled ) {
2380 int d_end, d_start;
2381 int dayofyear = dt.date().dayOfYear();
2382 int year = dt.date().year();
2383 int add = 0;
2384 if ( QDate::leapYear(year) )
2385 add = 1;
2386 QDate date ( year,1,1 );
2387 if ( daylightEnd > 59 )
2388 d_end = daylightEnd +add;
2389 else
2390 d_end = daylightEnd;
2391 if ( daylightStart > 59 )
2392 d_start = daylightStart +add;
2393 else
2394 d_start = daylightStart;
2395 QDate s_date = date.addDays( d_start -1 );
2396 QDate e_date = date.addDays( d_end -1 );
2397 int dof = s_date.dayOfWeek();
2398 if ( dof < 7 )
2399 s_date = s_date.addDays( -dof );
2400 dof = e_date.dayOfWeek();
2401 if ( dof < 7 )
2402 e_date = e_date.addDays( -dof );
2403 QTime startTime ( 3,0,0 );
2404 QDateTime startDt( s_date, startTime );
2405 QDateTime endDt( e_date, startTime );
2406 //qDebug("dayligt saving start %s end %s ",startDt.toString().latin1(),endDt.toString().latin1( ));
2407 if ( mSouthDaylight ) {
2408 if ( ! ( endDt < dt && dt < startDt) )
2409 addDaylight = true;
2410 } else {
2411 if ( startDt < dt && dt < endDt )
2412 addDaylight = true;
2413
2414
2415 }
2416 }
2417 int addMin = 0;
2418 if ( addDaylight )
2419 addMin = 60;
2420 return mTimeZoneOffset + addMin;
2421}
2422
2423void KLocale::setHore24Format ( bool b )
2424{
2425 mHourF24Format = b;
2426}
2427void KLocale::setWeekStartMonday( bool b )
2428{
2429 mWeekStartsMonday = b;
2430}
2431void KLocale::setIntDateFormat( int i )
2432{
2433 mIntDateFormat = i;
2434}
2435void KLocale::setLanguage( int i )
2436{
2437 mLanguage = i;
2438}
2439
2440
2441