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

tdecore

tdelocale.cpp

00001 // -*- c-basic-offset: 2 -*-
00002 /* This file is part of the KDE libraries
00003    Copyright (c) 1997,2001 Stephan Kulow <coolo@kde.org>
00004    Copyright (c) 1999 Preston Brown <pbrown@kde.org>
00005    Copyright (c) 1999-2002 Hans Petter Bieker <bieker@kde.org>
00006    Copyright (c) 2002 Lukas Tinkl <lukas@kde.org>
00007 
00008    This library is free software; you can redistribute it and/or
00009    modify it under the terms of the GNU Library General Public
00010    License as published by the Free Software Foundation; either
00011    version 2 of the License, or (at your option) any later version.
00012 
00013    This library is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016    Library General Public License for more details.
00017 
00018    You should have received a copy of the GNU Library General Public License
00019    along with this library; see the file COPYING.LIB.  If not, write to
00020    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00021    Boston, MA 02110-1301, USA.
00022 */
00023 
00024 #include <config.h>
00025 
00026 #include <stdlib.h> // getenv
00027 
00028 #include <tqtextcodec.h>
00029 #include <tqfile.h>
00030 #include <tqprinter.h>
00031 #include <tqdatetime.h>
00032 #include <tqfileinfo.h>
00033 #include <tqregexp.h>
00034 
00035 #include "kcatalogue.h"
00036 #include "tdeglobal.h"
00037 #include "kstandarddirs.h"
00038 #include "ksimpleconfig.h"
00039 #include "kinstance.h"
00040 #include "tdeconfig.h"
00041 #include "kdebug.h"
00042 #include "kcalendarsystem.h"
00043 #include "kcalendarsystemfactory.h"
00044 #include "tdelocale.h"
00045 
00046 #ifdef Q_WS_WIN
00047 #include <windows.h>
00048 #endif
00049 
00050 static const char * const SYSTEM_MESSAGES = "tdelibs";
00051 
00052 static const char *maincatalogue = 0;
00053 
00054 class TDELocalePrivate
00055 {
00056 public:
00057   int weekStartDay;
00058   bool nounDeclension;
00059   bool dateMonthNamePossessive;
00060   TQStringList languageList;
00061   TQStringList catalogNames; // list of all catalogs (regardless of language)
00062   TQValueList<KCatalogue> catalogues; // list of all loaded catalogs, contains one instance per catalog name and language
00063   TQString encoding;
00064   TQTextCodec * codecForEncoding;
00065   TDEConfig * config;
00066   bool formatInited;
00067   int /*TQPrinter::PageSize*/ pageSize;
00068   TDELocale::MeasureSystem measureSystem;
00069   TQStringList langTwoAlpha;
00070   TDEConfig *languages;
00071 
00072   TQString calendarType;
00073   KCalendarSystem * calendar;
00074   bool utf8FileEncoding;
00075   TQString appName;
00076 #ifdef Q_WS_WIN
00077   char win32SystemEncoding[3+7]; //"cp " + lang ID
00078 #endif
00079   bool useMainCatalogue;
00080 };
00081 
00082 static TDELocale *this_klocale = 0;
00083 
00084 TDELocale::TDELocale( const TQString & catalog, TDEConfig * config )
00085 {
00086   d = new TDELocalePrivate;
00087   d->config = config;
00088   d->languages = 0;
00089   d->calendar = 0;
00090   d->formatInited = false;
00091 
00092   initEncoding(0);
00093   initFileNameEncoding(0);
00094 
00095   TDEConfig *cfg = d->config;
00096   this_klocale = this;
00097   if (!cfg) cfg = TDEGlobal::instance()->config();
00098   this_klocale = 0;
00099   Q_ASSERT( cfg );
00100 
00101   d->appName = catalog;
00102   initLanguageList( cfg, config == 0);
00103   initMainCatalogues(catalog);
00104 }
00105 
00106 TQString TDELocale::_initLanguage(TDEConfigBase *config)
00107 {
00108   if (this_klocale)
00109   {
00110      // ### HPB Why this cast??
00111      this_klocale->initLanguageList((TDEConfig *) config, true);
00112      // todo: adapt current catalog list: remove unused languages, insert main catalogs, if not already found
00113      return this_klocale->language();
00114   }
00115   return TQString::null;
00116 }
00117 
00118 void TDELocale::initMainCatalogues(const TQString & catalog)
00119 {
00120   // Use the first non-null string.
00121   TQString mainCatalogue = catalog;
00122 
00123   // don't use main catalogue if we're looking up .desktop translations
00124   if (mainCatalogue.contains("desktop") == 0 || mainCatalogue.contains("kdesktop") == 1) {
00125     if (maincatalogue) {
00126       mainCatalogue = TQString::fromLatin1(maincatalogue);
00127     }
00128   }
00129 
00130   if (mainCatalogue.isEmpty()) {
00131     kdDebug(173) << "TDELocale instance created called without valid "
00132                  << "catalog! Give an argument or call setMainCatalogue "
00133                  << "before init" << endl;
00134   }
00135   else {
00136     // do not use insertCatalogue here, that would already trigger updateCatalogs
00137     d->catalogNames.append( mainCatalogue );   // application catalog
00138     if (mainCatalogue.contains("desktop") == 0 || mainCatalogue.contains("kdesktop") == 1) { //don't bother if we're looking up desktop translations
00139       d->catalogNames.append( SYSTEM_MESSAGES ); // always include tdelibs.mo
00140       d->catalogNames.append( "tdeio" );            // always include tdeio.mo
00141       d->catalogNames.append( "xdg-user-dirs" );
00142     }
00143     updateCatalogues(); // evaluate this for all languages
00144   }
00145 }
00146 
00147 void TDELocale::initLanguageList(TDEConfig * config, bool useEnv)
00148 {
00149   TDEConfigGroupSaver saver(config, "Locale");
00150 
00151   m_country = config->readEntry( "Country" );
00152   if ( m_country.isEmpty() )
00153     m_country = defaultCountry();
00154 
00155   // Reset the list and add the new languages
00156   TQStringList languageList;
00157   if ( useEnv )
00158     languageList += TQStringList::split
00159       (':', TQFile::decodeName( ::getenv("TDE_LANG") ));
00160 
00161   languageList += config->readListEntry("Language", ':');
00162 
00163   // same order as setlocale use
00164   if ( useEnv )
00165     {
00166       // HPB: Only run splitLocale on the environment variables..
00167       TQStringList langs;
00168 
00169       langs << TQFile::decodeName( ::getenv("LC_ALL") );
00170       langs << TQFile::decodeName( ::getenv("LC_MESSAGES") );
00171       langs << TQFile::decodeName( ::getenv("LANG") );
00172 
00173       for ( TQStringList::Iterator it = langs.begin();
00174         it != langs.end();
00175         ++it )
00176     {
00177       TQString ln, ct, chrset;
00178       splitLocale(*it, ln, ct, chrset);
00179 
00180       if (!ct.isEmpty()) {
00181         langs.insert(it, ln + '_' + ct);
00182         if (!chrset.isEmpty())
00183           langs.insert(it, ln + '_' + ct + '.' + chrset);
00184       }
00185 
00186           langs.insert(it, ln);
00187     }
00188 
00189       languageList += langs;
00190     }
00191 
00192   // now we have a language list -- let's use the first OK language
00193   setLanguage( languageList );
00194 }
00195 
00196 void TDELocale::initPluralTypes()
00197 {
00198   for ( TQValueList<KCatalogue>::Iterator it = d->catalogues.begin();
00199     it != d->catalogues.end();
00200     ++it )
00201   {
00202     TQString language = (*it).language();
00203     int pt = pluralType( language );
00204     (*it).setPluralType( pt );
00205   }
00206 }
00207 
00208 
00209 int TDELocale::pluralType( const TQString & language )
00210 {
00211   for ( TQValueList<KCatalogue>::ConstIterator it = d->catalogues.begin();
00212     it != d->catalogues.end();
00213     ++it )
00214   {
00215     if ( ((*it).name() == SYSTEM_MESSAGES ) && ((*it).language() == language )) {
00216       return pluralType( *it );
00217     }
00218   }
00219   // tdelibs.mo does not seem to exist for this language
00220   return -1;
00221 }
00222 
00223 int TDELocale::pluralType( const KCatalogue& catalog )
00224 {
00225     const char* pluralFormString =
00226     I18N_NOOP("_: Dear translator, please do not translate this string "
00227       "in any form, but pick the _right_ value out of "
00228       "NoPlural/TwoForms/French... If not sure what to do mail "
00229       "thd@kde.org and coolo@kde.org, they will tell you. "
00230       "Better leave that out if unsure, the programs will "
00231       "crash!!\nDefinition of PluralForm - to be set by the "
00232       "translator of tdelibs.po");
00233     TQString pf (catalog.translate( pluralFormString));
00234     if ( pf.isEmpty() ) {
00235       return -1;
00236     }
00237     else if ( pf == "NoPlural" )
00238       return 0;
00239     else if ( pf == "TwoForms" )
00240       return 1;
00241     else if ( pf == "French" )
00242       return 2;
00243     else if ( pf == "OneTwoRest" )
00244       return 3;
00245     else if ( pf == "Russian" )
00246       return 4;
00247     else if ( pf == "Polish" )
00248       return 5;
00249     else if ( pf == "Slovenian" )
00250       return 6;
00251     else if ( pf == "Lithuanian" )
00252       return 7;
00253     else if ( pf == "Czech" )
00254       return 8;
00255     else if ( pf == "Slovak" )
00256       return 9;
00257     else if ( pf == "Maltese" )
00258       return 10;
00259     else if ( pf == "Arabic" )
00260       return 11;
00261     else if ( pf == "Balcan" )
00262       return 12;
00263     else if ( pf == "Macedonian" )
00264       return 13;
00265     else if ( pf == "Gaeilge" )
00266         return 14;
00267     else {
00268       kdWarning(173) << "Definition of PluralForm is none of "
00269                << "NoPlural/"
00270                << "TwoForms/"
00271                << "French/"
00272                << "OneTwoRest/"
00273                << "Russian/"
00274                << "Polish/"
00275                << "Slovenian/"
00276                << "Lithuanian/"
00277                << "Czech/"
00278                << "Slovak/"
00279                << "Arabic/"
00280                << "Balcan/"
00281                << "Macedonian/"
00282                << "Gaeilge/"
00283                << "Maltese: " << pf << endl;
00284       exit(1);
00285     }
00286 }
00287 
00288 void TDELocale::doFormatInit() const
00289 {
00290   if ( d->formatInited ) return;
00291 
00292   TDELocale * that = const_cast<TDELocale *>(this);
00293   that->initFormat();
00294 
00295   d->formatInited = true;
00296 }
00297 
00298 void TDELocale::initFormat()
00299 {
00300   TDEConfig *config = d->config;
00301   if (!config) config = TDEGlobal::instance()->config();
00302   Q_ASSERT( config );
00303 
00304   kdDebug(173) << "TDELocale::initFormat" << endl;
00305 
00306   // make sure the config files are read using the correct locale
00307   // ### Why not add a TDEConfigBase::setLocale( const TDELocale * )?
00308   // ### Then we could remove this hack
00309   TDELocale *lsave = TDEGlobal::_locale;
00310   TDEGlobal::_locale = this;
00311 
00312   TDEConfigGroupSaver saver(config, "Locale");
00313 
00314   KSimpleConfig entry(locate("locale",
00315                              TQString::fromLatin1("l10n/%1/entry.desktop")
00316                              .arg(m_country)), true);
00317   entry.setGroup("KCM Locale");
00318 
00319   // Numeric
00320 #define readConfigEntry(key, default, save) \
00321   save = entry.readEntry(key, TQString::fromLatin1(default)); \
00322   save = config->readEntry(key, save);
00323 
00324 #define readConfigNumEntry(key, default, save, type) \
00325   save = (type)entry.readNumEntry(key, default); \
00326   save = (type)config->readNumEntry(key, save);
00327 
00328 #define readConfigBoolEntry(key, default, save) \
00329   save = entry.readBoolEntry(key, default); \
00330   save = config->readBoolEntry(key, save);
00331 
00332   readConfigEntry("DecimalSymbol", ".", m_decimalSymbol);
00333   readConfigEntry("ThousandsSeparator", ",", m_thousandsSeparator);
00334   m_thousandsSeparator.replace( TQString::fromLatin1("$0"), TQString() );
00335   //kdDebug(173) << "m_thousandsSeparator=" << m_thousandsSeparator << endl;
00336 
00337   readConfigEntry("PositiveSign", "", m_positiveSign);
00338   readConfigEntry("NegativeSign", "-", m_negativeSign);
00339 
00340   // Monetary
00341   readConfigEntry("CurrencySymbol", "$", m_currencySymbol);
00342   readConfigEntry("MonetaryDecimalSymbol", ".", m_monetaryDecimalSymbol);
00343   readConfigEntry("MonetaryThousandsSeparator", ",",
00344           m_monetaryThousandsSeparator);
00345   m_monetaryThousandsSeparator.replace(TQString::fromLatin1("$0"), TQString());
00346 
00347   readConfigNumEntry("FracDigits", 2, m_fracDigits, int);
00348   readConfigBoolEntry("PositivePrefixCurrencySymbol", true,
00349               m_positivePrefixCurrencySymbol);
00350   readConfigBoolEntry("NegativePrefixCurrencySymbol", true,
00351               m_negativePrefixCurrencySymbol);
00352   readConfigNumEntry("PositiveMonetarySignPosition", (int)BeforeQuantityMoney,
00353              m_positiveMonetarySignPosition, SignPosition);
00354   readConfigNumEntry("NegativeMonetarySignPosition", (int)ParensAround,
00355              m_negativeMonetarySignPosition, SignPosition);
00356 
00357 
00358   // Date and time
00359   readConfigEntry("TimeFormat", "%H:%M:%S", m_timeFormat);
00360   readConfigEntry("DateFormat", "%A %d %B %Y", m_dateFormat);
00361   readConfigEntry("DateFormatShort", "%Y-%m-%d", m_dateFormatShort);
00362   readConfigNumEntry("WeekStartDay", 1, d->weekStartDay, int);
00363 
00364   // other
00365   readConfigNumEntry("PageSize", (int)TQPrinter::A4, d->pageSize, int);
00366   readConfigNumEntry("MeasureSystem", (int)Metric, d->measureSystem,
00367              MeasureSystem);
00368   readConfigEntry("CalendarSystem", "gregorian", d->calendarType);
00369   delete d->calendar;
00370   d->calendar = 0; // ### HPB Is this the correct place?
00371 
00372   //Grammatical
00373   //Precedence here is l10n / i18n / config file
00374   KSimpleConfig language(locate("locale",
00375                     TQString::fromLatin1("%1/entry.desktop")
00376                                 .arg(m_language)), true);
00377   language.setGroup("KCM Locale");
00378 #define read3ConfigBoolEntry(key, default, save) \
00379   save = entry.readBoolEntry(key, default); \
00380   save = language.readBoolEntry(key, save); \
00381   save = config->readBoolEntry(key, save);
00382 
00383   read3ConfigBoolEntry("NounDeclension", false, d->nounDeclension);
00384   read3ConfigBoolEntry("DateMonthNamePossessive", false,
00385                d->dateMonthNamePossessive);
00386 
00387   // end of hack
00388   TDEGlobal::_locale = lsave;
00389 }
00390 
00391 bool TDELocale::setCountry(const TQString & country)
00392 {
00393   // Check if the file exists too??
00394   if ( country.isEmpty() )
00395     return false;
00396 
00397   m_country = country;
00398 
00399   d->formatInited = false;
00400 
00401   return true;
00402 }
00403 
00404 TQString TDELocale::catalogueFileName(const TQString & language,
00405                    const KCatalogue & catalog)
00406 {
00407   TQString path = TQString::fromLatin1("%1/LC_MESSAGES/%2.mo")
00408     .arg( language )
00409     .arg( catalog.name() );
00410 
00411   TQString fileName = locate( "locale", path );
00412   if (fileName.isEmpty())
00413     fileName = locate( "locale-bundle", path );
00414 
00415   return fileName;
00416 }
00417 
00418 bool TDELocale::setLanguage(const TQString & language)
00419 {
00420   if ( d->languageList.contains( language ) ) {
00421      d->languageList.remove( language );
00422   }
00423   d->languageList.prepend( language ); // let us consider this language to be the most important one
00424 
00425   m_language = language; // remember main language for shortcut evaluation
00426 
00427   // important when called from the outside and harmless when called before populating the
00428   // catalog name list
00429   updateCatalogues();
00430 
00431   d->formatInited = false;
00432 
00433   return true; // Maybe the mo-files for this language are empty, but in principle we can speak all languages
00434 }
00435 
00436 bool TDELocale::setLanguage(const TQStringList & languages)
00437 {
00438   TQStringList languageList( languages );
00439   // This list might contain
00440   // 1) some empty strings that we have to eliminate
00441   // 2) duplicate entries like in de:fr:de, where we have to keep the first occurrance of a language in order
00442   //    to preserve the order of precenence of the user => iterate backwards
00443   // 3) languages into which the application is not translated. For those languages we should not even load tdelibs.mo or tdeio.po.
00444   //    these langugage have to be dropped. Otherwise we get strange side effects, e.g. with Hebrew:
00445   //    the right/left switch for languages that write from
00446   //    right to left (like Hebrew or Arabic) is set in tdelibs.mo. If you only have tdelibs.mo
00447   //    but nothing from appname.mo, you get a mostly English app with layout from right to left.
00448   //    That was considered to be a bug by the Hebrew translators.
00449   for( TQStringList::Iterator it = languageList.fromLast();
00450     it != languageList.begin(); --it )
00451   {
00452     // kdDebug() << "checking " << (*it) << endl;
00453     bool bIsTranslated = isApplicationTranslatedInto( *it );
00454     if ( languageList.contains(*it) > 1 || (*it).isEmpty() || (!bIsTranslated) ) {
00455       // kdDebug() << "removing " << (*it) << endl;
00456       it = languageList.remove( it );
00457     }
00458   }
00459   // now this has left the first element of the list unchecked.
00460   // The question why this is the case is left as an exercise for the reader...
00461   // Besides the list might have been empty all the way, so check that too.
00462   if ( languageList.begin() != languageList.end() ) {
00463      TQStringList::Iterator it = languageList.begin(); // now pointing to the first element
00464      // kdDebug() << "checking " << (*it) << endl;
00465      if( (*it).isEmpty() || !(isApplicationTranslatedInto( *it )) ) {
00466         // kdDebug() << "removing " << (*it) << endl;
00467         languageList.remove( it ); // that's what the iterator was for...
00468      }
00469   }
00470 
00471   if ( languageList.isEmpty() ) {
00472     // user picked no language, so we assume he/she speaks English.
00473     languageList.append( defaultLanguage() );
00474   }
00475   m_language = languageList.first(); // keep this for shortcut evaluations
00476 
00477   d->languageList = languageList; // keep this new list of languages to use
00478   d->langTwoAlpha.clear(); // Flush cache
00479 
00480   // important when called from the outside and harmless when called before populating the
00481   // catalog name list
00482   updateCatalogues();
00483 
00484   return true; // we found something. Maybe it's only English, but we found something
00485 }
00486 
00487 bool TDELocale::isApplicationTranslatedInto( const TQString & language)
00488 {
00489   if ( language.isEmpty() ) {
00490     return false;
00491   }
00492 
00493   if ( language == defaultLanguage() ) {
00494     // en_us is always "installed"
00495     return true;
00496   }
00497 
00498   TQString appName = d->appName;
00499   if (maincatalogue) {
00500     appName = TQString::fromLatin1(maincatalogue);
00501   }
00502   // sorry, catalogueFileName requires catalog object,k which we do not have here
00503   // path finding was supposed to be moved completely to KCatalogue. The interface cannot
00504   // be changed that far during deep freeze. So in order to fix the bug now, we have
00505   // duplicated code for file path evaluation. Cleanup will follow later. We could have e.g.
00506   // a static method in KCataloge that can translate between these file names.
00507   // a stat
00508   TQString sFileName = TQString::fromLatin1("%1/LC_MESSAGES/%2.mo")
00509     .arg( language )
00510     .arg( appName );
00511   // kdDebug() << "isApplicationTranslatedInto: filename " << sFileName << endl;
00512 
00513   TQString sAbsFileName = locate( "locale", sFileName );
00514   if (sAbsFileName.isEmpty())
00515     sAbsFileName = locate( "locale-bundle", sFileName );
00516 
00517   // kdDebug() << "isApplicationTranslatedInto: absname " << sAbsFileName << endl;
00518   return ! sAbsFileName.isEmpty();
00519 }
00520 
00521 void TDELocale::splitLocale(const TQString & aStr,
00522               TQString & language,
00523               TQString & country,
00524               TQString & chrset)
00525 {
00526   TQString str = aStr;
00527 
00528   // just in case, there is another language appended
00529   int f = str.find(':');
00530   if (f >= 0)
00531     str.truncate(f);
00532 
00533   country = TQString::null;
00534   chrset = TQString::null;
00535   language = TQString::null;
00536 
00537   f = str.find('.');
00538   if (f >= 0)
00539     {
00540       chrset = str.mid(f + 1);
00541       str.truncate(f);
00542     }
00543 
00544   f = str.find('_');
00545   if (f >= 0)
00546     {
00547       country = str.mid(f + 1);
00548       str.truncate(f);
00549     }
00550 
00551   language = str;
00552 }
00553 
00554 TQString TDELocale::language() const
00555 {
00556   return m_language;
00557 }
00558 
00559 TQString TDELocale::country() const
00560 {
00561   return m_country;
00562 }
00563 
00564 TQString TDELocale::monthName(int i, bool shortName) const
00565 {
00566   if ( shortName )
00567     switch ( i )
00568       {
00569       case 1:   return translate("January", "Jan");
00570       case 2:   return translate("February", "Feb");
00571       case 3:   return translate("March", "Mar");
00572       case 4:   return translate("April", "Apr");
00573       case 5:   return translate("May short", "May");
00574       case 6:   return translate("June", "Jun");
00575       case 7:   return translate("July", "Jul");
00576       case 8:   return translate("August", "Aug");
00577       case 9:   return translate("September", "Sep");
00578       case 10:  return translate("October", "Oct");
00579       case 11:  return translate("November", "Nov");
00580       case 12:  return translate("December", "Dec");
00581       }
00582   else
00583     switch (i)
00584       {
00585       case 1:   return translate("January");
00586       case 2:   return translate("February");
00587       case 3:   return translate("March");
00588       case 4:   return translate("April");
00589       case 5:   return translate("May long", "May");
00590       case 6:   return translate("June");
00591       case 7:   return translate("July");
00592       case 8:   return translate("August");
00593       case 9:   return translate("September");
00594       case 10:  return translate("October");
00595       case 11:  return translate("November");
00596       case 12:  return translate("December");
00597       }
00598 
00599   return TQString::null;
00600 }
00601 
00602 TQString TDELocale::monthNamePossessive(int i, bool shortName) const
00603 {
00604   if ( shortName )
00605     switch ( i )
00606       {
00607       case 1:   return translate("of January", "of Jan");
00608       case 2:   return translate("of February", "of Feb");
00609       case 3:   return translate("of March", "of Mar");
00610       case 4:   return translate("of April", "of Apr");
00611       case 5:   return translate("of May short", "of May");
00612       case 6:   return translate("of June", "of Jun");
00613       case 7:   return translate("of July", "of Jul");
00614       case 8:   return translate("of August", "of Aug");
00615       case 9:   return translate("of September", "of Sep");
00616       case 10:  return translate("of October", "of Oct");
00617       case 11:  return translate("of November", "of Nov");
00618       case 12:  return translate("of December", "of Dec");
00619       }
00620   else
00621     switch (i)
00622       {
00623       case 1:   return translate("of January");
00624       case 2:   return translate("of February");
00625       case 3:   return translate("of March");
00626       case 4:   return translate("of April");
00627       case 5:   return translate("of May long", "of May");
00628       case 6:   return translate("of June");
00629       case 7:   return translate("of July");
00630       case 8:   return translate("of August");
00631       case 9:   return translate("of September");
00632       case 10:  return translate("of October");
00633       case 11:  return translate("of November");
00634       case 12:  return translate("of December");
00635       }
00636 
00637   return TQString::null;
00638 }
00639 
00640 TQString TDELocale::weekDayName (int i, bool shortName) const
00641 {
00642   return calendar()->weekDayName(i, shortName);
00643 }
00644 
00645 void TDELocale::insertCatalogue( const TQString & catalog )
00646 {
00647   if ( !d->catalogNames.contains( catalog) ) {
00648     d->catalogNames.append( catalog );
00649   }
00650   updateCatalogues( ); // evaluate the changed list and generate the neccessary KCatalog objects
00651 }
00652 
00653 void TDELocale::updateCatalogues( )
00654 {
00655   // some changes have occured. Maybe we have learned or forgotten some languages.
00656   // Maybe the language precedence has changed.
00657   // Maybe we have learned or forgotten some catalog names.
00658   // Now examine the list of KCatalogue objects and change it according to the new circumstances.
00659 
00660   // this could be optimized: try to reuse old KCatalog objects, but remember that the order of
00661   // catalogs might have changed: e.g. in this fashion
00662   // 1) move all catalogs into a temporary list
00663   // 2) iterate over all languages and catalog names
00664   // 3.1) pick the catalog from the saved list, if it already exists
00665   // 3.2) else create a new catalog.
00666   // but we will do this later.
00667 
00668   for ( TQValueList<KCatalogue>::Iterator it = d->catalogues.begin();
00669     it != d->catalogues.end(); )
00670   {
00671      it = d->catalogues.remove(it);
00672   }
00673 
00674   // now iterate over all languages and all wanted catalog names and append or create them in the right order
00675   // the sequence must be e.g. nds/appname nds/tdelibs nds/tdeio de/appname de/tdelibs de/tdeio etc.
00676   // and not nds/appname de/appname nds/tdelibs de/tdelibs etc. Otherwise we would be in trouble with a language
00677   // sequende nds,en_US, de. In this case en_US must hide everything below in the language list.
00678   for ( TQStringList::ConstIterator itLangs =  d->languageList.begin();
00679       itLangs != d->languageList.end(); ++itLangs)
00680   {
00681     for ( TQStringList::ConstIterator itNames =  d->catalogNames.begin();
00682     itNames != d->catalogNames.end(); ++itNames)
00683     {
00684       KCatalogue cat( *itNames, *itLangs ); // create Catalog for this name and this language
00685       d->catalogues.append( cat );
00686     }
00687   }
00688   initPluralTypes();  // evaluate the plural type for all languages and remember this in each KCatalogue
00689 }
00690 
00691 
00692 
00693 
00694 void TDELocale::removeCatalogue(const TQString &catalog)
00695 {
00696   if ( d->catalogNames.contains( catalog )) {
00697     d->catalogNames.remove( catalog );
00698     if (TDEGlobal::_instance)
00699       updateCatalogues();  // walk through the KCatalogue instances and weed out everything we no longer need
00700   }
00701 }
00702 
00703 void TDELocale::setActiveCatalogue(const TQString &catalog)
00704 {
00705   if ( d->catalogNames.contains( catalog ) ) {
00706     d->catalogNames.remove( catalog );
00707     d->catalogNames.prepend( catalog );
00708     updateCatalogues();  // walk through the KCatalogue instances and adapt to the new order
00709   }
00710 }
00711 
00712 TDELocale::~TDELocale()
00713 {
00714   delete d->calendar;
00715   delete d->languages;
00716   delete d;
00717   d = 0L;
00718 }
00719 
00720 TQString TDELocale::translate_priv(const char *msgid,
00721                 const char *fallback,
00722                 const char **translated,
00723                 int* pluralType ) const
00724 {
00725   if ( pluralType) {
00726     *pluralType = -1; // unless we find something more precise
00727   }
00728   if (!msgid || !msgid[0])
00729     {
00730       kdWarning() << "TDELocale: trying to look up \"\" in catalog. "
00731            << "Fix the program" << endl;
00732       return TQString::null;
00733     }
00734 
00735   if ( useDefaultLanguage() ) { // shortcut evaluation if en_US is main language: do not consult the catalogs
00736     return TQString::fromUtf8( fallback );
00737   }
00738 
00739   for ( TQValueList<KCatalogue>::ConstIterator it = d->catalogues.begin();
00740     it != d->catalogues.end();
00741     ++it )
00742     {
00743       // shortcut evaluation: once we have arrived at en_US (default language) we cannot consult
00744       // the catalog as it will not have an assiciated mo-file. For this default language we can
00745       // immediately pick the fallback string.
00746       if ( (*it).language() == defaultLanguage() ) {
00747         return TQString::fromUtf8( fallback );
00748       }
00749 
00750       const char * text = (*it).translate( msgid );
00751 
00752       if ( text )
00753     {
00754       // we found it
00755       if (translated) {
00756         *translated = text;
00757       }
00758       if ( pluralType) {
00759         *pluralType = (*it).pluralType(); // remember the plural type information from the catalog that was used
00760       }
00761       return TQString::fromUtf8( text );
00762     }
00763     }
00764 
00765   // Always use UTF-8 if the string was not found
00766   return TQString::fromUtf8( fallback );
00767 }
00768 
00769 TQString TDELocale::translate(const char* msgid) const
00770 {
00771   return translate_priv(msgid, msgid);
00772 }
00773 
00774 TQString TDELocale::translate( const char *index, const char *fallback) const
00775 {
00776   if (!index || !index[0] || !fallback || !fallback[0])
00777     {
00778       kdDebug(173) << "TDELocale: trying to look up \"\" in catalog. "
00779            << "Fix the program" << endl;
00780       return TQString::null;
00781     }
00782 
00783   if ( useDefaultLanguage() )
00784     return TQString::fromUtf8( fallback );
00785 
00786   char *newstring = new char[strlen(index) + strlen(fallback) + 5];
00787   sprintf(newstring, "_: %s\n%s", index, fallback);
00788   // as copying TQString is very fast, it looks slower as it is ;/
00789   TQString r = translate_priv(newstring, fallback);
00790   delete [] newstring;
00791 
00792   return r;
00793 }
00794 
00795 static TQString put_n_in(const TQString &orig, unsigned long n)
00796 {
00797   TQString ret = orig;
00798   int index = ret.find("%n");
00799   if (index == -1)
00800     return ret;
00801   ret.replace(index, 2, TQString::number(n));
00802   return ret;
00803 }
00804 
00805 #define EXPECT_LENGTH(x) \
00806    if (forms.count() != x) { \
00807       kdError() << "translation of \"" << singular << "\" doesn't contain " << x << " different plural forms as expected\n"; \
00808       return TQString( "BROKEN TRANSLATION %1" ).arg( singular ); }
00809 
00810 TQString TDELocale::translate( const char *singular, const char *plural,
00811                             unsigned long n ) const
00812 {
00813   if (!singular || !singular[0] || !plural || !plural[0])
00814     {
00815       kdWarning() << "TDELocale: trying to look up \"\" in catalog. "
00816            << "Fix the program" << endl;
00817       return TQString::null;
00818     }
00819 
00820   char *newstring = new char[strlen(singular) + strlen(plural) + 6];
00821   sprintf(newstring, "_n: %s\n%s", singular, plural);
00822   // as copying TQString is very fast, it looks slower as it is ;/
00823   int pluralType = -1;
00824   TQString r = translate_priv(newstring, 0, 0, &pluralType);
00825   delete [] newstring;
00826 
00827   if ( r.isEmpty() || useDefaultLanguage() || pluralType == -1) {
00828     if ( n == 1 ) {
00829       return put_n_in( TQString::fromUtf8( singular ),  n );
00830     } else {
00831       TQString tmp = TQString::fromUtf8( plural );
00832 #ifndef NDEBUG
00833       if (tmp.find("%n") == -1) {
00834               kdDebug() << "the message for i18n should contain a '%n'! " << plural << endl;
00835       }
00836 #endif
00837       return put_n_in( tmp,  n );
00838     }
00839   }
00840 
00841   TQStringList forms = TQStringList::split( "\n", r, false );
00842   switch ( pluralType ) {
00843   case 0: // NoPlural
00844     EXPECT_LENGTH( 1 );
00845     return put_n_in( forms[0], n);
00846   case 1: // TwoForms
00847     EXPECT_LENGTH( 2 );
00848     if ( n == 1 )
00849       return put_n_in( forms[0], n);
00850     else
00851       return put_n_in( forms[1], n);
00852   case 2: // French
00853     EXPECT_LENGTH( 2 );
00854     if ( n == 1 || n == 0 )
00855       return put_n_in( forms[0], n);
00856     else
00857       return put_n_in( forms[1], n);
00858   case 3: // OneTwoRest
00859     EXPECT_LENGTH( 3 );
00860     if ( n == 1 )
00861       return put_n_in( forms[0], n);
00862     else if ( n == 2 )
00863       return put_n_in( forms[1], n);
00864     else
00865       return put_n_in( forms[2], n);
00866   case 4: // Russian, corrected by mok
00867     EXPECT_LENGTH( 3 );
00868     if ( n%10 == 1  &&  n%100 != 11)
00869       return put_n_in( forms[0], n); // odin fail
00870     else if (( n%10 >= 2 && n%10 <=4 ) && (n%100<10 || n%100>20))
00871       return put_n_in( forms[1], n); // dva faila
00872     else
00873       return put_n_in( forms[2], n); // desyat' failov
00874   case 5: // Polish
00875     EXPECT_LENGTH( 3 );
00876     if ( n == 1 )
00877       return put_n_in( forms[0], n);
00878     else if ( n%10 >= 2 && n%10 <=4 && (n%100<10 || n%100>=20) )
00879       return put_n_in( forms[1], n);
00880     else
00881       return put_n_in( forms[2], n);
00882   case 6: // Slovenian
00883     EXPECT_LENGTH( 4 );
00884     if ( n%100 == 1 )
00885       return put_n_in( forms[1], n); // ena datoteka
00886     else if ( n%100 == 2 )
00887       return put_n_in( forms[2], n); // dve datoteki
00888     else if ( n%100 == 3 || n%100 == 4 )
00889       return put_n_in( forms[3], n); // tri datoteke
00890     else
00891       return put_n_in( forms[0], n); // sto datotek
00892   case 7: // Lithuanian
00893     EXPECT_LENGTH( 3 );
00894     if ( n%10 == 0 || (n%100>=11 && n%100<=19) )
00895       return put_n_in( forms[2], n);
00896     else if ( n%10 == 1 )
00897       return put_n_in( forms[0], n);
00898     else
00899       return put_n_in( forms[1], n);
00900   case 8: // Czech - use modern form which is equivalent to Slovak
00901   case 9: // Slovak
00902     EXPECT_LENGTH( 3 );
00903     if ( n == 1 )
00904       return put_n_in( forms[0], n);
00905     else if (( n >= 2 ) && ( n <= 4 ))
00906       return put_n_in( forms[1], n);
00907     else
00908       return put_n_in( forms[2], n);
00909   case 10: // Maltese
00910     EXPECT_LENGTH( 4 );
00911     if ( n == 1 )
00912       return put_n_in( forms[0], n );
00913     else if ( ( n == 0 ) || ( n%100 > 0 && n%100 <= 10 ) )
00914       return put_n_in( forms[1], n );
00915     else if ( n%100 > 10 && n%100 < 20 )
00916       return put_n_in( forms[2], n );
00917     else
00918       return put_n_in( forms[3], n );
00919   case 11: // Arabic
00920     EXPECT_LENGTH( 4 );
00921     if (n == 1)
00922       return put_n_in(forms[0], n);
00923     else if (n == 2)
00924       return put_n_in(forms[1], n);
00925     else if ( n < 11)
00926       return put_n_in(forms[2], n);
00927     else
00928       return put_n_in(forms[3], n);
00929   case 12: // Balcan
00930      EXPECT_LENGTH( 3 );
00931      if (n != 11 && n % 10 == 1)
00932     return put_n_in(forms[0], n);
00933      else if (n / 10 != 1 && n % 10 >= 2 && n % 10 <= 4)
00934     return put_n_in(forms[1], n);
00935      else
00936     return put_n_in(forms[2], n);
00937   case 13: // Macedonian
00938      EXPECT_LENGTH(3);
00939      if (n % 10 == 1)
00940     return put_n_in(forms[0], n);
00941      else if (n % 10 == 2)
00942     return put_n_in(forms[1], n);
00943      else
00944     return put_n_in(forms[2], n);
00945   case 14: // Gaeilge
00946       EXPECT_LENGTH(5);
00947       if (n == 1)                       // "ceann amhain"
00948           return put_n_in(forms[0], n);
00949       else if (n == 2)                  // "dha cheann"
00950           return put_n_in(forms[1], n);
00951       else if (n < 7)                   // "%n cinn"
00952           return put_n_in(forms[2], n);
00953       else if (n < 11)                  // "%n gcinn"
00954           return put_n_in(forms[3], n);
00955       else                              // "%n ceann"
00956           return put_n_in(forms[4], n);
00957   }
00958   kdFatal() << "The function should have been returned in another way\n";
00959 
00960   return TQString::null;
00961 }
00962 
00963 TQString TDELocale::translateQt( const char *context, const char *source,
00964                   const char *message) const
00965 {
00966   if (!source || !source[0]) {
00967     kdWarning() << "TDELocale: trying to look up \"\" in catalog. "
00968         << "Fix the program" << endl;
00969     return TQString::null;
00970   }
00971 
00972   if ( useDefaultLanguage() ) {
00973     return TQString::null;
00974   }
00975 
00976   char *newstring = 0;
00977   const char *translation = 0;
00978   TQString r;
00979 
00980   if ( message && message[0]) {
00981     char *newstring = new char[strlen(source) + strlen(message) + 5];
00982     sprintf(newstring, "_: %s\n%s", source, message);
00983     const char *translation = 0;
00984     // as copying TQString is very fast, it looks slower as it is ;/
00985     r = translate_priv(newstring, source, &translation);
00986     delete [] newstring;
00987     if (translation)
00988       return r;
00989   }
00990 
00991   if ( context && context[0] && message && message[0]) {
00992     newstring = new char[strlen(context) + strlen(message) + 5];
00993     sprintf(newstring, "_: %s\n%s", context, message);
00994     // as copying TQString is very fast, it looks slower as it is ;/
00995     r = translate_priv(newstring, source, &translation);
00996     delete [] newstring;
00997     if (translation)
00998       return r;
00999   }
01000 
01001   r = translate_priv(source, source, &translation);
01002   if (translation)
01003     return r;
01004   return TQString::null;
01005 }
01006 
01007 bool TDELocale::nounDeclension() const
01008 {
01009   doFormatInit();
01010   return d->nounDeclension;
01011 }
01012 
01013 bool TDELocale::dateMonthNamePossessive() const
01014 {
01015   doFormatInit();
01016   return d->dateMonthNamePossessive;
01017 }
01018 
01019 int TDELocale::weekStartDay() const
01020 {
01021   doFormatInit();
01022   return d->weekStartDay;
01023 }
01024 
01025 bool TDELocale::weekStartsMonday() const //deprecated
01026 {
01027   doFormatInit();
01028   return (d->weekStartDay==1);
01029 }
01030 
01031 TQString TDELocale::decimalSymbol() const
01032 {
01033   doFormatInit();
01034   return m_decimalSymbol;
01035 }
01036 
01037 TQString TDELocale::thousandsSeparator() const
01038 {
01039   doFormatInit();
01040   return m_thousandsSeparator;
01041 }
01042 
01043 TQString TDELocale::currencySymbol() const
01044 {
01045   doFormatInit();
01046   return m_currencySymbol;
01047 }
01048 
01049 TQString TDELocale::monetaryDecimalSymbol() const
01050 {
01051   doFormatInit();
01052   return m_monetaryDecimalSymbol;
01053 }
01054 
01055 TQString TDELocale::monetaryThousandsSeparator() const
01056 {
01057   doFormatInit();
01058   return m_monetaryThousandsSeparator;
01059 }
01060 
01061 TQString TDELocale::positiveSign() const
01062 {
01063   doFormatInit();
01064   return m_positiveSign;
01065 }
01066 
01067 TQString TDELocale::negativeSign() const
01068 {
01069   doFormatInit();
01070   return m_negativeSign;
01071 }
01072 
01073 int TDELocale::fracDigits() const
01074 {
01075   doFormatInit();
01076   return m_fracDigits;
01077 }
01078 
01079 bool TDELocale::positivePrefixCurrencySymbol() const
01080 {
01081   doFormatInit();
01082   return m_positivePrefixCurrencySymbol;
01083 }
01084 
01085 bool TDELocale::negativePrefixCurrencySymbol() const
01086 {
01087   doFormatInit();
01088   return m_negativePrefixCurrencySymbol;
01089 }
01090 
01091 TDELocale::SignPosition TDELocale::positiveMonetarySignPosition() const
01092 {
01093   doFormatInit();
01094   return m_positiveMonetarySignPosition;
01095 }
01096 
01097 TDELocale::SignPosition TDELocale::negativeMonetarySignPosition() const
01098 {
01099   doFormatInit();
01100   return m_negativeMonetarySignPosition;
01101 }
01102 
01103 static inline void put_it_in( TQChar *buffer, uint& index, const TQString &s )
01104 {
01105   for ( uint l = 0; l < s.length(); l++ )
01106     buffer[index++] = s.at( l );
01107 }
01108 
01109 static inline void put_it_in( TQChar *buffer, uint& index, int number )
01110 {
01111   buffer[index++] = number / 10 + '0';
01112   buffer[index++] = number % 10 + '0';
01113 }
01114 
01115 // insert (thousands)-"separator"s into the non-fractional part of str 
01116 static void _insertSeparator(TQString &str, const TQString &separator,
01117                  const TQString &decimalSymbol)
01118 {
01119   // leave fractional part untouched
01120   TQString mainPart = str.section(decimalSymbol, 0, 0);
01121   TQString fracPart = str.section(decimalSymbol, 1, 1,
01122                  TQString::SectionIncludeLeadingSep);
01123   
01124   for (int pos = mainPart.length() - 3; pos > 0; pos -= 3)
01125     mainPart.insert(pos, separator);
01126 
01127   str = mainPart + fracPart;
01128 }
01129 
01130 TQString TDELocale::formatMoney(double num,
01131                  const TQString & symbol,
01132                  int precision) const
01133 {
01134   // some defaults
01135   TQString currency = symbol.isNull()
01136     ? currencySymbol()
01137     : symbol;
01138   if (precision < 0) precision = fracDigits();
01139 
01140   // the number itself
01141   bool neg = num < 0;
01142   TQString res = TQString::number(neg?-num:num, 'f', precision);
01143 
01144   // Replace dot with locale decimal separator
01145   res.replace(TQChar('.'), monetaryDecimalSymbol());
01146 
01147   // Insert the thousand separators
01148   _insertSeparator(res, monetaryThousandsSeparator(), monetaryDecimalSymbol());
01149 
01150   // set some variables we need later
01151   int signpos = neg
01152     ? negativeMonetarySignPosition()
01153     : positiveMonetarySignPosition();
01154   TQString sign = neg
01155     ? negativeSign()
01156     : positiveSign();
01157 
01158   switch (signpos)
01159     {
01160     case ParensAround:
01161       res.prepend('(');
01162       res.append (')');
01163       break;
01164     case BeforeQuantityMoney:
01165       res.prepend(sign);
01166       break;
01167     case AfterQuantityMoney:
01168       res.append(sign);
01169       break;
01170     case BeforeMoney:
01171       currency.prepend(sign);
01172       break;
01173     case AfterMoney:
01174       currency.append(sign);
01175       break;
01176     }
01177 
01178   if (neg?negativePrefixCurrencySymbol():
01179       positivePrefixCurrencySymbol())
01180     {
01181       res.prepend(' ');
01182       res.prepend(currency);
01183     } else {
01184       res.append (' ');
01185       res.append (currency);
01186     }
01187 
01188   return res;
01189 }
01190 
01191 TQString TDELocale::formatMoney(const TQString &numStr) const
01192 {
01193   return formatMoney(numStr.toDouble());
01194 }
01195 
01196 TQString TDELocale::formatNumber(double num, int precision) const
01197 {
01198   if (precision == -1) precision = 2;
01199   // no need to round since TQString::number does this for us
01200   return formatNumber(TQString::number(num, 'f', precision), false, 0);
01201 }
01202 
01203 TQString TDELocale::formatLong(long num) const
01204 {
01205   return formatNumber((double)num, 0);
01206 }
01207 
01208 TQString TDELocale::formatNumber(const TQString &numStr) const
01209 {
01210   return formatNumber(numStr, true, 2);
01211 }
01212 
01213 // increase the digit at 'position' by one
01214 static void _inc_by_one(TQString &str, int position)
01215 {
01216   for (int i = position; i >= 0; i--)
01217     {
01218       char last_char = str[i].latin1();
01219       switch(last_char)
01220     {
01221     case '0':
01222       str[i] = (QChar)'1';
01223       break;
01224     case '1':
01225       str[i] = (QChar)'2';
01226       break;
01227     case '2':
01228       str[i] = (QChar)'3';
01229       break;
01230     case '3':
01231       str[i] = (QChar)'4';
01232       break;
01233     case '4':
01234       str[i] = (QChar)'5';
01235       break;
01236     case '5':
01237       str[i] = (QChar)'6';
01238       break;
01239     case '6':
01240       str[i] = (QChar)'7';
01241       break;
01242     case '7':
01243       str[i] = (QChar)'8';
01244       break;
01245     case '8':
01246       str[i] = (QChar)'9';
01247       break;
01248     case '9':
01249       str[i] = (QChar)'0';
01250       if (i == 0) str.prepend('1');
01251       continue;
01252     case '.':
01253       continue;
01254     }
01255       break;
01256     }
01257 }
01258 
01259 // Cut off if more digits in fractional part than 'precision'
01260 static void _round(TQString &str, int precision)
01261 {
01262   int decimalSymbolPos = str.find('.');
01263 
01264   if (decimalSymbolPos == -1)
01265     if (precision == 0)  return;
01266     else if (precision > 0) // add dot if missing (and needed)
01267       {
01268     str.append('.');
01269     decimalSymbolPos = str.length() - 1;
01270       }
01271 
01272   // fill up with more than enough zeroes (in case fractional part too short)
01273   str.append(TQString().fill('0', precision));
01274 
01275   // Now decide whether to round up or down
01276   char last_char = str[decimalSymbolPos + precision + 1].latin1();
01277   switch (last_char)
01278     {
01279     case '0':
01280     case '1':
01281     case '2':
01282     case '3':
01283     case '4':
01284       // nothing to do, rounding down
01285       break;
01286     case '5':
01287     case '6':
01288     case '7':
01289     case '8':
01290     case '9':
01291       _inc_by_one(str, decimalSymbolPos + precision);
01292       break;
01293     default:
01294       break;
01295     }
01296 
01297   decimalSymbolPos = str.find('.');
01298   str.truncate(decimalSymbolPos + precision + 1);
01299   
01300   // if precision == 0 delete also '.'
01301   if (precision == 0) str = str.section('.', 0, 0);
01302 }
01303 
01304 TQString TDELocale::formatNumber(const TQString &numStr, bool round,
01305                   int precision) const
01306 {
01307   TQString tmpString = numStr;
01308   if ((round  && precision < 0)  ||
01309       ! TQRegExp("^[+-]?\\d+(\\.\\d+)*(e[+-]?\\d+)?$").exactMatch(tmpString))
01310     return numStr;
01311 
01312   
01313   // Skip the sign (for now)
01314   bool neg = (tmpString[0] == (QChar)'-');
01315   if (neg  ||  tmpString[0] == (QChar)'+') tmpString.remove(0, 1);
01316 
01317   // Split off exponential part (including 'e'-symbol)
01318   TQString mantString = tmpString.section('e', 0, 0,
01319                      TQString::SectionCaseInsensitiveSeps);
01320   TQString expString = tmpString.section('e', 1, 1,
01321                     TQString::SectionCaseInsensitiveSeps |
01322                     TQString::SectionIncludeLeadingSep);
01323 
01324   if (round) _round(mantString, precision);
01325  
01326   // Replace dot with locale decimal separator
01327   mantString.replace(TQChar('.'), decimalSymbol());
01328   
01329   // Insert the thousand separators
01330   _insertSeparator(mantString, thousandsSeparator(), decimalSymbol());
01331 
01332   // How can we know where we should put the sign?
01333   mantString.prepend(neg?negativeSign():positiveSign());
01334   
01335   return mantString +  expString;
01336 }
01337 
01338 TQString TDELocale::formatDate(const TQDate &pDate, bool shortFormat) const
01339 {
01340   const TQString rst = shortFormat?dateFormatShort():dateFormat();
01341 
01342   TQString buffer;
01343 
01344   if ( ! pDate.isValid() ) return buffer;
01345 
01346   bool escape = false;
01347 
01348   int year = calendar()->year(pDate);
01349   int month = calendar()->month(pDate);
01350 
01351   for ( uint format_index = 0; format_index < rst.length(); ++format_index )
01352     {
01353       if ( !escape )
01354     {
01355       if ( (TQChar(rst.at( format_index )).unicode()) == '%' )
01356         escape = true;
01357       else
01358         buffer.append(rst.at(format_index));
01359     }
01360       else
01361     {
01362       switch ( TQChar(rst.at( format_index )).unicode() )
01363         {
01364         case '%':
01365           buffer.append('%');
01366           break;
01367         case 'Y':
01368           buffer.append(calendar()->yearString(pDate, false));
01369           break;
01370         case 'y':
01371           buffer.append(calendar()->yearString(pDate, true));
01372           break;
01373         case 'n':
01374               buffer.append(calendar()->monthString(pDate, true));
01375           break;
01376         case 'e':
01377               buffer.append(calendar()->dayString(pDate, true));
01378           break;
01379         case 'm':
01380               buffer.append(calendar()->monthString(pDate, false));
01381           break;
01382         case 'b':
01383           if (d->nounDeclension && d->dateMonthNamePossessive)
01384         buffer.append(calendar()->monthNamePossessive(month, year, true));
01385           else
01386         buffer.append(calendar()->monthName(month, year, true));
01387           break;
01388         case 'B':
01389           if (d->nounDeclension && d->dateMonthNamePossessive)
01390         buffer.append(calendar()->monthNamePossessive(month, year, false));
01391           else
01392         buffer.append(calendar()->monthName(month, year, false));
01393           break;
01394         case 'd':
01395               buffer.append(calendar()->dayString(pDate, false));
01396           break;
01397         case 'a':
01398           buffer.append(calendar()->weekDayName(pDate, true));
01399           break;
01400         case 'A':
01401           buffer.append(calendar()->weekDayName(pDate, false));
01402           break;
01403         default:
01404           buffer.append(rst.at(format_index));
01405           break;
01406         }
01407       escape = false;
01408     }
01409     }
01410   return buffer;
01411 }
01412 
01413 void TDELocale::setMainCatalogue(const char *catalog)
01414 {
01415   maincatalogue = catalog;
01416 }
01417 
01418 double TDELocale::readNumber(const TQString &_str, bool * ok) const
01419 {
01420   TQString str = _str.stripWhiteSpace();
01421   bool neg = str.find(negativeSign()) == 0;
01422   if (neg)
01423     str.remove( 0, negativeSign().length() );
01424 
01425   /* will hold the scientific notation portion of the number.
01426      Example, with 2.34E+23, exponentialPart == "E+23"
01427   */
01428   TQString exponentialPart;
01429   int EPos;
01430 
01431   EPos = str.find('E', 0, false);
01432 
01433   if (EPos != -1)
01434   {
01435     exponentialPart = str.mid(EPos);
01436     str = str.left(EPos);
01437   }
01438 
01439   int pos = str.find(decimalSymbol());
01440   TQString major;
01441   TQString minor;
01442   if ( pos == -1 )
01443     major = str;
01444   else
01445     {
01446       major = str.left(pos);
01447       minor = str.mid(pos + decimalSymbol().length());
01448     }
01449 
01450   // Remove thousand separators
01451   int thlen = thousandsSeparator().length();
01452   int lastpos = 0;
01453   while ( ( pos = major.find( thousandsSeparator() ) ) > 0 )
01454   {
01455     // e.g. 12,,345,,678,,922 Acceptable positions (from the end) are 5, 10, 15... i.e. (3+thlen)*N
01456     int fromEnd = major.length() - pos;
01457     if ( fromEnd % (3+thlen) != 0 // Needs to be a multiple, otherwise it's an error
01458         || pos - lastpos > 3 // More than 3 digits between two separators -> error
01459         || pos == 0          // Can't start with a separator
01460         || (lastpos>0 && pos-lastpos!=3))   // Must have exactly 3 digits between two separators
01461     {
01462       if (ok) *ok = false;
01463       return 0.0;
01464     }
01465 
01466     lastpos = pos;
01467     major.remove( pos, thlen );
01468   }
01469   if (lastpos>0 && major.length()-lastpos!=3)   // Must have exactly 3 digits after the last separator
01470   {
01471     if (ok) *ok = false;
01472     return 0.0;
01473   }
01474 
01475   TQString tot;
01476   if (neg) tot = (QChar)'-';
01477 
01478   tot += major + '.' + minor + exponentialPart;
01479 
01480   return tot.toDouble(ok);
01481 }
01482 
01483 double TDELocale::readMoney(const TQString &_str, bool * ok) const
01484 {
01485   TQString str = _str.stripWhiteSpace();
01486   bool neg = false;
01487   bool currencyFound = false;
01488   TQString symbol = currencySymbol();
01489   // First try removing currency symbol from either end
01490   int pos = str.find(symbol);
01491   if ( pos == 0 || pos == (int) str.length()-symbol.length() )
01492     {
01493       str.remove(pos,symbol.length());
01494       str = str.stripWhiteSpace();
01495       currencyFound = true;
01496     }
01497   if (str.isEmpty())
01498     {
01499       if (ok) *ok = false;
01500       return 0;
01501     }
01502   // Then try removing negative sign from either end
01503   // (with a special case for parenthesis)
01504   if (negativeMonetarySignPosition() == ParensAround)
01505     {
01506       if (str[0] == (QChar)'(' && str[str.length()-1] == (QChar)')')
01507         {
01508       neg = true;
01509       str.remove(str.length()-1,1);
01510       str.remove(0,1);
01511         }
01512     }
01513   else
01514     {
01515       int i1 = str.find(negativeSign());
01516       if ( i1 == 0 || i1 == (int) str.length()-1 )
01517         {
01518       neg = true;
01519       str.remove(i1,negativeSign().length());
01520         }
01521     }
01522   if (neg) str = str.stripWhiteSpace();
01523 
01524   // Finally try again for the currency symbol, if we didn't find
01525   // it already (because of the negative sign being in the way).
01526   if ( !currencyFound )
01527     {
01528       pos = str.find(symbol);
01529       if ( pos == 0 || pos == (int) str.length()-symbol.length() )
01530         {
01531       str.remove(pos,symbol.length());
01532       str = str.stripWhiteSpace();
01533         }
01534     }
01535 
01536   // And parse the rest as a number
01537   pos = str.find(monetaryDecimalSymbol());
01538   TQString major;
01539   TQString minior;
01540   if (pos == -1)
01541     major = str;
01542   else
01543     {
01544       major = str.left(pos);
01545       minior = str.mid(pos + monetaryDecimalSymbol().length());
01546     }
01547 
01548   // Remove thousand separators
01549   int thlen = monetaryThousandsSeparator().length();
01550   int lastpos = 0;
01551   while ( ( pos = major.find( monetaryThousandsSeparator() ) ) > 0 )
01552   {
01553     // e.g. 12,,345,,678,,922 Acceptable positions (from the end) are 5, 10, 15... i.e. (3+thlen)*N
01554     int fromEnd = major.length() - pos;
01555     if ( fromEnd % (3+thlen) != 0 // Needs to be a multiple, otherwise it's an error
01556         || pos - lastpos > 3 // More than 3 digits between two separators -> error
01557         || pos == 0          // Can't start with a separator
01558         || (lastpos>0 && pos-lastpos!=3))   // Must have exactly 3 digits between two separators
01559     {
01560       if (ok) *ok = false;
01561       return 0.0;
01562     }
01563     lastpos = pos;
01564     major.remove( pos, thlen );
01565   }
01566   if (lastpos>0 && major.length()-lastpos!=3)   // Must have exactly 3 digits after the last separator
01567   {
01568     if (ok) *ok = false;
01569     return 0.0;
01570   }
01571 
01572   TQString tot;
01573   if (neg) tot = (QChar)'-';
01574   tot += major + '.' + minior;
01575   return tot.toDouble(ok);
01576 }
01577 
01584 static int readInt(const TQString &str, uint &pos)
01585 {
01586   if (!str.at(pos).isDigit()) return -1;
01587   int result = 0;
01588   for (; str.length() > pos && str.at(pos).isDigit(); pos++)
01589     {
01590       result *= 10;
01591       result += str.at(pos).digitValue();
01592     }
01593 
01594   return result;
01595 }
01596 
01597 TQDate TDELocale::readDate(const TQString &intstr, bool* ok) const
01598 {
01599   TQDate date;
01600   date = readDate(intstr, ShortFormat, ok);
01601   if (date.isValid()) return date;
01602   return readDate(intstr, NormalFormat, ok);
01603 }
01604 
01605 TQDate TDELocale::readDate(const TQString &intstr, ReadDateFlags flags, bool* ok) const
01606 {
01607   TQString fmt = ((flags & ShortFormat) ? dateFormatShort() : dateFormat()).simplifyWhiteSpace();
01608   return readDate( intstr, fmt, ok );
01609 }
01610 
01611 TQDate TDELocale::readDate(const TQString &intstr, const TQString &fmt, bool* ok) const
01612 {
01613   //kdDebug() << "TDELocale::readDate intstr=" << intstr << " fmt=" << fmt << endl;
01614   TQString str = intstr.simplifyWhiteSpace().lower();
01615   int day = -1, month = -1;
01616   // allow the year to be omitted if not in the format
01617   int year = calendar()->year(TQDate::currentDate());
01618   uint strpos = 0;
01619   uint fmtpos = 0;
01620 
01621   int iLength; // Temporary variable used when reading input
01622 
01623   bool error = false;
01624 
01625   while (fmt.length() > fmtpos && str.length() > strpos && !error)
01626   {
01627 
01628     TQChar c = fmt.at(fmtpos++);
01629 
01630     if (c != (QChar)'%') {
01631       if (c.isSpace() && str.at(strpos).isSpace())
01632         strpos++;
01633       else if (c != str.at(strpos++))
01634         error = true;
01635     }
01636     else
01637     {
01638       int j;
01639       // remove space at the beginning
01640       if (str.length() > strpos && str.at(strpos).isSpace())
01641         strpos++;
01642 
01643       c = fmt.at(fmtpos++);
01644       switch (c)
01645       {
01646     case 'a':
01647     case 'A':
01648 
01649           error = true;
01650       j = 1;
01651       while (error && (j < 8)) {
01652         TQString s = calendar()->weekDayName(j, c == (QChar)'a').lower();
01653         int len = s.length();
01654         if (str.mid(strpos, len) == s)
01655             {
01656           strpos += len;
01657               error = false;
01658             }
01659         j++;
01660       }
01661       break;
01662     case 'b':
01663     case 'B':
01664 
01665           error = true;
01666       if (d->nounDeclension && d->dateMonthNamePossessive) {
01667         j = 1;
01668         while (error && (j < 13)) {
01669           TQString s = calendar()->monthNamePossessive(j, year, c == (QChar)'b').lower();
01670           int len = s.length();
01671           if (str.mid(strpos, len) == s) {
01672             month = j;
01673             strpos += len;
01674                 error = false;
01675           }
01676           j++;
01677         }
01678       }
01679       j = 1;
01680       while (error && (j < 13)) {
01681         TQString s = calendar()->monthName(j, year, c == (QChar)'b').lower();
01682         int len = s.length();
01683         if (str.mid(strpos, len) == s) {
01684           month = j;
01685           strpos += len;
01686               error = false;
01687         }
01688         j++;
01689       }
01690       break;
01691     case 'd':
01692     case 'e':
01693       day = calendar()->dayStringToInteger(str.mid(strpos), iLength);
01694       strpos += iLength;
01695 
01696       error = iLength <= 0;
01697       break;
01698 
01699     case 'n':
01700     case 'm':
01701       month = calendar()->monthStringToInteger(str.mid(strpos), iLength);
01702       strpos += iLength;
01703 
01704       error = iLength <= 0;
01705       break;
01706 
01707     case 'Y':
01708     case 'y':
01709       year = calendar()->yearStringToInteger(str.mid(strpos), iLength);
01710       strpos += iLength;
01711 
01712       error = iLength <= 0;
01713       break;
01714       }
01715     }
01716   }
01717 
01718   /* for a match, we should reach the end of both strings, not just one of
01719      them */
01720   if ( fmt.length() > fmtpos || str.length() > strpos )
01721   {
01722     error = true;
01723   }
01724 
01725   //kdDebug(173) << "TDELocale::readDate day=" << day << " month=" << month << " year=" << year << endl;
01726   if ( year != -1 && month != -1 && day != -1 && !error)
01727   {
01728     if (ok) *ok = true;
01729 
01730     TQDate result;
01731     calendar()->setYMD(result, year, month, day);
01732 
01733     return result;
01734   }
01735   else
01736   {
01737     if (ok) *ok = false;
01738     return TQDate(); // invalid date
01739   }
01740 }
01741 
01742 TQTime TDELocale::readTime(const TQString &intstr, bool *ok) const
01743 {
01744   TQTime _time;
01745   _time = readTime(intstr, WithSeconds, ok);
01746   if (_time.isValid()) return _time;
01747   return readTime(intstr, WithoutSeconds, ok);
01748 }
01749 
01750 TQTime TDELocale::readTime(const TQString &intstr, ReadTimeFlags flags, bool *ok) const
01751 {
01752   TQString str = intstr.simplifyWhiteSpace().lower();
01753   TQString Format = timeFormat().simplifyWhiteSpace();
01754   if (flags & WithoutSeconds)
01755     Format.remove(TQRegExp(".%S"));
01756 
01757   int hour = -1, minute = -1;
01758   int second = ( (flags & WithoutSeconds) == 0 ) ? -1 : 0; // don't require seconds
01759   bool g_12h = false;
01760   bool pm = false;
01761   uint strpos = 0;
01762   uint Formatpos = 0;
01763 
01764   while (Format.length() > Formatpos || str.length() > strpos)
01765     {
01766       if ( !(Format.length() > Formatpos && str.length() > strpos) ) goto error;
01767 
01768       TQChar c = Format.at(Formatpos++);
01769 
01770       if (c != (QChar)'%')
01771     {
01772       if (c.isSpace())
01773         strpos++;
01774       else if (c != str.at(strpos++))
01775         goto error;
01776       continue;
01777     }
01778 
01779       // remove space at the beginning
01780       if (str.length() > strpos && str.at(strpos).isSpace())
01781     strpos++;
01782 
01783       c = Format.at(Formatpos++);
01784       switch (c)
01785     {
01786     case 'p':
01787       {
01788         TQString s;
01789         s = translate("pm").lower();
01790         int len = s.length();
01791         if (str.mid(strpos, len) == s)
01792           {
01793         pm = true;
01794         strpos += len;
01795           }
01796         else
01797           {
01798         s = translate("am").lower();
01799         len = s.length();
01800         if (str.mid(strpos, len) == s) {
01801           pm = false;
01802           strpos += len;
01803         }
01804         else
01805           goto error;
01806           }
01807       }
01808       break;
01809 
01810     case 'k':
01811     case 'H':
01812       g_12h = false;
01813       hour = readInt(str, strpos);
01814       if (hour < 0 || hour > 23)
01815         goto error;
01816 
01817       break;
01818 
01819     case 'l':
01820     case 'I':
01821       g_12h = true;
01822       hour = readInt(str, strpos);
01823       if (hour < 1 || hour > 12)
01824         goto error;
01825 
01826       break;
01827 
01828     case 'M':
01829       minute = readInt(str, strpos);
01830       if (minute < 0 || minute > 59)
01831         goto error;
01832 
01833       break;
01834 
01835     case 'S':
01836       second = readInt(str, strpos);
01837       if (second < 0 || second > 59)
01838         goto error;
01839 
01840       break;
01841     }
01842     }
01843   if (g_12h) {
01844     hour %= 12;
01845     if (pm) hour += 12;
01846   }
01847 
01848   if (ok) *ok = true;
01849   return TQTime(hour, minute, second);
01850 
01851  error:
01852   if (ok) *ok = false;
01853   // ######## KDE4: remove this
01854   return TQTime(-1, -1, -1); // return invalid date if it didn't work
01855 }
01856 
01857 //BIC: merge with below
01858 TQString TDELocale::formatTime(const TQTime &pTime, bool includeSecs) const
01859 {
01860   return formatTime( pTime, includeSecs, false );
01861 }
01862 
01863 TQString TDELocale::formatTime(const TQTime &pTime, bool includeSecs, bool isDuration) const
01864 {
01865   const TQString rst = timeFormat();
01866 
01867   // only "pm/am" here can grow, the rest shrinks, but
01868   // I'm rather safe than sorry
01869   TQChar *buffer = new TQChar[rst.length() * 3 / 2 + 30];
01870 
01871   uint index = 0;
01872   bool escape = false;
01873   int number = 0;
01874 
01875   for ( uint format_index = 0; format_index < rst.length(); format_index++ )
01876     {
01877       if ( !escape )
01878     {
01879       if ( (TQChar(rst.at( format_index )).unicode()) == '%' )
01880         escape = true;
01881       else
01882         buffer[index++] = rst.at( format_index );
01883     }
01884       else
01885     {
01886       switch ( TQChar(rst.at( format_index )).unicode() )
01887         {
01888         case '%':
01889           buffer[index++] = (QChar)'%';
01890           break;
01891         case 'H':
01892           put_it_in( buffer, index, pTime.hour() );
01893           break;
01894         case 'I':
01895           if ( isDuration )
01896               put_it_in( buffer, index, pTime.hour() );
01897           else
01898               put_it_in( buffer, index, ( pTime.hour() + 11) % 12 + 1 );
01899           break;
01900         case 'M':
01901           put_it_in( buffer, index, pTime.minute() );
01902           break;
01903         case 'S':
01904           if (includeSecs)
01905         put_it_in( buffer, index, pTime.second() );
01906           else if ( index > 0 )
01907         {
01908           // we remove the separator sign before the seconds and
01909           // assume that works everywhere
01910           --index;
01911           break;
01912         }
01913           break;
01914         case 'k':
01915           number = pTime.hour();
01916         case 'l':
01917           // to share the code
01918           if ( (TQChar(rst.at( format_index )).unicode()) == 'l' )
01919         number = isDuration ? pTime.hour() : (pTime.hour() + 11) % 12 + 1;
01920           if ( number / 10 )
01921         buffer[index++] = number / 10 + '0';
01922           buffer[index++] = number % 10 + '0';
01923           break;
01924         case 'p':
01925           if ( !isDuration )
01926           {
01927         TQString s;
01928         if ( pTime.hour() >= 12 )
01929           put_it_in( buffer, index, translate("pm") );
01930         else
01931           put_it_in( buffer, index, translate("am") );
01932           }
01933           break;
01934         default:
01935           buffer[index++] = rst.at( format_index );
01936           break;
01937         }
01938       escape = false;
01939     }
01940     }
01941   TQString ret( buffer, index );
01942   delete [] buffer;
01943   if ( isDuration ) // eliminate trailing-space due to " %p"
01944     return ret.stripWhiteSpace();
01945   else
01946     return ret;
01947 }
01948 
01949 bool TDELocale::use12Clock() const
01950 {
01951   if ((timeFormat().contains(TQString::fromLatin1("%I")) > 0) ||
01952       (timeFormat().contains(TQString::fromLatin1("%l")) > 0))
01953     return true;
01954   else
01955     return false;
01956 }
01957 
01958 TQString TDELocale::languages() const
01959 {
01960   return d->languageList.join( TQString::fromLatin1(":") );
01961 }
01962 
01963 TQStringList TDELocale::languageList() const
01964 {
01965   return d->languageList;
01966 }
01967 
01968 TQString TDELocale::formatDateTime(const TQDateTime &pDateTime,
01969                 bool shortFormat,
01970                 bool includeSeconds) const
01971 {
01972   return translate("concatenation of dates and time", "%1 %2")
01973     .arg( formatDate( TQT_TQDATE_OBJECT(pDateTime.date()), shortFormat ) )
01974     .arg( formatTime( TQT_TQTIME_OBJECT(pDateTime.time()), includeSeconds ) );
01975 }
01976 
01977 TQString i18n(const char* text)
01978 {
01979   register TDELocale *instance = TDEGlobal::locale();
01980   if (instance)
01981     return instance->translate(text);
01982   return TQString::fromUtf8(text);
01983 }
01984 
01985 TQString i18n(const char* index, const char *text)
01986 {
01987   register TDELocale *instance = TDEGlobal::locale();
01988   if (instance)
01989     return instance->translate(index, text);
01990   return TQString::fromUtf8(text);
01991 }
01992 
01993 TQString i18n(const char* singular, const char* plural, unsigned long n)
01994 {
01995   register TDELocale *instance = TDEGlobal::locale();
01996   if (instance)
01997     return instance->translate(singular, plural, n);
01998   if (n == 1)
01999     return put_n_in(TQString::fromUtf8(singular), n);
02000   else
02001     return put_n_in(TQString::fromUtf8(plural), n);
02002 }
02003 
02004 void TDELocale::initInstance()
02005 {
02006   if (TDEGlobal::_locale)
02007     return;
02008 
02009   TDEInstance *app = TDEGlobal::instance();
02010   if (app) {
02011     TDEGlobal::_locale = new TDELocale(TQString::fromLatin1(app->instanceName()));
02012 
02013     // only do this for the global instance
02014     TQTextCodec::setCodecForLocale(TDEGlobal::_locale->codecForEncoding());
02015   }
02016   else
02017     kdDebug(173) << "no app name available using TDELocale - nothing to do\n";
02018 }
02019 
02020 TQString TDELocale::langLookup(const TQString &fname, const char *rtype)
02021 {
02022   TQStringList search;
02023 
02024   // assemble the local search paths
02025   const TQStringList localDoc = TDEGlobal::dirs()->resourceDirs(rtype);
02026 
02027   // look up the different languages
02028   for (int id=localDoc.count()-1; id >= 0; --id)
02029     {
02030       TQStringList langs = TDEGlobal::locale()->languageList();
02031       langs.append( "en" );
02032       langs.remove( defaultLanguage() );
02033       TQStringList::ConstIterator lang;
02034       for (lang = langs.begin(); lang != langs.end(); ++lang)
02035     search.append(TQString("%1%2/%3").arg(localDoc[id]).arg(*lang).arg(fname));
02036     }
02037 
02038   // try to locate the file
02039   TQStringList::Iterator it;
02040   for (it = search.begin(); it != search.end(); ++it)
02041     {
02042       kdDebug(173) << "Looking for help in: " << *it << endl;
02043 
02044       TQFileInfo info(*it);
02045       if (info.exists() && info.isFile() && info.isReadable())
02046     return *it;
02047     }
02048 
02049   return TQString::null;
02050 }
02051 
02052 bool TDELocale::useDefaultLanguage() const
02053 {
02054   return language() == defaultLanguage();
02055 }
02056 
02057 void TDELocale::initEncoding(TDEConfig *)
02058 {
02059   const int mibDefault = 4; // ISO 8859-1
02060 
02061   // This all made more sense when we still had the EncodingEnum config key.
02062   setEncoding( TQTextCodec::codecForLocale()->mibEnum() );
02063 
02064   if ( !d->codecForEncoding )
02065     {
02066       kdWarning(173) << " Defaulting to ISO 8859-1 encoding." << endl;
02067       setEncoding(mibDefault);
02068     }
02069 
02070   Q_ASSERT( d->codecForEncoding );
02071 }
02072 
02073 void TDELocale::initFileNameEncoding(TDEConfig *)
02074 {
02075   // If the following environment variable is set, assume all filenames
02076   // are in UTF-8 regardless of the current C locale.
02077   d->utf8FileEncoding = getenv("TDE_UTF8_FILENAMES") != 0;
02078   if (d->utf8FileEncoding)
02079   {
02080     TQFile::setEncodingFunction(TDELocale::encodeFileNameUTF8);
02081     TQFile::setDecodingFunction(TDELocale::decodeFileNameUTF8);
02082   }
02083   // Otherwise, stay with QFile's default filename encoding functions
02084   // which, on Unix platforms, use the locale's codec.
02085 }
02086 
02087 #ifdef USE_QT3
02088 TQCString TDELocale::encodeFileNameUTF8( const TQString & fileName )
02089 #endif // USE_QT3
02090 #ifdef USE_QT4
02091 QByteArray TDELocale::encodeFileNameUTF8( const QString & fileName )
02092 #endif // USE_QT4
02093 {
02094   return TQString(fileName).utf8();
02095 }
02096 
02097 #ifdef USE_QT3
02098 TQString TDELocale::decodeFileNameUTF8( const TQCString & localFileName )
02099 #endif // USE_QT3
02100 #ifdef USE_QT4
02101 QString TDELocale::decodeFileNameUTF8( const QByteArray & localFileName )
02102 #endif // USE_QT4
02103 {
02104   return TQString::fromUtf8(localFileName);
02105 }
02106 
02107 void TDELocale::setDateFormat(const TQString & format)
02108 {
02109   doFormatInit();
02110   m_dateFormat = format.stripWhiteSpace();
02111 }
02112 
02113 void TDELocale::setDateFormatShort(const TQString & format)
02114 {
02115   doFormatInit();
02116   m_dateFormatShort = format.stripWhiteSpace();
02117 }
02118 
02119 void TDELocale::setDateMonthNamePossessive(bool possessive)
02120 {
02121   doFormatInit();
02122   d->dateMonthNamePossessive = possessive;
02123 }
02124 
02125 void TDELocale::setTimeFormat(const TQString & format)
02126 {
02127   doFormatInit();
02128   m_timeFormat = format.stripWhiteSpace();
02129 }
02130 
02131 void TDELocale::setWeekStartsMonday(bool start) //deprecated
02132 {
02133   doFormatInit();
02134   if (start)
02135     d->weekStartDay = 1;
02136   else
02137     d->weekStartDay = 7;
02138 }
02139 
02140 void TDELocale::setWeekStartDay(int day)
02141 {
02142   doFormatInit();
02143   if (day>7 || day<1)
02144     d->weekStartDay = 1; //Monday is default
02145   else
02146     d->weekStartDay = day;
02147 }
02148 
02149 TQString TDELocale::dateFormat() const
02150 {
02151   doFormatInit();
02152   return m_dateFormat;
02153 }
02154 
02155 TQString TDELocale::dateFormatShort() const
02156 {
02157   doFormatInit();
02158   return m_dateFormatShort;
02159 }
02160 
02161 TQString TDELocale::timeFormat() const
02162 {
02163   doFormatInit();
02164   return m_timeFormat;
02165 }
02166 
02167 void TDELocale::setDecimalSymbol(const TQString & symbol)
02168 {
02169   doFormatInit();
02170   m_decimalSymbol = symbol.stripWhiteSpace();
02171 }
02172 
02173 void TDELocale::setThousandsSeparator(const TQString & separator)
02174 {
02175   doFormatInit();
02176   // allow spaces here
02177   m_thousandsSeparator = separator;
02178 }
02179 
02180 void TDELocale::setPositiveSign(const TQString & sign)
02181 {
02182   doFormatInit();
02183   m_positiveSign = sign.stripWhiteSpace();
02184 }
02185 
02186 void TDELocale::setNegativeSign(const TQString & sign)
02187 {
02188   doFormatInit();
02189   m_negativeSign = sign.stripWhiteSpace();
02190 }
02191 
02192 void TDELocale::setPositiveMonetarySignPosition(SignPosition signpos)
02193 {
02194   doFormatInit();
02195   m_positiveMonetarySignPosition = signpos;
02196 }
02197 
02198 void TDELocale::setNegativeMonetarySignPosition(SignPosition signpos)
02199 {
02200   doFormatInit();
02201   m_negativeMonetarySignPosition = signpos;
02202 }
02203 
02204 void TDELocale::setPositivePrefixCurrencySymbol(bool prefix)
02205 {
02206   doFormatInit();
02207   m_positivePrefixCurrencySymbol = prefix;
02208 }
02209 
02210 void TDELocale::setNegativePrefixCurrencySymbol(bool prefix)
02211 {
02212   doFormatInit();
02213   m_negativePrefixCurrencySymbol = prefix;
02214 }
02215 
02216 void TDELocale::setFracDigits(int digits)
02217 {
02218   doFormatInit();
02219   m_fracDigits = digits;
02220 }
02221 
02222 void TDELocale::setMonetaryThousandsSeparator(const TQString & separator)
02223 {
02224   doFormatInit();
02225   // allow spaces here
02226   m_monetaryThousandsSeparator = separator;
02227 }
02228 
02229 void TDELocale::setMonetaryDecimalSymbol(const TQString & symbol)
02230 {
02231   doFormatInit();
02232   m_monetaryDecimalSymbol = symbol.stripWhiteSpace();
02233 }
02234 
02235 void TDELocale::setCurrencySymbol(const TQString & symbol)
02236 {
02237   doFormatInit();
02238   m_currencySymbol = symbol.stripWhiteSpace();
02239 }
02240 
02241 int TDELocale::pageSize() const
02242 {
02243   doFormatInit();
02244   return d->pageSize;
02245 }
02246 
02247 void TDELocale::setPageSize(int pageSize)
02248 {
02249   // #### check if it's in range??
02250   doFormatInit();
02251   d->pageSize = pageSize;
02252 }
02253 
02254 TDELocale::MeasureSystem TDELocale::measureSystem() const
02255 {
02256   doFormatInit();
02257   return d->measureSystem;
02258 }
02259 
02260 void TDELocale::setMeasureSystem(MeasureSystem value)
02261 {
02262   doFormatInit();
02263   d->measureSystem = value;
02264 }
02265 
02266 TQString TDELocale::defaultLanguage()
02267 {
02268   return TQString::fromLatin1("en_US");
02269 }
02270 
02271 TQString TDELocale::defaultCountry()
02272 {
02273   return TQString::fromLatin1("C");
02274 }
02275 
02276 const char * TDELocale::encoding() const
02277 {
02278 #ifdef Q_WS_WIN
02279   if (0==qstrcmp("System", codecForEncoding()->name()))
02280   {
02281     //win32 returns "System" codec name here but KDE apps expect a real name:
02282     strcpy(d->win32SystemEncoding, "cp ");
02283     if (GetLocaleInfoA( MAKELCID(MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), SORT_DEFAULT), 
02284       LOCALE_IDEFAULTANSICODEPAGE, d->win32SystemEncoding+3, sizeof(d->win32SystemEncoding)-3-1 ))
02285     {
02286       return d->win32SystemEncoding;
02287     }
02288   }
02289 #endif
02290   return codecForEncoding()->name();
02291 }
02292 
02293 int TDELocale::encodingMib() const
02294 {
02295   return codecForEncoding()->mibEnum();
02296 }
02297 
02298 int TDELocale::fileEncodingMib() const
02299 {
02300   if (d->utf8FileEncoding)
02301      return 106;
02302   return codecForEncoding()->mibEnum();
02303 }
02304 
02305 TQTextCodec * TDELocale::codecForEncoding() const
02306 {
02307   return d->codecForEncoding;
02308 }
02309 
02310 bool TDELocale::setEncoding(int mibEnum)
02311 {
02312   TQTextCodec * codec = TQTextCodec::codecForMib(mibEnum);
02313   if (codec)
02314     d->codecForEncoding = codec;
02315 
02316   return codec != 0;
02317 }
02318 
02319 TQStringList TDELocale::languagesTwoAlpha() const
02320 {
02321   if (d->langTwoAlpha.count())
02322      return d->langTwoAlpha;
02323 
02324   const TQStringList &origList = languageList();
02325 
02326   TQStringList result;
02327 
02328   TDEConfig config(TQString::fromLatin1("language.codes"), true, false);
02329   config.setGroup("TwoLetterCodes");
02330 
02331   for ( TQStringList::ConstIterator it = origList.begin();
02332     it != origList.end();
02333     ++it )
02334     {
02335       TQString lang = *it;
02336       TQStringList langLst;
02337       if (config.hasKey( lang ))
02338          langLst = config.readListEntry( lang );
02339       else
02340       {
02341          int i = lang.find('_');
02342          if (i >= 0)
02343             lang.truncate(i);
02344          langLst << lang;
02345       }
02346 
02347       for ( TQStringList::ConstIterator langIt = langLst.begin();
02348         langIt != langLst.end();
02349         ++langIt )
02350     {
02351       if ( !(*langIt).isEmpty() && !result.contains( *langIt ) )
02352         result += *langIt;
02353     }
02354     }
02355   d->langTwoAlpha = result;
02356   return result;
02357 }
02358 
02359 TQStringList TDELocale::allLanguagesTwoAlpha() const
02360 {
02361   if (!d->languages)
02362     d->languages = new TDEConfig("all_languages", true, false, "locale");
02363 
02364   return d->languages->groupList();
02365 }
02366 
02367 TQString TDELocale::twoAlphaToLanguageName(const TQString &code) const
02368 {
02369   if (!d->languages)
02370     d->languages = new TDEConfig("all_languages", true, false, "locale");
02371 
02372   TQString groupName = code;
02373   const int i = groupName.find('_');
02374   groupName.replace(0, i, groupName.left(i).lower());
02375 
02376   d->languages->setGroup(groupName);
02377   return d->languages->readEntry("Name");
02378 }
02379 
02380 TQStringList TDELocale::allCountriesTwoAlpha() const
02381 {
02382   TQStringList countries;
02383   TQStringList paths = TDEGlobal::dirs()->findAllResources("locale", "l10n/*/entry.desktop");
02384   for(TQStringList::ConstIterator it = paths.begin();
02385       it != paths.end(); ++it)
02386   {
02387     TQString code = (*it).mid((*it).length()-16, 2);
02388     if (code != "/C")
02389        countries.append(code);
02390   }
02391   return countries;
02392 }
02393 
02394 TQString TDELocale::twoAlphaToCountryName(const TQString &code) const
02395 {
02396   TDEConfig cfg("l10n/"+code.lower()+"/entry.desktop", true, false, "locale");
02397   cfg.setGroup("KCM Locale");
02398   return cfg.readEntry("Name");
02399 }
02400 
02401 void TDELocale::setCalendar(const TQString & calType)
02402 {
02403   doFormatInit();
02404 
02405   d->calendarType = calType;
02406 
02407   delete d->calendar;
02408   d->calendar = 0;
02409 }
02410 
02411 TQString TDELocale::calendarType() const
02412 {
02413   doFormatInit();
02414 
02415   return d->calendarType;
02416 }
02417 
02418 const KCalendarSystem * TDELocale::calendar() const
02419 {
02420   doFormatInit();
02421 
02422   // Check if it's the correct calendar?!?
02423   if ( !d->calendar )
02424     d->calendar = KCalendarSystemFactory::create( d->calendarType, this );
02425 
02426   return d->calendar;
02427 }
02428 
02429 TDELocale::TDELocale(const TDELocale & rhs)
02430 {
02431   d = new TDELocalePrivate;
02432 
02433   *this = rhs;
02434 }
02435 
02436 TDELocale & TDELocale::operator=(const TDELocale & rhs)
02437 {
02438   // Numbers and money
02439   m_decimalSymbol = rhs.m_decimalSymbol;
02440   m_thousandsSeparator = rhs.m_thousandsSeparator;
02441   m_currencySymbol = rhs.m_currencySymbol;
02442   m_monetaryDecimalSymbol = rhs.m_monetaryDecimalSymbol;
02443   m_monetaryThousandsSeparator = rhs.m_monetaryThousandsSeparator;
02444   m_positiveSign = rhs.m_positiveSign;
02445   m_negativeSign = rhs.m_negativeSign;
02446   m_fracDigits = rhs.m_fracDigits;
02447   m_positivePrefixCurrencySymbol = rhs.m_positivePrefixCurrencySymbol;
02448   m_negativePrefixCurrencySymbol = rhs.m_negativePrefixCurrencySymbol;
02449   m_positiveMonetarySignPosition = rhs.m_positiveMonetarySignPosition;
02450   m_negativeMonetarySignPosition = rhs.m_negativeMonetarySignPosition;
02451 
02452   // Date and time
02453   m_timeFormat = rhs.m_timeFormat;
02454   m_dateFormat = rhs.m_dateFormat;
02455   m_dateFormatShort = rhs.m_dateFormatShort;
02456 
02457   m_language = rhs.m_language;
02458   m_country = rhs.m_country;
02459 
02460   // the assignment operator works here
02461   *d = *rhs.d;
02462   d->languages = 0; // Don't copy languages
02463   d->calendar = 0; // Don't copy the calendar
02464 
02465   return *this;
02466 }
02467 
02468 bool TDELocale::setCharset(const TQString & ) { return true; }
02469 TQString TDELocale::charset() const { return TQString::fromLatin1("UTF-8"); }
02470 
02471 // KDE4: remove
02472 #if 0
02473 void nothing() { i18n("&Next"); }
02474 #endif

tdecore

Skip menu "tdecore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdecore

Skip menu "tdecore"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.7.1
This website is maintained by Timothy Pearson.